aboutsummaryrefslogtreecommitdiff
path: root/noao/digiphot/photcal
diff options
context:
space:
mode:
authorJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
committerJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
commit40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch)
tree4464880c571602d54f6ae114729bf62a89518057 /noao/digiphot/photcal
downloadiraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'noao/digiphot/photcal')
-rw-r--r--noao/digiphot/photcal/README29
-rw-r--r--noao/digiphot/photcal/Revisions696
-rw-r--r--noao/digiphot/photcal/apfile.par25
-rw-r--r--noao/digiphot/photcal/catalog.par5
-rw-r--r--noao/digiphot/photcal/catalogs/README109
-rw-r--r--noao/digiphot/photcal/catalogs/arnica.dat88
-rw-r--r--noao/digiphot/photcal/catalogs/elias.dat58
-rw-r--r--noao/digiphot/photcal/catalogs/farnica.dat10
-rw-r--r--noao/digiphot/photcal/catalogs/felias.dat12
-rw-r--r--noao/digiphot/photcal/catalogs/flandolt.dat17
-rw-r--r--noao/digiphot/photcal/catalogs/fnicmos.dat12
-rw-r--r--noao/digiphot/photcal/catalogs/fnlandolt.dat17
-rw-r--r--noao/digiphot/photcal/catalogs/fodewahn.dat10
-rw-r--r--noao/digiphot/photcal/catalogs/fonlandolt.dat17
-rw-r--r--noao/digiphot/photcal/catalogs/fporter.dat14
-rw-r--r--noao/digiphot/photcal/catalogs/fukirt.dat10
-rw-r--r--noao/digiphot/photcal/catalogs/landolt.dat223
-rw-r--r--noao/digiphot/photcal/catalogs/nicmos.dat94
-rw-r--r--noao/digiphot/photcal/catalogs/nlandolt.dat526
-rw-r--r--noao/digiphot/photcal/catalogs/odewahn.dat283
-rw-r--r--noao/digiphot/photcal/catalogs/onlandolt.dat526
-rw-r--r--noao/digiphot/photcal/catalogs/porter.dat85
-rw-r--r--noao/digiphot/photcal/catalogs/tarnica.dat12
-rw-r--r--noao/digiphot/photcal/catalogs/telias.dat15
-rw-r--r--noao/digiphot/photcal/catalogs/tlandolt.dat23
-rw-r--r--noao/digiphot/photcal/catalogs/tnicmos.dat15
-rw-r--r--noao/digiphot/photcal/catalogs/tnlandolt.dat23
-rw-r--r--noao/digiphot/photcal/catalogs/todewahn.dat12
-rw-r--r--noao/digiphot/photcal/catalogs/tonlandolt.dat23
-rw-r--r--noao/digiphot/photcal/catalogs/tporter.dat23
-rw-r--r--noao/digiphot/photcal/catalogs/tukirt.dat12
-rw-r--r--noao/digiphot/photcal/catalogs/ukirt.dat34
-rw-r--r--noao/digiphot/photcal/chkconfig.par4
-rw-r--r--noao/digiphot/photcal/config.par8
-rw-r--r--noao/digiphot/photcal/debug/README1
-rw-r--r--noao/digiphot/photcal/debug/debug.h2
-rw-r--r--noao/digiphot/photcal/debug/debug.par14
-rw-r--r--noao/digiphot/photcal/debug/dginl.x30
-rw-r--r--noao/digiphot/photcal/debug/dgparser.x567
-rw-r--r--noao/digiphot/photcal/debug/dgptime.x21
-rw-r--r--noao/digiphot/photcal/debug/dgtable.x241
-rw-r--r--noao/digiphot/photcal/debug/mkpkg14
-rw-r--r--noao/digiphot/photcal/doc/apfile.hlp502
-rw-r--r--noao/digiphot/photcal/doc/chkconfig.hlp42
-rw-r--r--noao/digiphot/photcal/doc/config.hlp679
-rw-r--r--noao/digiphot/photcal/doc/evalfit.hlp267
-rw-r--r--noao/digiphot/photcal/doc/fitparams.hlp633
-rw-r--r--noao/digiphot/photcal/doc/inlfit.hlp259
-rw-r--r--noao/digiphot/photcal/doc/invertfit.hlp297
-rw-r--r--noao/digiphot/photcal/doc/mkapfile.hlp473
-rw-r--r--noao/digiphot/photcal/doc/mkcatalog.hlp220
-rw-r--r--noao/digiphot/photcal/doc/mkconfig.hlp451
-rw-r--r--noao/digiphot/photcal/doc/mkimsets.hlp356
-rw-r--r--noao/digiphot/photcal/doc/mknobsfile.hlp516
-rw-r--r--noao/digiphot/photcal/doc/mkobsfile.hlp519
-rw-r--r--noao/digiphot/photcal/doc/mkphotcors.hlp274
-rw-r--r--noao/digiphot/photcal/doc/obsfile.hlp511
-rw-r--r--noao/digiphot/photcal/doc/pcintro.hlp727
-rw-r--r--noao/digiphot/photcal/evalfit.par13
-rw-r--r--noao/digiphot/photcal/evaluate/README3
-rw-r--r--noao/digiphot/photcal/evaluate/invert.com15
-rw-r--r--noao/digiphot/photcal/evaluate/mkpkg18
-rw-r--r--noao/digiphot/photcal/evaluate/phcheck.x240
-rw-r--r--noao/digiphot/photcal/evaluate/pherrors.x278
-rw-r--r--noao/digiphot/photcal/evaluate/phinvert.x619
-rw-r--r--noao/digiphot/photcal/evaluate/phminv.f114
-rw-r--r--noao/digiphot/photcal/evaluate/phprint.x110
-rw-r--r--noao/digiphot/photcal/evaluate/t_evalfit.x495
-rw-r--r--noao/digiphot/photcal/evaluate/t_invertfit.x792
-rw-r--r--noao/digiphot/photcal/fitparams.par22
-rw-r--r--noao/digiphot/photcal/fitparams/README2
-rw-r--r--noao/digiphot/photcal/fitparams/fteval.com8
-rw-r--r--noao/digiphot/photcal/fitparams/fteval.x221
-rw-r--r--noao/digiphot/photcal/fitparams/ftindef.x184
-rw-r--r--noao/digiphot/photcal/fitparams/ftref.x50
-rw-r--r--noao/digiphot/photcal/fitparams/fttrneq.x541
-rw-r--r--noao/digiphot/photcal/fitparams/ftweights.x491
-rw-r--r--noao/digiphot/photcal/fitparams/mkpkg16
-rw-r--r--noao/digiphot/photcal/fitparams/t_fitparams.x205
-rw-r--r--noao/digiphot/photcal/imgroup.par6
-rw-r--r--noao/digiphot/photcal/invertfit.par13
-rw-r--r--noao/digiphot/photcal/io/README2
-rw-r--r--noao/digiphot/photcal/io/iocat.x376
-rw-r--r--noao/digiphot/photcal/io/iocoeffs.x282
-rw-r--r--noao/digiphot/photcal/io/iogetline.x89
-rw-r--r--noao/digiphot/photcal/io/iolineid.x51
-rw-r--r--noao/digiphot/photcal/io/ioobs.x150
-rw-r--r--noao/digiphot/photcal/io/iostrwrd.x51
-rw-r--r--noao/digiphot/photcal/io/mkpkg16
-rw-r--r--noao/digiphot/photcal/lib/apfile.h117
-rw-r--r--noao/digiphot/photcal/lib/fitparams.h7
-rw-r--r--noao/digiphot/photcal/lib/io.h78
-rw-r--r--noao/digiphot/photcal/lib/lexer.h60
-rw-r--r--noao/digiphot/photcal/lib/mctable.h28
-rw-r--r--noao/digiphot/photcal/lib/obsfile.h51
-rw-r--r--noao/digiphot/photcal/lib/parser.h169
-rw-r--r--noao/digiphot/photcal/lib/prdefs.h30
-rw-r--r--noao/digiphot/photcal/lib/preval.h41
-rw-r--r--noao/digiphot/photcal/lib/prstruct.h344
-rw-r--r--noao/digiphot/photcal/lib/prtoken.h42
-rw-r--r--noao/digiphot/photcal/lib/warning.dat11
-rw-r--r--noao/digiphot/photcal/mctable/mctable.hlp90
-rw-r--r--noao/digiphot/photcal/mctable/mctalloc.x48
-rw-r--r--noao/digiphot/photcal/mctable/mctclear.gx33
-rw-r--r--noao/digiphot/photcal/mctable/mctclear.x195
-rw-r--r--noao/digiphot/photcal/mctable/mctcopy.gx63
-rw-r--r--noao/digiphot/photcal/mctable/mctcopy.x86
-rw-r--r--noao/digiphot/photcal/mctable/mctfree.x20
-rw-r--r--noao/digiphot/photcal/mctable/mctget.gx46
-rw-r--r--noao/digiphot/photcal/mctable/mctget.x307
-rw-r--r--noao/digiphot/photcal/mctable/mctgetbuf.x23
-rw-r--r--noao/digiphot/photcal/mctable/mctgetrow.x25
-rw-r--r--noao/digiphot/photcal/mctable/mctindef.x40
-rw-r--r--noao/digiphot/photcal/mctable/mctmaxcol.x19
-rw-r--r--noao/digiphot/photcal/mctable/mctmaxrow.x19
-rw-r--r--noao/digiphot/photcal/mctable/mctncols.x20
-rw-r--r--noao/digiphot/photcal/mctable/mctnrows.x19
-rw-r--r--noao/digiphot/photcal/mctable/mctput.gx68
-rw-r--r--noao/digiphot/photcal/mctable/mctput.x490
-rw-r--r--noao/digiphot/photcal/mctable/mctreset.x28
-rw-r--r--noao/digiphot/photcal/mctable/mctrestore.gx135
-rw-r--r--noao/digiphot/photcal/mctable/mctrestore.x159
-rw-r--r--noao/digiphot/photcal/mctable/mctrew.x20
-rw-r--r--noao/digiphot/photcal/mctable/mctsave.x113
-rw-r--r--noao/digiphot/photcal/mctable/mctsget.gx42
-rw-r--r--noao/digiphot/photcal/mctable/mctsget.x307
-rw-r--r--noao/digiphot/photcal/mctable/mctshrink.x31
-rw-r--r--noao/digiphot/photcal/mctable/mctsput.gx40
-rw-r--r--noao/digiphot/photcal/mctable/mctsput.x291
-rw-r--r--noao/digiphot/photcal/mctable/mcttype.x19
-rw-r--r--noao/digiphot/photcal/mctable/mkpkg71
-rw-r--r--noao/digiphot/photcal/mctable/zzdebug.gx1318
-rw-r--r--noao/digiphot/photcal/mctable/zzdebug.x2066
-rw-r--r--noao/digiphot/photcal/mkapfile.cl187
-rw-r--r--noao/digiphot/photcal/mkcatalog.cl25
-rw-r--r--noao/digiphot/photcal/mkcatalog/README2
-rw-r--r--noao/digiphot/photcal/mkcatalog/mkpkg11
-rw-r--r--noao/digiphot/photcal/mkcatalog/phrecord.x243
-rw-r--r--noao/digiphot/photcal/mkcatalog/t_catalog.x902
-rw-r--r--noao/digiphot/photcal/mkconfig.cl99
-rw-r--r--noao/digiphot/photcal/mkconfig/catlist.key20
-rw-r--r--noao/digiphot/photcal/mkconfig/catsection.key42
-rw-r--r--noao/digiphot/photcal/mkconfig/mkpkg10
-rw-r--r--noao/digiphot/photcal/mkconfig/obsection.key43
-rw-r--r--noao/digiphot/photcal/mkconfig/obslist.key18
-rw-r--r--noao/digiphot/photcal/mkconfig/t_config.x1013
-rw-r--r--noao/digiphot/photcal/mkconfig/tranlist.key19
-rw-r--r--noao/digiphot/photcal/mkconfig/transection.key94
-rw-r--r--noao/digiphot/photcal/mkimsets.cl186
-rw-r--r--noao/digiphot/photcal/mkimsets/imlist.key35
-rw-r--r--noao/digiphot/photcal/mkimsets/imsets.key30
-rw-r--r--noao/digiphot/photcal/mkimsets/mkpkg10
-rw-r--r--noao/digiphot/photcal/mkimsets/t_imgroup.x430
-rw-r--r--noao/digiphot/photcal/mknobsfile.cl108
-rw-r--r--noao/digiphot/photcal/mkobsfile.cl152
-rw-r--r--noao/digiphot/photcal/mkobsfile/apfile.key36
-rw-r--r--noao/digiphot/photcal/mkobsfile/dinvers.f53
-rw-r--r--noao/digiphot/photcal/mkobsfile/mkpkg19
-rw-r--r--noao/digiphot/photcal/mkobsfile/phagrow.x1982
-rw-r--r--noao/digiphot/photcal/mkobsfile/phaigrow.x1635
-rw-r--r--noao/digiphot/photcal/mkobsfile/phaimtable.x409
-rw-r--r--noao/digiphot/photcal/mkobsfile/phimtable.x971
-rw-r--r--noao/digiphot/photcal/mkobsfile/phmatch.x487
-rw-r--r--noao/digiphot/photcal/mkobsfile/phsort.x528
-rw-r--r--noao/digiphot/photcal/mkobsfile/t_apfile.x727
-rw-r--r--noao/digiphot/photcal/mkobsfile/t_mkphotcors.x273
-rw-r--r--noao/digiphot/photcal/mkobsfile/t_obsfile.x1131
-rw-r--r--noao/digiphot/photcal/mkphotcors.par10
-rw-r--r--noao/digiphot/photcal/mkpkg38
-rw-r--r--noao/digiphot/photcal/obsfile.par18
-rw-r--r--noao/digiphot/photcal/parser/README2
-rw-r--r--noao/digiphot/photcal/parser/TODO4
-rw-r--r--noao/digiphot/photcal/parser/lexer.com13
-rw-r--r--noao/digiphot/photcal/parser/mkpkg43
-rw-r--r--noao/digiphot/photcal/parser/parser.com49
-rw-r--r--noao/digiphot/photcal/parser/parser.x849
-rw-r--r--noao/digiphot/photcal/parser/parser.y461
-rw-r--r--noao/digiphot/photcal/parser/pralloc.x304
-rw-r--r--noao/digiphot/photcal/parser/prcat.x43
-rw-r--r--noao/digiphot/photcal/parser/prcode.com8
-rw-r--r--noao/digiphot/photcal/parser/prcode.x273
-rw-r--r--noao/digiphot/photcal/parser/prconv.x72
-rw-r--r--noao/digiphot/photcal/parser/prerror.x57
-rw-r--r--noao/digiphot/photcal/parser/preval.gx319
-rw-r--r--noao/digiphot/photcal/parser/preval.x1448
-rw-r--r--noao/digiphot/photcal/parser/prexit.x324
-rw-r--r--noao/digiphot/photcal/parser/prget.x928
-rw-r--r--noao/digiphot/photcal/parser/prlexer.x337
-rw-r--r--noao/digiphot/photcal/parser/prmap.x200
-rw-r--r--noao/digiphot/photcal/parser/prparse.x102
-rw-r--r--noao/digiphot/photcal/parser/prput.x1020
-rw-r--r--noao/digiphot/photcal/parser/prtable.x1371
-rw-r--r--noao/digiphot/photcal/parser/prvtran.x25
-rw-r--r--noao/digiphot/photcal/parser/t_chkconfig.x228
-rw-r--r--noao/digiphot/photcal/parser/y.tab.h42
-rw-r--r--noao/digiphot/photcal/photcal.cl55
-rw-r--r--noao/digiphot/photcal/photcal.hd28
-rw-r--r--noao/digiphot/photcal/photcal.men16
-rw-r--r--noao/digiphot/photcal/photcal.par5
-rw-r--r--noao/digiphot/photcal/x_photcal.x10
200 files changed, 44020 insertions, 0 deletions
diff --git a/noao/digiphot/photcal/README b/noao/digiphot/photcal/README
new file mode 100644
index 00000000..aeb375a9
--- /dev/null
+++ b/noao/digiphot/photcal/README
@@ -0,0 +1,29 @@
+ Photometric Calibrations Package
+ -------------------------------------
+
+ The photometry calibration package contains a set for tasks for converting
+from the instrumental magnitude system to the standard photometric system.
+
+ The PHOTCAL directory structure is listed below. The package organization
+is by task and/or function.
+
+
+ |-catalogs----------library of standard photometric catalogs
+ |-debug-------------debugging routines
+ |-doc---------------the package documentation
+ |-evaluate----------routines to evaluate the transformations
+ |-fitparams---------routines to compute the transformations
+ |-io----------------package io routines
+|-photcal---|-lib---------------include files
+ |-mctable-----------package table routines
+ |-mkcatalog---------routines for typing in catalog files
+ |-mkconfig----------routines for creating the config files
+ |-mkimsets----------routines for creating the image set files
+ |-mkobsfile---------routines for preprocessing ap/daophot output
+ |-parser------------the parser code
+ |-test--------------directory of test data
+
+
+Lindsey Davis
+NOAO IRAF GROUP
+August 1991
diff --git a/noao/digiphot/photcal/Revisions b/noao/digiphot/photcal/Revisions
new file mode 100644
index 00000000..099b9326
--- /dev/null
+++ b/noao/digiphot/photcal/Revisions
@@ -0,0 +1,696 @@
+.help revisions May91 noao.digiphot.photcal
+.nf
+
+io/iocat.x
+io/ioobs.x
+ Added some necessary P2R macros for symtab usage (4/2/12, MJF)
+
+lib/lexer.h
+lib/prstruct.h
+ Added necessary P2R macros for 64-bit systems (9/8/10, MJF)
+
+
+=======
+V2.12.2
+=======
+
+photcal/photcal.cl
+photcal/photcal.hd
+photcal/photcal.men
+ Typo changes referencing PHTOCALX fixed (11/11/03 MJF)
+
+photcal/photcal.par
+ Fixed reference to photcalx$ in 'catdir' default value (11/11/03 MJF)
+
+photcal/doc/obsfile.hlp
+ OBSFILE expects "incolumns" to have 10 numbers and not 9 and specified
+ in the help file. The extra column is for an object ID. This may
+ have been added in Aug. 2001 judging from the last modify date of
+ the include defining the structure. (1/24/03, Valdes)
+
+ In the descriptions of the catalog files, the first catalog in the
+ list "Elias" has the wrong filename for the formats and templates
+ file. Currently they are flandolt.dat and and tlandolt.dat, which
+ should be felias.dat and telias.dat.
+ (9/13/02, Valdes, Warner)
+
+=======
+V2.12.1
+=======
+
+photcal/mknobsfile.cl
+photcal/mkobsfile.cl
+photcal/obsfile.par
+photcal/doc/obsfile.hlp
+photcal/doc/mkobsfile.hlp
+photcal/doc/mknobsfile.hlp
+ Declarations for the missing wrap parameter were added to the obsfile,
+ mknobsfile, and mkobsfile tasks. Descriptions of the wrap parameter
+ were added to the obsfile, mknobsfile, and mkobsfile task help pages.
+
+ (Davis, May 29, 2002)
+
+
+photcal$mkobsfile/phagrow.x
+ Added a missing sfree statement.
+
+ (Davis, February 19, 2002)
+
+photcal$mkobsfile/mkpkg
+ Added a missing "../lib/obsfile.h" dependency to the mkpkg phsort.x
+ declaration.
+
+ (Davis, December 13, 2001)
+
+photcal/fitparams/mkpkg
+photcal/fitparams/fttrneqs.x
+ Modified the interactiving fitting code so that the plots are automatically
+ autoscaled when a new equation is fit.
+
+ (Davis, October 9, 2000)
+
+photcal/mkimsets/t_imgroup.x
+ Modifed the imgroup task to write out the image root names minus
+ the directory specification if any to the output image sets file.
+
+ (Davis, April 25, 2000)
+
+photcal/mkimsets.cl
+ The mkimsets script was leaving a temporary file in tmp$ if the review
+ parameter was set to yes. This did not cause any trouble but might fill
+ up the tmp$ area after a while.
+
+ (Davis, April 24, 2000)
+
+photcal/*/mkpkg
+ Added some missing file dependencies and removed some unecessary ones.
+
+ (Davis, September 20, 1999)
+
+photcal/catalogs/nlandolt.dat
+ Replaced the existing catalog which was an early version I got off a tape
+ given to us by Arlo Landolt with a new version in which the positions
+ are upgraded to agree with the table as published in the literature.
+
+ (Davis, May 10, 1999)
+
+photcal/photcal.cl
+ Modified the package cl script to check and see if the tables package is
+ already loaded before checking to see whether it is defined and then
+ loading it.
+
+ (Davis, August 1, 1998)
+
+photcal/evaluate/phinvert.x
+photcal/evaluate/phminv.f
+ Modified the inversion routines to fit systems of equations which are
+ singular more robustly, by forcing the appropriate columns in the
+ inversion matrix to 0, and trying to fit the system in the least squares
+ sense.
+
+ (Davis, Novemeber 12, 1997)
+
+
+photcal$mkapfile.cl
+ Modified the way the mkapfile script handles the tdump pwidth parameter
+ to work around a change made to the tables.ttools.tdump task. The solution
+ is not ideal because it leaves the value of tdump.pwidth.p_max
+ modified but the parameter value is not changed.
+
+ (Davis, August 15, 1997)
+
+photcal/mkobsfile/t_obsfile.x
+photcal/mkobsfile/mkpkg
+photcal/mkimsets/t_imgroup.x
+ Fixed a bug in the filter id parsing code that was causing filter ids
+ that began with non-alphabetic characters [a-z][A-Z] to be incorrectly
+ parsed, e.g 1U,1B,1V became 1, U, 1B, 1, V instead of 1U, 1B, 1V as
+ intended.
+ (Davis, 6/12/97)
+
+photcal/catalogs/README
+photcal/catalogs/ukirt.dat
+photcal/catalogs/fukirt.dat
+photcal/catalogs/tukirt.dat
+photcal/mkconfig/catlist.key
+ Installed the UKIRT JHK standards list in the photcal package.
+ (Davis, 6/25/96)
+
+photcal/evaluate/phinvert.x
+ Modified the numerical inversion routines to avoid a floating point
+ precision problem on the Linux system. This precision problem would
+ cause the code to go into an infinite loop on some objects.
+ (Davis, 5/7/96)
+
+photcal/mkobsfile/phagrow.x
+photcal/mkobsfile/phaigrow.x
+ Modified the mkapfile/apfile task curve of growth fitting code to avoid
+ going into an infinite loop while fitting the seeing radius parameter RO
+ for an image. If RO cannot be fit after a reasonable number of attempts,
+ RO is set to INDEF and a cannot converge message is issued to the user.
+ The infinite loop situation can arise if there is bad data in the input
+ file, where bad data in this sense means one or more curve of growths
+ for object which are not stars, e.g cosmic rays and in some cases
+ galaxies. Modified the plotting and output routines to deal with the
+ INDEF RO case in a sensible manner.
+ (Davis, 1/29/96)
+
+photcal/mkapfile.cl
+ Added some missing commas to the column template string sent to the pdump
+ task when the input photometry files are ST tables, abug which resulted in
+ the first 1-9 apertures not being written to the output file, and either
+ a fit did not converge message in non-interactive mode or a floating
+ divide by zero error message in interactive mode.
+ (Davis, 10/6/95)
+
+photcal/mkobsfile/t_apfile.x
+photcal/mkobsfile/t_obsfile.x
+photcal/mkobsfile/t_phimtable.x
+ Modified the obsfile task (and as a result the mk(n)obsfile script task
+ as well) to accept long (> 161 characters) lines in the input text
+ files. The change avoids problems with the ttools task tdump used to extract
+ the fields of interest: image name, x, y, magnitude, magnitude and error,
+ exposure time, airmass, filter, and time of observation from ST tables
+ and which due to the internal formatting can exceed the default size of
+ an iraf image line.
+ (Davis, 10/6/95)
+
+photcal/mkobsfile/apfile.key
+ Added a description of the 'b' key to the mkapfile/apfile key file.
+ (Davis, 6/22/95/95)
+
+photcal/apfile.par
+photcal/mkapfile.cl
+photcal/lib/apfile.h
+photcal/doc/apfile.hlp
+photcal/doc/mkapfile.hlp
+photcal/mkobsfile/t_apfile.x
+photcal/mkobsfile/phagrow.x
+photcal/mkobsfile/phaitable.x
+ Added to suuport for reading the time of observation from the input
+ photometry files and/or the observing parameters file and writing it
+ to the output magnitudes file.
+ (Davis, 4/28/95)
+
+photcal/mkobsfile/phaimtable.x
+ Due to a typo mkapfile/pfile were not writing the filter id that was read
+ from the input photometry files into the output mag file correctly.
+ (Davis, 4/28/95)
+
+photcal/mkobsfile/t_apfile.x
+photcal/mkobsfile/phagrow.x
+photcal/mkobsfile/phaigrow.x
+ Modified the mkapfile/apfile tasks so that objects with good data
+ in only one aperture are not included in the fit but are included in
+ output magnitudes file.
+ (Davis, 4/27/95)
+
+photcal/mknobsfile.cl
+photcal/mkobsfile.cl
+ Reversed the order in which the itime and otime columns were read from the
+ input photometry files to avoid a problem with INDEF otimes being read
+ from allstar/nstar/peak photometry files.
+ (Davis, 3/21/95)
+
+photcal/mkobsfile/phmatch.x
+ The time of observations and airmass columns were switched on output
+ if matching by position was turned off, resulting in airmass being
+ written to the otime column and vice versa.
+
+ (Davis, 2/9/95)
+
+photcal/mkapfile.cl
+ A reference was being made to a tdump parameter outside of the loop
+ for processing ST binary tables files causing an "unknown task tdump"
+ error for users which do not have the tables package defined.
+
+ (Davis, 10/13/94)
+
+photcal/mkapfile.cl
+ A "> file" was being used instead if an ">> file" resulting in an error
+ when there was more than one file in the input list and the script
+ was unable to append to the output file.
+
+ (Davis, 10/13/94)
+
+photcal/mkobsfile/phmatch.x
+ Fixed a bug in the filter matching code that was causing stars in an
+ image which was the sole image in its set to be omitted from the output
+ file, if tolerance > 0 and the image was not the last one in the image
+ set.
+
+ (Davis, 21/6/94)
+
+photcal/obsfile.par
+photcal/mkphotcors.par
+photcal/mkimsets.cl
+photcal/mkobsfile.cl
+photcal/mknobsfile.cl
+photcal/lib/obsfile.h
+photcal/mkobsfile/t_obsfile.x
+photcal/mkobsfile/t_mkphotcors.x
+photcal/mkobsfile/phimtable.x
+photcal/mkobsfile/phmatch.x
+photcal/doc/obsfile.hlp
+photcal/doc/mkobsfile.hlp
+photcal/doc/mknobsfile.hlp
+photcal/doc/mkphotcors.hlp
+photcal/doc/mkimsets.hlp
+ Added support for picking up the time of observation to the photcal
+ preprocessor tasks obsfile/mknobsfile/mkobsfile.
+
+ (Davis, 4/4/94)
+
+photcal/evaluate/t_invertfit.x
+photcal/evaluate/phinvert.x
+ In cases where the user has not defined any set equations, invertfit will
+ pass a 2D array with a zero valued first dimension to a numerical
+ subroutine. Although this array is never accessed and the invertfit
+ appears to run correctly on most unix machines, invertfit under VMS
+ produces an adjustable array dimension error.
+
+ (Davis, 1/18/94)
+
+photcal/fitparams/ftweights.x
+ Fixed a bug in the fitparams weighting=photerrors scheme. Fitparams
+ was not correctly assigning errors to catalog and/or observations
+ variables defined in the set equations.
+
+ (Davis, 8/8/93)
+
+photcal/mknobsfile.cl
+photcal/mkobsfile.cl
+photcal/obsfile.par
+photcal/mkobsfile/t_obsfile.x
+photcal/doc/mknobsfile.hlp
+photcal/doc/mkobsfile.hlp
+photcal/doc/obsfile.hlp
+ Added a minmagerr parameter to the mknobsfile, mkobsfile, and obsfile
+ tasks.
+
+ (Davis, 7/31/93)
+
+photcal/catalogs/README
+photcal/catalogs/odewahn.dat
+photcal/catalogs/fodewahn.dat
+photcal/catalogs/todewahn.dat
+photcal/catalogs/porter.dat
+photcal/catalogs/fporter.dat
+photcal/catalogs/tporter.dat
+photcal/mkconfig/catlist.key
+ Installed two new photometry catalogs in photcal, the odewahn BVR cluster
+ standards catalog, and the porter compendium of cluster UBVRI standards.
+
+ (Davis, 4/21/93)
+
+photcal/
+ Installed two new tasks from computing the aperture corrections
+ MKAPFILE which uses apphot/daophot output as input, and APFILE
+ which uses a user's text file as input.
+
+ (Davis, 4/18/93)
+
+photcal/mkobsfile/phmatch.x
+ The position matching algorithm was failing in the case that: 1) there
+ were multiple matches on the same star and 2) the closest match was
+ not the first candidate found. The code was correctly matching to the
+ closest star but forgetting to unset the match index for the previous
+ candidate, confusing the indexing scheme, and resulting in stars being
+ left out of the output file.
+
+ (Davis, 4/2/93)
+
+photcal/mkobsfile/t_obsfile.x
+photcal/mkobsfile/phimtable.x
+ The obsfile task was not decoding the image names correctly from the
+ obsparams file when obsfile was called from the cl directly, instead
+ of from the script tasks mknobsfile and mkobsfile. Since obsfile
+ could not match the image names in the obsparams file with those in the
+ imsets file it simply ignored the contents of obsparams. This problem
+ was masking a second potential problem with normalization since the
+ code was not testing for INDEF exposure times.
+
+ (Davis, 3/1/93)
+
+photcal/mkimsets.cl
+photcal/mknobsfile.cl
+photcal/mkobsfile.cl
+ Modified the mkimsets, mknobsfile, and mkobsfile script tasks so that
+ they can deal the new pdump expression parameter.
+
+ (Davis, 25/2/93)
+
+photcal/fitparams
+ The fitparams task could produce incorrect weights, chi, and fitted
+ parameter error estimates in the case that weighting=photometric and
+ nreject > 1. This was occuring because the weight array was not being
+ reinitialized correctly after each interation in the rejection cycle.
+ The actual problem was in the inlfit package routine inlfit$inreject.gx.
+
+ (Davis, 12/17/92)
+
+photcal/mkcatalog/t_catalog.x
+photcal/mkcatalog/phrecord.x
+photcal/io/ioobs.x
+ Added some missing sfree calls.
+
+ (Davis, 9/2/92)
+
+photcal/lib/warning.dat
+ Added a newline to the end of the message printed by the photcal
+ loader when the tables package is not available.
+
+ (Davis, 5/29/92)
+
+photcal/evaluate/t_invertfit.x
+photcal/evaluate/t_phcheck.x
+photcal/evaluate/phinvert.x
+photcal/evalaute/pherrors.x
+ Modified the invertfit task so that it can invert a set of equations
+ for which one or more observations is missing if the remaining
+ number of equations is greater or equal to the number of catalog
+ variables to be solved for.
+
+ (Davis, 4/17/92)
+
+photcal/mkobsfile/phmatch.x
+ Modified the preprocessor routines to write out the x and y values
+ as measured in the original data frames instead of the shifted
+ values.
+
+ (Davis, 2/19/92)
+
+photcal/mkobsfile/phimtable.x
+ Modified the code which reads in the x and y shifts from the
+ standard input to accept the syntax "xshift,yshift" as well
+ as the syntax "xshift yshift".
+
+ (Davis, 1/8/92)
+
+photcal/catalogs/landolt.dat
+ Replaced the catalog landolt.dat with a new version containing the
+ the mean errors of the standard indices instead of the standard
+ deviations of the standard indices.
+
+ (Davis, 1/2/92)
+
+photcal/fitparams.par
+photcal/evalfit.par
+photcal/invertfit.par
+photcal/fitparams/t_fitparams.x
+photcal/evaluate/t_evalfit.x
+photcal/evaluate/t_invertfit.x
+photcal/doc/fitparams.hlp
+photcal/doc/evalfit.hlp
+photcal/doc/invertfit.hlp
+photcal/io/iocat.x
+ Modified the fitparams, evalfit, and invertfit tasks to use the
+ standard star catalog directory if the users sets the catalog
+ parameter to one of the standard catalogs.
+
+ (Davis, 2/1/92)
+
+photcal/catalogs/tlandolt.dat
+photcal/doc/mkconfig.hlp
+photcal/doc/config.hlp
+ Changed the values of the transformation equations zero points:
+ u1, b1, v1, r1, i1 to 0.0 from values like 25.0. The new values are
+ more consistent with typical apphot and daophot output, although
+ these number will always be chip/telescope dependent.
+
+ Changed the values of the color terms: u3, b3, v3, r3, i3 to
+ 0.0 to more closely correspond with reality.
+
+ (Davis, 2/1/92)
+
+photcal/mkimsets/t_imgroup.x
+ Added declarations for <fset.h> and <ctotok.h> to t_imgroup.x
+
+ (Davis, 20/11/91)
+
+photcal/
+ Changed all references to dump in the photcal scripts to pdump.
+
+ (Davis, 11/11/91)
+
+ *** Ran spplint on the photcal package.
+
+photcal/mkconfig/t_config.x
+ The routine ph_rcolnumber was being declared as a boolean instead
+ of an int inside the routines ph_rcsection and ph_rosection.
+
+ The boolean routine ph_isident was being declared everywhere as an
+ integer.
+
+photcal/parser/prtable.x
+ The routine pr_incol was declared as a function but called as a
+ subroutine.
+
+photcal/parser/prput.x
+ The routine mct_getp was being called instead of mct_putp inside the
+ routine pr_psym. It appears that this routine was not actually used
+ so this does not seem to matter.
+
+photcal/mctable/mctindef.x
+ Amovkc and amovks were being called with the integer constants INDEFS
+ and '\000' instead of short (INDEFS) and char ('\000'). This bug would
+ affect test versions of photcal.
+
+photcal/evaluate/phinvert.tx
+ The determinant det was declared as an integer variable in ph_accum instead
+ of a real. This was "almost" harmless because det was being computed
+ as real and simply passed into the calling routine where it was interpreted
+ as real. However one test was being done on det inside the ph_accum
+ routine which might fail. This was not a problem in the test version of
+ the code, but a bug introduced by my last minute changes.
+
+ (Davis, 10/4/91)
+
+photcal/invertfit.par
+photcal/evaluate/t_invertfit.x
+photcal/evaluate/phinvert.x
+photcal/evaluate/pherrors.x
+photcal/doc/invertfit.hlp
+photcal/evalfit.par
+photcal/evaluate/t_evalfit.x
+
+ 1. Improved the convergence criteria of the invertfit routines by
+ increasing the maximum number of iterations, testing the determinant
+ of the curvature matrix and quitting if it is < 1.0 e-20, making
+ sure that the parameter increments never are less than abs(.01),
+ and terminating the fit if the rms starts to increase. These changes
+ are not terribly important for the usual linear systems of
+ photometric equations but are important for trying to invert higher
+ order systems.
+
+ 2. Made catalog a hidden parameter in invertfit.
+
+ 3. Made catalog a hidden parameter in evalfit.
+
+ 4. Improved the help pages for invertfit and evalfit.
+
+ (Davis, 10/8/91)
+
+photcal/mkconfig.cl
+photcal/mkconfig/t_config.x
+photcal/doc/mkconfig.hlp
+
+ 1. Made template a hidden parameter with a default values of "".
+
+ 2. Made extensive modifications to the prompts to mprove the clarity
+ of the task.
+
+ 3. Removed the options parameter. It caused to many headaches in the
+ script.
+
+ 4. Made extensive modifications to the help page.
+
+ (Davis, 24/7/91)
+
+photcal/mkobsfile/phmatch.x
+ 1. The number of objects to be output was being computed incorrectly in the
+ case that tolerance <= 0.0 and allfilters=yes.
+
+ 2. In some circumstances the preprocessor was computing the number of
+ matched objects incorrectly resultings in a few dummy objects with
+ undefined or incorrect data being written at the end of the real data.
+
+ 3. If data from the same image existed in two different files and those
+ files were not in order in the input list then the pre-processor
+ would erroneously correct for the exposure time resulting in incorrect
+ magnitudes in the observations file.
+
+ (Davis, 19/7/91)
+
+photcal/evaluate/t_invertfit.x
+photcal/evaluate/phinvert.x
+photcal/evaluate/pherrors.x
+photcal/evaluate/phminv.f
+photcal/evaluate/phcheck.f
+ 1. Modified invertfit to be able to deal with set equations which contain
+ references to catalog variables which were not themselves referenced
+ in the transformation equations.
+
+ 2. Tightened the convergence criteria for doing the inversion.
+
+ (Davis, 8/7/91)
+
+photcal/mkobsfile/phimtable.x
+ 1. The code which reads in the images sets from the standard input has
+ been modified to prompt only for the image name, not the image filter.
+ If the filter id is defined in the database it will be used, otherwise
+ filter ids will be assigned to the images in the order in which they
+ occur in the parameter idfilters. The code which reads in filter id,
+ exposure time, and airmass from the optional observing parameters file
+ will now always prompt for a filter id.
+
+ (Davis, 8/7/91)
+
+photcal/mkobsfile/t_obsfile.x
+ 1. Fixed a bug in the pre-processor tasks (mknobsfile, obsfile, mkobsfile)
+ wherein the pre-processors would crash if an image name was referenced
+ in more than one image set. This bug was not in the original pre-processor
+ but crept in when the sorting algorithm was re-done. Checking for
+ duplicate image names has been removed from the sorting step and
+ placed in the matching step where it belongs.
+
+ (Davis, 8/7/91)
+
+photcal/mknobsfile.cl
+photcal/mkobsfile.cl
+ 1. Added the parameters verify and verbose to the mknobsfile task.
+
+ 2. Added the parameter verbose to the mkobsfile task.
+
+ (Davis, 6/7/91)
+
+photcal/mknobsfile.cl
+photcal/mkobsfile.cl
+photcal/obsfile.par
+photcal/mkobsfile/t_obsfile.x
+photcal/doc/mknobsilfe.hlp
+photcal/doc/obsilfe.hlp
+ 1. Removed the format parameter from the mknobsfile, obsfile and
+ mkobsfile tasks. The format description file is always assigned a
+ default name based on the name of the observations file. Any pre-existing
+ format file without an existing observations file will be deleted if a
+ new catalog of the same name is requested.
+
+ 2. Clarified the documentation for mknobsfile by emphasizing the
+ circumstances under which it is the preprocessor of choice. Switch the
+ order of examples 2 and 3, to reflect likely-hood of use.
+
+ 3. Clarified the documentation for obsfile by emphasizing the circumstances
+ under which it is the preprocessor of choice.
+
+ (Davis, 5/7/91)
+
+photcal/mkimsets.cl
+photcal/imgroup.par
+photcal/mkimsets/t_imgroup.x
+photcal/mkimsets/imlist.key
+photcal/mkimsets/imgroup.key
+photcal/doc/mkimsets.hlp
+
+ 1. Changed the mode of the mkimsets task parameter from auto to hidden.
+
+ 2. Changed the name of the mkimsets task parameter label to rename.
+
+ 3. Changed the name of the mkimsets task parameter check to review.
+
+ 4. Changed all the references to identifier in the mkimsets .hlp file
+ to name.
+
+ 5. Modified the .key files and the documentation appropriately.
+
+ (Davis, 4/7/91)
+
+photcal/mkcatalog.cl
+photcal/catalog.par
+photcal/mkcatalog/t_catalog.x
+photcal/doc/mkcatalog.hlp
+ 1. Removed the format parameter from the mkcatalog and catalog tasks.
+ The format description file is always assigned a default name
+ based on the name of the catalog. Any pre-existing format file without
+ and existing catalog will be deleted if a new catalog of the same
+ name is requested.
+
+ 2. Removed the title parameter and modified the task to write the file
+ name to the catalog title keyword. The task will complain if the file
+ name is not the same as the title keyword if the user tries to add
+ new records to an existing catalog. This will only happen if the
+ user has renamed the catalog or copied it to another file.
+
+ 3. The code was modified to prompt for the error columns and to supply
+ a default name of the form "error(name)" if a carriage return
+ character was issued.
+
+ 4. The documentation was modified to explain how the default naming scheme
+ of the preprocessors works. The examples were changed to use upper
+ case letters for the standard photometric indices. A note of explanation
+ was added regarding the EOF and CR characters (end-of-file and
+ carriage return)
+
+ (Davis 4/7/91)
+
+photcal/mkobsfile/phmatch.x
+ Fixed a bug in the matching code where stars which were not matched
+ in the first filter would not be written to the observations files.
+
+ (Davis 24/6/91)
+
+photcal/photcal.par
+ Changed the definition of the catalog directory from "newphotred$catalogs/"
+ to "photcal$catalogs/".
+
+ (Davis 20/6/91)
+
+photcal/inlfit/ingcolon.gx
+ INLFIT was not recognizing the full colon command "tolerance". It would
+ accept tol.
+
+ (Davis 19/6/91)
+
+photcal/mctable/mctput.gx
+ Test for the legal column limits had an && instead of an || expression.
+
+ (Davis 19/6/91)
+
+photcal/evaluate/phprint.x
+ The evalfit and invertfit programs were crashing with an error if
+ a symbol that was defined in the configuration file was included
+ in the print string.
+
+ (Davis 11/6/53)
+
+photcal/evaluate/invertfit.x
+ Added a protection against a zero divide error which can occur if
+ the fit is perfect.
+
+ (Davis 11/6/53)
+
+photcal/fitparams/fttrneq.x
+ Changed an erroneous call to amovkr to the correct call to amovr. This
+ fixed a bug which occurred when a user tried to quit the task
+ but changed their mind at the last minute.
+
+ (Davis 20/5/91)
+
+photcal/mctable/mctput.gx
+ Table space was being reallocated as type real no matter what the
+ data type of the table. This did not matter in previous versions
+ of photcal but became a problem when the star id facility was added
+ to inlfit.
+
+ (Davis 30/5/91)
+
+photcal/fitparams/ftweights.x
+ The routines for computing the weights were crashing if there were
+ INDEF values in the observations.
+
+ (Davis 20/5/91)
+
+ Beta release of photcal to selected sites. (Davis 20/5/91)
+
+.fi
+.endhelp
diff --git a/noao/digiphot/photcal/apfile.par b/noao/digiphot/photcal/apfile.par
new file mode 100644
index 00000000..89220eff
--- /dev/null
+++ b/noao/digiphot/photcal/apfile.par
@@ -0,0 +1,25 @@
+# Parameter file for APFILE
+
+photfiles,f,a,,,,The list of input text files
+incolumns,s,a,"",,,The format of the input text files
+naperts,i,a,,,,The number of apertures to extract from the input text files
+apercors,f,a,"",,,The output aperture corrections file
+smallap,i,h,1,1,,The index of the smallest aperture
+largeap,i,h,0,1,,The index of the largest aperture
+magfile,f,h,"",,,The optional output best magnitudes file
+logfile,f,h,"",,,The optional output log file
+plotfile,f,h,"",,,The optional output plot file
+append,b,h,no,,,"Open the log and plot files in append mode ?"
+obsparams,f,h,"",,,The optional input observing parameters file
+obscolumns,s,h,"2 3 4 5",,,The format of the input airmass file
+maglim,s,h,0.10,,,The maximum permitted magnitude error
+nparams,i,h,3,1,5,The number of cog model parameters to fit
+swings,r,h,1.2,1.0,,The power law slope of the stellar wings
+pwings,r,h,0.1,0.0,1.0,The fraction of the total power in the stellar wings
+pgauss,r,h,0.5,0.0,1.0,The fraction of the core power in the gaussian core
+rgescale,r,h,0.9,0.0,,"The exponential / gaussian core radial scales"
+xwings,r,h,0.0,,,The extinction coefficicent
+interactive,b,h,yes,,,Do the fit interactively ?
+verify,b,h,no,,,Verify interactive user input ?
+gcommands,*gcur,h,"",,,The graphics cursor
+graphics,s,h,stdgraph,,,The graphics device
diff --git a/noao/digiphot/photcal/catalog.par b/noao/digiphot/photcal/catalog.par
new file mode 100644
index 00000000..0d44b794
--- /dev/null
+++ b/noao/digiphot/photcal/catalog.par
@@ -0,0 +1,5 @@
+# Parameter file for CATALOG
+
+catalog,f,a,,,,The name of the output catalog
+review,b,h,no,,,Verify each existing catalog record
+verify,b,h,no,,,Verify each new catalog record
diff --git a/noao/digiphot/photcal/catalogs/README b/noao/digiphot/photcal/catalogs/README
new file mode 100644
index 00000000..3eee4c75
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/README
@@ -0,0 +1,109 @@
+This directory contains the supported standard star catalogs, format
+description files, and a template transformation equation set for each
+catalog.
+
+The following standard star catalogs are supported.
+
+ elias.dat - the Elias JHKL standards catalog
+ landolt.dat - the Landolt UBVRI standards catalog
+ nlandolt.dat - the new Landolt UBVRI standards catalog
+ odewahn.dat - the Odewahn BVR cluster standards catalog (1)
+ porter.dat - the Porter UBVRI standards catalog (2)
+ ukirt.dat - the UKIRT JHK standards (3)
+ nicmos.dat - the NICMOS JHKKs standards catalog (4)
+ arnica.dat - the ARNICA JHK standards catalog (4)
+
+Each supported catalog has an accompanying format description file which
+describes which photometric indices are stored in which column. This file is
+used by the MKCONFIG task to construct the user's configuration file. The
+following format files are defined.
+
+ felias.dat - format file for Elias JHKL standards
+ flandolt.dat - format file for Landolt UBVRI standards
+ fnlandolt.dat - format file for new Landolt UBVRI standards
+ fodewahn.dat - format file for Odewahn BVR cluster standards
+ fporter.dat - format file for Porter UBVRI cluster standards
+ fukirt.dat - format file for UKIRT JHK standards
+ fnicmos.dat - format file for NICMOS JHKKs standards
+ farnica.dat - format file for ARNICA JHK standards
+
+Each supported catalog has an accompanying template transformation file
+which defines a default set of transformations equations. This file is
+used as a template by the MKCONFIG task to guide the user in the construction
+of a set of transformation equations. The following transformation equations
+sets are defined.
+
+ telias.dat - template trnasformations for Elias JHKL standards
+ tlandolt.dat - template transformations for Landolt UBVRI standards
+ tnlandolt.dat - template transformations for new Landolt UBVRI standards
+ todewahn.dat - template transformations for Odewahn BVR cluster standards
+ tporter.dat - template transformations for Porter UBVRI cluster standards
+ tukirt.dat - template transformations for UKIRT JHK standards
+ tnicmos.dat - template transformations for the NICMOS JHKKs standards
+ tarnica.dat - template transformations for the ARNICA JHK standards
+
+The references for the supported catalogs are listed below.
+
+
+ elias.dat - Elias, et. al 1982, A.J. 87, 1029
+ landolt.dat - Landolt, A. U. 1983, A.J. 88, 439
+ nlandolt.dat - Landolt, A. U. 1992, A.J. 104, 340
+ odewahn.dat - Odewahn, S. C. 1992 PASP 104,553
+ porter.dat - unpublished
+ ukirt.dat - Casali, M. and Hawarden, T. 1992, JCMT-UKIRT
+ Newsletter, 4, 33
+ nicmos.dat - Persson et al. 1998, A.J. 116, 2475
+ arnica.dat - Hunt et al. 1998, A.J. 115, 2594
+
+Notes:
+
+(1) The Odewahn catalog contains data for the clusters NGC4147, NGC7006
+ and NGC7790. The data was kindly formatted for use with photcal by Pat
+ Hall (Steward Observatory).
+
+(2) The Porter catalog contains unpublished UBVRI data and data compiled from
+ the literature for the clusters M67, M92, NGC2264, NGC2419, NGC4147,
+ NGC7006, and NGC7790 kindly provided by Alain Porter (KPNO) and formatted
+ for use with photcal by Pat Hall (Steward Observatory). The following
+ notes describe how the the catalog was compiled.
+
+ Porter.dat contains unpublished UBVRI (**KRON-COUSINS** RI) photometry
+ compiled by Alain Porter (KPNO) from personal data, photometry from the
+ literature, and photmetry supplied by Lindsey Davis (KPNO). It is
+ basically intended to supplement BVRI data from Christian et.al. (1985).
+ The differences between this data and Christian's, and between this data
+ and the BVR data of Odewahn et.al. (1992), are well within the errors.
+ The only exception is that for stars in common with Odewahn's NGC 7790
+ data, this data is ~0.05 mag fainter than Odewahn's data, a difference
+ at the 3-sigma level.
+
+ Notes on individual clusters follow, giving the source of the ID numbers
+ and references where finding charts can be found.
+
+ M67 ID numbers are from Schild (1983), Eggen & Sandage (1964), or
+ Johnson & Sandage (1955).
+ M92 ID numbers are from Christian et.al. or from Sandage (1966).
+ NGC2264 ID numbers are from Christian et.al. or from Adams et.al. (1983).
+ NGC2419 These values come straight from Christian et.al. and thus there
+ is no U information for this cluster.
+ NGC4147 ID numbers are from Odewahn et.al.
+ NGC7006 ID numbers are from Christian et.al. or from Sandage & Wildey
+ (1967).
+ NGC7790 ID numbers are from Odewahn et.al., except for C-25 which is star
+ 25 of Christian et.al.
+
+ REFERENCES
+ Adams, M., et. al. 1983, ApJS 53, 893. (field P2 or 2P)
+ Christian, C.A., et. al. 1985, PASP 97, 363.
+ Eggen, O. and Sandage, A. 1964, ApJ 140, 130.
+ Johnson, H. and Sandage, A. 1955, ApJ 121, 616.
+ Odewahn, S.C., et. al. 1992, PASP 104, 553.
+ Sandage, A. 1966, ApJ 143, 313.
+ Sandage, A. and Wildey, R. 1967, ApJ 150, 469
+ Schild, R.E. 1983, PASP 95, 1021.
+
+(3) The UKIRT JHK catalog was formatted for use with photcal by Pat Hall
+ (Steward Observatory).
+
+(1) The NICMOS and ARNICAL catalogs were kindly formatted for use with photcal
+by Pat Hall (University or Toronto).
diff --git a/noao/digiphot/photcal/catalogs/arnica.dat b/noao/digiphot/photcal/catalogs/arnica.dat
new file mode 100644
index 00000000..392dda20
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/arnica.dat
@@ -0,0 +1,88 @@
+# Declare the ARNICA JHK standards catalog variables
+
+ AS01-0 10.716 0.005 10.507 0.010 10.470 0.003
+ AS02-0 8.775 0.006 8.771 0.012 8.770 0.009
+ AS03-0 12.606 0.011 12.729 0.008 12.827 0.013
+ AS04-0 10.555 0.004 10.301 0.005 10.277 0.006
+ AS04-1 12.371 0.021 12.033 0.020 11.962 0.025
+ AS05-0 13.232 0.009 13.314 0.007 13.381 0.010
+ AS05-1 14.350 0.013 13.663 0.011 13.507 0.009
+ AS06-0 8.713 0.010 8.694 0.014 8.674 0.010
+ AS07-0 11.105 0.013 10.977 0.009 10.946 0.010
+ AS08-0 8.744 0.011 8.723 0.014 8.697 0.012
+ AS08-1 8.772 0.011 7.836 0.018 7.570 0.017
+ AS08-2 9.728 0.011 9.121 0.015 8.995 0.016
+ AS09-0 8.432 0.012 8.380 0.014 8.340 0.011
+ AS09-1 11.546 0.015 10.923 0.016 10.730 0.015
+ AS10-0 11.349 0.011 11.281 0.009 11.259 0.006
+ AS11-0 9.151 0.009 9.181 0.010 9.183 0.011
+ AS11-1 11.299 0.009 10.342 0.015 10.051 0.008
+ AS12-0 13.700 0.018 13.812 0.015 13.884 0.011
+ AS12-1 11.241 0.007 10.931 0.018 10.866 0.020
+ AS13-0 10.517 0.005 10.189 0.005 10.137 0.005
+ AS13-1 12.201 0.019 11.781 0.007 11.648 0.009
+ AS13-2 12.521 0.008 12.101 0.005 11.970 0.006
+ AS13-3 13.345 0.015 12.964 0.017 12.812 0.012
+ AS14-0 8.688 0.013 8.623 0.014 8.590 0.007
+ AS14-1 9.871 0.015 9.801 0.015 9.755 0.011
+ AS15-0 10.874 0.007 10.669 0.010 10.628 0.008
+ AS15-1 12.656 0.011 11.980 0.010 11.792 0.011
+ AS15-2 13.711 0.014 12.927 0.017 12.719 0.012
+ AS15-3 14.320 0.015 13.667 0.017 13.415 0.015
+ AS16-0 14.159 0.021 14.111 0.011 14.305 0.017
+ AS16-1 13.761 0.020 13.638 0.005 13.606 0.021
+ AS16-2 11.411 0.010 11.428 0.017 11.445 0.008
+ AS16-3 13.891 0.012 13.855 0.011 13.818 0.011
+ AS16-4 11.402 0.015 11.106 0.019 11.043 0.009
+ AS17-0 14.353 0.012 14.039 0.015 13.983 0.016
+ AS17-1 12.434 0.009 12.077 0.012 12.027 0.017
+ AS17-2 14.745 0.012 14.124 0.012 13.871 0.016
+ AS17-3 13.077 0.007 12.782 0.010 12.706 0.006
+ AS17-4 14.459 0.018 13.795 0.014 13.430 0.018
+ AS18-0 12.741 0.008 12.402 0.004 12.338 0.013
+ AS18-1 10.769 0.024 10.614 0.014 10.575 0.014
+ AS19-0 12.670 0.014 12.334 0.013 12.263 0.004
+ AS19-1 10.095 0.017 9.794 0.013 9.746 0.010
+ AS19-2 12.745 0.019 12.488 0.024 12.437 0.012
+ AS20-0 9.551 0.012 9.519 0.007 9.497 0.015
+ AS21-0 9.061 0.007 9.043 0.015 9.031 0.007
+ AS22-0 12.966 0.005 13.038 0.010 13.158 0.007
+ AS23-0 8.889 0.010 8.847 0.009 8.828 0.010
+ AS24-0 9.398 0.009 9.345 0.009 9.338 0.010
+ AS25-0 14.029 0.008 14.134 0.010 14.195 0.009
+ AS26-0 13.000 0.015 12.455 0.012 12.379 0.010
+ AS26-1 12.120 0.016 11.527 0.016 11.428 0.016
+ AS27-0 10.910 0.015 10.781 0.007 10.761 0.010
+ AS27-1 12.991 0.015 12.677 0.024 12.608 0.019
+ AS28-0 8.455 0.010 8.378 0.014 8.372 0.008
+ AS29-0 10.234 0.005 9.842 0.013 9.760 0.009
+ AS29-1 13.904 0.017 13.566 0.019 13.503 0.020
+ AS30-0 13.505 0.004 13.197 0.011 13.141 0.014
+ AS30-1 12.497 0.017 12.157 0.011 12.175 0.021
+ AS31-0 10.744 0.008 10.644 0.005 10.602 0.004
+ AS31-1 12.504 0.010 12.131 0.011 12.048 0.007
+ AS31-2 13.290 0.009 12.633 0.011 12.476 0.010
+ AS32-0 8.017 0.018 7.917 0.012 7.925 0.014
+ AS33-0 12.220 0.004 11.834 0.005 11.739 0.009
+ AS33-1 13.180 0.009 12.477 0.004 12.343 0.008
+ AS33-2 13.724 0.024 13.271 0.023 13.168 0.014
+ AS34-0 8.443 0.019 8.434 0.003 8.436 0.019
+ AS35-0 8.625 0.009 8.544 0.011 8.524 0.006
+ AS36-0 13.168 0.013 13.242 0.007 13.301 0.007
+ AS36-1 13.538 0.028 13.049 0.012 12.960 0.014
+ AS36-2 14.246 0.014 13.847 0.014 13.737 0.008
+ AS36-3 14.165 0.004 13.607 0.009 13.333 0.022
+ AS36-4 15.312 0.008 14.769 0.006 14.514 0.022
+ AS37-0 8.669 0.017 8.678 0.009 8.635 0.009
+ AS37-1 11.020 0.026 10.516 0.014 10.399 0.011
+ AS38-0 11.932 0.006 11.988 0.009 12.027 0.010
+ AS38-1 12.994 0.004 12.657 0.012 12.588 0.020
+ AS38-2 11.355 0.023 11.026 0.014 10.991 0.013
+ AS39-0 13.808 0.008 13.929 0.002 14.011 0.009
+ AS39-1 15.033 0.022 14.333 0.004 14.045 0.018
+ AS40-0 11.051 0.013 10.408 0.013 10.240 0.013
+ AS40-1 11.900 0.012 11.097 0.011 10.861 0.008
+ AS40-2 11.477 0.018 10.569 0.014 10.314 0.018
+ AS40-3 10.578 0.015 9.966 0.011 9.785 0.008
+ AS40-4 10.356 0.015 9.695 0.008 9.516 0.007
+ AS40-5 9.488 0.013 9.418 0.007 9.405 0.008
diff --git a/noao/digiphot/photcal/catalogs/elias.dat b/noao/digiphot/photcal/catalogs/elias.dat
new file mode 100644
index 00000000..84fdadd9
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/elias.dat
@@ -0,0 +1,58 @@
+ HD225023 6.960 0.010 0.105 0.010 0.025 0.010 INDEF INDEF A0 b
+ G158-27 7.430 0.010 0.875 0.010 0.325 0.010 INDEF INDEF M b
+ HD1160 7.040 0.007 0.015 0.007 0.005 0.007 0.015 0.010 A0 a
+ HD2811 7.065 0.005 0.105 0.005 0.025 0.005 0.025 0.007 A2 a+
+ HD3029 7.090 0.010 0.160 0.010 0.030 0.010 INDEF INDEF A3 b
+ HR696 5.440 0.007 0.145 0.007 0.055 0.007 INDEF INDEF B2Ia a
+ HR718 4.390 0.007 -0.025 0.007 -0.010 0.007 -0.025 0.010 B9III a
+ Gl105.5 6.525 0.007 0.715 0.007 0.110 0.007 0.065 0.010 M0V a
+ HD18881 7.140 0.015 -0.015 0.015 -0.010 0.015 INDEF INDEF A0 c
+ HD19904 6.640 0.005 0.080 0.005 0.020 0.005 0.020 0.007 A2 a+
+ G77-31 7.840 0.010 0.900 0.010 0.320 0.010 0.290 0.015 M b
+ HD22686 7.185 0.007 0.010 0.007 0.005 0.007 -0.010 0.010 A0 a
+ HR1552 4.140 0.007 -0.100 0.007 -0.045 0.007 -0.025 0.010 B2III a
+ HD38921 7.535 0.005 0.035 0.005 0.015 0.005 0.010 0.007 A0 a+
+ HD40335 6.450 0.007 0.090 0.007 0.020 0.007 0.035 0.010 A0 a
+ HD44612 7.040 0.015 0.020 0.015 -0.005 0.015 INDEF INDEF A0 c
+ BD+0_1694 4.585 0.005 1.055 0.005 0.225 0.005 0.170 0.007 ? a+
+ Gl299 7.640 0.005 0.740 0.005 0.275 0.005 0.280 0.007 M5V a+
+ HD75223 7.280 0.005 0.045 0.005 0.015 0.005 0.020 0.007 A0 a+
+ HD77281 7.030 0.005 0.075 0.005 0.020 0.005 0.035 0.007 A2 a+
+ Gl347a 7.630 0.010 0.780 0.010 0.230 0.010 0.205 0.015 M5 b
+ HD84800 7.530 0.015 0.030 0.015 0.000 0.015 INDEF INDEF A2 c
+ HR3888 2.990 0.007 0.145 0.007 0.030 0.007 INDEF INDEF F2IV a
+ Gl390 6.045 0.007 0.825 0.007 0.205 0.007 0.165 0.010 M0V a
+ Gl406 6.080 0.010 0.980 0.010 0.360 0.010 0.350 0.015 M8V b
+ HD101452 6.845 0.005 0.160 0.005 0.040 0.005 0.035 0.007 A2 a+
+ HR4550 4.385 0.007 0.485 0.007 0.070 0.007 0.045 0.010 G8V a
+ HD105601 6.685 0.015 0.125 0.015 0.030 0.015 INDEF INDEF A2 c
+ HD106965 7.315 0.005 0.060 0.005 0.020 0.005 0.020 0.007 A2 a+
+ HR4689 3.765 0.007 0.025 0.007 0.010 0.007 0.010 0.010 A2IV a
+ HR5447 3.485 0.007 0.195 0.007 0.025 0.007 0.050 0.010 F2V a
+ HD129653 6.920 0.007 0.060 0.007 0.020 0.007 INDEF INDEF A2 a
+ HD129655 6.690 0.007 0.125 0.007 0.030 0.007 0.025 0.010 A2 a
+ HD130163 6.835 0.007 0.020 0.007 0.010 0.007 0.025 0.010 A0 a
+ BD+3_2954 4.805 0.010 1.035 0.010 0.190 0.010 0.155 0.015 M0 b
+ HD136754 7.135 0.010 0.015 0.010 -0.005 0.010 INDEF 0.000 A0 b
+ BD+2_2957 4.245 0.010 0.955 0.010 0.180 0.010 0.150 0.015 K2 b
+ HR6092 4.300 0.007 -0.100 0.007 -0.035 0.007 INDEF INDEF B5IV a
+ S_R3 6.520 0.015 1.185 0.015 0.445 0.015 INDEF INDEF [A0] c
+ Oph_S1 6.330 0.015 2.470 0.015 0.940 0.015 0.560 0.020 [B-A] c
+ HR6136 2.020 0.007 0.810 0.007 0.140 0.007 0.150 0.010 K4III a
+ HD161743 7.615 0.005 0.005 0.005 0.005 0.005 0.010 0.007 A0 a+
+ HD161903 7.020 0.007 0.150 0.007 0.035 0.007 0.035 0.010 A2 a
+ HD162208 7.110 0.010 0.105 0.010 0.035 0.010 INDEF INDEF A0 b
+ HR6707 3.205 0.007 0.245 0.007 0.040 0.007 INDEF INDEF F2IV a
+ Gl748 6.305 0.015 0.770 0.015 0.240 0.015 INDEF INDEF M4V c
+ HR7615 1.630 0.007 0.525 0.007 0.070 0.007 0.110 0.010 K0III a
+ Gl811.1 6.930 0.015 0.825 0.015 0.220 0.015 0.190 0.020 M4V c
+ HD201941 6.625 0.007 0.075 0.007 0.015 0.007 0.015 0.010 A2 a
+ HR8143 3.795 0.007 0.075 0.007 0.030 0.007 0.085 0.010 B9Ia a
+ HD203856 6.860 0.010 0.065 0.010 0.020 0.010 INDEF INDEF A0 b
+ HD205772 7.655 0.005 0.110 0.005 0.030 0.005 0.020 0.007 A3 a+
+ HR8541 4.250 0.007 0.050 0.007 0.015 0.007 0.020 0.010 B9Ia a
+ HR8551 2.295 0.007 0.610 0.007 0.075 0.007 0.075 0.010 K0III a
+ M15_I-12 9.420 0.000 0.770 0.000 0.130 0.000 INDEF INDEF ? i
+ M15_II-29 10.300 0.000 0.730 0.000 0.130 0.000 INDEF INDEF ? i
+ M15_II-64 10.570 0.000 0.690 0.000 0.140 0.000 INDEF INDEF ? i
+ M15_II-75 9.920 0.000 0.730 0.000 0.110 0.000 INDEF INDEF ? i
diff --git a/noao/digiphot/photcal/catalogs/farnica.dat b/noao/digiphot/photcal/catalogs/farnica.dat
new file mode 100644
index 00000000..96a58f4b
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/farnica.dat
@@ -0,0 +1,10 @@
+# Declare the ARNICA JHK standards catalog variables
+
+catalog
+
+J 2 # J magnitude
+error(J) 3 # err J
+H 4 # H magnitude
+error(H) 5 # err H
+K 6 # K magnitude
+error(K) 7 # err K
diff --git a/noao/digiphot/photcal/catalogs/felias.dat b/noao/digiphot/photcal/catalogs/felias.dat
new file mode 100644
index 00000000..476b166f
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/felias.dat
@@ -0,0 +1,12 @@
+# Declare the Elias JHKL standards catalog variables
+
+catalog
+
+K 2 # K magnitude
+error(K) 3 # err K
+JK 4 # (J - K) color
+error(JK) 5 # error (J - K)
+HK 6 # (H - K) color
+error(HK) 7 # error (H - K)
+KL 8 # (K - L) color
+error(KL) 9 # error (K - L)
diff --git a/noao/digiphot/photcal/catalogs/flandolt.dat b/noao/digiphot/photcal/catalogs/flandolt.dat
new file mode 100644
index 00000000..09b575b4
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/flandolt.dat
@@ -0,0 +1,17 @@
+# Declare the Landolt UBVRI standards catalog variables
+
+catalog
+
+V 4 # the V magnitude
+BV 5 # the (B-V) color
+UB 6 # the (U-B) color
+VR 7 # the (V-R) color
+RI 8 # the (R-I) color
+VI 9 # the (V-I) color
+
+error(V) 12 # the V magnitude error
+error(BV) 13 # the (B-V) color error
+error(UB) 14 # the (U-B) color error
+error(VR) 15 # the (V-R) color error
+error(RI) 16 # the (R-I) color error
+error(VI) 17 # the (V-I) color error
diff --git a/noao/digiphot/photcal/catalogs/fnicmos.dat b/noao/digiphot/photcal/catalogs/fnicmos.dat
new file mode 100644
index 00000000..21df0b34
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/fnicmos.dat
@@ -0,0 +1,12 @@
+# Declare the NICMOS JHKKs standards catalog variables
+
+catalog
+
+J 2 # J magnitude
+error(J) 3 # err J
+H 4 # H magnitude
+error(H) 5 # err H
+K 6 # K magnitude
+error(K) 7 # err K
+Ks 6 # Ks (K-short) magnitude
+error(Ks) 7 # err Ks
diff --git a/noao/digiphot/photcal/catalogs/fnlandolt.dat b/noao/digiphot/photcal/catalogs/fnlandolt.dat
new file mode 100644
index 00000000..e0d6b7ef
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/fnlandolt.dat
@@ -0,0 +1,17 @@
+# Declare the new Landolt UBVRI standards catalog variables
+
+catalog
+
+V 4 # the V magnitude
+BV 5 # the (B-V) color
+UB 6 # the (U-B) color
+VR 7 # the (V-R) color
+RI 8 # the (R-I) color
+VI 9 # the (V-I) color
+
+error(V) 12 # the V magnitude error
+error(BV) 13 # the (B-V) color error
+error(UB) 14 # the (U-B) color error
+error(VR) 15 # the (V-R) color error
+error(RI) 16 # the (R-I) color error
+error(VI) 17 # the (V-I) color error
diff --git a/noao/digiphot/photcal/catalogs/fodewahn.dat b/noao/digiphot/photcal/catalogs/fodewahn.dat
new file mode 100644
index 00000000..e834ba7d
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/fodewahn.dat
@@ -0,0 +1,10 @@
+# Declare the Odewahn BVR standards catalog variables
+
+catalog
+
+V 2 # the V magnitude
+error(V) 3 # the V magnitude error
+BV 4 # the (B-V) color
+error(BV) 5 # the (B-V) color error
+VR 6 # the (V-R) color
+error(VR) 7 # the (V-R) color error
diff --git a/noao/digiphot/photcal/catalogs/fonlandolt.dat b/noao/digiphot/photcal/catalogs/fonlandolt.dat
new file mode 100644
index 00000000..e0d6b7ef
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/fonlandolt.dat
@@ -0,0 +1,17 @@
+# Declare the new Landolt UBVRI standards catalog variables
+
+catalog
+
+V 4 # the V magnitude
+BV 5 # the (B-V) color
+UB 6 # the (U-B) color
+VR 7 # the (V-R) color
+RI 8 # the (R-I) color
+VI 9 # the (V-I) color
+
+error(V) 12 # the V magnitude error
+error(BV) 13 # the (B-V) color error
+error(UB) 14 # the (U-B) color error
+error(VR) 15 # the (V-R) color error
+error(RI) 16 # the (R-I) color error
+error(VI) 17 # the (V-I) color error
diff --git a/noao/digiphot/photcal/catalogs/fporter.dat b/noao/digiphot/photcal/catalogs/fporter.dat
new file mode 100644
index 00000000..a0495b22
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/fporter.dat
@@ -0,0 +1,14 @@
+# Declare the Porter unpublished UBVRI photometry catalog variables
+
+catalog
+
+V 2 # V magnitude
+error(V) 3 # error in V
+UB 4 # (U-B) color
+error(UB) 5 # error in (U-B)
+BV 6 # (B-V) color
+error(BV) 7 # error in (B-V)
+VR 8 # (V-R) color
+error(VR) 9 # error in (V-R)
+RI 10 # (R-I) color
+error(RI) 11 # error in (R-I)
diff --git a/noao/digiphot/photcal/catalogs/fukirt.dat b/noao/digiphot/photcal/catalogs/fukirt.dat
new file mode 100644
index 00000000..0afd8da4
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/fukirt.dat
@@ -0,0 +1,10 @@
+# Declare the UKIRT JHK standards catalog variables
+
+catalog
+
+K 2 # K magnitude
+error(K) 3 # err K
+JK 4 # (J - K) color
+error(JK) 5 # error (J - K)
+HK 6 # (H - K) color
+error(HK) 7 # error (H - K)
diff --git a/noao/digiphot/photcal/catalogs/landolt.dat b/noao/digiphot/photcal/catalogs/landolt.dat
new file mode 100644
index 00000000..e6becb23
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/landolt.dat
@@ -0,0 +1,223 @@
+ 315 0:06:59 -02:37:52 6.440 -0.145 -0.497 -0.037 -0.064 -0.101 4 3 0.007 0.007 0.004 0.004 0.005 0.007
+ 2892 0:31:26 01:06:13 9.366 1.321 1.409 0.692 0.625 1.319 15 10 0.004 0.004 0.005 0.002 0.003 0.002
+ -15_115 0:37:36 -15:04:51 10.881 -0.190 -0.860 -0.095 -0.103 -0.198 11 8 0.006 0.004 0.006 0.003 0.008 0.008
+ -12_134 0:46:19 -11:57:32 11.775 -0.294 -1.329 -0.088 -0.078 -0.161 12 8 0.005 0.004 0.009 0.004 0.010 0.007 1
+ -11_162 0:51:30 -10:44:49 11.190 -0.081 -1.138 0.050 0.095 0.144 10 7 0.008 0.005 0.006 0.005 0.003 0.006
+ 92_336 0:54:16 00:42:36 8.046 0.985 0.815 0.518 0.465 0.984 16 10 0.002 0.002 0.003 0.001 0.004 0.005
+ 92_342 0:54:24 00:38:22 11.616 0.435 -0.040 0.264 0.272 0.536 22 12 0.002 0.002 0.004 0.002 0.002 0.002
+ 92_263 0:54:54 00:31:26 11.784 1.048 0.846 0.564 0.520 1.085 23 12 0.005 0.003 0.006 0.002 0.002 0.003 2
+ 5505 0:56:05 01:36:00 9.001 1.078 0.955 0.553 0.502 1.056 12 8 0.003 0.004 0.005 0.001 0.003 0.003
+ 92_288 0:56:31 00:31:55 11.631 0.857 0.473 0.489 0.441 0.931 23 12 0.003 0.004 0.004 0.003 0.002 0.002
+ F_11 1:03:30 04:09:15 12.061 -0.236 -0.978 -0.119 -0.141 -0.260 24 12 0.002 0.002 0.003 0.002 0.004 0.004
+ 93_103 1:52:35 00:18:50 8.831 1.161 1.157 0.585 0.518 1.104 18 11 0.003 0.003 0.005 0.003 0.002 0.003
+ F_16 1:53:51 -06:50:42 12.405 -0.010 0.015 -0.009 0.004 -0.001 25 13 0.002 0.002 0.008 0.005 0.004 0.004
+ 93_317 1:53:52 00:38:36 11.547 0.489 -0.053 0.293 0.296 0.589 20 11 0.001 0.002 0.003 0.002 0.001 0.001
+ 93_326 1:54:04 00:42:40 9.569 0.454 -0.039 0.263 0.265 0.528 24 14 0.002 0.003 0.004 0.003 0.003 0.003
+ 93_332 1:54:17 00:35:48 9.789 0.518 -0.024 0.296 0.306 0.602 18 11 0.004 0.004 0.005 0.003 0.002 0.003
+ 93_333 1:54:19 00:41:20 12.006 0.829 0.434 0.469 0.421 0.891 20 10 0.002 0.003 0.004 0.002 0.002 0.003
+ 93_241 1:54:33 00:32:08 9.400 0.853 0.425 0.463 0.453 0.916 24 14 0.002 0.003 0.005 0.001 0.002 0.002
+ 93_424 1:54:40 00:52:19 11.620 1.084 0.945 0.553 0.504 1.059 20 10 0.002 0.004 0.006 0.001 0.002 0.001
+ 11983 1:56:47 -07:36:11 8.192 1.512 1.884 0.807 0.746 1.554 22 14 0.005 0.006 0.010 0.006 0.003 0.005
+ 12021 1:57:10 -02:10:37 8.874 -0.082 -0.404 -0.042 -0.056 -0.098 22 14 0.002 0.004 0.003 0.002 0.003 0.003
+ F_22 2:29:32 05:12:19 12.798 -0.055 -0.816 -0.105 -0.101 -0.201 26 16 0.003 0.004 0.006 0.004 0.005 0.005
+ F_24 2:34:19 03:40:10 12.409 -0.199 -1.172 0.092 0.362 0.450 26 16 0.004 0.002 0.008 0.003 0.004 0.005
+ 16581 2:38:46 01:17:26 8.195 -0.057 -0.305 -0.025 -0.038 -0.063 21 15 0.004 0.004 0.003 0.002 0.002 0.003
+ -0_454 2:55:09 00:27:24 8.895 1.426 1.579 0.758 0.686 1.445 20 12 0.003 0.003 0.008 0.002 0.002 0.002
+ 94_305 2:55:10 00:27:20 8.889 1.423 1.586 0.757 0.685 1.443 17 10 0.005 0.005 0.007 0.003 0.001 0.004
+ 94_308 2:55:28 00:27:41 8.743 0.494 -0.004 0.290 0.287 0.576 22 15 0.002 0.002 0.004 0.002 0.002 0.002
+ 94_242 2:56:36 00:15:02 11.730 0.307 0.095 0.177 0.186 0.362 19 12 0.002 0.002 0.003 0.002 0.002 0.003
+ -2_524 2:56:54 -02:03:26 10.307 -0.104 -0.641 -0.050 -0.062 -0.111 24 16 0.003 0.004 0.004 0.002 0.003 0.004
+ 94_251 2:57:01 00:12:28 11.203 1.218 1.275 0.656 0.586 1.243 19 12 0.002 0.002 0.005 0.002 0.001 0.002
+ 94_702 2:57:27 01:07:18 11.595 1.416 1.614 0.758 0.672 1.431 19 12 0.002 0.003 0.008 0.002 0.002 0.002
+ 94_342 2:57:43 00:22:39 9.041 0.993 0.716 0.527 0.488 1.015 18 12 0.002 0.003 0.005 0.002 0.001 0.002
+ 21197 3:24:18 -05:23:14 7.866 1.150 1.141 0.686 0.558 1.246 24 15 0.005 0.005 0.003 0.002 0.002 0.003
+ 95_301 3:51:55 00:28:39 11.219 1.285 1.298 0.692 0.622 1.313 21 14 0.004 0.002 0.006 0.003 0.001 0.003
+ 95_96 3:52:08 -00:02:21 10.014 0.147 0.068 0.079 0.093 0.172 45 31 0.003 0.002 0.004 0.001 0.002 0.002
+ 95_52 3:53:28 -00:10:58 9.574 0.529 0.069 0.307 0.304 0.611 23 14 0.003 0.003 0.003 0.002 0.002 0.002
+ 95_206 3:53:30 00:14:44 8.737 0.502 0.015 0.290 0.285 0.575 21 13 0.002 0.002 0.004 0.002 0.001 0.002
+ 95_132 3:54:05 00:02:44 12.062 0.449 0.302 0.259 0.289 0.546 19 13 0.003 0.003 0.009 0.002 0.003 0.003
+ 95_74 3:54:45 -00:11:49 11.529 1.127 0.702 0.598 0.566 1.163 17 12 0.002 0.002 0.007 0.002 0.002 0.002
+ 95_236 3:55:27 00:06:08 11.492 0.735 0.169 0.421 0.412 0.832 16 12 0.001 0.003 0.006 0.002 0.001 0.002
+ 96_180 4:50:55 -00:06:44 8.930 1.049 0.841 0.548 0.504 1.051 20 12 0.003 0.001 0.005 0.001 0.002 0.002
+ 96_36 4:50:57 -00:11:41 10.589 0.250 0.111 0.133 0.137 0.270 19 10 0.002 0.002 0.005 0.001 0.001 0.002
+ 96_393 4:51:44 00:00:39 9.652 0.598 0.042 0.345 0.343 0.687 18 11 0.002 0.003 0.005 0.002 0.003 0.003
+ 96_737 4:51:49 00:21:01 11.718 1.331 1.173 0.736 0.698 1.433 19 10 0.003 0.003 0.009 0.002 0.001 0.002
+ 96_406 4:52:04 00:05:36 9.300 0.220 0.148 0.116 0.121 0.237 20 12 0.002 0.002 0.005 0.002 0.002 0.002
+ 96_83 4:52:13 -00:16:11 11.721 0.181 0.197 0.090 0.100 0.189 24 13 0.002 0.002 0.007 0.003 0.003 0.004
+ 96_235 4:52:33 -00:06:31 11.139 1.072 0.900 0.558 0.510 1.068 19 10 0.002 0.002 0.005 0.002 0.001 0.001
+ 36395 5:30:36 -03:36:56 7.960 1.474 1.231 0.985 1.095 2.076 28 18 0.005 0.005 0.005 0.002 0.002 0.003
+ GD_71 5:51:34 15:53:11 13.027 -0.255 -1.099 -0.141 -0.168 -0.305 24 13 0.003 0.005 0.008 0.004 0.008 0.007
+ 97_249 5:56:22 00:01:07 11.735 0.651 0.098 0.366 0.353 0.719 13 7 0.004 0.003 0.007 0.001 0.001 0.002
+ 97_346 5:56:41 00:13:17 9.260 0.594 0.114 0.338 0.324 0.662 29 18 0.002 0.002 0.003 0.002 0.001 0.003
+ 97_351 5:56:51 00:13:38 9.783 0.205 0.084 0.124 0.142 0.264 44 27 0.002 0.001 0.005 0.001 0.001 0.002
+ 97_284 5:57:39 00:05:09 10.787 1.366 1.098 0.778 0.726 1.504 14 7 0.002 0.004 0.006 0.002 0.001 0.002
+ 46056 6:30:33 04:50:58 8.230 0.192 -0.762 0.135 0.149 0.283 3 2 0.010 0.003 0.003 0.003 0.003 0.006 3
+ 47761 6:39:17 -04:41:00 8.724 0.159 -0.602 0.138 0.141 0.279 21 13 0.012 0.002 0.007 0.003 0.005 0.007 4
+ 98_978 6:50:48 -00:10:22 10.576 0.606 0.103 0.351 0.321 0.671 18 11 0.003 0.002 0.003 0.000 0.001 0.002
+ 98_185 6:51:16 -00:26:14 10.537 0.203 0.114 0.112 0.126 0.237 18 11 0.004 0.001 0.005 0.002 0.002 0.003
+ 50167 6:51:17 01:16:41 7.861 1.535 1.744 0.826 0.757 1.583 23 14 0.004 0.003 0.005 0.002 0.002 0.003
+ 98_193 6:51:18 -00:26:10 10.027 1.175 1.163 0.616 0.537 1.154 17 9 0.003 0.002 0.003 0.001 0.001 0.002
+ 98_653 6:51:19 -00:17:11 9.538 -0.004 -0.097 0.007 0.008 0.014 43 30 0.002 0.000 0.000 0.000 0.000 0.001
+ 98_667 6:51:25 -00:16:34 8.378 0.028 -0.336 0.071 0.078 0.149 20 13 0.004 0.002 0.005 0.002 0.002 0.002
+ 98_320 6:52:02 -00:35:26 9.180 1.143 1.136 0.596 0.520 1.116 37 25 0.002 0.002 0.002 0.001 0.000 0.001
+ 52533 7:00:42 -03:05:28 7.702 -0.088 -0.958 -0.011 -0.030 -0.038 23 13 0.005 0.002 0.005 0.002 0.005 0.004
+ 57884 7:22:22 -04:11:30 9.135 2.299 3.864 1.264 1.019 2.287 27 14 0.014 0.009 0.164 0.006 0.003 0.008 4
+ +5_1668 7:26:30 05:24:18 9.843 1.557 1.213 1.206 1.514 2.714 24 13 0.005 0.006 0.014 0.007 0.004 0.007
+ 60826 7:35:42 02:06:22 8.983 2.741 5.118 1.495 1.178 2.677 24 13 0.047 0.013 0.219 0.013 0.006 0.019 4
+ 99_6 7:52:48 -00:47:12 11.054 1.249 1.287 0.652 0.577 1.229 22 11 0.002 0.003 0.004 0.002 0.000 0.001
+ 99_358 7:53:12 -00:19:45 9.605 0.776 0.509 0.432 0.405 0.838 21 12 0.004 0.003 0.004 0.003 0.003 0.003
+ 99_367 7:53:26 -00:23:13 11.149 1.005 0.829 0.531 0.477 1.009 20 10 0.002 0.003 0.003 0.002 0.001 0.002
+ 99_296 7:54:01 -00:27:12 8.454 1.187 1.265 0.600 0.523 1.123 15 9 0.004 0.004 0.003 0.002 0.002 0.002
+ 99_185 7:54:07 -00:43:00 8.344 1.081 0.975 0.563 0.507 1.071 17 10 0.004 0.003 0.004 0.002 0.002 0.001
+ 99_408 7:54:27 -00:23:08 9.807 0.407 0.043 0.253 0.247 0.499 27 16 0.002 0.002 0.002 0.001 0.001 0.001
+ 99_418 7:54:41 -00:15:07 9.474 -0.041 -0.154 -0.003 -0.013 -0.016 17 10 0.005 0.004 0.008 0.003 0.003 0.004
+ 99_438 7:55:08 -00:14:26 9.399 -0.155 -0.719 -0.060 -0.082 -0.143 48 31 0.003 0.002 0.002 0.001 0.001 0.001
+ 99_447 7:55:21 -00:18:18 9.415 -0.071 -0.217 -0.031 -0.041 -0.074 22 11 0.002 0.002 0.005 0.001 0.001 0.001
+ 65079 7:56:19 03:00:09 7.832 -0.182 -0.786 -0.055 -0.075 -0.130 18 11 0.005 0.005 0.005 0.002 0.004 0.006
+ 72055 8:29:50 -07:06:14 8.113 -0.137 -0.460 -0.031 -0.056 -0.086 17 10 0.004 0.004 0.007 0.003 0.003 0.003
+ 100_241 8:51:49 -00:36:23 10.140 0.156 0.102 0.077 0.087 0.164 20 12 0.002 0.002 0.007 0.001 0.001 0.002
+ 100_606 8:52:12 -00:06:04 8.641 0.052 0.125 0.026 0.022 0.048 15 7 0.002 0.004 0.011 0.002 0.002 0.002
+ 100_162 8:52:29 -00:40:03 9.148 1.274 1.501 0.648 0.553 1.204 37 20 0.002 0.002 0.004 0.001 0.001 0.002
+ 100_280 8:52:50 -00:33:15 11.802 0.496 0.009 0.295 0.296 0.591 20 12 0.003 0.003 0.003 0.002 0.002 0.003
+ 76082 8:53:13 -00:33:20 8.409 1.118 1.090 0.585 0.516 1.101 15 9 0.003 0.006 0.006 0.002 0.001 0.002
+ 100_95 8:54:08 -00:54:40 8.915 0.814 0.391 0.453 0.431 0.884 15 8 0.002 0.002 0.006 0.002 0.002 0.002
+ 79097 9:11:07 -06:54:45 7.601 1.628 1.933 0.990 1.100 2.087 19 11 0.007 0.002 0.007 0.004 0.003 0.006 5
+ 84971 9:47:59 -02:38:29 8.636 -0.159 -0.770 -0.063 -0.089 -0.152 19 11 0.004 0.003 0.003 0.003 0.003 0.004
+ 101_389 9:53:34 -00:10:50 9.962 0.427 -0.001 0.256 0.248 0.503 16 10 0.001 0.002 0.002 0.002 0.002 0.002
+ 101_311 9:53:49 -00:20:01 8.233 0.265 0.003 0.159 0.164 0.322 19 11 0.002 0.002 0.005 0.002 0.002 0.002
+ 101_24 9:54:50 -01:03:10 7.997 1.108 1.037 0.575 0.515 1.091 16 9 0.004 0.004 0.004 0.002 0.002 0.003
+ 101_324 9:55:11 -00:18:56 9.743 1.157 1.149 0.591 0.520 1.111 20 13 0.003 0.003 0.003 0.001 0.000 0.002
+ 101_333 9:55:53 -00:23:22 7.835 1.485 1.787 0.795 0.728 1.524 19 11 0.004 0.003 0.006 0.003 0.002 0.003
+ 101_282 9:56:19 -00:25:42 10.002 0.429 0.010 0.260 0.260 0.520 17 9 0.003 0.003 0.003 0.003 0.003 0.002
+ 101_281 9:56:19 -00:27:20 11.579 0.814 0.435 0.455 0.410 0.866 21 12 0.002 0.002 0.005 0.001 0.001 0.002
+ 101_363 9:57:33 -00:21:16 9.871 0.262 0.121 0.145 0.151 0.296 19 13 0.002 0.002 0.006 0.001 0.001 0.002
+ +1_2447 10:28:14 00:58:09 9.652 1.509 1.238 1.044 1.226 2.266 19 9 0.003 0.006 0.013 0.004 0.002 0.004
+ G162_66 10:32:59 -11:37:02 13.015 -0.174 -0.982 -0.126 -0.136 -0.262 26 14 0.003 0.003 0.005 0.003 0.006 0.006
+ 102_276 10:52:26 -00:57:56 9.910 0.492 -0.024 0.291 0.285 0.575 18 10 0.001 0.001 0.003 0.001 0.004 0.003
+ 102_466 10:53:52 -00:50:40 9.246 1.056 0.921 0.563 0.506 1.069 16 10 0.002 0.002 0.003 0.002 0.002 0.002
+ 102_472 10:54:04 -00:50:15 8.754 1.014 0.819 0.528 0.483 1.011 16 7 0.004 0.002 0.004 0.002 0.002 0.002
+ 102_620 10:54:20 -00:43:31 10.067 1.087 1.013 0.642 0.523 1.167 18 11 0.002 0.002 0.003 0.002 0.002 0.002
+ 102_58 10:54:32 -01:20:38 9.380 0.060 0.021 0.044 0.015 0.060 35 18 0.002 0.003 0.006 0.001 0.001 0.001
+ 102_625 10:54:39 -00:43:57 8.890 0.552 0.035 0.312 0.308 0.621 16 8 0.005 0.002 0.003 0.002 0.002 0.003
+ 102_381 10:55:55 -01:05:18 7.916 0.309 0.095 0.173 0.173 0.346 16 7 0.004 0.001 0.005 0.002 0.002 0.003
+ 102_1081 10:56:19 -00:08:21 9.904 0.665 0.251 0.367 0.332 0.698 18 11 0.003 0.002 0.004 0.001 0.001 0.002
+ G163_50 11:07:14 -05:04:16 13.057 0.031 -0.676 -0.089 -0.072 -0.163 23 11 0.004 0.004 0.005 0.004 0.005 0.005
+ 97503 11:12:29 04:33:32 8.702 1.178 1.121 0.720 0.596 1.317 16 9 0.004 0.004 0.005 0.002 0.002 0.002
+ +5_2468 11:14:46 05:02:20 9.348 -0.116 -0.560 -0.038 -0.054 -0.092 17 10 0.005 0.003 0.004 0.002 0.002 0.002
+ 100340 11:32:03 05:21:40 10.117 -0.242 -0.975 -0.101 -0.137 -0.238 18 10 0.005 0.005 0.007 0.003 0.003 0.003
+ +5_2529 11:41:01 05:14:04 9.581 1.250 1.188 0.781 0.668 1.450 18 10 0.005 0.006 0.008 0.002 0.002 0.002
+ 103_462 11:53:13 -00:26:48 10.111 0.564 0.089 0.324 0.306 0.630 15 10 0.003 0.002 0.003 0.001 0.002 0.002
+ 103_483 11:54:15 -00:28:21 8.353 0.427 0.093 0.245 0.235 0.480 20 11 0.003 0.002 0.002 0.001 0.002 0.002
+ 103_302 11:55:20 -00:42:54 9.862 0.369 -0.058 0.230 0.237 0.467 32 20 0.002 0.002 0.002 0.001 0.003 0.003
+ 103_526 11:56:08 -00:25:13 10.903 1.089 0.941 0.563 0.509 1.073 17 11 0.003 0.004 0.004 0.001 0.001 0.001
+ 104_306 12:40:18 -00:32:15 9.361 1.583 1.662 0.833 0.763 1.588 44 28 0.010 0.005 0.007 0.003 0.005 0.004 4
+ 104_337 12:41:42 -00:29:21 11.207 0.768 0.336 0.434 0.399 0.832 22 14 0.002 0.002 0.004 0.001 0.002 0.002
+ 104_461 12:42:21 -00:27:26 9.706 0.478 -0.029 0.290 0.289 0.580 47 29 0.002 0.002 0.002 0.000 0.001 0.000
+ 104_598 12:44:31 -00:11:42 11.476 1.108 1.052 0.663 0.546 1.211 21 14 0.003 0.002 0.006 0.003 0.002 0.003
+ 118246 13:34:56 -06:04:55 8.089 -0.141 -0.636 -0.034 -0.047 -0.081 19 10 0.007 0.002 0.005 0.003 0.003 0.004 6
+ 105_205 13:35:07 -00:53:16 8.798 1.363 1.616 0.744 0.675 1.419 34 21 0.003 0.002 0.004 0.001 0.001 0.001
+ 105_405 13:35:14 -00:30:00 8.309 1.521 1.905 0.832 0.784 1.617 27 14 0.004 0.001 0.007 0.001 0.002 0.002
+ 105_214 13:35:30 -00:51:10 7.062 0.528 -0.010 0.313 0.311 0.624 17 8 0.003 0.002 0.004 0.002 0.002 0.003
+ 105_28 13:35:58 -01:11:04 8.345 1.039 0.870 0.533 0.485 1.018 19 10 0.003 0.003 0.004 0.002 0.002 0.002
+ 105_663 13:36:44 -00:08:41 8.760 0.342 0.033 0.211 0.217 0.429 18 10 0.005 0.002 0.003 0.002 0.002 0.002
+ 105_448 13:37:02 -00:32:57 9.176 0.249 0.037 0.149 0.162 0.311 20 13 0.002 0.001 0.004 0.001 0.000 0.002
+ 105_66 13:38:49 -01:08:53 9.426 0.977 0.756 0.522 0.481 1.003 31 19 0.002 0.002 0.003 0.001 0.000 0.001
+ 105_815 13:39:18 00:02:23 11.456 0.387 -0.232 0.270 0.294 0.563 18 12 0.002 0.004 0.004 0.001 0.002 0.002
+ +2_2711 13:41:35 01:34:48 10.367 -0.162 -0.708 -0.070 -0.094 -0.165 25 13 0.004 0.004 0.004 0.003 0.003 0.003
+ 121968 13:58:04 -02:50:54 10.256 -0.179 -0.935 -0.069 -0.095 -0.164 15 8 0.003 0.003 0.006 0.003 0.003 0.004
+ 106_834 14:38:43 -00:11:00 9.088 0.701 0.292 0.379 0.357 0.736 15 8 0.003 0.002 0.005 0.005 0.004 0.003
+ 106_1024 14:39:21 00:05:36 11.594 0.332 0.085 0.195 0.196 0.391 19 12 0.008 0.003 0.006 0.003 0.002 0.004 7
+ 106_700 14:40:06 -00:19:47 9.787 1.361 1.574 0.728 0.642 1.372 19 12 0.003 0.003 0.004 0.001 0.001 0.002
+ 106_1250 14:40:41 00:10:06 8.123 1.029 0.832 0.532 0.494 1.026 15 8 0.004 0.002 0.004 0.001 0.001 0.002
+ 106_575 14:40:53 -00:22:12 9.341 1.308 1.483 0.672 0.592 1.265 18 9 0.005 0.003 0.008 0.004 0.002 0.004
+ 106_485 14:43:28 -00:33:20 9.484 0.380 -0.039 0.232 0.232 0.463 19 10 0.005 0.002 0.005 0.002 0.002 0.003
+ 129975 14:44:51 -00:17:23 8.373 1.504 1.899 0.829 0.776 1.605 17 9 0.003 0.003 0.007 0.002 0.001 0.002
+ 107_544 15:36:03 -00:12:14 9.037 0.401 0.156 0.233 0.226 0.457 37 22 0.002 0.001 0.002 0.001 0.001 0.001
+ 107_684 15:36:31 -00:06:51 8.433 0.619 0.072 0.356 0.353 0.708 14 7 0.003 0.004 0.005 0.002 0.002 0.002
+ 107_970 15:36:40 00:21:30 10.910 1.604 1.788 1.144 1.426 2.567 20 11 0.012 0.003 0.012 0.004 0.007 0.006 4
+ 107_35 15:36:42 -00:50:10 7.779 1.275 1.309 0.663 0.585 1.249 14 9 0.003 0.003 0.004 0.003 0.002 0.002
+ 107_1006 15:37:48 00:17:16 11.715 0.764 0.285 0.440 0.420 0.861 16 10 0.002 0.002 0.004 0.002 0.002 0.002
+ 107_347 15:37:50 -00:33:01 9.443 1.296 1.299 0.713 0.653 1.367 17 10 0.003 0.001 0.002 0.001 0.001 0.002
+ 107_595 15:38:17 -00:15:40 7.500 0.543 0.051 0.312 0.297 0.608 16 9 0.003 0.003 0.005 0.002 0.002 0.002
+ 107_131 15:39:38 -00:51:49 8.073 1.118 0.948 0.598 0.548 1.147 12 6 0.002 0.002 0.003 0.002 0.000 0.001
+ 140850 15:45:11 -01:23:50 8.816 1.670 2.078 0.948 0.947 1.895 25 14 0.002 0.002 0.007 0.002 0.002 0.003
+ 148817 16:29:55 -00:06:49 8.341 1.485 1.805 0.804 0.737 1.542 24 12 0.005 0.002 0.005 0.001 0.002 0.002
+ 149382 16:33:36 -03:58:59 8.944 -0.281 -1.167 -0.126 -0.138 -0.264 16 8 0.002 0.005 0.011 0.002 0.003 0.002
+ 108_1332 16:34:35 -00:02:18 9.199 0.384 0.087 0.228 0.228 0.454 33 19 0.002 0.001 0.002 0.001 0.001 0.002
+ 108_702 16:35:12 -00:22:57 8.208 0.559 0.021 0.319 0.309 0.628 32 20 0.002 0.001 0.002 0.000 0.000 0.001
+ 108_475 16:36:14 -00:32:53 11.308 1.379 1.464 0.741 0.665 1.408 21 12 0.002 0.003 0.006 0.002 0.002 0.002
+ 108_1491 16:36:28 -00:00:54 9.059 0.965 0.620 0.524 0.498 1.022 38 24 0.001 0.001 0.002 0.001 0.001 0.001
+ 108_827 16:36:36 -00:22:54 7.964 1.303 1.413 0.682 0.589 1.269 21 11 0.000 0.001 0.000 0.000 0.002 0.001
+ 108_551 16:37:01 -00:31:19 10.705 0.175 0.180 0.097 0.109 0.204 51 31 0.002 0.001 0.005 0.001 0.002 0.003
+ 108_1911 16:37:01 00:04:33 8.050 0.758 0.390 0.417 0.366 0.784 13 7 0.001 0.002 0.006 0.002 0.002 0.002
+ 157881 17:25:05 02:10:12 7.540 1.356 1.276 0.854 0.768 1.622 20 11 0.005 0.007 0.002 0.002 0.002 0.002
+ 160233 17:37:56 04:21:19 9.095 -0.054 -0.846 -0.003 -0.023 -0.026 16 9 0.004 0.003 0.008 0.002 0.002 0.003
+ 109_71 17:43:20 -00:24:38 11.491 0.321 0.156 0.188 0.223 0.410 19 12 0.002 0.002 0.006 0.002 0.001 0.002
+ 109_381 17:43:26 -00:20:12 11.728 0.701 0.231 0.426 0.437 0.863 19 11 0.003 0.004 0.003 0.002 0.001 0.002
+ 109_747 17:44:05 -00:07:45 8.477 0.305 0.243 0.187 0.210 0.396 26 14 0.002 0.002 0.004 0.001 0.002 0.001
+ 109_231 17:44:34 -00:25:31 9.331 1.462 1.600 0.786 0.705 1.492 50 27 0.002 0.002 0.004 0.000 0.000 0.001
+ 109_1082 17:44:43 00:04:38 9.017 0.802 0.344 0.455 0.423 0.878 16 9 0.005 0.004 0.009 0.002 0.002 0.003
+ 109_537 17:44:56 -00:21:15 10.358 0.608 0.229 0.377 0.393 0.769 42 24 0.004 0.002 0.003 0.001 0.001 0.002
+ +4_3508 17:46:49 04:50:24 9.326 1.753 2.077 0.974 0.900 1.874 14 8 0.005 0.004 0.015 0.002 0.001 0.003
+ 161961 17:47:50 -02:11:27 7.782 0.224 -0.747 0.148 0.158 0.306 20 11 0.003 0.004 0.009 0.002 0.002 0.002
+ +4_3561 17:57:09 04:15:45 9.553 1.737 1.264 1.228 1.553 2.779 7 3 0.005 0.005 0.023 0.005 0.003 0.005
+ 170493 18:29:05 -01:49:38 8.037 1.076 1.068 0.634 0.509 1.145 14 8 0.002 0.003 0.004 0.002 0.001 0.001
+ 110_471 18:40:42 00:33:01 7.474 1.449 1.710 0.767 0.681 1.448 15 8 0.003 0.002 0.007 0.002 0.001 0.002
+ 110_340 18:40:43 00:14:28 10.023 0.301 0.123 0.169 0.180 0.349 35 22 0.002 0.001 0.004 0.001 0.002 0.002
+ 110_353 18:41:31 00:08:24 8.447 2.002 2.292 1.186 1.120 2.306 25 14 0.003 0.003 0.007 0.003 0.003 0.004
+ 110_441 18:42:48 00:18:44 11.124 0.553 0.111 0.325 0.337 0.663 17 10 0.003 0.004 0.004 0.002 0.002 0.003
+ 110_450 18:43:06 00:22:01 11.585 0.950 0.690 0.552 0.631 1.181 17 10 0.005 0.007 0.005 0.002 0.002 0.003
+ 173637 18:45:50 -07:56:56 9.375 0.236 -0.729 0.168 0.187 0.354 15 9 0.004 0.004 0.004 0.002 0.002 0.002
+ 175544 18:55:02 00:14:49 7.395 0.107 -0.671 0.074 0.077 0.151 19 11 0.002 0.003 0.008 0.002 0.002 0.002
+ 184914 19:35:58 -04:19:26 8.170 1.180 0.940 0.636 0.604 1.241 20 12 0.001 0.002 0.004 0.001 0.001 0.002
+ 111_717 19:36:09 00:05:29 8.529 0.425 0.224 0.236 0.247 0.483 15 8 0.003 0.003 0.005 0.002 0.002 0.002
+ 111_2522 19:36:19 00:35:31 9.706 0.164 -0.409 0.121 0.140 0.267 21 11 0.005 0.003 0.004 0.005 0.002 0.002
+ 111_773 19:36:30 00:08:56 8.963 0.206 -0.211 0.118 0.144 0.261 38 22 0.001 0.002 0.002 0.001 0.001 0.001
+ 111_775 19:36:30 00:10:02 10.747 1.738 2.042 0.965 0.897 1.864 20 11 0.003 0.004 0.017 0.002 0.001 0.002
+ 111_1969 19:36:58 00:23:44 10.384 1.961 2.304 1.181 1.223 2.405 20 11 0.004 0.003 0.010 0.003 0.002 0.003
+ 111_2009 19:37:09 00:24:24 10.608 0.889 0.513 0.509 0.460 0.969 13 7 0.004 0.004 0.007 0.003 0.002 0.003
+ 111_1496 19:37:36 00:18:39 7.216 0.278 0.113 0.154 0.166 0.319 13 7 0.001 0.002 0.006 0.001 0.002 0.002
+ 111_2864 19:38:02 00:34:16 8.292 1.716 2.017 0.933 0.853 1.786 20 11 0.003 0.003 0.009 0.002 0.002 0.002
+ 188934 19:56:52 00:11:51 9.351 2.040 2.102 0.942 0.787 1.731 20 10 0.013 0.021 0.031 0.003 0.002 0.003 4
+ 191639 20:10:22 -08:53:10 6.223 -0.087 -1.031 0.014 0.014 0.027 14 9 0.051 0.014 0.007 0.012 0.017 0.029 4,8
+ 196395 20:36:21 -00:33:12 8.711 1.662 2.059 0.933 0.926 1.859 18 11 0.002 0.002 0.005 0.002 0.002 0.003
+ 196573 20:37:31 00:57:40 7.885 1.641 2.043 0.931 0.955 1.884 10 6 0.005 0.003 0.003 0.003 0.002 0.003
+ 112_595 20:40:32 00:13:14 11.349 1.598 2.003 0.899 0.901 1.800 19 10 0.004 0.003 0.018 0.002 0.002 0.003
+ 112_636 20:40:49 00:13:18 9.853 0.688 0.132 0.402 0.396 0.799 14 8 0.005 0.003 0.008 0.004 0.003 0.004
+ 112_223 20:41:29 00:05:46 11.421 0.454 0.008 0.273 0.273 0.546 17 10 0.002 0.002 0.003 0.002 0.003 0.003
+ 112_1242 20:41:38 00:23:29 9.088 0.414 0.019 0.251 0.250 0.501 16 9 0.002 0.003 0.003 0.001 0.002 0.002
+ 112_275 20:41:50 00:04:05 9.905 1.206 1.298 0.647 0.570 1.217 38 23 0.002 0.002 0.004 0.001 0.001 0.001
+ 112_805 20:42:00 00:12:52 12.090 0.150 0.151 0.063 0.075 0.138 20 11 0.003 0.002 0.004 0.003 0.003 0.004
+ 112_822 20:42:09 00:11:48 11.550 1.031 0.871 0.558 0.505 1.064 18 10 0.002 0.004 0.007 0.001 0.002 0.002
+ 199280 20:55:31 -03:37:10 6.566 -0.076 -0.306 -0.034 -0.043 -0.078 12 7 0.002 0.002 0.003 0.001 0.001 0.001
+ 200340 21:02:14 -00:59:44 6.498 -0.099 -0.496 -0.037 -0.045 -0.083 10 6 0.003 0.002 0.002 0.002 0.002 0.002
+ 205556 21:35:11 05:25:11 8.301 -0.054 -0.395 -0.021 -0.032 -0.053 18 10 0.004 0.003 0.003 0.002 0.002 0.002
+ 113_442 21:39:54 00:40:37 9.650 1.163 1.251 0.605 0.517 1.123 12 7 0.003 0.003 0.006 0.003 0.003 0.003
+ 113_466 21:40:42 00:36:06 10.007 0.452 -0.001 0.282 0.282 0.565 32 19 0.002 0.001 0.002 0.001 0.001 0.002
+ 113_259 21:40:58 00:13:30 11.743 1.196 1.213 0.622 0.545 1.168 21 12 0.002 0.003 0.008 0.002 0.002 0.002
+ 113_475 21:41:05 00:35:11 10.306 1.057 0.841 0.569 0.526 1.096 21 12 0.002 0.002 0.004 0.001 0.002 0.002
+ 113_267 21:41:10 00:16:37 7.653 0.488 0.013 0.291 0.291 0.582 10 5 0.004 0.003 0.005 0.002 0.002 0.001
+ 113_269 21:41:15 00:13:35 9.482 1.112 1.054 0.572 0.520 1.092 10 5 0.003 0.003 0.012 0.003 0.003 0.003
+ 113_276 21:41:41 00:22:14 9.074 0.647 0.181 0.357 0.336 0.692 12 6 0.004 0.003 0.007 0.003 0.002 0.003
+ 113_274 21:41:41 00:22:38 8.831 0.480 0.004 0.284 0.271 0.555 13 7 0.003 0.003 0.003 0.002 0.003 0.003
+ G93_48 21:51:39 02:19:17 12.736 -0.008 -0.790 -0.099 -0.096 -0.194 27 14 0.003 0.004 0.003 0.003 0.006 0.006
+ 209796 22:05:16 01:18:36 8.933 1.187 1.173 0.621 0.557 1.178 19 11 0.003 0.002 0.006 0.002 0.002 0.002
+ 210894 22:12:50 -04:38:19 9.167 1.315 1.462 0.697 0.605 1.304 17 10 0.003 0.003 0.007 0.002 0.002 0.003
+ 114_531 22:39:51 00:47:14 12.094 0.732 0.170 0.422 0.405 0.827 18 10 0.001 0.003 0.005 0.001 0.002 0.002
+ 114_548 22:40:51 00:54:24 11.600 1.362 1.572 0.732 0.652 1.385 19 11 0.005 0.003 0.009 0.002 0.001 0.003
+ 114_750 22:40:59 01:07:54 11.913 -0.038 -0.357 0.030 -0.017 0.013 23 15 0.003 0.003 0.003 0.002 0.004 0.004
+ 114_755 22:41:22 01:12:06 10.908 0.571 -0.064 0.311 0.310 0.621 16 11 0.002 0.002 0.002 0.002 0.001 0.002
+ 114_670 22:41:24 01:05:34 11.106 1.203 1.220 0.645 0.578 1.224 13 8 0.001 0.002 0.006 0.002 0.002 0.002
+ 114_473 22:41:38 00:41:32 8.503 1.008 0.807 0.532 0.483 1.015 11 6 0.002 0.004 0.006 0.002 0.003 0.003
+ 114_172 22:42:03 00:09:10 6.969 0.311 0.105 0.187 0.189 0.376 15 9 0.003 0.002 0.006 0.001 0.002 0.002
+ 114_272 22:42:11 00:19:37 7.737 0.864 0.473 0.480 0.462 0.941 9 5 0.002 0.003 0.008 0.002 0.003 0.002
+ 114_176 22:42:24 00:16:32 9.242 1.490 1.854 0.804 0.719 1.524 40 26 0.002 0.002 0.004 0.000 0.000 0.001
+ 216135 22:49:41 -13:23:12 10.112 -0.115 -0.630 -0.052 -0.069 -0.121 16 9 0.003 0.002 0.003 0.002 0.003 0.002
+ GD_246 23:11:35 10:42:08 13.090 -0.317 -1.188 -0.149 -0.185 -0.333 31 16 0.003 0.004 0.003 0.004 0.007 0.008
+ F_108 23:15:24 -01:55:32 12.966 -0.231 -1.058 -0.104 -0.138 -0.241 30 16 0.004 0.003 0.003 0.002 0.007 0.007
+ 115_420 23:41:50 01:00:58 11.162 0.470 -0.033 0.287 0.295 0.581 16 10 0.002 0.002 0.003 0.002 0.002 0.002
+ 115_271 23:41:55 00:40:10 9.695 0.619 0.099 0.352 0.350 0.700 47 28 0.001 0.002 0.002 0.001 0.000 0.001
+ 115_427 23:42:28 01:01:46 8.857 1.168 1.140 0.618 0.551 1.169 15 8 0.003 0.003 0.008 0.002 0.002 0.002
+ 115_349 23:42:29 00:49:15 8.600 1.066 0.869 0.557 0.507 1.066 11 6 0.003 0.002 0.004 0.002 0.002 0.002
+ 115_516 23:43:29 01:09:13 10.433 1.030 0.759 0.563 0.535 1.099 20 12 0.002 0.002 0.002 0.001 0.001 0.002
+ +1_4774 23:48:16 02:20:39 9.003 1.434 1.128 0.971 1.075 2.043 14 9 0.002 0.007 0.018 0.002 0.001 0.002
diff --git a/noao/digiphot/photcal/catalogs/nicmos.dat b/noao/digiphot/photcal/catalogs/nicmos.dat
new file mode 100644
index 00000000..bc8bca10
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/nicmos.dat
@@ -0,0 +1,94 @@
+# Declare the NICMOS JHKKs standards catalog variables
+
+ 9101 11.622 0.005 11.298 0.005 11.223 0.008 11.223 0.005 P525-E
+ 9103 10.932 0.006 10.657 0.004 10.596 0.005 10.594 0.004 S294-D
+ 9104 11.045 0.005 10.750 0.005 10.693 0.010 10.695 0.005 S754-C
+ 9105 11.309 0.010 10.975 0.006 10.897 0.006 10.910 0.005 P530-D
+ 9106 12.153 0.007 11.842 0.005 11.772 0.010 11.788 0.006 S301-D
+ 9107 11.934 0.005 11.610 0.004 11.492 0.011 11.503 0.005 P247-U
+ 9108 11.737 0.009 11.431 0.006 11.337 0.008 11.336 0.005 P533-D
+ 9109 11.552 0.002 11.326 0.002 11.255 0.027 11.269 0.002 S055-D
+ 9111 11.246 0.006 11.031 0.006 10.992 0.033 10.980 0.006 S361-D
+ 9113 11.059 0.005 10.766 0.005 10.708 0.034 10.713 0.005 S252-D
+ 9115 12.069 0.007 11.874 0.005 11.826 0.007 11.831 0.005 S363-D
+ 9116 11.426 0.009 11.148 0.009 11.077 0.014 11.058 0.008 S840-F
+ 9118 11.723 0.011 11.357 0.009 11.264 0.016 11.261 0.010 S842-E
+ 9119 12.114 0.006 11.838 0.005 11.765 0.009 11.781 0.005 S121-E
+ 9121 11.719 0.004 11.434 0.004 0.000 0.099 11.372 0.004 S255-S
+ 9122 11.680 0.006 11.408 0.006 11.356 0.013 11.352 0.006 P161-D
+ 9123 10.833 0.007 10.499 0.007 10.431 0.015 10.442 0.009 S427-D
+ 9125 10.885 0.007 10.598 0.006 10.514 0.013 10.522 0.008 S005-D
+ 9126 11.876 0.013 11.522 0.014 0.000 0.099 11.450 0.022 P309-U
+ 9129 10.914 0.007 10.585 0.006 10.487 0.021 10.496 0.009 S209-D
+ 9131 10.819 0.008 10.546 0.007 10.499 0.010 10.515 0.008 P035-R
+ 9132 11.949 0.006 11.669 0.005 11.608 0.004 11.609 0.004 S312-T
+ 9133 11.521 0.007 11.048 0.008 10.965 0.016 10.960 0.010 S495-E
+ 9134 11.881 0.007 11.624 0.005 11.575 0.005 11.596 0.006 P545-C
+ 9135 12.362 0.010 12.098 0.011 0.000 0.099 12.040 0.014 S705-D
+ 9136 12.489 0.008 12.214 0.008 12.138 0.018 12.142 0.011 S165-E
+ 9137 11.153 0.007 10.891 0.007 10.830 0.019 10.836 0.010 S372-S
+ 9138 11.354 0.006 11.041 0.006 10.981 0.015 10.982 0.008 S852-C
+ 9139 11.683 0.008 11.338 0.007 11.276 0.011 11.282 0.010 P091-D
+ 9140 11.409 0.011 11.085 0.008 0.000 0.099 11.022 0.012 S262-E
+ 9141 11.081 0.008 10.775 0.008 10.715 0.035 10.718 0.010 S708-D
+ 9142 11.993 0.006 11.729 0.005 11.686 0.009 11.697 0.007 P212-C
+ 9143 12.344 0.007 12.121 0.005 12.067 0.006 12.081 0.005 P550-C
+ 9144 11.642 0.009 11.335 0.008 11.263 0.018 11.280 0.010 S264-D
+ 9145 11.958 0.009 11.711 0.008 11.664 0.011 11.675 0.009 P064-D
+ 9146 11.323 0.007 11.002 0.005 10.931 0.003 10.936 0.004 S217-D
+ 9147 12.111 0.007 11.803 0.007 11.722 0.013 11.724 0.007 S064-F
+ 9148 11.642 0.009 11.378 0.008 11.324 0.011 11.343 0.008 P266-C
+ 9149 12.213 0.007 11.917 0.006 11.861 0.005 11.865 0.005 S860-D
+ 9150 11.661 0.008 11.310 0.007 11.250 0.014 11.267 0.008 S791-C
+ 9152 11.149 0.009 10.878 0.007 10.831 0.011 10.839 0.010 P133-C
+ 9153 11.947 0.008 11.605 0.008 11.560 0.013 11.540 0.008 P499-E
+ 9154 11.232 0.007 10.990 0.007 10.904 0.009 10.915 0.008 S008-D
+ 9155 12.045 0.008 11.701 0.005 11.622 0.005 11.633 0.005 S867-V
+ 9156 10.873 0.008 10.588 0.006 10.523 0.009 10.530 0.007 P041-C
+ 9157 11.341 0.007 10.924 0.005 10.851 0.004 10.849 0.004 S273-E
+ 9158 11.640 0.008 11.277 0.006 11.210 0.008 11.223 0.007 P272-D
+ 9160 10.914 0.008 10.701 0.008 10.649 0.010 10.659 0.009 S870-T
+ 9162 12.258 0.012 11.924 0.008 11.857 0.013 11.868 0.012 P177-D
+ 9164 12.180 0.007 11.895 0.006 11.842 0.007 11.844 0.006 P565-C
+ 9166 11.816 0.007 11.479 0.005 11.419 0.007 11.429 0.006 P330-E
+ 9169 11.355 0.007 11.118 0.005 11.075 0.008 11.080 0.007 P138-C
+ 9170 11.132 0.005 10.835 0.005 10.739 0.006 10.744 0.005 S875-C
+ 9172 12.477 0.009 12.118 0.006 12.026 0.006 12.031 0.006 S279-F
+ 9173 11.039 0.007 10.778 0.007 10.693 0.009 10.711 0.008 S024-D
+ 9175 12.252 0.006 11.916 0.007 11.834 0.011 11.839 0.007 S071-D
+ 9177 12.104 0.005 11.764 0.004 11.688 0.006 11.696 0.005 P182-E
+ 9178 10.966 0.007 10.658 0.008 10.566 0.014 10.575 0.008 S808-C
+ 9181 12.464 0.011 12.127 0.008 12.095 0.007 12.070 0.007 S234-E
+ 9182 11.479 0.005 11.142 0.005 11.082 0.010 11.085 0.005 S813-D
+ 9183 12.247 0.004 11.940 0.004 11.873 0.007 11.880 0.005 P576-F
+ 9185 12.021 0.005 11.662 0.004 11.586 0.012 11.585 0.005 S889-E
+ 9186 11.403 0.009 11.120 0.006 11.045 0.006 11.055 0.006 S893-D
+ 9187 11.857 0.003 11.596 0.003 11.538 0.009 11.542 0.003 S677-D
+ 9188 11.634 0.005 11.337 0.004 11.257 0.008 11.262 0.006 P290-D
+ BRI0021 11.835 0.008 11.086 0.007 10.552 0.010 10.561 0.008 Red
+ T832-38078 11.833 0.010 11.248 0.008 10.890 0.013 10.913 0.008 Red
+ LHS191 11.621 0.013 11.058 0.012 10.667 0.020 10.717 0.016 Red
+ IRAS537W 12.974 0.009 11.032 0.009 9.981 0.013 10.013 0.011 Red
+ IRAS537S 13.855 0.012 12.087 0.009 10.972 0.014 11.035 0.012 Red
+ LHS2026 12.066 0.006 11.497 0.005 11.129 0.007 11.156 0.008 Red
+ LHS2397a 11.897 0.008 11.190 0.007 10.691 0.008 10.709 0.010 Red
+ cskd-8 11.741 0.010 9.913 0.010 9.151 0.011 9.137 0.013 Red
+ cskd-9 11.372 0.010 9.788 0.010 9.161 0.011 9.154 0.013 Red
+ cskd-12 11.585 0.007 9.506 0.005 8.617 0.007 8.608 0.007 Red
+ cskd-15a 10.879 0.010 9.286 0.007 8.625 0.010 8.617 0.011 Red
+ cske-23 10.624 0.008 8.762 0.006 7.917 0.008 7.889 0.008 Red
+ cskd-16 11.986 0.011 9.982 0.008 9.137 0.011 9.124 0.010 Red
+ cskd-18 9.365 0.010 9.058 0.008 8.999 0.011 8.992 0.010 Red
+ cskd-20 9.903 0.011 8.590 0.008 8.089 0.011 8.077 0.010 Red
+ cskd-21 10.382 0.006 9.918 0.006 9.647 0.007 9.658 0.007 Red
+ cskd-34 12.494 0.015 10.537 0.014 9.677 0.016 9.668 0.019 Red
+ cskd-37 12.489 0.015 10.415 0.014 9.528 0.016 9.513 0.019 Red
+ cskf-12 9.671 0.008 8.858 0.007 8.561 0.009 8.561 0.008 Red
+ cskf-13a 10.631 0.010 9.861 0.009 9.486 0.011 9.506 0.011 Red
+ cskf-14a 10.095 0.008 8.851 0.007 8.387 0.009 8.361 0.008 Red
+ T868-53850 11.589 0.008 10.993 0.008 10.633 0.009 10.657 0.012 Red
+ T868-110639 12.612 0.009 11.865 0.010 11.336 0.009 11.353 0.011 Red
+ L134 11.408 0.009 9.627 0.010 8.875 0.011 8.898 0.013 Red
+ OphN9 17.549 0.022 12.389 0.011 9.527 0.014 9.620 0.018 Red
+ L547 11.872 0.010 9.831 0.011 8.888 0.014 8.870 0.016 Red
+ BRI2202 11.652 0.010 11.083 0.009 10.721 0.013 10.736 0.011 Red
diff --git a/noao/digiphot/photcal/catalogs/nlandolt.dat b/noao/digiphot/photcal/catalogs/nlandolt.dat
new file mode 100644
index 00000000..e81c9335
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/nlandolt.dat
@@ -0,0 +1,526 @@
+ TPHE_A 00:30:09 -46:31:22 14.651 0.793 0.380 0.435 0.405 0.841 29 12 0.0028 0.0046 0.0071 0.0019 0.0035 0.0032
+ TPHE_B 00:30:16 -46:27:55 12.334 0.405 0.156 0.262 0.271 0.535 29 17 0.0115 0.0026 0.0039 0.0020 0.0019 0.0035
+ TPHE_C 00:30:17 -46:32:34 14.376 -0.298 -1.217 -0.148 -0.211 -0.360 39 23 0.0022 0.0024 0.0043 0.0038 0.0133 0.0149
+ TPHE_D 00:30:18 -46:31:11 13.118 1.551 1.871 0.849 0.810 1.663 37 23 0.0033 0.0030 0.0118 0.0015 0.0023 0.0030
+ TPHE_E 00:30:19 -46:24:36 11.630 0.443 -0.103 0.276 0.283 0.564 34 8 0.0017 0.0012 0.0024 0.0007 0.0015 0.0019
+ TPHE_F 00:30:50 -46:33:33 12.474 0.855 0.532 0.492 0.435 0.926 5 3 0.0004 0.0058 0.0161 0.0004 0.0040 0.0036
+ TPHE_G 00:31:05 -46:22:43 10.442 1.546 1.915 0.934 1.085 2.025 5 3 0.0004 0.0013 0.0036 0.0004 0.0009 0.0009
+ PG0029+024 00:31:50 +02:38:26 15.268 0.362 -0.184 0.251 0.337 0.593 5 2 0.0094 0.0174 0.0112 0.0161 0.0125 0.0067
+ PG0039+049 00:42:05 +05:09:44 12.877 -0.019 -0.871 0.067 0.097 0.164 4 3 0.0020 0.0030 0.0055 0.0035 0.0055 0.0045
+ 92_309 00:53:14 +00:46:02 13.842 0.513 -0.024 0.326 0.325 0.652 2 1 0.0035 0.0057 0.0028 0.0014 0.0035 0.0014
+ 92_235 00:53:16 +00:36:18 10.595 1.638 1.984 0.894 0.911 1.806 5 2 0.0058 0.0045 0.0098 0.0031 0.0045 0.0067
+ 92_322 00:53:47 +00:47:33 12.676 0.528 -0.002 0.302 0.305 0.608 2 1 0.0007 0.0049 0.0028 0.0014 0.0007 0.0007
+ 92_245 00:54:16 +00:39:51 13.818 1.418 1.189 0.929 0.907 1.836 21 8 0.0028 0.0079 0.0301 0.0024 0.0024 0.0028
+ 92_248 00:54:31 +00:40:15 15.346 1.128 1.289 0.690 0.553 1.245 4 2 0.0255 0.0160 0.0955 0.0215 0.0145 0.0175
+ 92_249 00:54:34 +00:41:05 14.325 0.699 0.240 0.399 0.370 0.770 17 8 0.0049 0.0085 0.0114 0.0046 0.0065 0.0073
+ 92_250 00:54:37 +00:38:56 13.178 0.814 0.480 0.446 0.394 0.840 20 9 0.0022 0.0034 0.0074 0.0022 0.0022 0.0029
+ 92_330 00:54:44 +00:43:26 15.073 0.568 -0.115 0.331 0.334 0.666 2 1 0.0141 0.0297 0.0163 0.0304 0.0000 0.0304
+ 92_252 00:54:48 +00:39:23 14.932 0.517 -0.140 0.326 0.332 0.666 41 18 0.0033 0.0055 0.0082 0.0047 0.0072 0.0068
+ 92_253 00:54:52 +00:40:20 14.085 1.131 0.955 0.719 0.616 1.337 39 17 0.0032 0.0062 0.0221 0.0027 0.0043 0.0050
+ 92_335 00:55:00 +00:44:13 12.523 0.672 0.208 0.380 0.338 0.719 2 1 0.0007 0.0028 0.0049 0.0000 0.0014 0.0014
+ 92_339 00:55:03 +00:44:11 15.579 0.449 -0.177 0.306 0.339 0.645 19 8 0.0087 0.0117 0.0126 0.0117 0.0197 0.0177
+ 92_342 00:55:10 +00:43:14 11.613 0.436 -0.042 0.266 0.270 0.538 48 34 0.0013 0.0012 0.0023 0.0013 0.0009 0.0016
+ 92_188 00:55:10 +00:23:12 14.751 1.050 0.751 0.679 0.573 1.254 14 6 0.0096 0.0187 0.0551 0.0051 0.0043 0.0088
+ 92_409 00:55:14 +00:56:07 10.627 1.138 1.136 0.734 0.625 1.361 5 3 0.0031 0.0027 0.0085 0.0022 0.0027 0.0018
+ 92_410 00:55:15 +01:01:49 14.984 0.398 -0.134 0.239 0.242 0.484 27 13 0.0058 0.0064 0.0083 0.0052 0.0102 0.0117
+ 92_412 00:55:16 +01:01:53 15.036 0.457 -0.152 0.285 0.304 0.589 27 13 0.0054 0.0077 0.0133 0.0069 0.0094 0.0106
+ 92_259 00:55:22 +00:40:30 14.997 0.642 0.108 0.370 0.452 0.821 3 1 0.0115 0.0219 0.0214 0.0191 0.0202 0.0150
+ 92_345 00:55:24 +00:51:07 15.216 0.745 0.121 0.465 0.476 0.941 2 1 0.0007 0.0014 0.0339 0.0057 0.0113 0.0057
+ 92_347 00:55:26 +00:50:49 15.752 0.543 -0.097 0.339 0.318 0.658 4 2 0.0255 0.0280 0.0355 0.0295 0.0755 0.0995
+ 92_260 00:55:29 +00:37:07 15.071 1.162 1.115 0.719 0.608 1.328 9 4 0.0090 0.0093 0.0477 0.0070 0.0057 0.0080
+ 92_348 00:55:30 +00:44:34 12.109 0.598 0.056 0.345 0.341 0.688 4 2 0.0010 0.0015 0.0035 0.0015 0.0005 0.0020
+ 92_417 00:55:32 +00:53:07 15.922 0.477 -0.185 0.351 0.305 0.657 6 3 0.0127 0.0188 0.0318 0.0151 0.0678 0.0625
+ 92_263 00:55:40 +00:36:18 11.782 1.048 0.843 0.563 0.522 1.087 52 35 0.0011 0.0014 0.0033 0.0010 0.0011 0.0015
+ 92_497 00:55:54 +01:11:42 13.642 0.729 0.257 0.404 0.378 0.783 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 92_498 00:55:57 +01:10:40 14.408 1.010 0.794 0.648 0.531 1.181 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 92_500 00:55:58 +01:10:24 15.841 1.003 0.211 0.738 0.599 1.338 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 92_425 00:55:59 +00:52:58 13.941 1.191 1.173 0.755 0.627 1.384 36 19 0.0038 0.0067 0.0115 0.0023 0.0027 0.0038
+ 92_501 00:56:00 +01:10:52 12.958 0.610 0.068 0.345 0.331 0.677 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 92_426 00:56:00 +00:52:53 14.466 0.729 0.184 0.412 0.396 0.809 8 4 0.0099 0.0131 0.0293 0.0078 0.0124 0.0120
+ 92_355 00:56:06 +00:50:47 14.965 1.164 1.201 0.759 0.645 1.406 15 7 0.0088 0.0124 0.0465 0.0070 0.0052 0.0090
+ 92_427 00:56:07 +01:00:18 14.953 0.809 0.352 0.462 2.922 3.275 2 1 0.0021 0.0085 0.0233 0.0014 0.0113 0.0092
+ 92_502 00:56:08 +01:04:24 11.812 0.486 -0.095 0.284 0.292 0.576 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 92_430 00:56:16 +00:53:16 14.440 0.567 -0.040 0.338 0.338 0.676 35 18 0.0041 0.0052 0.0081 0.0029 0.0049 0.0051
+ 92_276 00:56:27 +00:41:53 12.036 0.629 0.067 0.368 0.357 0.726 21 11 0.0039 0.0022 0.0039 0.0031 0.0031 0.0052
+ 92_282 00:56:47 +00:38:29 12.969 0.318 -0.038 0.201 0.221 0.422 27 15 0.0031 0.0023 0.0044 0.0017 0.0023 0.0033
+ 92_508 00:56:51 +01:09:35 11.679 0.529 -0.047 0.318 0.320 0.639 3 2 0.0035 0.0046 0.0029 0.0058 0.0029 0.0029
+ 92_507 00:56:51 +01:05:58 11.332 0.932 0.688 0.507 0.461 0.969 3 2 0.0006 0.0046 0.0006 0.0012 0.0006 0.0012
+ 92_364 00:56:53 +00:44:02 11.673 0.607 -0.037 0.356 0.357 0.714 4 2 0.0015 0.0015 0.0085 0.0045 0.0010 0.0055
+ 92_433 00:56:54 +01:00:43 11.667 0.655 0.110 0.367 0.348 0.716 3 2 0.0006 0.0035 0.0115 0.0029 0.0017 0.0023
+ 92_288 00:57:17 +00:36:46 11.630 0.855 0.472 0.489 0.441 0.931 48 33 0.0014 0.0014 0.0022 0.0012 0.0009 0.0013
+ F_11 01:04:22 +04:13:37 12.065 -0.240 -0.978 -0.120 -0.142 -0.261 63 47 0.0009 0.0011 0.0024 0.0011 0.0016 0.0021
+ F_16 01:54:08 -06:42:54 12.406 -0.012 0.009 -0.003 0.002 -0.001 45 32 0.0013 0.0013 0.0027 0.0015 0.0018 0.0021
+ 93_407 01:54:37 +00:53:49 11.971 0.852 0.564 0.487 0.421 0.908 5 3 0.0027 0.0031 0.0134 0.0031 0.0036 0.0027
+ 93_317 01:54:38 +00:43:00 11.546 0.488 -0.055 0.293 0.298 0.592 37 28 0.0007 0.0008 0.0018 0.0007 0.0008 0.0008
+ 93_333 01:55:05 +00:45:44 12.011 0.832 0.436 0.469 0.422 0.892 38 28 0.0015 0.0018 0.0026 0.0010 0.0011 0.0016
+ 93_424 01:55:26 +00:56:43 11.620 1.083 0.943 0.554 0.502 1.058 40 29 0.0009 0.0014 0.0041 0.0008 0.0008 0.0008
+ G3_33 02:00:09 +13:04:04 12.298 1.804 1.316 1.355 1.751 3.099 11 5 0.0030 0.0096 0.0145 0.0039 0.0045 0.0048
+PG0220+132B 02:23:34 +13:28:07 14.216 0.937 0.319 0.562 0.496 1.058 3 2 0.0081 0.0375 0.0583 0.0058 0.0127 0.0069
+ PG0220+132 02:23:38 +13:27:38 14.760 -0.132 -0.922 -0.050 -0.120 -0.170 5 3 0.0063 0.0112 0.0103 0.0098 0.0170 0.0264
+PG0220+132A 02:23:39 +13:27:33 15.771 0.783 -0.339 0.514 0.481 0.995 3 2 0.0150 0.0699 0.0537 0.0110 0.0589 0.0479
+ F_22 02:30:17 +05:15:51 12.799 -0.054 -0.806 -0.103 -0.105 -0.207 60 50 0.0014 0.0017 0.0030 0.0012 0.0028 0.0035
+PG0231+051E 02:33:28 +05:19:44 13.804 0.677 0.201 0.390 0.369 0.757 3 2 0.0046 0.0040 0.0075 0.0035 0.0017 0.0023
+PG0231+051D 02:33:33 +05:19:28 14.027 1.088 1.046 0.675 0.586 1.256 3 2 0.0029 0.0075 0.0312 0.0081 0.0064 0.0110
+PG0231+051A 02:33:40 +05:17:38 12.772 0.710 0.270 0.405 0.394 0.799 7 4 0.0008 0.0015 0.0030 0.0011 0.0030 0.0030
+PG0231+051C 02:33:41 +05:20:19 13.702 0.671 0.114 0.399 0.385 0.783 2 1 0.0014 0.0078 0.0148 0.0028 0.0064 0.0085
+ PG0231+051 02:33:41 +05:18:40 16.105 -0.329 -1.192 -0.162 -0.371 -0.534 7 4 0.0068 0.0083 0.0045 0.0276 0.1066 0.1221
+PG0231+051B 02:33:45 +05:17:30 14.735 1.448 1.342 0.954 0.998 1.951 7 4 0.0030 0.0072 0.0178 0.0034 0.0026 0.0057
+ F_24 02:35:08 +03:43:57 12.411 -0.203 -1.169 0.090 0.364 0.451 76 65 0.0016 0.0011 0.0030 0.0015 0.0015 0.0021
+ 94_171 02:53:38 +00:17:19 12.659 0.817 0.304 0.480 0.483 0.964 18 9 0.0028 0.0035 0.0045 0.0035 0.0019 0.0038
+ 94_296 02:55:20 +00:28:14 12.255 0.750 0.235 0.415 0.387 0.803 2 1 0.0021 0.0014 0.0014 0.0021 0.0021 0.0000
+ 94_394 02:56:14 +00:35:10 12.273 0.545 -0.047 0.344 0.330 0.676 2 1 0.0028 0.0014 0.0014 0.0007 0.0014 0.0007
+ 94_401 02:56:31 +00:40:05 14.293 0.638 0.098 0.389 0.369 0.759 2 1 0.0014 0.0028 0.0120 0.0064 0.0035 0.0099
+ 94_242 02:57:21 +00:18:38 11.728 0.301 0.107 0.178 0.184 0.362 60 53 0.0012 0.0010 0.0022 0.0013 0.0010 0.0017
+ 94_251 02:57:46 +00:16:02 11.204 1.219 1.281 0.659 0.587 1.247 52 45 0.0010 0.0011 0.0033 0.0008 0.0007 0.0011
+ 94_702 02:58:13 +01:10:53 11.594 1.418 1.621 0.756 0.673 1.430 64 56 0.0010 0.0014 0.0046 0.0009 0.0009 0.0011
+ GD_50 03:48:50 -00:58:33 14.063 -0.276 -1.191 -0.145 -0.180 -0.325 43 24 0.0032 0.0037 0.0056 0.0043 0.0076 0.0098
+ 95_15 03:52:40 -00:05:22 11.302 0.712 0.157 0.424 0.385 0.809 2 1 0.0007 0.0007 0.0035 0.0014 0.0014 0.0028
+ 95_301 03:52:41 +00:31:21 11.216 1.290 1.296 0.692 0.620 1.311 47 40 0.0015 0.0015 0.0048 0.0009 0.0007 0.0013
+ 95_16 03:52:41 -00:05:06 14.313 1.306 1.322 0.796 0.676 1.472 4 2 0.0120 0.0160 0.0310 0.0135 0.0060 0.0090
+ 95_302 03:52:42 +00:31:18 11.694 0.825 0.447 0.471 0.420 0.891 29 20 0.0020 0.0015 0.0056 0.0013 0.0011 0.0017
+ 95_96 03:52:54 +00:00:19 10.010 0.147 0.072 0.079 0.095 0.174 70 55 0.0016 0.0012 0.0032 0.0010 0.0011 0.0014
+ 95_97 03:52:57 -00:00:20 14.818 0.906 0.380 0.522 0.546 1.068 2 1 0.0007 0.0226 0.0212 0.0028 0.0191 0.0212
+ 95_98 03:53:00 +00:02:52 14.448 1.181 1.092 0.723 0.620 1.342 2 1 0.0007 0.0014 0.0177 0.0092 0.0071 0.0163
+ 95_100 03:53:01 +00:00:13 15.633 0.791 0.051 0.538 0.421 0.961 3 1 0.0283 0.0785 0.1132 0.0144 0.0572 0.0439
+ 95_101 03:53:04 +00:02:53 12.677 0.778 0.263 0.436 0.426 0.863 2 1 0.0028 0.0028 0.0099 0.0064 0.0064 0.0120
+ 95_102 03:53:07 +00:01:09 15.622 1.001 0.162 0.448 0.618 1.065 3 1 0.0335 0.0803 0.0612 0.0115 0.0508 0.0618
+ 95_252 03:53:11 +00:27:19 15.394 1.452 1.178 0.816 0.747 1.566 6 3 0.0065 0.0257 0.0433 0.0090 0.0086 0.0131
+ 95_190 03:53:13 +00:16:20 12.627 0.287 0.236 0.195 0.220 0.415 44 22 0.0020 0.0017 0.0039 0.0017 0.0015 0.0021
+ 95_193 03:53:20 +00:16:31 14.338 1.211 1.239 0.748 0.616 1.366 20 10 0.0049 0.0063 0.0255 0.0042 0.0034 0.0058
+ 95_105 03:53:21 -00:00:20 13.574 0.976 0.627 0.550 0.536 1.088 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 95_107 03:53:25 +00:02:18 16.275 1.324 1.115 0.947 0.962 1.907 2 1 0.0035 0.1068 0.1732 0.0438 0.0226 0.0212
+ 95_106 03:53:25 +00:01:22 15.137 1.251 0.369 0.394 0.508 0.903 2 1 0.0064 0.0615 0.0240 0.1520 0.0127 0.1407
+ 95_112 03:53:40 -00:01:13 15.502 0.662 0.077 0.605 0.620 1.227 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 95_41 03:53:41 -00:02:31 14.060 0.903 0.297 0.589 0.585 1.176 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 95_317 03:53:44 +00:29:50 13.449 1.320 1.120 0.768 0.708 1.476 24 11 0.0035 0.0067 0.0131 0.0033 0.0012 0.0035
+ 95_42 03:53:44 -00:04:33 15.606 -0.215 -1.111 -0.119 -0.180 -0.300 41 18 0.0058 0.0073 0.0064 0.0075 0.0269 0.0276
+ 95_263 03:53:47 +00:26:38 12.679 1.500 1.559 0.801 0.711 1.513 19 10 0.0030 0.0034 0.0094 0.0023 0.0011 0.0028
+ 95_115 03:53:48 -00:00:48 14.680 0.836 0.096 0.577 0.579 1.157 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 95_43 03:53:49 -00:03:01 10.803 0.510 -0.016 0.308 0.316 0.624 16 10 0.0022 0.0020 0.0027 0.0027 0.0018 0.0035
+ 95_271 03:54:17 +00:18:49 13.669 1.287 0.916 0.734 0.717 1.453 15 7 0.0057 0.0080 0.0127 0.0023 0.0023 0.0036
+ 95_328 03:54:19 +00:36:28 13.525 1.532 1.298 0.908 0.868 1.776 23 11 0.0029 0.0054 0.0186 0.0027 0.0015 0.0031
+ 95_329 03:54:24 +00:37:07 14.617 1.184 1.093 0.766 0.642 1.410 13 6 0.0047 0.0103 0.0311 0.0044 0.0094 0.0089
+ 95_330 03:54:31 +00:29:05 12.174 1.999 2.233 1.166 1.100 2.268 47 23 0.0025 0.0026 0.0137 0.0020 0.0016 0.0028
+ 95_275 03:54:44 +00:27:20 13.479 1.763 1.740 1.011 0.931 1.944 40 20 0.0028 0.0054 0.0201 0.0022 0.0016 0.0025
+ 95_276 03:54:46 +00:25:54 14.118 1.225 1.218 0.748 0.646 1.395 14 7 0.0061 0.0102 0.0216 0.0040 0.0032 0.0051
+ 95_60 03:54:49 -00:07:05 13.429 0.776 0.197 0.464 0.449 0.914 20 10 0.0031 0.0031 0.0060 0.0029 0.0025 0.0034
+ 95_218 03:54:50 +00:10:08 12.095 0.708 0.208 0.397 0.370 0.767 20 14 0.0034 0.0022 0.0034 0.0020 0.0020 0.0027
+ 95_132 03:54:51 +00:05:21 12.064 0.448 0.300 0.259 0.287 0.545 33 27 0.0023 0.0021 0.0057 0.0016 0.0017 0.0026
+ 95_62 03:55:00 -00:02:55 13.538 1.355 1.181 0.742 0.685 1.428 22 11 0.0030 0.0053 0.0136 0.0019 0.0019 0.0028
+ 95_137 03:55:04 +00:03:33 14.440 1.457 1.136 0.893 0.845 1.737 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 95_139 03:55:05 +00:03:13 12.196 0.923 0.677 0.562 0.476 1.039 3 2 0.0017 0.0046 0.0191 0.0023 0.0017 0.0035
+ 95_66 03:55:07 -00:09:31 12.892 0.715 0.167 0.426 0.438 0.864 2 1 0.0021 0.0071 0.0035 0.0007 0.0057 0.0049
+ 95_227 03:55:08 +00:14:35 15.779 0.771 0.034 0.515 0.552 1.067 14 7 0.0118 0.0289 0.0417 0.0115 0.0107 0.0150
+ 95_142 03:55:09 +00:01:19 12.927 0.588 0.097 0.371 0.375 0.745 22 11 0.0030 0.0030 0.0036 0.0019 0.0017 0.0028
+ 95_74 03:55:31 -00:09:13 11.531 1.126 0.686 0.600 0.567 1.165 39 34 0.0016 0.0013 0.0035 0.0013 0.0010 0.0013
+ 95_231 03:55:39 +00:10:43 14.216 0.452 0.297 0.270 0.290 0.560 26 13 0.0043 0.0045 0.0071 0.0045 0.0053 0.0076
+ 95_284 03:55:42 +00:26:34 13.669 1.398 1.073 0.818 0.766 1.586 20 9 0.0040 0.0078 0.0239 0.0027 0.0036 0.0049
+ 95_149 03:55:44 +00:07:05 10.938 1.593 1.564 0.874 0.811 1.685 17 11 0.0051 0.0039 0.0095 0.0024 0.0017 0.0029
+ 95_285 03:55:46 +00:23:40 15.561 0.937 0.703 0.607 0.602 1.210 2 1 0.0071 0.0255 0.0636 0.0071 0.0064 0.0134
+ 95_236 03:56:13 +00:08:43 11.491 0.736 0.162 0.420 0.411 0.831 35 31 0.0010 0.0014 0.0035 0.0012 0.0008 0.0015
+ 96_21 04:51:16 -00:14:51 12.182 0.490 -0.004 0.299 0.297 0.598 2 1 0.0028 0.0007 0.0028 0.0057 0.0014 0.0035
+ 96_36 04:51:43 -00:10:12 10.591 0.247 0.118 0.134 0.136 0.271 34 24 0.0014 0.0012 0.0034 0.0009 0.0009 0.0015
+ 96_737 04:52:35 +00:22:29 11.716 1.334 1.160 0.733 0.695 1.428 35 26 0.0020 0.0019 0.0052 0.0010 0.0009 0.0014
+ 96_409 04:52:58 +00:09:04 13.778 0.543 0.042 0.340 0.340 0.682 2 1 0.0106 0.0007 0.0240 0.0085 0.0049 0.0127
+ 96_83 04:52:59 -00:14:44 11.719 0.179 0.202 0.093 0.097 0.190 37 26 0.0013 0.0010 0.0046 0.0010 0.0013 0.0016
+ 96_235 04:53:19 -00:05:04 11.140 1.074 0.898 0.559 0.510 1.068 32 22 0.0014 0.0011 0.0028 0.0007 0.0009 0.0009
+ G97_42 05:28:01 +09:39:07 12.443 1.639 1.259 1.171 1.485 2.655 23 11 0.0017 0.0035 0.0186 0.0025 0.0031 0.0033
+ G102_22 05:42:05 +12:30:14 11.509 1.621 1.134 1.211 1.590 2.800 20 10 0.0013 0.0027 0.0074 0.0034 0.0031 0.0042
+ GD_71 05:52:28 +15:53:15 13.032 -0.249 -1.107 -0.137 -0.164 -0.302 86 73 0.0014 0.0013 0.0023 0.0014 0.0021 0.0026
+ 97_249 05:57:07 +00:01:12 11.733 0.648 0.100 0.369 0.353 0.723 69 62 0.0010 0.0008 0.0014 0.0006 0.0007 0.0010
+ 97_42 05:57:09 -00:11:13 12.448 1.626 1.208 1.160 1.485 2.641 2 1 0.0057 0.0156 0.0127 0.0071 0.0021 0.0057
+ 97_345 05:57:26 +00:20:26 11.608 1.655 1.680 0.928 0.844 1.771 23 14 0.0027 0.0040 0.0156 0.0021 0.0015 0.0029
+ 97_351 05:57:37 +00:13:42 9.781 0.202 0.096 0.124 0.141 0.264 102 83 0.0009 0.0008 0.0020 0.0007 0.0008 0.0010
+ 97_75 05:57:55 -00:09:29 11.483 1.872 2.100 1.047 0.952 1.999 20 12 0.0038 0.0047 0.0101 0.0029 0.0016 0.0038
+ 97_284 05:58:25 +00:05:12 10.788 1.363 1.087 0.774 0.725 1.500 77 68 0.0009 0.0010 0.0022 0.0007 0.0006 0.0010
+ 97_224 05:58:44 -00:05:13 14.085 0.910 0.341 0.553 0.547 1.102 2 1 0.0127 0.0177 0.0049 0.0120 0.0127 0.0000
+ 98_961 06:51:27 -00:15:37 13.089 1.283 1.003 0.701 0.662 1.362 2 1 0.0021 0.0007 0.0014 0.0021 0.0000 0.0021
+ 98_966 06:51:29 -00:16:27 14.001 0.469 0.357 0.283 0.331 0.613 2 1 0.0035 0.0014 0.0021 0.0014 0.0191 0.0205
+ 98_556 06:51:30 -00:24:52 14.137 0.338 0.126 0.196 0.243 0.437 6 3 0.0053 0.0053 0.0131 0.0057 0.0045 0.0090
+ 98_557 06:51:30 -00:25:07 14.780 1.397 1.072 0.755 0.741 1.494 2 1 0.0007 0.0544 0.0269 0.0092 0.0297 0.0198
+ 98_562 06:51:31 -00:18:59 12.185 0.522 -0.002 0.305 0.303 0.607 2 1 0.0028 0.0049 0.0035 0.0014 0.0014 0.0000
+ 98_563 06:51:32 -00:26:26 14.162 0.416 -0.190 0.294 0.317 0.610 10 5 0.0051 0.0085 0.0073 0.0044 0.0079 0.0082
+ 98_978 06:51:34 -00:11:28 10.572 0.609 0.094 0.349 0.322 0.671 46 38 0.0015 0.0009 0.0016 0.0007 0.0009 0.0012
+ 98_L1 06:51:39 -00:26:38 15.672 1.243 0.776 0.730 0.712 1.445 3 2 0.0075 0.0462 0.0976 0.0110 0.0254 0.0318
+ 98_L2 06:51:40 -00:21:11 15.859 1.340 1.497 0.754 0.572 1.327 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 98_581 06:51:40 -00:25:43 14.556 0.238 0.161 0.118 0.244 0.361 7 3 0.0246 0.0280 0.0200 0.0193 0.0197 0.0155
+ 98_580 06:51:40 -00:26:43 14.728 0.367 0.303 0.241 0.305 0.547 4 2 0.0255 0.0185 0.0185 0.0125 0.0460 0.0395
+ 98_L3 06:51:42 -00:15:18 14.614 1.936 1.837 1.091 1.047 2.142 4 2 0.0145 0.0265 0.1450 0.0090 0.0070 0.0110
+ 98_L4 06:51:42 -00:16:35 16.332 1.344 1.086 0.936 0.785 1.726 2 2 0.0580 0.0325 0.3429 0.0205 0.0368 0.0580
+ 98_1002 06:51:43 -00:15:53 14.568 0.574 -0.027 0.354 0.379 0.733 4 2 0.0055 0.0065 0.0110 0.0070 0.0125 0.0130
+ 98_590 06:51:43 -00:22:21 14.642 1.352 0.853 0.753 0.747 1.500 4 2 0.0110 0.0120 0.0525 0.0050 0.0105 0.0135
+ 98_614 06:51:49 -00:20:34 15.674 1.063 0.399 0.834 0.645 1.480 2 1 0.0424 0.0474 0.0311 0.0226 0.0368 0.0580
+ 98_618 06:51:50 -00:21:17 12.723 2.192 2.144 1.254 1.151 2.407 14 7 0.0051 0.0075 0.0307 0.0035 0.0032 0.0045
+ 98_624 06:51:52 -00:20:16 13.811 0.791 0.394 0.417 0.404 0.822 2 1 0.0141 0.0240 0.0042 0.0014 0.0212 0.0198
+ 98_626 06:51:53 -00:20:46 14.758 1.406 1.067 0.806 0.816 1.624 2 1 0.0071 0.0028 0.0438 0.0092 0.0205 0.0113
+ 98_627 06:51:53 -00:22:03 14.900 0.689 0.078 0.428 0.387 0.817 2 1 0.0064 0.0170 0.0085 0.0007 0.0127 0.0127
+ 98_634 06:51:56 -00:20:57 14.608 0.647 0.123 0.382 0.372 0.757 2 1 0.0042 0.0049 0.0127 0.0113 0.0177 0.0064
+ 98_642 06:51:59 -00:21:33 15.290 0.571 0.318 0.302 0.393 0.697 2 1 0.0191 0.0453 0.0120 0.0198 0.0021 0.0177
+ 98_185 06:52:02 -00:27:21 10.536 0.202 0.113 0.109 0.124 0.231 45 37 0.0018 0.0009 0.0033 0.0010 0.0013 0.0018
+ 98_646 06:52:03 -00:21:18 15.839 1.060 1.426 0.583 0.504 1.090 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 98_193 06:52:04 -00:27:18 10.030 1.180 1.152 0.615 0.537 1.153 44 35 0.0015 0.0008 0.0023 0.0011 0.0008 0.0015
+ 98_653 06:52:05 -00:18:19 9.539 -0.004 -0.099 0.009 0.008 0.017 65 50 0.0014 0.0004 0.0009 0.0007 0.0007 0.0011
+ 98_650 06:52:05 -00:19:40 12.271 0.157 0.110 0.080 0.086 0.166 31 20 0.0020 0.0014 0.0041 0.0016 0.0022 0.0027
+ 98_652 06:52:05 -00:21:58 14.817 0.611 0.126 0.276 0.339 0.618 2 1 0.0113 0.0297 0.0177 0.0453 0.0240 0.0226
+ 98_666 06:52:10 -00:23:34 12.732 0.164 -0.004 0.091 0.108 0.200 25 14 0.0034 0.0028 0.0042 0.0042 0.0030 0.0048
+ 98_671 06:52:12 -00:18:22 13.385 0.968 0.719 0.575 0.494 1.071 27 15 0.0037 0.0048 0.0108 0.0033 0.0035 0.0046
+ 98_670 06:52:12 -00:19:17 11.930 1.356 1.313 0.723 0.653 1.375 32 19 0.0016 0.0018 0.0058 0.0018 0.0012 0.0023
+ 98_676 06:52:14 -00:19:21 13.068 1.146 0.666 0.683 0.673 1.352 17 8 0.0032 0.0041 0.0107 0.0015 0.0218 0.0032
+ 98_675 06:52:14 -00:19:41 13.398 1.909 1.936 1.082 1.002 2.085 44 21 0.0026 0.0035 0.0283 0.0018 0.0018 0.0024
+ 98_L5 06:52:16 -00:19:39 17.800 1.900 -0.100 3.100 2.600 5.800 6 3 0.1633 0.3266 0.4491 0.1225 0.0408 0.1225
+ 98_682 06:52:17 -00:19:42 13.749 0.632 0.098 0.366 0.352 0.717 13 7 0.0039 0.0039 0.0064 0.0017 0.0025 0.0039
+ 98_685 06:52:19 -00:20:19 11.954 0.463 0.096 0.290 0.280 0.570 22 14 0.0030 0.0021 0.0028 0.0023 0.0021 0.0034
+ 98_688 06:52:19 -00:23:34 12.754 0.293 0.245 0.158 0.180 0.337 21 11 0.0033 0.0024 0.0081 0.0037 0.0050 0.0074
+ 98_1082 06:52:20 -00:14:15 15.010 0.835 -0.001 0.485 0.619 1.102 3 1 0.0058 0.0139 0.0225 0.0029 0.0133 0.0162
+ 98_1087 06:52:21 -00:15:50 14.439 1.595 1.284 0.928 0.882 1.812 12 5 0.0040 0.0141 0.0592 0.0035 0.0049 0.0072
+ 98_1102 06:52:28 -00:13:43 12.113 0.314 0.089 0.193 0.195 0.388 15 8 0.0034 0.0026 0.0059 0.0026 0.0036 0.0052
+ 98_1112 06:52:35 -00:15:23 13.975 0.814 0.286 0.443 0.431 0.874 5 2 0.0067 0.0040 0.0152 0.0054 0.0031 0.0076
+ 98_1119 06:52:37 -00:14:33 11.878 0.551 0.069 0.312 0.299 0.611 7 4 0.0023 0.0038 0.0042 0.0019 0.0042 0.0045
+ 98_1124 06:52:38 -00:16:34 13.707 0.315 0.258 0.173 0.201 0.373 24 12 0.0035 0.0043 0.0080 0.0029 0.0051 0.0057
+ 98_1122 06:52:38 -00:17:05 14.090 0.595 -0.297 0.376 0.442 0.816 25 12 0.0034 0.0060 0.0074 0.0038 0.0028 0.0046
+ 98_724 06:52:38 -00:19:22 11.118 1.104 0.904 0.575 0.527 1.103 12 7 0.0035 0.0035 0.0052 0.0023 0.0023 0.0038
+ 98_733 06:52:40 -00:17:16 12.238 1.285 1.087 0.698 0.650 1.347 20 10 0.0034 0.0042 0.0060 0.0029 0.0022 0.0040
+ RU_149G 07:24:12 -00:31:46 12.829 0.541 0.033 0.322 0.322 0.645 18 12 0.0026 0.0040 0.0042 0.0021 0.0026 0.0040
+ RU_149A 07:24:14 -00:32:44 14.495 0.298 0.118 0.196 0.196 0.391 18 12 0.0066 0.0052 0.0111 0.0099 0.0085 0.0139
+ RU_149F 07:24:15 -00:30:58 13.471 1.115 1.025 0.594 0.538 1.132 19 11 0.0028 0.0078 0.0223 0.0021 0.0023 0.0034
+ RU_149 07:24:15 -00:32:55 13.866 -0.129 -0.779 -0.040 -0.068 -0.108 46 30 0.0022 0.0027 0.0031 0.0022 0.0062 0.0069
+ RU_149D 07:24:16 -00:32:38 11.480 -0.037 -0.287 0.021 0.008 0.029 18 11 0.0019 0.0021 0.0028 0.0012 0.0019 0.0024
+ RU_149C 07:24:18 -00:32:17 14.425 0.195 0.141 0.093 0.127 0.222 18 11 0.0052 0.0042 0.0111 0.0061 0.0099 0.0106
+ RU_149B 07:24:18 -00:32:58 12.642 0.662 0.151 0.374 0.354 0.728 15 10 0.0021 0.0034 0.0049 0.0018 0.0026 0.0028
+ RU_149E 07:24:19 -00:31:08 13.718 0.522 -0.007 0.321 0.314 0.637 12 8 0.0064 0.0049 0.0069 0.0035 0.0066 0.0087
+ RU_152F 07:29:51 -02:04:29 14.564 0.635 0.069 0.382 0.315 0.689 15 8 0.0052 0.0057 0.0096 0.0067 0.0176 0.0222
+ RU_152E 07:29:51 -02:05:09 12.362 0.042 -0.086 0.030 0.034 0.065 12 8 0.0014 0.0020 0.0020 0.0014 0.0023 0.0029
+ RU_152 07:29:55 -02:06:18 13.014 -0.190 -1.073 -0.057 -0.087 -0.145 40 25 0.0019 0.0024 0.0032 0.0024 0.0030 0.0038
+ RU_152B 07:29:56 -02:05:39 15.019 0.500 0.022 0.290 0.309 0.600 23 10 0.0046 0.0088 0.0181 0.0054 0.0175 0.0211
+ RU_152A 07:29:57 -02:06:02 14.341 0.543 -0.085 0.325 0.329 0.654 14 8 0.0061 0.0086 0.0168 0.0051 0.0094 0.0131
+ RU_152C 07:29:59 -02:05:18 12.222 0.573 -0.013 0.342 0.340 0.683 13 9 0.0025 0.0031 0.0033 0.0022 0.0019 0.0031
+ RU_152D 07:30:03 -02:04:16 11.076 0.875 0.491 0.473 0.449 0.921 14 10 0.0013 0.0016 0.0024 0.0011 0.0019 0.0019
+ 99_438 07:55:54 -00:16:51 9.398 -0.155 -0.725 -0.059 -0.081 -0.141 105 87 0.0014 0.0007 0.0014 0.0007 0.0007 0.0009
+ 99_447 07:56:07 -00:20:43 9.417 -0.067 -0.225 -0.032 -0.041 -0.074 70 59 0.0008 0.0008 0.0014 0.0008 0.0008 0.0011
+ 100_241 08:52:35 -00:39:48 10.139 0.157 0.101 0.078 0.085 0.163 53 43 0.0011 0.0007 0.0016 0.0005 0.0005 0.0008
+ 100_162 08:53:15 -00:43:29 9.150 1.276 1.497 0.649 0.553 1.203 72 53 0.0012 0.0011 0.0026 0.0006 0.0007 0.0009
+ 100_267 08:53:18 -00:41:31 13.027 0.485 -0.062 0.307 0.302 0.608 3 3 0.0069 0.0023 0.0133 0.0075 0.0040 0.0040
+ 100_269 08:53:19 -00:41:10 12.350 0.547 -0.040 0.335 0.331 0.666 3 3 0.0035 0.0029 0.0150 0.0035 0.0029 0.0017
+ 100_280 08:53:36 -00:36:41 11.799 0.494 -0.002 0.295 0.291 0.588 58 47 0.0008 0.0009 0.0014 0.0008 0.0008 0.0012
+ 100_394 08:53:55 -00:32:21 11.384 1.317 1.457 0.705 0.636 1.341 9 5 0.0080 0.0040 0.0087 0.0023 0.0027 0.0030
+PG0918+029D 09:21:22 +02:47:30 12.272 1.044 0.821 0.575 0.535 1.108 19 11 0.0021 0.0030 0.0071 0.0016 0.0018 0.0018
+ PG0918+029 09:21:28 +02:46:03 13.327 -0.271 -1.081 -0.129 -0.159 -0.288 45 27 0.0024 0.0024 0.0030 0.0019 0.0055 0.0063
+PG0918+029B 09:21:34 +02:48:01 13.963 0.765 0.366 0.417 0.370 0.787 20 11 0.0034 0.0072 0.0159 0.0025 0.0045 0.0056
+PG0918+029A 09:21:35 +02:46:20 14.490 0.536 -0.032 0.325 0.336 0.661 29 14 0.0033 0.0058 0.0095 0.0039 0.0076 0.0085
+PG0918+029C 09:21:42 +02:46:38 13.537 0.631 0.087 0.367 0.357 0.722 21 10 0.0020 0.0028 0.0048 0.0015 0.0022 0.0028
+ -12_2918 09:31:18 -13:29:20 10.067 1.501 1.166 1.067 1.318 2.385 13 9 0.0025 0.0028 0.0075 0.0039 0.0022 0.0042
+PG0942-029D 09:45:10 -03:05:53 13.707 0.564 0.129 0.348 0.343 0.687 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+PG0942-029A 09:45:10 -03:10:17 14.731 0.783 0.339 0.610 0.477 1.081 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+PG0942-029B 09:45:12 -03:06:57 14.108 0.525 0.085 0.368 0.333 0.697 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ PG0942-029 09:45:12 -03:09:24 14.004 -0.294 -1.175 -0.130 -0.149 -0.280 14 7 0.0045 0.0056 0.0069 0.0069 0.0120 0.0144
+PG0942-029C 09:45:15 -03:06:39 14.989 0.727 0.369 0.539 0.376 0.909 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 101_315 09:54:51 -00:27:28 11.249 1.153 1.056 0.612 0.559 1.172 19 11 0.0037 0.0018 0.0067 0.0016 0.0011 0.0021
+ 101_316 09:54:52 -00:18:32 11.552 0.493 0.032 0.293 0.291 0.584 17 10 0.0027 0.0024 0.0036 0.0019 0.0029 0.0032
+ 101_L1 09:55:29 -00:21:37 16.501 0.757 -0.104 0.421 0.527 0.947 4 1 0.0310 0.0340 0.0290 0.0225 0.0855 0.1070
+ 101_320 09:55:33 -00:22:31 13.823 1.052 0.690 0.581 0.561 1.141 11 7 0.0048 0.0103 0.0181 0.0039 0.0036 0.0045
+ 101_L2 09:55:35 -00:18:48 15.770 0.602 0.082 0.321 0.304 0.625 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 101_404 09:55:41 -00:18:21 13.459 0.996 0.697 0.530 0.500 1.029 12 7 0.0040 0.0078 0.0095 0.0049 0.0032 0.0055
+ 101_324 09:55:57 -00:23:14 9.742 1.161 1.148 0.591 0.519 1.110 56 43 0.0015 0.0009 0.0020 0.0007 0.0007 0.0011
+ 101_262 09:56:08 -00:29:48 14.295 0.784 0.297 0.440 0.387 0.827 4 2 0.0045 0.0160 0.0205 0.0075 0.0100 0.0035
+ 101_408 09:56:08 -00:12:40 14.785 1.200 1.347 0.718 0.603 1.321 2 1 0.0240 0.0438 0.0170 0.0170 0.0120 0.0297
+ 101_326 09:56:08 -00:27:08 14.923 0.729 0.227 0.406 0.375 0.780 13 6 0.0078 0.0094 0.0128 0.0055 0.0111 0.0122
+ 101_410 09:56:09 -00:14:02 13.646 0.546 -0.063 0.298 0.326 0.623 2 1 0.0085 0.0014 0.0021 0.0106 0.0035 0.0064
+ 101_327 09:56:09 -00:25:50 13.441 1.155 1.139 0.717 0.574 1.290 28 15 0.0032 0.0057 0.0098 0.0023 0.0017 0.0028
+ 101_413 09:56:14 -00:11:56 12.583 0.983 0.716 0.529 0.497 1.025 9 6 0.0023 0.0047 0.0103 0.0033 0.0040 0.0040
+ 101_268 09:56:19 -00:31:55 14.380 1.531 1.381 1.040 1.200 2.237 11 5 0.0078 0.0199 0.0769 0.0048 0.0036 0.0045
+ 101_330 09:56:21 -00:27:19 13.723 0.577 -0.026 0.346 0.338 0.684 28 14 0.0038 0.0038 0.0051 0.0028 0.0057 0.0064
+ 101_415 09:56:23 -00:16:52 15.259 0.577 -0.008 0.346 0.350 0.695 2 1 0.0028 0.0247 0.0021 0.0198 0.0134 0.0332
+ 101_270 09:56:27 -00:35:43 13.711 0.554 0.055 0.332 0.306 0.637 2 1 0.0000 0.0014 0.0127 0.0049 0.0071 0.0014
+ 101_278 09:56:55 -00:29:38 15.494 1.041 0.737 0.596 0.548 1.144 2 1 0.0184 0.0226 0.0269 0.0198 0.0148 0.0346
+ 101_L3 09:56:55 -00:30:27 15.953 0.637 -0.033 0.396 0.395 0.792 2 1 0.0233 0.0184 0.0707 0.0382 0.0488 0.0870
+ 101_281 09:57:05 -00:31:38 11.575 0.812 0.419 0.452 0.412 0.864 19 11 0.0037 0.0018 0.0048 0.0023 0.0011 0.0025
+ 101_L4 09:57:08 -00:31:28 16.264 0.793 0.362 0.578 0.062 0.644 2 1 0.0170 0.0141 0.0014 0.0191 0.2638 0.2807
+ 101_L5 09:57:11 -00:31:37 15.928 0.622 0.115 0.414 0.305 0.720 2 1 0.0106 0.0283 0.0863 0.0078 0.0134 0.0212
+ 101_421 09:57:16 -00:17:16 13.180 0.507 -0.031 0.327 0.296 0.623 2 1 0.0021 0.0021 0.0035 0.0021 0.0007 0.0014
+ 101_338 09:57:18 -00:20:59 13.788 0.634 0.024 0.350 0.340 0.691 2 1 0.0071 0.0071 0.0042 0.0021 0.0035 0.0014
+ 101_339 09:57:18 -00:25:00 14.449 0.850 0.501 0.458 0.398 0.857 2 1 0.0099 0.0085 0.0099 0.0240 0.0042 0.0290
+ 101_424 09:57:20 -00:16:26 15.058 0.764 0.273 0.429 0.425 0.855 2 1 0.0276 0.0389 0.0191 0.0226 0.0205 0.0431
+ 101_427 09:57:26 -00:17:16 14.964 0.805 0.321 0.484 0.369 0.854 2 1 0.0269 0.0297 0.0014 0.0247 0.0113 0.0368
+ 101_341 09:57:30 -00:21:52 14.342 0.575 0.059 0.332 0.309 0.641 2 1 0.0113 0.0141 0.0071 0.0007 0.0078 0.0071
+ 101_342 09:57:31 -00:21:49 15.556 0.529 -0.065 0.339 0.419 0.758 2 1 0.0141 0.0085 0.0085 0.0240 0.0021 0.0226
+ 101_343 09:57:31 -00:22:54 15.504 0.606 0.094 0.396 0.338 0.734 2 1 0.0276 0.0488 0.0177 0.0226 0.0255 0.0481
+ 101_429 09:57:32 -00:18:17 13.496 0.980 0.782 0.617 0.526 1.143 23 13 0.0039 0.0019 0.0060 0.0017 0.0020 0.0030
+ 101_431 09:57:37 -00:17:51 13.684 1.246 1.144 0.808 0.708 1.517 23 13 0.0056 0.0063 0.0102 0.0033 0.0029 0.0042
+ 101_L6 09:57:39 -00:17:52 16.497 0.711 0.183 0.445 0.583 1.024 2 1 0.0219 0.0092 0.0311 0.0113 0.1648 0.1732
+ 101_207 09:57:53 -00:47:35 12.419 0.515 -0.078 0.321 0.320 0.641 22 14 0.0028 0.0038 0.0062 0.0017 0.0019 0.0023
+ 101_363 09:58:19 -00:25:23 9.874 0.261 0.129 0.146 0.151 0.297 53 44 0.0012 0.0008 0.0025 0.0008 0.0008 0.0011
+ GD_108 10:00:47 -07:33:31 13.561 -0.215 -0.942 -0.098 -0.122 -0.220 21 12 0.0028 0.0041 0.0039 0.0041 0.0050 0.0055
+ G162_66 10:33:43 -11:40:39 13.012 -0.165 -0.996 -0.126 -0.141 -0.266 80 64 0.0015 0.0013 0.0022 0.0010 0.0020 0.0025
+ G44_27 10:36:02 +05:07:11 12.636 1.586 1.088 1.185 1.526 2.714 8 4 0.0120 0.0106 0.0106 0.0046 0.0039 0.0032
+ PG1034+001 10:37:04 -00:08:20 13.228 -0.365 -1.274 -0.155 -0.203 -0.359 33 16 0.0024 0.0024 0.0033 0.0026 0.0042 0.0054
+ G163_6 10:42:55 +02:47:22 14.706 1.550 1.228 1.090 1.384 2.478 4 3 0.0070 0.0115 0.0655 0.0090 0.0015 0.0085
+ PG1047+003 10:50:03 -00:00:32 13.474 -0.290 -1.121 -0.132 -0.162 -0.295 32 18 0.0039 0.0030 0.0041 0.0037 0.0088 0.0110
+PG1047+003A 10:50:06 -00:01:08 13.512 0.688 0.168 0.422 0.418 0.840 15 7 0.0046 0.0049 0.0067 0.0026 0.0026 0.0036
+PG1047+003B 10:50:09 -00:02:00 14.751 0.679 0.172 0.391 0.371 0.764 13 5 0.0050 0.0086 0.0128 0.0022 0.0080 0.0086
+PG1047+003C 10:50:18 -00:00:23 12.453 0.607 -0.019 0.378 0.358 0.737 11 6 0.0093 0.0024 0.0060 0.0036 0.0033 0.0045
+ G44_40 10:50:54 +06:48:57 11.675 1.644 1.213 1.216 1.568 2.786 13 6 0.0033 0.0031 0.0092 0.0031 0.0017 0.0039
+ 102_620 10:55:06 -00:48:19 10.069 1.083 1.020 0.642 0.524 1.167 54 45 0.0010 0.0010 0.0018 0.0011 0.0008 0.0012
+ G45_20 10:56:38 +07:02:23 13.507 2.034 1.165 1.823 2.174 4.000 19 10 0.0060 0.0069 0.0346 0.0073 0.0025 0.0062
+ 102_1081 10:57:04 -00:13:10 9.903 0.664 0.255 0.366 0.333 0.698 58 50 0.0009 0.0009 0.0017 0.0008 0.0008 0.0011
+ G163_27 10:57:35 -07:31:23 14.338 0.288 -0.548 0.206 0.210 0.417 26 15 0.0055 0.0047 0.0065 0.0041 0.0075 0.0082
+ G163_50 11:08:00 -05:09:26 13.059 0.035 -0.688 -0.085 -0.072 -0.159 54 41 0.0014 0.0020 0.0023 0.0012 0.0020 0.0027
+ G163_51 11:08:07 -05:13:47 12.576 1.506 1.228 1.084 1.359 2.441 29 16 0.0046 0.0046 0.0182 0.0019 0.0035 0.0041
+ G10_50 11:47:44 +00:48:55 11.153 1.752 1.318 1.294 1.673 2.969 14 7 0.0024 0.0024 0.0078 0.0037 0.0021 0.0037
+ 103_302 11:56:06 -00:47:54 9.861 0.368 -0.056 0.228 0.237 0.465 57 45 0.0016 0.0011 0.0017 0.0009 0.0009 0.0015
+ 103_626 11:56:46 -00:21:54 11.836 0.413 -0.057 0.262 0.274 0.535 17 10 0.0034 0.0027 0.0032 0.0022 0.0015 0.0024
+ G12_43 12:33:20 +09:01:08 12.467 1.846 1.085 1.530 1.944 3.479 13 6 0.0042 0.0053 0.0466 0.0053 0.0039 0.0033
+ 104_306 12:41:04 -00:37:11 9.370 1.592 1.666 0.832 0.762 1.591 89 68 0.0067 0.0030 0.0059 0.0020 0.0024 0.0033
+ 104_423 12:41:36 -00:31:15 15.602 0.630 0.050 0.262 0.559 0.818 2 1 0.0247 0.0389 0.0269 0.0361 0.1167 0.1520
+ 104_428 12:41:41 -00:26:27 12.630 0.985 0.748 0.534 0.497 1.032 25 16 0.0038 0.0028 0.0044 0.0024 0.0018 0.0036
+ 104_L1 12:41:44 -00:22:43 14.608 0.630 0.064 0.374 0.364 0.739 2 1 0.0007 0.0014 0.0127 0.0113 0.0163 0.0042
+ 104_430 12:41:50 -00:25:52 13.858 0.652 0.131 0.364 0.363 0.727 15 8 0.0052 0.0062 0.0085 0.0046 0.0041 0.0065
+ 104_325 12:42:03 -00:41:36 15.581 0.694 0.051 0.345 0.307 0.652 2 1 0.0163 0.0431 0.0219 0.0255 0.0148 0.0403
+ 104_330 12:42:12 -00:40:40 15.296 0.594 -0.028 0.369 0.371 0.739 15 6 0.0103 0.0276 0.0155 0.0124 0.0214 0.0225
+ 104_440 12:42:14 -00:24:48 15.114 0.440 -0.227 0.289 0.317 0.605 11 5 0.0081 0.0084 0.0103 0.0069 0.0232 0.0262
+ 104_237 12:42:17 -00:51:18 15.395 1.088 0.918 0.647 0.628 1.274 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 104_L2 12:42:20 -00:35:13 16.048 0.650 -0.172 0.344 0.323 0.667 4 2 0.0190 0.0265 0.0450 0.0295 0.0755 0.1000
+ 104_443 12:42:20 -00:25:22 15.372 1.331 1.280 0.817 0.778 1.595 3 2 0.0087 0.0023 0.1120 0.0139 0.0104 0.0202
+ 104_444 12:42:21 -00:32:29 13.477 0.512 -0.070 0.313 0.331 0.643 2 1 0.0014 0.0099 0.0085 0.0021 0.0014 0.0007
+ 104_335 12:42:22 -00:33:09 11.665 0.622 0.145 0.357 0.334 0.691 4 2 0.0095 0.0010 0.0020 0.0035 0.0045 0.0070
+ 104_334 12:42:21 -00:40:28 13.484 0.518 -0.067 0.323 0.331 0.653 24 16 0.0047 0.0031 0.0039 0.0029 0.0031 0.0047
+ 104_239 12:42:23 -00:46:32 13.936 1.356 1.291 0.868 0.805 1.675 7 3 0.0060 0.0087 0.0231 0.0045 0.0030 0.0057
+ 104_336 12:42:25 -00:39:58 14.404 0.830 0.495 0.461 0.403 0.865 14 6 0.0067 0.0072 0.0123 0.0059 0.0099 0.0104
+ 104_338 12:42:31 -00:38:32 16.059 0.591 -0.082 0.348 0.372 0.719 8 5 0.0078 0.0219 0.0368 0.0088 0.0209 0.0170
+ 104_339 12:42:34 -00:41:39 15.459 0.832 0.709 0.476 0.374 0.849 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 104_244 12:42:35 -00:45:47 16.011 0.590 -0.152 0.338 0.489 0.825 2 2 0.0092 0.0057 0.0113 0.0035 0.0269 0.0290
+ 104_455 12:42:52 -00:24:19 15.105 0.581 -0.024 0.360 0.357 0.716 13 7 0.0067 0.0144 0.0122 0.0053 0.0089 0.0122
+ 104_456 12:42:54 -00:32:06 12.362 0.622 0.135 0.357 0.337 0.694 4 2 0.0025 0.0025 0.0045 0.0035 0.0065 0.0080
+ 104_457 12:42:54 -00:28:49 16.048 0.753 0.522 0.484 0.490 0.974 9 4 0.0107 0.0187 0.0770 0.0183 0.0370 0.0213
+ 104_460 12:43:03 -00:28:21 12.886 1.287 1.243 0.813 0.693 1.507 24 16 0.0043 0.0033 0.0067 0.0022 0.0020 0.0033
+ 104_461 12:43:07 -00:32:21 9.705 0.476 -0.030 0.289 0.290 0.580 95 74 0.0010 0.0008 0.0013 0.0007 0.0006 0.0006
+ 104_350 12:43:15 -00:33:21 13.634 0.673 0.165 0.383 0.353 0.736 14 7 0.0043 0.0035 0.0056 0.0032 0.0045 0.0061
+ 104_470 12:43:22 -00:29:56 14.310 0.732 0.101 0.295 0.356 0.649 3 1 0.0121 0.0092 0.0202 0.0133 0.0035 0.0150
+ 104_364 12:43:47 -00:34:30 15.799 0.601 -0.131 0.314 0.397 0.712 2 1 0.0156 0.0488 0.0559 0.0085 0.0410 0.0495
+ 104_366 12:43:54 -00:34:52 12.908 0.870 0.424 0.517 0.464 0.982 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 104_479 12:43:56 -00:32:51 16.087 1.271 0.673 0.657 0.607 1.264 2 1 0.0339 0.0276 0.3995 0.0028 0.0035 0.0071
+ 104_367 12:43:59 -00:33:36 15.844 0.639 -0.126 0.382 0.296 0.679 2 1 0.0255 0.0212 0.0156 0.0177 0.0042 0.0226
+ 104_484 12:44:20 -00:30:57 14.406 1.024 0.732 0.514 0.486 1.000 2 1 0.0071 0.0184 0.0134 0.0057 0.0064 0.0120
+ 104_485 12:44:24 -00:30:16 15.017 0.838 0.493 0.478 0.488 0.967 2 1 0.0113 0.0339 0.0226 0.0014 0.0113 0.0099
+ 104_490 12:44:33 -00:25:53 12.572 0.535 0.048 0.318 0.312 0.630 12 8 0.0029 0.0032 0.0052 0.0023 0.0023 0.0026
+ 104_598 12:45:17 -00:16:37 11.479 1.106 1.050 0.670 0.546 1.215 70 59 0.0017 0.0011 0.0027 0.0010 0.0008 0.0012
+ G14_55 13:28:22 -02:21:28 11.336 1.491 1.157 1.078 1.388 2.462 5 2 0.0058 0.0049 0.0076 0.0067 0.0013 0.0063
+ PG1323-086 13:25:39 -08:49:16 13.481 -0.140 -0.681 -0.048 -0.078 -0.127 39 18 0.0019 0.0022 0.0026 0.0018 0.0045 0.0045
+PG1323-086A 13:25:49 -08:50:22 13.591 0.393 -0.019 0.252 0.252 0.506 20 12 0.0257 0.0022 0.0045 0.0027 0.0047 0.0060
+PG1323-086C 13:25:50 -08:48:37 14.003 0.707 0.245 0.395 0.363 0.759 26 13 0.0031 0.0027 0.0076 0.0024 0.0041 0.0049
+PG1323-086B 13:25:50 -08:51:53 13.406 0.761 0.265 0.426 0.407 0.833 23 13 0.0019 0.0029 0.0042 0.0023 0.0023 0.0031
+PG1323-086D 13:26:05 -08:50:34 12.080 0.587 0.005 0.346 0.335 0.684 15 6 0.0023 0.0018 0.0036 0.0013 0.0026 0.0031
+ 105_505 13:35:25 -00:23:38 10.270 1.422 1.218 0.910 0.861 1.771 6 3 0.0061 0.0102 0.0053 0.0053 0.0033 0.0069
+ 105_437 13:37:17 -00:37:56 12.535 0.248 0.067 0.136 0.143 0.279 7 3 0.0060 0.0038 0.0094 0.0053 0.0026 0.0076
+ 105_815 13:40:04 -00:02:10 11.453 0.385 -0.237 0.267 0.291 0.560 22 14 0.0016 0.0030 0.0028 0.0013 0.0013 0.0015
+ +2_2711 13:42:21 +01:30:17 10.367 -0.166 -0.697 -0.072 -0.095 -0.167 54 39 0.0012 0.0014 0.0018 0.0008 0.0010 0.0012
+ 121968 13:58:52 -02:55:12 10.254 -0.186 -0.908 -0.073 -0.098 -0.172 46 32 0.0012 0.0010 0.0021 0.0007 0.0010 0.0012
+ PG1407-013 14:10:26 -01:30:13 13.750 -0.259 -1.119 -0.130 -0.144 -0.277 3 2 0.0040 0.0064 0.0173 0.0046 0.0173 0.0219
+ 106_1024 14:40:07 +00:01:45 11.599 0.332 0.085 0.196 0.195 0.390 35 27 0.0051 0.0022 0.0029 0.0019 0.0014 0.0029
+ 106_700 14:40:52 -00:23:36 9.785 1.362 1.582 0.728 0.641 1.370 53 44 0.0011 0.0010 0.0022 0.0010 0.0010 0.0014
+ PG1514+034 15:17:14 +03:10:27 13.997 -0.009 -0.955 0.087 0.126 0.212 6 3 0.0078 0.0082 0.0102 0.0029 0.0065 0.0073
+ PG1525-071 15:28:11 -07:16:27 15.053 -0.198 -1.148 -0.088 -0.075 -0.168 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+PG1525-071D 15:28:12 -07:16:33 16.301 0.564 0.305 0.411 0.346 0.757 2 1 0.0021 0.1570 0.0325 0.0113 0.0198 0.0085
+PG1525-071A 15:28:13 -07:15:54 13.509 0.757 0.257 0.445 0.425 0.869 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+PG1525-071B 15:28:14 -07:16:08 16.403 0.730 0.135 0.442 0.366 0.808 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+PG1525-071C 15:28:16 -07:14:21 13.530 1.109 1.130 0.590 0.513 1.104 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+PG1528+062B 15:30:40 +06:01:11 11.989 0.593 0.005 0.364 0.344 0.711 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+PG1528+062A 15:30:49 +06:01:24 15.553 0.830 0.356 0.433 0.389 0.824 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ PG1528+062 15:30:50 +06:00:56 14.767 -0.252 -1.091 -0.111 -0.182 -0.296 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+PG1528+062C 15:30:56 +06:00:07 13.477 0.644 0.074 0.357 0.340 0.699 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+PG1530+057A 15:33:10 +05:33:45 13.711 0.829 0.414 0.473 0.412 0.886 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ PG1530+057 15:33:11 +05:32:27 14.211 0.151 -0.789 0.162 0.036 0.199 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+PG1530+057B 15:33:18 +05:33:48 12.842 0.745 0.325 0.423 0.376 0.799 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 107_970 15:37:25 +00:18:34 10.939 1.596 1.750 1.142 1.435 2.574 57 47 0.0074 0.0017 0.0061 0.0020 0.0033 0.0040
+ 107_568 15:37:53 -00:17:18 13.054 1.149 0.862 0.625 0.595 1.217 15 7 0.0015 0.0028 0.0039 0.0021 0.0028 0.0028
+ 107_1006 15:38:34 +00:14:22 11.712 0.766 0.279 0.442 0.421 0.863 59 51 0.0010 0.0010 0.0025 0.0008 0.0009 0.0010
+ 107_720 15:38:37 -00:02:24 13.121 0.599 0.088 0.374 0.355 0.731 2 1 0.0057 0.0028 0.0106 0.0099 0.0028 0.0078
+ 107_456 15:38:43 -00:19:47 12.919 0.921 0.589 0.537 0.478 1.015 20 10 0.0020 0.0029 0.0045 0.0020 0.0025 0.0036
+ 107_457 15:38:46 -00:20:15 14.910 0.792 0.350 0.494 0.469 0.964 2 1 0.0021 0.0035 0.0099 0.0028 0.0064 0.0092
+ 107_351 15:38:46 -00:32:06 12.342 0.562 -0.005 0.351 0.358 0.708 25 14 0.0020 0.0024 0.0040 0.0016 0.0022 0.0026
+ 107_592 15:38:51 -00:17:10 11.847 1.318 1.380 0.709 0.647 1.357 9 5 0.0033 0.0047 0.0133 0.0013 0.0023 0.0020
+ 107_458 15:38:50 -00:24:27 11.676 1.214 1.189 0.667 0.602 1.274 2 1 0.0042 0.0057 0.0050 0.0028 0.0007 0.0035
+ 107_459 15:38:51 -00:22:31 12.284 0.900 0.427 0.525 0.517 1.045 2 1 0.0014 0.0106 0.0099 0.0028 0.0007 0.0035
+ 107_212 15:38:57 -00:45:30 13.383 0.683 0.135 0.404 0.411 0.818 2 1 0.0064 0.0106 0.0198 0.0071 0.0085 0.0148
+ 107_215 15:38:57 -00:43:06 16.046 0.115 -0.082 -0.032 -0.475 -0.511 3 2 0.0266 0.0312 0.0092 0.0935 0.2991 0.3943
+ 107_213 15:38:57 -00:44:14 14.262 0.802 0.261 0.531 0.509 1.038 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 107_357 15:39:05 -00:39:11 14.418 0.675 0.025 0.416 0.421 0.840 2 1 0.0000 0.0035 0.0057 0.0120 0.0233 0.0113
+ 107_599 15:39:09 -00:14:28 14.675 0.698 0.243 0.433 0.438 0.869 17 7 0.0082 0.0121 0.0061 0.0053 0.0121 0.0155
+ 107_359 15:39:09 -00:35:31 12.797 0.580 -0.124 0.379 0.381 0.759 6 3 0.0049 0.0069 0.0118 0.0029 0.0033 0.0053
+ 107_600 15:39:11 -00:15:49 14.884 0.503 0.049 0.339 0.361 0.700 9 4 0.0170 0.0130 0.0227 0.0097 0.0147 0.0203
+ 107_601 15:39:14 -00:13:26 14.646 1.412 1.265 0.923 0.835 1.761 33 13 0.0045 0.0073 0.0247 0.0035 0.0031 0.0038
+ 107_602 15:39:19 -00:15:29 12.116 0.991 0.585 0.545 0.531 1.074 17 9 0.0027 0.0029 0.0070 0.0015 0.0022 0.0032
+ 107_612 15:39:35 -00:15:06 14.256 0.896 0.296 0.551 0.530 1.081 2 1 0.0057 0.0014 0.0035 0.0035 0.0007 0.0021
+ 107_611 15:39:36 -00:12:36 14.329 0.890 0.455 0.520 0.447 0.968 4 2 0.0065 0.0085 0.0165 0.0090 0.0105 0.0170
+ 107_614 15:39:42 -00:13:10 13.926 0.622 0.033 0.361 0.370 0.732 4 2 0.0065 0.0170 0.0150 0.0040 0.0130 0.0090
+ 107_626 15:40:06 -00:17:28 13.468 1.000 0.728 0.600 0.527 1.126 24 12 0.0045 0.0082 0.0118 0.0025 0.0022 0.0035
+ 107_627 15:40:08 -00:17:22 13.349 0.779 0.226 0.465 0.454 0.918 24 12 0.0055 0.0047 0.0049 0.0022 0.0027 0.0037
+ 107_484 15:40:17 -00:21:13 11.311 1.237 1.291 0.664 0.577 1.240 13 7 0.0044 0.0022 0.0111 0.0019 0.0008 0.0022
+ 107_636 15:40:41 -00:14:54 14.873 0.751 0.121 0.432 0.465 0.896 2 1 0.0134 0.0120 0.0177 0.0085 0.0417 0.0325
+ 107_639 15:40:45 -00:17:11 14.197 0.640 -0.026 0.399 0.404 0.803 10 6 0.0161 0.0092 0.0202 0.0104 0.0095 0.0127
+ 107_640 15:40:50 -00:16:48 15.050 0.755 0.092 0.511 0.506 1.017 5 3 0.0250 0.0103 0.0322 0.0183 0.0161 0.0246
+ G153_41 16:17:55 -15:35:52 13.422 -0.205 -1.133 -0.135 -0.154 -0.290 23 11 0.0035 0.0031 0.0063 0.0033 0.0056 0.0065
+ G138_25 16:25:14 +15:41:15 13.513 1.419 1.265 0.883 0.796 1.685 2 1 0.0007 0.0177 0.0382 0.0028 0.0028 0.0049
+ -12_4523 16:30:18 -12:39:08 10.069 1.568 1.192 1.152 1.498 2.649 8 5 0.0032 0.0025 0.0025 0.0007 0.0018 0.0014
+ PG1633+099 16:35:24 +09:47:50 14.397 -0.192 -0.974 -0.093 -0.116 -0.212 13 6 0.0025 0.0022 0.0047 0.0033 0.0089 0.0111
+PG1633+099A 16:35:26 +09:47:53 15.256 0.873 0.320 0.505 0.511 1.015 15 6 0.0036 0.0052 0.0090 0.0036 0.0093 0.0111
+PG1633+099B 16:35:34 +09:46:22 12.969 1.081 1.007 0.590 0.502 1.090 12 6 0.0017 0.0020 0.0069 0.0012 0.0014 0.0020
+PG1633+099C 16:35:38 +09:46:16 13.229 1.134 1.138 0.618 0.523 1.138 10 6 0.0025 0.0022 0.0038 0.0016 0.0022 0.0038
+PG1633+099D 16:35:40 +09:46:43 13.691 0.535 -0.025 0.324 0.327 0.650 9 5 0.0020 0.0020 0.0050 0.0017 0.0033 0.0033
+ 108_719 16:36:11 -00:25:32 12.690 1.031 0.648 0.553 0.533 1.087 4 2 0.0045 0.0025 0.0005 0.0045 0.0025 0.0050
+ 108_1848 16:36:58 +00:05:57 11.738 0.559 0.073 0.331 0.325 0.657 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 108_475 16:37:00 -00:34:40 11.309 1.380 1.462 0.744 0.665 1.409 71 58 0.0014 0.0013 0.0042 0.0008 0.0007 0.0011
+ 108_1863 16:37:13 +00:02:34 12.244 0.803 0.378 0.446 0.398 0.844 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 108_551 16:37:47 -00:33:06 10.703 0.179 0.178 0.099 0.110 0.208 104 76 0.0011 0.0007 0.0023 0.0006 0.0010 0.0011
+ 108_1918 16:37:50 -00:00:37 11.384 1.432 1.839 0.773 0.661 1.434 2 1 0.0007 0.0014 0.0000 0.0042 0.0000 0.0042
+ 108_981 16:39:17 -00:25:08 12.071 0.494 0.237 0.310 0.312 0.622 4 2 0.0025 0.0015 0.0075 0.0020 0.0030 0.0010
+ PG1647+056 16:50:18 +05:32:53 14.773 -0.173 -1.064 -0.058 -0.022 -0.082 7 3 0.0087 0.0087 0.0076 0.0102 0.0151 0.0163
+ WOLF_629 16:55:27 -08:18:53 11.759 1.677 1.256 1.185 1.525 2.715 6 3 0.0041 0.0029 0.0033 0.0016 0.0012 0.0012
+ PG1657+078 16:59:32 +07:43:31 15.015 -0.149 -0.940 -0.063 -0.033 -0.100 9 4 0.0067 0.0053 0.0090 0.0087 0.0270 0.0330
+PG1657+078B 16:59:32 +07:42:11 14.721 0.708 0.065 0.417 0.420 0.838 2 1 0.0021 0.0064 0.0071 0.0014 0.0000 0.0014
+PG1657+078A 16:59:33 +07:42:25 14.033 1.069 0.730 0.573 0.539 1.113 2 1 0.0007 0.0007 0.0064 0.0064 0.0057 0.0127
+PG1657+078C 16:59:35 +07:42:26 15.225 0.840 0.385 0.521 0.444 0.967 2 1 0.0000 0.0042 0.0085 0.0057 0.0127 0.0071
+ -4_4226 17:05:15 -05:05:05 10.071 1.415 1.085 0.970 1.141 2.113 6 3 0.0033 0.0012 0.0029 0.0004 0.0008 0.0012
+ 109_71 17:44:06 -00:24:59 11.493 0.323 0.153 0.186 0.223 0.410 50 42 0.0010 0.0011 0.0020 0.0008 0.0008 0.0011
+ 109_381 17:44:12 -00:20:32 11.730 0.704 0.225 0.428 0.435 0.861 55 45 0.0011 0.0015 0.0015 0.0009 0.0008 0.0011
+ 109_949 17:44:13 -00:02:28 12.828 0.806 0.363 0.500 0.517 1.020 2 1 0.0064 0.0007 0.0099 0.0078 0.0035 0.0113
+ 109_954 17:44:15 -00:02:17 12.436 1.296 0.956 0.764 0.731 1.496 9 5 0.0093 0.0060 0.0203 0.0017 0.0027 0.0033
+ 109_956 17:44:17 -00:02:32 14.639 1.283 0.858 0.779 0.743 1.525 2 1 0.0113 0.0198 0.0035 0.0184 0.0156 0.0346
+ 109_199 17:45:02 -00:29:28 10.990 1.739 1.967 1.006 0.900 1.904 3 2 0.0098 0.0040 0.0035 0.0035 0.0040 0.0046
+ 109_231 17:45:20 -00:25:51 9.332 1.462 1.593 0.785 0.704 1.492 76 52 0.0011 0.0014 0.0028 0.0006 0.0007 0.0009
+ 109_537 17:45:42 -00:21:34 10.353 0.609 0.227 0.376 0.392 0.768 66 47 0.0027 0.0012 0.0020 0.0009 0.0010 0.0015
+ G21_15 18:27:13 +04:03:05 13.889 0.092 -0.598 -0.039 -0.030 -0.069 19 9 0.0046 0.0053 0.0067 0.0046 0.0094 0.0094
+ 110_229 18:40:45 +00:01:51 13.649 1.910 1.391 1.198 1.155 2.356 30 16 0.0031 0.0091 0.0225 0.0018 0.0020 0.0026
+ 110_230 18:40:51 +00:02:23 14.281 1.084 0.728 0.624 0.596 1.218 21 11 0.0031 0.0050 0.0116 0.0020 0.0044 0.0050
+ 110_232 18:40:52 +00:01:58 12.516 0.729 0.147 0.439 0.450 0.889 28 16 0.0032 0.0028 0.0045 0.0015 0.0019 0.0025
+ 110_233 18:40:52 +00:00:51 12.771 1.281 0.812 0.773 0.818 1.593 22 10 0.0028 0.0034 0.0070 0.0021 0.0015 0.0021
+ 110_239 18:41:19 +00:00:14 13.858 0.899 0.584 0.541 0.517 1.060 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 110_339 18:41:27 +00:08:26 13.607 0.988 0.776 0.563 0.468 1.036 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 110_340 18:41:29 +00:15:22 10.025 0.303 0.127 0.170 0.182 0.353 64 51 0.0014 0.0010 0.0022 0.0006 0.0009 0.0010
+ 110_477 18:41:43 +00:26:41 13.988 1.345 0.715 0.850 0.857 1.707 21 11 0.0072 0.0131 0.0375 0.0031 0.0039 0.0063
+ 110_246 18:41:51 +00:05:20 12.706 0.586 -0.129 0.381 0.410 0.790 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 110_346 18:41:55 +00:10:00 14.757 0.999 0.752 0.697 0.646 1.345 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 110_349 18:42:13 +00:10:14 15.095 1.088 0.668 0.503 -0.059 0.477 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 110_355 18:42:19 +00:08:24 11.944 1.023 0.504 0.652 0.727 1.378 16 8 0.0027 0.0030 0.0045 0.0022 0.0022 0.0035
+ 110_358 18:42:37 +00:15:01 14.430 1.039 0.418 0.603 0.543 1.150 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 110_360 18:42:40 +00:09:10 14.618 1.197 0.539 0.715 0.717 1.432 5 2 0.0094 0.0192 0.0291 0.0085 0.0031 0.0080
+ 110_361 18:42:45 +00:08:04 12.425 0.632 0.035 0.361 0.348 0.709 30 17 0.0022 0.0022 0.0029 0.0018 0.0020 0.0029
+ 110_362 18:42:48 +00:06:26 15.693 1.333 3.919 0.918 0.885 1.803 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 110_266 18:42:49 +00:05:06 12.018 0.889 0.411 0.538 0.577 1.111 8 3 0.0014 0.0028 0.0039 0.0014 0.0021 0.0032
+ 110_L1 18:42:50 +00:07:10 16.252 1.752 2.953 1.066 0.992 2.058 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 110_364 18:42:52 +00:07:54 13.615 1.133 1.095 0.697 0.585 1.281 15 7 0.0021 0.0067 0.0088 0.0015 0.0026 0.0021
+ 110_365 18:42:57 +00:07:20 13.470 2.261 1.895 1.360 1.270 2.631 45 20 0.0027 0.0091 0.0313 0.0021 0.0022 0.0034
+ 110_157 18:42:57 -00:08:56 13.491 2.123 1.679 1.257 1.139 2.395 7 3 0.0057 0.0257 0.1750 0.0034 0.0049 0.0057
+ 110_496 18:42:59 +00:31:08 13.004 1.040 0.737 0.607 0.681 1.287 9 4 0.0027 0.0060 0.0230 0.0020 0.0023 0.0043
+ 110_273 18:42:59 +00:02:23 14.686 2.527 1.000 1.509 1.345 2.856 5 2 0.0161 0.0783 1.3416 0.0040 0.0103 0.0107
+ 110_497 18:43:02 +00:30:56 14.196 1.052 0.380 0.606 0.597 1.203 5 2 0.0054 0.0063 0.0143 0.0067 0.0045 0.0063
+ 110_280 18:43:07 -00:03:40 12.996 2.151 2.133 1.235 1.148 2.384 25 12 0.0034 0.0144 0.0906 0.0018 0.0030 0.0036
+ 110_499 18:43:07 +00:28:00 11.737 0.987 0.639 0.600 0.674 1.273 23 13 0.0031 0.0029 0.0071 0.0019 0.0017 0.0029
+ 110_502 18:43:10 +00:27:40 12.330 2.326 2.326 1.373 1.250 2.625 38 19 0.0031 0.0047 0.0225 0.0019 0.0024 0.0041
+ 110_504 18:43:11 +00:30:05 14.022 1.248 1.323 0.797 0.683 1.482 5 2 0.0013 0.0063 0.0268 0.0036 0.0063 0.0080
+ 110_503 18:43:11 +00:29:43 11.773 0.671 0.506 0.373 0.436 0.808 26 14 0.0031 0.0020 0.0051 0.0018 0.0016 0.0022
+ 110_506 18:43:19 +00:30:27 11.312 0.568 0.059 0.335 0.312 0.652 2 1 0.0021 0.0021 0.0064 0.0007 0.0042 0.0042
+ 110_507 18:43:19 +00:29:26 12.440 1.141 0.830 0.633 0.579 1.206 2 1 0.0049 0.0057 0.0057 0.0042 0.0000 0.0049
+ 110_290 18:43:22 -00:01:15 11.898 0.708 0.196 0.418 0.418 0.836 3 2 0.0029 0.0006 0.0046 0.0023 0.0029 0.0035
+ 110_441 18:43:34 +00:19:40 11.121 0.555 0.112 0.324 0.336 0.660 43 36 0.0015 0.0015 0.0023 0.0012 0.0009 0.0020
+ 110_311 18:43:48 -00:00:22 15.505 1.796 1.179 1.010 0.864 1.874 4 2 0.0180 0.0360 0.1255 0.0340 0.0830 0.1130
+ 110_312 18:43:50 +00:00:07 16.093 1.319 -0.788 1.137 1.154 2.293 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 110_450 18:43:52 +00:22:58 11.585 0.944 0.691 0.552 0.625 1.177 49 42 0.0020 0.0017 0.0033 0.0011 0.0010 0.0016
+ 110_316 18:43:52 +00:01:05 14.821 1.731 4.355 0.858 0.910 1.769 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 110_315 18:43:52 +00:00:49 13.637 2.069 2.256 1.206 1.133 2.338 8 4 0.0067 0.0361 0.4639 0.0032 0.0057 0.0067
+ 110_319 18:43:55 +00:02:01 11.861 1.309 1.076 0.742 0.700 1.443 3 2 0.0110 0.0029 0.0035 0.0040 0.0017 0.0058
+ 111_775 19:37:16 +00:12:05 10.744 1.738 2.029 0.965 0.896 1.862 61 48 0.0015 0.0009 0.0059 0.0008 0.0006 0.0010
+ 111_773 19:37:16 +00:10:59 8.963 0.206 -0.210 0.119 0.144 0.262 66 47 0.0012 0.0010 0.0017 0.0007 0.0007 0.0009
+ 111_1925 19:37:29 +00:25:01 12.388 0.395 0.262 0.221 0.253 0.474 26 13 0.0018 0.0014 0.0043 0.0018 0.0014 0.0024
+ 111_1965 19:37:42 +00:26:50 11.419 1.710 1.865 0.951 0.877 1.830 16 8 0.0018 0.0037 0.0090 0.0010 0.0010 0.0012
+ 111_1969 19:37:44 +00:25:48 10.382 1.959 2.306 1.177 1.222 2.400 58 47 0.0017 0.0014 0.0054 0.0008 0.0009 0.0013
+ 111_2039 19:38:05 +00:32:13 12.395 1.369 1.237 0.739 0.689 1.430 8 4 0.0021 0.0028 0.0120 0.0021 0.0021 0.0021
+ 111_2088 19:38:22 +00:31:01 13.193 1.610 1.678 0.888 0.818 1.708 8 4 0.0014 0.0042 0.0110 0.0018 0.0014 0.0018
+ 111_2093 19:38:24 +00:31:25 12.538 0.637 0.283 0.370 0.397 0.766 8 4 0.0025 0.0035 0.0071 0.0032 0.0021 0.0039
+ 112_595 20:41:18 +00:16:28 11.352 1.601 1.993 0.899 0.901 1.801 46 37 0.0022 0.0016 0.0060 0.0009 0.0012 0.0015
+ 112_704 20:42:02 +00:19:10 11.452 1.536 1.742 0.822 0.746 1.570 19 12 0.0030 0.0023 0.0076 0.0021 0.0018 0.0025
+ 112_223 20:42:14 +00:09:01 11.424 0.454 0.010 0.273 0.274 0.547 45 37 0.0012 0.0009 0.0021 0.0012 0.0010 0.0016
+ 112_250 20:42:26 +00:07:43 12.095 0.532 -0.025 0.317 0.323 0.639 18 12 0.0021 0.0019 0.0042 0.0019 0.0019 0.0026
+ 112_275 20:42:36 +00:07:21 9.905 1.210 1.299 0.647 0.569 1.217 63 48 0.0001 0.0009 0.0025 0.0008 0.0005 0.0009
+ 112_805 20:42:46 +00:16:08 12.086 0.152 0.150 0.063 0.075 0.138 51 42 0.0010 0.0011 0.0028 0.0011 0.0015 0.0021
+ 112_822 20:42:55 +00:15:04 11.549 1.031 0.883 0.558 0.502 1.060 36 27 0.0012 0.0015 0.0040 0.0008 0.0010 0.0012
+ MARK_A2 20:43:54 -10:45:32 14.540 0.666 0.096 0.379 0.371 0.751 21 10 0.0028 0.0031 0.0046 0.0024 0.0050 0.0059
+ MARK_A1 20:43:58 -10:47:11 15.911 0.609 -0.014 0.367 0.373 0.740 25 10 0.0040 0.0090 0.0136 0.0044 0.0128 0.0148
+ MARK_A 20:43:59 -10:47:42 13.258 -0.242 -1.162 -0.115 -0.125 -0.241 39 22 0.0019 0.0018 0.0038 0.0018 0.0045 0.0048
+ MARK_A3 20:44:02 -10:45:39 14.818 0.938 0.651 0.587 0.510 1.098 22 10 0.0023 0.0034 0.0104 0.0021 0.0030 0.0045
+ WOLF_918 21:11:30 -13:08:22 10.868 1.494 1.146 0.981 1.088 2.065 8 4 0.0049 0.0039 0.0053 0.0025 0.0032 0.0028
+ G26_7 21:31:16 -09:47:28 12.005 1.669 1.235 1.300 1.695 2.986 6 3 0.0057 0.0037 0.0204 0.0053 0.0049 0.0073
+ 113_440 21:40:35 +00:41:45 11.796 0.637 0.167 0.363 0.350 0.715 2 1 0.0014 0.0014 0.0042 0.0000 0.0028 0.0021
+ 113_221 21:40:36 +00:21:00 12.071 1.031 0.874 0.550 0.490 1.041 24 10 0.0016 0.0020 0.0055 0.0018 0.0014 0.0022
+ 113_L1 21:40:47 +00:28:32 15.530 1.343 1.180 0.867 0.723 1.594 2 1 0.0042 0.0509 0.1867 0.0049 0.0049 0.0007
+ 113_337 21:40:49 +00:27:55 14.225 0.519 -0.025 0.351 0.331 0.682 5 3 0.0130 0.0058 0.0085 0.0072 0.0063 0.0116
+ 113_339 21:40:56 +00:27:57 12.250 0.568 -0.034 0.340 0.347 0.687 31 18 0.0020 0.0020 0.0038 0.0014 0.0016 0.0025
+ 113_233 21:40:59 +00:22:00 12.398 0.549 0.096 0.338 0.322 0.661 2 1 0.0021 0.0014 0.0007 0.0000 0.0007 0.0007
+ 113_342 21:41:00 +00:27:34 10.878 1.015 0.696 0.537 0.513 1.050 7 3 0.0015 0.0015 0.0060 0.0019 0.0023 0.0049
+ 113_239 21:41:07 +00:22:32 13.038 0.516 0.051 0.318 0.327 0.647 2 1 0.0057 0.0028 0.0042 0.0014 0.0035 0.0049
+ 113_241 21:41:09 +00:25:50 14.352 1.344 1.452 0.897 0.797 1.683 22 9 0.0019 0.0032 0.0056 0.0012 0.0031 0.0038
+ 113_245 21:41:13 +00:21:51 15.665 0.628 0.112 0.396 0.318 0.716 2 1 0.0092 0.0099 0.0021 0.0240 0.0106 0.0354
+ 113_459 21:41:15 +00:43:04 12.125 0.535 -0.018 0.307 0.313 0.623 4 2 0.0070 0.0055 0.0070 0.0055 0.0060 0.0105
+ 113_250 21:41:24 +00:20:41 13.160 0.505 -0.003 0.309 0.316 0.626 4 2 0.0025 0.0025 0.0165 0.0035 0.0045 0.0045
+ 113_466 21:41:28 +00:40:14 10.004 0.454 -0.001 0.281 0.282 0.563 58 41 0.0007 0.0008 0.0016 0.0009 0.0008 0.0012
+ 113_259 21:41:44 +00:17:37 11.742 1.194 1.221 0.621 0.543 1.166 48 34 0.0010 0.0016 0.0032 0.0010 0.0010 0.0013
+ 113_260 21:41:48 +00:23:52 12.406 0.514 0.069 0.308 0.298 0.606 23 11 0.0044 0.0021 0.0029 0.0019 0.0015 0.0019
+ 113_475 21:41:51 +00:39:19 10.306 1.058 0.844 0.570 0.527 1.098 40 30 0.0013 0.0011 0.0027 0.0009 0.0009 0.0011
+ 113_263 21:41:53 +00:25:37 15.481 0.280 0.074 0.194 0.207 0.401 4 1 0.0100 0.0080 0.0250 0.0035 0.0120 0.0140
+ 113_265 21:41:53 +00:18:02 14.934 0.639 0.101 0.411 0.395 0.807 9 4 0.0180 0.0120 0.0163 0.0160 0.0170 0.0263
+ 113_366 21:41:54 +00:29:21 13.537 1.096 0.896 0.623 0.588 1.211 2 1 0.0007 0.0049 0.0049 0.0113 0.0021 0.0099
+ 113_268 21:41:57 +00:19:53 15.281 0.589 -0.018 0.379 0.407 0.786 6 2 0.0033 0.0094 0.0229 0.0078 0.0208 0.0229
+ 113_34 21:41:59 +00:01:07 15.173 0.484 -0.054 0.306 0.346 0.652 2 1 0.0014 0.0035 0.0205 0.0106 0.0127 0.0021
+ 113_372 21:42:02 +00:28:36 13.681 0.670 0.080 0.395 0.370 0.766 2 1 0.0042 0.0028 0.0141 0.0042 0.0099 0.0064
+ 113_149 21:42:06 +00:09:27 13.469 0.621 0.043 0.379 0.386 0.765 2 1 0.0078 0.0149 0.0099 0.0049 0.0085 0.0042
+ 113_153 21:42:09 +00:15:06 14.476 0.745 0.285 0.462 0.441 0.902 3 2 0.1051 0.0381 0.0502 0.0121 0.0139 0.0064
+ 113_272 21:42:21 +00:21:04 13.904 0.633 0.067 0.370 0.340 0.710 2 1 0.0014 0.0007 0.0255 0.0007 0.0134 0.0120
+ 113_158 21:42:22 +00:14:09 13.116 0.723 0.247 0.407 0.374 0.782 3 2 0.0035 0.0023 0.0040 0.0029 0.0046 0.0029
+ 113_156 21:42:22 +00:12:06 11.224 0.526 -0.057 0.303 0.314 0.618 2 1 0.0035 0.0035 0.0057 0.0042 0.0007 0.0028
+ 113_491 21:42:25 +00:43:53 14.373 0.764 0.306 0.434 0.420 0.854 4 2 0.0025 0.0020 0.0185 0.0085 0.0095 0.0175
+ 113_492 21:42:28 +00:38:21 12.174 0.553 0.005 0.342 0.341 0.684 9 5 0.0033 0.0063 0.0063 0.0027 0.0033 0.0053
+ 113_493 21:42:29 +00:38:10 11.767 0.786 0.392 0.430 0.393 0.824 8 4 0.0039 0.0035 0.0064 0.0028 0.0018 0.0039
+ 113_495 21:42:30 +00:38:07 12.437 0.947 0.530 0.512 0.497 1.010 6 3 0.0024 0.0029 0.0053 0.0033 0.0037 0.0057
+ 113_163 21:42:35 +00:16:46 14.540 0.658 0.106 0.380 0.355 0.735 15 7 0.0041 0.0049 0.0093 0.0054 0.0083 0.0108
+ 113_165 21:42:38 +00:15:34 15.639 0.601 0.003 0.354 0.392 0.746 2 1 0.0007 0.0057 0.0297 0.0212 0.0431 0.0643
+ 113_281 21:42:39 +00:19:00 15.247 0.529 -0.026 0.347 0.359 0.706 2 1 0.0078 0.0014 0.0311 0.0021 0.0368 0.0389
+ 113_167 21:42:41 +00:16:08 14.841 0.597 -0.034 0.351 0.376 0.728 2 1 0.0007 0.0099 0.0240 0.0071 0.0141 0.0219
+ 113_177 21:42:56 +00:14:46 13.560 0.789 0.318 0.456 0.436 0.890 27 13 0.0052 0.0040 0.0060 0.0044 0.0037 0.0056
+ 113_182 21:43:08 +00:14:51 14.370 0.659 0.065 0.402 0.422 0.824 13 6 0.0144 0.0089 0.0089 0.0039 0.0086 0.0089
+ 113_187 21:43:20 +00:16:52 15.080 1.063 0.969 0.638 0.535 1.174 7 4 0.0060 0.0163 0.0299 0.0068 0.0042 0.0072
+ 113_189 21:43:27 +00:17:22 15.421 1.118 0.958 0.713 0.605 1.319 8 4 0.0138 0.0127 0.0714 0.0113 0.0074 0.0156
+ 113_307 21:43:30 +00:18:02 14.214 1.128 0.911 0.630 0.614 1.245 2 1 0.0049 0.0269 0.0035 0.0014 0.0219 0.0198
+ 113_191 21:43:33 +00:15:56 12.337 0.799 0.223 0.471 0.466 0.937 7 4 0.0042 0.0023 0.0045 0.0023 0.0023 0.0034
+ 113_195 21:43:40 +00:17:22 13.692 0.730 0.201 0.418 0.413 0.832 10 5 0.0051 0.0057 0.0101 0.0032 0.0038 0.0032
+ G93_48 21:52:25 +02:23:20 12.739 -0.008 -0.792 -0.097 -0.094 -0.191 56 40 0.0013 0.0012 0.0024 0.0012 0.0024 0.0027
+PG2213-006C 22:16:18 -00:22:15 15.109 0.721 0.177 0.426 0.404 0.830 7 4 0.0045 0.0057 0.0068 0.0023 0.0068 0.0064
+PG2213-006B 22:16:22 -00:21:49 12.706 0.749 0.297 0.427 0.402 0.829 7 4 0.0011 0.0023 0.0026 0.0008 0.0015 0.0015
+PG2213-006A 22:16:24 -00:21:27 14.178 0.673 0.100 0.406 0.403 0.808 9 5 0.0050 0.0033 0.0057 0.0030 0.0050 0.0060
+ PG2213-006 22:16:28 -00:21:15 14.124 -0.217 -1.125 -0.092 -0.110 -0.203 10 5 0.0022 0.0028 0.0063 0.0044 0.0085 0.0092
+ G156_31 22:38:28 -15:19:17 12.361 1.993 1.408 1.648 2.042 3.684 20 8 0.0027 0.0049 0.0130 0.0027 0.0027 0.0029
+ 114_531 22:40:37 +00:51:56 12.094 0.733 0.186 0.422 0.403 0.825 42 32 0.0011 0.0015 0.0028 0.0009 0.0012 0.0015
+ 114_637 22:40:43 +01:03:10 12.070 0.801 0.307 0.456 0.415 0.872 15 8 0.0044 0.0018 0.0080 0.0026 0.0023 0.0028
+ 114_446 22:41:04 +00:46:04 12.064 0.737 0.237 0.397 0.369 0.769 2 1 0.0035 0.0035 0.0064 0.0035 0.0028 0.0007
+ 114_654 22:41:26 +01:10:11 11.833 0.656 0.178 0.368 0.341 0.711 6 3 0.0008 0.0037 0.0057 0.0016 0.0033 0.0037
+ 114_656 22:41:35 +01:11:13 12.644 0.965 0.698 0.547 0.506 1.051 5 1 0.0036 0.0067 0.0219 0.0040 0.0018 0.0049
+ 114_548 22:41:37 +00:59:07 11.601 1.362 1.573 0.738 0.651 1.387 52 42 0.0014 0.0017 0.0058 0.0010 0.0010 0.0014
+ 114_750 22:41:45 +01:12:38 11.916 -0.041 -0.354 0.027 -0.015 0.011 57 46 0.0015 0.0013 0.0024 0.0013 0.0021 0.0025
+ 114_670 22:42:10 +01:10:17 11.101 1.206 1.223 0.645 0.561 1.208 16 10 0.0027 0.0015 0.0117 0.0020 0.0022 0.0020
+ 114_176 22:43:11 +00:21:16 9.239 1.485 1.853 0.800 0.717 1.521 60 43 0.0010 0.0013 0.0032 0.0006 0.0008 0.0009
+ G156_57 22:53:16 -14:15:38 10.180 1.556 1.182 1.174 1.542 2.713 14 7 0.0027 0.0019 0.0072 0.0011 0.0027 0.0027
+ GD_246 23:12:35 +10:50:27 13.094 -0.318 -1.187 -0.148 -0.183 -0.332 73 57 0.0018 0.0015 0.0022 0.0012 0.0028 0.0032
+ F_108 23:16:12 -01:50:35 12.958 -0.235 -1.052 -0.103 -0.135 -0.239 76 58 0.0014 0.0016 0.0021 0.0014 0.0029 0.0030
+ PG2317+046 23:19:55 +04:52:35 12.876 -0.246 -1.137 -0.074 -0.035 -0.118 10 4 0.0085 0.0041 0.0079 0.0032 0.0028 0.0079
+ PG2331+055 23:33:44 +05:46:36 15.182 -0.066 -0.487 -0.012 -0.031 -0.044 2 1 0.0057 0.0071 0.0035 0.0078 0.0057 0.0127
+PG2331+055A 23:33:49 +05:46:49 13.051 0.741 0.257 0.419 0.401 0.821 2 1 0.0021 0.0014 0.0014 0.0014 0.0014 0.0014
+PG2331+055B 23:33:51 +05:45:07 14.744 0.819 0.429 0.481 0.454 0.935 2 1 0.0035 0.0007 0.0014 0.0035 0.0064 0.0021
+PG2336+004B 23:38:39 +00:42:42 12.431 0.507 -0.035 0.314 0.316 0.625 2 1 0.0007 0.0021 0.0021 0.0000 0.0014 0.0014
+PG2336+004A 23:38:43 +00:42:24 11.277 0.679 0.135 0.398 0.372 0.767 2 1 0.0007 0.0014 0.0000 0.0000 0.0014 0.0014
+ PG2336+004 23:38:44 +00:42:55 15.899 -0.172 -0.781 -0.061 -0.048 -0.110 2 1 0.0113 0.0099 0.0007 0.0092 0.0127 0.0226
+ 115_554 23:41:31 +01:26:26 11.812 1.005 0.548 0.586 0.538 1.127 2 1 0.0042 0.0028 0.0028 0.0057 0.0021 0.0028
+ 115_486 23:41:33 +01:16:45 12.482 0.493 -0.049 0.298 0.308 0.607 16 9 0.0025 0.0035 0.0047 0.0020 0.0020 0.0020
+ 115_412 23:42:01 +01:09:01 12.209 0.573 -0.040 0.327 0.335 0.665 2 1 0.0021 0.0049 0.0035 0.0007 0.0021 0.0021
+ 115_268 23:42:30 +00:52:11 12.494 0.634 0.077 0.366 0.348 0.714 1 1 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
+ 115_420 23:42:36 +01:05:58 11.161 0.468 -0.027 0.286 0.293 0.580 51 42 0.0013 0.0011 0.0020 0.0013 0.0010 0.0015
+ 115_271 23:42:41 +00:45:10 9.695 0.615 0.101 0.353 0.349 0.701 77 55 0.0010 0.0010 0.0014 0.0009 0.0008 0.0011
+ 115_516 23:44:15 +01:14:13 10.434 1.028 0.759 0.563 0.534 1.098 60 49 0.0012 0.0010 0.0019 0.0009 0.0008 0.0010
+ PG2349+002 23:51:53 +00:28:17 13.277 -0.191 -0.921 -0.103 -0.116 -0.219 11 5 0.0063 0.0106 0.0078 0.0057 0.0078 0.0060
diff --git a/noao/digiphot/photcal/catalogs/odewahn.dat b/noao/digiphot/photcal/catalogs/odewahn.dat
new file mode 100644
index 00000000..387a9b4f
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/odewahn.dat
@@ -0,0 +1,283 @@
+# ID V error(V) BV error(BV) VR error(VR)
+#
+# NGC 4147
+#
+ N4147-6 16.730 0.013 0.773 0.010 0.496 0.011
+ N4147-9 18.308 0.025 0.625 0.031 0.429 0.030
+ N4147-11 16.785 0.009 0.779 0.017 0.472 0.013
+ N4147-12 17.722 0.013 1.107 0.019 0.748 0.010
+ N4147-14 17.358 0.007 0.054 0.007 -0.066 0.015
+ N4147-15 16.734 0.005 0.132 0.013 0.017 0.010
+ N4147-102 18.997 0.052 0.583 0.103 0.366 0.049
+ N4147-103 19.038 0.026 0.571 0.075 0.560 0.053
+ N4147-104 18.558 0.022 1.296 0.027 0.884 0.039
+ N4147-106 19.191 0.061 0.529 0.083 0.392 0.074
+ N4147-107 18.895 0.020 0.600 0.077 0.409 0.034
+ N4147-109 17.575 0.013 0.733 0.017 0.402 0.026
+ N4147-110 18.823 0.027 0.629 0.071 0.488 0.063
+ N4147-111 20.138 0.061 0.346 0.055 0.105 0.070
+ N4147-112 19.842 0.064 0.377 0.081 0.224 0.088
+ N4147-114 18.967 0.013 0.680 0.036 0.330 0.045
+ N4147-115 18.283 0.012 0.664 0.019 0.415 0.014
+ N4147-119 17.457 0.007 0.687 0.017 0.493 0.014
+ N4147-120 15.034 0.009 1.034 0.018 0.618 0.015
+ N4147-121 17.996 0.015 1.436 0.015 0.942 0.024
+ N4147-122 16.381 0.008 0.632 0.013 0.431 0.013
+ N4147-123 19.637 0.032 0.679 0.069 0.262 0.066
+ N4147-124 16.984 0.007 0.479 0.014 0.320 0.007
+ N4147-125 18.857 0.039 0.672 0.029 0.382 0.065
+ N4147-126 18.017 0.032 0.711 0.035 0.441 0.033
+ N4147-127 17.903 0.013 0.655 0.010 0.402 0.019
+ N4147-128 18.589 0.027 0.649 0.067 0.521 0.041
+ N4147-129 17.528 0.031 0.748 0.020 0.427 0.024
+ N4147-130 17.192 0.013 0.014 0.015 -0.059 0.015
+ N4147-131 18.310 0.023 0.663 0.024 0.447 0.029
+ N4147-132 17.572 0.015 0.671 0.016 0.464 0.016
+ N4147-133 17.466 0.012 0.653 0.012 0.443 0.015
+ N4147-134 17.038 0.070 0.247 0.028 0.164 0.037
+ N4147-135 17.287 0.051 -0.093 0.032 -0.062 0.052
+ N4147-136 16.894 0.016 0.683 0.026 0.374 0.015
+ N4147-138 19.300 0.038 0.540 0.095 0.385 0.074
+ N4147-141 16.863 0.012 0.654 0.014 0.438 0.012
+ N4147-142 18.711 0.025 1.416 0.033 0.881 0.021
+ N4147-143 17.640 0.012 0.655 0.032 0.448 0.008
+ N4147-144 16.535 0.007 0.787 0.011 0.492 0.014
+ N4147-145 17.264 0.077 0.312 0.028 0.320 0.030
+ N4147-146 15.917 0.059 0.321 0.030 0.347 0.055
+ N4147-147 15.945 0.016 0.831 0.014 0.523 0.013
+#
+# NGC 7006
+#
+ N7006-1 17.323 0.013 1.102 0.031 0.698 0.025
+ N7006-5 15.756 0.005 1.031 0.011 0.557 0.007
+ N7006-6 17.989 0.014 0.736 0.018 0.461 0.013
+ N7006-7 12.810 0.009 0.474 0.012 0.293 0.005
+ N7006-8 19.483 0.041 0.789 0.043 0.464 0.014
+ N7006-9 19.024 0.040 0.497 0.052 0.241 0.033
+ N7006-12 18.096 0.007 1.042 0.013 0.568 0.011
+ N7006-14 18.920 0.021 0.599 0.040 0.427 0.040
+ N7006-15 18.291 0.013 0.808 0.014 0.472 0.008
+ N7006-16 13.598 0.005 0.591 0.013 0.346 0.004
+ N7006-17 16.485 0.005 0.822 0.011 0.438 0.007
+ N7006-19 15.514 0.011 0.659 0.009 0.360 0.006
+ N7006-24 19.020 0.023 0.491 0.027 0.315 0.027
+ N7006-25 16.472 0.005 1.305 0.005 0.775 0.003
+ N7006-27 18.323 0.006 0.766 0.017 0.428 0.012
+ N7006-29 19.074 0.036 0.724 0.023 0.354 0.013
+ N7006-30 18.838 0.013 0.690 0.022 0.445 0.023
+ N7006-31 16.777 0.005 0.940 0.008 0.541 0.006
+ N7006-33 19.813 0.025 0.897 0.164 0.314 0.050
+ N7006-34 17.924 0.009 0.964 0.015 0.545 0.012
+ N7006-35 18.861 0.014 0.616 0.053 0.350 0.023
+ N7006-36 18.808 0.014 0.618 0.025 0.380 0.010
+ N7006-37 18.866 0.022 0.620 0.039 0.365 0.040
+ N7006-39 16.139 0.010 0.818 0.010 0.444 0.007
+ N7006-40 18.883 0.010 0.537 0.053 0.327 0.035
+ N7006-41 18.950 0.022 0.617 0.031 0.423 0.017
+ N7006-42 18.617 0.015 1.007 0.036 0.631 0.022
+ N7006-43 18.455 0.010 0.866 0.023 0.505 0.022
+ N7006-44 18.873 0.022 0.454 0.030 0.296 0.021
+ N7006-46 19.298 0.023 0.716 0.044 0.351 0.058
+ N7006-48 19.676 0.021 0.999 0.036 0.520 0.033
+ N7006-49 19.117 0.021 0.052 0.034 0.016 0.041
+ N7006-50 19.068 0.020 0.419 0.046 0.252 0.030
+ N7006-51 18.945 0.021 0.910 0.038 0.497 0.034
+ N7006-52 18.647 0.010 0.900 0.030 0.502 0.015
+ N7006-53 19.562 0.007 1.016 0.075 0.406 0.059
+ N7006-55 19.609 0.041 1.054 0.088 0.800 0.057
+ N7006-56 17.544 0.006 0.979 0.010 0.546 0.006
+ N7006-57 18.943 0.019 0.573 0.035 0.356 0.035
+ N7006-60 16.587 0.005 1.254 0.015 0.681 0.004
+ N7006-61 18.812 0.016 0.750 0.028 0.373 0.027
+ N7006-65 17.585 0.013 0.941 0.013 0.537 0.010
+ N7006-66 17.225 0.007 0.836 0.008 0.436 0.008
+ N7006-68 17.601 0.011 1.042 0.014 0.578 0.013
+ N7006-69 18.631 0.014 0.673 0.030 0.419 0.026
+ N7006-75 18.631 0.050 0.566 0.029 0.324 0.029
+ N7006-79 19.021 0.026 0.480 0.054 0.281 0.037
+ N7006-86 16.815 0.005 1.211 0.012 0.663 0.007
+ N7006-89 13.854 0.012 0.819 0.005 0.452 0.007
+ N7006-93 19.227 0.015 0.139 0.062 -0.179 0.042
+ N7006-97 18.405 0.020 0.656 0.048 0.400 0.020
+ N7006-102 18.922 0.016 0.429 0.025 0.189 0.028
+ N7006-109 19.122 0.021 0.860 0.159 0.391 0.047
+ N7006-110 17.479 0.013 1.033 0.017 0.617 0.014
+ N7006-111 17.018 0.010 1.175 0.013 0.627 0.005
+ N7006-112 13.972 0.010 1.087 0.008 0.585 0.004
+ N7006-115 18.970 0.023 1.312 0.042 0.701 0.030
+ N7006-117 18.602 0.015 0.626 0.029 0.387 0.026
+ N7006-119 18.844 0.015 0.254 0.048 0.068 0.022
+ N7006-122 18.984 0.054 0.553 0.095 0.349 0.073
+ N7006-124 18.111 0.033 0.803 0.034 0.457 0.034
+ N7006-127 17.653 0.011 1.005 0.027 0.589 0.013
+ N7006-132 16.919 0.010 1.091 0.012 0.574 0.008
+ N7006-134 15.217 0.005 0.955 0.006 0.536 0.003
+ N7006-148 18.809 0.017 0.603 0.056 0.400 0.029
+ N7006-150 19.101 0.033 0.128 0.064 -0.034 0.098
+ N7006-153 18.753 0.019 0.561 0.017 0.332 0.016
+ N7006-157 18.324 0.033 0.753 0.018 0.420 0.006
+ N7006-162 18.153 0.022 0.787 0.031 0.417 0.019
+ N7006-163 18.712 0.013 0.201 0.028 0.188 0.017
+ N7006-164 18.917 0.036 1.080 0.055 0.507 0.040
+ N7006-165 18.690 0.021 0.229 0.030 0.131 0.021
+ N7006-166 17.464 0.010 1.019 0.015 0.560 0.009
+ N7006-167 19.926 0.046 0.720 0.018 0.344 0.048
+ N7006-168 18.820 0.014 0.892 0.031 0.518 0.015
+ N7006-169 18.138 0.008 0.966 0.027 0.544 0.009
+ N7006-170 16.257 0.004 1.390 0.011 0.730 0.003
+ N7006-173 19.735 0.044 0.727 0.061 0.536 0.095
+ N7006-175 18.800 0.016 0.519 0.011 0.361 0.030
+ N7006-176 18.985 0.022 0.610 0.033 0.392 0.025
+ N7006-177 18.444 0.014 0.894 0.026 0.472 0.018
+ N7006-179 17.945 0.012 0.802 0.020 0.493 0.014
+ N7006-182 17.865 0.012 0.870 0.026 0.509 0.010
+ N7006-183 16.270 0.004 1.180 0.008 0.638 0.003
+ N7006-184 17.664 0.015 0.901 0.016 0.529 0.012
+ N7006-185 19.882 0.022 0.961 0.134 0.590 0.039
+ N7006-186 19.448 0.038 0.816 0.059 0.554 0.045
+ N7006-187 18.738 0.027 0.918 0.019 0.463 0.026
+ N7006-188 16.637 0.006 0.959 0.018 0.523 0.009
+ N7006-189 18.884 0.026 0.165 0.033 0.086 0.069
+ N7006-191 18.746 0.015 0.721 0.032 0.345 0.023
+ N7006-192 19.548 0.037 1.202 0.072 0.390 0.055
+ N7006-193 19.370 0.020 1.092 0.046 0.591 0.038
+ N7006-194 19.328 0.048 0.836 0.077 0.405 0.085
+ N7006-196 16.679 0.007 0.943 0.006 0.526 0.006
+ N7006-198 19.420 0.027 1.131 0.040 1.003 0.018
+ N7006-199 16.721 0.005 0.655 0.023 0.402 0.015
+ N7006-200 18.848 0.024 0.677 0.042 0.372 0.038
+ N7006-202 18.843 0.009 0.636 0.030 0.377 0.014
+ N7006-203 19.145 0.024 0.925 0.021 0.587 0.037
+ N7006-205 19.420 0.026 0.733 0.040 0.486 0.038
+ N7006-206 19.687 0.063 0.684 0.068 0.493 0.020
+ N7006-207 17.944 0.013 0.893 0.027 0.536 0.021
+ N7006-208 19.697 0.032 0.944 0.084 0.382 0.056
+ N7006-209 14.907 0.008 0.992 0.006 0.541 0.005
+ N7006-212 18.846 0.009 0.651 0.021 0.274 0.026
+ N7006-213 18.362 0.046 0.874 0.010 0.346 0.034
+ N7006-214 17.970 0.011 0.889 0.045 0.537 0.016
+ N7006-215 19.063 0.026 0.476 0.027 0.210 0.032
+#
+# NGC 7790
+#
+ N7790_1 13.029 0.005 0.438 0.004 0.285 0.006
+ N7790_2 17.037 0.022 1.485 0.019 0.871 0.020
+ N7790_3 17.538 0.019 0.954 0.018 0.597 0.022
+ N7790_4 12.994 0.008 0.404 0.005 0.249 0.006
+ N7790_5 15.885 0.003 0.552 0.010 0.286 0.010
+ N7790_6 18.125 0.018 0.890 0.032 0.627 0.031
+ N7790_7 18.298 0.057 1.340 0.219 0.628 0.044
+ N7790_8 16.308 0.004 0.661 0.010 0.394 0.022
+ N7790_9 17.120 0.023 1.004 0.022 0.592 0.014
+ N7790_10 17.577 0.017 0.928 0.025 0.548 0.017
+ N7790_11 16.993 0.018 0.864 0.016 0.539 0.020
+ N7790_12 18.070 0.023 0.964 0.042 0.615 0.028
+ N7790_14 17.968 0.025 1.601 0.033 0.918 0.034
+ N7790_15 18.484 0.028 1.349 0.089 0.671 0.036
+ N7790_16 15.941 0.006 0.591 0.012 0.338 0.009
+ N7790_17 15.732 0.006 0.517 0.011 0.289 0.005
+ N7790_18 18.332 0.029 1.214 0.074 0.630 0.049
+ N7790_20 15.696 0.003 0.548 0.005 0.316 0.007
+ N7790_21 16.029 0.007 0.551 0.008 0.289 0.009
+ N7790_22 15.766 0.007 1.449 0.012 0.859 0.008
+ N7790_23 14.997 0.006 1.596 0.011 0.914 0.005
+ N7790_24 16.622 0.012 0.666 0.009 0.377 0.019
+ N7790_25 15.791 0.006 0.972 0.013 0.543 0.008
+ N7790_26 16.715 0.013 0.805 0.011 0.448 0.026
+ N7790_27 17.575 0.025 0.923 0.022 0.523 0.027
+ N7790_28 16.919 0.014 0.764 0.019 0.434 0.017
+ N7790_29 13.305 0.006 0.391 0.004 0.248 0.005
+ N7790_30 13.474 0.006 0.406 0.004 0.251 0.005
+ N7790_31 13.597 0.003 0.445 0.005 0.287 0.004
+ N7790_32 15.402 0.007 0.594 0.010 0.353 0.006
+ N7790_34 17.724 0.018 0.898 0.015 0.555 0.023
+ N7790_35 18.391 0.055 0.985 0.063 0.680 0.063
+ N7790_36 14.526 0.004 0.485 0.004 0.299 0.005
+ N7790_37 14.724 0.004 0.467 0.004 0.282 0.004
+ N7790_38 16.132 0.007 0.647 0.010 0.374 0.010
+ N7790_39 17.622 0.014 1.169 0.025 0.662 0.019
+ N7790_40 17.740 0.014 1.217 0.031 0.726 0.011
+ N7790_41 17.709 0.015 0.892 0.020 0.526 0.025
+ N7790_42 17.589 0.025 1.129 0.033 0.669 0.020
+ N7790_43 18.317 0.027 1.016 0.037 0.603 0.036
+ N7790_44 18.388 0.049 1.147 0.072 0.691 0.043
+ N7790_45 15.778 0.007 0.561 0.010 0.312 0.007
+ N7790_46 17.901 0.022 1.046 0.017 0.644 0.022
+ N7790_47 18.377 0.031 1.229 0.040 0.827 0.047
+ N7790_48 15.261 0.004 0.857 0.008 0.519 0.004
+ N7790_49 16.573 0.010 1.687 0.021 1.008 0.013
+ N7790_50 17.896 0.020 1.714 0.060 1.005 0.019
+ N7790_51 14.430 0.004 0.419 0.004 0.251 0.004
+ N7790_52 17.564 0.018 1.661 0.034 1.026 0.018
+ N7790_53 16.323 0.012 0.626 0.010 0.343 0.009
+ N7790_54 16.559 0.010 1.003 0.023 0.612 0.011
+ N7790_55 17.949 0.018 0.985 0.033 0.563 0.026
+ N7790_56 18.301 0.027 0.874 0.042 0.579 0.038
+ N7790_57 18.788 0.029 1.177 0.093 0.691 0.033
+ N7790_58 15.294 0.003 0.610 0.005 0.350 0.005
+ N7790_59 15.976 0.006 0.559 0.005 0.315 0.007
+ N7790_60 16.804 0.014 1.177 0.021 0.640 0.010
+ N7790_61 18.636 0.024 1.030 0.071 0.493 0.054
+ N7790_62 15.423 0.004 1.667 0.005 0.974 0.003
+ N7790_63 18.554 0.043 1.179 0.096 0.546 0.070
+ N7790_64 18.733 0.036 1.293 0.109 0.594 0.045
+ N7790_65 16.045 0.005 0.709 0.005 0.409 0.008
+ N7790_66 15.939 0.006 0.572 0.009 0.328 0.010
+ N7790_67 17.013 0.012 0.859 0.015 0.522 0.013
+ N7790_68 17.689 0.021 1.114 0.031 0.668 0.010
+ N7790_69 17.876 0.016 1.032 0.033 0.586 0.021
+ N7790_70 18.407 0.022 1.160 0.063 0.688 0.030
+ N7790_71 18.429 0.047 1.331 0.078 0.654 0.054
+ N7790_72 14.248 0.005 0.541 0.004 0.335 0.004
+ N7790_73 16.161 0.007 1.144 0.010 0.634 0.007
+ N7790_74 17.407 0.024 0.960 0.030 0.596 0.016
+ N7790_75 17.898 0.020 0.944 0.036 0.601 0.026
+ N7790_76 18.194 0.054 0.745 0.061 0.414 0.047
+ N7790_77 16.012 0.005 0.726 0.009 0.445 0.008
+ N7790_78 18.025 0.023 0.927 0.053 0.572 0.037
+ N7790_79 17.927 0.024 1.260 0.053 0.712 0.029
+ N7790_80 15.616 0.004 0.541 0.006 0.297 0.006
+ N7790_81 17.374 0.018 1.668 0.026 0.971 0.018
+ N7790_82 13.152 0.006 0.489 0.004 0.271 0.005
+ N7790_83 16.078 0.005 0.792 0.007 0.467 0.009
+ N7790_84 18.485 0.066 1.182 0.078 0.831 0.051
+ N7790_85 16.685 0.018 0.967 0.020 0.574 0.019
+ N7790_86 16.724 0.010 0.995 0.006 0.617 0.012
+ N7790_87 17.860 0.014 0.861 0.031 0.557 0.024
+ N7790_88 15.795 0.004 0.993 0.004 0.566 0.004
+ N7790_89 18.709 0.041 0.975 0.082 0.713 0.029
+ N7790_90 17.654 0.014 0.895 0.021 0.566 0.020
+ N7790_91 18.229 0.031 1.136 0.059 0.619 0.038
+ N7790_92 18.518 0.043 1.000 0.083 0.597 0.069
+ N7790_93 18.066 0.016 1.327 0.042 0.822 0.024
+ N7790_94 16.129 0.008 0.694 0.007 0.422 0.006
+ N7790_95 15.829 0.006 0.583 0.007 0.341 0.007
+ N7790_96 15.787 0.009 0.708 0.004 0.416 0.006
+ N7790_97 13.189 0.005 1.491 0.005 0.819 0.004
+ N7790_98 14.126 0.003 0.800 0.003 0.474 0.003
+ N7790_99 16.761 0.018 0.791 0.017 0.435 0.009
+ N7790_100 17.820 0.021 1.143 0.034 0.692 0.027
+ N7790_101 18.078 0.021 1.005 0.037 0.634 0.033
+ N7790_103 16.761 0.010 0.779 0.012 0.436 0.008
+ N7790_104 15.227 0.006 0.538 0.006 0.318 0.007
+ N7790_105 15.704 0.005 1.896 0.015 1.092 0.007
+ N7790_106 17.433 0.019 1.139 0.021 0.679 0.017
+ N7790_107 15.362 0.005 1.939 0.013 1.116 0.007
+ N7790_108 17.175 0.016 1.147 0.024 0.654 0.016
+ N7790_109 17.433 0.016 0.997 0.024 0.599 0.029
+ N7790_110 16.683 0.019 1.145 0.020 0.717 0.016
+ N7790_111 18.598 0.029 1.055 0.040 0.668 0.032
+ N7790_112 16.528 0.006 1.119 0.014 0.668 0.009
+ N7790_113 14.868 0.004 0.484 0.005 0.316 0.005
+ N7790_114 17.459 0.015 1.037 0.020 0.617 0.016
+ N7790_115 17.616 0.019 1.142 0.024 0.668 0.025
+ N7790_116 17.833 0.016 1.593 0.039 0.988 0.024
+ N7790_117 18.177 0.015 1.034 0.052 0.646 0.060
+ N7790_119 18.285 0.025 0.943 0.061 0.612 0.022
+ N7790_121 17.994 0.038 1.005 0.091 0.580 0.035
+ N7790_122 18.509 0.022 1.674 0.190 1.284 0.030
+ N7790_123 15.671 0.007 1.447 0.015 0.876 0.008
+ N7790_124 18.451 0.041 1.092 0.055 0.634 0.042
+ N7790_125 17.307 0.020 1.093 0.039 0.584 0.016
+ N7790_126 17.629 0.011 0.954 0.016 0.564 0.021
+ N7790_127 17.830 0.025 1.092 0.056 0.650 0.021
diff --git a/noao/digiphot/photcal/catalogs/onlandolt.dat b/noao/digiphot/photcal/catalogs/onlandolt.dat
new file mode 100644
index 00000000..62773b2e
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/onlandolt.dat
@@ -0,0 +1,526 @@
+ TPHE_A 00:30:09 -46:31:22 14.651 0.793 0.380 0.435 0.405 0.841 29 12 0.00279 0.00464 0.00706 0.00186 0.00353 0.00316
+ TPHE_B 00:30:16 -46:27:55 12.334 0.405 0.156 0.262 0.271 0.535 29 17 0.01151 0.00260 0.00390 0.00204 0.00186 0.00353
+ TPHE_C 00:30:17 -46:32:34 14.376 -0.298 -1.217 -0.148 -0.211 -0.360 39 23 0.00224 0.00240 0.00432 0.00384 0.01329 0.01489
+ TPHE_D 00:30:18 -46:31:11 13.118 1.551 1.871 0.849 0.810 1.663 37 23 0.00329 0.00296 0.01184 0.00148 0.00230 0.00296
+ TPHE_E 00:30:19 -46:24:36 11.630 0.443 -0.103 0.276 0.283 0.564 34 8 0.00171 0.00120 0.00240 0.00069 0.00154 0.00189
+ TPHE_F 00:30:50 -46:33:33 12.474 0.855 0.532 0.492 0.435 0.926 5 3 0.00045 0.00581 0.01610 0.00045 0.00402 0.00358
+ TPHE_G 00:31:05 -46:22:43 10.442 1.546 1.915 0.934 1.085 2.025 5 3 0.00045 0.00134 0.00358 0.00045 0.00089 0.00089
+ PG0029+024 00:31:50 +02:38:26 15.268 0.362 -0.184 0.251 0.337 0.593 5 2 0.00939 0.01744 0.01118 0.01610 0.01252 0.00671
+ PG0039+049 00:42:05 +05:09:44 12.877 -0.019 -0.871 0.067 0.097 0.164 4 3 0.00200 0.00300 0.00550 0.00350 0.00550 0.00450
+ 92_309 00:53:14 +00:46:06 13.842 0.513 -0.024 0.326 0.325 0.652 2 1 0.00354 0.00566 0.00283 0.00141 0.00354 0.00141
+ 92_235 00:53:16 +00:36:22 10.595 1.638 1.984 0.894 0.911 1.806 5 2 0.00581 0.00447 0.00984 0.00313 0.00447 0.00671
+ 92_322 00:53:47 +00:47:41 12.676 0.528 -0.002 0.302 0.305 0.608 2 1 0.00071 0.00495 0.00283 0.00141 0.00071 0.00071
+ 92_245 00:54:16 +00:39:56 13.818 1.418 1.189 0.929 0.907 1.836 21 8 0.00284 0.00786 0.03011 0.00240 0.00240 0.00284
+ 92_248 00:54:31 +00:40:20 15.346 1.128 1.289 0.690 0.553 1.245 4 2 0.02550 0.01600 0.09550 0.02150 0.01450 0.01750
+ 92_249 00:54:34 +00:41:10 14.325 0.699 0.240 0.399 0.370 0.770 17 8 0.00485 0.00849 0.01140 0.00461 0.00655 0.00728
+ 92_250 00:54:37 +00:39:01 13.178 0.814 0.480 0.446 0.394 0.840 20 9 0.00224 0.00335 0.00738 0.00224 0.00224 0.00291
+ 92_330 00:54:44 +00:43:31 15.073 0.568 -0.115 0.331 0.334 0.666 2 1 0.01414 0.02970 0.01626 0.03041 0.00000 0.03041
+ 92_252 00:54:48 +00:39:28 14.932 0.517 -0.140 0.326 0.332 0.666 41 18 0.00328 0.00547 0.00818 0.00475 0.00715 0.00678
+ 92_253 00:54:52 +00:40:24 14.085 1.131 0.955 0.719 0.616 1.337 39 17 0.00320 0.00624 0.02210 0.00272 0.00432 0.00496
+ 92_335 00:55:00 +00:44:18 12.523 0.672 0.208 0.380 0.338 0.719 2 1 0.00071 0.00283 0.00495 0.00000 0.00141 0.00141
+ 92_339 00:55:03 +00:44:16 15.579 0.449 -0.177 0.306 0.339 0.645 19 8 0.00872 0.01170 0.01262 0.01170 0.01973 0.01767
+ 92_342 00:55:10 +00:43:19 11.613 0.436 -0.042 0.266 0.270 0.538 48 34 0.00130 0.00115 0.00231 0.00130 0.00087 0.00159
+ 92_188 00:55:10 +00:23:17 14.751 1.050 0.751 0.679 0.573 1.254 14 6 0.00962 0.01871 0.05506 0.00508 0.00428 0.00882
+ 92_409 00:55:14 +00:56:12 10.627 1.138 1.136 0.734 0.625 1.361 5 3 0.00313 0.00268 0.00850 0.00224 0.00268 0.00179
+ 92_410 00:55:15 +01:01:54 14.984 0.398 -0.134 0.239 0.242 0.484 27 13 0.00577 0.00635 0.00828 0.00520 0.01020 0.01174
+ 92_412 00:55:16 +01:01:58 15.036 0.457 -0.152 0.285 0.304 0.589 27 13 0.00539 0.00770 0.01328 0.00693 0.00943 0.01058
+ 92_259 00:55:22 +00:40:34 14.997 0.642 0.108 0.370 0.452 0.821 3 1 0.01155 0.02194 0.02136 0.01905 0.02021 0.01501
+ 92_345 00:55:24 +00:51:11 15.216 0.745 0.121 0.465 0.476 0.941 2 1 0.00071 0.00141 0.03394 0.00566 0.01131 0.00566
+ 92_347 00:55:26 +00:50:53 15.752 0.543 -0.097 0.339 0.318 0.658 4 2 0.02550 0.02800 0.03550 0.02950 0.07550 0.09950
+ 92_260 00:55:29 +00:37:12 15.071 1.162 1.115 0.719 0.608 1.328 9 4 0.00900 0.00933 0.04767 0.00700 0.00567 0.00800
+ 92_348 00:55:30 +00:44:39 12.109 0.598 0.056 0.345 0.341 0.688 4 2 0.00100 0.00150 0.00350 0.00150 0.00050 0.00200
+ 92_417 00:55:32 +00:53:12 15.922 0.477 -0.185 0.351 0.305 0.657 6 3 0.01266 0.01878 0.03184 0.01511 0.06777 0.06246
+ 92_263 00:55:40 +00:36:23 11.782 1.048 0.843 0.563 0.522 1.087 52 35 0.00111 0.00139 0.00333 0.00097 0.00111 0.00153
+ 92_497 00:55:54 +01:11:46 13.642 0.729 0.257 0.404 0.378 0.783 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 92_498 00:55:57 +01:10:44 14.408 1.010 0.794 0.648 0.531 1.181 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 92_500 00:55:58 +01:10:29 15.841 1.003 0.211 0.738 0.599 1.338 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 92_425 00:55:59 +00:53:03 13.941 1.191 1.173 0.755 0.627 1.384 36 19 0.00383 0.00667 0.01150 0.00233 0.00267 0.00383
+ 92_501 00:56:00 +01:10:57 12.958 0.610 0.068 0.345 0.331 0.677 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 92_426 00:56:00 +00:52:58 14.466 0.729 0.184 0.412 0.396 0.809 8 4 0.00990 0.01308 0.02934 0.00778 0.01237 0.01202
+ 92_355 00:56:06 +00:50:52 14.965 1.164 1.201 0.759 0.645 1.406 15 7 0.00878 0.01239 0.04648 0.00697 0.00516 0.00904
+ 92_427 00:56:07 +01:00:23 14.953 0.809 0.352 0.462 2.922 3.275 2 1 0.00212 0.00849 0.02333 0.00141 0.01131 0.00919
+ 92_502 00:56:08 +01:04:29 11.812 0.486 -0.095 0.284 0.292 0.576 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 92_430 00:56:16 +00:53:21 14.440 0.567 -0.040 0.338 0.338 0.676 35 18 0.00406 0.00524 0.00811 0.00287 0.00490 0.00507
+ 92_276 00:56:27 +00:41:57 12.036 0.629 0.067 0.368 0.357 0.726 21 11 0.00393 0.00218 0.00393 0.00306 0.00306 0.00524
+ 92_282 00:56:47 +00:38:34 12.969 0.318 -0.038 0.201 0.221 0.422 27 15 0.00308 0.00231 0.00443 0.00173 0.00231 0.00327
+ 92_508 00:56:51 +01:09:40 11.679 0.529 -0.047 0.318 0.320 0.639 3 2 0.00346 0.00462 0.00289 0.00577 0.00289 0.00289
+ 92_507 00:56:51 +01:06:03 11.332 0.932 0.688 0.507 0.461 0.969 3 2 0.00058 0.00462 0.00058 0.00115 0.00058 0.00115
+ 92_364 00:56:53 +00:44:07 11.673 0.607 -0.037 0.356 0.357 0.714 4 2 0.00150 0.00150 0.00850 0.00450 0.00100 0.00550
+ 92_433 00:56:54 +01:00:47 11.667 0.655 0.110 0.367 0.348 0.716 3 2 0.00058 0.00346 0.01155 0.00289 0.00173 0.00231
+ 92_288 00:57:17 +00:36:52 11.630 0.855 0.472 0.489 0.441 0.931 48 33 0.00144 0.00144 0.00217 0.00115 0.00087 0.00130
+ F_11 01:04:22 +04:13:37 12.065 -0.240 -0.978 -0.120 -0.142 -0.261 63 47 0.00088 0.00113 0.00239 0.00113 0.00164 0.00214
+ F_16 01:54:08 -06:42:54 12.406 -0.012 0.009 -0.003 0.002 -0.001 45 32 0.00134 0.00134 0.00268 0.00149 0.00179 0.00209
+ 93_407 01:54:37 +00:53:59 11.971 0.852 0.564 0.487 0.421 0.908 5 3 0.00268 0.00313 0.01342 0.00313 0.00358 0.00268
+ 93_317 01:54:38 +00:43:11 11.546 0.488 -0.055 0.293 0.298 0.592 37 28 0.00066 0.00082 0.00181 0.00066 0.00082 0.00082
+ 93_333 01:55:05 +00:45:54 12.011 0.832 0.436 0.469 0.422 0.892 38 28 0.00146 0.00178 0.00260 0.00097 0.00114 0.00162
+ 93_424 01:55:26 +00:56:54 11.620 1.083 0.943 0.554 0.502 1.058 40 29 0.00095 0.00142 0.00411 0.00079 0.00079 0.00079
+ G3_33 02:00:09 +13:04:04 12.298 1.804 1.316 1.355 1.751 3.099 11 5 0.00302 0.00965 0.01447 0.00392 0.00452 0.00482
+PG0220+132B 02:23:34 +13:28:11 14.216 0.937 0.319 0.562 0.496 1.058 3 2 0.00808 0.03753 0.05831 0.00577 0.01270 0.00693
+ PG0220+132 02:23:38 +13:27:42 14.760 -0.132 -0.922 -0.050 -0.120 -0.170 5 3 0.00626 0.01118 0.01029 0.00984 0.01699 0.02639
+PG0220+132A 02:23:39 +13:27:37 15.771 0.783 -0.339 0.514 0.481 0.995 3 2 0.01501 0.06986 0.05369 0.01097 0.05889 0.04792
+ F_22 02:30:17 +05:15:51 12.799 -0.054 -0.806 -0.103 -0.105 -0.207 60 50 0.00142 0.00168 0.00297 0.00116 0.00284 0.00349
+PG0231+051E 02:33:28 +05:19:48 13.804 0.677 0.201 0.390 0.369 0.757 3 2 0.00462 0.00404 0.00751 0.00346 0.00173 0.00231
+PG0231+051D 02:33:33 +05:19:32 14.027 1.088 1.046 0.675 0.586 1.256 3 2 0.00289 0.00751 0.03118 0.00808 0.00635 0.01097
+PG0231+051A 02:33:40 +05:17:41 12.772 0.710 0.270 0.405 0.394 0.799 7 4 0.00076 0.00151 0.00302 0.00113 0.00302 0.00302
+PG0231+051C 02:33:41 +05:20:22 13.702 0.671 0.114 0.399 0.385 0.783 2 1 0.00141 0.00778 0.01485 0.00283 0.00636 0.00849
+ PG0231+051 02:33:41 +05:18:43 16.105 -0.329 -1.192 -0.162 -0.371 -0.534 7 4 0.00680 0.00832 0.00454 0.02759 0.10659 0.12208
+PG0231+051B 02:33:45 +05:17:33 14.735 1.448 1.342 0.954 0.998 1.951 7 4 0.00302 0.00718 0.01776 0.00340 0.00265 0.00567
+ F_24 02:35:08 +03:43:57 12.411 -0.203 -1.169 0.090 0.364 0.451 76 65 0.00161 0.00115 0.00298 0.00149 0.00149 0.00206
+ 94_171 02:53:38 +00:17:34 12.659 0.817 0.304 0.480 0.483 0.964 18 9 0.00283 0.00354 0.00448 0.00354 0.00189 0.00377
+ 94_296 02:55:20 +00:28:29 12.255 0.750 0.235 0.415 0.387 0.803 2 1 0.00212 0.00141 0.00141 0.00212 0.00212 0.00000
+ 94_394 02:56:14 +00:35:25 12.273 0.545 -0.047 0.344 0.330 0.676 2 1 0.00283 0.00141 0.00141 0.00071 0.00141 0.00071
+ 94_401 02:56:31 +00:40:21 14.293 0.638 0.098 0.389 0.369 0.759 2 1 0.00141 0.00283 0.01202 0.00636 0.00354 0.00990
+ 94_242 02:57:21 +00:18:54 11.728 0.301 0.107 0.178 0.184 0.362 60 53 0.00116 0.00103 0.00219 0.00129 0.00103 0.00168
+ 94_251 02:57:46 +00:16:18 11.204 1.219 1.281 0.659 0.587 1.247 52 45 0.00097 0.00111 0.00333 0.00083 0.00069 0.00111
+ 94_702 02:58:13 +01:11:09 11.594 1.418 1.621 0.756 0.673 1.430 64 56 0.00100 0.00137 0.00463 0.00088 0.00088 0.00112
+ GD_50 03:48:50 -00:58:33 14.063 -0.276 -1.191 -0.145 -0.180 -0.325 43 24 0.00320 0.00366 0.00564 0.00427 0.00762 0.00976
+ 95_15 03:52:40 -00:05:03 11.302 0.712 0.157 0.424 0.385 0.809 2 1 0.00071 0.00071 0.00354 0.00141 0.00141 0.00283
+ 95_301 03:52:41 +00:31:37 11.216 1.290 1.296 0.692 0.620 1.311 47 40 0.00146 0.00146 0.00481 0.00088 0.00073 0.00131
+ 95_16 03:52:41 -00:04:47 14.313 1.306 1.322 0.796 0.676 1.472 4 2 0.01200 0.01600 0.03100 0.01350 0.00600 0.00900
+ 95_302 03:52:42 +00:31:37 11.694 0.825 0.447 0.471 0.420 0.891 29 20 0.00204 0.00149 0.00557 0.00130 0.00111 0.00167
+ 95_96 03:52:54 +00:00:37 10.010 0.147 0.072 0.079 0.095 0.174 70 55 0.00155 0.00120 0.00323 0.00096 0.00108 0.00143
+ 95_97 03:52:57 -00:00:01 14.818 0.906 0.380 0.522 0.546 1.068 2 1 0.00071 0.02263 0.02121 0.00283 0.01909 0.02121
+ 95_98 03:53:00 +00:03:11 14.448 1.181 1.092 0.723 0.620 1.342 2 1 0.00071 0.00141 0.01768 0.00919 0.00707 0.01626
+ 95_100 03:53:01 +00:00:31 15.633 0.791 0.051 0.538 0.421 0.961 3 1 0.02829 0.07852 0.11316 0.01443 0.05716 0.04388
+ 95_101 03:53:04 +00:03:12 12.677 0.778 0.263 0.436 0.426 0.863 2 1 0.00283 0.00283 0.00990 0.00636 0.00636 0.01202
+ 95_102 03:53:07 +00:01:28 15.622 1.001 0.162 0.448 0.618 1.065 3 1 0.03349 0.08025 0.06120 0.01155 0.05081 0.06178
+ 95_252 03:53:11 +00:27:37 15.394 1.452 1.178 0.816 0.747 1.566 6 3 0.00653 0.02572 0.04327 0.00898 0.00857 0.01306
+ 95_190 03:53:13 +00:16:39 12.627 0.287 0.236 0.195 0.220 0.415 44 22 0.00196 0.00166 0.00392 0.00166 0.00151 0.00211
+ 95_193 03:53:20 +00:16:50 14.338 1.211 1.239 0.748 0.616 1.366 20 10 0.00492 0.00626 0.02549 0.00425 0.00335 0.00581
+ 95_105 03:53:21 -00:00:01 13.574 0.976 0.627 0.550 0.536 1.088 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 95_107 03:53:25 +00:02:36 16.275 1.324 1.115 0.947 0.962 1.907 2 1 0.00354 0.10677 0.17324 0.04384 0.02263 0.02121
+ 95_106 03:53:25 +00:01:40 15.137 1.251 0.369 0.394 0.508 0.903 2 1 0.00636 0.06152 0.02404 0.15203 0.01273 0.14071
+ 95_112 03:53:40 -00:00:54 15.502 0.662 0.077 0.605 0.620 1.227 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 95_41 03:53:41 -00:02:12 14.060 0.903 0.297 0.589 0.585 1.176 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 95_317 03:53:44 +00:30:06 13.449 1.320 1.120 0.768 0.708 1.476 24 11 0.00347 0.00674 0.01306 0.00327 0.00122 0.00347
+ 95_42 03:53:44 -00:04:08 15.606 -0.215 -1.111 -0.119 -0.180 -0.300 41 18 0.00578 0.00734 0.00640 0.00750 0.02686 0.02764
+ 95_263 03:53:47 +00:26:57 12.679 1.500 1.559 0.801 0.711 1.513 19 10 0.00298 0.00344 0.00941 0.00229 0.00115 0.00275
+ 95_115 03:53:48 -00:00:29 14.680 0.836 0.096 0.577 0.579 1.157 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 95_43 03:53:49 -00:02:42 10.803 0.510 -0.016 0.308 0.316 0.624 16 10 0.00225 0.00200 0.00275 0.00275 0.00175 0.00350
+ 95_271 03:54:17 +00:19:08 13.669 1.287 0.916 0.734 0.717 1.453 15 7 0.00568 0.00800 0.01265 0.00232 0.00232 0.00361
+ 95_328 03:54:19 +00:36:47 13.525 1.532 1.298 0.908 0.868 1.776 23 11 0.00292 0.00542 0.01856 0.00271 0.00146 0.00313
+ 95_329 03:54:24 +00:37:25 14.617 1.184 1.093 0.766 0.642 1.410 13 6 0.00471 0.01026 0.03106 0.00444 0.00943 0.00888
+ 95_330 03:54:31 +00:29:23 12.174 1.999 2.233 1.166 1.100 2.268 47 23 0.00248 0.00263 0.01371 0.00204 0.00160 0.00277
+ 95_275 03:54:44 +00:27:37 13.479 1.763 1.740 1.011 0.931 1.944 40 20 0.00285 0.00538 0.02008 0.00221 0.00158 0.00253
+ 95_276 03:54:46 +00:26:13 14.118 1.225 1.218 0.748 0.646 1.395 14 7 0.00615 0.01016 0.02165 0.00401 0.00321 0.00508
+ 95_60 03:54:49 -00:06:46 13.429 0.776 0.197 0.464 0.449 0.914 20 10 0.00313 0.00313 0.00604 0.00291 0.00246 0.00335
+ 95_218 03:54:50 +00:10:26 12.095 0.708 0.208 0.397 0.370 0.767 20 14 0.00335 0.00224 0.00335 0.00201 0.00201 0.00268
+ 95_132 03:54:51 +00:05:40 12.064 0.448 0.300 0.259 0.287 0.545 33 27 0.00226 0.00209 0.00574 0.00157 0.00174 0.00261
+ 95_62 03:55:00 -00:02:36 13.538 1.355 1.181 0.742 0.685 1.428 22 11 0.00298 0.00533 0.01364 0.00192 0.00192 0.00277
+ 95_137 03:55:04 +00:03:51 14.440 1.457 1.136 0.893 0.845 1.737 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 95_139 03:55:05 +00:03:32 12.196 0.923 0.677 0.562 0.476 1.039 3 2 0.00173 0.00462 0.01905 0.00231 0.00173 0.00346
+ 95_66 03:55:07 -00:09:12 12.892 0.715 0.167 0.426 0.438 0.864 2 1 0.00212 0.00707 0.00354 0.00071 0.00566 0.00495
+ 95_227 03:55:08 +00:14:54 15.779 0.771 0.034 0.515 0.552 1.067 14 7 0.01176 0.02886 0.04169 0.01149 0.01069 0.01497
+ 95_142 03:55:09 +00:01:39 12.927 0.588 0.097 0.371 0.375 0.745 22 11 0.00298 0.00298 0.00362 0.00192 0.00171 0.00277
+ 95_74 03:55:31 -00:08:54 11.531 1.126 0.686 0.600 0.567 1.165 39 34 0.00160 0.00128 0.00352 0.00128 0.00096 0.00128
+ 95_231 03:55:39 +00:11:02 14.216 0.452 0.297 0.270 0.290 0.560 26 13 0.00431 0.00451 0.00706 0.00451 0.00530 0.00765
+ 95_284 03:55:44 +00:25:27 13.669 1.398 1.073 0.818 0.766 1.586 20 9 0.00402 0.00783 0.02393 0.00268 0.00358 0.00492
+ 95_149 03:55:44 +00:07:23 10.938 1.593 1.564 0.874 0.811 1.685 17 11 0.00509 0.00388 0.00946 0.00243 0.00170 0.00291
+ 95_285 03:55:46 +00:23:59 15.561 0.937 0.703 0.607 0.602 1.210 2 1 0.00707 0.02546 0.06364 0.00707 0.00636 0.01344
+ 95_236 03:56:13 +00:09:02 11.491 0.736 0.162 0.420 0.411 0.831 35 31 0.00101 0.00135 0.00355 0.00118 0.00085 0.00152
+ 96_21 04:51:16 -00:14:30 12.182 0.490 -0.004 0.299 0.297 0.598 2 1 0.00283 0.00071 0.00283 0.00566 0.00141 0.00354
+ 96_36 04:51:43 -00:09:51 10.591 0.247 0.118 0.134 0.136 0.271 34 24 0.00137 0.00120 0.00343 0.00086 0.00086 0.00154
+ 96_737 04:52:35 +00:22:50 11.716 1.334 1.160 0.733 0.695 1.428 35 26 0.00203 0.00186 0.00524 0.00101 0.00085 0.00135
+ 96_409 04:52:58 +00:09:26 13.778 0.543 0.042 0.340 0.340 0.682 2 1 0.01061 0.00071 0.02404 0.00849 0.00495 0.01273
+ 96_83 04:52:59 -00:14:22 11.719 0.179 0.202 0.093 0.097 0.190 37 26 0.00132 0.00099 0.00460 0.00099 0.00132 0.00164
+ 96_235 04:53:19 -00:04:42 11.140 1.074 0.898 0.559 0.510 1.068 32 22 0.00141 0.00106 0.00283 0.00071 0.00088 0.00088
+ G97_42 05:28:01 +09:39:07 12.443 1.639 1.259 1.171 1.485 2.655 23 11 0.00167 0.00354 0.01856 0.00250 0.00313 0.00334
+ G102_22 05:42:05 +12:30:14 11.509 1.621 1.134 1.211 1.590 2.800 20 10 0.00134 0.00268 0.00738 0.00335 0.00313 0.00425
+ GD_71 05:52:28 +15:33:15 13.032 -0.249 -1.107 -0.137 -0.164 -0.302 86 73 0.00140 0.00129 0.00226 0.00140 0.00205 0.00259
+ 97_249 05:57:07 +00:01:34 11.733 0.648 0.100 0.369 0.353 0.723 69 62 0.00096 0.00084 0.00144 0.00060 0.00072 0.00096
+ 97_42 05:57:09 -00:10:50 12.448 1.626 1.208 1.160 1.485 2.641 2 1 0.00566 0.01556 0.01273 0.00707 0.00212 0.00566
+ 97_345 05:57:26 +00:20:48 11.608 1.655 1.680 0.928 0.844 1.771 23 14 0.00271 0.00396 0.01564 0.00209 0.00146 0.00292
+ 97_351 05:57:37 +00:14:05 9.781 0.202 0.096 0.124 0.141 0.264 102 83 0.00089 0.00079 0.00198 0.00069 0.00079 0.00099
+ 97_75 05:57:55 -00:09:07 11.483 1.872 2.100 1.047 0.952 1.999 20 12 0.00380 0.00470 0.01006 0.00291 0.00157 0.00380
+ 97_284 05:58:25 +00:05:35 10.788 1.363 1.087 0.774 0.725 1.500 77 68 0.00091 0.00103 0.00217 0.00068 0.00057 0.00103
+ 97_224 05:58:44 -00:04:50 14.085 0.910 0.341 0.553 0.547 1.102 2 1 0.01273 0.01768 0.00495 0.01202 0.01273 0.00000
+ 98_961 06:51:27 -00:15:15 13.089 1.283 1.003 0.701 0.662 1.362 2 1 0.00212 0.00071 0.00141 0.00212 0.00000 0.00212
+ 98_966 06:51:29 -00:16:05 14.001 0.469 0.357 0.283 0.331 0.613 2 1 0.00354 0.00141 0.00212 0.00141 0.01909 0.02051
+ 98_556 06:51:30 -00:24:30 14.137 0.338 0.126 0.196 0.243 0.437 6 3 0.00531 0.00531 0.01306 0.00572 0.00449 0.00898
+ 98_557 06:51:30 -00:24:45 14.780 1.397 1.072 0.755 0.741 1.494 2 1 0.00071 0.05445 0.02687 0.00919 0.02970 0.01980
+ 98_562 06:51:31 -00:18:37 12.185 0.522 -0.002 0.305 0.303 0.607 2 1 0.00283 0.00495 0.00354 0.00141 0.00141 0.00000
+ 98_563 06:51:32 -00:26:04 14.162 0.416 -0.190 0.294 0.317 0.610 10 5 0.00506 0.00854 0.00727 0.00443 0.00791 0.00822
+ 98_978 06:51:34 -00:11:06 10.572 0.609 0.094 0.349 0.322 0.671 46 38 0.00147 0.00088 0.00162 0.00074 0.00088 0.00118
+ 98_L1 06:51:39 -00:26:16 15.672 1.243 0.776 0.730 0.712 1.445 3 2 0.00751 0.04619 0.09757 0.01097 0.02540 0.03175
+ 98_L2 06:51:40 -00:20:49 15.859 1.340 1.497 0.754 0.572 1.327 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 98_581 06:51:40 -00:25:21 14.556 0.238 0.161 0.118 0.244 0.361 7 3 0.02457 0.02797 0.02003 0.01928 0.01965 0.01550
+ 98_580 06:51:40 -00:26:21 14.728 0.367 0.303 0.241 0.305 0.547 4 2 0.02550 0.01850 0.01850 0.01250 0.04600 0.03950
+ 98_L3 06:51:42 -00:14:56 14.614 1.936 1.837 1.091 1.047 2.142 4 2 0.01450 0.02650 0.14500 0.00900 0.00700 0.01100
+ 98_L4 06:51:42 -00:16:13 16.332 1.344 1.086 0.936 0.785 1.726 2 2 0.05798 0.03253 0.34295 0.02051 0.03677 0.05798
+ 98_1002 06:51:43 -00:15:31 14.568 0.574 -0.027 0.354 0.379 0.733 4 2 0.00550 0.00650 0.01100 0.00700 0.01250 0.01300
+ 98_590 06:51:43 -00:21:59 14.642 1.352 0.853 0.753 0.747 1.500 4 2 0.01100 0.01200 0.05250 0.00500 0.01050 0.01350
+ 98_614 06:51:49 -00:20:12 15.674 1.063 0.399 0.834 0.645 1.480 2 1 0.04243 0.04738 0.03111 0.02263 0.03677 0.05798
+ 98_618 06:51:50 -00:20:55 12.723 2.192 2.144 1.254 1.151 2.407 14 7 0.00508 0.00748 0.03074 0.00347 0.00321 0.00454
+ 98_624 06:51:52 -00:19:54 13.811 0.791 0.394 0.417 0.404 0.822 2 1 0.01414 0.02404 0.00424 0.00141 0.02121 0.01980
+ 98_626 06:51:53 -00:20:24 14.758 1.406 1.067 0.806 0.816 1.624 2 1 0.00707 0.00283 0.04384 0.00919 0.02051 0.01131
+ 98_627 06:51:53 -00:21:41 14.900 0.689 0.078 0.428 0.387 0.817 2 1 0.00636 0.01697 0.00849 0.00071 0.01273 0.01273
+ 98_634 06:51:56 -00:20:35 14.608 0.647 0.123 0.382 0.372 0.757 2 1 0.00424 0.00495 0.01273 0.01131 0.01768 0.00636
+ 98_642 06:51:59 -00:21:11 15.290 0.571 0.318 0.302 0.393 0.697 2 1 0.01909 0.04525 0.01202 0.01980 0.00212 0.01768
+ 98_185 06:52:02 -00:26:59 10.536 0.202 0.113 0.109 0.124 0.231 45 37 0.00179 0.00089 0.00328 0.00104 0.00134 0.00179
+ 98_646 06:52:03 -00:20:56 15.839 1.060 1.426 0.583 0.504 1.090 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 98_193 06:52:04 -00:26:56 10.030 1.180 1.152 0.615 0.537 1.153 44 35 0.00151 0.00075 0.00226 0.00106 0.00075 0.00151
+ 98_653 06:52:05 -00:17:57 9.539 -0.004 -0.099 0.009 0.008 0.017 65 50 0.00136 0.00037 0.00087 0.00074 0.00074 0.00112
+ 98_650 06:52:05 -00:19:18 12.271 0.157 0.110 0.080 0.086 0.166 31 20 0.00198 0.00144 0.00413 0.00162 0.00216 0.00269
+ 98_652 06:52:05 -00:21:36 14.817 0.611 0.126 0.276 0.339 0.618 2 1 0.01131 0.02970 0.01768 0.04525 0.02404 0.02263
+ 98_666 06:52:10 -00:23:12 12.732 0.164 -0.004 0.091 0.108 0.200 25 14 0.00340 0.00280 0.00420 0.00420 0.00300 0.00480
+ 98_671 06:52:12 -00:18:00 13.385 0.968 0.719 0.575 0.494 1.071 27 15 0.00366 0.00481 0.01078 0.00327 0.00346 0.00462
+ 98_670 06:52:12 -00:18:55 11.930 1.356 1.313 0.723 0.653 1.375 32 19 0.00159 0.00177 0.00583 0.00177 0.00124 0.00230
+ 98_676 06:52:14 -00:18:59 13.068 1.146 0.666 0.683 0.673 1.352 17 8 0.00315 0.00412 0.01067 0.00146 0.02183 0.00315
+ 98_675 06:52:14 -00:19:19 13.398 1.909 1.936 1.082 1.002 2.085 44 21 0.00256 0.00347 0.02834 0.00181 0.00181 0.00241
+ 98_L5 06:52:16 -00:19:17 17.800 1.900 -0.100 3.100 2.600 5.800 6 3 0.16330 0.32660 0.44907 0.12247 0.04082 0.12247
+ 98_682 06:52:17 -00:19:20 13.749 0.632 0.098 0.366 0.352 0.717 13 7 0.00388 0.00388 0.00638 0.00166 0.00250 0.00388
+ 98_685 06:52:19 -00:19:57 11.954 0.463 0.096 0.290 0.280 0.570 22 14 0.00298 0.00213 0.00277 0.00235 0.00213 0.00341
+ 98_688 06:52:19 -00:23:12 12.754 0.293 0.245 0.158 0.180 0.337 21 11 0.00327 0.00240 0.00807 0.00371 0.00502 0.00742
+ 98_1082 06:52:20 -00:13:53 15.010 0.835 -0.001 0.485 0.619 1.102 3 1 0.00577 0.01386 0.02252 0.00289 0.01328 0.01617
+ 98_1087 06:52:21 -00:15:28 14.439 1.595 1.284 0.928 0.882 1.812 12 5 0.00404 0.01415 0.05918 0.00346 0.00491 0.00722
+ 98_1102 06:52:28 -00:13:21 12.113 0.314 0.089 0.193 0.195 0.388 15 8 0.00336 0.00258 0.00594 0.00258 0.00361 0.00516
+ 98_1112 06:52:35 -00:15:01 13.975 0.814 0.286 0.443 0.431 0.874 5 2 0.00671 0.00402 0.01521 0.00537 0.00313 0.00760
+ 98_1119 06:52:37 -00:14:11 11.878 0.551 0.069 0.312 0.299 0.611 7 4 0.00227 0.00378 0.00416 0.00189 0.00416 0.00454
+ 98_1124 06:52:38 -00:16:12 13.707 0.315 0.258 0.173 0.201 0.373 24 12 0.00347 0.00429 0.00796 0.00286 0.00510 0.00572
+ 98_1122 06:52:38 -00:16:43 14.090 0.595 -0.297 0.376 0.442 0.816 25 12 0.00340 0.00600 0.00740 0.00380 0.00280 0.00460
+ 98_724 06:52:38 -00:19:00 11.118 1.104 0.904 0.575 0.527 1.103 12 7 0.00346 0.00346 0.00520 0.00231 0.00231 0.00375
+ 98_733 06:52:40 -00:16:54 12.238 1.285 1.087 0.698 0.650 1.347 20 10 0.00335 0.00425 0.00604 0.00291 0.00224 0.00402
+ RU_149G 07:24:10 -00:30:49 12.829 0.541 0.033 0.322 0.322 0.645 18 12 0.00259 0.00401 0.00424 0.00212 0.00259 0.00401
+ RU_149A 07:24:12 -00:31:47 14.495 0.298 0.118 0.196 0.196 0.391 18 12 0.00660 0.00519 0.01108 0.00990 0.00849 0.01391
+ RU_149F 07:24:13 -00:30:01 13.471 1.115 1.025 0.594 0.538 1.132 19 11 0.00275 0.00780 0.02225 0.00206 0.00229 0.00344
+ RU_149 07:24:13 -00:31:58 13.866 -0.129 -0.779 -0.040 -0.068 -0.108 46 30 0.00221 0.00265 0.00310 0.00221 0.00619 0.00693
+ RU_149D 07:24:14 -00:31:41 11.480 -0.037 -0.287 0.021 0.008 0.029 18 11 0.00189 0.00212 0.00283 0.00118 0.00189 0.00236
+ RU_149C 07:24:16 -00:31:20 14.425 0.195 0.141 0.093 0.127 0.222 18 11 0.00519 0.00424 0.01108 0.00613 0.00990 0.01061
+ RU_149B 07:24:16 -00:32:01 12.642 0.662 0.151 0.374 0.354 0.728 15 10 0.00207 0.00336 0.00491 0.00181 0.00258 0.00284
+ RU_149E 07:24:17 -00:30:11 13.718 0.522 -0.007 0.321 0.314 0.637 12 8 0.00635 0.00491 0.00693 0.00346 0.00664 0.00866
+ RU_152F 07:27:25 -01:58:07 14.564 0.635 0.069 0.382 0.315 0.689 15 8 0.00516 0.00568 0.00955 0.00671 0.01756 0.02221
+ RU_152E 07:27:25 -01:58:47 12.362 0.042 -0.086 0.030 0.034 0.065 12 8 0.00144 0.00202 0.00202 0.00144 0.00231 0.00289
+ RU_152 07:27:29 -01:59:56 13.014 -0.190 -1.073 -0.057 -0.087 -0.145 40 25 0.00190 0.00237 0.00316 0.00237 0.00300 0.00379
+ RU_152B 07:27:30 -01:59:17 15.019 0.500 0.022 0.290 0.309 0.600 23 10 0.00459 0.00876 0.01814 0.00542 0.01752 0.02106
+ RU_152A 07:27:31 -01:59:40 14.341 0.543 -0.085 0.325 0.329 0.654 14 8 0.00615 0.00855 0.01684 0.00508 0.00935 0.01310
+ RU_152C 07:27:33 -01:58:56 12.222 0.573 -0.013 0.342 0.340 0.683 13 9 0.00250 0.00305 0.00333 0.00222 0.00194 0.00305
+ RU_152D 07:27:37 -01:57:54 11.076 0.875 0.491 0.473 0.449 0.921 14 10 0.00134 0.00160 0.00241 0.00107 0.00187 0.00187
+ 99_438 07:55:54 -00:16:32 9.398 -0.155 -0.725 -0.059 -0.081 -0.141 105 87 0.00137 0.00068 0.00137 0.00068 0.00068 0.00088
+ 99_447 07:56:07 -00:20:23 9.417 -0.067 -0.225 -0.032 -0.041 -0.074 70 59 0.00084 0.00084 0.00143 0.00084 0.00084 0.00108
+ 100_241 08:52:35 -00:39:32 10.139 0.157 0.101 0.078 0.085 0.163 53 43 0.00110 0.00069 0.00165 0.00055 0.00055 0.00082
+ 100_162 08:53:15 -00:43:12 9.150 1.276 1.497 0.649 0.553 1.203 72 53 0.00118 0.00106 0.00259 0.00059 0.00071 0.00094
+ 100_267 08:53:18 -00:41:14 13.027 0.485 -0.062 0.307 0.302 0.608 3 3 0.00693 0.00231 0.01328 0.00751 0.00404 0.00404
+ 100_269 08:53:19 -00:40:54 12.350 0.547 -0.040 0.335 0.331 0.666 3 3 0.00346 0.00289 0.01501 0.00346 0.00289 0.00173
+ 100_280 08:53:36 -00:36:24 11.799 0.494 -0.002 0.295 0.291 0.588 58 47 0.00079 0.00092 0.00144 0.00079 0.00079 0.00118
+ 100_394 08:53:55 -00:32:04 11.384 1.317 1.457 0.705 0.636 1.341 9 5 0.00800 0.00400 0.00867 0.00233 0.00267 0.00300
+PG0918+029D 09:21:22 +02:47:33 12.272 1.044 0.821 0.575 0.535 1.108 19 11 0.00206 0.00298 0.00711 0.00161 0.00184 0.00184
+ PG0918+029 09:21:28 +02:46:06 13.327 -0.271 -1.081 -0.129 -0.159 -0.288 45 27 0.00239 0.00239 0.00298 0.00194 0.00552 0.00626
+PG0918+029B 09:21:34 +02:48:04 13.963 0.765 0.366 0.417 0.370 0.787 20 11 0.00335 0.00716 0.01588 0.00246 0.00447 0.00559
+PG0918+029A 09:21:35 +02:46:23 14.490 0.536 -0.032 0.325 0.336 0.661 29 14 0.00334 0.00576 0.00947 0.00390 0.00761 0.00854
+PG0918+029C 09:21:42 +02:46:41 13.537 0.631 0.087 0.367 0.357 0.722 21 10 0.00196 0.00284 0.00480 0.00153 0.00218 0.00284
+ -12_2918 09:31:18 -13:29:20 10.067 1.501 1.166 1.067 1.318 2.385 13 9 0.00250 0.00277 0.00749 0.00388 0.00222 0.00416
+PG0942-029D 09:45:10 -03:05:50 13.707 0.564 0.129 0.348 0.343 0.687 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+PG0942-029A 09:45:10 -03:10:14 14.731 0.783 0.339 0.610 0.477 1.081 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+PG0942-029B 09:45:12 -03:06:54 14.108 0.525 0.085 0.368 0.333 0.697 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ PG0942-029 09:45:12 -03:09:21 14.004 -0.294 -1.175 -0.130 -0.149 -0.280 14 7 0.00454 0.00561 0.00695 0.00695 0.01203 0.01443
+PG0942-029C 09:45:15 -03:06:36 14.989 0.727 0.369 0.539 0.376 0.909 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 101_315 09:54:51 -00:27:16 11.249 1.153 1.056 0.612 0.559 1.172 19 11 0.00367 0.00184 0.00665 0.00161 0.00115 0.00206
+ 101_316 09:54:53 -00:18:20 11.552 0.493 0.032 0.293 0.291 0.584 17 10 0.00267 0.00243 0.00364 0.00194 0.00291 0.00315
+ 101_L1 09:55:30 -00:21:25 16.501 0.757 -0.104 0.421 0.527 0.947 4 1 0.03100 0.03400 0.02900 0.02250 0.08550 0.10700
+ 101_320 09:55:34 -00:22:19 13.823 1.052 0.690 0.581 0.561 1.141 11 7 0.00482 0.01025 0.01809 0.00392 0.00362 0.00452
+ 101_L2 09:55:36 -00:18:36 15.770 0.602 0.082 0.321 0.304 0.625 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 101_404 09:55:42 -00:18:09 13.459 0.996 0.697 0.530 0.500 1.029 12 7 0.00404 0.00779 0.00953 0.00491 0.00318 0.00548
+ 101_324 09:55:58 -00:23:02 9.742 1.161 1.148 0.591 0.519 1.110 56 43 0.00147 0.00094 0.00200 0.00067 0.00067 0.00107
+ 101_262 09:56:08 -00:29:36 14.295 0.784 0.297 0.440 0.387 0.827 4 2 0.00450 0.01600 0.02050 0.00750 0.01000 0.00350
+ 101_408 09:56:09 -00:12:28 14.785 1.200 1.347 0.718 0.603 1.321 2 1 0.02404 0.04384 0.01697 0.01697 0.01202 0.02970
+ 101_326 09:56:09 -00:26:56 14.923 0.729 0.227 0.406 0.375 0.780 13 6 0.00777 0.00943 0.01276 0.00555 0.01109 0.01220
+ 101_410 09:56:10 -00:13:50 13.646 0.546 -0.063 0.298 0.326 0.623 2 1 0.00849 0.00141 0.00212 0.01061 0.00354 0.00636
+ 101_327 09:56:10 -00:25:37 13.441 1.155 1.139 0.717 0.574 1.290 28 15 0.00321 0.00567 0.00983 0.00227 0.00170 0.00283
+ 101_413 09:56:15 -00:11:44 12.583 0.983 0.716 0.529 0.497 1.025 9 6 0.00233 0.00467 0.01033 0.00333 0.00400 0.00400
+ 101_268 09:56:19 -00:31:43 14.380 1.531 1.381 1.040 1.200 2.237 11 5 0.00784 0.01990 0.07689 0.00482 0.00362 0.00452
+ 101_330 09:56:22 -00:27:07 13.723 0.577 -0.026 0.346 0.338 0.684 28 14 0.00378 0.00378 0.00510 0.00283 0.00567 0.00643
+ 101_415 09:56:24 -00:16:40 15.259 0.577 -0.008 0.346 0.350 0.695 2 1 0.00283 0.02475 0.00212 0.01980 0.01344 0.03323
+ 101_270 09:56:27 -00:35:31 13.711 0.554 0.055 0.332 0.306 0.637 2 1 0.00000 0.00141 0.01273 0.00495 0.00707 0.00141
+ 101_278 09:56:55 -00:29:26 15.494 1.041 0.737 0.596 0.548 1.144 2 1 0.01838 0.02263 0.02687 0.01980 0.01485 0.03465
+ 101_L3 09:56:55 -00:30:15 15.953 0.637 -0.033 0.396 0.395 0.792 2 1 0.02333 0.01838 0.07071 0.03818 0.04879 0.08697
+ 101_281 09:57:05 -00:31:26 11.575 0.812 0.419 0.452 0.412 0.864 19 11 0.00367 0.00184 0.00482 0.00229 0.00115 0.00252
+ 101_L4 09:57:08 -00:31:16 16.264 0.793 0.362 0.578 0.062 0.644 2 1 0.01697 0.01414 0.00141 0.01909 0.26375 0.28072
+ 101_L5 09:57:11 -00:31:25 15.928 0.622 0.115 0.414 0.305 0.720 2 1 0.01061 0.02828 0.08627 0.00778 0.01344 0.02121
+ 101_421 09:57:17 -00:17:05 13.180 0.507 -0.031 0.327 0.296 0.623 2 1 0.00212 0.00212 0.00354 0.00212 0.00071 0.00141
+ 101_338 09:57:19 -00:20:47 13.788 0.634 0.024 0.350 0.340 0.691 2 1 0.00707 0.00707 0.00424 0.00212 0.00354 0.00141
+ 101_339 09:57:19 -00:24:48 14.449 0.850 0.501 0.458 0.398 0.857 2 1 0.00990 0.00849 0.00990 0.02404 0.00424 0.02899
+ 101_424 09:57:21 -00:16:14 15.058 0.764 0.273 0.429 0.425 0.855 2 1 0.02758 0.03889 0.01909 0.02263 0.02051 0.04313
+ 101_427 09:57:27 -00:17:04 14.964 0.805 0.321 0.484 0.369 0.854 2 1 0.02687 0.02970 0.00141 0.02475 0.01131 0.03677
+ 101_341 09:57:31 -00:21:40 14.342 0.575 0.059 0.332 0.309 0.641 2 1 0.01131 0.01414 0.00707 0.00071 0.00778 0.00707
+ 101_342 09:57:32 -00:21:37 15.556 0.529 -0.065 0.339 0.419 0.758 2 1 0.01414 0.00849 0.00849 0.02404 0.00212 0.02263
+ 101_343 09:57:32 -00:22:42 15.504 0.606 0.094 0.396 0.338 0.734 2 1 0.02758 0.04879 0.01768 0.02263 0.02546 0.04808
+ 101_429 09:57:33 -00:18:05 13.496 0.980 0.782 0.617 0.526 1.143 23 13 0.00392 0.00188 0.00605 0.00167 0.00200 0.00304
+ 101_431 09:57:38 -00:17:39 13.684 1.246 1.144 0.808 0.708 1.517 23 13 0.00563 0.00626 0.01022 0.00334 0.00292 0.00417
+ 101_L6 09:57:40 -00:17:40 16.497 0.711 0.183 0.445 0.583 1.024 2 1 0.02192 0.00919 0.03111 0.01131 0.16476 0.17324
+ 101_207 09:57:53 -00:47:23 12.419 0.515 -0.078 0.321 0.320 0.641 22 14 0.00277 0.00384 0.00618 0.00171 0.00192 0.00235
+ 101_363 09:58:20 -00:25:23 9.874 0.261 0.129 0.146 0.151 0.297 53 44 0.00124 0.00082 0.00247 0.00082 0.00082 0.00110
+ GD_108 10:00:47 -07:33:31 13.561 -0.215 -0.942 -0.098 -0.122 -0.220 21 12 0.00284 0.00415 0.00393 0.00415 0.00502 0.00546
+ G162_66 10:33:43 -11:40:39 13.012 -0.165 -0.996 -0.126 -0.141 -0.266 80 64 0.00145 0.00134 0.00224 0.00101 0.00201 0.00246
+ G44_27 10:36:02 +05:07:11 12.636 1.586 1.088 1.185 1.526 2.714 8 4 0.01202 0.01061 0.01061 0.00460 0.00389 0.00318
+ PG1034+001 10:37:17 -00:07:25 13.228 -0.365 -1.274 -0.155 -0.203 -0.359 33 16 0.00244 0.00244 0.00331 0.00261 0.00418 0.00540
+ G163_6 10:42:55 +02:47:22 14.706 1.550 1.228 1.090 1.384 2.478 4 3 0.00700 0.01150 0.06550 0.00900 0.00150 0.00850
+ PG1047+003 10:50:03 -00:00:30 13.474 -0.290 -1.121 -0.132 -0.162 -0.295 32 18 0.00389 0.00301 0.00407 0.00371 0.00884 0.01096
+PG1047+003A 10:50:06 -00:01:06 13.512 0.688 0.168 0.422 0.418 0.840 15 7 0.00465 0.00491 0.00671 0.00258 0.00258 0.00361
+PG1047+003B 10:50:09 -00:01:58 14.751 0.679 0.172 0.391 0.371 0.764 13 5 0.00499 0.00860 0.01276 0.00222 0.00804 0.00860
+PG1047+003C 10:50:18 -00:00:21 12.453 0.607 -0.019 0.378 0.358 0.737 11 6 0.00935 0.00241 0.00603 0.00362 0.00332 0.00452
+ G44_40 10:50:54 +06:48:57 11.675 1.644 1.213 1.216 1.568 2.786 13 6 0.00333 0.00305 0.00915 0.00305 0.00166 0.00388
+ 102_620 10:55:06 -00:48:13 10.069 1.083 1.020 0.642 0.524 1.167 54 45 0.00095 0.00095 0.00177 0.00109 0.00082 0.00122
+ G45_20 10:56:38 +07:02:23 13.507 2.034 1.165 1.823 2.174 4.000 19 10 0.00596 0.00688 0.03464 0.00734 0.00252 0.00619
+ 102_1081 10:57:05 -00:13:04 9.903 0.664 0.255 0.366 0.333 0.698 58 50 0.00092 0.00092 0.00171 0.00079 0.00079 0.00105
+ G163_27 10:57:35 -07:31:23 14.338 0.288 -0.548 0.206 0.210 0.417 26 15 0.00549 0.00471 0.00647 0.00412 0.00745 0.00824
+ G163_50 11:08:00 -05:09:26 13.059 0.035 -0.688 -0.085 -0.072 -0.159 54 41 0.00136 0.00204 0.00231 0.00122 0.00204 0.00272
+ G163_51 11:08:07 -05:13:47 12.576 1.506 1.228 1.084 1.359 2.441 29 16 0.00464 0.00464 0.01820 0.00186 0.00353 0.00409
+ G10_50 11:47:44 +00:48:55 11.153 1.752 1.318 1.294 1.673 2.969 14 7 0.00241 0.00241 0.00775 0.00374 0.00214 0.00374
+ 103_302 11:56:06 -00:47:54 9.861 0.368 -0.056 0.228 0.237 0.465 57 45 0.00159 0.00106 0.00172 0.00093 0.00093 0.00146
+ 103_626 11:56:47 -00:21:47 11.836 0.413 -0.057 0.262 0.274 0.535 17 10 0.00340 0.00267 0.00315 0.00218 0.00146 0.00243
+ G12_43 12:33:20 +09:01:08 12.467 1.846 1.085 1.530 1.944 3.479 13 6 0.00416 0.00527 0.04659 0.00527 0.00388 0.00333
+ 104_306 12:41:04 -00:37:15 9.370 1.592 1.666 0.832 0.762 1.591 89 68 0.00668 0.00297 0.00594 0.00201 0.00244 0.00329
+ 104_423 12:41:36 -00:31:18 15.602 0.630 0.050 0.262 0.559 0.818 2 1 0.02475 0.03889 0.02687 0.03606 0.11667 0.15203
+ 104_428 12:41:41 -00:26:30 12.630 0.985 0.748 0.534 0.497 1.032 25 16 0.00380 0.00280 0.00440 0.00240 0.00180 0.00360
+ 104_L1 12:41:44 -00:22:47 14.608 0.630 0.064 0.374 0.364 0.739 2 1 0.00071 0.00141 0.01273 0.01131 0.01626 0.00424
+ 104_430 12:41:50 -00:25:56 13.858 0.652 0.131 0.364 0.363 0.727 15 8 0.00516 0.00620 0.00852 0.00465 0.00413 0.00645
+ 104_325 12:42:03 -00:41:39 15.581 0.694 0.051 0.345 0.307 0.652 2 1 0.01626 0.04313 0.02192 0.02546 0.01485 0.04031
+ 104_330 12:42:12 -00:40:43 15.296 0.594 -0.028 0.369 0.371 0.739 15 6 0.01033 0.02763 0.01549 0.01239 0.02143 0.02246
+ 104_440 12:42:14 -00:24:51 15.114 0.440 -0.227 0.289 0.317 0.605 11 5 0.00814 0.00844 0.01025 0.00693 0.02322 0.02623
+ 104_237 12:42:17 -00:51:21 15.395 1.088 0.918 0.647 0.628 1.274 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 104_L2 12:42:19 -00:35:16 16.048 0.650 -0.172 0.344 0.323 0.667 4 2 0.01900 0.02650 0.04500 0.02950 0.07550 0.10000
+ 104_443 12:42:20 -00:25:25 15.372 1.331 1.280 0.817 0.778 1.595 3 2 0.00866 0.00231 0.11201 0.01386 0.01039 0.02021
+ 104_444 12:42:20 -00:32:32 13.477 0.512 -0.070 0.313 0.331 0.643 2 1 0.00141 0.00990 0.00849 0.00212 0.00141 0.00071
+ 104_335 12:42:21 -00:33:12 11.665 0.622 0.145 0.357 0.334 0.691 4 2 0.00950 0.00100 0.00200 0.00350 0.00450 0.00700
+ 104_334 12:42:21 -00:40:31 13.484 0.518 -0.067 0.323 0.331 0.653 24 16 0.00469 0.00306 0.00388 0.00286 0.00306 0.00469
+ 104_239 12:42:23 -00:46:36 13.936 1.356 1.291 0.868 0.805 1.675 7 3 0.00605 0.00869 0.02306 0.00454 0.00302 0.00567
+ 104_336 12:42:25 -00:40:02 14.404 0.830 0.495 0.461 0.403 0.865 14 6 0.00668 0.00722 0.01229 0.00588 0.00989 0.01042
+ 104_338 12:42:31 -00:38:36 16.059 0.591 -0.082 0.348 0.372 0.719 8 5 0.00778 0.02192 0.03677 0.00884 0.02086 0.01697
+ 104_339 12:42:34 -00:41:43 15.459 0.832 0.709 0.476 0.374 0.849 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 104_244 12:42:35 -00:45:51 16.011 0.590 -0.152 0.338 0.489 0.825 2 2 0.00919 0.00566 0.01131 0.00354 0.02687 0.02899
+ 104_455 12:42:52 -00:24:22 15.105 0.581 -0.024 0.360 0.357 0.716 13 7 0.00666 0.01442 0.01220 0.00527 0.00888 0.01220
+ 104_456 12:42:53 -00:32:09 12.362 0.622 0.135 0.357 0.337 0.694 4 2 0.00250 0.00250 0.00450 0.00350 0.00650 0.00800
+ 104_457 12:42:54 -00:28:52 16.048 0.753 0.522 0.484 0.490 0.974 9 4 0.01067 0.01867 0.07700 0.01833 0.03700 0.02133
+ 104_460 12:43:03 -00:28:25 12.886 1.287 1.243 0.813 0.693 1.507 24 16 0.00429 0.00327 0.00674 0.00225 0.00204 0.00327
+ 104_461 12:43:06 -00:32:25 9.705 0.476 -0.030 0.289 0.290 0.580 95 74 0.00103 0.00082 0.00133 0.00072 0.00062 0.00062
+ 104_350 12:43:14 -00:33:25 13.634 0.673 0.165 0.383 0.353 0.736 14 7 0.00428 0.00347 0.00561 0.00321 0.00454 0.00615
+ 104_470 12:43:22 -00:30:00 14.310 0.732 0.101 0.295 0.356 0.649 3 1 0.01212 0.00924 0.02021 0.01328 0.00346 0.01501
+ 104_364 12:43:46 -00:34:34 15.799 0.601 -0.131 0.314 0.397 0.712 2 1 0.01556 0.04879 0.05586 0.00849 0.04101 0.04950
+ 104_366 12:43:53 -00:34:56 12.908 0.870 0.424 0.517 0.464 0.982 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 104_479 12:43:55 -00:32:55 16.087 1.271 0.673 0.657 0.607 1.264 2 1 0.03394 0.02758 0.39952 0.00283 0.00354 0.00707
+ 104_367 12:43:58 -00:33:40 15.844 0.639 -0.126 0.382 0.296 0.679 2 1 0.02546 0.02121 0.01556 0.01768 0.00424 0.02263
+ 104_484 12:44:20 -00:31:01 14.406 1.024 0.732 0.514 0.486 1.000 2 1 0.00707 0.01838 0.01344 0.00566 0.00636 0.01202
+ 104_485 12:44:23 -00:30:20 15.017 0.838 0.493 0.478 0.488 0.967 2 1 0.01131 0.03394 0.02263 0.00141 0.01131 0.00990
+ 104_490 12:44:33 -00:25:57 12.572 0.535 0.048 0.318 0.312 0.630 12 8 0.00289 0.00318 0.00520 0.00231 0.00231 0.00260
+ 104_598 12:45:17 -00:16:41 11.479 1.106 1.050 0.670 0.546 1.215 70 59 0.00167 0.00108 0.00275 0.00096 0.00084 0.00120
+ G14_55 13:28:22 -02:21:28 11.336 1.491 1.157 1.078 1.388 2.462 5 2 0.00581 0.00492 0.00760 0.00671 0.00134 0.00626
+ PG1323-086 13:25:39 -08:49:18 13.481 -0.140 -0.681 -0.048 -0.078 -0.127 39 18 0.00192 0.00224 0.00256 0.00176 0.00448 0.00448
+PG1323-086A 13:25:49 -08:50:24 13.591 0.393 -0.019 0.252 0.252 0.506 20 12 0.02571 0.00224 0.00447 0.00268 0.00470 0.00604
+PG1323-086C 13:25:50 -08:48:39 14.003 0.707 0.245 0.395 0.363 0.759 26 13 0.00314 0.00275 0.00765 0.00235 0.00412 0.00490
+PG1323-086B 13:25:50 -08:51:55 13.406 0.761 0.265 0.426 0.407 0.833 23 13 0.00188 0.00292 0.00417 0.00229 0.00229 0.00313
+PG1323-086D 13:26:05 -08:50:36 12.080 0.587 0.005 0.346 0.335 0.684 15 6 0.00232 0.00181 0.00361 0.00129 0.00258 0.00310
+ 105_505 13:35:24 -00:23:47 10.270 1.422 1.218 0.910 0.861 1.771 6 3 0.00612 0.01021 0.00531 0.00531 0.00327 0.00694
+ 105_437 13:37:17 -00:38:05 12.535 0.248 0.067 0.136 0.143 0.279 7 3 0.00605 0.00378 0.00945 0.00529 0.00265 0.00756
+ 105_815 13:40:04 -00:02:19 11.453 0.385 -0.237 0.267 0.291 0.560 22 14 0.00160 0.00298 0.00275 0.00126 0.00134 0.00151
+ +2_2711 13:42:20 +01:29:58 10.367 -0.166 -0.697 -0.072 -0.095 -0.167 54 39 0.00122 0.00136 0.00177 0.00082 0.00095 0.00122
+ 121968 13:58:51 -02:55:38 10.254 -0.186 -0.908 -0.073 -0.098 -0.172 46 32 0.00118 0.00103 0.00206 0.00074 0.00103 0.00118
+ PG1407-013 14:10:26 -01:30:16 13.750 -0.259 -1.119 -0.130 -0.144 -0.277 3 2 0.00404 0.00635 0.01732 0.00462 0.01732 0.02194
+ 106_1024 14:40:07 +00:01:31 11.599 0.332 0.085 0.196 0.195 0.390 35 27 0.00507 0.00220 0.00287 0.00186 0.00135 0.00287
+ 106_700 14:40:51 -00:23:50 9.785 1.362 1.582 0.728 0.641 1.370 53 44 0.00110 0.00096 0.00220 0.00096 0.00096 0.00137
+ PG1514+034 15:17:14 +03:10:22 13.997 -0.009 -0.955 0.087 0.126 0.212 6 3 0.00776 0.00816 0.01021 0.00286 0.00653 0.00735
+ PG1525-071 15:28:11 -07:16:32 15.053 -0.198 -1.148 -0.088 -0.075 -0.168 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+PG1525-071D 15:28:12 -07:16:38 16.301 0.564 0.305 0.411 0.346 0.757 2 1 0.00212 0.15698 0.03253 0.01131 0.01980 0.00849
+PG1525-071A 15:28:13 -07:15:59 13.509 0.757 0.257 0.445 0.425 0.869 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+PG1525-071B 15:28:14 -07:16:13 16.403 0.730 0.135 0.442 0.366 0.808 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+PG1525-071C 15:28:16 -07:14:26 13.530 1.109 1.130 0.590 0.513 1.104 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+PG1528+062B 15:30:40 +06:01:06 11.989 0.593 0.005 0.364 0.344 0.711 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+PG1528+062A 15:30:49 +06:01:19 15.553 0.830 0.356 0.433 0.389 0.824 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ PG1528+062 15:30:50 +06:00:51 14.767 -0.252 -1.091 -0.111 -0.182 -0.296 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+PG1528+062C 15:30:56 +06:00:02 13.477 0.644 0.074 0.357 0.340 0.699 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+PG1530+057A 15:33:10 +05:33:40 13.711 0.829 0.414 0.473 0.412 0.886 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ PG1530+057 15:33:11 +05:32:22 14.211 0.151 -0.789 0.162 0.036 0.199 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+PG1530+057B 15:33:18 +05:33:43 12.842 0.745 0.325 0.423 0.376 0.799 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 107_970 15:37:25 +00:18:16 10.939 1.596 1.750 1.142 1.435 2.574 57 47 0.00742 0.00172 0.00609 0.00199 0.00331 0.00397
+ 107_568 15:37:52 -00:17:36 13.054 1.149 0.862 0.625 0.595 1.217 15 7 0.00155 0.00284 0.00387 0.00207 0.00284 0.00284
+ 107_1006 15:38:33 +00:14:04 11.712 0.766 0.279 0.442 0.421 0.863 59 51 0.00104 0.00104 0.00247 0.00078 0.00091 0.00104
+ 107_720 15:38:37 -00:02:42 13.121 0.599 0.088 0.374 0.355 0.731 2 1 0.00566 0.00283 0.01061 0.00990 0.00283 0.00778
+ 107_456 15:38:42 -00:20:05 12.919 0.921 0.589 0.537 0.478 1.015 20 10 0.00201 0.00291 0.00447 0.00201 0.00246 0.00358
+ 107_457 15:38:46 -00:20:33 14.910 0.792 0.350 0.494 0.469 0.964 2 1 0.00212 0.00354 0.00990 0.00283 0.00636 0.00919
+ 107_351 15:38:46 -00:32:24 12.342 0.562 -0.005 0.351 0.358 0.708 25 14 0.00200 0.00240 0.00400 0.00160 0.00220 0.00260
+ 107_592 15:38:50 -00:17:28 11.847 1.318 1.380 0.709 0.647 1.357 9 5 0.00333 0.00467 0.01333 0.00133 0.00233 0.00200
+ 107_458 15:38:50 -00:24:45 11.676 1.214 1.189 0.667 0.602 1.274 2 1 0.00424 0.00566 0.00495 0.00283 0.00071 0.00354
+ 107_459 15:38:51 -00:22:49 12.284 0.900 0.427 0.525 0.517 1.045 2 1 0.00141 0.01061 0.00990 0.00283 0.00071 0.00354
+ 107_212 15:38:56 -00:45:48 13.383 0.683 0.135 0.404 0.411 0.818 2 1 0.00636 0.01061 0.01980 0.00707 0.00849 0.01485
+ 107_215 15:38:57 -00:43:24 16.046 0.115 -0.082 -0.032 -0.475 -0.511 3 2 0.02656 0.03118 0.00924 0.09353 0.29907 0.39433
+ 107_213 15:38:57 -00:44:32 14.262 0.802 0.261 0.531 0.509 1.038 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 107_357 15:39:05 -00:39:29 14.418 0.675 0.025 0.416 0.421 0.840 2 1 0.00000 0.00354 0.00566 0.01202 0.02333 0.01131
+ 107_599 15:39:09 -00:14:46 14.675 0.698 0.243 0.433 0.438 0.869 17 7 0.00825 0.01213 0.00606 0.00534 0.01213 0.01552
+ 107_359 15:39:09 -00:35:49 12.797 0.580 -0.124 0.379 0.381 0.759 6 3 0.00490 0.00694 0.01184 0.00286 0.00327 0.00531
+ 107_600 15:39:10 -00:16:07 14.884 0.503 0.049 0.339 0.361 0.700 9 4 0.01700 0.01300 0.02267 0.00967 0.01467 0.02033
+ 107_601 15:39:13 -00:13:44 14.646 1.412 1.265 0.923 0.835 1.761 33 13 0.00453 0.00731 0.02472 0.00348 0.00313 0.00383
+ 107_602 15:39:18 -00:15:47 12.116 0.991 0.585 0.545 0.531 1.074 17 9 0.00267 0.00291 0.00703 0.00146 0.00218 0.00315
+ 107_612 15:39:35 -00:15:24 14.256 0.896 0.296 0.551 0.530 1.081 2 1 0.00566 0.00141 0.00354 0.00354 0.00071 0.00212
+ 107_611 15:39:36 -00:12:54 14.329 0.890 0.455 0.520 0.447 0.968 4 2 0.00650 0.00850 0.01650 0.00900 0.01050 0.01700
+ 107_614 15:39:41 -00:13:28 13.926 0.622 0.033 0.361 0.370 0.732 4 2 0.00650 0.01700 0.01500 0.00400 0.01300 0.00900
+ 107_626 15:40:05 -00:17:46 13.468 1.000 0.728 0.600 0.527 1.126 24 12 0.00449 0.00816 0.01184 0.00245 0.00225 0.00347
+ 107_627 15:40:07 -00:17:40 13.349 0.779 0.226 0.465 0.454 0.918 24 12 0.00551 0.00469 0.00490 0.00225 0.00265 0.00367
+ 107_484 15:40:17 -00:21:31 11.311 1.237 1.291 0.664 0.577 1.240 13 7 0.00444 0.00222 0.01109 0.00194 0.00083 0.00222
+ 107_636 15:40:40 -00:15:12 14.873 0.751 0.121 0.432 0.465 0.896 2 1 0.01344 0.01202 0.01768 0.00849 0.04172 0.03253
+ 107_639 15:40:44 -00:17:29 14.197 0.640 -0.026 0.399 0.404 0.803 10 6 0.01613 0.00917 0.02024 0.01044 0.00949 0.01265
+ 107_640 15:40:49 -00:17:06 15.050 0.755 0.092 0.511 0.506 1.017 5 3 0.02504 0.01029 0.03220 0.01834 0.01610 0.02460
+ G153_41 16:17:55 -15:35:52 13.422 -0.205 -1.133 -0.135 -0.154 -0.290 23 11 0.00354 0.00313 0.00626 0.00334 0.00563 0.00646
+ G138_25 16:25:14 +15:41:15 13.513 1.419 1.265 0.883 0.796 1.685 2 1 0.00071 0.01768 0.03818 0.00283 0.00283 0.00495
+ -12_4523 16:30:18 -12:39:08 10.069 1.568 1.192 1.152 1.498 2.649 8 5 0.00318 0.00247 0.00247 0.00071 0.00177 0.00141
+ PG1633+099 16:35:24 +09:47:45 14.397 -0.192 -0.974 -0.093 -0.116 -0.212 13 6 0.00250 0.00222 0.00471 0.00333 0.00888 0.01109
+PG1633+099A 16:35:26 +09:47:48 15.256 0.873 0.320 0.505 0.511 1.015 15 6 0.00361 0.00516 0.00904 0.00361 0.00930 0.01110
+PG1633+099B 16:35:34 +09:46:17 12.969 1.081 1.007 0.590 0.502 1.090 12 6 0.00173 0.00202 0.00693 0.00115 0.00144 0.00202
+PG1633+099C 16:35:38 +09:46:11 13.229 1.134 1.138 0.618 0.523 1.138 10 6 0.00253 0.00221 0.00379 0.00158 0.00221 0.00379
+PG1633+099D 16:35:40 +09:46:38 13.691 0.535 -0.025 0.324 0.327 0.650 9 5 0.00200 0.00200 0.00500 0.00167 0.00333 0.00333
+ 108_719 16:36:11 -00:25:53 12.690 1.031 0.648 0.553 0.533 1.087 4 2 0.00450 0.00250 0.00050 0.00450 0.00250 0.00500
+ 108_1848 16:36:58 +00:05:36 11.738 0.559 0.073 0.331 0.325 0.657 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 108_475 16:37:00 -00:35:01 11.309 1.380 1.462 0.744 0.665 1.409 71 58 0.00142 0.00131 0.00415 0.00083 0.00071 0.00107
+ 108_1863 16:37:13 +00:02:13 12.244 0.803 0.378 0.446 0.398 0.844 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 108_551 16:37:47 -00:33:27 10.703 0.179 0.178 0.099 0.110 0.208 104 76 0.00108 0.00069 0.00226 0.00059 0.00098 0.00108
+ 108_1918 16:37:50 -00:00:58 11.384 1.432 1.839 0.773 0.661 1.434 2 1 0.00071 0.00141 0.00000 0.00424 0.00000 0.00424
+ 108_981 16:39:17 -00:25:28 12.071 0.494 0.237 0.310 0.312 0.622 4 2 0.00250 0.00150 0.00750 0.00200 0.00300 0.00100
+ PG1647+056 16:50:18 +05:32:48 14.773 -0.173 -1.064 -0.058 -0.022 -0.082 7 3 0.00869 0.00869 0.00756 0.01021 0.01512 0.01625
+ WOLF_629 16:55:27 -08:18:53 11.759 1.677 1.256 1.185 1.525 2.715 6 3 0.00408 0.00286 0.00327 0.00163 0.00122 0.00122
+ PG1657+078 16:59:32 +07:43:25 15.015 -0.149 -0.940 -0.063 -0.033 -0.100 9 4 0.00667 0.00533 0.00900 0.00867 0.02700 0.03300
+PG1657+078B 16:59:32 +07:42:05 14.721 0.708 0.065 0.417 0.420 0.838 2 1 0.00212 0.00636 0.00707 0.00141 0.00000 0.00141
+PG1657+078A 16:59:33 +07:42:19 14.033 1.069 0.730 0.573 0.539 1.113 2 1 0.00071 0.00071 0.00636 0.00636 0.00566 0.01273
+PG1657+078C 16:59:35 +07:42:20 15.225 0.840 0.385 0.521 0.444 0.967 2 1 0.00000 0.00424 0.00849 0.00566 0.01273 0.00707
+ -4_4226 17:05:15 -05:05:05 10.071 1.415 1.085 0.970 1.141 2.113 6 3 0.00327 0.00122 0.00286 0.00041 0.00082 0.00122
+ 109_71 17:44:06 -00:25:22 11.493 0.323 0.153 0.186 0.223 0.410 50 42 0.00099 0.00113 0.00198 0.00085 0.00085 0.00113
+ 109_381 17:44:12 -00:20:55 11.730 0.704 0.225 0.428 0.435 0.861 55 45 0.00108 0.00148 0.00148 0.00094 0.00081 0.00108
+ 109_949 17:44:13 -00:02:51 12.828 0.806 0.363 0.500 0.517 1.020 2 1 0.00636 0.00071 0.00990 0.00778 0.00354 0.01131
+ 109_954 17:44:15 -00:02:39 12.436 1.296 0.956 0.764 0.731 1.496 9 5 0.00933 0.00600 0.02033 0.00167 0.00267 0.00333
+ 109_956 17:44:17 -00:02:54 14.639 1.283 0.858 0.779 0.743 1.525 2 1 0.01131 0.01980 0.00354 0.01838 0.01556 0.03465
+ 109_199 17:45:03 -00:29:51 10.990 1.739 1.967 1.006 0.900 1.904 3 2 0.00981 0.00404 0.00346 0.00346 0.00404 0.00462
+ 109_231 17:45:20 -00:26:13 9.332 1.462 1.593 0.785 0.704 1.492 76 52 0.00115 0.00138 0.00275 0.00057 0.00069 0.00092
+ 109_537 17:45:42 -00:21:57 10.353 0.609 0.227 0.376 0.392 0.768 66 47 0.00271 0.00123 0.00197 0.00086 0.00098 0.00148
+ G21_15 18:27:13 +04:03:05 13.889 0.092 -0.598 -0.039 -0.030 -0.069 19 9 0.00459 0.00528 0.00665 0.00459 0.00941 0.00941
+ 110_229 18:40:46 +00:01:28 13.649 1.910 1.391 1.198 1.155 2.356 30 16 0.00310 0.00913 0.02246 0.00183 0.00201 0.00256
+ 110_230 18:40:52 +00:02:01 14.281 1.084 0.728 0.624 0.596 1.218 21 11 0.00306 0.00502 0.01157 0.00196 0.00436 0.00502
+ 110_232 18:40:53 +00:01:35 12.516 0.729 0.147 0.439 0.450 0.889 28 16 0.00321 0.00283 0.00454 0.00151 0.00189 0.00246
+ 110_233 18:40:53 +00:00:28 12.771 1.281 0.812 0.773 0.818 1.593 22 10 0.00277 0.00341 0.00704 0.00213 0.00149 0.00213
+ 110_239 18:41:20 -00:00:08 13.858 0.899 0.584 0.541 0.517 1.060 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 110_339 18:41:27 +00:08:04 13.607 0.988 0.776 0.563 0.468 1.036 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 110_340 18:41:29 +00:15:00 10.025 0.303 0.127 0.170 0.182 0.353 64 51 0.00137 0.00100 0.00225 0.00062 0.00088 0.00100
+ 110_477 18:41:44 +00:26:19 13.988 1.345 0.715 0.850 0.857 1.707 21 11 0.00720 0.01309 0.03753 0.00306 0.00393 0.00633
+ 110_246 18:41:51 +00:04:58 12.706 0.586 -0.129 0.381 0.410 0.790 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 110_346 18:41:55 +00:09:37 14.757 0.999 0.752 0.697 0.646 1.345 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 110_349 18:42:13 +00:09:52 15.095 1.088 0.668 0.503 -0.059 0.477 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 110_355 18:42:19 +00:08:02 11.944 1.023 0.504 0.652 0.727 1.378 16 8 0.00275 0.00300 0.00450 0.00225 0.00225 0.00350
+ 110_358 18:42:36 +00:14:39 14.430 1.039 0.418 0.603 0.543 1.150 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 110_360 18:42:40 +00:08:48 14.618 1.197 0.539 0.715 0.717 1.432 5 2 0.00939 0.01923 0.02907 0.00850 0.00313 0.00805
+ 110_361 18:42:45 +00:07:42 12.425 0.632 0.035 0.361 0.348 0.709 30 17 0.00219 0.00219 0.00292 0.00183 0.00201 0.00292
+ 110_362 18:42:48 +00:06:04 15.693 1.333 3.919 0.918 0.885 1.803 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 110_L1 18:42:50 +00:06:48 16.252 1.752 2.953 1.066 0.992 2.058 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 110_266 18:42:50 +00:04:44 12.018 0.889 0.411 0.538 0.577 1.111 8 3 0.00141 0.00283 0.00389 0.00141 0.00212 0.00318
+ 110_364 18:42:52 +00:07:32 13.615 1.133 1.095 0.697 0.585 1.281 15 7 0.00207 0.00671 0.00878 0.00155 0.00258 0.00207
+ 110_365 18:42:57 +00:06:58 13.470 2.261 1.895 1.360 1.270 2.631 45 20 0.00268 0.00909 0.03130 0.00209 0.00224 0.00343
+ 110_157 18:42:57 -00:09:18 13.491 2.123 1.679 1.257 1.139 2.395 7 3 0.00567 0.02570 0.17500 0.00340 0.00491 0.00567
+ 110_496 18:43:00 +00:30:46 13.004 1.040 0.737 0.607 0.681 1.287 9 4 0.00267 0.00600 0.02300 0.00200 0.00233 0.00433
+ 110_273 18:43:00 +00:02:01 14.686 2.527 1.000 1.509 1.345 2.856 5 2 0.01610 0.07826 1.34164 0.00402 0.01029 0.01073
+ 110_497 18:43:03 +00:30:34 14.196 1.052 0.380 0.606 0.597 1.203 5 2 0.00537 0.00626 0.01431 0.00671 0.00447 0.00626
+ 110_280 18:43:07 -00:04:02 12.996 2.151 2.133 1.235 1.148 2.384 25 12 0.00340 0.01440 0.09060 0.00180 0.00300 0.00360
+ 110_499 18:43:08 +00:27:38 11.737 0.987 0.639 0.600 0.674 1.273 23 13 0.00313 0.00292 0.00709 0.00188 0.00167 0.00292
+ 110_502 18:43:11 +00:27:18 12.330 2.326 2.326 1.373 1.250 2.625 38 19 0.00308 0.00470 0.02255 0.00195 0.00243 0.00406
+ 110_504 18:43:12 +00:29:43 14.022 1.248 1.323 0.797 0.683 1.482 5 2 0.00134 0.00626 0.02683 0.00358 0.00626 0.00805
+ 110_503 18:43:12 +00:29:21 11.773 0.671 0.506 0.373 0.436 0.808 26 14 0.00314 0.00196 0.00510 0.00177 0.00157 0.00216
+ 110_506 18:43:20 +00:30:05 11.312 0.568 0.059 0.335 0.312 0.652 2 1 0.00212 0.00212 0.00636 0.00071 0.00424 0.00424
+ 110_507 18:43:20 +00:29:04 12.440 1.141 0.830 0.633 0.579 1.206 2 1 0.00495 0.00566 0.00566 0.00424 0.00000 0.00495
+ 110_290 18:43:22 -00:01:37 11.898 0.708 0.196 0.418 0.418 0.836 3 2 0.00289 0.00058 0.00462 0.00231 0.00289 0.00346
+ 110_441 18:43:34 +00:19:18 11.121 0.555 0.112 0.324 0.336 0.660 43 36 0.00152 0.00152 0.00229 0.00122 0.00091 0.00198
+ 110_311 18:43:48 -00:00:44 15.505 1.796 1.179 1.010 0.864 1.874 4 2 0.01800 0.03600 0.12550 0.03400 0.08300 0.11300
+ 110_312 18:43:50 -00:00:15 16.093 1.319 -0.788 1.137 1.154 2.293 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 110_450 18:43:52 +00:22:36 11.585 0.944 0.691 0.552 0.625 1.177 49 42 0.00200 0.00171 0.00329 0.00114 0.00100 0.00157
+ 110_316 18:43:53 +00:00:43 14.821 1.731 4.355 0.858 0.910 1.769 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 110_315 18:43:53 +00:00:27 13.637 2.069 2.256 1.206 1.133 2.338 8 4 0.00672 0.03606 0.46386 0.00318 0.00566 0.00672
+ 110_319 18:43:56 +00:01:39 11.861 1.309 1.076 0.742 0.700 1.443 3 2 0.01097 0.00289 0.00346 0.00404 0.00173 0.00577
+ 111_775 19:37:17 +00:11:44 10.744 1.738 2.029 0.965 0.896 1.862 61 48 0.00154 0.00090 0.00589 0.00077 0.00064 0.00102
+ 111_773 19:37:17 +00:10:38 8.963 0.206 -0.210 0.119 0.144 0.262 66 47 0.00123 0.00098 0.00172 0.00074 0.00074 0.00086
+ 111_1925 19:37:29 +00:24:40 12.388 0.395 0.262 0.221 0.253 0.474 26 13 0.00177 0.00137 0.00431 0.00177 0.00137 0.00235
+ 111_1965 19:37:42 +00:26:30 11.419 1.710 1.865 0.951 0.877 1.830 16 8 0.00175 0.00375 0.00900 0.00100 0.00100 0.00125
+ 111_1969 19:37:44 +00:25:27 10.382 1.959 2.306 1.177 1.222 2.400 58 47 0.00171 0.00144 0.00538 0.00079 0.00092 0.00131
+ 111_2039 19:38:05 +00:31:52 12.395 1.369 1.237 0.739 0.689 1.430 8 4 0.00212 0.00283 0.01202 0.00212 0.00212 0.00212
+ 111_2088 19:38:22 +00:30:40 13.193 1.610 1.678 0.888 0.818 1.708 8 4 0.00141 0.00424 0.01096 0.00177 0.00141 0.00177
+ 111_2093 19:38:24 +00:31:05 12.538 0.637 0.283 0.370 0.397 0.766 8 4 0.00247 0.00354 0.00707 0.00318 0.00212 0.00389
+ 112_595 20:41:19 +00:16:11 11.352 1.601 1.993 0.899 0.901 1.801 46 37 0.00221 0.00162 0.00605 0.00088 0.00118 0.00147
+ 112_704 20:42:03 +00:18:53 11.452 1.536 1.742 0.822 0.746 1.570 19 12 0.00298 0.00229 0.00757 0.00206 0.00184 0.00252
+ 112_223 20:42:15 +00:08:44 11.424 0.454 0.010 0.273 0.274 0.547 45 37 0.00119 0.00089 0.00209 0.00119 0.00104 0.00164
+ 112_250 20:42:27 +00:07:25 12.095 0.532 -0.025 0.317 0.323 0.639 18 12 0.00212 0.00189 0.00424 0.00189 0.00189 0.00259
+ 112_275 20:42:36 +00:07:03 9.905 1.210 1.299 0.647 0.569 1.217 63 48 0.00013 0.00088 0.00252 0.00076 0.00050 0.00088
+ 112_805 20:42:47 +00:15:51 12.086 0.152 0.150 0.063 0.075 0.138 51 42 0.00098 0.00112 0.00280 0.00112 0.00154 0.00210
+ 112_822 20:42:56 +00:14:47 11.549 1.031 0.883 0.558 0.502 1.060 36 27 0.00117 0.00150 0.00400 0.00083 0.00100 0.00117
+ MARK_A2 20:43:54 -10:45:32 14.540 0.666 0.096 0.379 0.371 0.751 21 10 0.00284 0.00306 0.00458 0.00240 0.00502 0.00589
+ MARK_A1 20:43:58 -10:47:11 15.911 0.609 -0.014 0.367 0.373 0.740 25 10 0.00400 0.00900 0.01360 0.00440 0.01280 0.01480
+ MARK_A 20:43:59 -10:47:42 13.258 -0.242 -1.162 -0.115 -0.125 -0.241 39 22 0.00192 0.00176 0.00384 0.00176 0.00448 0.00480
+ MARK_A3 20:44:02 -10:45:39 14.818 0.938 0.651 0.587 0.510 1.098 22 10 0.00235 0.00341 0.01045 0.00213 0.00298 0.00448
+ WOLF_918 21:11:30 -13:08:22 10.868 1.494 1.146 0.981 1.088 2.065 8 4 0.00495 0.00389 0.00530 0.00247 0.00318 0.00283
+ G26_7 21:31:16 -09:47:28 12.005 1.669 1.235 1.300 1.695 2.986 6 3 0.00572 0.00367 0.02041 0.00531 0.00490 0.00735
+ 113_440 21:40:35 +00:41:32 11.796 0.637 0.167 0.363 0.350 0.715 2 1 0.00141 0.00141 0.00424 0.00000 0.00283 0.00212
+ 113_221 21:40:37 +00:20:47 12.071 1.031 0.874 0.550 0.490 1.041 24 10 0.00163 0.00204 0.00551 0.00184 0.00143 0.00225
+ 113_L1 21:40:47 +00:28:19 15.530 1.343 1.180 0.867 0.723 1.594 2 1 0.00424 0.05091 0.18668 0.00495 0.00495 0.00071
+ 113_337 21:40:49 +00:27:42 14.225 0.519 -0.025 0.351 0.331 0.682 5 3 0.01297 0.00581 0.00850 0.00716 0.00626 0.01163
+ 113_339 21:40:56 +00:27:44 12.250 0.568 -0.034 0.340 0.347 0.687 31 18 0.00198 0.00198 0.00377 0.00144 0.00162 0.00251
+ 113_342 21:41:00 +00:27:21 10.878 1.015 0.696 0.537 0.513 1.050 7 3 0.00151 0.00151 0.00605 0.00189 0.00227 0.00491
+ 113_233 21:41:00 +00:21:47 12.398 0.549 0.096 0.338 0.322 0.661 2 1 0.00212 0.00141 0.00071 0.00000 0.00071 0.00071
+ 113_239 21:41:08 +00:22:19 13.038 0.516 0.051 0.318 0.327 0.647 2 1 0.00566 0.00283 0.00424 0.00141 0.00354 0.00495
+ 113_241 21:41:10 +00:25:37 14.352 1.344 1.452 0.897 0.797 1.683 22 9 0.00192 0.00316 0.00559 0.00124 0.00313 0.00379
+ 113_245 21:41:14 +00:21:38 15.665 0.628 0.112 0.396 0.318 0.716 2 1 0.00919 0.00990 0.00212 0.02404 0.01061 0.03536
+ 113_459 21:41:15 +00:42:50 12.125 0.535 -0.018 0.307 0.313 0.623 4 2 0.00700 0.00550 0.00700 0.00550 0.00600 0.01050
+ 113_250 21:41:25 +00:20:28 13.160 0.505 -0.003 0.309 0.316 0.626 4 2 0.00250 0.00250 0.01650 0.00350 0.00450 0.00450
+ 113_466 21:41:28 +00:40:00 10.004 0.454 -0.001 0.281 0.282 0.563 58 41 0.00066 0.00079 0.00158 0.00092 0.00079 0.00118
+ 113_259 21:41:45 +00:17:24 11.742 1.194 1.221 0.621 0.543 1.166 48 34 0.00101 0.00159 0.00318 0.00101 0.00101 0.00130
+ 113_260 21:41:49 +00:23:39 12.406 0.514 0.069 0.308 0.298 0.606 23 11 0.00438 0.00209 0.00292 0.00188 0.00146 0.00188
+ 113_475 21:41:51 +00:39:05 10.306 1.058 0.844 0.570 0.527 1.098 40 30 0.00126 0.00111 0.00269 0.00095 0.00095 0.00111
+ 113_366 21:41:54 +00:29:08 13.537 1.096 0.896 0.623 0.588 1.211 2 1 0.00071 0.00495 0.00495 0.01131 0.00212 0.00990
+ 113_263 21:41:54 +00:25:24 15.481 0.280 0.074 0.194 0.207 0.401 4 1 0.01000 0.00800 0.02500 0.00350 0.01200 0.01400
+ 113_265 21:41:54 +00:17:49 14.934 0.639 0.101 0.411 0.395 0.807 9 4 0.01800 0.01200 0.01633 0.01600 0.01700 0.02633
+ 113_268 21:41:58 +00:19:40 15.281 0.589 -0.018 0.379 0.407 0.786 6 2 0.00327 0.00939 0.02286 0.00776 0.02082 0.02286
+ 113_34 21:41:59 +00:00:54 15.173 0.484 -0.054 0.306 0.346 0.652 2 1 0.00141 0.00354 0.02051 0.01061 0.01273 0.00212
+ 113_372 21:42:02 +00:28:23 13.681 0.670 0.080 0.395 0.370 0.766 2 1 0.00424 0.00283 0.01414 0.00424 0.00990 0.00636
+ 113_149 21:42:06 +00:09:14 13.469 0.621 0.043 0.379 0.386 0.765 2 1 0.00778 0.01485 0.00990 0.00495 0.00849 0.00424
+ 113_153 21:42:10 +00:14:53 14.476 0.745 0.285 0.462 0.441 0.902 3 2 0.10508 0.03811 0.05023 0.01212 0.01386 0.00635
+ 113_272 21:42:21 +00:20:44 13.904 0.633 0.067 0.370 0.340 0.710 2 1 0.00141 0.00071 0.02546 0.00071 0.01344 0.01202
+ 113_158 21:42:22 +00:13:56 13.116 0.723 0.247 0.407 0.374 0.782 3 2 0.00346 0.00231 0.00404 0.00289 0.00462 0.00289
+ 113_156 21:42:22 +00:11:58 11.224 0.526 -0.057 0.303 0.314 0.618 2 1 0.00354 0.00354 0.00566 0.00424 0.00071 0.00283
+ 113_491 21:42:25 +00:43:40 14.373 0.764 0.306 0.434 0.420 0.854 4 2 0.00250 0.00200 0.01850 0.00850 0.00950 0.01750
+ 113_492 21:42:28 +00:38:08 12.174 0.553 0.005 0.342 0.341 0.684 9 5 0.00333 0.00633 0.00633 0.00267 0.00333 0.00533
+ 113_493 21:42:29 +00:37:57 11.767 0.786 0.392 0.430 0.393 0.824 8 4 0.00389 0.00354 0.00636 0.00283 0.00177 0.00389
+ 113_495 21:42:30 +00:37:54 12.437 0.947 0.530 0.512 0.497 1.010 6 3 0.00245 0.00286 0.00531 0.00327 0.00367 0.00572
+ 113_163 21:42:36 +00:16:33 14.540 0.658 0.106 0.380 0.355 0.735 15 7 0.00413 0.00491 0.00930 0.00542 0.00826 0.01084
+ 113_281 21:42:39 +00:18:41 15.247 0.529 -0.026 0.347 0.359 0.706 2 1 0.00778 0.00141 0.03111 0.00212 0.03677 0.03889
+ 113_165 21:42:39 +00:15:20 15.639 0.601 0.003 0.354 0.392 0.746 2 1 0.00071 0.00566 0.02970 0.02121 0.04313 0.06435
+ 113_167 21:42:42 +00:15:55 14.841 0.597 -0.034 0.351 0.376 0.728 2 1 0.00071 0.00990 0.02404 0.00707 0.01414 0.02192
+ 113_177 21:42:57 +00:14:33 13.560 0.789 0.318 0.456 0.436 0.890 27 13 0.00520 0.00404 0.00597 0.00443 0.00366 0.00558
+ 113_182 21:43:09 +00:14:38 14.370 0.659 0.065 0.402 0.422 0.824 13 6 0.01442 0.00888 0.00888 0.00388 0.00860 0.00888
+ 113_187 21:43:21 +00:16:39 15.080 1.063 0.969 0.638 0.535 1.174 7 4 0.00605 0.01625 0.02986 0.00680 0.00416 0.00718
+ 113_189 21:43:28 +00:17:09 15.421 1.118 0.958 0.713 0.605 1.319 8 4 0.01379 0.01273 0.07142 0.01131 0.00742 0.01556
+ 113_307 21:43:31 +00:17:49 14.214 1.128 0.911 0.630 0.614 1.245 2 1 0.00495 0.02687 0.00354 0.00141 0.02192 0.01980
+ 113_191 21:43:34 +00:15:43 12.337 0.799 0.223 0.471 0.466 0.937 7 4 0.00416 0.00227 0.00454 0.00227 0.00227 0.00340
+ 113_195 21:43:41 +00:17:09 13.692 0.730 0.201 0.418 0.413 0.832 10 5 0.00506 0.00569 0.01012 0.00316 0.00379 0.00316
+ G93_48 21:52:25 +02:23:20 12.739 -0.008 -0.792 -0.097 -0.094 -0.191 56 40 0.00134 0.00120 0.00241 0.00120 0.00241 0.00267
+PG2213-006C 22:16:18 -00:22:18 15.109 0.721 0.177 0.426 0.404 0.830 7 4 0.00454 0.00567 0.00680 0.00227 0.00680 0.00643
+PG2213-006B 22:16:22 -00:21:51 12.706 0.749 0.297 0.427 0.402 0.829 7 4 0.00113 0.00227 0.00265 0.00076 0.00151 0.00151
+PG2213-006A 22:16:24 -00:21:29 14.178 0.673 0.100 0.406 0.403 0.808 9 5 0.00500 0.00333 0.00567 0.00300 0.00500 0.00600
+ PG2213-006 22:16:28 -00:21:17 14.124 -0.217 -1.125 -0.092 -0.110 -0.203 10 5 0.00221 0.00285 0.00632 0.00443 0.00854 0.00917
+ G156_31 22:38:28 -15:19:17 12.361 1.993 1.408 1.648 2.042 3.684 20 8 0.00268 0.00492 0.01297 0.00268 0.00268 0.00291
+ 114_531 22:40:37 +00:51:49 12.094 0.733 0.186 0.422 0.403 0.825 42 32 0.00108 0.00154 0.00278 0.00093 0.00123 0.00154
+ 114_637 22:40:43 +01:03:02 12.070 0.801 0.307 0.456 0.415 0.872 15 8 0.00439 0.00181 0.00800 0.00258 0.00232 0.00284
+ 114_446 22:41:04 +00:45:56 12.064 0.737 0.237 0.397 0.369 0.769 2 1 0.00354 0.00354 0.00636 0.00354 0.00283 0.00071
+ 114_654 22:41:26 +01:10:03 11.833 0.656 0.178 0.368 0.341 0.711 6 3 0.00082 0.00367 0.00572 0.00163 0.00327 0.00367
+ 114_656 22:41:35 +01:11:01 12.644 0.965 0.698 0.547 0.506 1.051 5 1 0.00358 0.00671 0.02191 0.00402 0.00179 0.00492
+ 114_548 22:41:37 +00:58:59 11.601 1.362 1.573 0.738 0.651 1.387 52 42 0.00139 0.00166 0.00582 0.00097 0.00097 0.00139
+ 114_750 22:41:45 +01:12:30 11.916 -0.041 -0.354 0.027 -0.015 0.011 57 46 0.00146 0.00132 0.00238 0.00132 0.00212 0.00252
+ 114_670 22:42:10 +01:10:09 11.101 1.206 1.223 0.645 0.561 1.208 16 10 0.00275 0.00150 0.01175 0.00200 0.00225 0.00200
+ 114_176 22:43:11 +00:21:09 9.239 1.485 1.853 0.800 0.717 1.521 60 43 0.00103 0.00129 0.00323 0.00065 0.00077 0.00090
+ GD_246 23:12:35 +10:50:27 13.094 -0.318 -1.187 -0.148 -0.183 -0.332 73 57 0.00176 0.00152 0.00222 0.00117 0.00281 0.00316
+ F_108 23:16:12 -01:50:35 12.958 -0.235 -1.052 -0.103 -0.135 -0.239 76 58 0.00138 0.00161 0.00206 0.00138 0.00287 0.00298
+ G156_57 22:53:16 -14:15:38 10.180 1.556 1.182 1.174 1.542 2.713 14 7 0.00267 0.00187 0.00722 0.00107 0.00267 0.00267
+ PG2317+046 23:19:55 +04:52:34 12.876 -0.246 -1.137 -0.074 -0.035 -0.118 10 4 0.00854 0.00411 0.00791 0.00316 0.00285 0.00791
+ PG2331+055 23:33:44 +05:46:35 15.182 -0.066 -0.487 -0.012 -0.031 -0.044 2 1 0.00566 0.00707 0.00354 0.00778 0.00566 0.01273
+PG2331+055A 23:33:49 +05:46:48 13.051 0.741 0.257 0.419 0.401 0.821 2 1 0.00212 0.00141 0.00141 0.00141 0.00141 0.00141
+PG2331+055B 23:33:51 +05:45:06 14.744 0.819 0.429 0.481 0.454 0.935 2 1 0.00354 0.00071 0.00141 0.00354 0.00636 0.00212
+PG2336+004B 23:38:38 +00:42:42 12.431 0.507 -0.035 0.314 0.316 0.625 2 1 0.00071 0.00212 0.00212 0.00000 0.00141 0.00141
+PG2336+004A 23:38:42 +00:42:24 11.277 0.679 0.135 0.398 0.372 0.767 2 1 0.00071 0.00141 0.00000 0.00000 0.00141 0.00141
+ PG2336+004 23:38:43 +00:42:55 15.899 -0.172 -0.781 -0.061 -0.048 -0.110 2 1 0.01131 0.00990 0.00071 0.00919 0.01273 0.02263
+ 115_554 23:41:31 +01:26:24 11.812 1.005 0.548 0.586 0.538 1.127 2 1 0.00424 0.00283 0.00283 0.00566 0.00212 0.00283
+ 115_486 23:41:33 +01:16:43 12.482 0.493 -0.049 0.298 0.308 0.607 16 9 0.00250 0.00350 0.00475 0.00200 0.00200 0.00200
+ 115_412 23:42:01 +01:08:58 12.209 0.573 -0.040 0.327 0.335 0.665 2 1 0.00212 0.00495 0.00354 0.00071 0.00212 0.00212
+ 115_268 23:42:30 +00:52:09 12.494 0.634 0.077 0.366 0.348 0.714 1 1 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+ 115_420 23:42:36 +01:05:56 11.161 0.468 -0.027 0.286 0.293 0.580 51 42 0.00126 0.00112 0.00196 0.00126 0.00098 0.00154
+ 115_271 23:42:41 +00:45:08 9.695 0.615 0.101 0.353 0.349 0.701 77 55 0.00103 0.00103 0.00137 0.00091 0.00080 0.00114
+ 115_516 23:44:15 +01:14:11 10.434 1.028 0.759 0.563 0.534 1.098 60 49 0.00116 0.00103 0.00194 0.00090 0.00077 0.00103
+ PG2349+002 23:51:53 +00:28:17 13.277 -0.191 -0.921 -0.103 -0.116 -0.219 11 5 0.00633 0.01055 0.00784 0.00573 0.00784 0.00603
diff --git a/noao/digiphot/photcal/catalogs/porter.dat b/noao/digiphot/photcal/catalogs/porter.dat
new file mode 100644
index 00000000..6bd8111b
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/porter.dat
@@ -0,0 +1,85 @@
+# ID V error(V) UB error(UB) BV error(BV) VR error(VR) RI error(RI)
+#
+M67-81 10.024 0.011 -0.388 0.010 -0.080 0.015 -0.040 0.011 -0.028 0.011
+M67-105 10.302 0.011 1.318 0.015 1.266 0.009 0.650 0.010 0.580 0.010
+M67-106 13.095 0.007 0.060 0.028 0.562 0.017 0.338 0.016 0.332 0.007
+M67-108 9.711 0.015 1.539 0.005 1.370 0.014 0.707 0.017 0.644 0.011
+M67-111 12.730 0.010 0.051 0.009 0.560 0.007 0.319 0.009 0.318 0.011
+M67-117 12.625 0.015 0.278 0.005 0.784 0.015 0.466 0.005 0.438 0.006
+M67-124 12.119 0.028 0.043 0.038 0.457 0.007 0.280 0.010 0.278 0.003
+M67-127 12.776 0.020 0.064 0.011 0.552 0.013 0.322 0.016 0.328 0.007
+M67-128 13.162 0.010 0.045 0.017 0.569 0.014 0.338 0.014 0.310 0.030
+M67-129 13.189 0.022 0.075 0.019 0.574 0.020 0.341 0.014 0.348 0.024
+M67-130 12.894 0.023 0.029 0.033 0.448 0.019 0.283 0.017 0.292 0.010
+M67-132 13.107 0.010 0.063 0.015 0.606 0.009 0.347 0.015 0.343 0.018
+M67-134 12.262 0.019 0.065 0.021 0.580 0.007 0.334 0.010 0.325 0.023
+M67-135 11.445 0.012 0.913 0.010 1.060 0.010 0.556 0.004 0.499 0.011
+M67-141 10.476 0.015 1.010 0.020 1.106 0.009 0.570 0.014 0.520 0.010
+M67-149 12.562 0.013 0.071 0.030 0.606 0.009 0.341 0.001 0.331 0.010
+M67-170 9.678 0.011 1.483 0.009 1.355 0.005 0.697 0.006 0.628 0.004
+M67-I-9 13.209 0.012 0.048 0.010 0.569 0.009 0.329 0.002 0.323 0.004
+M67-I-51 14.160 0.029 0.070 0.020 0.600 0.020 0.326 0.010 0.291 0.013
+M92-A 14.036 0.010 0.325 0.029 0.798 0.026 0.516 0.014 0.417 0.014
+M92-B 16.791 0.023 -0.132 0.017 0.636 0.015 0.403 0.006 0.368 0.043
+M92-C 17.542 0.015 -0.254 0.039 0.550 0.017 0.357 0.017 0.323 0.020
+M92-IX-2 14.694 0.019 0.093 0.017 0.788 0.033 0.485 0.017 0.454 0.018
+M92-IX-5 13.078 0.012 0.020 0.008 0.612 0.016 0.257 0.060 0.421 0.119
+M92-IX-6 14.579 0.014 0.109 0.025 0.800 0.021 0.485 0.009 0.461 0.033
+M92-IX-8 16.331 0.021 -0.442 0.012 -0.112 0.018 -0.038 0.010 -0.085 0.005
+M92-IX-9 16.052 0.009 -0.111 0.013 0.534 0.016 0.313 0.008 0.277 0.005
+M92-IX-10 14.618 0.014 0.111 0.018 0.783 0.019 0.486 0.014 0.464 0.035
+M92-IX-13 14.475 0.001 -0.015 0.044 0.567 0.028 0.403 0.016 0.362 0.030
+M92-IX-25 15.932 0.021 -0.079 0.009 0.574 0.030 0.351 0.015 0.302 0.019
+M92-IX-26 16.437 0.020 -0.478 0.004 -0.112 0.016 -0.041 0.010 -0.086 0.020
+M92-IX-31 15.146 0.023 0.844 0.030 1.025 0.018 0.630 0.020 0.522 0.019
+M92-IX-34 15.982 0.027 -0.026 0.014 0.637 0.072 0.433 0.013 0.411 0.013
+M92-IX-100 16.986 0.010 1.124 0.044 1.146 0.012 0.722 0.008 0.589 0.029
+M92-X-9 15.078 0.018 0.067 0.033 0.589 0.022 0.360 0.015 0.321 0.019
+M92-X-10 14.311 0.011 0.068 0.005 0.590 0.030 0.372 0.006 0.289 0.001
+N2264-A 15.765 0.001 0.714 0.020 1.092 0.020 0.598 0.020 0.689 0.020
+N2264-B 17.101 0.011 0.781 0.020 1.206 0.020 0.700 0.021 0.783 0.004
+N2264-239 17.635 0.008 0.435 0.001 1.326 0.001 0.776 0.001 0.826 0.001
+N2264-245 18.238 0.037 0.428 0.030 1.065 0.030 0.674 0.035 0.774 0.016
+N2264-252 17.623 0.001 0.808 0.001 1.200 0.001 0.671 0.018 0.778 0.003
+N2419-P 15.514 0.023 INDEF INDEF 0.582 0.019 0.332 0.016 0.350 0.012
+N2419-I 13.759 0.014 INDEF INDEF 0.673 0.008 0.385 0.007 0.387 INDEF
+N2419-Z 17.054 0.014 INDEF INDEF 1.269 0.035 0.803 0.007 0.734 0.017
+N2419-A-II-55 17.528 0.028 INDEF INDEF 0.599 INDEF 0.403 0.014 0.292 0.030
+N2419-A-II-73 18.250 0.189 INDEF INDEF 0.666 0.158 0.375 0.017 0.115 0.049
+N2419-A-II-89 17.552 0.170 INDEF INDEF 0.813 0.161 0.408 0.030 0.430 0.061
+N2419-B-II-11 16.836 0.015 INDEF INDEF 0.537 0.028 0.328 0.023 0.335 0.027
+N4147-6 16.773 0.017 0.199 0.038 0.828 0.017 0.477 0.014 0.475 0.011
+N4147-11 16.824 0.022 0.193 0.041 0.807 0.022 0.476 0.020 0.468 0.031
+N4147-12 17.663 0.025 0.976 0.090 1.156 0.022 0.700 0.022 0.601 0.017
+N4147-14 17.410 0.023 -0.059 0.026 -0.008 0.012 0.007 0.033 -0.015 0.032
+N4147-15 16.780 0.027 0.121 0.012 0.103 0.018 0.083 0.024 0.083 0.028
+N4147-119 17.464 0.019 0.079 0.081 0.752 0.014 0.452 0.017 0.446 0.019
+N4147-120 15.081 0.018 0.720 0.018 1.066 0.008 0.558 0.045 0.605 0.026
+N4147-122 16.424 0.020 -0.093 0.022 0.675 0.030 0.423 0.022 0.427 0.010
+N4147-124 16.989 0.009 -0.206 0.031 0.488 0.029 0.323 0.021 0.343 0.014
+N4147-141 16.891 0.018 0.102 0.047 0.713 0.025 0.409 0.022 0.388 0.014
+N7006-II-4 16.586 0.010 0.979 0.009 1.269 0.021 0.670 0.016 0.690 0.010
+N7006-II-6 17.506 0.019 0.541 0.075 1.019 0.018 0.558 0.003 0.606 0.010
+N7006-II-28 16.798 0.014 0.806 0.187 1.210 0.024 0.659 0.010 0.655 0.010
+N7006-III-1 16.480 0.018 1.210 0.049 1.280 0.026 0.783 0.018 0.711 0.020
+N7006-III-5 16.767 0.014 0.569 0.025 0.938 0.010 0.549 0.008 0.516 0.010
+N7006-III-7 17.910 0.007 0.456 0.063 0.971 0.029 0.524 0.003 0.567 0.010
+N7006-III-17 16.141 0.018 0.367 0.051 0.835 0.014 0.450 0.011 0.444 0.010
+N7006-III-31 13.889 0.017 INDEF INDEF 0.836 0.030 0.450 0.032 0.417 0.001
+N7006-III-32 14.000 0.014 INDEF INDEF 1.100 0.037 0.583 0.031 0.572 0.001
+N7790-36 14.525 0.026 0.016 0.001 0.514 0.018 0.289 0.004 0.384 0.004
+N7790-37 14.722 0.028 0.047 0.004 0.494 0.011 0.283 0.001 0.375 0.001
+N7790-51 14.389 0.023 -0.007 0.007 0.461 0.009 0.249 0.003 0.345 0.003
+N7790-58 15.315 0.015 0.291 0.040 0.646 0.031 0.339 0.002 0.445 0.010
+N7790-59 15.924 0.010 0.299 0.035 0.619 0.028 0.311 0.007 0.421 0.005
+N7790-65 15.950 0.013 0.403 0.004 0.795 0.015 0.413 0.006 0.516 0.006
+N7790-72 14.231 0.022 -0.340 0.040 0.595 0.008 0.330 0.007 0.432 0.007
+N7790-77 15.954 0.011 0.344 0.037 0.772 0.032 0.421 0.011 0.547 0.005
+N7790-80 15.585 0.004 0.260 0.036 0.599 0.027 0.299 0.011 0.405 0.007
+N7790-88 15.753 0.009 0.445 0.040 1.047 0.022 0.567 0.011 0.590 0.031
+N7790-95 15.778 0.012 0.295 0.025 0.643 0.022 0.328 0.008 0.488 0.009
+N7790-96 15.745 0.006 0.338 0.023 0.761 0.027 0.399 0.009 0.517 0.004
+N7790-98 14.149 0.021 0.204 0.016 0.836 0.001 0.465 0.004 0.503 0.001
+N7790-104 15.216 0.006 0.169 0.020 0.592 0.024 0.299 0.002 0.409 0.002
+N7790-113 14.862 0.011 -0.027 0.007 0.541 0.007 0.294 0.001 0.381 0.001
+N7790-C-25 15.503 0.010 0.102 0.029 0.706 0.022 0.399 0.012 0.499 0.001
diff --git a/noao/digiphot/photcal/catalogs/tarnica.dat b/noao/digiphot/photcal/catalogs/tarnica.dat
new file mode 100644
index 00000000..12a2fb41
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/tarnica.dat
@@ -0,0 +1,12 @@
+# Sample transformation section for the Aarnica JHK system
+
+transformation
+
+fit j1=0.0, j2=0.05, j3=0.000
+JFIT : mJ = J + j1 + j2 * XJ + j3 * (J - K)
+
+fit h1=0.0, h2=0.05, h3=0.000
+HFIT : mH = H + h1 + h2 * XH + h3 * (H - K)
+
+fit k1=0.0, k2=0.05, k3=0.000
+KFIT : mK = K + k1 + k2 * XK + k3 * (H - K)
diff --git a/noao/digiphot/photcal/catalogs/telias.dat b/noao/digiphot/photcal/catalogs/telias.dat
new file mode 100644
index 00000000..e46891a2
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/telias.dat
@@ -0,0 +1,15 @@
+# Sample transformation section for the Elias JHKL system
+
+transformation
+
+fit j1=0.0, j2=0.05, j3=0.000
+JFIT : mJ = (K + JK) + j1 + j2 * XJ + j3 * JK
+
+fit h1=0.0, h2=0.05, h3=0.000
+HFIT : mH = (K + HK) + h1 + h2 * XH + h3 * HK
+
+fit k1=0.0, k2=0.05, k3=0.000
+KFIT : mK = K + k1 + k2 * XK + k3 * HK
+
+fit l1=0.0, l2=0.05, l3=0.000
+LFIT : mL = (K - KL) + l1 + l2 * XL + l3 * KL
diff --git a/noao/digiphot/photcal/catalogs/tlandolt.dat b/noao/digiphot/photcal/catalogs/tlandolt.dat
new file mode 100644
index 00000000..8b999804
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/tlandolt.dat
@@ -0,0 +1,23 @@
+# Sample transformation section for the Landolt UBVRI system
+
+transformation
+
+fit u1=0.0, u2=0.65, u3=0.000
+const u4=0.0
+UFIT : mU = (UB + BV + V) + u1 + u2 * XU + u3 * UB + u4 * UB * XU
+
+fit b1=0.0, b2=0.35, b3=0.000
+const b4=0.0
+BFIT : mB = (BV + V) + b1 + b2 * XB + b3 * BV + b4 * BV * XB
+
+fit v1=0.0, v2=0.17, v3=0.000
+const v4=0.0
+VFIT : mV = V + v1 + v2 * XV + v3 * BV + v4 * BV * XV
+
+fit r1=0.0, r2=0.08, r3=0.000
+const r4=0.0
+RFIT : mR = (V - VR) + r1 + r2 * XR + r3 * VR + r4 * VR * XR
+
+fit i1=0.0, i2=0.03, i3=0.000
+const i4=0.0
+IFIT : mI = (V - VI) + i1 + i2 * XI + i3 * VI + i4 * VI * XI
diff --git a/noao/digiphot/photcal/catalogs/tnicmos.dat b/noao/digiphot/photcal/catalogs/tnicmos.dat
new file mode 100644
index 00000000..c68c5b25
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/tnicmos.dat
@@ -0,0 +1,15 @@
+# Sample transformation section for the Persson et al JHKKs system
+
+transformation
+
+fit j1=0.0, j2=0.05, j3=0.000
+JFIT : mJ = J + j1 + j2 * XJ + j3 * (J - K)
+
+fit h1=0.0, h2=0.05, h3=0.000
+HFIT : mH = H + h1 + h2 * XH + h3 * (H - K)
+
+fit k1=0.0, k2=0.05, k3=0.000
+KFIT : mK = K + k1 + k2 * XK + k3 * (H - K)
+
+fit ks1=0.0, ks2=0.05, ks3=0.000
+KSFIT : mKs = Ks + ks1 + ks2 * XKs + ks3 * (H - Ks)
diff --git a/noao/digiphot/photcal/catalogs/tnlandolt.dat b/noao/digiphot/photcal/catalogs/tnlandolt.dat
new file mode 100644
index 00000000..4d195737
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/tnlandolt.dat
@@ -0,0 +1,23 @@
+# Sample transformation section for the new Landolt UBVRI system
+
+transformation
+
+fit u1=0.0, u2=0.65, u3=0.000
+const u4=0.0
+UFIT : mU = (UB + BV + V) + u1 + u2 * XU + u3 * UB + u4 * UB * XU
+
+fit b1=0.0, b2=0.35, b3=0.000
+const b4=0.0
+BFIT : mB = (BV + V) + b1 + b2 * XB + b3 * BV + b4 * BV * XB
+
+fit v1=0.0, v2=0.17, v3=0.000
+const v4=0.0
+VFIT : mV = V + v1 + v2 * XV + v3 * BV + v4 * BV * XV
+
+fit r1=0.0, r2=0.08, r3=0.000
+const r4=0.0
+RFIT : mR = (V - VR) + r1 + r2 * XR + r3 * VR + r4 * VR * XR
+
+fit i1=0.0, i2=0.03, i3=0.000
+const i4=0.0
+IFIT : mI = (V - VI) + i1 + i2 * XI + i3 * VI + i4 * VI * XI
diff --git a/noao/digiphot/photcal/catalogs/todewahn.dat b/noao/digiphot/photcal/catalogs/todewahn.dat
new file mode 100644
index 00000000..4d56ee56
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/todewahn.dat
@@ -0,0 +1,12 @@
+# Sample transformation section for the Odewahn BVR standards
+
+transformation
+
+fit b1=0.0, b2=0.35, b3=0.000, b4=0.000
+BFIT : mB = (BV + V) + b1 + b2 * XB + b3 * BV + b4 * BV * XB
+
+fit v1=0.0, v2=0.17, v3=0.000
+VFIT : mV = V + v1 + v2 * XV + v3 * BV
+
+fit r1=0.0, r2=0.08, r3=0.000
+RFIT : mR = (V - VR) + r1 + r2 * XR + r3 * VR
diff --git a/noao/digiphot/photcal/catalogs/tonlandolt.dat b/noao/digiphot/photcal/catalogs/tonlandolt.dat
new file mode 100644
index 00000000..4d195737
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/tonlandolt.dat
@@ -0,0 +1,23 @@
+# Sample transformation section for the new Landolt UBVRI system
+
+transformation
+
+fit u1=0.0, u2=0.65, u3=0.000
+const u4=0.0
+UFIT : mU = (UB + BV + V) + u1 + u2 * XU + u3 * UB + u4 * UB * XU
+
+fit b1=0.0, b2=0.35, b3=0.000
+const b4=0.0
+BFIT : mB = (BV + V) + b1 + b2 * XB + b3 * BV + b4 * BV * XB
+
+fit v1=0.0, v2=0.17, v3=0.000
+const v4=0.0
+VFIT : mV = V + v1 + v2 * XV + v3 * BV + v4 * BV * XV
+
+fit r1=0.0, r2=0.08, r3=0.000
+const r4=0.0
+RFIT : mR = (V - VR) + r1 + r2 * XR + r3 * VR + r4 * VR * XR
+
+fit i1=0.0, i2=0.03, i3=0.000
+const i4=0.0
+IFIT : mI = (V - VI) + i1 + i2 * XI + i3 * VI + i4 * VI * XI
diff --git a/noao/digiphot/photcal/catalogs/tporter.dat b/noao/digiphot/photcal/catalogs/tporter.dat
new file mode 100644
index 00000000..95ed9adf
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/tporter.dat
@@ -0,0 +1,23 @@
+# Sample transformation section for the Porter UBVRI system
+
+transformation
+
+fit u1=0.0, u2=0.65, u3=0.000
+const u4=0.0
+UFIT : mU = (UB + BV + V) + u1 + u2 * XU + u3 * UB + u4 * UB * XU
+
+fit b1=0.0, b2=0.35, b3=0.000
+const b4=0.0
+BFIT : mB = (BV + V) + b1 + b2 * XB + b3 * BV + b4 * BV * XB
+
+fit v1=0.0, v2=0.17, v3=0.000
+const v4=0.0
+VFIT : mV = V + v1 + v2 * XV + v3 * BV + v4 * BV * XV
+
+fit r1=0.0, r2=0.08, r3=0.000
+const r4=0.0
+RFIT : mR = (V - VR) + r1 + r2 * XR + r3 * VR + r4 * VR * XR
+
+fit i1=0.0, i2=0.03, i3=0.000
+const i4=0.0
+IFIT : mI = (V - VR - RI) + i1 + i2 * XI + i3 * RI + i4 * RI * XI
diff --git a/noao/digiphot/photcal/catalogs/tukirt.dat b/noao/digiphot/photcal/catalogs/tukirt.dat
new file mode 100644
index 00000000..b7ec53df
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/tukirt.dat
@@ -0,0 +1,12 @@
+# Sample transformation section for the UKIRT JHK system
+
+transformation
+
+fit j1=0.0, j2=0.05, j3=0.000
+JFIT : mJ = (K + JK) + j1 + j2 * XJ + j3 * JK
+
+fit h1=0.0, h2=0.05, h3=0.000
+HFIT : mH = (K + HK) + h1 + h2 * XH + h3 * HK
+
+fit k1=0.0, k2=0.05, k3=0.000
+KFIT : mK = K + k1 + k2 * XK + k3 * HK
diff --git a/noao/digiphot/photcal/catalogs/ukirt.dat b/noao/digiphot/photcal/catalogs/ukirt.dat
new file mode 100644
index 00000000..02de0d1a
--- /dev/null
+++ b/noao/digiphot/photcal/catalogs/ukirt.dat
@@ -0,0 +1,34 @@
+ FS01 12.967 0.021 0.462 0.011 0.081 0.012
+ FS02 10.466 0.003 0.247 0.003 0.038 0.003
+ FS03 12.822 0.007 -0.222 0.011 -0.097 0.007
+ FS04 10.264 0.005 0.292 0.003 0.040 0.007
+ FS05 12.342 0.006 -0.007 0.004 -0.002 0.004
+ FS06 13.374 0.015 -0.135 0.014 -0.069 0.012
+ FS07 10.940 0.005 0.165 0.012 0.037 0.010
+ FS08 8.313 0.006 0.766 0.002 0.129 0.004
+ FS09 8.266 0.006 0.884 0.003 0.158 0.005
+ FS10 14.919 0.072 -0.170 0.077 -0.049 0.060
+ FS11 11.278 0.018 0.076 0.025 0.016 0.019
+ FS12 13.898 0.003 -0.217 0.014 -0.091 0.018
+ FS13 10.135 0.003 0.382 0.002 0.047 0.005
+ FS14 14.261 0.012 -0.153 0.005 -0.079 0.020
+ FS15 12.360 0.021 0.418 0.008 0.060 0.007
+ FS16 12.631 0.008 0.340 0.006 0.038 0.005
+ FS17 12.270 0.007 0.411 0.007 0.073 0.003
+ FS18 10.522 0.008 0.292 0.003 0.031 0.003
+ FS19 13.796 0.025 -0.231 0.021 -0.142 0.047
+ FS20 13.473 0.017 -0.120 0.015 -0.069 0.012
+ FS21 13.132 0.004 -0.184 0.033 -0.101 0.037
+ FS33 14.240 0.016 -0.223 0.010 -0.078 0.024
+ FS23 12.374 0.001 0.623 0.004 0.072 0.018
+ FS24 10.753 0.008 0.151 0.006 0.019 0.004
+ FS25 9.756 0.017 0.475 0.003 0.070 0.005
+ FS26 7.972 0.009 0.858 0.004 0.155 0.006
+ FS27 13.123 0.018 0.371 0.013 0.058 0.014
+ FS28 10.597 0.016 0.148 0.010 0.047 0.005
+ FS35 11.757 0.017 0.474 0.008 0.089 0.005
+ FS34 12.989 0.011 -0.170 0.008 -0.070 0.009
+ FS29 13.346 0.024 -0.171 0.011 -0.075 0.012
+ FS30 12.015 0.020 -0.092 0.013 -0.036 0.005
+ FS31 14.039 0.010 -0.241 0.020 -0.120 0.017
+ FS32 13.664 0.012 -0.205 0.022 -0.088 0.015
diff --git a/noao/digiphot/photcal/chkconfig.par b/noao/digiphot/photcal/chkconfig.par
new file mode 100644
index 00000000..87688df2
--- /dev/null
+++ b/noao/digiphot/photcal/chkconfig.par
@@ -0,0 +1,4 @@
+# Parameter file for CHKCONFIG
+
+config,f,a,,,,Input configuration file
+verbose,b,h,no,,,Verbose output ?
diff --git a/noao/digiphot/photcal/config.par b/noao/digiphot/photcal/config.par
new file mode 100644
index 00000000..353fc2c4
--- /dev/null
+++ b/noao/digiphot/photcal/config.par
@@ -0,0 +1,8 @@
+# Parameter file for CONFIG
+
+config,f,a,,,,The new configuration file
+catalog,f,h,"",,,The source of the catalog format description
+observations,f,h,"",,,The source of the observations format description
+transform,f,h,"",,,The source of the transformation equations
+template,f,h,"",,,An existing template configuration file
+verify,b,h,no,,,Verify each new configuration file entry ?
diff --git a/noao/digiphot/photcal/debug/README b/noao/digiphot/photcal/debug/README
new file mode 100644
index 00000000..09f34a17
--- /dev/null
+++ b/noao/digiphot/photcal/debug/README
@@ -0,0 +1 @@
+This directory contains code used for debugging.
diff --git a/noao/digiphot/photcal/debug/debug.h b/noao/digiphot/photcal/debug/debug.h
new file mode 100644
index 00000000..f26948d1
--- /dev/null
+++ b/noao/digiphot/photcal/debug/debug.h
@@ -0,0 +1,2 @@
+# Dump file
+define DUMPFILE "dump.log"
diff --git a/noao/digiphot/photcal/debug/debug.par b/noao/digiphot/photcal/debug/debug.par
new file mode 100644
index 00000000..504a0d3b
--- /dev/null
+++ b/noao/digiphot/photcal/debug/debug.par
@@ -0,0 +1,14 @@
+# Parameter file for the DEBUG task
+
+lexcode,b,h,no,,,Debug lexer code
+parcode,b,h,no,,,Debug parser code
+parvars,b,h,no,,,Dump parser variables
+partable,b,h,no,,,Dump parser tables
+fitcode,b,h,no,,,Debug fitcoeffs code
+photcode,b,h,no,,,Debug photproc code
+iocode,b,h,no,,,Debug i/o code
+cattable,b,h,no,,,Dump catalog data table
+obstable,b,h,no,,,Dump catalog observations table
+reftable,b,h,no,,,Dump reference equation table
+wtstable,b,h,no,,,Dump weight table
+nlfit,b,h,no,,,Dump NLFIT structure
diff --git a/noao/digiphot/photcal/debug/dginl.x b/noao/digiphot/photcal/debug/dginl.x
new file mode 100644
index 00000000..62e93c1b
--- /dev/null
+++ b/noao/digiphot/photcal/debug/dginl.x
@@ -0,0 +1,30 @@
+include "debug.h"
+
+# DG_INLDUMP -- Dump the NLFIT and INLFIT structures into a file.
+
+procedure dg_inldump (in, nl)
+
+pointer in # INLFIT descriptor
+pointer nl # NLFIT descriptor
+
+int fd
+
+int open()
+
+begin
+ # Open the dump file.
+ iferr (fd = open (DUMPFILE, APPEND, TEXT_FILE))
+ return
+
+ # Put in the time stamp.
+ call dg_ptime (fd, "dg_inldump")
+
+ # Dump the NLFIT structure.
+ call nl_dumpr (fd, nl)
+
+ # Dump the INLFIT structure.
+ call in_dumpr (fd, in)
+
+ # Close the dump file.
+ call close (fd)
+end
diff --git a/noao/digiphot/photcal/debug/dgparser.x b/noao/digiphot/photcal/debug/dgparser.x
new file mode 100644
index 00000000..7056fef5
--- /dev/null
+++ b/noao/digiphot/photcal/debug/dgparser.x
@@ -0,0 +1,567 @@
+include "../lib/parser.h"
+include "../lib/prstruct.h"
+include "../lib/preval.h"
+include "debug.h"
+
+# DG_PRVDUMP -- Dump the parser variables.
+
+procedure dg_prvdump (label)
+
+char label[ARB] # string label
+
+int fd
+
+include "../parser/parser.com"
+
+bool clgetb()
+int open()
+
+begin
+ # Debug ?
+ if (!clgetb ("debug.parvars"))
+ return
+
+ # Open the log file.
+ iferr (fd = open (DUMPFILE, APPEND, TEXT_FILE))
+ return
+
+ # Put in the time stamp.
+ call dg_ptime (fd, label)
+
+ # Dump the table pointers.
+ call fprintf (fd, "(obstable=%d) (cattable=%d) (partable=%d)\n")
+ call pargi (obstable)
+ call pargi (cattable)
+ call pargi (partable)
+ call fprintf (fd, "(settable=%d) (exttable=%d) (trntable=%d)\n")
+ call pargi (settable)
+ call pargi (exttable)
+ call pargi (trntable)
+ call fprintf (fd, "(trobstable=%d) (trcattable=%d)\n")
+ call pargi (trobstable)
+ call pargi (trcattable)
+ call fprintf (fd, "(tfobstable=%d) (tfcattable=%d)\n")
+ call pargi (tfobstable)
+ call pargi (tfcattable)
+ call fprintf (fd, "(tpartable=%d)\n")
+ call pargi (tpartable)
+
+ # Dump the counters.
+ call fprintf (fd, "(nerrors=%d) (nwarnings=%d)\n")
+ call pargi (nerrors)
+ call pargi (nwarnings)
+ call fprintf (fd,
+ "(nobsvars=%d) (ncatvars=%d) (nfitpars=%d) (ntotpars=%d)\n")
+ call pargi (nobsvars)
+ call pargi (ncatvars)
+ call pargi (nfitpars)
+ call pargi (ntotpars)
+ call fprintf (fd, "(nseteqs=%d) (nexteqs=%d) (ntrneqs=%d)\n")
+ call pargi (nseteqs)
+ call pargi (nexteqs)
+ call pargi (ntrneqs)
+
+ # Dump the column limits.
+ call fprintf (fd, "(mincol=%d)\n")
+ call pargi (mincol)
+ call fprintf (fd, "(minobscol=%d) (maxobscol=%d)\n")
+ call pargi (minobscol)
+ call pargi (maxobscol)
+ call fprintf (fd, "(mincatcol=%d) (maxcatcol=%d)\n")
+ call pargi (mincatcol)
+ call pargi (maxcatcol)
+
+ # Dump the flags.
+ call fprintf (fd, "(flageqsect=%d) (flagerrors=%d)\n")
+ call pargi (flageqsect)
+ call pargi (flagerrors)
+
+ # Close the dump file.
+ call close (fd)
+end
+
+
+# DG_PRTDUMP -- Dump the parser symbol table.
+
+procedure dg_prtdump (label, stp)
+
+char label[ARB] # string label
+pointer stp # symbol table pointer
+
+int fd
+pointer sym
+
+bool clgetb()
+int open()
+pointer sthead(), stnext()
+
+begin
+ # Debug ?
+ if (!clgetb ("debug.partable"))
+ return
+
+ # Open lthe og file.
+ iferr (fd = open (DUMPFILE, APPEND, TEXT_FILE))
+ return
+
+ # Put in the time stamp.
+ call dg_ptime (fd, label)
+
+ # Check for the null pointer.
+ if (stp == NULL) {
+ call fprintf (fd, "dg_prdump: Null pointer\n")
+ return
+ }
+
+ # Dump the table.
+ sym = sthead (stp)
+ while (sym != NULL) {
+
+ # Dump the symbol information.
+ call dg_symdump (fd, stp, sym)
+
+ # Dump the substructure information (if any).
+ call dg_subdump (fd, stp, sym)
+
+ # Advance to next symbol.
+ sym = stnext (stp, sym)
+ }
+
+ # Close the dump file.
+ call close (fd)
+end
+
+
+# DG_SYMDUMP -- Dump symbol structure.
+
+procedure dg_symdump (fd, stp, sym)
+
+int fd # dump file descriptor
+pointer stp # table pointer
+pointer sym # symbol pointer
+
+
+pointer stname(), strefstab()
+
+begin
+ # Check for a null substructure pointer.
+ if (sym == NULL) {
+ call fprintf (fd, "-- dg_symdump: Null pointer\n")
+ return
+ }
+
+ # Print the main structure.
+ call fprintf (fd,
+ "-- dg_symdump: (%s) (sym=%d) (offset=%d) (type=%d) (num=%d) (sub=%d)\n")
+ call pargstr (Memc[stname (stp, sym)])
+ call pargi (sym - strefstab (stp, 0))
+ call pargi (sym)
+ call pargi (PSYM_TYPE (sym))
+ call pargi (PSYM_NUM (sym))
+ call pargi (PSYM_SUB (sym))
+ call flush (fd)
+end
+
+
+# DG_SUBDUMP -- Dump symbol substructure.
+
+procedure dg_subdump (fd, stp, sym)
+
+int fd # dump file descriptor
+pointer stp # table pointer
+pointer sym # symbol pointer
+
+pointer ptr
+
+begin
+ # Check for a null substructure pointer.
+ ptr = PSYM_SUB (sym)
+ if (ptr == NULL) {
+ call fprintf (fd, "dg_subdump: Null substructure pointer\n")
+ return
+ }
+
+ # Branch according to symbol type.
+ switch (PSYM_TYPE (sym)) {
+ case PTY_CATVAR, PTY_OBSVAR:
+ call dg_inpdump (fd, stp, ptr)
+ case PTY_FITPAR, PTY_CONST:
+ call dg_fitdump (fd, stp, ptr)
+ case PTY_SETEQ:
+ call dg_setdump (fd, stp, ptr)
+ case PTY_EXTEQ:
+ call dg_extdump (fd, stp, ptr)
+ case PTY_TRNEQ:
+ call dg_trndump (fd, stp, ptr)
+ default:
+ call fprintf (fd, "dg_subdump: Unknown symbol type\n")
+ }
+end
+
+
+# DG_INPDUMP -- Dump the input variable substructure.
+
+procedure dg_inpdump (fd, stp, ptr)
+
+int fd # dump file descriptor
+pointer stp # table pointer
+pointer ptr # substructure pointer
+
+bool itob()
+
+begin
+ # Print substructure pointer.
+ call fprintf (fd, "dg_inpdump: (ptr=%d)\n")
+ call pargi (ptr)
+
+ # Print input, error and weight columns.
+ call fprintf (fd, "(input=%d) (error=%d) (weight=%d) (spare=%b)\n")
+ call pargi (PINP_COL (ptr))
+ call pargi (PINP_ERRCOL (ptr))
+ call pargi (PINP_WTSCOL (ptr))
+ call pargb (itob (PINP_SPARE(ptr)))
+ call flush (fd)
+end
+
+
+# DG_FITDUMP -- Dump the set equation substructure.
+
+procedure dg_fitdump (fd, stp, ptr)
+
+int fd # dump file descriptor
+pointer stp # table pointer
+pointer ptr # substructure pointer
+
+begin
+ # Print the substructure pointer.
+ call fprintf (fd, "dg_fitdump: (ptr=%d)\n")
+ call pargi (ptr)
+
+ # Print the parameter value and delta.
+ call fprintf (fd, "(value=%g) (delta=%g)\n")
+ call pargr (PFIT_VALUE (ptr))
+ call pargr (PFIT_DELTA (ptr))
+end
+
+
+# DG_SETDUMP -- Dump the set equation substructure.
+
+procedure dg_setdump (fd, stp, ptr)
+
+int fd # dump file descriptor
+pointer stp # table pointer
+pointer ptr # substructure pointer
+
+pointer strefsbuf()
+
+begin
+ # Print the substructure pointer.
+ call fprintf (fd, "dg_setdump: (ptr=%d)\n")
+ call pargi (ptr)
+
+ # Print the equation string.
+ call fprintf (fd, "equation: %d [%s]\n")
+ call pargi (PSEQ_EQ (ptr))
+ call pargstr (Memc[strefsbuf (stp, PSEQ_EQ (ptr))])
+
+ # Print the error equation strings.
+ call fprintf (fd, "error: %d [%s]\n")
+ call pargi (PSEQ_ERROR (ptr))
+ call pargstr (Memc[strefsbuf (stp, PSEQ_ERROR (ptr))])
+ call fprintf (fd, "error max: %d [%s]\n")
+ call pargi (PSEQ_ERRMIN (ptr))
+ call pargstr (Memc[strefsbuf (stp, PSEQ_ERRMIN (ptr))])
+ call fprintf (fd, "error min: %d [%s]\n")
+ call pargi (PSEQ_ERRMAX (ptr))
+ call pargstr (Memc[strefsbuf (stp, PSEQ_ERRMAX (ptr))])
+
+ # Print the weight equation strings.
+ call fprintf (fd, "weight: %d [%s]\n")
+ call pargi (PSEQ_WEIGHT (ptr))
+ call pargstr (Memc[strefsbuf (stp, PSEQ_WEIGHT (ptr))])
+ call fprintf (fd, "error max: %d [%s]\n")
+ call pargi (PSEQ_WTSMIN (ptr))
+ call pargstr (Memc[strefsbuf (stp, PSEQ_WTSMIN (ptr))])
+ call fprintf (fd, "error min: %d [%s]\n")
+ call pargi (PSEQ_WTSMAX (ptr))
+ call pargstr (Memc[strefsbuf (stp, PSEQ_WTSMAX (ptr))])
+
+ # Print the equation code.
+ call fprintf (fd, "equation rpn: ")
+ call dg_cdump (fd, PSEQ_RPNEQ (ptr))
+
+ # Print the error equation codes.
+ call fprintf (fd, "error rpn: ")
+ call dg_cdump (fd, PSEQ_RPNERROR (ptr))
+ call fprintf (fd, "error min rpn: ")
+ call dg_cdump (fd, PSEQ_RPNERRMIN (ptr))
+ call fprintf (fd, "error max rpn: ")
+ call dg_cdump (fd, PSEQ_RPNERRMAX (ptr))
+
+ # Print the weight equation codes.
+ call fprintf (fd, "weight rpn: ")
+ call dg_cdump (fd, PSEQ_RPNWEIGHT (ptr))
+ call fprintf (fd, "weight min rpn: ")
+ call dg_cdump (fd, PSEQ_RPNWTSMIN (ptr))
+ call fprintf (fd, "weight max rpn: ")
+ call dg_cdump (fd, PSEQ_RPNWTSMAX (ptr))
+end
+
+
+# DG_EXTDUMP -- Dump the extinction equation substructure.
+
+procedure dg_extdump (fd, stp, ptr)
+
+int fd # dump file descriptor
+pointer stp # table pointer
+pointer ptr # substructure pointer
+
+begin
+ # Print the substructure pointer.
+ call fprintf (fd, "dg_extdump: (ptr=%d)\n")
+ call pargi (ptr)
+end
+
+
+# DG_TRNDUMP -- Dump the transformation equation substructure.
+
+procedure dg_trndump (fd, stp, ptr)
+
+int fd # dump file descriptor
+pointer stp # table pointer
+pointer ptr # substructure pointer
+
+int i
+
+pointer strefsbuf()
+
+begin
+ # Print substructure pointer, number of variables, and parameters
+ call fprintf (fd,
+ "dg_trndump: (ptr=%d) (nrcat=%d) (nrobs=%d) (nrvar=%d) (nfcat=%d) ")
+ call pargi (ptr)
+ call pargi (PTEQ_NRCAT (ptr))
+ call pargi (PTEQ_NROBS (ptr))
+ call pargi (PTEQ_NRVAR (ptr))
+ call pargi (PTEQ_NFCAT (ptr))
+ call fprintf (fd,
+ "(nfobs=%d) (nfvar=%d) (nvar=%d) (npar=%d) (nfpar=%d)\n")
+ call pargi (PTEQ_NFOBS (ptr))
+ call pargi (PTEQ_NFVAR (ptr))
+ call pargi (PTEQ_NVAR (ptr))
+ call pargi (PTEQ_NPAR (ptr))
+ call pargi (PTEQ_NFPAR (ptr))
+ call flush (fd)
+
+ # Print reference equation variable offsets.
+ call fprintf (fd, "Reference variable offsets:")
+ do i = 1, PTEQ_NRVAR (ptr) {
+ call fprintf (fd, " %d")
+ call pargi (PTEQ_REFVAR (ptr, i))
+ }
+ call fprintf (fd, "\n")
+ call flush (fd)
+
+ # Print reference equation counters.
+ call fprintf (fd, "Reference equation counters:")
+ do i = 1, PTEQ_NRVAR (ptr) {
+ call fprintf (fd, " %d")
+ call pargi (PTEQ_REFCNT (ptr, i))
+ }
+ call fprintf (fd, "\n")
+ call flush (fd)
+
+ # Print fit equation variable offsets.
+ call fprintf (fd, "Fit variable offsets:")
+ do i = 1, PTEQ_NFVAR (ptr) {
+ call fprintf (fd, " %d")
+ call pargi (PTEQ_FITVAR (ptr, i))
+ }
+ call fprintf (fd, "\n")
+ call flush (fd)
+
+ # Print fit equation counters.
+ call fprintf (fd, "Fit equation counters:")
+ do i = 1, PTEQ_NFVAR (ptr) {
+ call fprintf (fd, " %d")
+ call pargi (PTEQ_FITCNT (ptr, i))
+ }
+ call fprintf (fd, "\n")
+ call flush (fd)
+
+ # Print parameter offsets.
+ call fprintf (fd, "Parameter offsets:")
+ do i = 1, PTEQ_NPAR (ptr) {
+ call fprintf (fd, " %d")
+ call pargi (PTEQ_PAR (ptr, i))
+ }
+ call fprintf (fd, "\n")
+ call flush (fd)
+
+ # Print the parameter values.
+ call fprintf (fd, "Parameter values:")
+ do i = 1, PTEQ_NPAR (ptr) {
+ call fprintf (fd, " %g")
+ call pargr (PTEQ_PARVAL (ptr, i))
+ }
+ call fprintf (fd, "\n")
+ call flush (fd)
+
+ # Print the fitting parameter list.
+ call fprintf (fd, "Parameter list:")
+ do i = 1, PTEQ_NPAR (ptr) {
+ call fprintf (fd, " %d")
+ call pargi (PTEQ_PLIST (ptr, i))
+ }
+ call fprintf (fd, "\n")
+ call flush (fd)
+
+ # Print fit and reference equation strings.
+ call fprintf (fd, "Fit: %d [%s]\n")
+ call pargi (PTEQ_FIT (ptr))
+ call pargstr (Memc[strefsbuf (stp, PTEQ_FIT (ptr))])
+ call fprintf (fd, "Reference: %d [%s]\n")
+ call pargi (PTEQ_REF (ptr))
+ call pargstr (Memc[strefsbuf (stp, PTEQ_REF (ptr))])
+ call flush (fd)
+
+ # Print error equation strings.
+ call fprintf (fd, "Error: %d [%s]\n")
+ call pargi (PTEQ_ERROR (ptr))
+ call pargstr (Memc[strefsbuf (stp, PTEQ_ERROR (ptr))])
+ call fprintf (fd, "Error max: %d [%s]\n")
+ call pargi (PTEQ_ERRMIN (ptr))
+ call pargstr (Memc[strefsbuf (stp, PTEQ_ERRMIN (ptr))])
+ call fprintf (fd, "Error min: %d [%s]\n")
+ call pargi (PTEQ_ERRMAX (ptr))
+ call pargstr (Memc[strefsbuf (stp, PTEQ_ERRMAX (ptr))])
+ call flush (fd)
+
+ # Print weight equation strings.
+ call fprintf (fd, "Weight: %d [%s]\n")
+ call pargi (PTEQ_WEIGHT (ptr))
+ call pargstr (Memc[strefsbuf (stp, PTEQ_WEIGHT (ptr))])
+ call fprintf (fd, "Weight min: %d [%s]\n")
+ call pargi (PTEQ_WTSMIN (ptr))
+ call pargstr (Memc[strefsbuf (stp, PTEQ_WTSMIN (ptr))])
+ call fprintf (fd, "Weight max: %d [%s]\n")
+ call pargi (PTEQ_WTSMAX (ptr))
+ call pargstr (Memc[strefsbuf (stp, PTEQ_WTSMAX (ptr))])
+ call flush (fd)
+
+ # Print plot equation strings.
+ call fprintf (fd, "Plot x: %d [%s]\n")
+ call pargi (PTEQ_XPLOT (ptr))
+ call pargstr (Memc[strefsbuf (stp, PTEQ_XPLOT (ptr))])
+ call fprintf (fd, "Plot y: %d [%s]\n")
+ call pargi (PTEQ_YPLOT (ptr))
+ call pargstr (Memc[strefsbuf (stp, PTEQ_YPLOT (ptr))])
+ call flush (fd)
+
+ # Print derivative strings.
+ call fprintf (fd, "Derivatives:\n")
+ do i = 1, PTEQ_NPAR (ptr) {
+ call fprintf (fd, "%d ")
+ call pargi (i)
+ if (!IS_INDEFI (PTEQ_DER (ptr, i))) {
+ call fprintf (fd, "(%d) [%s]\n")
+ call pargi (PTEQ_DER (ptr, i))
+ call pargstr (Memc[strefsbuf (stp, PTEQ_DER (ptr, i))])
+ } else
+ call fprintf (fd, "INDEF\n")
+ }
+ call flush (fd)
+
+ # Print equation codes.
+ call fprintf (fd, "Fit rpn: ")
+ call dg_cdump (fd, PTEQ_RPNFIT (ptr))
+ call fprintf (fd, "Reference rpn: ")
+ call dg_cdump (fd, PTEQ_RPNREF (ptr))
+
+ # Print error equation codes.
+ call fprintf (fd, "Error rpn: ")
+ call dg_cdump (fd, PTEQ_RPNERROR (ptr))
+ call fprintf (fd, "Error min rpn: ")
+ call dg_cdump (fd, PTEQ_RPNERRMIN (ptr))
+ call fprintf (fd, "Error max rpn: ")
+ call dg_cdump (fd, PTEQ_RPNERRMAX (ptr))
+
+ # Print weight equation codes.
+ call fprintf (fd, "Weight rpn: ")
+ call dg_cdump (fd, PTEQ_RPNWEIGHT (ptr))
+ call fprintf (fd, "Weight min rpn: ")
+ call dg_cdump (fd, PTEQ_RPNWTSMIN (ptr))
+ call fprintf (fd, "Weight max rpn: ")
+ call dg_cdump (fd, PTEQ_RPNWTSMAX (ptr))
+
+ # Print plot equation codes.
+ call fprintf (fd, "Plot x rpn: ")
+ call dg_cdump (fd, PTEQ_RPNXPLOT (ptr))
+ call fprintf (fd, "Plot y rpn: ")
+ call dg_cdump (fd, PTEQ_RPNYPLOT (ptr))
+
+ # Print derivative codes.
+ call fprintf (fd, "Derivative rpn:\n")
+ do i = 1, PTEQ_NPAR (ptr) {
+ call fprintf (fd, "%d ")
+ call pargi (i)
+ call dg_cdump (fd, PTEQ_RPNDER (ptr, i))
+ }
+
+ # Flush output.
+ call flush (fd)
+end
+
+
+# DG_CDUMP -- Dump equation code.
+
+procedure dg_cdump (fd, code)
+
+int fd # dump file descriptor
+pointer code # equation code
+
+int i, n
+
+begin
+ # Check the pointer.
+ if (code == NULL) {
+ call fprintf (fd, "Null code\n")
+ return
+ } else {
+ call fprintf (fd, "(%d) [")
+ call pargi (code)
+ }
+ call flush (fd)
+
+ # Print the equation code.
+ i = 1
+ n = Memi[code + i - 1]
+ while (n != PEV_EOC) {
+
+ # Print instruction according to type.
+ if (n == PEV_OBSVAR || n == PEV_CATVAR || n == PEV_PARAM ||
+ n == PEV_SETEQ || n == PEV_EXTEQ || n == PEV_TRNEQ) {
+ call fprintf (fd, "%d,%d ")
+ call pargi (n)
+ i = i + 1
+ call pargi (Memi[code + i - 1])
+ } else if (n == PEV_NUMBER) {
+ call fprintf (fd, "%d,%g ")
+ call pargi (n)
+ i = i + 1
+ call pargr (Memr[code + i - 1])
+ } else {
+ call fprintf (fd, "%d ")
+ call pargi (Memi[code + i - 1])
+ }
+
+ # Get next instruction.
+ i = i + 1
+ n = Memi[code + i - 1]
+ }
+ call fprintf (fd, "%d]\n")
+ call pargi (PEV_EOC)
+
+ # Flush output.
+ call flush (fd)
+end
diff --git a/noao/digiphot/photcal/debug/dgptime.x b/noao/digiphot/photcal/debug/dgptime.x
new file mode 100644
index 00000000..e7cb9ae9
--- /dev/null
+++ b/noao/digiphot/photcal/debug/dgptime.x
@@ -0,0 +1,21 @@
+include <time.h>
+
+
+# DG_PTIME - Put time stamp into a text file
+
+procedure dg_ptime (fd, label)
+
+int fd # log file descriptor
+char label[ARB] # string label
+
+char str[SZ_TIME] # time string
+
+long clktime()
+
+begin
+ call cnvtime (clktime (long (0)), str, SZ_TIME)
+
+ call fprintf (fd, "\n**** %s **** (%s) ****\n")
+ call pargstr (str)
+ call pargstr (label)
+end
diff --git a/noao/digiphot/photcal/debug/dgtable.x b/noao/digiphot/photcal/debug/dgtable.x
new file mode 100644
index 00000000..c207ef29
--- /dev/null
+++ b/noao/digiphot/photcal/debug/dgtable.x
@@ -0,0 +1,241 @@
+include <time.h>
+include "debug.h"
+
+# DG_DCATDAT - Dump catalog data symbol table
+
+procedure dg_dcatdat (label, ctable, nvars)
+
+char label[ARB] # string label
+pointer ctable # catalog data symbol table
+int nvars # number of catalog variables
+
+int n
+int fd
+pointer sym
+
+bool clgetb()
+int open()
+pointer sthead(), stnext(), stname()
+
+begin
+ # Debug ?
+ if (!clgetb ("debug.cattable"))
+ return
+
+ # Open the dump file.
+ iferr (fd = open (DUMPFILE, APPEND, TEXT_FILE))
+ return
+
+ # Log the time.
+ call dg_ptime (fd, label)
+
+ # Test the pointer.
+ if (ctable == NULL) {
+ call fprintf (fd, "dg_dcatat: Null table pointer\n")
+ call close (fd)
+ return
+ }
+
+ # Print the title.
+ call fprintf (fd, "dg_dcatdat: (ctable=%d) (nvars=%d)\n")
+ call pargi (ctable)
+ call pargi (nvars)
+
+ # Print the values in reverse order.
+ sym = sthead (ctable)
+ while (sym != NULL) {
+
+ # Print the matching name.
+ call fprintf (fd, "%d: (%s) ")
+ call pargi (sym)
+ call pargstr (Memc[stname (ctable, sym)])
+
+ # Print the indices.
+ do n = 1, nvars {
+ call fprintf (fd, "%g ")
+ call pargr (Memr[P2R(sym + n - 1)])
+ }
+
+ # Skip one line.
+ call fprintf (fd, "\n")
+
+ # Advance to the next symbol.
+ sym = stnext (ctable, sym)
+ }
+
+ # Close the file.
+ call close (fd)
+end
+
+
+# DG_DCATOBS - Dump the catalog observation table.
+
+procedure dg_dcatobs (label, otable)
+
+char label[ARB] # string label
+pointer otable # observation table
+
+int fd
+int row, col
+
+bool clgetb()
+
+int open()
+int mct_nrows(), mct_maxcol(), mct_ncols()
+real mct_getr()
+
+begin
+ # Debug ?
+ if (!clgetb ("debug.obstable"))
+ return
+
+ # Open the dump file.
+ iferr (fd = open (DUMPFILE, APPEND, TEXT_FILE))
+ return
+
+ # Log the time.
+ call dg_ptime (fd, label)
+
+ # Test the table pointer.
+ if (otable == NULL) {
+ call fprintf (fd, "dg_dcatobs: Null observation table pointer\n")
+ call close (fd)
+ return
+ }
+
+ # Print the title.
+ call fprintf (fd,
+ "dg_dcatobs: (otable=%d) (maxcols=%d) (nrows=%d) (ncols=%d\n")
+ call pargi (otable)
+ call pargi (mct_maxcol (otable))
+ call pargi (mct_nrows (otable))
+ call pargi (mct_ncols (otable))
+
+ # Loop over all data in the table.
+ do row = 1, mct_nrows (otable) {
+
+ # Print the running number.
+ call fprintf (fd, "%3d : ")
+ call pargi (row)
+
+ # Print the values.
+ do col = 1, mct_maxcol (otable) {
+ call fprintf (fd, "%g ")
+ call pargr (mct_getr (otable, row, col))
+ }
+
+ # Skip one line.
+ call fprintf (fd, "\n")
+ }
+
+ # Close the file.
+ call close (fd)
+end
+
+
+# DG_DREF - Dump the reference table.
+
+procedure dg_dref (label, rtable)
+
+char label[ARB] # string label
+pointer rtable # reference table
+
+int n
+int fd
+
+bool clgetb()
+int open()
+int mct_nrows(), mct_maxcol(), mct_ncols()
+real mct_getr()
+
+begin
+ # Debug ?
+ if (!clgetb ("debug.reftable"))
+ return
+
+ # Open the dump file.
+ iferr (fd = open (DUMPFILE, APPEND, TEXT_FILE))
+ return
+
+ # Log the time.
+ call dg_ptime (fd, label)
+
+ # Test the pointer.
+ if (rtable == NULL) {
+ call fprintf (fd, "dg_dref: Null reference table pointer\n")
+ call close (fd)
+ return
+ }
+
+ # Print the title.
+ call fprintf (fd,
+ "dg_dref: (rtable=%d) (maxcols=%d) (nrows=%d) (ncols=%d)\n")
+ call pargi (rtable)
+ call pargi (mct_maxcol (rtable))
+ call pargi (mct_nrows (rtable))
+ call pargi (mct_ncols (rtable))
+
+ # Print the values.
+ do n = 1, mct_nrows (rtable) {
+ call fprintf (fd, "%d: %g\n")
+ call pargi (n)
+ call pargr (mct_getr (rtable, n, 1))
+ }
+
+ # Close the file.
+ call close (fd)
+end
+
+
+# DG_DWEIGHTS - Dump the weight table.
+
+procedure dg_dweights (label, wtable)
+
+char label[ARB] # string label
+pointer wtable # weight table
+
+int n
+int fd
+
+bool clgetb()
+int open()
+int mct_nrows(), mct_maxcol(), mct_ncols()
+real mct_getr()
+
+begin
+ # Debug ?
+ if (!clgetb ("debug.wtstable"))
+ return
+
+ # Open the dump file.
+ iferr (fd = open (DUMPFILE, APPEND, TEXT_FILE))
+ return
+
+ # Log the time.
+ call dg_ptime (fd, label)
+
+ # Test the table pointer.
+ if (wtable == NULL) {
+ call fprintf (fd, "dg_dweight: Null weight table pointer\n")
+ call close (fd)
+ return
+ }
+
+ # Print the title.
+ call fprintf (fd,
+ "dg_dweight: (wtable=%d) (maxcols=%d) (nrows=%d) (ncols=%d)\n")
+ call pargi (wtable)
+ call pargi (mct_maxcol (wtable))
+ call pargi (mct_nrows (wtable))
+ call pargi (mct_ncols (wtable))
+
+ # Print the values.
+ do n = 1, mct_nrows (wtable) {
+ call fprintf (fd, "%d: %g\n")
+ call pargi (n)
+ call pargr (mct_getr (wtable, n, 1))
+ }
+
+ # Close the file.
+ call close (fd)
+end
diff --git a/noao/digiphot/photcal/debug/mkpkg b/noao/digiphot/photcal/debug/mkpkg
new file mode 100644
index 00000000..82d36e01
--- /dev/null
+++ b/noao/digiphot/photcal/debug/mkpkg
@@ -0,0 +1,14 @@
+# The MKPKG file for the DEBUG task.
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ dginl.x debug.h
+ dgparser.x ../lib/parser.h ../lib/preval.h \
+ ../lib/prstruct.h debug.h
+ dgtable.x debug.h <time.h>
+ dgptime.x <time.h>
+ ;
diff --git a/noao/digiphot/photcal/doc/apfile.hlp b/noao/digiphot/photcal/doc/apfile.hlp
new file mode 100644
index 00000000..51c64034
--- /dev/null
+++ b/noao/digiphot/photcal/doc/apfile.hlp
@@ -0,0 +1,502 @@
+.help apfile Apr93 photcal
+.ih
+NAME
+apfile -- prepare an aperture corrections file from a list of photometry
+files using the daogrow algorithm
+.ih
+USAGE
+apfile photfiles incolumns naperts apercors
+.ih
+PARAMETERS
+.ls photfiles
+A list of text files containing the images names or image ids, x and y
+coordinates, filter ids, exposure times, airmasses, aperture radii,
+magnitudes, and magnitude errors
+of all the objects to be used to compute the aperture corrections.
+\fIPhotfiles\fR are assumed to be the output of the user's own digital
+photometry program. All the files in \fIphotfiles\fR must have the format
+specified by \fIincolumns\fR.
+.le
+.ls incolumns
+A list of ten numbers separated by commas or whitespace specifying
+which columns in \fIphotfiles\fR contain the following quantities: the
+image name or image id, x coordinate, y coordinate, filter id, exposure time,
+airmass, time of observation, first aperture radius, magnitude measured
+inside the first aperture radius, magnitude error measured inside the
+first aperture radius respectively.
+.le
+.ls naperts
+The number of aperture radii for which aperture radii, magnitudes, and
+magnitude errors are to be extracted from \fIphotfiles\fR.
+.le
+.ls apercors
+The name of the output text file containing the aperture
+corrections computed between \fIsmallap\fR and \fIlargeap\fR
+for each image in \fIphotfiles\fR.
+.le
+.ls smallap = 1
+The index of the smallest extracted aperture for which the aperture
+correction is to be computed.
+.le
+.ls largeap = 0
+The index of the largest extracted aperture for which the aperture
+correction is to be computed. If \fIlargeap\fR is 0, then
+the largest aperture is \fInaperts\fR.
+.le
+.ls magfile = ""
+The name of an optional output text file containing the magnitudes
+of all the stars in \fIphotfiles\fR, corrected to the aperture \fIlargeap\fR
+by using the measured magnitude and computed aperture correction at
+which the estimated error is a minimum.
+.le
+.ls logfile = ""
+The name of an optional output text file containing details of the curve
+of growth model fit for each image in \fIphotfiles\fR. If \fIlogfile\fR is
+"", no file is written. If \fIappend\fR = "no" a new logfile is written, if
+"yes" output is appended to an existing logfile.
+.le
+.ls plotfile = ""
+The name of an optional output plot file containing plots of the
+curve of growth model fit, the fit residuals versus aperture radius,
+magnitude inside the first aperture, x coordinate, and y coordinate,
+and the aperture correction versus aperture radius for each image
+in \fIphotfiles\fR. If \fIplotfile\fR is "", no file is written.
+If \fIappend\fR = "no" a new plotfile is written, if
+"yes" output is appended to an existing plotfile.
+.le
+.ls append = no
+Open \fIlogfile\fR and/or \fIplotfile\fR in append mode ?
+.le
+.ls obsparams = ""
+The name of an optional input text file containing the correct filter ids,
+exposure times, airmasses, and times of observation for each image
+whose values are either
+undefined or incorrectly stored in \fIphotfiles\fR. The observing parameters
+for each image are listed in \fIobsparams\fR,
+1 image per line with the image name in column 1 and the filter id,
+exposure time, airmass, and time of exposure in
+\fIobscolumns\fR. The image names must match those in \fIphotfiles\fR.
+.le
+.ls obscolumns = "2 3 4 5"
+The list of numbers separated by commas or whitespace specifying which
+columns in the text file \fIobsparams\fR contain the correct filter ids,
+exposure times, airmasses, and times of observation respectively. The
+number 0 can be used as
+a place holder in the obscolumns string. For example to correct only
+the \fIphotfiles\fR airmass values, \fIobscolumns\fR should be set to
+"0 0 column 0", where column is the airmass column number.
+.le
+.ls maglim = 0.10
+The maximum magnitude error permitted in the input magnitude measurements.
+Data at and following the first aperture radius whose associated magnitude
+measurement has an error greater than \fImagerr\fR is rejected on input.
+.le
+.ls nparams = 3
+The of number parameters in the five parameter curve of growth model to be fit.
+The remaining parameters 5 - nparams parameters are held constant.
+For \fInparams\fR = 3, the parameters \fIswings\fR,
+\fIpwings\fR, and \fIpgauss\fR are fit, and \fIrgescale\fR and
+and \fIxwings\fR maintain their default values.
+\fINparams\fR must be greater than or equal to one.
+.le
+.ls swings = 1.2
+The slope of the power law component of the analytic curve of growth model
+describing the seeing independent part of the stellar profile. For a
+physically reasonable profile \fIswings\fR must be greater than 1.
+.le
+.ls pwings = 0.1
+The fraction of the total power in the seeing independent
+part of the stellar profile, if \fIxwings\fR is 0.0.
+.le
+.ls pgauss = 0.5
+The fraction of the total power in the seeing dependent part of the
+profile contained in the gaussian rather than the exponential component
+of the analytic curve of growth function.
+.le
+.ls rgescale = 0.9
+The ratio of the exponential to the gaussian radial scale
+lengths in the seeing dependent part of the profile.
+In practice the curve of growth model fits for most data do not depend
+significantly on this parameter and it can be left at its default value.
+.le
+.ls xwings = 0.0
+A parameter describing the effect of airmass on the total power
+in the seeing independent part of the stellar profile, where this quantity
+is defined as defined as \fIpwings\fR + \fIxwings\fR * \fIairmass\fR.
+.le
+.ls interactive = yes
+Fit the curve of growth interactively ?
+.le
+.ls verify = no
+Verify interactive user input ? This option is used only if \fIobsparams\fR
+is set to the standard input STDIN.
+.le
+.ls gcommands = ""
+The interactive graphics cursor.
+.le
+.ls graphics = "stdgraph"
+The default graphics device.
+.le
+
+.ih
+DESCRIPTION
+
+APFILE takes a list of user generated text files \fIphotfiles\fR,
+containing image names or ids, x and y coordinates, filter ids, exposure times,
+airmasses, times of observation, aperture radii, measured magnitudes,
+and magnitude errors for
+one or more stars in one or more images, computes the aperture correction
+between the apertures \fIsmallap\fR and \fIlargeap\fR for each image using
+a weighted average of the computed model curve of growth and the observed
+curve of growth, and writes the results to \fIapercors\fR.
+
+APFILE computes the aperture corrections by performing the following steps:
+1) extracts the image names or ids, x and y coordinates, filter ids, exposure
+times, airmasses, times of observation
+and \fInaperts\fR aperture radii, measured magnitudes,
+and magnitude errors for all the objects in \fIphotfiles\fR, 2) rejects data
+for all aperture radii greater than any aperture radius for which the magnitude
+or magnitude error is INDEF, the magnitude error is > \fImaglim\fR,
+or the number of apertures left containing good data is < 2,
+3) adds in quadrature a magnitude error of 0.001 magnitudes to the extracted
+magnitude errors, 4) edits any incorrect or undefined values of
+the filter id, exposure time, airmass, and time of observation
+in \fIphotfiles\fR using the values
+in \fIobsparams\fR if defined, or default values of INDEF, 1.0, 1.25, and INDEF
+respectively, 5) computes the theoretical and observed curve of growth
+curve for each image, 6) computes the adopted curve of growth for each
+image by combining the theoretical and observed curves with weights that
+favor the observed curve at smaller aperture radii and the theoretical curve
+at larger aperture radii, 7) integrates the adopted growth curve between
+the \fIsmallap\fR and \fIlargeap\fR apertures to
+compute the final aperture correction, 8) writes the results for each image
+to \fIapercors\fR, 9) optionally computes magnitudes for all the stars
+in \fIphotfiles\fR corrected to \fIlargeap\fR using the observed magnitude
+and computed correction for which the signal to noise is highest,
+10) optionally writes a \fIlogfile\fR containing the details of the
+fit for all the individual images, 11) optionally writes a file of
+plots of the fit, the residuals, and the curve of growth for all the
+images.
+
+The parameter \fIincolumns\fR describes the format of \fIphotfiles\fR.
+\fIIncolumns\fR is a list of 9 numbers separated by commas or
+whitespace which specify the columns containing the following quantities:
+the image name or id, , the x coordinate, the y coordinate, the filter
+id, the exposure time, the airmass, the time of observation,
+the first aperture radius extracted,
+the first measured magnitude extracted,
+and the first magnitude error extracted. The number of aperture radii,
+magnitudes, and magnitude errors extracted are specified by \fInaperts\fR.
+For example if \fIincolumns\fR is "1,3,4,0,0,2,5,0,20,35" and \fInaperts\fR
+is 15, then the image name is assumed to be in column 1,
+the x and y coordinates in columns 3 and 4, the filter id, exposure time,
+and time of exposure
+are missing and will be assigned values of INDEF, 1.0, and INDEF respectively,
+the airmass is in column 2, the aperture
+radii in columns 5-19, the magnitudes in columns 20-34, and the magnitude
+errors in columns 35-49. The aperture radii must be written in
+\fIphotfiles\fR in increasing order of size. The columns image name,
+x coordinate, y coordinate, aperture radii, magnitude, and magnitude error
+are mandatory and must be present in \fIphotfiles\fR. The filter id,
+exposure time, and airmass columns are optional in which case they
+may be represented by a "0" in the appropriate place in \fIincolumns\fR.
+
+Values of the filter ids, exposure times, airmasses, and times of observation
+which are undefined
+or incorrect in \fIphotfiles\fR, can be entered or corrected by reading values
+from the file \fIobsparams\fR a simple multi-column text file with a
+format specified by \fIobscolumns\fR.
+If no values are read from \fIphotfiles\fR or \fIobsparams\fR default values
+for the filter id, exposure time, airmass, and time of observation
+of "INDEF", 1.0, 1.25, "INDEF" respectively will be assigned.
+It must be emphasized that the airmass is actually used in the curve of
+growth analysis only if \fInparams\fR is equal to
+5, and that the quantities filter id and exposure time are not used in
+the analysis at all. However if the user should wish to use the corrected
+magnitudes optionally computed and written to \fImagfile\fR in any subsequent
+analysis it is important to include the correct values of
+these quantities in \fImagfile\fR.
+
+If \fIinteractive\fR is "yes", the user can interact with the curve of
+growth fitting process by examining plots of the model fit, the residuals
+versus aperture radius, magnitude in the first aperture, x and y coordinates,
+and the aperture correction
+as a function of radius, by changing the number of parameters to be fit and
+their initial values, deleting and undeleting points with the graphics
+cursor, refitting the model curve of growth and reexamining the results
+until satisfied. Users must realize that when deleting and undeleting
+points with the graphics cursor data for all the apertures above
+the one being deleted or undeleted will also be deleted.
+
+The output aperture corrections file \fIapercors\fR is a simple text
+file containing the image name in column 1, the aperture correction
+computed from \fIsmallap\fR to \fIlargeap\fR in column 2, and the
+estimated error in the aperture correction in column 3.
+The sign of the aperture correction is such that the
+correction must be added to the observed magnitude to compute the corrected
+magnitude. \fIApercors\fR is written in a form suitable for input to
+the MKNOBSILE, MKOBSFILE, or OBSFILE tasks.
+
+If \fImagfile\fR is not "", a file containing the image name or id, x and y
+position, filter id, exposure time, airmass, magnitude corrected to
+\fIlargeap\fR using the observed magnitude and computed correction at the
+aperture radius with the highest signal-to-noise ratio, and the associated
+magnitude error, for all the stars in all the images in \fIphotfiles\fR.
+\fIMagfile\fR is written in a form suitable for input to the OBSFILE task.
+
+If \fIlogfile\fR is not "", all the details and diagnostics of the
+curve of growth fit are logged either to a new file, if \fIappend\fR = "no"
+or to a previously existing file, \fIappend\fR = "yes". The output
+consists of: 1) a banner listing
+the date, time, and \fIapercors\fR for which the entry is relevant, 2)
+a listing of the number of parameters \fInparams\fR in the five parameter
+curve of growth model to be fit, the initial values of all the parameters, and
+the small and large aperture numbers, 3) the fitted values of the
+curve of growth model parameters and their errors where parameters which
+were not fit have zero-valued errors, 4) the computed seeing radius
+for each image,
+5) the theoretical, observed, and adopted curves of growth and
+their associated errors, 6) the aperture correction to largeap,
+the estimated total aperture correction to an
+aperture radius twice the largest aperture radius, and the estimated error
+in the aperture correction, 7) the aperture
+correction from \fIsmallap\fR to \fIlargeap\fR, 8) for each star
+in the image the observed magnitudes, magnitude corrected to the largest
+aperture, and magnitude corrected to twice the largest aperture, and
+finally, 9) a summary of the mean adopted curve of growth, the mean residual,
+and the mean residual squared for all the data for all the images
+as a function of aperture radius.
+
+If \fIplotfile\fR is not "", plots of the final curve of growth model fit,
+residuals as a function of aperture radius, magnitude, x, y, and the
+aperture correction to the largest aperture \fIlargeap\fR
+for each image in \fIphotfiles\fR are saved in the plot metacode file
+\fIplotfile\fR..
+
+.ih
+CURSOR COMMANDS
+
+The following commands are available in interactive graphics cursor mode.
+
+.nf
+ Keystroke Commands
+
+? Print help
+w Print computed aperture correction
+c Print coordinates of star nearest cursor
+f Compute a new fit
+d Delete point(s) nearest the cursor
+u Undelete point(s) nearest the cursor
+m Plot the observed and model cog versus radius
+r Plot the cog fit residuals versus radius
+b Plot the cog fit residuals versus magnitude
+x Plot the cog residuals versus the x coordinate
+y Plot the cog residuals versus the y coordinate
+a Plot the aperture correction versus radius
+g Redraw the current plot
+n Move to the next image
+p Move to the previous image
+q Quit task
+
+ Colon commands
+
+:show parameters Show the initial cog model parameter values
+:show model Show the fitted cog model parameters
+:show seeing Show the computed seeing radii for all images
+:image [value] Show/set the image to be analyzed
+
+ Colon Parameter Editing Commands
+
+:smallap [value] Show/set the index of the smallest aperture
+:largeap [value] Show/set the index of the largest aperture
+:nparams [value] Show/set the number of cog model parameters to fit
+:swings [value] Show/set initial power law slope of stellar wings
+:pwings [value] Show/set fraction of total power in stellar wings
+:pgauss [value] Show/set fraction of total core power in gaussian
+:rgescale [value] Show/set ratio of exp to gauss radial scales
+:xwings [value] Show/set the extinction coefficient
+.fi
+
+.ih
+ALGORITHMS
+
+The algorithm used to compute the aperture correction is the DAOGROW
+algorithm developed by Peter Stetson (1990).
+
+In this algorithm the stellar profile is approximated by the following
+3 component model where P, G, E denote the power law, gaussian, and
+exponential analytic components of the model respectively. The subscript i
+denotes quantities that are a function of each image.
+
+.nf
+
+ I[r,X[i];RO[i],swings,pwings,pgauss,regscale,xwings] =
+ (pwings + X[i] * xwings) * P[r;swings] + (1 - pwings - X[i] *
+ xwings) * (pgauss * G[r;RO[i]] + (1 - pgauss) *
+ E[r;rgescale,RO[i]])
+
+ P[r;swings] = mnorm * (1 + r ** 2) ** swings
+ mnorm = (swings - 1) / PI
+
+ G[r;RO[i]] = gnorm * exp (-0.5 * r ** 2 / RO[i] ** 2)
+ gnorm = 1 / (2 * PI * RO[i] ** 2)
+
+ E[r;RO[i]] = hnorm * exp (-r / (rgescale * RO[i]))
+ hnorm = 1 / (2 * PI * (rgescale * RO[i]) ** 2)
+
+.fi
+
+This equation is actually applied to the magnitude differences between
+apertures where the observed magnitude differences are computed as follows
+for image i, star j, and aperture k.
+
+.nf
+
+ mdiff[i,j,k] = m[i,j,k] - m[i,j,k-1] k=2,..,naperts
+
+.fi
+
+
+The observed differences are fit by least-squares techniques to
+to the theoretical model differences represented by the following equation.
+
+.nf
+
+diff[i,j,k] = -2.5 * log10 (integral (2 * PI * r * I) from 0 to r[k] /
+ integral (2 * PI * r * I) from 0 to r[k-1])
+
+.fi
+
+The integrals of the three model components P, G, and E are the following.
+
+.nf
+
+ integral (2 * PI * r * P) = 1 - (1 + r ** 2) ** -swings
+
+ integral (2 * PI * r * G) = 1 - exp (-r ** 2 / (2 * RO[i] ** 2))
+
+ integral (2 * PI * r * H) = 1 + (1 + r / (rgescale * RO[i]) *
+ exp (-r / (rgescale * RO[i]))
+
+.fi
+
+In a given run of APFILE the seeing radius
+RO[i] is fit separately for each image, but the parameters swings, pwings,
+pgauss, rgescale, and xwings are fit to the entire data set. Therefore
+the RO[i] values define a family curves, each differing from the other
+by the seeing radius RO[i] alone. It turns out that for most data the
+fits do not depend significantly on the \fIrgescale\fR and \fIxwings\fR
+parameters. Therefore by default \fInparams\fR is set to 3 and
+\fIrgescale\fR and \fIxwings\fR are set to default values of 0.9 and 0.0
+respectively.
+
+After the theoretical and observed growth curves are computed for
+each image, they are combined to produce an adopted growth curve. The
+weighting scheme used in the combining process is such that at small radii
+where the observed magnitude differences have the smallest errors,
+the observed values,
+are favored, and at large radii the theoretical curve is favored. At
+all points in the computation of the theoretical curve, the observed curve,
+and the adopted curve, tests are made for deviant data points and these
+are down-weighted. The adopted curve is integrated between \fIsmallap\fr
+and \fIlargeap\fR to produce the aperture correction for each image.
+
+Because the error in the observed magnitudes grows rapidly toward
+larger radii, while the error in the aperture correction grows
+rapidly toward smaller radii, the combined error for the star will
+have some minimum value, usually at an intermediate aperture. If
+\fImagfile\fR is not "", the magnitudes corrected to \fIlargeap\fR
+using the observed magnitude and correction where the error
+is lowest are written to \fImagfile\fR, along with the image id, x and y
+coordinates, filter ids, exposure times, airmasses, and errors in the
+magnitude. This file can be read into the OBSFILE program so as to
+create a photometry catalog suitable for input into PHOTCAL.
+
+
+.ih
+REFERENCES
+
+A full description of the DAOGROW algorithm used by APFILE can be
+found in the article "On the Growth-Curve Method for Calibrating
+Stellar Photometry with CCDs" by Peter Stetson in PASP 102, 932
+(1990).
+
+.ih
+EXAMPLES
+
+1. Prepare an aperture corrections file from a set of observations
+from 5 different data frames taken in a single night. The input
+photometry files contain the image ids in column 1, the x and y positions
+in columns 3 and 4, the airmass in column 2, and the 15 aperture radii,
+magnitudes, and magnitude errors in columns 5-19,20-34,35-49 respectively.
+
+.nf
+ ph> apfile photfiles "1,3,4,0,0,2,0,5,20,35" 15 apercor
+
+ ... plot of the cog for the first image will appear
+
+ ... type r to examine fit residuals versus radius
+
+ ... type a to examine the aperture correction curve
+ versus radius
+
+ ... type n to look at results for next image
+
+ ... type d to remove a discrepant point
+
+ ... type f to refit the cog
+
+ ... type r to examine the residuals for this image
+
+ ... type p to recheck the residuals for the first image
+
+ ... step through the remaining image deleting points and
+ refitting as necessary
+
+ ... type q to quit
+
+ ... the compute aperture corrections will appear in apercor
+.fi
+
+2. Repeat the previous example in non-interactive mode saving all the
+details and plots of the fit in the log and plot file respectively.
+
+.nf
+ ph> apfile photfiles "1,3,4,0,0,2,0,5,20,35" 15 apercor \
+ inter- logfile=apercor.log plotfile=apercor.plot
+
+ ph> page apercor.log
+
+ ... page through the log file
+
+ ph> gkiextract apercor.plot "1-25" | stdplot
+
+ ... send all the plots of the fit to the default plotter
+.fi
+
+3. Compute the magnitudes corrected to largeap, of all the standard
+stars observed in a night using the observed magnitude and computed magnitude
+correction at the aperture radius with the lowest error. Assume that the
+format of the input photometry files is the same as in the two previous
+examples and the filter ids (U,B,V), exposure times, and airmasses were
+all present and correct in the photometry files.
+
+.nf
+ ph> apfile stdfiles "1,3,4,0,0,2,0,5,20,35" 15 apercor inter-\
+ magfile="stdfiles.ap" logfile=apercor.log\
+ plotfile=apercor.plot
+
+ ph> obsfile stdfiles.ap "1,2,3,4,5,6,7,8,9" "U,B,V" imsets stdobs
+
+ ... create a standard star observations file suitable for
+ input to the photcal package
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+mkapfile, mknobsfile,mkobsfile,obsfile
+.endhelp
diff --git a/noao/digiphot/photcal/doc/chkconfig.hlp b/noao/digiphot/photcal/doc/chkconfig.hlp
new file mode 100644
index 00000000..be3ed549
--- /dev/null
+++ b/noao/digiphot/photcal/doc/chkconfig.hlp
@@ -0,0 +1,42 @@
+.help chkconfig Aug91 noao.digiphot.photcal
+.ih
+NAME
+chkconfig -- Check the grammar and syntax of the configuration file
+.ih
+USAGE
+chkconfig config
+.ih
+PARAMETERS
+.ls config
+The name of the configuration file to be checked. \fIConfig\fR is the
+text file specifying both the format of the input files, and the form of
+transformation equations.
+.le
+.ls verbose = yes
+Print detailed diagnostic information on the standard output ?
+.le
+
+.ih
+DESCRIPTION
+
+CHKCONFIG parses the configuration file \fIconfig\fR line by line,
+searching for syntax and/or semantic errors. Its primary function is to aid
+the user in setting up a complete and correct set of transformation
+equations to be fit. CHKCONFIG is run automatically by the task MKCONFIG,
+but can also be run stand-alone at any time.
+
+.ih
+EXAMPLES
+
+Check the configuration file for grammar and syntax errors.
+
+.nf
+ph> chk config
+.fi
+
+.ih
+BUGS
+.ih
+SEE ALSO
+mkconfig,fitparams
+.endhelp
diff --git a/noao/digiphot/photcal/doc/config.hlp b/noao/digiphot/photcal/doc/config.hlp
new file mode 100644
index 00000000..7e44ca24
--- /dev/null
+++ b/noao/digiphot/photcal/doc/config.hlp
@@ -0,0 +1,679 @@
+.help config Aug91 noao.digiphot.photcal
+.ih
+INTRODUCTION
+
+The \fIconfiguration file\fR is a text file which describes how the input data
+is organized in the input standard star \fIcatalog\fR and the
+\fIobservations\fR files, and defines the form of the transformation
+equations required to convert from the observed or instrumental indices
+to the standard indices.
+
+The \fIcatalog\fR file contains the standard indices for a set of
+standard stars, referenced in the catalog by a name called the \fImatching
+name\fR. The matching name must be in the first column of the
+catalog and also must be unique, i.e. each catalog file
+entry is assumed to be unique. The standard indices may be in any column
+other than the first.
+
+The \fIobservations\fR files contain the observed indices for a
+subset of the standard stars and/or program stars, referenced in the
+file by a matching name, which must be in the first column of the
+observations file. The observed indices may be in any column other than
+the first. The names of the standard stars must match those
+in the catalog file.
+Only standard star observations whose matching names are found in the
+catalog file are used to compute the transformation equations.
+
+The configuration file is divided into three sections: the \fIcatalog
+section\fR which describes the format of the catalog file, the
+\fIobservations section\fR which describes the format of the observations
+file, and the \fItransformation section\fR which defines the form of
+the transformation equations. The catalog section must occur before the
+observation section in the configuration file, and the observation
+section must occur before the transformation section.
+
+The \fIcatalog\fR and \fIobservations sections\fR are used to assign
+names to the columns in the input file.
+The named columns can later be referenced in the transformation equations,
+by using the names
+as though they were variables in a programming language.
+
+The \fItransformation section\fR is used to define the equations to be solved,
+to specify which parameters are to be varied and which are to
+be held constant during the fitting process, and to assign initial values
+to all of the parameters.
+Any number of transformation equations may be defined in the
+transformation section.
+
+The transformation section may also be used, OPTIONALLY, to
+define temporary variables (\fIthe set equations\fR),
+define the derivatives of the transformation equations
+to be fit with respect to the parameters (\fIthe derivative equations or
+delta declarations\fR),
+define expressions for weights and errors (\fIthe weight and error
+equations\fR), and define the default expressions to be plotted
+during the interactive fitting process (\fIthe plot equation\fR).
+
+.ih
+THE CATALOG SECTION
+
+The catalog section is used to assign names to columns in the
+standard star catalog, and optionally, to associate error columns with
+the named columns.
+
+The catalog section begins with the keyword \fIcatalog\fR, followed by
+any number of name and error(name), column associations.
+
+.ls Syntax
+.nf
+catalog
+
+name number
+
+error(name) number
+.fi
+.le
+
+The first declaration creates a name column number association.
+It consists of a name followed
+by a column number. The name becomes the variable name
+for that column.
+
+The second declaration creates an error (name) column number association.
+It begins with the keyword \fIerror\fR, followed by a name in parentheses
+and a column number.
+The name must be the name of an input column previously declared in the
+catalog section. The error declarations are optional.
+
+The column number must be a decimal integer greater than two, since
+catalog files always reserve the first column for a matching name.
+This name is used to match objects in the catalog file with objects in the
+observations file.
+
+.ls Example
+.nf
+# Sample catalog section for the UBV system.
+
+catalog
+
+V 2
+error(V) 3
+BV 4
+error(BV) 5
+UB 6
+error(UB) 7
+.fi
+.le
+
+.ih
+THE OBSERVATION SECTION
+
+The observation section is used to assign names to columns in the
+observations files, and to optionally, associate error columns with the
+named columns.
+
+The observations section begins with the keyword \fIobservation\fR, followed by
+any number of name and error (name) column associations.
+
+.ls Syntax
+.nf
+observation
+
+name number
+
+error (name) number
+.fi
+.le
+
+The first declaration creates a name column number association.
+It consists of a name followed
+by a column number. The name becomes the variable name
+for that column.
+
+The second declaration creates an error (name) column number association.
+It starts with the keyword \fIerror\fR, followed by a name
+in parentheses, and a column number.
+The name must be the name of an input column previously declared in the
+observation section. The error declarations are optional.
+
+The column number must be a decimal integer greater two,
+since the first column of the observations file is reserved for a matching name.
+This name is used to match objects in the observations file with
+objects in the catalog file.
+
+.ls Example
+.nf
+# Sample observation section for the UBV system.
+
+observation
+
+u 2
+error(u) 3
+b 4
+error(b) 5
+v 6
+error(v) 7
+x 8
+.fi
+.le
+
+.ih
+THE TRANSFORMATION SECTION
+
+The transformation section is used to define the transformation equations,
+to specify which parameters are to be altered and which are to be
+held constant during the fitting process, and to assign initial values
+to the parameters.
+
+The transformation section begins with the keyword \fItransformation\fR,
+followed by the list of parameter declarations,
+followed by the transformation equation.
+
+.ls Syntax
+.nf
+transformation
+
+fit parameter = value, parameter = value, ...
+
+constant parameter = value, parameter = value, ...
+
+label : expression = expression
+ (function) (fit)
+.fi
+.le
+
+The \fIfit\fR keyword begins a list of the parameters to be fit.
+The named parameters will be fit if they are present
+in a transformation equation.
+The fit parameter values are used as the initial guesses for the
+parameters.
+
+The \fIconstant\fR keyword begins a list of the parameters to be held
+constant.
+The named parameters will not be fit. Instead the values are regarded
+as constant values in any transformation equation in which they appear.
+Constant parameter declarations are used to fix
+values if they are known, or to restrict the degrees
+of freedom of the fit.
+
+All parameters, both fit and constant, must be declared before the first
+equations in which they appear.
+There may be any number of fit and constant parameter declaration statements.
+Redefinitions are allowed, i.e., it is possible to declare a parameter with
+the fit keyword, and redefine it later with the constant keyword.
+The inverse is also true.
+
+The \fItransformation\fR equations are composed of three elements: the equation
+label, the function expression, and the fit expression.
+
+The \fIlabel\fR is used to assign a name to the equation and fit expression.
+The label can be any name not already in use. The ":" after the label is
+necessary to delimit it from the rest of the transformation equation
+definition. Labels are used primarily to associate the optional error,
+weight and plot equations with the appropriate transformation equations.
+However these labels can also be used in expressions belonging
+to subsequent equations, an action equivalent to replacing them with the
+fit expression they reference, before performing the actual evaluation.
+
+The \fIfunction\fR expression (left hand side of the "=" sign) is used as a
+reference expression, i.e. an expression that has no fitting or
+constant parameters in it. The function expression contains only values
+computed from the input data which are known before the fit starts.
+
+The \fIfit\fR expression (right hand side of the "=" sign) is an expression
+which contains the parameters, both those to be fit and those that are
+fixed.
+If this expression contains names defined
+in the catalog section , it will be possible to perform the fit,
+but will not be possible to apply the transformations in the forward
+sense to program observations that don't have matching catalog values.
+If the number of transformations equations is greater than or equal to
+the total number of catalog variables used in the transformation equations,
+it MAY be possible to invert the system of equations and so evaluate
+the catalog variables for program objects.
+
+.ls Example
+.nf
+
+# Sample transformation section for the UBV system
+
+transform
+
+# V equation
+
+fit v1 = 25.0, v2=0.03, v3=-0.17
+VFIT : V = v1 + v + v2 * (b - v) + v3 * x
+
+# B - V equation
+
+fit b1 = 2.10, b2 = 1.15, b3=-0.12
+const b4 = 0.0
+BVFIT : BV = b1 + b2 * (b - v) + b3 * x + b4 * (b - v) * x
+
+# U - B equation
+
+fit u1 = 3.45, u2 = 1.063, u3=-0.30
+const u4=0.0
+UBFIT : UB = u1 + u2 * (u - b) + u3 * x + u4 * (u - b) * x
+.fi
+.le
+
+.ih
+OPTIONAL TRANSFORMATION SECTION FEATURES
+
+The transformation section may also be used, OPTIONALLY, to define
+temporary variables (\fIthe set equations\fR), define explicitly the
+derivatives of the transformation equations to be fit with respect to the
+fit and constant parameters (\fIthe derivative equations or delta
+declarations\fR), define
+expressions for the weights and/or errors (\fIthe weight and error
+equations\fR), and define an equation to be plotted (\fIthe plot equation\fR).
+
+.ls The Set Equation
+.le
+
+The \fIset equations\fR are used to assign names to expressions. They are
+primarily intended for computing quantities not listed explicitly
+in the catalog or observation files, but that may be derived from them.
+
+.ls
+.nf
+syntax
+
+set name = expression
+.fi
+.le
+
+A set equation declaration begins with the \fIset\fR keyword,
+followed by
+a name, followed by an equal sign, followed by an expression.
+The expression may contain any name defined in the catalog and
+observation sections, or any names defined in a previous
+set equation.
+
+In the example below the variables
+V, BV and UB were declared in the catalog section, but the user wished
+to define a new variable U to simplify the form of one of the
+transformation equations.
+
+.ls
+.nf
+example
+
+set U = V + BV + UB
+.fi
+.le
+
+.ls The Delta Declaration and the Derivative Equations
+.le
+
+The \fIdelta\fR declaration statement or the \fIderivative\fR equation
+are used to tell
+the non-linear least squares routines how to compute the derivatives
+of the transformation equations with respect to the parameters to be fit.
+If the user does
+not specify how the derivatives are to be computed, a
+default value for delta (see below) is used and the fit proceeds. For most
+simple photometric transformations the default delta is entirely adequate,
+and no delta statements or derivative expressions are required.
+
+However the user can elect to specify the derivatives implicitly using
+the \fIdelta\fR
+declaration syntax, or to supply explicit expressions for the derivatives
+with respect to the parameters, using the \fIderivative\fR equation
+syntax. For transformation equations which are linearly dependent on
+their parameters, or in cases where the derivative expressions are
+very complex the delta statement syntax is preferred over the more
+correct derivative equation syntax. For non-analytic expressions the
+delta syntax is required.
+
+.ls
+.nf
+syntax
+
+delta parameter = value, parameter = value
+
+ or
+
+derivative (label, parameter) = expression
+.fi
+.le
+
+A \fIdelta\fR declaration begins with the \fIdelta\fR keyword,
+followed by a list of parameter value associations, where each value
+is the region over which the derivative with respect to that parameter
+will be computed empirically. All the delta values must be greater than zero.
+
+A \fIderivative\fR equation begins with the keyword \fIderivative\fR,
+followed by
+the label of the equation whose derivative is being computed and
+the name of the parameter
+with respect to which the derivative is being taken in parentheses, finally
+followed by the derivative
+expression itself.
+
+If both a derivative equation and a delta statement are given for the same
+parameter, the parser will issue a warning message, and the derivative
+equation will take precedence over the delta declaration.
+
+The following example shows how the derivatives for an equation can be
+specified in each of the two ways.
+
+.ls
+.nf
+example
+
+VFIT: V = v + v1 + v2 * x + v3 * (b - v)
+ delta v1=.1, v2=.05, v3=.02
+
+or
+
+VFIT: V = v + v1 - v2 * x + v3 * (b - v)
+ deriv (VFIT,v1) = 1.0
+ deriv (VFIT,v2) = x
+ deriv (VFIT,v3) = (b - v)
+.fi
+.le
+
+.ls Weight equation
+.le
+
+The weight equation can be used to specify the way the weights will be
+computed for each data point,
+for each transformation equation. The weight equation is optional, and
+whether or not the weight expression is actually used by the fitting procedure
+depends on the application. The minimum and maximum weight expressions
+are also optional.
+
+.ls
+.nf
+weight (label) = expression
+ min = expression max = expression
+
+.fi
+.le
+
+The \fIweight\fR equation begins with the \fIweight\fR keyword, followed by
+the label of the equation in parentheses, followed by an equal sign,
+followed by the weight expression. Optionally,
+the weight expression can be immediately followed by the \fImin\fR and
+\fImax\fR keywords
+each of which may be followed by an expression.
+The expressions may contain any names declared in the catalog or
+observations sections, names defined by a set equation, or parameters declared
+in a fit or constant statement. Users should be extremely cautious about
+the latter as weights are evaluated before the fit, i.e. before the
+fit parameters have assumed their final values.
+
+In the following example weights are set to 1 over the standard deviation
+of the v measurement, sigmav, where sigmav was declared in the observation
+section.
+
+.ls
+.nf
+example
+
+VFIT: V = v + v1 + v2 * x + v3 * (b - v)
+ weight (VFIT) = 1.0 / sigmav ** 2
+.fi
+.le
+
+.ls The Plot Equation
+.le
+
+The plot equation is used to specify the default expressions for the x and y
+axes respectively, to be plotted when the transformation equations are fit
+interactively. The plot
+defined by the plot equation will be in the graphics window
+after the initial fit, instead of the default residuals versus function plot.
+
+.ls
+.nf
+syntax
+
+plot (label) = expression, expression
+ (x axis) (y axis)
+.fi
+.le
+
+A \fIplot\fR equation begins with the \fIplot\fR keyword, followed by
+the label of the associated transformation equation in parentheses,
+followed by an equals
+sign, and finally followed by the plot expressions for the x and y axis
+separated
+by a comma.
+
+In the following example the user has decided he/she wants the default plot
+for the VFIT equation to be a plot of the residuals versus the
+observed (b - v) color.
+It should be emphasized that the user could also produce the same graph
+inside the interactive fitting routines by reprogramming one of the graph
+keys.
+
+.ls
+.nf
+example
+
+VFIT: V = v + v1 + v2 * x + v3 * (b - v)
+ plot (VFIT) = b - v, V - (v + v1 + v2 * x + v3 * (b - v))
+.fi
+.le
+
+.ls Error equation
+.le
+
+The error equation is used to specify the way the error will be computed for
+each data point for each transformation. The error equation is optional, and
+whether or not it is used by the fitting or evaluation procedures
+depends on the application. The minimum and maximum error expressions
+are also optional.
+
+.ls
+.nf
+syntax
+
+error (label) = expression
+ min = expression max = expression
+.fi
+.le
+
+An \fIerror\fR equation begins with the \fIerror\fR keyword, followed by
+the label of the associated transformation equation in brackets,
+followed by an equal sign,
+followed by the error expression. Optionally,
+the error expression can be followed by the \fImin\fR and \fImax\fR keywords
+each of which must be followed by an expression.
+The expressions may contain any names declared in the catalog or
+observations sections, names defined by a set equation, or parameters declared
+in a fit or constant statement.
+
+In the following example the error for each data point is set equal to the
+standard deviation of the v measurement, sigmav, which was declared earlier
+in the observation section.
+
+.ls
+.nf
+example
+
+VFIT: V = v + v1 - v2 * x + v3 * (b - v)
+ error (VFIT) = sigmav
+.fi
+.le
+
+.ih
+THE PHOTCAL LANGUAGE GLOSSARY
+
+The configuration file consists of a series of instructions, written by
+the user in a mini-language understood by the PHOTCAL parser, which tell
+the various PHOTCAL routines
+what to do. The basic elements of the language are numerical constants,
+identifiers, arithmetic operators, arithmetic expressions, and comment
+statements.
+
+Numerical \fIconstants\fR may be decimal integers or floating point numbers.
+Double precision and complex numbers are not supported. The INDEF constant
+is not supported, although it is permitted in the input data.
+
+An \fIidentifier\fR (keyword, name, label, function) is an upper or
+lowercase letter, followed by zero or more upper or lowercase letters or
+digits.
+Identifiers can be of any length up to the maximum text file line length.
+
+A \fIkeyword\fR is an identifier with special meaning to the PHOTCAL routines.
+For example the three identifiers "catalog", "observations", and
+"transformation" are used to declare the beginning of the catalog,
+observations, and transformation sections of the configuration file.
+
+A \fIname\fR is a user variable that has either been declared in the
+catalog or observation sections of the configuration file, declared as
+a parameter using the fit or const declaration statements in the
+transformation section of the configuration file, or
+defined by a set equation in the transformation section.
+
+A \fIlabel\fR is an identifier which is assigned to an equation. It is used
+to tell the parser which transformation equation, the optional derivative,
+weight, error or plot equations are associated with.
+
+A \fIfunction\fR is a built-in mathematical function that can be
+used in expressions.
+
+The following identifiers are reserved by the program to name
+\fIkeywords\fR and \fIfunctions\fR. These reserved identifiers
+cannot be used to name user variables or label equations.
+
+.nf
+# keywords
+
+catalog constant delta derivative
+error *extinction fit observations
+plot *print set transformation
+weight
+
+*reserved keywords not currently used
+
+# functions
+
+abs acos asin atan
+cos exp log log10
+sin sqrt tan
+.fi
+
+Keywords may be abbreviated to up to three characters but names, labels,
+and functions may not be abbreviated.
+
+The following arithmetic \fIoperators\fR are recognized by PHOTCAL:
+"+" (addition), "-" (subtraction), "*" (multiplication), "/" (division),
+"**" (exponentiation), "-" (minus sign), and "+" (plus sign).
+The arithmetic operators follow normal FORTRAN rules of precedence
+
+\fIExpressions\fR can be any legal arithmetic FORTRAN expression, using the
+legal names, operators, functions, or constants defined above.
+Parenthesis "(" and ")" may be used as well.
+
+\fIComments\fR may be placed anywhere in the configuration file, as long
+as they are preceded by a "#" sign.
+All input succeeding this character to the end of the line is skipped.
+
+Every physical \fIline\fR in the configuration file must be shorter than the
+IRAF text file line limit, currently
+161 characters, but long constructs, for example a long transformation
+equation may span more than one physical line.
+
+.ih
+EXAMPLES
+
+Example 1. A sample configuration file for reducing UBV photoelectric
+photometry. Note the optional use of the delta declaration statement
+and the weight equations.
+
+.nf
+# Configuration file for reducing UBV photoelectric photometry.
+
+catalog
+
+V 2 # V magnitude
+BV 3 # B - V color
+UB 4 # U - B color
+
+observation
+
+v 2 # v instrumental magnitude
+b 3 # b instrumental magnitude
+u 4 # u instrumental magnitude
+ev 5 # error in v instrumental magnitude
+eb 6 # error in b instrumental magnitude
+eu 7 # error in u instrumental magnitude
+X 8 # airmass
+
+transformation
+
+fit v1 = 25.0, v2=0.16, v3=-0.043
+VFIT: V = v1 + v - v2 * X + v3 * (b - v)
+ delta v1=0.10, v2=0.02, v3=0.02
+ weight (VFIT) = 1. / ev ** 2
+
+fit b1 = 1.0, b2=0.09, b3=1.06
+BVFIT: BV = b1 - b2 * X + b3 * (b - v)
+ delta b1=0.10, b2=0.02, b3=0.02
+ weight (BFIT) = 1.0 / (ev ** 2 + eb ** 2)
+
+fit u1 = 2.0, u2=0.300, u3=0.95
+UBFIT: UB = u1 - u2 * x + u3 * (u - b)
+ delta u1=0.10, u2=0.02, u3=0.02
+ weight (UFIT) = 1. / (eb ** 2 + eu ** 2)
+.fi
+
+Example 2. A sample configuration file for reducing UBV CCD photometry.
+Note the optional use of the error column declarations in the catalog and
+observations sections. The error columns can be used to compute
+the weights by the FITPARAMS task. Also note how the set equations are
+used to simplify the transformation equations.
+
+.nf
+catalog
+
+V 2 # V magnitude
+BV 3 # B-V color
+UB 4 # U-B color
+error(V) 5 # error in V magnitude
+error(BV) 6 # error in B-V color
+error(UB) 7 # error in U-B color
+
+observation
+
+ut1 3 # ut time of filter 1 observation
+X1 4 # airmass of filter 1 observation
+m1 7 # filter 1 instrumental magnitude
+error(m1) 8 # error in filter 1 instrumental magnitude
+ut2 10 # ut time of filter 2 observation
+X2 11 # airmass of filter 2 observation
+m2 14 # filter 2 instrumental magnitude
+error(m2) 15 # error in filter 2 instrumental magnitude
+ut3 17 # ut time of filter 3 observation
+X3 18 # airmass of filter 3 observation
+m3 19 # filter 3 instrumental magnitude
+error(m3) 20 # error in filter 3 instrumental magnitude
+
+
+transformation
+
+set B = V + BV
+set U = V + BV + UB
+
+fit u1 = 0.0, u2=0.68, u3=-0.05
+const u4 = 0.0
+UFIT: u = u1 + U + u2 * Xu + u3 * UB + u4 * Xu * UB
+ delta u1=.1, u2=.02, u3=0.02
+
+fit b1 = 0.0, b2=0.30, b3=-0.08
+const b4 = 0.0
+BFIT: b = u1 + B + b2 * Xb + b3 * BV + b4 * Xb * BV
+ delta b1=.1, b2=.02, b3=0.02
+
+fit v1 = 0.0, v2=0.15, v3=0.03
+const v4 = 0.0
+VFIT: v = v1 + V + v2 * Xv + v3 * BV + v4 * Xv * BV
+ delta v1=.1, v2=.02, v3=0.02
+.fi
+
+.endhelp
diff --git a/noao/digiphot/photcal/doc/evalfit.hlp b/noao/digiphot/photcal/doc/evalfit.hlp
new file mode 100644
index 00000000..9a256964
--- /dev/null
+++ b/noao/digiphot/photcal/doc/evalfit.hlp
@@ -0,0 +1,267 @@
+.help evalfit Aug91 noao.digiphot.photcal
+.ih
+NAME
+evalfit -- evaluate the fit
+.ih
+USAGE
+evalfit observations config parameters calib
+.ih
+PARAMETERS
+.ls observations
+The list of files containing the observations.
+\fIObservations\fR are multi-column text files, whose columns are delimited
+by whitespace, and whose first column is reserved for an object id.
+All observations files in the list must have the same format.
+.le
+.ls config
+The configuration file. \fIConfig\fR is a text file which
+specifies the format of the \fIobservations\fR and \fIcatalog\fR files, and
+defines the form of the transformation equations to be evaluated.
+More information can be obtained about this file by typing
+"help mkconfig" and "help config".
+.le
+.ls parameters
+The name of the file produced by the FITPARAMS task.
+\fIParameters\fR is a text file
+containing the fitted parameter values for each
+equation and other information about the quality of the
+fit. Records in \fIparameters\fR are assigned a name equal to the label
+of fitted equation. If more than one record in \fIparameters\fR has
+the same name then the last record of that name is used by EVALFIT to
+evaluate the fit.
+.le
+.ls calib
+The name of the output file. \fICalib\fR is a text file
+containing the name of the fitted object in the first column,
+followed by the \fIprint\fR
+variables if any, followed by the fitted value, error of the fit (if
+\fIerrors\fR is not "undefined"), and residual of the
+fit (if catalog matching is enabled) for each equation.
+.le
+.ls catalogs
+The list of files containing the catalog data.
+\fICatalogs\fR are multi-column text files, whose columns are delimited
+by whitespace, and whose first column is reserved for an object id.
+All catalog files in the list must have the same format.
+If \fIcatalogs\fR = "", then no id matching with the observations
+files is done.
+.le
+.ls errors = "undefined"
+The algorithm used to compute formal errors for each object fit. The choices
+are:
+.ls undefined
+No errors are computed and no error values are output.
+.le
+.ls obserrors
+The error in each fitted value is computed by summing in quadrature
+the contribution to the total error made by each individual error in the
+observations file variables. If no error columns are defined for the
+observations files the error is assumed to be INDEF.
+.le
+.ls equations
+The error in each fitted value is computed by evaluating the error
+equations associated with each transformation equation. If no error equation
+is defined then the error is assumed to be INDEF.
+.le
+.le
+.ls objects = "all"
+The type of objects to output to \fIcalib\fR. The choices are:
+.ls all
+Both program and standard stars are output.
+.le
+.ls program = yes
+Only program stars are output.
+.le
+.ls standard = yes
+Only standard stars are output.
+.le
+.le
+.ls print = ""
+Additional variables to be printed in the output file. These variables are
+printed immediately after the id, and may be any of the
+catalog variables, observations variables, or the set equation variables
+defined in \fIconfig\fR.
+.le
+.ls format = ""
+An SPP style format string to apply to the output data, in place of the
+default format. SPP format strings
+are described in detail in the formats section.
+.le
+.ls append = no
+Append the output to \fIcalib\fR instead of creating a new file. If the
+file already exists and \fIappend\fR is "no" EVALFIT will abort.
+.le
+.ls catdir = ")_.catdir"
+The directory containing the supported standard star catalogs.
+The default parameter value redirects \fIcatdir\fR
+to a package parameter of the same name. A list of standard
+catalogs may be obtained by printing the file "photcal$catalogs/README".
+Alternatively the user may create their own standard star catalogs
+and standard star catalog directory.
+.le
+
+.ih
+DESCRIPTION
+
+EVALFIT evaluates the transformation equations
+for the program and/or standard objects in \fIobservations\fR, using
+the transformation equations defined in \fIconfig\fR,
+the fitted parameter values in the file \fIparameters\fR produced by the
+FITPARAMS
+task, and writes the output to the file \fIcalib\fR. If \fIappend\fR is "yes"
+output may be appended to an existing file.
+
+EVALFIT computes the values of the catalog variables for the program
+stars by inserting the observations variables directly into the
+transformation equations. EVALFIT can evaluate any number of transformation
+equations, but if there are any standard catalog variables in the right-hand
+side of the transformation equation, EVALFIT will assign INDEF to the fitted
+for that equation.
+
+Below are two sets of transformation equations. The first set can be evaluated
+with EVALFIT, the second set cannot and must be inverted with INVERTFIT.
+In both cases the catalog variables to be fit are V and BV, and
+the observed quantities are mv, mb, Xv, and Xb.
+
+.nf
+ System 1: V = v0 + mv + v1 * (Xv + Xb) / 2. + v2 * (mb - mv)
+ BV = b0 + b1 * (Xv + Xb) / 2. + b2 * (mb - mv)
+
+ System 2: mv = v0 + V + v1 * Xv + v2 * BV
+ mb = b0 + V + BV + b1 * Xb + b2 * BV
+.fi
+
+
+Formal errors for each fit may
+be computed by, 1) setting \fIerrors\fR to "obserrors" and using the
+error columns defined in the observations section of \fIconfig\fR
+to estimate the errors or 2) evaluating the error equations defined in
+\fIconfig\fR.
+
+If the user wishes to match the objects in \fIobservations\fR with those
+in \fIcatalogs\fR in order for example, to compute the residuals of the fit,
+\fIcatalogs\fR must be defined. Similarly if \fIobjects\fR is "program"
+or "standard", \fIcatalogs\fR must be defined in order to enable
+id matching.
+
+Legal \fIcatalog\fR and \fIobservations\fR files are multi-column text
+files whose columns are delimited by whitespace.
+The first column of a catalog file is \fIalways\fR reserved for an object id.
+The first column of an observations file is reserved for an
+object id which can be
+used to match the observational data with the corresponding catalog data.
+All other columns may contain any quantity which can be
+expressed as an integer or real number. Sexagesimal format numbers
+(hh:mm:ss) are interpreted internally as real numbers. The constant
+INDEF can be used to represent data that is missing or undefined.
+Double precision and complex data are
+not supported. Lines beginning with "#" are treated as comment lines.
+
+By default EVALFIT prints out the object id,
+followed by the variables listed in the \fIprint\fR
+parameter, followed by the fit value, estimated
+error (if \fIerrors\fR is not "undefined"), and residual of the fit
+(for any standard star observations that can be matched with the
+catalog values) for each fitted equation. The user can format the output
+by setting the \fIformat\fR parameter to an SPP style string.
+SPP format strings are described in detail below.
+
+.ih
+FORMATS
+A format specification has the form "%w.dCn", where w is the field width,
+d is the number of decimal places or the number of digits of precision,
+C is the format code, and n is radix character for format code "r" only.
+The w and d fields are optional. The format codes C are as follows:
+
+.nf
+b boolean (YES or NO)
+c single character (c or '\c' or '\0nnn')
+d decimal integer
+e exponential format (D specifies the precision)
+f fixed format (D specifies the number of decimal places)
+g general format (D specifies the precision)
+h hms format (hh:mm:ss.ss, D = no. decimal places)
+m minutes, seconds (or hours, minutes) (mm:ss.ss)
+o octal integer
+rN convert integer in any radix N
+s string (D field specifies max chars to print)
+t advance To column given as field W
+u unsigned decimal integer
+w output the number of spaces given by field W
+x hexadecimal integer
+z complex format (r,r) (D = precision)
+
+
+Conventions for w (field width) specification:
+
+ W = n right justify in field of N characters, blank fill
+ -n left justify in field of N characters, blank fill
+ 0n zero fill at left (only if right justified)
+absent, 0 use as much space as needed (D field sets precision)
+
+
+Escape sequences (e.g. "\n" for newline):
+
+\b backspace (\fBnot implemented\fR)
+\f formfeed
+\n newline (crlf)
+\r carriage return
+\t tab
+\" string delimiter character
+\' character constant delimiter character
+\\ backslash character
+\nnn octal value of character
+
+Examples
+
+%s format a string using as much space as required
+%-10s left justify a string in a field of 10 characters
+%-10.10s left justify and truncate a string in a field of 10 characters
+%10s right justify a string in a field of 10 characters
+%10.10s right justify and truncate a string in a field of 10 characters
+
+%7.3f print a real number right justified in floating point format
+%-7.3f same as above but left justified
+%15.7e print a real number right justified in exponential format
+%-15.7e same as above but left justified
+%12.5g print a real number right justified in general format
+%-12.5g same as above but left justified
+
+\n insert a newline
+
+.fi
+
+
+Note that deferred value fields are \fBnot implemented\fR in EVALFIT.
+
+.ih
+EXAMPLES
+
+1. Evaluate the fit for a list of program stars in m92. Use the errors
+in the observed quantities to estimate the errors.
+
+.nf
+ ph> evalfit m92.obs m92.cfg m92.fit m92.cal
+.fi
+
+2. Repeat the fit computed above but include the variables xu and yu which
+are the positions of the objects in the u frame in the output.
+
+.nf
+ ph> evalfit m92.obs m92.cfg m92.fit m92.cal print="xu,yu"
+.fi
+
+3. Repeat the fit computed above but format the output. The user has
+determined that the output will have 5 columns containing the object id,
+xu, yu, fit value and fit error respectively.
+
+.nf
+ ph> evalfit m92.obs m92.cfg m92.fit m92.cal print="xu,yu"\
+ format="%-10.10s %-7.2f %-7.2f %-7.3f %-6.3f\n"
+
+.fi
+
+.ih
+SEE ALSO
+mkconfig,chkconfig,fitparams,invertfit
+.endhelp
diff --git a/noao/digiphot/photcal/doc/fitparams.hlp b/noao/digiphot/photcal/doc/fitparams.hlp
new file mode 100644
index 00000000..fbd9a61e
--- /dev/null
+++ b/noao/digiphot/photcal/doc/fitparams.hlp
@@ -0,0 +1,633 @@
+.help fitparams Aug91 noao.digiphot.photcal
+.ih
+NAME
+fitparams -- solve for the parameters of the transformation equations
+.ih
+USAGE
+fitparams observations catalogs config parameters
+.ih
+PARAMETERS
+.ls observations
+The list of files containing the observational data. Observations files are
+multi-column text files whose columns are delimited by whitespace, and
+whose first column is usually reserved for the object id.
+All observations files in the list must have the same format.
+The format of legal observations files is described in further detail in
+the description section.
+.le
+.ls catalogs
+The list of files containing the catalog data. Catalog files are
+multi-column text files whose columns are delimited by whitespace,
+and whose first column is always reserved for the object id.
+If more than one entry with the same id exists in the list of catalogs,
+only the first entry is used.
+All catalog files in the list must have the same format.
+The format of legal catalog files is described in further detail in
+the description section.
+.le
+.ls config
+The name of the configuration file. The configuration file is a text file
+specifying the format of the input catalog and observations files, and the
+form of the transformation
+equations. A brief description of the syntax and grammar of this file
+is given in the configuration file section.
+.le
+.ls parameters
+The name of the output database file.
+Parameters is a text database file to which the error analysis of the fit
+and the parameter values and errors for each transformation equation are
+written.
+The output of fitparams is appended to parameters as a set of new records,
+one for each of the transformation equations.
+If more than one record exists with the same record name, the
+last record written takes precedence.
+.le
+.ls weighting = "uniform"
+The following weighting schemes are supported.
+.ls uniform
+The data points are all assigned a weight of one.
+.le
+.ls photometric
+The total error squared for each data point is set to the total error in the
+catalog variables squared plus the total error in the observations variables
+squared and the weight for each data point is set to 1.0 / error ** 2.
+This option assumes that all the sources of error are in the photometric
+indices (magnitudes and colors), that error columns (see the description
+of the configuration file below) have been declared for at least one
+photometric index, and that the contribution of each catalog or observations
+variable to the total error is weighted by the number of times it occurs
+in the transformation equation.
+If \fIaddscatter\fR is "yes" then an additional "scatter" term is fit and
+added to the weights.
+.le
+.ls equations
+The weight equation (see the description of the configuration file below)
+is evaluated for each point and the weight for that point is set to that
+value. If there is no weight equation the weights are all set to one.
+If \fIaddscatter\fR is "yes" then an additional "scatter" term is fit and
+added to the weights.
+.le
+.le
+.ls addscatter = yes
+Add an additional scatter term to the weights if the average error in the fit
+is much greater than the average error in the measurements? \fIAddscatter\fR
+has no effect if \fIweighting\fR is "uniform". \fIAddscatter\fR is recommended
+if \fIweighting\fR is "photometric" as the intrinsic error in the
+transformations is often much greater than the formal errors of
+measurement and the scatter term stabilizes the fit.
+Users of the \fIweighting\fR equals "equations" option
+may wish to turn off \fIaddscatter\fR.
+.le
+.ls tolerance = 3.0e-5
+The convergence tolerance for the non-linear least squares fit.
+The fit will stop iterating
+when the fractional change in the reduced chi-square of the residuals from
+iteration to iteration is less than \fItolerance\fR.
+.le
+.ls maxiter = 15
+The maximum number of iterations for the non-linear least squares fit.
+When this number is reached the fitting process will terminate even
+if the fit has not converged.
+.le
+.ls nreject = 0
+The maximum number of bad data rejection iterations. If \fInreject\fR is
+greater than zero the initial fit is used
+to detect and reject deviant points before performing the final fit.
+No rejection is performed if \fInreject\fR is less than or equal
+to zero.
+.le
+.ls low_reject = 3.0, high_reject = 3.0
+The lower and upper rejection limits in units of the rms of the fit.
+Points deviating from the initial fit by more than this amount are rejected
+before performing the final fit. No rejection is done if both limits
+are zero.
+.le
+.ls grow = 0.0
+The default rejection growing radius. Points within a distance given
+by this parameter of any rejected point are also rejected.
+.le
+.ls interactive = yes
+Fit equations interactively ? When this parameter is \fIyes\fR, the user will
+be presented with plots of the data and can interact with the fitting
+process.
+.le
+.ls logfile = "STDOUT"
+The name of the output text file to which selected detailed results of the
+fitting process are written. By default logfile is the standard output.
+If logfile is "", logging is turned off altogether. Otherwise new
+output is appended to logfile which can therefor become quite large.
+.le
+.ls log_unmatched = yes
+Write the list of observations with no corresponding catalog entries to
+logfile? This option is useful for checking for errors in the observed
+object id names and for users who like to run fitparams in non-interactive
+mode.
+.le
+.ls log_fit = no
+Write the error analysis of the final fit in logfile? This option is
+useful for users who like to run fitparams in non-interactive mode.
+.le
+.ls log_results = no
+Write the results of the current fit to logfile? This option is
+useful for users who like to run fitparams in non-interactive mode.
+.le
+.ls catdir = ")_.catdir"
+The directory containing the supported standard star catalogs.
+The default parameter value redirects \fIcatdir\fR
+to a package parameter of the same name. A list of standard
+catalogs may be obtained by printing the file "photcal$catalogs/README".
+Alternatively the user may create their own standard star catalogs
+and standard star catalog directory.
+.le
+.ls graphics = "stdgraph"
+The default graphics device.
+This parameter is used only if \fBinteractive=yes\fR.
+.le
+.ls cursor = ""
+Graphics cursor input. When null the standard graphics cursor is used.
+Otherwise the specified cursor command file is used.
+This parameter is used only if \fBinteractive=yes\fR.
+.le
+
+.ih
+DESCRIPTION
+
+FITPARAMS parses the configuration file \fIconfig\fR checking for
+grammar and syntax errors. FITPARAMS attempts to recover from any
+errors and to finish parsing the configuration
+file, but it will not process the input data if errors are present.
+The configuration file is described briefly in the configuration file
+section and in detail in the help page for the configuration file.
+
+Once the configuration file is successfully parsed, FITPARAMS reads the list
+of catalog files and loads the values of the catalog variables
+declared in \fIconfig\fR into memory.
+If no catalog section is declared in \fIconfig\fR, if the catalog section
+is empty, or if catalogs is "", no catalog data is read
+and all the required input data is assumed to be in \fIobservations\fR.
+After the catalog data is read, FITPARAMS reads the observations files
+\fIobservations\fR, matches the object ids of the observations with the
+corresponding catalog object ids, and loads all the observations
+variables declared in \fIconfig\fR into memory. Id matching is disabled
+if no catalog
+data is read, otherwise only those observations which have a matching catalog
+entry will be used in the fit. If a catalog section declaration was made
+in \fIconfig\fR, even an empty one, FITPARAMS assumes that the object ids
+are in column 1 of \fIobservations\fR.
+
+Legal \fIcatalog\fR and \fIobservations\fR files are multi-column text
+files whose columns are delimited by whitespace.
+The first column of a catalog file is \fIalways\fR reserved for an object id.
+The first column of an observations file is \fIusually\fR reserved for an
+object id which can be
+used to match the observational data with the corresponding catalog data.
+All other columns may contain any quantity which can be
+expressed as an integer or real number. Sexagesimal format numbers
+(hh:mm:ss) are interpreted internally as real numbers. The constant
+INDEF can be used to represent data that is missing or undefined.
+Double precision and complex data are
+not supported. Lines beginning with "#" are treated as comment lines.
+
+FITPARAMS solves the fit
+for each equation in the configuration file either interactively
+or non-interactively depending on the value of \fIinteractive\fR,
+and writes the solution in the output file \fIparameters\fR for later
+use by the evaluation routines EVALFIT or INVERTFIT.
+Selected results can also be written to \fIlogfile\fR if
+any of the switches \fIlog_unmatched\fR, \fIlog_fit\fR, or \fIlog_results\fR
+are enabled.
+In interactive mode the user can use all the interactive capabilities
+of the interactive non-linear least squares package INLFIT.
+INLFIT is described more fully below.
+
+.ih
+THE CONFIGURATION FILE
+
+The configuration file is a text file which specifies how the data is
+organized in the input files and how the transformation
+equations are to be fit.
+
+The input data are assumed to come from two different sources that may
+be either in the same input file or in different input files.
+These sources are known as the \fIcatalog\fR and the \fIobservations\fR
+respectively.
+
+The \fIcatalog\fR contains values indexed by a name called the
+matching name. This name must be in the first column of the
+catalog and is also assumed to be unique, i.e, each catalog
+entry is assumed to be unique.
+
+The \fIobservations\fR are values that may be either indexed by a matching
+name if a catalog section is specified in the configuration file, or a
+stream of input values in an ordinary text file.
+If a catalog section is specified and non-empty, each observation is
+matched against the
+catalog entries, and only observations whose matching names are found in the
+catalog are used to compute the transformation equations.
+Otherwise all values are used.
+
+The configuration file is divided in three sections: the \fIcatalog
+section\fR which describes the format of the catalog files, the
+\fIobservations section\fR which describes the format of the observation
+files, and the \fItransformation section\fR which defines the
+transformation equations in that order.
+
+The catalog and observations sections permit the user to assign
+names to the input file
+columns. These columns can later be referenced by name in the configuration
+file by using these assigned names
+as if they were variables in a programming language.
+
+The transformation section is used to define the equations to solve,
+and assign initial values to the fitting parameters.
+The user may also optionally define equations for the derivatives of
+the transformation equations with respect to the parameters,
+the weights to be used in the fit,
+the errors of the fit and the default equations to be
+plotted in the interactive fitting process.
+It is possible to specify any number of transformation equations in
+this section.
+
+SAMPLE CONFIGURATION FILES
+
+Example 1. Configuration file for reducing UBV photoelectric photometry.
+
+.nf
+# Configuration file for reducing UBV photoelectric photometry.
+
+catalog
+
+V 2 # V magnitude
+BV 3 # B - V color
+UB 4 # U - B color
+
+observation
+
+v 2 # v instrumental magnitude
+b 3 # b instrumental magnitude
+u 4 # u instrumental magnitude
+ev 5 # error in v instrumental magnitude
+eb 6 # error in b instrumental magnitude
+eu 7 # error in u instrumental magnitude
+X 8 # airmass
+
+transformation
+
+fit v1 = 0.0, v2=0.16, v3=-0.043
+VFIT: V = v1 + v - v2 * X + v3 * (b - v)
+ weight(VFIT) = 1.0 / ev ** 2
+ plot(VFIT) = V, V - (v1 + v - v2 * X + v3 * (b - v))
+
+fit b1 = 0.0, b2=0.09, b3=1.21
+BVFIT: BV = b1 - b2 * X + b3 * (b - v)
+ weight (BVFIT) = 1.0 / (eb ** 2 + ev ** 2)
+ plot(BVFIT) = BV, BV - (b1 - b2 * X + b3 * (b - v))
+
+fit u1 = 0.0, u2=0.300, u3=0.861
+UBFIT: UB = u1 - u2 * X + u3 * (u - b)
+ weight (UBFIT) = 1.0 / (eu ** 2 + eb ** 2)
+ plot(UBFIT) = UB, UB - (u1 - u2 * X + u3 * (u - b))
+.fi
+
+Example 2. Configuration file for reducing UBV CCD photometry.
+
+.nf
+catalog
+
+V 2 # V magnitude
+BV 3 # B - V color
+UB 4 # U - B color
+error(V) 5 # error in V magnitude
+error(BV) 6 # error in B-V color
+error(UB) 7 # error in U-B color
+
+observation
+
+m1 2 # filter 1 instrumental magnitude
+error(m1) 3 # error in filter 1 instrumental magnitude
+Xm1 4 # airmass of filter 1 observation
+m2 6 # filter 2 instrumental magnitude
+error(m2) 7 # error in filter 2 instrumental magnitude
+Xm2 8 # airmass of filter 2 observation
+m3 10 # filter 3 instrumental magnitude
+error(m3) 11 # error in filter 3 instrumental magnitude
+Xm3 12 # airmass of filter 3 observation
+
+
+transformation
+
+fit u1 = 27.0, u2=0.68, u3=0.05
+UFIT: m3 = u1 + V + BV + UB + u2 * Xm3 + u3 * UB
+
+fit b1 = 26.0, b2=0.30, b3=0.18
+BFIT: m2 = b1 + V + BV + b2 * Xm2 + b3 * BV
+
+fit v1 = 25.0, v2=0.17, v3=-0.02
+VFIT: m1 = v1 + V + v2 * Xm1 + v3 * BV
+.fi
+
+
+.ih
+THE NON-LINEAR INTERACTIVE FITTING PACKAGE
+
+DESCRIPTION
+
+INLFIT fits an n-dimensional function to a set data
+points, iterating until the reduced chi-squared changes
+by less than \fItolerance\fR percent between successive iterations, or
+machine precision is reached and the fit converges, or until the maximum number
+of iterations \fImaxiter\fR is reached. If the maximum number
+of iterations is reached before convergence a status flag
+is set.
+
+After computing an initial fit, INLFIT presents the user with a plot of
+the fit and activates the graphics cursor.
+At this point the user may examine and/or interact with the fit by,
+for example, reprogramming the default graph keys,
+editing the default convergence or bad data rejection parameters,
+deleting and undeleting points,
+altering which parameters in the fitting function are actually to be
+fit and which are to be held constant, and refitting the data.
+
+If \fInreject\fR is greater than zero the RMS of the residuals is computed
+and points whose residuals are less than \fIlow_reject\fR * RMS
+or \fIhigh_reject\fR * RMS value are excluded from the fit. Points within
+a distance \fIgrow\fR of a rejected point are also excluded from
+the fit. The function is then refit without the rejected points.
+The rejection algorithm is executed until the number of rejection
+iterations reaches \fInreject\fR or no more points are rejected.
+
+ALGORITHMS
+
+INLFIT uses the standard Levenberg-Marquardt non-linear least squares
+algorithm to fit the data. Detailed descriptions of the algorithm can
+be found in the following two references.
+.nf
+
+1. Bevington, P.R., 1969, Data Reduction and Error Analysis for the
+ Physical Sciences, Chapter 11, page 235.
+
+2. Press, W.H. et al., 1986, Numerical Recipes: The Art of Scientific
+ Computing, Chapter 14, page 523.
+
+.fi
+
+CURSOR COMMANDS
+
+The following interactive cursor keystroke commands are available from
+with the INLFIT package.
+.ls ?
+The terminal is cleared and a menu of cursor keystroke and colon commands
+is printed.
+.le
+.ls c
+The id, coordinates of the data point nearest the cursor, along with the
+function value, the fitted value and the residual, are printed on the status
+line.
+.le
+.ls d
+The data point nearest the cursor and not previously deleted is marked with an
+X. It will not be used in further fits until it is undeleted.
+.le
+.ls f
+The function is fit to the data and the fit is graphed using the default
+plot type.
+.le
+.ls g
+Redefine the graph keys "h-l" from their defaults. A prompt is issued for the
+graph key to be redefined. Another prompt is issued for the data to be
+plotted at which point the user must enter the x and y axis data to plot,
+delimited by a comma. The data types are the following (they can be
+abbreviated to up to three characters).
+.nf
+
+ function Dependent variable or function
+ fit Fitted value
+ residuals Residuals (function - fit)
+ ratio Ratio (function / fit)
+ nonlinear Nonlinear component
+ identifier Independent variable named "identifier" (if defined)
+ var n Independent variable number "n"
+ user n User defined plot equation "n" (if defined)
+
+.fi
+The application program can define independent variable names and user plot
+functions, aside from the standard options provided. If variable names are
+supplied, the user can reference them by their names. Otherwise they can be
+always referenced by "var n", where "n" is the variable number (the user has
+to know the variable order in this case). The ":variables" command will
+list the currently defined variables by name and number.
+The application program may
+define any number of plot equations aside from the defaults provided. In this
+case the user may reference them by "user n", where "n" is the plot function
+number (the user must know the equation order in this case).
+.le
+.ls h, i, j, k, l
+By default each key produces a different graph. The graphs are described by
+the data which is graphed along each axis as defined above. The default graph
+keys,
+which may be redefined by the application program or interactively by using
+the 'g' key, are the following.
+.nf
+
+ h function, fit
+ i function, residuals
+ j function, ratio
+ k var 1, function
+ l user 1, user 2 (default)
+
+.fi
+The initial graph key, if not redefined by the application program is 'h'.
+.le
+.ls o
+Overplot the next fit provided the graph format has not changed.
+.le
+.ls q
+Exit from the interactive curve fitting package.
+.le
+.ls r
+Redraw the current graph.
+.le
+.ls t
+Toggle fit overplotting on and off. If this option is on the data
+and fitted values are overplotted. Otherwise only data points are plotted.
+The fitted values are marked using boxes.
+.le
+.ls u
+Undelete the data point nearest the cursor which has been previously deleted.
+This option does not work over points marked as deleted by the application
+program before calling inlfit.
+.le
+.ls w [key]
+Set the graph window or data range along each axis to be graphed.. This is a
+\fBgtools\fR option which prints the prompt "window:". The available cursor
+keystroke commands are printed with '?' and on-line help is available by
+typing "help gtools".
+.le
+.ls I
+Interrupt the task immediately without saving the current fit.
+.le
+
+Colon commands are used to show or set the values of parameters.
+The application program calling \fBinlfit\fR can add more commands.
+Parameter names can be abbreviated. The following commands are supported.
+.ls :show [file]
+Show the current values of the fitting parameters high_reject,
+low_reject, niterate, grow, tol, itmax. The default output device
+is the terminal (STDOUT) and the screen is cleared before the information
+is output. If a file is specified then the information is appended
+to the named file.
+.le
+.ls :variables [file]
+List the currently loaded variables. The number, id, minimum value and maximum
+value of each variable is printed. The default output device is the terminal
+(STDOUT) and the screen is cleared before the information is output.
+If a file is specified then the information is appended to the named file.
+.le
+.ls :data [file]
+List the raw data. The value of each standard catalog and observations
+catalog variable for each data point is printed. The default output device
+is the terminal (STDOUT) and the screen is cleared before the information
+is output. If a file is specified then the information is appended to
+the named file.
+.le
+.ls :errors [file]
+Show the error analysis of the current fit. The number of iterations,
+total number of points, the number of rejected and deleted points,
+the standard deviation, the reduced chi, average error (always = 1.0 if
+weight = 1.0, otherwise = 1.0 / <weight>),
+average scatter (always = 0.0 if no weights scatter term is fit)
+and the rms value are
+printed on the screen.
+The fitted parameters and their errors are also printed. The default output is
+the terminal (STDOUT) and the screen is cleared before the information is
+output. If a file is specified then the information is appended to
+the named file.
+.le
+.ls :results [file]
+List the results of the current fit. The function value, the fitted value,
+the residual, and the weight are printed for each data point. The default
+output device is the terminal (STDOUT) and the screen is cleared before
+the information is output. If a file is specified then the information is
+appended to the named file.
+.le
+.ls :vshow [file]
+A verbose version of ":show" which is equivalent to a ":show" plus a ":errors"
+plus a ":results". The default output device is the terminal (STDOUT)
+and the screen is cleared before the information is output.
+If a file is specified then the information is appended to the named file.
+.le
+.ls :page file
+Page through the named file.
+.le
+.ls :tolerance [value]
+Show or set the value of the fitting tolerance. Tolerance is the maximum
+fraction by which the reduced chi-squared can change from one iteration to the
+next for the fit to meet the convergence criteria.
+.le
+.ls :maxiter [value]
+Show or set the maximum number of fitting iterations.
+.le
+.ls :nreject [value]
+Show or set the maximum number of rejection iterations. A value of zero
+means that automatic bad data rejection is turned off.
+.le
+.ls :low_reject [value], :high_reject [value]
+Show or set the values of the bad data rejection limits.
+If both low_reject and high_reject are zero then automatic bad data
+rejection is turned off.
+If either of the high or low rejection limits are greater than zero,
+and nreject is greater than zero, the rms of the initial fit is computed.
+Points with residuals
+more than low_reject * rms below zero and high_reject * rms above zero
+are removed before the final fit. Rejected points are marked on the
+graphs with diamonds.
+.le
+.ls :grow [value]
+Show or set the value of the rejection growing radius. Any points
+within this distance of a rejected point are also rejected.
+.le
+.ls :fit [parameter] [value]
+Set the starting guess value for the named coefficient and allow the
+parameter value to change (converge) during the fit.
+If the value is not specified inlfit will use the last starting guess.
+.le
+.ls :const [parameter] [value]
+Set the named parameter to be a constant with the specified value, i.e,
+its value won't change during the fit.
+If the value is not specified inlfit will use its last starting value.
+.le
+.ls :/help
+Print help for the graph formatting options (the w key).
+.le
+.ls :.help
+Print help for the general IRAF graphics options.
+.le
+
+.ih
+EXAMPLES
+
+1. Fit a set of UBV standard star data non-interactively using the automatic
+bad data rejection algorithm and the configuration file shown in example
+2 under the configuration file section.
+
+.nf
+ ph> fitparams m92.obs m92.cat m92.config m92.fit nreject=10 inter-
+
+ ... compute valued for the parameters in all the transformation
+ equations
+
+ ph> page m92.fit
+
+ ... check that the fitted parameter values are reasonable
+
+ ph> invertfit m92.obs m92.cat m92.config m92.fit m92.out
+
+ ... evaluate the transformation equations for all the standard
+ stars
+.fi
+
+2. Fit the same set of data interactively but deleting bad points by
+eye instead of using the automatic rejection algorithm.
+
+.nf
+ ph> fitparams m92.obs m92.cat m92.config m92.fit
+
+ ... a default plot of the UFIT equation comes up on the screen
+ (the fit or right-hand side of the equation is plotted
+ versus the function or left-hand side of the equation)
+
+ ... type '?' to show the available commands
+
+ ... type 'i' to plot the residuals versus the function (LHS of
+ the equation)
+
+ ... delete bad points with the 'd' key and refit using the 'f'
+ key
+
+ ... check for any dependencies of the residuals on the color
+ term by reprogramming the graph key 'l' using the 'g' key
+ (type 'g' to enter the reprogramming menu, 'l' after the
+ prompt to reprogram the 'l' key, and "UB, residuals" in
+ response to the question of which axes to plot
+
+ ... list the plot windowing menu by typing 'w' followed by '?'
+ after the "window:" prompt
+
+ ... type 'w' followed by 'z' after the ":window" prompt to zoom
+ up on an interesting area in the plot, a 'w' followed by 'a'
+ will return to normal scaling
+
+ ... type 'q' to quit the fit for this equation
+
+ ... answer "yes" to the question about saving the fit
+
+ ... proceed to the next fit by typing "next" in response to the
+ prompt
+
+.fi
+
+.ih
+SEE ALSO
+chkconfig,mkconfig,gtools,inlfit
+.endhelp
diff --git a/noao/digiphot/photcal/doc/inlfit.hlp b/noao/digiphot/photcal/doc/inlfit.hlp
new file mode 100644
index 00000000..0daf5cd6
--- /dev/null
+++ b/noao/digiphot/photcal/doc/inlfit.hlp
@@ -0,0 +1,259 @@
+.help inlfit Aug91 noao.digiphot.inlfit
+.ih
+NAME
+inlfit -- The interactive non-linear least squares fitting package
+
+.ih
+SYNOPSIS
+
+The INLFIT package is a set of procedures, callable from any IRAF task,
+for interactively fitting an arbitrary function of n independent variables
+using non-linear least squares techniques. The calling task
+must supply the function to be fit and its derivatives, initial values for
+various convergence and bad data rejection parameters, the data to be fit,
+and weights for all the data points. The INLFIT package is layered on the
+NLFIT package which does the actual fitting.
+
+.ih
+DESCRIPTION
+
+INLFIT fits an n-dimensional function to a set of data
+points iterating until the reduced chi-squared changes
+by less than \fItolerance\fR percent between successive iterations, or
+until machine precision is reached, or until
+the maximum number
+of iterations \fImaxiter\fR is reached. If the maximum number
+of iterations is reached before convergence a status flag
+is set.
+
+After computing an initial fit, INLFIT presents the user with a plot of
+the fit and activates the graphics cursor.
+At this point the user may examine and/or interact with the fit by,
+for example, reprogramming the default graph keys,
+editing the default convergence or bad data rejection parameters,
+deleting and undeleting points,
+altering which parameters in the fitting function are actually to be
+fit and which are to be held constant, and refitting the data.
+
+If \fInreject\fR is greater than zero the RMS of the residuals is computed
+and points whose residuals are less than \fIlow_reject\fR * RMS
+or greater than \fIhigh_reject\fR * RMS value are excluded from the fit.
+Points within
+a distance \fIgrow\fR of a rejected point are also excluded from
+the fit. The function is then refit without the rejected points.
+The rejection algorithm is executed until the number of rejection
+iterations reaches \fInreject\fR or no more points are rejected.
+
+.ih
+CURSOR COMMANDS
+
+The following interactive cursor keystroke commands are available from
+with the INLFIT package.
+.ls ?
+The terminal is cleared and a menu of cursor keystroke and colon commands
+is printed.
+.le
+.ls c
+The id, coordinates of the data point nearest the cursor, along with the
+function value, the fitted value and the residual, are printed on the status
+line.
+.le
+.ls d
+The data point nearest the cursor and not previously deleted is marked with an
+X. It will not be used in further fits until it is undeleted.
+.le
+.ls f
+The function is fit to the data and the fit is graphed using the default
+plot type.
+.le
+.ls g
+Redefine the graph keys "h-l" from their defaults. A prompt is issued for the
+graph key to be redefined. Another prompt is issued for the data to be
+plotted at which point the user must enter the x and y axis data to plot,
+delimited by a comma. The data types are the following (they can be
+abbreviated to up to three characters).
+.nf
+
+ function Dependent variable or function
+ fit Fitted value
+ residuals Residuals (function - fit)
+ ratio Ratio (function / fit)
+ nonlinear Nonlinear component
+ identifier Independent variable named "identifier" (if defined)
+ var n Independent variable number "n"
+ user n User defined plot equation "n" (if defined)
+
+.fi
+The application program can define independent variable names and user plot
+functions, aside from the standard options provided. If variable names are
+supplied, the user can reference them by their names. Otherwise they can be
+always referenced by "var n", where "n" is the variable number (the user has
+to know the variable order in this case). The ":variables" command will
+list the currently defined variables by name and number.
+The application program may
+define any number of plot equations aside from the defaults provided. In this
+case the user may reference them by "user n", where "n" is the plot function
+number (the user must know the equation order in this case).
+.le
+.ls h, i, j, k, l
+By default each key produces a different graph. The graphs are described by
+the data which is graphed along each axis as defined above. The default graph
+keys,
+which may be redefined by the application program or interactively by using
+the 'g' key, are the following.
+.nf
+
+ h function, fit
+ i function, residuals
+ j function, ratio
+ k var 1, function
+ l user 1, user 2 (default)
+
+.fi
+The initial graph key, if not redefined by the application program is 'h'.
+.le
+.ls o
+Overplot the next fit provided the graph format has not changed.
+.le
+.ls q
+Exit from the interactive curve fitting package.
+.le
+.ls r
+Redraw the current graph.
+.le
+.ls t
+Toggle fit overploting on and off. If this option is on the data
+and fitted values are overplotted. Otherwise only data points are plotted.
+The fitted values are marked using boxes.
+.le
+.ls u
+Undelete the data point nearest the cursor which has been previously deleted.
+This option does not work over points marked as deleted by the application
+program before calling inlfit.
+.le
+.ls w [key]
+Set the graph window or data range along each axis to be graphed.. This is a
+\fBgtools\fR option which prints the prompt "window:". The available cursor
+keystroke commands are printed with '?' and on-line help is available by
+typing "help gtools".
+.le
+.ls I
+Interrupt the task immediately without saving the current fit.
+.le
+
+Colon commands are used to show or set the values of parameters.
+The application program calling \fBinlfit\fR can add more commands.
+Parameter names can be abbreviated. The following commands are supported.
+.ls :show [file]
+Show the current values of the fitting parameters high_reject,
+low_reject, niterate, grow, tol, itmax. The default output device
+is the terminal (STDOUT) and the screen is cleared before the information
+is output. If a file is specified then the information is appended
+to the named file.
+.le
+.ls :variables [file]
+List the currently loaded variables. The number, id, minimum value and maximum
+value of each variable is printed. The default output device is the terminal
+(STDOUT) and the screen is cleared before the information is output.
+If a file is specified then the information is appended to the named file.
+.le
+.ls :data [file]
+List the raw data. The value of each standard catalog and observations
+catalog variable for each data point is printed. The default output device
+is the terminal (STDOUT) and the screen is cleared before the information
+is output. If a file is specified then the information is appended to
+the named file.
+.le
+.ls :errors [file]
+Show the error analysis of the current fit. The number of iterations,
+total number of points,
+the number of rejected and deleted points, the standard deviation,
+the reduced chi, the average error (always = 1.0 if weight=1.0, otherwise
+= 1.0 / <weight>), the average scatter (always 0.0 if no weights scatter term is
+fit),
+the reduce chi, and the rms are printed on the screen. The fitted parameters
+and their errors are also printed. The default output is the terminal
+(STDOUT) and the screen is cleared before the information is
+output. If a file is specified then the information is appended to
+the named file.
+.le
+.ls :results [file]
+List the results of the current fit. The function value, the fitted value,
+the residual, and the weight are printed for each data point. The default
+output device is the terminal (STDOUT) and the screen is cleared before
+the information is output. If a file is specified then the information is
+appended to the named file.
+.le
+.ls :vshow [file]
+A verbose version of ":show" which is equivalent to a ":show" plus a ":errors"
+plus a ":results". The default output device is the terminal (STDOUT)
+and the screen is cleared before the information is output.
+If a file is specified then the information is appended to the named file.
+.le
+.ls :page file
+Page through the named file.
+.le
+.ls :tolerance [value]
+Show or set the value of the fitting tolerance. Tolerance is the maximum
+fraction by which the reduced chi-squared can change from one iteration to the
+next for the fit to meet the convergence criteria.
+.le
+.ls :maxiter [value]
+Show or set the maximum number of fitting iterations.
+.le
+.ls :nreject [value]
+Show or set the maximum number of rejection iterations. A value of zero
+means that automatic bad data rejection is turned off.
+.le
+.ls :low_reject [value], :high_reject [value]
+Show or set the values of the bad data rejection limits.
+If both low_reject and high_reject are zero then automatic bad data
+rejection is turned off.
+If either of the high or low rejection limits are greater than zero,
+and nreject is greater than zero, the rms of the initial fit is computed.
+Points with residuals
+more than low_reject * rms below zero and high_reject * rms above zero
+are removed before the final fit. Rejected points are marked on the
+graphs with diamonds.
+.le
+.ls :grow [value]
+Show or set the value of the rejection growing radius. Any points
+within this distance of a rejected point are also rejected.
+.le
+.ls :fit [parameter] [value]
+Set the starting guess value for the named coefficient and allow the
+parameter value to change (converge) during the fit.
+If the value is not specified inlfit will use the last starting guess.
+.le
+.ls :const [parameter] [value]
+Set the named parameter to be a constant with the specified value, i.e,
+its value won't change during the fit.
+If the value is not specified inlfit will use its last starting value.
+.le
+.ls :/help
+Print help for the graph formatting options.
+.le
+.ls :.help
+Print help for the general IRAF graphics options.
+.le
+
+.ih
+ALGORITHMS
+
+INLFIT uses the standard Levenberg-Marquardt non-linear least squares
+algorithm to fit the data. Detailed descriptions of the algorithm can
+be found in the following two references.
+.nf
+
+1. Bevington, P.R., 1969, Data Reduction and Error Analysis for the
+ Physical Sciences, Chapter 11, page 235.
+
+2. Press, W.H. et al., 1986, Numerical Recipes: The Art of Scientific
+ Computing, Chapter 14, page 523.
+
+.fi
+
+.ih
+SEE ALSO
+gtools
+.endhelp
diff --git a/noao/digiphot/photcal/doc/invertfit.hlp b/noao/digiphot/photcal/doc/invertfit.hlp
new file mode 100644
index 00000000..0923d0fb
--- /dev/null
+++ b/noao/digiphot/photcal/doc/invertfit.hlp
@@ -0,0 +1,297 @@
+.help invertfit Aug91 noao.digiphot.photcal
+.ih
+NAME
+invertfit -- evaluate the fit by inverting the system of equations defined
+in the configuration file
+.ih
+USAGE
+invertfit observations config parameters calib
+.ih
+PARAMETERS
+.ls observations
+The list of files containing the observations.
+\fIObservations\fR are multi-column text files, whose columns are delimited
+by whitespace, and whose first column is reserved for an object id.
+All observations files in the list must have the same format.
+.le
+.ls config
+The configuration file. \fIConfig\fR is a text file which specifies the
+format of the \fIobservations\fR and \fIcatalog\fR files, and defines the
+form of the transformation equations to be inverted.
+More information can be obtained about the format of this file
+by typing "help mkconfig" and "help config".
+.le
+.ls parameters
+The name of the file containing the fit produced by the FITPARAMS task.
+\fIParameters\fR is a text file
+containing the fitted parameter values for each
+equation and other information about the quality of the
+fit. Records in \fIparameters\fR are assigned a name equal to the label
+of the fitted equation. If more than one record in \fIparameters\fR has
+the same name then the last record is used by INVERTFIT to do the inversion.
+.le
+.ls calib
+The name of the output file. \fICalib\fR is a text file containing
+the name of the fitted object in the first column,
+followed by the values of the \fIprint\fR variables if any,
+followed by the fitted value of each catalog variable, error in the
+catalog variable (if \fIerrors\fR is not
+"undefined"), and residual of the fit (if catalog matching is enabled).
+.le
+.ls catalogs = ""
+The list of files containing the catalog data.
+\fICatalogs\fR are multi-column text files, whose columns are delimited
+by whitespace, and whose first column is always reserved for an object id.
+All catalog files in the list must have the same format.
+If \fIcatalogs\fR is "", then no id matching with the observations files
+is done, and the residuals of the fit cannot be computed.
+.le
+.ls errors = "obserrors"
+The algorithm used to compute formal errors for each object fit. The choices
+are:
+.ls undefined
+No errors are computed and no error values are output.
+.le
+.ls obserrors
+The error in each fitted value is computed by summing in quadrature
+the contribution to the total error made by each individual error in the
+observations files variables. If no error columns are defined for the
+observations files, the error is assigned the value INDEF.
+.le
+.ls equations
+The error in each fitted value is computed by summing in quadrature
+the contribution to the total error made by each error
+equation associated with a transformation equation.
+If no error equation is defined for any of the transformation
+equations, then the error is assumed to be INDEF.
+.le
+.le
+.ls objects = "all"
+The type of objects to output to \fIcalib\fR. The choices are:
+.ls all
+Both program and standard objects are output.
+.le
+.ls program = yes
+Only program objects are output.
+.le
+.ls standard = yes
+Only standard objects are output.
+.le
+.le
+.ls print = ""
+Additional variables to be printed in the output file. These variables are
+printed immediately after the object id, and may be any of the
+catalog variables, observations variables, or the set equation variables
+defined in \fIconfig\fR.
+.le
+.ls format = ""
+An SPP style format string to be used for formatting the output data, in
+place of the default format. SPP format
+strings are described in detail in the formats section.
+.le
+.ls append = no
+Append the output to \fIcalib\fR instead of creating a new file. If the
+file already exists and \fIappend\fR is "no" INVERTFIT will abort.
+.le
+.ls catdir = ")_.catdir"
+The directory containing the supported standard star catalogs.
+The default parameter value redirects \fIcatdir\fR
+to a package parameter of the same name. A list of standard
+catalogs may be obtained by printing the file "photcal$catalogs/README".
+Alternatively the user may create their own standard star catalogs
+and standard star catalog directory.
+.le
+
+.ih
+DESCRIPTION
+
+INVERTFIT computes magnitudes and colors for the standard or
+program stars in \fIobservations\fR by inverting the system of
+transformation equations defined in \fIconfig\fR, using the
+parameter values in the file \fIparameters\fR produced by the FITPARAMS
+task, and writes the fitted values to the output file \fIcalib\fR.
+If \fIappend\fR is "yes" output may be appended to an existing file.
+
+INVERTFIT computes the values of the catalog variables for the program
+stars by inverting the system of transformation equations defined in
+\fIconfig\fR. IT IS THE RESPONSIBILITY OF THE USER TO ENSURE THAT
+THE SYSTEM OF EQUATIONS IS ACTUALLY INVERTIBLE.
+Two minimum conditions must be met. First, the number of
+transformation equations must be greater than or equal to the number of
+catalog variables to be fit, and second, all the catalog variables must
+be on the right-hand side of the transformation equations.
+INVERTFIT will test for both of these conditions, issue a warning, and
+terminate execution if either of these conditions are not met.
+
+Below are two sets of transformation equations.
+The first set
+can be inverted by INVERTFIT, the second set cannot and must be
+evaluated by EVALFIT. In both cases the catalog variables to be fit
+are V and BV, and the observed quantities are mv, mb, Xv, and Xb.
+
+.nf
+ System 1: mv = v0 + V + v1 * Xv + v2 * BV
+ mb = b0 + V + BV + b1 * Xb + b2 * BV
+
+ System 2: V = v0 + mv + v1 * (Xv + Xb) / 2. + v2 * (mb - mv)
+ BV = b0 + b1 * (Xv + Xb) / 2.0 + b2 * (mb - mv)
+.fi
+
+It is possible though not recommended, to use set equation variables as
+unknowns in the transformation
+equations, provided that the total number of unknowns on the right-hand
+side of the equations remains less than or equal to the number of transformation
+equations. Set equations containing catalog variables must not be used
+in the left-hand side of the transformation equations. An example of a set
+of transformation equations which use a set equation variable is shown
+below. Note that there still are only two independent variables V and BV and
+that the output file \fIcalib\fR will contain V and BV only.
+
+.nf
+ System 1: set B = V + BV
+ mv = v0 + V + v1 * Xv + v2 * BV
+ mb = b0 + B + b1 * Xb + b2 * BV
+.fi
+
+Some systems of equations are invertible but do not have a UNIQUE solution.
+A sample of such a system is shown below.
+There are quadratic terms in BV, implying that this set of
+equations probably has two solutions, both of which may be
+be mathematically correct, but only one of which is physically meaningful.
+INVERTFIT does not test for this condition and may converge to either solution.
+
+.nf
+ System 1: mv = v0 + V + v1 * BV + v2 * BV ** 2
+ mb = b0 + V + BV + b1 * BV + b2 * BV ** 2
+.fi
+
+
+Formal errors for the fit may
+be computed by, 1) setting \fIerrors\fR to "obserrors" and using the
+error columns defined in the observations section of \fIconfig\fR
+to estimate the errors or 2) setting \fIerrors\fR to "equations" and
+using the error equations defined in \fIconfig\fR to estimate the errors.
+
+If the user wishes to match the objects in \fIobservations\fR with those
+in \fIcatalogs\fR in order for example, to compute the residuals of the fit,
+\fIcatalogs\fR must be defined. Similarly if \fIobjects\fR is "program"
+or "standard", \fIcatalogs\fR must be defined in order to enable
+id matching.
+
+Legal \fIcatalog\fR and \fIobservations\fR files are multi-column text
+files whose columns are delimited by whitespace.
+The first column of a catalog file is \fIalways\fR reserved for an object id.
+The first column of an observations file is reserved for an
+object id which can be
+used to match the observational data with the catalog data.
+All other columns may contain any quantity which can be
+expressed as an integer or real number. Sexagesimal format numbers
+(hh:mm:ss) are interpreted internally as real numbers. The constant
+INDEF can be used to represent data that is missing or undefined.
+Double precision and complex data are
+not supported. Lines beginning with "#" are treated as comment lines.
+
+By default INVERTFIT prints out the id,
+followed by the variables listed in the \fIprint\fR
+parameter, followed by the fit value, estimated
+error (if \fIerrors\fR is "undefined", and residual of the fit (for any
+standard star observations that can be matched with the catalog values)
+for each fitted catalog variable.
+The user can format the output by setting the \fIformat\fR parameter to an SPP
+style string. SPP format strings are described in detail below.
+
+.ih
+FORMATS
+A format specification has the form "%w.dCn", where w is the field width,
+d is the number of decimal places or the number of digits of precision,
+C is the format code, and n is radix character for format code "r" only.
+The w and d fields are optional. The format codes C are as follows:
+
+.nf
+b boolean (YES or NO)
+c single character (c or '\c' or '\0nnn')
+d decimal integer
+e exponential format (D specifies the precision)
+f fixed format (D specifies the number of decimal places)
+g general format (D specifies the precision)
+h hms format (hh:mm:ss.ss, D = no. decimal places)
+m minutes, seconds (or hours, minutes) (mm:ss.ss)
+o octal integer
+rN convert integer in any radix N
+s string (D field specifies max chars to print)
+t advance To column given as field W
+u unsigned decimal integer
+w output the number of spaces given by field W
+x hexadecimal integer
+z complex format (r,r) (D = precision)
+
+
+Conventions for w (field width) specification:
+
+ W = n right justify in field of N characters, blank fill
+ -n left justify in field of N characters, blank fill
+ 0n zero fill at left (only if right justified)
+absent, 0 use as much space as needed (D field sets precision)
+
+
+Escape sequences (e.g. "\n" for newline):
+
+\b backspace (\fBnot implemented\fR)
+\f formfeed
+\n newline (crlf)
+\r carriage return
+\t tab
+\" string delimiter character
+\' character constant delimiter character
+\\ backslash character
+\nnn octal value of character
+
+Examples
+
+%s format a string using as much space as required
+%-10s left justify a string in a field of 10 characters
+%-10.10s left justify and truncate a string in a field of 10 characters
+%10s right justify a string in a field of 10 characters
+%10.10s right justify and truncate a string in a field of 10 characters
+
+%7.3f print a real number right justified in floating point format
+%-7.3f same as above but left justified
+%15.7e print a real number right justified in exponential format
+%-15.7e same as above but left justified
+%12.5g print a real number right justified in general format
+%-12.5g same as above but left justified
+
+\n insert a newline
+
+.fi
+
+.ih
+EXAMPLES
+
+1. Evaluate the fit for a list of program stars in m92. Use the errors
+in the observed quantities to estimate the errors.
+
+.nf
+ ph> invertfit m92.obs m92.cfg m92.fit m92.cal
+.fi
+
+2. Repeat the fit computed above but include the variables xu and yu which
+are the positions of the objects in the u frame in the output.
+
+.nf
+ ph> invertfit m92.obs m92.cfg m92.fit m92.cal print="xu,yu"
+.fi
+
+3. Repeat the fit computed in 1 but format the output. The user has
+determined that the output will have 7 columns containing the object
+id, V, error(V), resid(V), BV, error(BV), and resid(BV).
+
+.nf
+ ph> invertfit m92.obs m92.cfg m92.fit m92.cal\
+ format="%-10.10s %7.3f %6.3f %6.3f %7.3f %6.3f %6.3f\n"
+.fi
+
+.ih
+SEE ALSO
+mkconfig,chkconfig,fitparams,evalfit
+.endhelp
diff --git a/noao/digiphot/photcal/doc/mkapfile.hlp b/noao/digiphot/photcal/doc/mkapfile.hlp
new file mode 100644
index 00000000..7f1d5876
--- /dev/null
+++ b/noao/digiphot/photcal/doc/mkapfile.hlp
@@ -0,0 +1,473 @@
+.help mkapfile Apr93 photcal
+.ih
+NAME
+mkapfile -- prepare an aperture corrections file from a list of APPHOT
+photometry files using the daogrow algorithm
+.ih
+USAGE
+mkapfile photfiles naperts apercors
+.ih
+PARAMETERS
+.ls photfiles
+A list of APPHOT photometry files containing the images names or image ids, x-y
+coordinates, filter ids, exposure times, airmasses, aperture radii,
+magnitudes, and magnitude errors
+of all the objects to be used to compute the aperture corrections.
+.le
+.ls naperts
+The number of aperture radii for which aperture radii, magnitudes, and
+magnitude errors are to be extracted from \fIphotfiles\fR.
+.le
+.ls apercors
+The name of the output text file containing the aperture
+corrections computed between \fIsmallap\fR and \fIlargeap\fR
+for each image in \fIphotfiles\fR.
+.le
+.ls smallap = 1
+The index of the smallest extracted aperture for which the aperture
+correction is to be computed.
+.le
+.ls largeap = 0
+The index of the largest extracted aperture for which the aperture
+correction is to be computed. If \fIlargeap\fR is 0, then
+the largest aperture is \fInaperts\fR.
+.le
+.ls magfile = ""
+The name of an optional output text file containing the magnitudes
+of all the stars in \fIphotfiles\fR, corrected to the aperture \fIlargeap\fR
+by using the measured magnitude and computed aperture correction at
+which the estimated error is a minimum.
+.le
+.ls logfile = ""
+The name of an optional output text file containing details of the curve
+of growth model fit for each image in \fIphotfiles\fR. If \fIlogfile\fR is
+"", no file is written. If \fIappend\fR = "no" a new logfile is written, if
+"yes" output is appended to an existing logfile.
+.le
+.ls plotfile = ""
+The name of an optional output plot file containing plots of the
+curve of growth model fit, the fit residuals versus aperture radius,
+magnitude inside the first aperture, x coordinate, and y coordinate,
+and the aperture correction versus aperture radius for each image
+in \fIphotfiles\fR. If \fIplotfile\fR is "", no file is written.
+If \fIappend\fR = "no" a new plotfile is written, if
+"yes" output is appended to an existing plotfile.
+.le
+.ls append = no
+Open \fIlogfile\fR and/or \fIplotfile\fR in append mode ?
+.le
+.ls obsparams = ""
+The name of an optional input text file containing the correct filter ids,
+exposure times, and airmasses for each image whose values are either
+undefined or incorrectly stored in \fIphotfiles\fR. The observing parameters
+for each image are listed in \fIobsparams\fR,
+1 image per line with the image name in column 1 and the filter id,
+exposure time, and airmass in
+\fIobscolumns\fR. The image names must match those in \fIphotfiles\fR.
+.le
+.ls obscolumns = "2 3 4 5"
+The list of numbers separated by commas or whitespace specifying which
+columns in the text file \fIobsparams\fR contain the correct filter ids,
+exposure times, airmasses, and times of observation respectively. The
+number 0 can be used as
+a place holder in the obscolumns string. For example to correct only
+the \fIphotfiles\fR airmass values, \fIobscolumns\fR should be set to
+"0 0 column 0", where column is the airmass column number.
+.le
+.ls maglim = 0.10
+The maximum magnitude error permitted in the input magnitude measurements.
+Data at and following the first aperture radius whose associated magnitude
+measurement has an error greater than \fImagerr\fR is rejected on input.
+.le
+.ls nparams = 3
+The number parameters in the five parameter curve of growth model to be fit.
+The remaining parameters 5 - nparams parameters are held constant.
+For \fInparams\fR = 3, the parameters \fIswings\fR,
+\fIpwings\fR, and \fIpgauss\fR are fit, and \fIrgescale\fR and
+and \fIxwings\fR maintain their default values.
+\fINparams\fR must be greater than or equal to one.
+.le
+.ls swings = 1.2
+The slope of the power law component of the analytic curve of growth model
+describing the seeing independent part of the stellar profile. For a
+physically reasonable profile \fIswings\fR must be greater than 1.
+.le
+.ls pwings = 0.1
+The fraction of the total power in the seeing independent
+part of the stellar profile, if \fIxwings\fR is 0.0.
+.le
+.ls pgauss = 0.5
+The fraction of the total power in the seeing dependent part of the
+profile contained in the gaussian rather than the exponential component
+of the analytic curve of growth function.
+.le
+.ls rgescale = 0.9
+The ratio of the exponential to the gaussian radial scale
+lengths in the seeing dependent part of the profile.
+In practice the curve of growth model fits for most data do not depend
+significantly on this parameter and it can be left at its default value.
+.le
+.ls xwings = 0.0
+A parameter describing the effect of airmass on the total power
+in the seeing independent part of the stellar profile, where this quantity
+is defined as defined as \fIpwings\fR + \fIxwings\fR * \fIairmass\fR.
+.le
+.ls interactive = yes
+Fit the curve of growth interactively ?
+.le
+.ls verify = no
+Verify interactive user input ? This option is used only if \fIobsparams\fR
+is set to the standard input STDIN.
+.le
+.ls gcommands = ""
+The interactive graphics cursor.
+.le
+.ls graphics = "stdgraph"
+The default graphics device.
+.le
+
+.ih
+DESCRIPTION
+
+MKAPFILE takes a list of APPHOT photometry files \fIphotfiles\fR,
+containing the image names, x and y coordinates, filter ids, exposure times,
+airmasses, aperture radii, measured magnitudes, and magnitude errors for
+one or more stars in one or more images, computes the aperture correction
+between the apertures \fIsmallap\fR and \fIlargeap\fR for each image using
+a weighted average of the computed model curve of growth and the observed
+curve of growth, and writes the computed aperture corrections
+to \fIapercors\fR.
+
+MKAPFILE computes the aperture corrections by performing the following steps:
+1) extracts the image names, x and y coordinates, filter ids, exposure
+times, airmasses, times of observation, and \fInaperts\fR aperture radii,
+measured magnitudes,
+and magnitude errors for all the objects in \fIphotfiles\fR, 2) rejects data
+for all aperture radii greater than any aperture radius for which the magnitude
+or magnitude error is INDEF, the magnitude error is > \fImaglim\fR,
+or the number of apertures left containing good data is < 2,
+3) adds in quadrature a magnitude error of 0.001 magnitudes to the extracted
+magnitude errors, 4) edits any incorrect or undefined values of
+the filter id, exposure time, airmass, and time of observation
+in \fIphotfiles\fR using the values
+in \fIobsparams\fR if defined, or default values of INDEF, 1.0, 1.25, and INDEF
+respectively, 5) computes the theoretical and observed curve of growth
+curve for each image, 6) computes the adopted curve of growth for each
+image by combining the theoretical and observed curves with weights that
+favor the observed curve at smaller aperture radii and the theoretical curve
+at larger aperture radii, 7) integrates the adopted growth curve between
+the \fIsmallap\fR and \fIlargeap\fR apertures to
+compute the final aperture correction, 8) writes the results for each image
+to \fIapercors\fR, 9) optionally computes magnitudes for all the stars
+in \fIphotfiles\fR corrected to \fIlargeap\fR using the observed magnitude
+and computed correction for which the signal to noise is highest,
+10) optionally writes a \fIlogfile\fR containing the details of the
+fit for all the individual images, 11) optionally writes a file of
+plots of the fit, the residuals, and the curve of growth for all the
+images.
+
+MKAPFILE extracts the fields/columns IMAGE, XCENTER, YCENTER, IFILTER,
+ITIME, XAIRMASS, OTIME, RAPERT, MAG and MERR from \fIphotfiles\fR.
+The number of aperture radii,
+magnitudes, and magnitude errors extracted are specified by \fInaperts\fR.
+For example if \fInaperts\fR
+is 15, then the first 15 values of RAPERT, MAG, and MERR are extracted
+from \fIphotfiles\fR.
+
+Values of the filter ids, exposure times, airmasses, and times of
+observation which are undefined
+or incorrect in \fIphotfiles\fR, can be entered or corrected by reading values
+from the file \fIobsparams\fR, a simple multi-column text file with a
+format specified by \fIobscolumns\fR.
+If no values are read from \fIphotfiles\fR or \fIobsparams\fR, default values
+for the filter id, exposure time, airmass, and time of observation
+of "INDEF", 1.0, 1.25, and INDEF respectively will be assigned.
+It must be emphasized that the airmass is actually used in the curve of
+growth analysis only if \fInparams\fR is equal to
+5, and that the quantities filter id, exposure time, and time of observation
+are not used in
+the analysis at all. However if the user should wish to use the corrected
+magnitudes optionally computed and written to \fImagfile\fR in any subsequent
+analysis it is important to include the correct values of
+these quantities in \fImagfile\fR.
+
+If \fIinteractive\fR is "yes", the user can interact with the curve of
+growth fitting process by examining plots of the model fit, the residuals
+versus aperture radius, magnitude in the first aperture, x and y coordinates,
+and the aperture correction
+as a function of radius, by changing the number of parameters to be fit and
+their initial values, deleting and undeleting points with the graphics
+cursor, refitting the model curve of growth and reexamining the results
+until satisfied. Users should realize when deleting or undeleting points
+with the graphics cursor that all
+the apertures above the marked point will be deleted or undeleted.
+
+The output aperture corrections file \fIapercors\fR is a simple text
+file containing the image name in column 1, the aperture correction
+computed from \fIsmallap\fR to \fIlargeap\fR in column 2, and the
+estimated error in the aperture correction in column 3.
+The sign of the aperture correction is such that the
+correction must be added to the observed magnitude to compute the corrected
+magnitude. \fIApercors\fR is written in a form suitable for input to
+the MKNOBSILE, MKOBSFILE, or OBSFILE tasks.
+
+If \fImagfile\fR is not "", a file containing the image name, x and y
+position, filter id, exposure time, airmass, time observation,
+magnitude corrected to
+\fIlargeap\fR using the observed magnitude and computed correction at the
+aperture radius with the highest signal-to-noise ratio, the associated
+magnitude error, and the radius to which the correction was made,
+for all the stars in all the images in \fIphotfiles\fR.
+\fIMagfile\fR is written in a form suitable for input to the OBSFILE task.
+
+If \fIlogfile\fR is not "", all the details and diagnostics of the
+curve of growth fit are logged either to a new file, if \fIappend\fR = "no"
+or to a previously existing file, \fIappend\fR = "yes". The output
+consists of: 1) a banner listing
+the date, time, and \fIapercors\fR for which the entry is relevant, 2)
+a listing of the number of parameters \fInparams\fR in the five parameter
+curve of growth model to be fit, the initial values of all the parameters, and
+the small and large aperture numbers, 3) the fitted values of the
+curve of growth model parameters and their errors where parameters which
+were not fit have zero-valued errors, 4) the computed seeing radius
+for each image,
+5) the theoretical, observed, and adopted curves of growth and
+their associated errors, 6) the aperture correction to largeap,
+the estimated total aperture correction to an
+aperture radius twice the largest aperture radius, and the estimated error
+in the aperture correction, 7) the aperture
+correction from \fIsmallap\fR to \fIlargeap\fR, 8) for each star
+in the image the observed magnitudes, magnitude corrected to the largest
+aperture, and magnitude corrected to twice the largest aperture, and
+finally, 9) a summary of the mean adopted curve of growth, the mean residual,
+and the mean residual squared for all the data for all the images
+as a function of aperture radius.
+
+If \fIplotfile\fR is not "", plots of the final curve of growth model fit,
+residuals as a function of aperture radius, magnitude, x, y, and the
+aperture correction to the largest aperture \fIlargeap\fR
+for each image in \fIphotfiles\fR are saved in the plot metacode file
+\fIplotfile\fR..
+
+.ih
+CURSOR COMMANDS
+
+The following commands are available in interactive graphics cursor mode.
+
+.nf
+ Keystroke Commands
+
+? Print help
+w Print computed aperture correction
+c Print coordinates of star nearest cursor
+f Compute a new fit
+d Delete point(s) nearest the cursor
+u Undelete point(s) nearest the cursor
+m Plot the observed and model cog versus radius
+r Plot the cog fit residuals versus radius
+b Plot the cog fit residuals versus magnitude
+x Plot the cog residuals versus the x coordinate
+y Plot the cog residuals versus the y coordinate
+a Plot the aperture correction versus radius
+g Redraw the current plot
+n Move to the next image
+p Move to the previous image
+q Quit task
+
+ Colon commands
+
+:show parameters Show the initial cog model parameter values
+:show model Show the fitted cog model parameters
+:show seeing Show the computed seeing radii for all images
+:image [value] Show/set the image to be analyzed
+
+ Colon Parameter Editing Commands
+
+:smallap [value] Show/set the index of the smallest aperture
+:largeap [value] Show/set the index of the largest aperture
+:nparams [value] Show/set the number of cog model parameters to fit
+:swings [value] Show/set initial power law slope of stellar wings
+:pwings [value] Show/set fraction of total power in stellar wings
+:pgauss [value] Show/set fraction of total core power in gaussian
+:rgescale [value] Show/set ratio of exp to gauss radial scales
+:xwings [value] Show/set the extinction coefficient
+.fi
+
+.ih
+ALGORITHMS
+
+The algorithm used to compute the aperture correction is the DAOGROW
+algorithm developed by Peter Stetson (1990, see the references section).
+
+In this algorithm the stellar profile is approximated by the following
+3 component model where P, G, E denote the power law, gaussian, and
+exponential analytic components of the model respectively. The subscript i
+denotes quantities that are a function of each image.
+
+.nf
+
+ I[r,X[i];RO[i],swings,pwings,pgauss,regscale,xwings] =
+ (pwings + X[i] * xwings) * P[r;swings] + (1 - pwings - X[i] *
+ xwings) * (pgauss * G[r;RO[i]] + (1 - pgauss) *
+ E[r;rgescale,RO[i]])
+
+ P[r;swings] = mnorm * (1 + r ** 2) ** swings
+ mnorm = (swings - 1) / PI
+
+ G[r;RO[i]] = gnorm * exp (-0.5 * r ** 2 / RO[i] ** 2)
+ gnorm = 1 / (2 * PI * RO[i] ** 2)
+
+ E[r;RO[i]] = hnorm * exp (-r / (rgescale * RO[i]))
+ hnorm = 1 / (2 * PI * (rgescale * RO[i]) ** 2)
+
+.fi
+
+This equation is actually applied to the magnitude differences between
+apertures where the observed magnitude differences are computed as follows
+for image i, star j, and aperture k.
+
+.nf
+
+ mdiff[i,j,k] = m[i,j,k] - m[i,j,k-1] k=2,..,naperts
+
+.fi
+
+
+The observed differences are fit by least-squares techniques to
+to the theoretical model differences represented by the following equation.
+
+.nf
+
+diff[i,j,k] = -2.5 * log10 (integral (2 * PI * r * I) from 0 to r[k] /
+ integral (2 * PI * r * I) from 0 to r[k-1])
+
+.fi
+
+The integrals of the three model components P, G, and E are the following.
+
+.nf
+
+ integral (2 * PI * r * P) = 1 - (1 + r ** 2) ** -swings
+
+ integral (2 * PI * r * G) = 1 - exp (-r ** 2 / (2 * RO[i] ** 2))
+
+ integral (2 * PI * r * H) = 1 + (1 + r / (rgescale * RO[i]) *
+ exp (-r / (rgescale * RO[i]))
+
+.fi
+
+In a given run of MKAPFILE the seeing radius
+RO[i] is fit separately for each image, but the parameters swings, pwings,
+pgauss, rgescale, and xwings are fit to the entire data set. Therefore
+the RO[i] values define a family curves, each differing from the other
+by the seeing radius RO[i] alone. It turns out that for most data the
+fits do not depend significantly on the \fIrgescale\fR and \fIxwings\fR
+parameters. Therefore by default \fInparams\fR is set to 3 and
+\fIrgescale\fR and \fIxwings\fR are set to default values of 0.9 and 0.0
+respectively.
+
+After the theoretical and observed growth curves are computed for
+each image, they are combined to produce an adopted growth curve. The
+weighting scheme used in the combining process is such that at small radii
+where the observed magnitude differences have the smallest errors,
+the observed values,
+are favored, and at large radii the theoretical curve is favored. At
+all points in the computation of the theoretical curve, the observed curve,
+and the adopted curve, tests are made for deviant data points and these
+are down-weighted. The adopted curve is integrated between \fIsmallap\fr
+and \fIlargeap\fR to produce the aperture correction for each image.
+
+Because the error in the observed magnitudes grows rapidly toward
+larger radii, while the error in the aperture correction grows
+rapidly toward smaller radii, the combined error for the star will
+have some minimum value, usually at an intermediate aperture. If
+\fImagfile\fR is not "", the magnitudes corrected to \fIlargeap\fR
+using the observed magnitude and correction where the error
+is lowest are written to \fImagfile\fR, along with the image id, x and y
+coordinates, filter ids, exposure times, airmasses, and errors in the
+magnitude. This file can be read into the OBSFILE program so as to
+create a photometry catalog suitable for input into PHOTCAL.
+
+
+.ih
+REFERENCES
+
+A full description of the DAOGROW algorithm used by MKAPFILE can be
+found in the article "On the Growth-Curve Method for Calibrating
+Stellar Photometry with CCDs" by Peter Stetson in PASP 102, 932
+(1990).
+
+.ih
+EXAMPLES
+
+1. Prepare an aperture corrections file from a set of observations
+from 5 different data frames taken in a single night.
+
+.nf
+ ph> mkapfile *.mag.* 15 apercor
+
+ ... plot of the cog for the first image will appear
+
+ ... type r to examine fit residuals versus radius
+
+ ... type a to examine the aperture correction curve
+ versus radius
+
+ ... type n to look at results for next image
+
+ ... type d to remove a discrepant point
+
+ ... type f to refit the cog
+
+ ... type r to examine the residuals for this image
+
+ ... type p to recheck the residuals for the first image
+
+ ... step through the remaining image deleting points and
+ refitting as necessary
+
+ ... type q to quit
+
+ ... the compute aperture corrections will appear in apercor
+.fi
+
+2. Repeat the previous example in non-interactive mode saving all the
+details and plots of the fit in the log and plot file respectively.
+
+.nf
+ ph> mkapfile *.mag.* 15 apercor inter- logfile=apercor.log\
+ plotfile=apercor.plot
+
+ ph> page apercor.log
+
+ ... page through the log file
+
+ ph> gkiextract apercor.plot "1-25" | stdplot
+
+ ... send all the plots of the fit to the default plotter
+.fi
+
+3. Compute the magnitudes corrected to largeap, of all the standard
+stars observed in a night using the observed magnitude and computed magnitude
+correction at the aperture radius with the lowest error.
+Assume that the filter ids (U,B,V), exposure times, and airmasses were
+all present and correct in the photometry files.
+
+.nf
+ ph> mkapfile stdfiles 15 apercor inter- magfile="stdfiles.ap"\
+ logfile=apercor.log plotfile=apercor.plot
+
+ ph> obsfile stdfiles.ap "1,2,3,4,5,6,7,8,9" "U,B,V" imsets stdobs
+
+ ... create a standard star observations file suitable for
+ input to the photcal package
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+apfile, mknobsfile,mkobsfile,obsfile
+.endhelp
diff --git a/noao/digiphot/photcal/doc/mkcatalog.hlp b/noao/digiphot/photcal/doc/mkcatalog.hlp
new file mode 100644
index 00000000..11f03a3f
--- /dev/null
+++ b/noao/digiphot/photcal/doc/mkcatalog.hlp
@@ -0,0 +1,220 @@
+.help mkcatalog Aug91 noao.digiphot.photcal
+
+.ih
+NAME
+mkcatalog -- create or edit a catalog, usually but not necessarily
+a standard star catalog
+.ih
+USAGE
+mkcatalog catalog
+.ih
+PARAMETERS
+.ls catalog
+The name of the new output catalog to be created or a previously existing
+catalog to be edited.
+.le
+.ls review = no
+Review any pre-existing entries?
+.le
+.ls verify = no
+Verify each new entry?
+.le
+.ls edit = yes
+Enter edit mode after entering all the values?
+.le
+.ih
+DESCRIPTION
+
+MKCATALOG is a script task which permits the user to create or edit
+the catalog \fIcatalog\fR, usually but not necessarily, a standard star
+catalog. MKCATALOG has two modes of operation, entry mode and edit mode.
+In entry mode MKCATALOG prompts the user for input.
+In edit mode MKCATALOG calls up the default editor specified by
+the IRAF environment variable \fIeditor\fR.
+
+If \fIcatalog\fR is a new catalog, MKCATALOG prompts the user for
+the name of the object id column, the names of the data columns,
+the names of the error columns (these are optional), and the widths
+of the columns. Typing the end-of-file character <EOF>,
+usually ^Z or ^D, terminates column definition
+and places the user in entry mode.
+In entry mode MKCATALOG prompts the user for the object ids and data values.
+Entering carriage return, <CR>, after MKCATALOG prompts for a new object id
+writes a blank line to the output catalog.
+Entering <CR> after MKCATALOG prompts for any other column
+value writes INDEF (the IRAF undefined value) in that column of the
+output catalog.
+Entry mode is terminated by typing <EOF> in response to a query for
+a new object id. The user may verify each new
+entry by setting the parameter \fIverify\fR to "yes".
+
+Each new catalog created by MKCATALOG has an associated format
+description file listing the column names and numbers associations defined by
+the user. This file, referenced by its parent catalog name, can be
+used as input to the MKCONFIG task.
+The actual name of the format description file on disk is constructed by
+prepending the catalog name \fIcatalog\fR with the string "f" and
+appending the string ".dat". For example if a new catalog
+called "UBVcat" is created by MKCATALOG, a format description
+file called "fUBVcat.dat" will also be created. Any pre-existing format
+description file of that name, which does not have an associated catalog
+file, will be deleted.
+
+If the catalog \fIcatalog\fR exists and was created with MKCATALOG,
+MKCATALOG reads
+the number of columns, the column names, and column widths from the
+header of the catalog, and enters entry mode positioned at the end
+of the file. If the parameter \fIreview\fR = "yes", then the user can
+review and verify existing catalog entries before entering new ones.
+When entry mode is terminated MKCATALOG enters edit mode
+in the usual way.
+
+If \fIcatalog\fR exists but was not created with MKCATALOG, MKCATALOG
+enters edit mode immediately.
+
+If \fIcatalog\fR is a standard star catalog, the user should be aware
+that the object ids he/she has typed in, are those against which the object
+ids in the standard star observations files will be matched by the
+fitting task FITPARAMS.
+Normally the user is expected to edit the object ids in the standard
+star observations
+files to match those in the standard star catalog.
+For example, the PHOTCAL APPHOT/DAOPHOT pre-processor tasks MKNOBSFILE
+and MKOBSFILE, produce observations files whose object ids
+are of the form "field-#", where "field" is the name
+of the observed field and "#" is a sequence number, which is defined
+only if there is more than one observed star in the field.
+In this scheme the id of the the fourth observed star in the field "M92"
+is "M92-4". If this star is actually the standard star "IX-10" in
+\fIcatalog\fR, the user must change the object id in the observations file
+to "IX-10". Alternatively the user can set up the naming
+convention in \fIcatalog\fR itself, to match the naming
+convention of MKNOBSFILE
+or MKOBSFILE by assigning the standard stars names like "field-#" and
+subsequently measuring the standard stars in the same order as they
+appear in the catalog. In this scheme star, "M92-4" in
+the observations file would also be "M92-4" in the standard star
+catalog, and no editing would be required. This technique is most useful
+for standard sequences in clusters.
+
+THE MKCATALOG TASK AND THE ENTIRE PHOTCAL PACKAGE IMPOSE THE FOLLOWING
+RESTRICTIONS
+ON BOTH STAR ID NAMES AND THE COLUMN ID NAMES THAT MAY BE ASSIGNED, AND ON
+THE FORMAT OF EACH FIELD.
+
+Object id names must be composed of characters in the set [a-z,A-Z,0-9,+,-,_].
+Other characters may be included as part of the user id, but
+will be ignored by the PHOTCAL id matching code. Object id names are
+case insensitive. To the id matching code the name "BD+61_305" is the
+same as "bd+61_305".
+
+Column names must be composed of characters in the set [a-z,A-Z,0-9]
+and the first character of the column name must be a letter of the alphabet.
+This means for example, that an individual column cannot be assigned the
+name "B-V", since "B-V" will be interpreted as an arithmetic expression not
+as a variable, by the PHOTCAL equation parsing routines.
+"B-V" may be replaced with something like "BV" or "BMV".
+MKCATALOG will complain if the user tries to enter an illegal column name.
+Column names are case sensitive. Column "BV" is not the same as
+column "bv".
+
+Whitespace is not permitted in either the object ids or in the column
+values. MKCATALOG will truncate any id or column value at the first
+whitespace encountered. The column widths entered by the user are used
+solely to determine
+the maximum width of each field (excess characters will be truncated)
+and to align the columns for ease of
+visual inspection by the user. The column widths are not used by the
+PHOTCAL catalog reading code.
+
+.ih
+EXAMPLES
+
+1. Create a new standard star catalog containing the 3 photometric indices
+V, B-V, and U-B and their respective errors. Note that MKCATALOG supplies
+default names of the form "error(name)" for the error columns where "name"
+is the name of the previous column. Users are strongly urged to use the
+default names since they simplify the use of the statistical weighting
+scheme in the FITPARAMS task. If no error information is available
+error column entry can be skipped by typing <-> in response to the query
+for an error column name.
+
+.nf
+ph> mkcatalog UBVcat
+
+... enter the column names, error column names and widths as prompted
+ and shown below, note that the end-of-file character <EOF> is
+ actually ^Z in this case
+
+Enter the id column name (name, <CR>=ID, <EOF>=quit entry):
+ Enter width of id column (width, <CR>=15):
+Enter a name for column 2 (name, <CR>=COL2, <EOF>=quit entry): V
+ Enter width of column 2 (width, <CR>=10):
+Enter a name for error column 3 (name, <CR>=error(V), <->=skip):
+ Enter width of column 3 (width, <CR>=10):
+Enter a name for column 4 (name, <CR>=COL4, <EOF>=quit entry): BV
+ Enter width of column 4 (width, <CR>=10):
+Enter a name for error column 5 (name, <CR>=error(BV), <->=skip):
+ Enter width of column 5 (width, <CR>=10):
+Enter a name for column 6 (name, <CR>=COL6, <EOF>=quit entry): UB
+ Enter width of column 6 (width, <CR>=10):
+Enter a name for error column 7 (name, <CR>=error(UB), <->=skip):
+ Enter width of column 7 (width, <CR>=10):
+Enter a name for column 8 (name, <CR>=COL8, <EOF>=quit entry): ^Z
+
+
+Catalog UBVcat in file UBVcat has 7 columns
+ Column 1: ID
+ Column 2: V
+ Column 3: error(V)
+ Column 4: BV
+ Column 5: error(BV)
+ Column 6: UB
+ Column 7: error(UB)
+
+
+... note that the <EOF> character terminates column definition
+
+... enter values for each defined column as prompted
+
+... type <EOF> to terminate entry mode
+
+... review the entries with the editor
+.fi
+
+
+2. Add new entries to the file created in example 1.
+
+.nf
+ph> mkcatalog UBVcat
+
+... enter new values as prompted
+
+... type <EOF> to terminate entry mode
+
+... review the catalog with the editor
+.fi
+
+
+3. Edit an existing catalog created with a foreign program.
+
+.nf
+ph> mkcatalog VRI.usr
+
+... review the catalog with the editor
+.fi
+
+.ih
+TIME REQUIREMENTS
+
+.ih
+BUGS
+
+The longest line permitted by an editor varies from editor to
+editor. Users should be aware that it may not be possible to use
+edit mode on very long text lines.
+
+.ih
+SEE ALSO
+photcal$catalogs/README,mknobsfile,mkobsfile,mkconfig
+.endhelp
diff --git a/noao/digiphot/photcal/doc/mkconfig.hlp b/noao/digiphot/photcal/doc/mkconfig.hlp
new file mode 100644
index 00000000..ff4e2cf2
--- /dev/null
+++ b/noao/digiphot/photcal/doc/mkconfig.hlp
@@ -0,0 +1,451 @@
+.help mkconfig Aug91 noao.digiphot.photcal
+.ih
+NAME
+mkconfig -- create a new configuration file
+.ih
+USAGE
+mkconfig config
+.ih
+PARAMETERS
+.ls config
+The name of the new configuration file.
+.le
+.ls catalog
+The source of the standard star catalog format description.
+\fICatalog\fR may be one of the supported standard star
+catalogs maintained
+in the directory "photcal$catalogs/", a catalog created with
+MKCATALOG, the standard input "STDIN",
+or a file created by the user containing the catalog
+format description.
+\fICatalog\fR is not prompted for if \fItemplate\fR is "".
+.le
+.ls observations
+The source of the observations file format description.
+\fIObservations\fR may be a catalog created by MKNOBSFILE,
+MKOBSFILE, OBSFILE, or MKCATALOG, the standard input "STDIN",
+or a file created by the user containing the observations file format
+description. \fIObservations\fR is not prompted for if \fItemplate\fR is "".
+.le
+.ls transform
+The source of the transformation equations definition.
+\fITransform\fR may be the name of one of the supported standard star
+catalogs maintained in the directory "photcal$catalogs/",
+the standard input "STDIN", or a file created by the user
+containing the transformation equations definition.
+\fITransform\fR is not prompted for if \fItemplate\fR is "".
+.le
+.ls template = ""
+The name of an existing configuration file that can be used as a template
+for the new configuration file.
+If \fItemplate\fR is the null string "", then MKCONFIG
+prompts the user for the source of the standard star catalog
+and observations file format descriptions
+\fIcatalog\fR and \fIobservations\fR, and the source of the transformation
+equation definitions \fItransform\fR.
+If \fItemplate\fR exists,
+MKCONFIG copies \fItemplate\fR into \fIconfig\fR and enters the editor
+if \fIedit\fR is "yes".
+.le
+.ls catdir = ")_.catdir"
+The directory containing the supported standard star catalogs.
+The default parameter value redirects \fIcatdir\fR
+to a package parameter of the same name. A list of standard
+catalogs may be obtained by printing the file "photcal$catalogs/README".
+Alternatively the user may create their own standard star catalogs
+and standard star catalog directory.
+.le
+.ls verify = no
+Verify each new entry in the configuration file as it is entered?
+.le
+.ls edit = yes
+Enter the editor and review the new configuration file?
+.le
+.ls check = yes
+Check the new configuration file for semantic and syntax errors?
+.le
+.ls verbose = no
+Print detailed information about the results of the check step instead
+of only a short summary?
+.le
+
+.ih
+DESCRIPTION
+
+MKCONFIG is a script task which creates and/or edits the configuration
+file \fIconfig\fR. If the configuration file already
+exists MKCONFIG, quits with a warning message. If the configuration file is
+a new file, MKCONFIG either prompts the
+user for input if \fItemplate\fR = "", or copies the existing configuration
+file \fItemplate\fR into \fIconfig\fR.
+
+If \fItemplate\fR is "", MKCONFIG prompts the user for:
+1) the source of the standard star catalog format description
+\fIcatalog\fR, which assigns names to the columns of the standard star
+catalog,
+2) the source of the observations file format description
+\fIobservations\fR, which assigns names to the columns of the observations file,
+3) and the source of the transformation equations \fItransform\fR, which
+defines the form of the transformation equations from the
+instrumental to the standard system.
+
+If \fIcatalog\fR, \fIobservations\fR, or \fItransform\fR
+are set to the standard input "STDIN", MKCONFIG prompts for input from
+the terminal, verifying the input as it is entered if \fIverify\fR is "yes".
+
+If \fIcatalog\fR is a standard star catalog name or a file name,
+MKCONFIG searches 1) the current directory for the associated format
+description file "fcatalog.dat", 2) the directory
+\fIcatdir\fR for the format description file "fcatalog.dat",
+and 3) the current directory for a file called "catalog", in that order.
+\fICatalog\fR is usually one of the supported standard star catalogs or
+a standard star catalog created by the user with MKCATALOG.
+
+If \fIobservations\fR is an observations file name or a file name,
+MKCONFIG searches 1) the current directory for the format
+description file "fobservations.dat", and 2)
+the current directory for a file called "observations", in that order.
+\fIObservations\fR is usually created by the user with MKNOBSFILE or MKOBSFILE.
+
+If \fItransform\fR is assigned a standard star catalog name or a file name,
+MKCONFIG searches 1) the directory
+\fIcatdir\fR for the transformation equations definition file
+"ttransform.dat", and 2)
+the current directory for a file called "transform", in that order.
+\fITransform\fR is usually one of the supported standard star catalogs or
+"STDIN".
+
+The default photometric standards directory is "photcal$catalogs/".
+A list of supported catalogs is shown below.
+The standard catalog format description files may be listed or
+printed with the commands
+"dir photcal$catalogs/f*.dat" or "lprint photcal$catalogs/f*.dat" respectively.
+The standard transformation equation definition files may be listed or
+printed with
+the commands "dir photcal$catalogs/t*.dat" or "lprint photcal$catalogs/t*.dat"
+respectively.
+
+After data entry, and if \fIedit\fR is "yes",
+MKCONFIG enters the default text editor defined by the
+IRAF environment variable \fIeditor\fR. Small
+corrections to the configuration file may be made at this point.
+Next the configuration file is checked for semantic and syntax errors
+if \fIcheck\fR is "yes" and the results are written on the terminal.
+
+.ih
+STANDARD CATALOG FORMAT AND TRANSFORM FILES
+
+The list of standard star catalog files, catalog format description files
+and transformation equation definitions files is presented below.
+
+.nf
+ # catalogs # formats # transformations
+
+ landolt.dat flandolt.dat tlandolt.dat
+.fi
+
+.ih
+THE CONFIGURATION FILE
+
+The \fIconfiguration file\fR is a text file which describes how the input data
+is organized in the input files, and defines the form of the transformation
+equations required to convert from the instrumental to the standard system.
+
+The input data is assumed to come from two sources,
+standard star catalogs known as \fIcatalogs\fR
+and \fIobservations\fR files.
+The \fIcatalog\fR files contain the standard indices of a set of standard
+stars, referenced in the catalog by a name called the
+matching name.
+The \fIobservations\fR files contain the instrumental magnitudes or colors of
+a subset of the standard stars and/or program stars, also referenced by a
+matching name.
+The names of the observed standard stars must match the names in the
+standard star catalog. The matching names must be stored in column 1
+in both the catalog and observations files.
+
+The configuration file is divided up into three sections: the \fIcatalog
+section\fR which describes the format of the catalog files, the
+\fIobservations section\fR which describes the format of the observation
+files, and the \fItransformation section\fR which defines the
+transformation equations. The catalog section must always appear before the
+observation section, and the observation section must always appear before the
+transformation section.
+
+The \fIcatalog and observations sections\fR are used to assign
+names to the columns in the input catalog and observations files.
+These columns may later be referenced by name and the names used
+as variables in the transformation equations.
+
+The \fItransformation section\fR is used to define the
+transformation equations,
+to specify which parameters are to be varied and which are to be held constant
+during the fitting process,
+and to assign initial values to all the parameters.
+Any number of transformation equations may be defined in
+the transformation section.
+
+The transformation section may also be used to, OPTIONALLY,
+define temporary variables (the set equations), define explicitly
+the derivatives of the transformation equations to be fit with respect
+to the parameters (derivative equations
+and delta declarations), define expressions for the weights and
+errors (weight and error equations), and define an expression to be
+plotted (the plot equation).
+
+For a detailed description
+of the grammar and syntax of the configuration file type \fI"help config"\fR.
+
+The following examples show typical configuration files for two different types
+of photometric calibrations.
+
+
+\fIExample 1\fR. A sample configuration file for reducing UBV photoelectric
+photometry. Note that the instrumental magnitudes are all on the right-hand
+side of the transformation equation and that the standard magnitudes and colors
+are all
+on the left-hand side. Once the values of the transformation equation
+parameters are computed by FITPARAMS using observations of the standard stars,
+standard magnitudes and colors for the program stars can be computed simply by
+evaluating the right-hand side of the transformation equation using
+the task EVALFIT. In this type of setup the equations are fit separately
+and evaluated separately. Note also the use of the error column declarations
+in the observation section, and the use of the const statement to fix the
+values of some parameters.
+
+.nf
+# Configuration file for reducing UBV photoelectric photometry.
+
+catalog
+
+V 2 # V magnitude
+BV 3 # B - V color
+UB 4 # U - B color
+
+observation
+
+v 2 # v instrumental magnitude
+b 3 # b instrumental magnitude
+u 4 # u instrumental magnitude
+error(v) 5 # error in v instrumental magnitude
+error(b) 6 # error in b instrumental magnitude
+error(u) 7 # error in u instrumental magnitude
+X 8 # airmass
+
+transformation
+
+fit v1 = 0.0, v2=0.16, v3=-0.043
+const v4 = 0.0
+VFIT: V = v1 + v - v2 * X + v3 * (b - v) + v4 * X * (b - v)
+
+fit b1 = 0.0, b2=0.09, b3=1.266
+const b4 = 0.0
+BVFIT: BV = b1 - b2 * X + b3 * (b - v) + b4 * X * (b - v)
+
+fit u1 = 0.0, u2=0.300, u3=0.861
+const u4 = 0.0
+UBFIT: UB = u1 - u2 * X + u3 * (u - b) + u4 * X * (u - b)
+.fi
+
+
+\fIExample 2\fR. A sample configuration file for reducing UBV CCD photometry.
+Note that the instrumental magnitudes are all on the left-hand side of the
+transformation equations and the standard star magnitudes and colors
+are all on the right-hand
+side. Once the values of the transformation equation parameters have been
+computed by FITPARAMS using observations of the standard stars, the
+standard magnitudes and colors of the program stars
+can be computed by inverting the system of equations using the task
+INVERTFIT.
+In this type of setup the equations are fit independently, but evaluated
+as a system.
+Note also that the telescope filter slots 1, 2 and 3 were assigned to
+filters v, b and u respectively which is why MKNOBSFILE assigned the names
+m1, m2, m3 to v, b, and u respectively. The user can change these if desired.
+Note also the use of the error declaration statements in both the catalog
+and the observations section.
+
+.nf
+catalog
+
+V 2 # V magnitude
+BV 3 # B - V color
+UB 4 # U - B color
+error(V) 5 # error in V magnitude
+error(BV) 6 # error in B-V color
+error(UB) 7 # error in U-B color
+
+observation
+
+ut1 3 # ut time of filter 1 observation
+X1 4 # airmass of filter 1 observation
+m1 7 # filter 1 instrumental magnitude
+error(m1) 8 # error in filter 1 instrumental magnitude
+ut2 10 # ut time of filter 2 observation
+X2 11 # airmass of filter 2 observation
+m2 14 # filter 2 instrumental magnitude
+error(m2) 15 # error in filter 2 instrumental magnitude
+ut3 17 # ut time of filter 3 observation
+X3 18 # airmass of filter 3 observation
+m3 19 # filter 3 instrumental magnitude
+error(m3) 20 # error in filter 3 instrumental magnitude
+
+
+transformation
+
+fit u1 = 0.0, u2=0.68, u3=0.060
+UFIT: m3 = u1 + V + BV + UB + u2 * X3 + u3 * UB
+
+fit b1 = 0.0, b2=0.30, b3=0.010
+BFIT: m2 = b1 + V + BV + b2 * X2 + b3 * BV
+
+fit v1 = 0.0, v2=0.15, v3=0.000
+VFIT: m3 = v1 + V + v2 * X3 + v3 * BV
+.fi
+
+.ih
+EXAMPLES
+
+1. Type in from scratch a new configuration file to reduce some UBV
+photoelectric photometry. The catalog and observations file are simple
+text files written with the user's own data acquisition software, whose
+format is known by the user.
+
+.nf
+ ph> mkconfig ubv.cfg
+
+ ... answer "STDIN" in response to the query for the catalog
+ parameter, and enter the standard star catalog format
+ description as prompted
+
+ ... a sample input session is shown below, note that in this
+ examine <EOF> is implemented as ^Z
+
+ ENTER THE STANDARD STAR CATALOG FORMAT DESCRIPTION
+
+ Enter column definition (name number, ?=help, <EOF>=quit entry): V 2
+ Enter column definition (name number, ?=help, <EOF>=quit entry): BV 3
+ Enter column definition (name number, ?=help, <EOF>=quit entry): UB 4
+ Enter column definition (name number, ?=help, <EOF>=quit entry): ^Z
+
+ ... answer "STDIN" in response to the query for the
+ observations parameter, and enter the observations file
+ format description as prompted
+
+ ... a sample input session is shown below, note that in this
+ example <EOF> is implemented as ^Z
+
+ ENTER THE OBSERVATIONS FILE FORMAT DESCRIPTION
+
+ Enter column definition (name number, ?=help, <EOF>=quit entry): v 2
+ Enter column definition (name number, ?=help, <EOF>=quit entry): b 3
+ Enter column definition (name number, ?=help, <EOF>=quit entry): u 4
+ Enter column definition (name number, ?=help, <EOF>=quit entry): X 5
+ Enter column definition (name number, ?=help, <EOF>=quit entry): ^Z
+
+ ... answer "STDIN" in response to the query for the
+ transform parameter, and enter the transformation
+ equations as prompted
+
+ ... a sample input session is shown below for a single equation is
+ shown below, note that in this example <EOF> is implemented as
+ ^Z
+
+ ENTER THE TRANSFORMATION EQUATIONS
+
+ Enter the label and functional form for EQUATION 1
+
+ Enter label (e.g. VFIT) (label, ?=help, <EOF>=quit entry): VFIT
+ Enter equation (equation, equation\=continue, ?=help, <EOF>=quit entry):
+ V = v + v1 + v2 * X + v3 * (b - v)
+
+ Enter initial values for the parameters to be fit in EQUATION 1
+
+ Enter parameter 1 (name value, ?=help, <EOF>=quit entry):v1 25.
+ Enter parameter 2 (name value, ?=help, <EOF>=quit entry):v2 -.15
+ Enter parameter 3 (name value, ?=help, <EOF>=quit entry):v3 1.06
+ Enter parameter 4 (name value, ?=help, <EOF>=quit entry):^Z
+
+ Enter initial values for the parameters to be held constant in
+ EQUATION 1
+
+ Enter parameter1 and value (name value, ?=help, <EOF>=quit entry):^Z
+
+ Enter the label and functional form for EQUATION 2
+
+ Enter label (e.g. VFIT) (label, ?=help, <EOF>=quit entry): BFIT
+
+ ... after the program enters the editor make any small changes
+ required
+
+ ... examine the final output for errors
+
+ ph> edit ubv.cfg
+
+ ... correct any errors with the editor
+
+ ph> chkconfig ubv.cfg
+
+ ... check the newly edited file for errors
+
+.fi
+
+2. Create a configuration file to reduce some JHK photometry. In this
+example the user has created a JHK standard star catalog called jhkcat
+using the task MKCATALOG, an observations file called jhkobs
+using the task MKNOBSFILE, and has decided to type in the transformation
+equations by hand using the default editor.
+
+.nf
+ ph> mkconfig jhk.cfg jhkcat jhkobs
+
+ ... answer "STDIN" in response to the query for the
+ transform parameter, followed by <EOF>, usually ^Z
+ to terminate prompting for the transformation equations
+
+ ... use the editor to enter the transformation equations
+
+ ... check the result for errors
+
+ ph> edit jhk.cfg
+
+ ... correct errors found in previous run using the editor
+
+ ph> chkconfig jhk.cfg
+
+ ... check the edited file for errors
+.fi
+
+3. Create a new configuration file for reducing some UBVR photometry, using
+the UBVR standards in the landolt UBVRI standard star catalog. The standard
+star observations file "stdobs" was created with the task MKNOBSFILE.
+
+.nf
+ ph> mkconfig ubvr.cfg landolt stdobs landolt
+
+ ... read in the catalog format description for the
+ landolt UBVRI standards catalog
+
+ ... read in the observations file format description
+ created by a previous run of mknobsfile
+
+ ... read in the sample transformation description file for the
+ landolt UBVRI system
+
+ ... use the editor to delete any references to catalog
+ variables that are not going to be used in the
+ transformation equations, and to edit the transformation
+ equations as desired
+
+ ... check the result for errors
+
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+edit,chkconfig,mknobsfile,mkobsfile
+.endhelp
diff --git a/noao/digiphot/photcal/doc/mkimsets.hlp b/noao/digiphot/photcal/doc/mkimsets.hlp
new file mode 100644
index 00000000..1ba9165a
--- /dev/null
+++ b/noao/digiphot/photcal/doc/mkimsets.hlp
@@ -0,0 +1,356 @@
+.help mkimsets Apr94 noao.digiphot.photcal
+.ih
+NAME
+mkimsets -- create an image set file from the observations for input
+to MKNOBSFILE OR OBSFILE
+.ih
+USAGE
+mkimsets imlist idfilters imsets
+.ih
+PARAMETERS
+.ls imlist
+The file(s) containing all the image names and filter ids associated with
+the observations.
+\fIImlist\fR is a list of APPHOT/DAOPHOT databases if \fIinput\fR =
+"photfiles", a list of images if \fIinput\fR = "images", or the name
+of a user text file if \fIinput\fR = "user".
+The default input is a list of APPHOT/DAOPHOT databases.
+.le
+.ls idfilters
+The ids of the filters, separated by whitespace or
+commas, which define a complete observation.
+The order in which the filter ids are listed in the string \fIidfilters\fR
+determines the order in which the image names associated with each observation
+are written in \fIimsets\fR.
+.le
+.ls imsets
+The name of the output image set file which lists each observation of
+each star field, assigns a name
+to each observation, and specifies which images belong to the same
+observation of that star field.
+.le
+.ls imobsparams = ""
+The name of the output image list file containing the image name,
+the filter id,
+and the quantities specified by \fIfields\fR, for each
+unique image referenced in \fIimlist\fR.
+\fIImobsparams\fR includes changes made by the user if \fIedit\fR is
+"yes". If \fIimobsparams\fR is "" the output image list
+is not saved.
+.le
+.ls input = photfiles
+The source of the information used to create the image set file.
+The options are:
+.ls photfiles
+Extract the image list from the APPHOT/DAOPHOT
+databases containing
+the photometry. This option uses the PTOOLS task DUMP to extract
+the image name, the filter id, the exposure time, the airmass, the
+time of observation, and
+other user selected fields \fIfields\fR from the database files.
+.le
+.ls images
+Extract the image list from the headers of the images containing
+the objects measured
+with APPHOT or DAOPHOT. This option uses the IMAGES task HSELECT to extract
+the image name, the filter id \fIfilter\fR, and other user selected
+fields \fIfields\fR from the image headers. Useful additional fields
+might be the image title and the time of the observation.
+.le
+.ls user
+Extract the image list from a user created file which has the
+image name in the first column, the filter id in the column
+\fIfilter\fR, and
+other useful information in the columns specified by \fIfields\fR.
+.le
+.le
+.ls filter
+The filter id keyword.
+\fIFilter\fR is always the APPHOT/DAOPHOT database keyword "IFILTER"
+if \fIinput\fR is "photfiles",
+the image header keyword which defines the filter id if \fIinput\fR is
+"images", or the number of the column
+containing the filter id, if \fIinput\fR is "user".
+.le
+.ls fields = ""
+The list of additional fields, besides the image name and filter id,
+to be extracted from \fIimlist\fR, separated by whitespace or commas.
+If \fIinput\fR is "photfiles" \fIfields\fR is a list of APPHOT/DAOPHOT
+keywords including "itime,xairmass"; if \fIinput\fR is "images"
+\fIfields\fR is a list of image
+header keywords; if \fIinput\fR is "user" \fIfields\fR is a list of the
+column numbers defining the fields to be extracted from the user file.
+\fIFields\fR may include any quantities, for example airmass, image title, or
+the time of the observation, which aid the user in the interactive
+image name grouping process.
+.le
+.ls sort = ""
+Sort the extracted image list in order of the value of the quantity \fIsort\fR.
+\fISort\fR must be one of the fields
+\fI"image"\fR, \fIfilter\fR, or \fIfields\fR if \fIinput\fR
+is "images" or "photfiles", or the column number in the user file of the
+field to be sorted on if \fIinput\fR is "user".
+\fISort\fR is used to reorder the image list
+before entering the editor.
+.le
+.ls edit = yes
+Edit the extracted image name list interactively, checking that the images
+belonging to a single observation are adjacent to one another in the list,
+and that the filter ids are present and match those in \fIidfilters\fR.
+For each observation there must be an image name for every filter
+in \fIidfilters\fR.
+Missing set members must be assigned the image name "INDEF" for undefined
+and the filter id of the missing observation.
+.le
+.ls rename = yes
+Enter new names for each observation of each field interactively.
+If \fIrename\fR is "no", default names
+of the form "OBS1", "OBS2", ..., "OBSN" are assigned. If \fIrename\fR is "yes",
+MKIMSETS prints each image set
+on the terminal and prompts the user for the new name.
+Images sets containing a single standard star observation should be assigned
+the name of the standard star in the standard star catalog.
+.le
+.ls review = yes
+Review and edit \fIimsets\fR to check that the image set names are correct
+and that the images names have been properly grouped into sets.
+.le
+.ih
+DESCRIPTION
+MKIMSETS is a script task which takes as input a list of
+the image names and filter ids, \fIimlist\fR, associated
+with objects whose magnitudes have been measured with APPHOT, DAOPHOT,
+or a user program, and produces the image set file \fIimsets\fR
+required as input by the preprocessor tasks MKNOBSFILE or OBSFILE.
+MKIMSETS is used in conjunction with MKNOBSFILE OR OBSFILE to combine many
+individual digital photometry measurements, for example standard star
+measurements,
+into a single observations file. The source of the input image list is
+a list of IRAF images if \fIinput\fR is "images",
+a list of APPHOT or DAOPHOT database files if \fIinput\fR is "photfiles",
+or a user supplied text file if \fIinput\fR is "user".
+
+The output image set file \fIimsets\fR lists each observation of
+each star field, assigns a name supplied by the user
+to each observation, and specifies which images belong to the same
+observation of that star field.
+In the case of image sets which contain a single standard star measurement,
+the image set name should
+match the name of the standard star in the standard star catalog.
+
+The optional output image observing parameters file \fIimobsparams\fR
+lists each unique image in \fIimlist\fR, its
+filter id \fIfilter\fR, and other user specified fields \fIfields\fR.
+\fIImobsparams\fR may be edited by
+the user, and used by the preprocessor tasks MKNOBSFILE or OBSFILE
+to correct erroneous or undefined values of
+filter id, exposure time, airmass and time of observation in the input
+databases. By default \fIimobsparams\fR is not written.
+
+After task initialization, MKIMSETS extracts each unique image name,
+the corresponding filter id stored in column \fIfilter\fR,
+and the corresponding values of the user defined fields \fIfields\fR,
+from the input list \fIimlist\fR, and writes the resulting image list
+in tabular form to a temporary file.
+The temporary image list file contains the image name in column 1,
+the value of \fIfilter\fR in column 2, and the values of
+any additional fields in succeeding columns in the order they were
+specified in \fIfields\fR.
+
+If \fIsort\fR is one of the extracted
+fields "image", \fIfilter\fR, or \fIfields\fR, MKIMSETS sorts the image
+list based on the values of \fIsort\fR, before writing the results to the
+the temporary image list file.
+
+If \fIedit\fR is "yes", the user enters the text editor and edits the
+temporary image list interactively.
+The image list must be arranged so that members of each image set are
+adjacent to each other in the image list.
+Missing images may be represented by
+an INDEF in column 1, the appropriate filter id in column 2, and
+INDEF in any other columns.
+The edit step is necessary if the image names are not in any logical
+order in \fIimlist\fR for \fIinput\fR = "images",
+do not occur in any logical order in the APPHOT/DAOPHOT
+databases for \fIinput\fR = "photfiles", or are not listed logically
+in \fIimlist\fR for \fIinput\fR = "user".
+At this point MKIMSETS saves the temporary image list in the text file
+\fIimobsparams\fR, if \fIimobsparams\fR is defined.
+
+After the initial edit, MKIMSETS groups the images in the temporary image list,
+by using the filter ids in \fIidfilters\fR, and assuming that the image
+names are in logical order.
+If \fIrename\fR is "yes", MKIMSETS prompts the user for the name of each
+image set. Otherwise the default names OBS1, OBS2, ..., OBSN are
+assigned.
+If \fIreview\fR is "yes", MKIMSETS enters the editor, permitting the user
+to review \fIimsets\fR and interactively
+correct any mistakes.
+Image sets are written to \fIimsets\fR, 1 set
+per line with the image set name in column 1, a colon in column 2,
+followed by, in filter order and separated by whitespace, the names of the
+images of that field, for that observation.
+
+.ih
+EXAMPLES
+
+1. Create an image set file from a list of APPHOT databases which
+contain UBV observations of 5 standard stars. The UBV filters are
+identified in the APPHOT databases by the filters ids "1","2", "3"
+respectively. There is one database file
+for each star measured. Since data for each of the stars was taken
+sequentially and the images were read sequentially off tape, the user
+requests MKIMSETS to sort the extracted data by image name. Note that
+the time of observation field was undefined in the input data sets.
+
+.nf
+ ph> mkimsets *.mag.* "1,2,3" jan10.stdim sort="image"
+
+ ... MKIMSETS constructs the image list and sorts on
+ the image name
+
+ ... MKIMSETS enters the editor and lists the first few
+ lines of the intermediate image list file
+
+ im001 1 3.0 1.150 INDEF
+ im002 2 2.0 1.150 INDEF
+ im003 3 2.0 1.140 INDEF
+ im004 1 6.0 1.300 INDEF
+ im005 2 4.0 1.300 INDEF
+ im006 3 2.0 1.300 INDEF
+ im007 1 5.0 1.263 INDEF
+ im008 3 1.0 1.270 INDEF
+ im009 2 3.0 1.270 INDEF
+ im010 1 2.0 1.030 INDEF
+ im011 3 10.0 1.030 INDEF
+ im012 1 30.0 1.093 INDEF
+ im013 2 20.0 1.110 INDEF
+ im014 3 10.0 1.110 INDEF
+
+ ... the user notices that standard 4 is missing a B
+ observation and that the observations of standard 3
+ are out of order and edits the file as follows
+
+ im001 1 3.0 1.150 INDEF
+ im002 2 2.0 1.150 INDEF
+ im003 3 2.0 1.140 INDEF
+ im004 1 6.0 1.300 INDEF
+ im005 2 4.0 1.300 INDEF
+ im006 3 2.0 1.300 INDEF
+ im007 1 5.0 1.263 INDEF
+ im009 2 3.0 1.270 INDEF
+ im008 3 1.0 1.270 INDEF
+ im010 1 2.0 1.030 INDEF
+ INDEF 2 INDEF INDEF INDEF
+ im011 3 10.0 1.030 INDEF
+ im012 1 30.0 1.093 INDEF
+ im013 2 20.0 1.110 INDEF
+ im014 3 10.0 1.110 INDEF
+
+ ... the user quits the editor
+
+ ... MKIMSETS groups the image list prompting for a
+ name for each image set
+
+ ... MKIMSETS enters the editor, displays the first few
+ lines of the imsets file, and allows the user to
+ correct any mistakes
+
+ STD1 : im001 im002 im003
+ STD2 : im004 im005 im006
+ STD3 : im007 im009 im008
+ STD4 : im010 INDEF im011
+ STD5 : im012 im013 im014
+
+ ... quit the editor
+.fi
+
+
+2. Create the image set file from the list of IRAF images associated with
+the APPHOT databases in example 1. The images contain the image
+header keyword "f1pos" which specifies the filter id and which may assume
+the values "1,2,3" where "1,2,3" stand for "U,B,V".
+Since the data for the individual stars was taken sequentially the user
+requests MKIMSETS to print out value of the sidereal time stored in the
+image header keyword "ST", and to sort on that
+parameter. The image title is also printed out as an image grouping
+aid to the user. It is placed last in the fields parameter because any
+internal blanks in the title would otherwise confuse the sorting routine.
+
+.nf
+ ph> mkimsets *.imh "1,2,3" jan10.stdim input="images" \
+ filter="f1pos" fields="ST,i_title" sort="ST"
+
+ ... MKIMSETS constructs the image list and sorts on
+ the column containing the sidereal time
+
+ ... MKIMSETS enters the editor and lists the first
+ few lines of the temporary image list file, the sidereal
+ time is in column 3 and the image title containing
+ some blanks is in column 4
+
+ im001 1 12:30:50.2 STD1 U filter
+ im002 2 12:35:40.1 STD1 B
+ im003 3 12:40:16.2 STD1 v filter
+ im004 1 12:50:50.2 STD2
+ im005 2 12:55:40.1 STD2 B
+ im006 3 12:59:58.2 STD2 V
+ im007 1 13:10:50.2 STD3 U
+ im008 3 13:15:40.1 STD3 V
+ im009 2 13:20:16.2 STD3 B
+ im010 1 13:30:50.2 STD4 u
+ im011 3 13:40:40.1 STD4 V
+ im012 1 13:50:50.2 STD5 U
+ im013 2 13:55:40.1 STD5 B
+ im014 3 13:59:58.2 STD5 V
+
+ ... the user notices that standard 4 is missing a B
+ observation and that the observations of standard 3
+ are out of order and edits the file as follows
+
+ im001 1 12:30:50.2 STD1 U filter
+ im002 2 12:35:40.1 STD1 B
+ im003 3 12:40:16.2 STD1 v filter
+ im004 1 12:50:50.2 STD2
+ im005 2 12:55:40.1 STD2 B
+ im006 3 12:59:58.2 STD2 V
+ im007 1 13:10:50.2 STD3 U
+ im009 2 13:20:16.2 STD3 B
+ im008 3 13:15:40.1 STD3 V
+ im010 1 13:30:50.2 STD4 u
+ INDEF 2 INDEF INDEF
+ im011 3 13:40:40.1 STD4 V
+ im012 1 13:50:50.2 STD5 U
+ im013 2 13:55:40.1 STD5 B
+ im014 3 13:59:58.2 STD5 V
+
+ ... the user quits the editor
+
+ ... MKIMSETS groups the edited image list prompting for a
+ name for each image set
+
+ ... MKIMSETS enters the editor, displays the first few
+ lines of the image set file and permits the
+ user to correct any mistakes
+
+ STD1 : im001 im002 im003
+ STD2 : im004 im005 im006
+ STD3 : im007 im009 im008
+ STD4 : im010 INDEF im011
+ STD5 : im012 im013 im014
+
+ ... quit the editor
+
+ ... note that MKIMSETS did not save the output image list
+
+.fi
+
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+images.hselect,ptools.dump,mknobsfile,mkobsfile
+.endhelp
diff --git a/noao/digiphot/photcal/doc/mknobsfile.hlp b/noao/digiphot/photcal/doc/mknobsfile.hlp
new file mode 100644
index 00000000..cb2497b3
--- /dev/null
+++ b/noao/digiphot/photcal/doc/mknobsfile.hlp
@@ -0,0 +1,516 @@
+.help mknobsfile Apr94 noao.digiphot.photcal
+.ih
+NAME
+mknobsfile -- prepare an observations file from a list of APPHOT/DAOPHOT
+files containing observations of objects in one or more fields
+.ih
+USAGE
+mknobsfile photfiles idfilters imsets observations
+.ih
+PARAMETERS
+.ls photfiles
+The APPHOT or DAOPHOT output database(s) containing the standard
+and/or program object instrumental magnitudes. These databases
+are normally created by the
+APPHOT QPHOT and PHOT tasks or the DAOPHOT PHOT task, but may also
+have been written by the DAOPHOT PEAK, NSTAR or ALLSTAR tasks.
+.le
+.ls idfilters
+The list of filter ids separated by whitespace or
+commas which define a complete observation.
+.le
+.ls imsets
+The input image set file which lists the observations of
+each field, assigns a name to each
+field, and tells MKNOBSFILE which images belong to the same
+observation of that field.
+Only observations corresponding to the images specified in \fIimsets\fR
+will be extracted from \fIphotfiles\fR.
+Observations are listed in \fIimsets\fR, 1 observation
+per line with the field name in column 1, a colon in column 2,
+followed by the names of the
+images of that field which belong to that observation.
+The format of \fIimsets\fR is described in detail below.
+.le
+.ls observations
+The output observation file suitable for input to FITPARAMS or
+EVALFIT/INVERTFIT.
+.le
+.ls wrap = yes
+Format the output observations file for easy reading ? If wrap = yes then
+the observations for each filter are written to a separate line and the
+* character in column 1 is interpreted as a continuation character. Otherwise
+all the observations for a single object are written to a single line
+where the maximum size of a line is SZ_LINE characters.
+.le
+.ls obsparams = ""
+The name of an optional text file containing the correct filter ids,
+exposure times, airmasses, and times of observation for each image whose values are either
+not stored or incorrectly stored in \fIphotfiles\fR.
+The observing parameters for each image are listed in the file
+\fIobsparams\fR, 1 image per line with the image
+name in column 1 and the filter ids, exposure times, airmasses, and times of observation,
+in columns \fIobscolumns\fR.
+The image names must match those in
+\fIimsets\fR. Images which have no
+entries in \fIobsparams\fR are assigned the values stored in \fIphotfiles\fR.
+.le
+.ls obscolumns = "2 3 4 5"
+The list of numbers separated by commas or whitespace specifying which columns
+in the text file \fIobsparams\fR contain the correct filter ids,
+exposure times, airmasses, and times ob observation respectively.
+The number 0 can be used as a place holder in the \fIobscolumns\fR string.
+For example, to correct only the \fIphotfiles\fR airmass
+values, \fIobscolumns\fR should be set to "0 0 column 0", where column is
+the airmass column number.
+The default value of \fIobscolumns\fR corresponds to
+the format of the default \fIobsparams\fR file produced by MKIMSETS.
+.le
+.ls minmagerr = 0.001
+The error that will be assigned to a non-INDEF valued magnitude measurement
+if its recorded magnitude error is less than \fIminmagerr\fR.
+.le
+.ls shifts = ""
+The name of the text file specifying the x and y shifts to be ADDED
+to the x-y positions of all objects in an image before position matching (the
+original x's and y's are retained in the output).
+Shifts are listed for each image, 1 image per line with
+the name of the image in column 1, followed by the x and y shifts
+in columns 2 and 3 respectively. Image names must match those in
+\fIimsets\fR. Images for which
+no shift is supplied are assigned x and y shifts of zero.
+.le
+.ls apercors = ""
+The name of the text file specifying the aperture corrections
+to be ADDED to the extracted magnitudes.
+Aperture corrections are listed for each image, 1 image per line with
+the name of the image in column 1, followed by the aperture correction in
+magnitudes in column 2.
+The image names must match those in
+\fIimsets\fR. Images for which
+no aperture correction is supplied are assigned a default value of 0.0.
+.le
+.ls aperture = 1
+The aperture number
+in \fIphotfiles\fR for which the magnitude is extracted, if the magnitudes
+were measured through more than one aperture.
+By default the magnitude through the first aperture is extracted.
+.le
+.ls tolerance = 5.0
+The tolerance in pixels for matching objects in the same observation,
+but different images. MKNOBSFILE extracts
+the x and y coordinates of each object in each image of a given observation
+from \fIphotfiles\fR, adds the shift for that image in
+\fIshifts\fR to the extracted x-y coordinates,
+and matches the objects to within \fItolerance\fR pixels.
+Missing objects are assigned INDEF entries in \fIobservations\fR.
+If \fItolerance\fR is less
+than or equal to 0 no coordinate matching is done, and objects are
+matched in order of occurrence with missing objects being assigned
+INDEF values.
+.le
+.ls allfilters = no
+Output only objects which are successfully matched in all the filters
+specified by \fIidfilters\fR.
+.le
+.ls verify = no
+Verify any data entered interactively by the user ?
+.le
+.ls verbose = yes
+Print status, warning, and error messages ?
+.le
+
+.ih
+DESCRIPTION
+
+MKNOBSFILE takes a list of APPHOT or DAOPHOT database files \fIphotfiles\fR,
+where each file contains observations of 1 or more objects taken through 1 or
+more filters, and the image set file \fIimsets\fR and prepares an observations
+file \fIobservations\fR.
+MKNOBSFILE is optimized for creating a single observations file from a large
+number of observations of fields containing only a single star, or observations
+of a large number of
+fields containing only a few stars per field. MKNOBSFILE IS NORMALLY THE
+PREPROCESSOR OF CHOICE FOR PREPARING STANDARD STAR OBSERVATIONS FILES.
+
+MKNOBSFILE performs the following functions: 1) extracts the quantities
+image name, x and y position, exposure time, filter id,
+airmass, time of observation, magnitude and error from
+\fIphotfiles\fR, 2) corrects any erroneous or missing values of filter id,
+exposure time, and airmass in \fIphotfiles\fR, 3) associates each
+field with 1 or more sets of images of that
+field taken through different filters 4) matches individual objects within
+a given observation by order of occurrence or x-y position,
+5) assigns a unique name to each object in each field.
+
+The image set file \fIimsets\fR assigns a name to each star field.
+For fields containing only a single standard star this name should match the
+name of the standard star in the standard star catalog. For fields
+containing more than one star, MKNOBSFILE constructs a unique name for
+each object in the field by adding
+a sequence number to the field name in \fIimsets\fR, which if the star
+is a standard star, the user must
+later edit. For example the fourth star in the field "M92" will be assigned
+the name "M92-4" in \fIobservations\fR. If this star is a standard star and
+its true name is "IX-10" in the standard star catalog, then the user
+must change "M92-4" to "IX-10" in \fIobservations\fR. \fIImsets\fR also
+tells MKNOBSFILE which images
+in \fIphotfiles\fR are images of the same region of the sky belonging
+to the same observation.
+The format of \fIimsets\fR is described in detail below.
+If the number of observations is small the user may wish to simply type in
+\fIimsets\fR by hand. If the number of observations is large,
+a separate task MKIMSETS is available to assist users in preparing
+\fIimsets\fR.
+
+Values of the filter ids, exposure times, airmasses, and exposure times
+which are missing or incorrect in \fIphotfiles\fR,
+can be corrected by reading values listed in the columns \fIobscolumns\fR
+in the file \fIobsparams\fR. The format of \fIobsparams\fR is described
+in detail below.
+
+MKNOBSFILE matches the objects in different images within the same observation
+either
+by order of occurrence if \fItolerance\fR is less than or equal to 0.0,
+or by x-y position. Matching by position is done by identifying which objects
+in each of the
+images of a given field and observation set are within \fItolerance\fR
+pixels of each other. The user may supply an optional file of x and y
+shifts \fIshifts\fR to be added to the object positions prior to
+matching. The format of \fIshifts\fR is described in detail below.
+If the parameter \fIallfilters\fR is "yes", only objects which are matched
+in all the filters \fIidfilters\fR are output to \fIobservations\fR.
+
+MNOBSFILE permits the user to supply
+an optional file of aperture corrections \fIapercors\fR containing
+magnitude corrections which are added to the instrumental
+magnitudes in \fIphotfiles\fR.
+The format of \fIapercors\fR is described in detail below.
+
+Each new observations file created by MKNOBSFILE has an associated format
+description file listing the column names and numbers in
+\fIobservations\fR, of the fields extracted
+from \fIphotfiles\fR.
+This file, referenced by its parent observations file name, can be
+used as input to the MKCONFIG task.
+The actual name of the format description file on disk is constructed by
+prepending the observations file name \fIobservations\fR with the
+string "f" and
+appending the string ".dat". For example if a new observations file
+called "nite1stds" is created by MKNOBSFILE, a format description
+file called "fnite1stds.dat" will also be created. Any pre-existing format
+description file of that name, which does not have an associated observations
+file, will be deleted.
+
+THE IMSETS FILE
+
+The \fIimsets\fR file lists the
+observations of each field which are to be extracted from \fIphotfiles\fR,
+assigns a name to each
+field, and informs MKNOBSFILE which images belong to the same
+observation of that field.
+Observations are listed in \fIimsets\fR, 1 observation
+per line with the field name in column 1, a colon in column 2,
+followed by the names of the
+images of that field, for that observation, separated by whitespace.
+Only data for images in \fIimsets\fR which match those in
+\fIphotfiles\fR will be extracted. USERS SHOULD REALIZE THAT IF THE IMAGE
+NAMES IN THE PHOTOMETRY FILES INCLUDE THE EXTENSIONS ".imh" OR ".hhh",
+THEN THE IMAGE NAMES IN IMSETS MUST AS WELL.
+
+The field name is used to generate the object names in \fIobservations\fR.
+If there is only a single measured object in a field, then the
+name of that object in \fIobservations\fR will be the name of the field.
+If the single object is a standard star, the user should edit
+\fIimsets\fR so that the field name is the same as the name of the
+standard star in the standard star catalog.
+If a stellar field contains more than
+one measured object, MKNOBSFILE generates names of the form "field-#"
+where "field" is the field name and "#" is a sequence number.
+For example the fourth star in the field "M92" will be assigned the
+name "M92-4" in \fIobservations\fR. If the star is a standard star,
+the user must edit the object names in \fIobservations\fR
+to match those in the standard star catalog.
+
+Any number of observations may have the same field name. This normally
+occurs, for example, when multiple observations of a single standard
+star or standard star field are made at several airmasses.
+
+If there
+are no filter ids in \fIphotfiles\fR or \fIobsparams\fR then the images in
+each image set are assigned the filter ids in \fIidfilters\fR in order
+of occurrence.
+
+The \fIimsets\fR file for a set of 50 UBV frames of fifteen standard star
+fields, some containing a single star and some containing several stars,
+is listed below. Column 1 contains the name of the standard field.
+Column 2 contains a ':'. The U, B and V
+images for each field are listed in columns 3, 4 and 5 respectively.
+The missing U image for field "STDFIELD7" is represented by the name "INDEF".
+The standard stars in "STDFIELD1" and "STDFIELD2" were observed twice in
+the same night at different airmasses.
+
+.nf
+ STDFIELD1 : nite001 nite002 nite003
+ STDFIELD1 : nite045 nite046 nite047
+ STDFIELD2 : nite004 nite005 nite006
+ STDFIELD2 : nite048 nite049 nite050
+ ...
+ STDFIELD7 : INDEF nite019 nite020
+ ...
+ STDFIELD14 : nite039 nite040 nite041
+ STDFIELD15 : nite042 nite043 nite044
+.fi
+
+THE OBSPARAMS FILE
+
+A sample corrections file \fIobsparams\fR for the previous set of
+UBV standards observations is shown below.
+The filter ids, exposure times, airmasses, and times of observation for all the images were
+correctly read
+from the image headers with the exception of the filter id, exposure time,
+airmass, and time of observation for the first "STDFIELD2" V frame.
+The correct filter id, exposure time, and airmass is supplied
+in \fIobsparams\fR and \fIobscolumns\fR is set to "2 3 4 5"
+
+.nf
+ nite006 3 8 1.256 05:34:03.2
+.fi
+
+Zero can be used as a place holder in \fIobscolumns\fR,
+as in the following example where
+the user only wants to correct the exposure time and the airmass and
+leave the filter id alone. In this case \fIobscolumns\fR is "0 2 3 0"
+and \fIobsparams\fR looks as follows.
+
+.nf
+ nite006 8 1.256
+.fi
+
+Only images listed in \fIimsets\fR can have their observing parameters
+modified by \fIobsparams\fR.
+
+THE SHIFTS FILE
+
+The file \fIshifts\fR lists the shifts for each image, 1 shift per line,
+with the image name in column 1 and the x and y shifts in columns 2 and
+3 respectively.
+The image names in \fIshifts\fR must match those in \fIimsets\fR.
+
+A sample shifts file for the previous set of UBV standards
+observations is shown below. All the standards except for "STD14" are assumed
+to have no significant shifts from filter to filter. The B and V frames
+for "STDFIELD14" are shifted -10 pixels in x and -5 pixels
+in y with respect to the U frame. Therefore +10 and +5 pixels should be
+added to the "STDFIELD14" B and V frame positions respectively before
+position matching.
+
+.nf
+ nite040 10.0 5.0
+ nite041 10.0 5.0
+.fi
+
+An alternate way of listing the same observations would be the following.
+
+.nf
+ nite039 -10.0 -5.0
+.fi
+
+THE APERCORS FILE
+
+The file \fIapercors\fR lists the aperture corrections for each image,
+1 aperture correction per line,
+with the image name in column 1 and the aperture correction in magnitudes
+in column 2 respectively.
+The image names in \fIapercors\fR must match those in \fIimsets\fR.
+
+The \fIapercors\fR file for the previous set of UBV observations is shown
+below.
+The aperture corrections for all the standard stars are assumed to be
+zero except for "STDFIELD14".
+
+.nf
+ nite039 -0.150
+ nite040 -0.100
+ nite041 -0.090
+.fi
+
+.ih
+OUTPUT
+For the previous set of UBV observations the output file
+\fIobservations\fR produced by MKNOBSFILE will look like the following.
+The filter ids for the U,B,V filters are assumed to be 1,2,3.
+Note that the exposure times are assumed to have been normalized either prior
+to executing MKNOBSFILE or by using the contents of the \fIobsparams\fR
+file, and so are not included in \fIobservations\fR.
+
+.nf
+ # FIELD FILTER OTIME AIRMASS X Y MAG MERR
+
+ STDFIELD1-1 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ STDFIELD1-2 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ STDFIELD1-3 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ STDFIELD1-1 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ STDFIELD1-2 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ STDFIELD1-3 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ STDFIELD2-1 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ STDFIELD2-2 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ STDFIELD2-1 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ STDFIELD2-2 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ .............................................................
+ STDFIELD7 INDEF INDEF INDEF INDEF INDEF INDEF INDEF
+ * 2 . . . . . .
+ * 3 . . . . . .
+ .............................................................
+ STDFIELD14 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ STDFIELD15-1 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ STDFIELD15-2 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+.fi
+
+The accompanying format description file has the following form.
+
+.nf
+# Declare the observations file variables
+
+observations
+
+T1 3 # time of observation in filter 1
+X1 4 # airmass in filter 1
+x1 5 # x coordinate in filter 1
+y1 6 # y coordinate in filter 1
+m1 7 # instrumental magnitude in filter 1
+error(m1) 8 # magnitude error in filter 1
+
+T2 10 # time of observation in filter 2
+X2 11 # airmass in filter 2
+x2 12 # x coordinate in filter 2
+y2 13 # y coordinate in filter 2
+m2 14 # instrumental magnitude in filter 2
+error(m2) 15 # magnitude error in filter 2
+
+T3 17 # time of observation in filter 3
+X3 15 # airmass in filter 3
+x3 16 # x coordinate in filter 3
+y3 17 # y coordinate in filter 3
+m3 18 # instrumental magnitude in filter 3
+error(m3) 19 # magnitude error in filter 3
+.fi
+
+.ih
+EXAMPLES
+
+1. Prepare an observations file, from a set of standard star observations
+computed by the APPHOT PHOT
+task, for input to FITPARAMS. There is one PHOT output file per standard star
+per filter and each file contains only a single measurement.
+Therefore position matching is not necessary. The magnitudes have been
+been normalized to unit exposure time by PHOT, and the filter ids
+and airmasses read from the image headers, and written to the PHOT database,
+files are correct.
+
+.nf
+ ph> mkimsets *.mag.* "1,2,3" jun11.stdim
+
+ ... interactively create the image set file
+
+ ph> mknobsfile *.mag.* "1,2,3" jun11.stdim jun11.stobs tol=0.0
+
+ ... create the observations file
+
+.fi
+
+2. Prepare an observations file from a set of standard star observations
+computed by the APPHOT PHOT
+task, for input to FITPARAMS. The three PHOT files contain UBV measurements
+respectively of several bright stars in one of the selected areas.
+The stars in each image
+were detected automatically with the APPHOT DAOFIND task so some measurements
+of bright non-standard stars as well as standard stars are contained in the
+PHOT output files. Position matching is therefore necessary but the x and
+y shifts between frames are less than 5 pixels.
+
+.nf
+ ph> edit sa15.stdim
+
+ ... since the imsets file will only have a single entry type
+ it in by hand, it will contain a single line and look
+ something like the following
+
+ SA15 : obj215 obj216 obj217
+
+ ph> mknobsfile obj*.mag.* "1,2,3" sa15.stdim sa15.stdobs \
+ tolerance=5.0
+
+ ... make the observations file
+
+ ph> edit sa15.stdobs
+
+ ... edit the observations file if necessary so that the names of
+ the standard stars correspond to those in the standard
+ star catalog
+.fi
+
+3. Prepare an observations file from a set of standard star observations
+computed by the APPHOT PHOT task, for input to FITPARAMS.
+The single PHOT output file contains UBV
+measurements of 18 standard stars in the M92 field. No position matching is
+necessary, but the user forgot to define the exposure time keyword parameter
+in PHOT, so the PHOT magnitudes are not normalized for exposure time.
+The airmasses
+and filter ids are correct. Since the images are still on disk the user
+simply runs HSELECT in the images package to produce a list of the correct
+exposure times and then runs MKNOBSFILE.
+
+.nf
+ ph> mkimsets M92.imh.mag.1 "1,2,3" jun11.stdim
+
+ ... interactively create the image set file
+
+ ph> hselect M92*.imh $I,exptime yes > exptimes
+
+ ... create the obsparams file with the correct exposure times
+
+ ph> mknobsfile M92.mag.1 "1,2,3" jun11.stdim jun11.stdobs\
+ obscolumns="0 2 0 0" obsparams="exptimes" tolerance=0.0
+
+ ph> edit jun11.stdobs
+
+ ... edit the observations file if necessary so that the names of
+ the standard stars correspond to those in the standard
+ star catalog
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+mkimsets,mkphotcors,mkobsfile
+.endhelp
diff --git a/noao/digiphot/photcal/doc/mkobsfile.hlp b/noao/digiphot/photcal/doc/mkobsfile.hlp
new file mode 100644
index 00000000..114e789c
--- /dev/null
+++ b/noao/digiphot/photcal/doc/mkobsfile.hlp
@@ -0,0 +1,519 @@
+.help mkobsfile Apr94 noao.digiphot.photcal
+.ih
+NAME
+mkobsfile -- prepare a single observations file from a list of APPHOT/DAOPHOT
+files containing observations of objects in a single field
+.ih
+USAGE
+mkobsfile photfiles idfilters observations
+.ih
+PARAMETERS
+.ls photfiles
+The APPHOT or DAOPHOT output database(s) containing the
+object magnitudes. In the case of MKOBSFILE these databases are
+normally created by the DAOPHOT PEAK, NSTAR or ALLSTAR tasks, but may also
+have been written by the APPHOT QPHOT and PHOT tasks or the DAOPHOT PHOT task.
+.le
+.ls idfilters
+The list of filters separated by whitespace or
+commas which define a complete observation.
+.le
+.ls observations
+The output observations file suitable for input to FITPARAMS or
+EVALFIT/INVERTFIT.
+.le
+.ls wrap = yes
+Format the output observations file for easy reading ? If wrap = yes then
+the observations for each filter are written on a separate line and the
+* character in column 1 is interpreted as a continuation character.
+Otherwise all the data for each object is written to a single line
+where the maximum size of a line is the current value of SZ_LINE.
+.le
+.ls imsets = "STDIN"
+The input/output image set file which lists the observations of each field,
+assigns a name to each field, and tells MKOBSFILE which images belong to the
+same observation of that field.
+Only observations corresponding to the images listed in \fIimsets\fR
+will be extracted from \fIphotfiles\fR.
+If \fIimsets\fR is the
+standard input "STDIN", MKOBSFILE prompts the user for the field name
+and the associated list of images.
+Otherwise the observations are assumed to be listed in
+\fIimsets\fR, 1 observation per line with the field name in column 1,
+a colon in column 2,
+followed by, the names of the
+images of that field belonging to that observation.
+The format of \fIimsets\fR is described in detail below.
+.le
+.ls obsparams = ""
+The name of an optional text file containing the filter ids, exposure times,
+airmasses, and times of observation for each image whose values are
+either not stored or incorrectly stored in \fIphotfiles\fR.
+If \fIobsparams\fR is the standard input "STDIN", MKOBSFILE prompts the user
+for the correct filter id, exposure time, airmass, and time of observation
+for each image in each image set.
+Otherwise the observing parameters for each image are assumed to be
+listed in \fIobsparams\fR, 1 image per line, with the image
+name in column 1 and the filter ids, exposure times, airmasses,
+and times of observation in the columns defined by \fIobscolumns\fR.
+The image names must match those in \fIimsets\fR.
+Images which have no
+entries in \fIobsparams\fR are assigned the values stored in \fIphotfiles\fR.
+.le
+.ls obscolumns = "2 3 4 5"
+The list of numbers separated by commas or whitespace specifying which columns
+in \fIobsparams\fR contain the correct filter ids, exposure times,
+airmasses, and times ob observation respectively.
+The number 0 may be used as a place holder in
+the \fIobscolumns\fR string. For example, to correct only the \fIphotfiles\fR
+airmass values, \fIobscolumns\fR should be set to "0 0 column 0", where
+column is the airmass column number. The default
+value of \fIobscolumns\fR corresponds to the format of the default
+\fIobsparams\fR file produced by MKIMSETS.
+.le
+.ls minmagerr = 0.001
+The error that will be assigned to a non-INDEF valued magnitude measurement
+if the recorded error is less than \fIminmagerr\fR.
+.le
+.ls shifts = "STDIN"
+The name of the text file specifying the x-y shifts to be added
+to the x-y positions of all objects in an image before position matching (the
+original x's and y's are retained in the output).
+If \fIshifts\fR is the standard input "STDIN", MKOBSFILE prompts the
+user for the correct x and y shift for each image in each image set.
+Otherwise the shifts are assumed to be listed in \fIshifts\fR,
+1 image per line, with
+the name of the image in column 1, followed by the x and y shifts
+in columns 2 and 3 respectively. Image names must match those in \fIimsets\fR.
+Images for which no shift is supplied are assigned x and y shifts of zero.
+.le
+.ls apercors = "STDIN"
+The name of the text file specifying the aperture corrections
+to be added to the extracted magnitudes for each image before writing
+the magnitudes to \fIobservations\fR.
+If \fIapercors\fR is the standard input "STDIN", MKOBSFILE prompts the
+user for the correct aperture correction for each image in each image set.
+Otherwise the aperture corrections are assumed to be listed in \fIapercors\fR,
+1 image per
+line with the name of the image in column 1, followed by the aperture
+correction in magnitudes in column 2.
+The image names must match those in the \fIimsets\fR. Images for which
+no aperture correction is supplied are assigned a default value of 0.0.
+.le
+.ls aperture = 1
+The aperture number
+in \fIphotfiles\fR for which the magnitude is extracted, if the magnitudes
+were measured through more than one aperture.
+By default the magnitude through the first aperture is extracted.
+.le
+.ls tolerance = 5.0
+The tolerance in pixels for matching objects in the same observation,
+but different images. MKOBSFILE extracts
+the x and y coordinates of each object in each image of a given observation
+from \fIphotfiles\fR, adds the shift for that image in
+\fIshifts\fR to the extracted x-y coordinates,
+and matches the objects to within \fItolerance\fR pixels.
+Missing objects are assigned INDEF entries in \fIobservations\fR.
+If \fItolerance\fR is less
+than or equal to 0 no coordinate matching is done, and objects are
+matched in order of occurrence with missing objects being assigned
+INDEF values.
+.le
+.ls allfilters = no
+Output only objects which are successfully matched in all the filters
+specified by \fIidfilters\fR?
+.le
+.ls verify = no
+Verify any data entered interactively by the user ?
+.le
+.ls verbose = yes
+Print status, warning, and error messages ?
+.le
+
+.ih
+DESCRIPTION
+
+MKOBSFILE takes a list of APPHOT or DAOPHOT database files \fIphotfiles\fR,
+each containing observations of one or more objects in one or more fields
+and prepares an observation file \fIobservations\fR.
+By default MKOBSFILE prompts the user for the 1) name of each observation
+of each star field (\fIimsets\fR), 2) the names of the images belonging to
+each observation of each starfield (\fIimsets\fR) , 3) shifts for each
+image in each observation (\fIshifts\fR), and 4) aperture corrections for
+each image in each observation (\fIapercors\fR). MKOBSFILE is optimized
+for creating a single observations
+file containing observations of many stars in a single star field.
+MKOBSFILE IS THE
+PREPROCESSOR OF CHOICE FOR PREPARING MULTI-OBJECT SINGLE FIELD OBSERVATIONS
+OF A CROWDED STAR FIELD.
+
+MKOBSFILE performs
+the following functions: 1) extracts the quantities
+image name, x and y position, exposure time, filter id,
+airmass, time of observation, magnitude and magnitude
+error from \fIphotfiles\fR,
+2) corrects erroneous or missing values of the filter id, exposure time,
+airmass, and time of observation in \fIphotfiles\fR, 3) associates each
+field with one or more sets of images of that field taken through
+different filters,
+4) matches individual objects within a given image set by order of occurrence
+or x-y position
+and, 5) assigns a unique name to each object in each field.
+
+The image set file \fIimsets\fR assigns a name to each field.
+For fields containing only a single standard star this name should match
+the name of the standard star in the standard star catalog.
+For fields containing more than one star, MKOBSFILE constructs a unique
+name for each object in the field by adding a sequence number to the field
+name in \fIimsets\fR, which if the star is a standard star the user
+must later edit. For example the fourth star in the field "M92" will
+be assigned the name "M92-4" in \fIobservations\fR. If this star is a
+standard star and its true name is "IX-10" in the standard star catalog,
+then the user must change "M92-4" to "IX-10" in \fIobservations\fR.
+\fIImsets\fR also tells MKOBSFILE which images in \fIphotfiles\fR are
+images of the same region of the sky belonging to the same observation.
+By default MKOBSFILE defines the image set file interactively
+by prompting the user for input.
+If the number of observations is small the user should leave \fIimsets\fR
+set to "STDIN" and enter the image sets as prompted. If the number of
+observations is large the user should consider using MKIMSETS and
+MKNOBSFILE to create their observations file.
+The format of \fIimsets\fR is described in detail below.
+
+Values of the filter ids , exposure times, airmasses, and times of
+observation which are missing or incorrect in \fIphotfiles\fR,
+can be corrected by reading the correct values from the columns
+\fIobscolumns\fR in the file
+\fIobsparams\fR. The format of \fIobsparams\fR is described in detail below.
+If \fIobsparams\fR is the standard input "STDIN" then MKOBSFILE will
+prompt the user for the filter ids, exposure times, airmasses, and times of
+observation for each image in each image set.
+
+MKOBSFILE matches the objects in different images within the same observation
+either
+by order of occurrence if \fItolerance\fR is less than or equal to 0.0,
+or by x-y position. Matching by position is done by identifying which objects
+in each of the
+images of a given field and observation set are within \fItolerance\fR
+pixels of each other. The user may supply an optional file of x and y
+shifts \fIshifts\fR to be added to the object positions prior to
+matching. The format of \fIshifts\fR is described in detail below.
+If the parameter \fIallfilters\fR is "yes", only objects which are matched
+in all the filters \fIidfilters\fR are output.
+If \fIshifts\fR is the standard input "STDIN" then MKOBSFILE will prompt
+the user for the x and y shifts for each image in each image set.
+
+MKOBSFILE permits the user to supply
+an optional file of aperture corrections \fIapercors\fR containing
+the magnitude corrections to be added to the instrumental
+magnitudes in \fIphotfiles\fR.
+The format of \fIapercors\fR is described in detail below.
+If \fIapercors\fR is the standard input "STDIN", then MKOBSFILE will
+prompt the user for the aperture correction for each image in each
+image set.
+
+Each new observations file created by MKNOBSFILE has an associated format
+description file listing the column names and numbers in \fIobservations\fR,
+of the fields extracted from \fIphotfiles\fR. This file, referenced by its
+parent observations file name, can be used as input to the MKCONFIG task.
+The actual name of the format description file on disk is constructed
+by prepending the observations file name \fIobservations\fR with the string
+"f" and appending the string ".dat". For example if a new observations
+file called "m92long" is created by MKOBSFILE, a format description file
+called "fm92long.dat" will also be created. Any pre-existing format
+description file of that name, which does not have an associated observations
+file, will be deleted.
+
+THE IMSETS FILE
+
+The \fIimsets\fR file lists the observations of
+each field which are to be extracted from \fIphotfiles\fR,
+assigns a name to each
+field, and informs MKOBSFILE which images belong to the same
+observation of that field.
+Observations are listed in \fIimsets\fR, 1 observation
+per line with the field name in column 1, a colon in column 2,
+followed by the names of the
+images of that field for that observation separated by whitespace.
+
+The field name is used to generate the object names in \fIobservations\fR.
+If there is only a single measured object in a field, then the name of that
+object in \fIobservations\fR will be the name of the field. If the single
+object is a standard star, the user should edit \fIimsets\fR so that the
+field name is the same as the name of the standard star in the standard star
+catalog. If a stellar field contains more than one measured object,
+MKOBSFILE generates names of the form "field-#" where "field" is the field
+name and "#" is a sequence number. For example the fourth star in the
+field "M92" is assigned the name "M92-4" in \fIobservations\fR. If the star
+is a standard star, the user must edit the object names in \fIobservations\fR
+to match those in the standard star catalog.
+
+Any number of observations may have the same field name. This normally
+occurs, for example, when multiple observations of s single standard
+star or standard star field are made at several airmasses.
+
+If there
+are no filter ids in \fIphotfiles\fR or \fIobsparams\fR then the images in
+each image set are assigned the filter ids in \fIidfilters\fR in order
+of occurrence, or user input if \fIimsets\fR is "STDIN".
+
+The \fIimsets\fR file for a set of 9 UBV frames of the globular cluster
+M92 is listed below. The U, B and V
+images for a set of long, medium and short exposure image sets of M92 are
+listed in columns 2, 3 and 4 respectively.
+
+.nf
+ M92L : m92ul m92bl m92vl
+ M92M : m92um m92bm m92vm
+ M92S : m92us m92bs m92vs
+.fi
+
+THE OBSPARAMS FILE
+
+The file \fIobsparams\fR lists the correct filter ids, exposure times,
+airmasses, and times of observation for each image,
+1 image per line, with the image name in column 1, and the remaining
+quantities in the columns specified by \fIobscolumns\fR.
+The images names must correspond to those in \fIimsets\fR.
+
+A sample corrections file \fIobsparams\fR for the previous set of
+UBV M92 observations is shown below.
+The filter ids, exposure times, airmasses, and times of observation
+for all the images were correctly read into \fIphotfiles\fR
+from the image headers with the exception of the filter id, exposure time,
+airmass, and time of observation for the V frame of "M92M".
+The correct filter id, exposure time, airmass, and time of observation
+is supplied in \fIobsparams\fR with \fIobscolumns\fR set to "2 3 4 5"
+as follows.
+
+.nf
+ m92vm 3 300 1.256 03:14:20.4
+.fi
+
+Zero can be used as a place holder in \fIobscolumns\fR as in the
+following example where
+the user wants to correct only the exposure time and the airmass but
+leave the filter id and time of observation alone. In this
+case \fIobscolumns\fR is set to "0 2 3 0" and \fIobsparams\fR looks as follows.
+
+.nf
+ m92vm 300 1.256
+.fi
+
+THE SHIFTS FILE
+
+The file \fIshifts\fR lists the shifts for each image, 1 shift per line,
+with the image name in column 1 and the x and y shifts in columns 2 and
+3 respectively.
+The image names in \fIshifts\fR must match those in \fIimsets\fR.
+
+A sample shifts file for the previous set of UBV M92
+observations is listed below. The U observations are used as the position
+reference and so are assigned x-y shifts of 0.
+The long and middle exposure B and V frames have small but significant
+shifts with
+respect to the U frames and so are included in the shifts file.
+The short exposure images are not significantly shifted with respect to
+one another and so are not included in the shifts file.
+
+.nf
+ m92ul 0.0 0.0
+ m92bl -5.2 -2.9
+ m92vl -10.0 -5.6
+ m92um 0.0 0.0
+ m92bm 4.0 -1.1
+ m92vm 6.3 -2.7
+.fi
+
+THE APERCORS FILE
+
+The file \fIapercors\fR lists the aperture corrections for each image,
+1 aperture correction per line,
+with the image name in column 1 and the aperture correction in magnitudes
+in column 2 respectively.
+The image names in \fIapercors\fR must match those in
+\fIimsets\fR.
+
+A sample \fIapercors\fR file for the previous set of UBV observations is shown
+below.
+
+.nf
+ m92ul -0.15
+ m92bl -0.09
+ m92vl -0.05
+ m92um -0.14
+ m92bm -0.10
+ m92vm -0.06
+ m92us -0.16
+ m92bs -0.10
+ m92vs -0.04
+.fi
+
+.ih
+OUTPUT
+The output observations file has the following format. Note that
+the exposure times are assumed to have been normalized either prior
+to executing MKOBSFILE or by using the contents of the \fIobsparams\fR
+file, and so are not included in \fIobservations\fR.
+
+.nf
+ # FIELD FILTER OTIME AIRMASS X Y MAG MERR
+
+ M92L-1 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ M92L-2 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ .
+ .
+ .
+ M92L-N 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ .......................................................
+ M92M-1 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ M92M-2 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ .
+ .
+ .
+ M92M-N 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ ........................................................
+ M92S-1 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ M92S-2 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ .
+ .
+ .
+ M92S-N 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ ........................................................
+.fi
+
+The accompanying format description file has the following
+format.
+
+.nf
+# Declare the observations file variables
+
+observations
+
+T1 3 # the time of observation in filter 1
+X1 4 # airmass in filter 1
+x1 5 # x coordinate in filter 1
+y1 6 # y coordinate in filter 1
+m1 7 # instrumental magnitude in filter 1
+error(m1) 8 # magnitude error in filter 1
+
+T2 10 # the time of observation in filter 2
+X2 11 # airmass in filter 2
+x2 12 # x coordinate in filter 2
+y2 13 # y coordinate in filter 2
+m2 14 # instrumental magnitude in filter 2
+error(m2) 15 # magnitude error in filter 2
+
+T3 17 # time of observation in filter 3
+X3 18 # airmass in filter 3
+x3 19 # x coordinate in filter 3
+y3 20 # y coordinate in filter 3
+m3 21 # instrumental magnitude in filter 3
+error(m3) 22 # magnitude error in filter 3
+.fi
+
+.ih
+EXAMPLES
+
+1. Prepare an observations file from a set of observations of an open cluster
+computed by the DAOPHOT ALLSTAR task.
+There is one ALLSTAR output file per filter, with each file
+containing observations of several hundred cluster stars.
+Position matching is required. The magnitudes have already been normalized to
+unit exposure time by the earlier PHOT step, and the filter ids and airmasses
+read from the image headers and written to the ALLSTAR files are correct.
+
+.nf
+ ph> assemble the following information
+
+ ... the name of the image associated with each allstar file
+
+ ... the appropriate x-y shifts for each image
+
+ ... the aperture corrections for each image
+
+ ph> mkobsfile ocl*.als.* "1,2,3" ocl.obs tol=4.0
+
+ ... for each complete observation mkobsfile prompts for the
+ field name and the associated image names (in this case
+ 3 since there are 3 filters in idfilters) taken through
+ each filter
+ ... the end-of-file character <EOF> typed in response to the
+ query for the next image set name terminates image set
+ set entry
+
+ ... next mkobsfile prompts for an x and y shift for each
+ image in each image set
+ ... the end-of-file character <EOF> typed in response to the
+ query for the next image x-y shift terminates image shift
+ entry
+
+ ... next mkobsfile prompts for an aperture correction for each
+ image in each image set
+ ... the end-of-file character <EOF> typed in response to the
+ query for the next image aperture correction terminates
+ aperture correction entry
+.fi
+
+2. Prepare an observations file from a set of globular cluster standard star
+observations computed with the DAOPHOT PHOT task. The three PHOT output
+files contain UBV measurements for the all the standard stars
+in the globular cluster field plus a few extraneous objects.
+Position matching is required, but since the filter to filter shifts are
+small no x-y offsets are required for position matching.
+Since these objects are standard stars, aperture corrections are not
+required. The user forgot to define the filter id, exposure time,
+airmass, and time of observation image header keyword parameters
+inside DAOPHOT, so the magnitudes are not normalized for exposure time,
+and the airmasses, filter ids, and times of observation are incorrect.
+
+.nf
+ ph> assemble the following information
+
+ ... the name of the image associated with each phot file
+
+ ... the filter id, exposure time, and airmass of each image
+
+ ph> mkobsfile gcl*.mag.* "1,2,3" gcl.obs obsparams="STDIN"\
+ obcolumns="2 3 4 5" shifts="" apercors="" tolerance=5.0
+
+ ... mkobsfile prompts the user for a field name and an image
+ name corresponding to each filter as above
+ ... the end-of-file character <EOF> typed in response to the
+ query for the next image set name terminates image set
+ set entry
+
+ ... mkobsfile prompts the user for the correct filter id,
+ exposure time, airmass, and time of observation for each
+ image in each image set
+ ... the end-of-file character <EOF> typed in response to the
+ query for the next set of corrections terminates image
+ corrections entry
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+mkimsets,mkphotcors,mknobsfile
+.endhelp
diff --git a/noao/digiphot/photcal/doc/mkphotcors.hlp b/noao/digiphot/photcal/doc/mkphotcors.hlp
new file mode 100644
index 00000000..1ee3506a
--- /dev/null
+++ b/noao/digiphot/photcal/doc/mkphotcors.hlp
@@ -0,0 +1,274 @@
+.help mkphotcors Apr94 noao.digiphot.photcal
+.ih
+NAME
+mkphotcors -- type in and/or check the observing parameters, shifts
+or aperture corrections files for a given image set file.
+.ih
+USAGE
+mkphotcors imsets idfilters obsparams shifts apercors
+.ih
+PARAMETERS
+.ls imsets
+The name of the input/output text file of observations, where a complete
+observation consists of an observation name usually the name of
+the observed star field,
+followed by a list of images of that star field taken through the filters
+\fIidfilters\fR.
+If \fIimsets\fR does not exist, MKPHOTCORS prompts the user for
+input and writes the results to a new image set file \fIimsets\fR.
+If \fIimsets\fR does exist, MKPHOTCORS reads the file and prints messages
+about any errors or inconsistencies it finds in it. If \fIimsets\fR is "",
+MKPHOTCORS prompts the user for input, but does not create a new \fIimsets\fR
+file.
+.le
+.ls idfilters
+The list of filters separated by whitespace or commas which define a complete
+observation. If \fIimsets\fR is entered interactively by the user,
+\fIidfilters\fR defines the number of images in an
+observation. If \fIimsets\fR is an existing file, MKPHOTCORS uses
+the number of filters specified by \fIidfilters\fR to
+check that there are the correct number of images in each observation.
+.le
+.ls obsparams
+The name of the input/output text file containing the quantities filter id,
+exposure time, airmass, and time of observation, for each image in \fIimsets\fR.
+If \fIobsparams\fR does not exist, MKPHOTCORS prompts the user for input
+and writes the results to the new observing parameters file \fIobsparams\fR.
+If \fIobsparams\fR already exists, MKPHOTCORS reads the file using the format
+specified by \fIobscolumns\fR, and prints out messages about any
+errors and inconsistencies it finds.
+If \fIobsparams\fR
+is "", the user is not prompted for input and no output file is created.
+.le
+.ls shifts
+The name of the input/output text file containing the x-y shifts to be applied
+to the measured x-y coordinates of each object in each image in \fIimsets\fR.
+If \fIshifts\fR does not exist, MKPHOTCORS prompts the user for input
+and writes the results to the new shifts file \fIshifts\fR.
+If \fIshifts\fR already exists, MKPHOTCORS reads the file and prints out
+messages about any errors and inconsistencies it finds.
+If \fIshifts\fR is "", the user is not prompted for input and no output
+file is created.
+.le
+.ls apercors
+The name of the input/output text file containing the aperture corrections
+to be applied
+to the measured magnitudes of each object in each image in \fIimsets\fR.
+If \fIapercors\fR does not exist, MKPHOTCORS prompts the user for input
+and writes the results to the new aperture corrections file \fIapercors\fR.
+If \fIapercors\fR already exists, MKPHOTCORS reads the file and prints out
+messages about any errors and inconsistencies it finds.
+If \fIapercors\fR is "", the user is not prompted for input and no output
+file is created.
+.le
+.ls obscolumns = "2 3 4 5"
+The list of numbers separated by commas or whitespace specifying which
+columns in \fIobsparams\fR contain the filter ids, exposure times,
+airmasses, and times of observation, respectively of the images listed in column 1.
+\fIObscolumns\fR is only used if \fIobsparams\fR already exists on disk.
+The number 0 may be used as a place holder in the \fIobscolumns\fR string.
+For example to read in only the airmass values, \fIobscolumns\fR should be
+set to "0 0 column" if the airmass values are in column.
+.le
+.ls verify = no
+Verify all data entered interactively ?
+.le
+.ls verbose = yes
+Print messages about actions taken by MKPHOTCORS, and any warning or error
+messages generated.
+.le
+
+.ih
+DESCRIPTION
+MKPHOTCORS takes an image set file \fIimsets\fR and a list of filter ids
+\fIidfilters\fR and writes one or more of the photometric corrections files
+\fIobsparams\fR, \fIshifts\fR and \fIapercors\fR required by the
+preprocessor tasks MKNOBSFILE and MKOBSFILE. MKPHOTCORS is intended as
+a simple tool to assist the user in creating and/or checking the input
+required by the MKNOBSFILE and MKOBSFILE tasks.
+
+\fIImsets\fR is the name of the input/output text file which tells
+MKNOBSFILE or MKOBSFILE which
+observations are to be extracted from the photometry files.
+A complete observation consists of the observation name,
+for example "M92", followed by a list of images
+taken through the filters \fIidfilters\fR, for example "m92u m92b m92v".
+Observations are listed in \fIimsets\fR, 1 observation per line, with the
+observation name in column 1, a colon in column 2, followed by, in filter
+order and separated by whitespace, the names of the images belonging
+to that observation. A sample image set file is shown in the next section.
+
+\fIImsets\fR may be an existing file created with the MKIMSETS task, a file
+typed in by hand by the user, or a new file to be created by MKPHOTCORS.
+If \fIimsets\fR already exists, MKPHOTCORS reads the file and prints warning
+messages if it cannot decode the observations specification, or if the
+number of images in the observation does not match the number specified
+by \fIidfilters\fR. If imsets does not exist, MKPHOTCORS prompts the user
+for input using \fIidfilters\fR to determine the number of images
+there should be in each observation, and writes the results to the new
+image set file \fIimsets\fR. If \fIimsets\fR is "", MKPHOTCORS prompts
+the user for input but does not save the results.
+
+\fIObsparams\fR is the name of the input/output text file listing the
+observing parameters filter id, exposure time, airmass, and time of observation,
+for the images in
+\fIimsets\fR. \fIObsparams\fR is used to correct missing or incorrect
+filter ids, exposure times, airmasses, and times of observation in the photometry files, and
+is not required if all these values are correctly recorded in the photometry
+files. The observing parameters for each image are listed in
+\fIobsparams\fR, 1 image per line, with the image name in column 1, and the
+filter id, exposure time, airmass, and time of observation in the columns \fIobscolumns\fR.
+A sample observing parameters file is shown in the next section.
+
+\fIObsparams\fR may be an existing file created with the MKIMSETS task,
+a file typed in by hand by the user, or a new file to be created by
+MKPHOTCORS. If \fIobsparams\fR already exists, MKPHOTCORS reads the file
+and prints warning messages if it cannot decode the observing parameters,
+or if the there is an entry which does not correspond to one of the images
+listed in \fIimsets\fR. If \fIobsparams\fR does not exist, MKPHOTCORS
+prompts the user for input for each image in \fIimsets\fR and
+writes the results to a new observing parameters file \fIobsparams\fR.
+If \fIobsparams\fR is "", MKPHOTCORS does not prompt for input and no new
+file is written.
+
+\fIShifts\fR is the name of the text file specifying the x-y shifts, as
+a function of image, to be
+added to the x-y positions of all objects in the images listed in \fIimsets\fR.
+These shifts are
+used to brings frames of the same star field taken through different
+filters into rough alignment before matching individual objects.
+\fIShifts\fR is not required if the frame to frame shifts are
+small, as is usually the case if the filters are of comparable thickness,
+and the exposures are short or well-guided. The x-y shifts are listed 1
+per line with the name of the image in column 1, and the x and y shifts in
+columns 2 and 3 respectively.
+A sample shifts file is shown in the next section.
+
+\fIShifts\fR may be an existing file created with the IMCENTROID task and
+edited by the user,
+a file typed in by hand by the user, or a new file to be created by
+MKPHOTCORS. If \fIshifts\fR already exists, MKPHOTCORS reads the file
+and prints warning messages if it cannot decode the shifts,
+or if the there is an entry which does not correspond to one of the images
+listed in \fIimsets\fR. If \fIshifts\fR does not exist, MKPHOTCORS
+prompts the user for input for each of the images in \fIimsets\fR and
+writes the results to a new shifts file \fIshifts\fR.
+If \fIshifts\fR is "", MKPHOTCORS does not prompt for input and no new
+file is written.
+
+\fIApercors\fR is the name of the text file specifying the aperture
+corrections, as a function of image, to be added to the magnitudes of all
+objects in the images listed in \fIimsets\fR.
+The aperture corrections are most often used to correct the instrumental
+magnitudes of stars
+measured through a small aperture to minimize crowding affects, to the
+instrumental magnitudes of standard stars measured through a larger
+aperture. These aperture corrections will normally be a function of filter
+and of seeing and focus which can change throughout the night.
+Aperture corrections are normally not required for standard star measurements.
+Aperture corrections are listed 1 per line with
+the name of the image in column 1, and the aperture correction in column 2.
+A sample aperture corrections file is shown in the next section.
+
+\fIApercors\fR may be an existing file
+typed in by hand by the user, or a new file to be created by
+MKPHOTCORS. If \fIapercors\fR already exists, MKPHOTCORS reads the file
+and prints warning messages if it cannot decode the aperture corrections,
+or if the there is an entry which does not correspond to one of the images
+listed in \fIimsets\fR. If \fIapercors\fR does not exist, MKPHOTCORS
+prompts the user for input for each of the images in \fIimsets\fR and
+writes the results to a aperture corrections file \fIapercors\fR.
+If \fIapercors\fR is "", MKPHOTCORS does not prompt for input and no new
+file is written.
+
+.ih
+OUTPUT
+
+A sample image set file for a set of UBV 100 second, 600 seconds, and
+1800 second exposure images of the globular cluster m92 is shown below.
+The labels "M92S", "M92M", and "M92L" stand for the 100, 600, 1800 second
+exposure observations sets respectively. The names which follow the labels are
+the names of the actual IRAF images comprising each data set. The image names
+must match those in the photometry files.
+
+.nf
+ M92S : m92us m92bs m92vs
+ M92M : m92um m92bm m92vm
+ M92L : m92ul m92bl m92vl
+.fi
+
+A sample observing parameters file is shown for the above data set. In this
+example the user forgot to tell the photometry code to pick up the filter ids,
+exposure times, airmasses, and times of observation from the image headers and
+so is obliged to
+correct them after the fact via the observing parameters file. The filters
+U B V are represented by the numbers 1 2 3.
+
+.nf
+ m92us 1 100 1.10 03:10:53
+ m92bs 2 100 1.09 03:14:06
+ m92vs 3 100 1.06 03:18:54
+ m92um 1 600 1.03 04:15:05
+ m92bm 2 600 1.03 04:29:43
+ m92vm 3 600 1.03 04:44:56
+ m92ul 1 1800 1.06 06:10:33
+ m92bl 2 1800 1.12 06:45:32
+ m92vl 3 1800 1.18 07:23:02
+.fi
+
+A sample shifts file for the above data set is shown below.
+Only the long exposure frames have significant frame to frame shifts
+so only those images are included in the shifts file.
+The long u frame is used a position reference so its x-y shift is zero.
+
+.nf
+ m92ul 0.0 0.0
+ m92bl 5.4 8.4
+ m92vl 9.6 17.1
+.fi
+
+A sample aperture corrections file for the above data set is shown below.
+Note that the aperture correction appears to vary in a systematic
+way with filter.
+
+.nf
+ m92us -.153
+ m92bs -.110
+ m92vs -.083
+ m92um -.149
+ m92bm -.108
+ m92vm -.090
+ m92ul -.160
+ m92bl -.123
+ m92vl -.079
+.fi
+
+.ih
+EXAMPLES
+
+1. Type in the image set file and accompanying shifts and aperture corrections
+files for a set of UBV observations of a crowded field in NGC4147. The filter
+ids "1 2 3" stand
+for "U B V". The photometry programs picked up the correct values of
+the filter id, exposure time, and airmass from the image headers
+and wrote them to the photometry
+files so the observing parameters file is not required.
+
+.nf
+ ph> mkphotcors n4147.imsets "1,2,3" "" n4147.shifts n4147.apcors
+.fi
+
+2. Type in the shifts and aperture corrections files for the already
+existing image set file m17.imsets. In this case the filter set is "J H K".
+
+.nf
+ ph> mkphotcors m17.imsets "J,H,K" "" m17.shifts m17.apcors
+.fi
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+mkimsets,mknobsfile,mkobsfile
+.endhelp
diff --git a/noao/digiphot/photcal/doc/obsfile.hlp b/noao/digiphot/photcal/doc/obsfile.hlp
new file mode 100644
index 00000000..a0e5b480
--- /dev/null
+++ b/noao/digiphot/photcal/doc/obsfile.hlp
@@ -0,0 +1,511 @@
+.help obsfile Apr94 noao.digiphot.photcal
+.ih
+NAME
+obsfile -- prepare an observations file from a list of user created
+photometry files containing observations of objects in one or more fields
+.ih
+USAGE
+obsfile photfiles incolumns idfilters imsets observations
+.ih
+PARAMETERS
+.ls photfiles
+A list of text files containing the image names or an image id, x-y positions,
+magnitudes, magnitude errors, airmasses, filter ids, exposure times, and time
+of observation of all the measured objects. \fIPhotfiles\fR are assumed to be
+the output of the user's own digital photometry program. All the files in the
+list must have the format specified by \fIincolumns\fR.
+.le
+.ls incolumns
+A list of ten numbers separated by commas or whitespace specifying which
+columns in \fIphotfiles\fR contain the following fields: the image name or id,
+x coordinate, y coordinate, filter id, exposure time, airmass, time of
+observation, instrumental magnitude, magnitude error, and object id
+respectively.
+.le
+.ls idfilters
+The list of filter ids separated by whitespace or commas which define a
+complete observation. The filter ids must correspond to those in
+\fIphotfiles\fR.
+.le
+.ls imsets
+The name of the text file which lists the observations of each field, assigns a
+name to each field, and tells OBSFILE which images belong to the same
+observation of that field. Only observations corresponding to the images
+specified in \fIimsets\fR will be extracted from \fIphotfiles\fR. Observations
+are listed in \fIimsets\fR, 1 observation per line with the field name in
+column 1, a colon in column 2, followed by, in filter order and separated by
+whitespace, the names of the images of that field belonging to that
+observation. The format of \fIimsets\fR is described in detail below.
+.le
+.ls observations
+The output observations file suitable for input to FITPARAMS or
+EVALFIT/INVERTFIT.
+.le
+.ls wrap = yes
+Format the output observations file for easy reading ? If wrap = yes then the
+observation in each filter are written on a separate line and the * character
+in column 1 is interpreted as a continuation character. Otherwise all the
+observations for a single filter are written on a single line where the maximum
+length of a line is SZ_LINE characters.
+.le
+.ls obsparams = ""
+The name of an optional text file containing the correct filter ids, exposure
+times, airmasses, and time of observations for each image whose values are
+either undefined or incorrectly stored in \fIphotfiles\fR. The observing
+parameters for each image are listed in the file \fIobsparams\fR, 1 image per
+line with the image name in column 1 and the filter ids, exposure times,
+airmasses, and times of observation listed in columns \fIobscolumns\fR. The
+image names must match those in \fIimsets\fR. Images which have no entries in
+\fIobsparams\fR are assigned the values stored in \fIphotfiles\fR.
+.le
+.ls obscolumns = "2 3 4 5"
+The list of numbers separated by commas or whitespace specifying which columns
+in the text file \fIobsparams\fR contain the correct filter ids, exposure
+times, airmasses, and times of observation respectively. The number 0 can be
+used as a place holder in the \fIobscolumns\fR string. For example, to correct
+only the \fIphotfiles\fR airmass values, \fIobscolumns\fR should be set to
+"0 0 column 0", where column is the airmass column number. The default value of
+\fIobscolumns\fR corresponds to the format of the default \fIobsparams\fR file
+produced by MKIMSETS.
+.le
+.ls minmagerr = 0.001
+The error that will be assigned to a non-INDEF valued magnitude measurement
+whose recorded error is less than \fIminmagerr\fR.
+.le
+.ls shifts = ""
+The name of the text file specifying the x and y shifts to be ADDED to the x-y
+positions of all objects in an image before position matching (the original x's
+and y's are retained in the output). Shifts are listed for each image, 1 image
+per line with the name of the image in column 1, followed by the x and y shifts
+in columns 2 and 3 respectively. Image names must match those in \fIimsets\fR.
+Images for which no shift is supplied are assigned x and y shifts of zero.
+.le
+.ls apercors = ""
+The name of the text file specifying the aperture corrections to be ADDED to
+the extracted magnitudes. Aperture corrections are listed for each image, 1
+image per line with the name of the image in column 1, followed by the aperture
+correction in magnitudes in column 2. The image names must match those in
+\fIimsets\fR. Images for which no aperture correction is supplied are assigned
+a default value of zero.
+.le
+.ls normtime = no
+Normalize the magnitudes to an exposure time of one time unit using the
+exposure times in \fIphotfiles\fR.
+.le
+.ls tolerance = 5.0
+The tolerance in pixels for matching objects in the same observation, but
+different images. OBSFILE extracts the x and y coordinates of each object
+in each image of a given observation from \fIphotfiles\fR, adds the shift for
+that image in \fIshifts\fR to the extracted x-y coordinates, and matches the
+objects to within \fItolerance\fR pixels. Missing objects are assigned INDEF
+entries in \fIobservations\fR. If \fItolerance\fR is less than or equal to 0
+no coordinate matching is done, and objects are matched in order of occurrence
+with missing objects being assigned INDEF values.
+.le
+.ls allfilters = no
+Output only objects which are successfully matched in all the filters specified
+by \fIidfilters\fR?
+.le
+.ls verify = no
+Verify interactive user input? This option is used only if any of \fIimsets\fR,
+\fIobsparams\fR, \fIshifts\fR, or \fI apercors\fR are set to the standard input
+"STDIN".
+.le
+.ls verbose = yes
+Print messages about actions taken by the task or any warnings or errors
+encountered?
+.le
+
+.ih
+DESCRIPTION
+
+OBSFILE takes a list of user generated text files \fIphotfiles\fR, where each
+file contains observations of one or more objects taken through one or more
+filters, and the image set file \fIimsets\fR, and prepares a single
+observations file \fIobservations\fR. OBSFILE is intended for use with any
+user digital stellar photometry program which writes its output in simple text
+files format.
+
+OBSFILE performs the following functions: 1) extracts the quantities
+image name or image id, x and y position, filter id, exposure time, airmass,
+time of observation, magnitude, and magnitude error from
+\fIphotfiles\fR, 2) corrects any erroneous or missing values of filter id,
+exposure time, airmass, or time of observation in \fIphotfiles\fR, 3) associates each
+field with one or more sets of images of that
+field taken through different filters 4) matches individual objects within
+a given observation by order of occurrence or x-y position, and
+5) assigns a unique name to each object in each field.
+
+The parameter \fIincolumns\fR describes the format of \fIphotfiles\fR.
+\fIIncolumns\fR is a list of ten numbers separated by commas or whitespace
+which specify the columns containing the following fields: the
+image name or id,
+the x coordinate, the y coordinate, the filter id, the exposure time,
+the airmass, the time of observation the instrumental magnitude, the
+magnitude error, and the object id.
+For example
+if \fIincolumns\fR is "10 2 3 6 8 7 9 4 5 1", the object id is assumed to
+be in column 1, the image id in column 10, the x and y positions in columns 2 and 3, the filter id,
+exposure time, airmass, and time of observation in columns 6, 8, 7 and 9,
+and the instrumental
+magnitude and magnitude error in columns 4 and 5. The image names must
+match those in \fIimsets\fR or the corresponding input data is skipped.
+The columns image name, x coordinate, y coordinate, and magnitude
+are mandatory and must be present in \fIphotfiles\fR.
+Other missing columns in the data may be represented by a "0" in the
+appropriate place in \fIincolumns\fR.
+For example, if there is no magnitude error
+column in \fIphotfiles\fR a value of INDEF will be written in the appropriate
+column in \fIobservations\fR.
+If there is no airmass column in \fIphotfiles\fR the value in
+\fIobspararms\fR if any, or the value INDEF will be written to the appropriate
+column in \fIobservations\fR.
+If there is no filter id column in \fIphotfiles\fR the value in
+\fIobspararms\fR if any, or one of the values in \fIidfilters\fR
+will be written to the appropriate column in \fIobservations\fR.
+If there is no exposure time column in \fIphotfiles\fR the value in
+\fIobspararms\fR if any, or a value of one will be assumed.
+If there is no time of observation time column in \fIphotfiles\fR the value in
+\fIobspararms\fR if any, or a value of INDEF will be assumed.
+
+The image set file \fIimsets\fR assigns a name to each field.
+For fields containing only a single standard star this name should
+match the name of the standard star in the standard star catalog.
+For fields containing more than one star, OBSFILE constructs a unique
+name for each object in the field by adding a sequence number to the
+field name in \fIimsets\fR, which if the star is a standard star, the
+user must later edit. For example the fourth star in the field "M92"
+will be assigned the name "M92-4" in \fIobservations\fR.
+If this star is a standard star and its true name is "IX-10" in the
+standard star catalog, then the user must change "M92-4" to "IX-10"
+in \fIobservations\fR.
+\fIImsets\fR also tells OBSFILE which images
+in \fIphotfiles\fR are images of the same region of the sky belonging
+to the same observation.
+The format of \fIimsets\fR is described in detail below.
+If the number of observations is small the user may wish to simply type
+in \fIimsets\fR by hand. If the number of observations is large, a
+separate task MKIMSETS is available to assist users in preparing
+\fIimsets\fR.
+
+Values of the filter ids, exposure times, airmasses, and times of observation,
+which are undefined or incorrect in \fIphotfiles\fR,
+can be corrected by reading values listed in the columns \fIobscolumns\fR
+in the file \fIobsparams\fR. The format of \fIobsparams\fR is described
+in detail below.
+
+OBSFILE matches the objects in different images within the same observation
+either
+by order of occurrence if \fItolerance\fR is less than or equal to 0.0,
+or by x-y position. Matching by position is done by identifying which objects
+in each of the
+images of a given field and observation set are within \fItolerance\fR
+pixels of each other. The user may supply an optional file of x and y
+shifts \fIshifts\fR to be added to the object positions prior to
+matching. The format of \fIshifts\fR is described in detail below.
+If the parameter \fIallfilters\fR is "yes", only objects which are matched
+in all the filters \fIidfilters\fR are output to \fIobservations\fR.
+
+OBSFILE permits the user to supply
+an optional file of aperture corrections \fIapercors\fR containing
+magnitude corrections which are added to the instrumental
+magnitudes in \fIphotfiles\fR.
+The format of \fIapercors\fR is described in detail below.
+
+Each new observations file created by OBSFILE has an associated format
+description file listing the column names and numbers in \fIobservations\fR,
+of the fields extracted from \fIphotfiles\fR. This file, referenced
+by its parent observations file name, can be used as input to the
+MKCONFIG task. The actual name of the format description file on disk is
+constructed by prepending the string "f" and appending the string ".dat"
+to \fIobservations\fR.
+For example if a new observations file called "nite1" is created by
+OBSFILE, a format description file called "fnite1.dat" will also be
+created. Any pre-existing format description file of that name, which does
+not have an associated observations file, will be deleted.
+
+
+THE IMSETS FILE
+
+The \fIimsets\fR file lists the
+the observations of each field, assigns a name to each
+field, and informs OBSFILE which images belong to the same
+observation of that field.
+Observations are listed in \fIimsets\fR, 1 observation
+per line with the field name in column 1, a colon in column 2,
+followed by the names of the
+images of that field for that observation separated by whitespace.
+Only data for image names in \fIimsets\fR which match those in
+\fIphotfiles\fR will be extracted.
+
+The field name is used to generate the output object name in \fIobservations\fR.
+If there is only a single measured object in the field, then the name
+of that object in \fIobservations\fR will be the name of the field. If
+the single object is a standard star, the user should edit \fIimsets\fR
+so that the field name is the same as the name of the standard star in
+the standard star catalog. If a stellar field contains more than one
+measured object, OBSFILE generates names of the form "field-#" where
+"field" is the field name and "#" is a sequence number. For example the
+fourth star in the field "M92" will be assigned the name "M92-4" in
+\fIobservations\fR. If the star is a standard star, the user must edit
+the object names in \fIobservations\fR to match those in the standard
+star catalog.
+
+Any number of observations may have the same field name. This normally occurs,
+for example, when multiple observations of a single standard star of
+standard star field are made at several airmasses.
+
+If there
+are no filter ids in \fIphotfiles\fR or \fIobsparams\fR then the images in
+each image set are assigned the filter ids in \fIidfilters\fR in order
+of occurrence.
+
+The \fIimsets\fR file for a set of 50 UBV frames of fifteen standard star
+fields is listed below. There is only a single bright star per field.
+The name of star field in column 1 has been edited to be identical
+to the name of the standard in the standard star catalog. Column 2 contains
+a ':'. The U, B and V
+images for each field are listed in columns 3, 4 and 5 respectively.
+The missing U image for field "STD7" is represented by the name "INDEF".
+Standard stars "STD1" and "STD2" were observed twice in the same night
+at different airmasses.
+
+.nf
+ STD1 : nite001 nite002 nite003
+ STD1 : nite045 nite046 nite047
+ STD2 : nite004 nite005 nite006
+ STD2 : nite048 nite049 nite050
+ ...
+ STD7 : INDEF nite019 nite020
+ ...
+ STD14 : nite039 nite040 nite041
+ STD15 : nite042 nite043 nite044
+.fi
+
+THE OBSPARAMS FILE
+
+A sample corrections file \fIobsparams\fR for the previous set of
+UBV standards observations is shown below.
+The filter ids, exposure times, airmasses, and times of observation for all the images were
+correctly read
+from the image headers with the exception of the filter id, exposure time,
+and airmass for the first "STD2" V frame.
+The correct filter id, exposure time, airmass, and time of observation, is supplied
+in \fIobsparams\fR and \fIobscolumns\fR is set to "2 3 4 5"
+
+.nf
+ nite006 3 8 1.256 14:30:02.3
+.fi
+
+Zero can be used as a place holder in \fIobscolumns\fR,
+as in the following example where
+the user only wants to correct the exposure time and the airmass and
+leave the filter id alone. In this case \fIobscolumns\fR is "0 2 3 0"
+and \fIobsparams\fR looks as follows.
+
+.nf
+ nite006 8 1.256
+.fi
+
+Only images listed in \fIimsets\fR can have their observing parameters
+modified by \fIobsparams\fR.
+
+THE SHIFTS FILE
+
+The file \fIshifts\fR lists the shifts for each image, 1 shift per line,
+with the image name in column 1 and the x and y shifts in columns 2 and
+3 respectively.
+The image names in \fIshifts\fR must match those in \fIimsets\fR.
+
+A sample shifts file for the previous set of UBV standards
+observations is shown below. All the standards except for "STD14" are assumed
+to have no significant shifts from filter to filter. The B and V frames
+for "STD14" are shifted -10 pixels in x and -5 pixels
+in y with respect to the U frame. Therefore +10 and +5 pixels should be
+added to the "STD14" B and V frame positions respectively before
+position matching.
+
+.nf
+ nite040 10.0 5.0
+ nite041 10.0 5.0
+.fi
+
+An alternate way of listing the same observations would be the following.
+
+.nf
+ nite039 -10.0 -5.0
+.fi
+
+THE APERCORS FILE
+
+The file \fIapercors\fR lists the aperture corrections for each image,
+1 aperture correction per line,
+with the image name in column 1 and the aperture correction in magnitudes
+in column 2 respectively.
+The image names in \fIapercors\fR must match those in \fIimsets\fR.
+
+The \fIapercors\fR file for the previous set of UBV observations is shown
+below.
+The aperture corrections for all the standard stars are assumed to be
+zero except for "STD14".
+
+.nf
+ nite039 -0.150
+ nite040 -0.100
+ nite041 -0.090
+.fi
+
+.ih
+OUTPUT
+For the previous set of UBV observations the output file
+\fIobservations\fR produced by OBSFILE will look like the following.
+The filter ids for the U,B,V filters are assumed to be 1,2,3.
+Note that the exposure times are assumed to have been normalized either
+prior to running OBSFILE or by OBSFILE itself,
+and so are not included in \fIobservations\fR.
+
+.nf
+ # FIELD FILTER OTIME AIRMASS X Y MAG MERR
+
+ STD1 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ STD1 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ STD2 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ STD2 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ ........................................................
+ STD7 INDEF INDEF INDEF INDEF INDEF INDEF INDEF
+ * 2 . . . . . .
+ * 3 . . . . . .
+ .......................................................
+ STD14 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+ STD15 1 . . . . . .
+ * 2 . . . . . .
+ * 3 . . . . . .
+.fi
+
+The accompanying format description file has the following form.
+
+.nf
+# Declare the observations file variables
+
+observations
+
+X1 3 # airmass in filter 1
+T1 4 # time of observation in filter 1
+x1 5 # x coordinate in filter 1
+y1 6 # y coordinate in filter 1
+m1 7 # instrumental magnitude in filter 1
+error(m1) 8 # magnitude error in filter 1
+
+X2 10 # airmass in filter 2
+T2 11 # time of observation in filter 2
+x2 12 # x coordinate in filter 2
+y2 13 # y coordinate in filter 2
+m2 14 # instrumental magnitude in filter 2
+error(m2) 15 # magnitude error in filter 2
+
+X3 16 # airmass in filter 3
+T3 17 # time of observation in filter 3
+x3 18 # x coordinate in filter 3
+y3 19 # y coordinate in filter 3
+m3 20 # instrumental magnitude in filter 3
+error(m3) 21 # magnitude error in filter 3
+.fi
+
+.ih
+EXAMPLES
+
+1. Prepare an observations file, from a set of standard star observations
+in a file output by the user's own digital stellar photometry program,
+for input to FITPARAMS. A sample of the file illustrating the format
+is shown below.
+Since there is only one star per field, position matching is not necessary.
+The magnitudes have already been normalized to unit exposure time by the
+user's program, and the filter ids and airmasses are correct. However the
+observing time column is missing and represented by a zero in the incolumns
+parameters.
+
+.nf
+ ph> head magsfile
+
+ ... print out the first few lines of the photometry file
+
+ std1u 40.4 50.3 18.059 0.043 U 1.030 1.0
+ std1b 42.5 53.1 17.089 0.023 B 1.032 1.0
+ std1v 43.8 56.9 16.023 0.020 V 1.034 1.0
+ std2u 39.4 55.3 17.029 0.040 U 1.135 1.0
+ std2b 41.5 57.3 15.905 0.020 B 1.140 1.0
+ std2v 42.6 58.9 14.899 0.018 V 1.144 1.0
+ ..... .... .... ...... ..... . ..... ...
+ ..... .... .... ...... ..... . ..... ...
+
+ ph> type fields
+
+ ... print out the corresponding image set file
+
+ std1 : std1u std1b std1v
+ std2 : std2u std2b std2v
+ ..... ..... ..... .....
+ ..... ..... ..... .....
+
+ ph> obsfile magsfile "1 2 3 6 8 7 0 4 5" "U,B,V" fields standards.obs\
+ tol=0.0
+
+ ... create the observations file
+
+ ph> edit standards.obs
+
+ ... edit the observations file so that the object names
+ match those in the standard star catalog
+.fi
+
+2. Prepare an observations file from a set of program star observations
+of a crowded field in the globular cluster M92 computed by the same
+digital photometry
+program as above, for input to FITPARAMS. The 3 input files contain UBV
+measurements of over 2000 stars in the M92 field. Since the same stars
+were not measured in all filters position matching is necessary.
+
+.nf
+ ph> head m92umags,m92bmags,m92vmags
+
+ ... print the first few lines of the input files on the
+ standard output
+
+ m92u 80.4 42.3 17.046 0.046 U 1.056 1.0
+ m92u .... .... ...... ..... U 1.056 1.0
+
+ m92b 62.6 81.1 18.071 0.041 B 1.030 1.0
+ m92b .... .... ...... ..... B 1.030 1.0
+
+ m92v 33.8 26.9 16.023 0.022 V 1.034 1.0
+ m92v .... .... ...... ..... V 1.034 1.0
+
+ ph> type fields
+
+ ... print out the image set file
+
+ m92 : m92u m92b m92v
+
+ ph> obsfile m92umags,m92bmags,m92vmags "1 2 3 6 8 7 0 4 5" "U,B,V"\
+ fields standards.obs tolerance=8.0
+
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+mkimsets,mknobsfile,mkobsfile
+.endhelp
diff --git a/noao/digiphot/photcal/doc/pcintro.hlp b/noao/digiphot/photcal/doc/pcintro.hlp
new file mode 100644
index 00000000..8a2287b1
--- /dev/null
+++ b/noao/digiphot/photcal/doc/pcintro.hlp
@@ -0,0 +1,727 @@
+.help pcintro Apr94 noao.digiphot.photcal
+.ih
+I. INTRODUCTION
+
+The photometric calibration package PHOTCAL, contains a set of tasks
+for computing the transformation from the instrumental system to the standard
+photometric system, and applying the computed transformations to
+the observational data.
+
+PHOTCAL distinguishes between two types of objects: \fIstandard stars\fR,
+and \fIprogram stars\fR. Standard stars have known instrumental and standard
+photometric indices. Program stars have known instrumental photometric
+indices, but unknown standard photometric indices.
+
+The standard indices of standard stars are contained in standard star
+catalogs known as \fIcatalog files\fR. Each standard star catalog
+contains only a single entry for a given standard star. The
+instrumental indices of both standard and program stars are
+contained in observations catalogs, known as \fIobservations files\fR.
+There may be any number of observations per star in an observations
+file.
+
+PHOTCAL uses a setup file called the \fIconfiguration file\fR to specify
+the format of the input catalog and observations files and define the
+transformation equations to be fit.
+
+Normally the user must perform the following logical steps to
+complete their photometric calibrations with PHOTCAL. However not all types
+of data require all the following steps.
+
+.ls [1]
+Prepare a standard star catalog file using the MKCATALOG task.
+.le
+.ls [2]
+Prepare a standard star observations file using the MKIMSETS and MKNOBSFILE
+tasks or alternatively the MKOBSFILE task.
+.le
+.ls [3]
+Create the configuration file using the MKCONFIG and CHKCONFIG tasks.
+.le
+.ls [4]
+Fit the transformation equations with the FITPARAMS task.
+.le
+.ls [5]
+Apply the transformations to the standard star observations file using
+the EVALFIT or INVERTFIT tasks.
+.le
+.ls [6]
+Prepare a program star observations file using the MKIMSETS and MKNOBSFILE
+tasks or alternatively the MKOBSFILE tasks.
+.le
+.ls [7]
+Apply the transformations to the program star observations file using the
+EVALFIT or INVERTFIT tasks.
+.le
+
+.ih
+II. THE CATALOG AND OBSERVATIONS FILES FORMAT
+
+PHOTCAL catalog and observation files are simple text files containing any
+number of columns. Columns are delimited by whitespace.
+The first column is always reserved for the star id or
+matching name, and the rest contain actual data such as positions, magnitudes,
+colors, errors, air mass, or any other quantity of interest.
+Comments can be inserted
+as separate lines at any point in the catalog or observations files
+by beginning the comment line with the character "#".
+
+The star id is used to
+match observations with catalog entries, and to determine which objects
+are standard and which are program stars. Star ids may contain any non-blank
+characters,
+but lower case letters are converted to upper case, and
+characters not in the set [A-Z,0-9,+,-,_] are removed before
+star id matching. Catalog files must contain only a single entry per star.
+Observations files may contain multiple entries per star.
+Missing or unknown data values should be set to INDEF not left blank.
+
+Normal catalog and observations files records are restricted in length to
+the maximum size of a text
+file line in IRAF, currently 161 characters including the newline. The maximum
+record length can be extended by replacing the star id in column 1
+with the continuation character "*".
+
+Several preprocessors are provided to convert data coming from other
+IRAF packages, such as APPHOT and DAOPHOT, into a format suitable for PHOTCAL.
+If a preprocessor for a specific type of data does
+not exist, then the user will have to use other IRAF facilities to convert it
+to into the appropriate format, or write their own.
+
+.ih
+III. PREPARE A STANDARD STAR CATALOG FILE
+
+A standard star catalog suitable for input to PHOTCAL may be prepared in
+one of the following ways. The advantages and disadvantages of each
+method are briefly discussed.
+
+.ls [1]
+Use one of the standard star catalogs supported by PHOTCAL and maintained in
+the directory "photcal$catalogs/". Each supported standard star catalog has
+an associated catalog format description file defining the format of the
+standard star catalog. The catalog format description file may be used as
+input to the MKCONFIG task. A list of currently supported standard star
+catalogs and their format files can be found in the file
+"photcal$catalogs/README".
+
+The principal advantage of this option is that no data entry is
+required on the part of the user. The principal disadvantage is that
+PHOTCAL, in preparation for id matching, loads the entire standard
+star catalog into memory, even though the number of observed
+standard stars may have been only a few dozen. For typical standard
+star catalogs containing a few hundred objects this is not a problem,
+but very large standard star catalogs should be avoided.
+.le
+.ls [2]
+Prepare a standard star catalog with the MKCATALOG task. MKCATALOG
+prompts the user for the catalog title, the id column name and width, and the
+names and widths of all the data columns.
+When column definition is complete, MKCATALOG writes the catalog
+definition information into the catalog header and the associated catalog
+format file and prompts for data.
+The catalog format description file created by MKCATALOG may be used
+as input to MKCONFIG.
+Type "help mkcatalog" for the details of task usage.
+
+The principal advantages of using MKCATALOG are that the task always
+produces a PHOTCAL readable catalog and accompanying format description file,
+and that the standard star catalog contains values only for those objects
+that have actually been observed.
+.le
+.ls [3]
+With a text file editor create or edit a standard star catalog which
+conforms to the requirements of PHOTCAL as described in the previous section.
+
+The principal advantage of this option is that the user can take advantage
+of any spread sheet capabilities that his/her favorite editor has. The
+principal disadvantage is that a format description file is not
+automatically created along with the catalog.
+.le
+.ls [4]
+Reformat an existing standard star catalog until it conforms to the
+requirements of photcal as described in the previous section. In some
+case this may require writing a local preprocessor program. PHOTCAL users
+should be aware of the PROTO package tasks JOIN and FIELDS, the LISTS
+package tasks COLUMN, and the UTILITIES package task TRANSLIT.
+.le
+
+The first few lines of a representative catalog file produced by MKCATALOG are
+listed below. V, BV, and UB stand for the V magnitude, B-V color,
+and U-B color respectively. The non-blank lines beginning with '#' at the
+beginning of the file are for the internal use of the MKCATALOG task only,
+and are ignored by other PHOTCAL tasks.
+
+.nf
+# CATALOG: ubv.cat
+# NCOLS: 7
+# HDRLENGTH: 68
+#
+# ID V error(V) BV error(BV) UB error(UB)
+# 8 8 8 8 8 8 8
+
+ 105-307 12.050 0.020 0.690 0.020 0.220 0.020
+ 105-405 8.309 0.004 1.521 0.001 1.905 0.007
+ 105-411 10.620 0.014 0.950 0.010 0.620 0.008
+ 105-256 11.820 0.013 0.610 0.012 0.180 0.022
+.fi
+
+The accompanying format description file produced by MKCATALOG is listed below.
+This file associates a column number with the column name and can be used
+as input to MKCONFIG. The comments opposite
+the column definitions were not produced by MKCATALOG but typed in later.
+
+.nf
+
+# Declare the catalog variables
+
+catalog
+
+V 2 # the V magnitude
+error(V) 3 # the error in the V magnitude
+BV 4 # the B-V color
+error(BV) 5 # the error in the B-V color
+UB 6 # the U-B color
+error(UB) 7 # the error in the U-B color
+
+.fi
+
+.ih
+IV. PREPARE A STANDARD STAR OBSERVATIONS FILE
+
+A standard star observations file suitable for input to PHOTCAL may be
+prepared in one of the following ways. APPHOT and DAOPHOT users should
+use options [1] or [2]. Other users must either enter their data by hand using
+options [3] and [4], or write a local program to prepare their data
+for input to PHOTCAL, option [5].
+
+.ls [1]
+If the standard star magnitudes were computed with APPHOT or DAOPHOT
+and consist of many individual and repeated observations of standard star
+fields, then use MKIMSETS
+followed by MKNOBSFILE to create an observations file. MKIMSETS creates
+an image set definition file, telling MKNOBSFILE which images taken
+in which filters belong to the same observation of a given stellar field.
+For each observations file written, MKNOBSFILE
+creates an associated format description file defining the format of
+the new observations file and suitable for input to
+MKCONFIG. MKNOBSFILE is set up to run automatically once the image set file
+is defined. Type "help mknobsfile" for details.
+.le
+.ls [2]
+If the standard star magnitudes in one or more colors were computed with
+APPHOT or DAOPHOT and all the standard stars are in one stellar field,
+use the MKOBSFILE task to create an observations file.
+For each observations file created, MKOBSFILE
+creates an associated format description file defining the format of
+the new observations file, and suitable for input to
+MKCONFIG. MKOBSFILE prompts the user for all
+the required input. Type "help mkobsfile" for details.
+.le
+.ls [3]
+Prepare a standard star observations file with the MKCATALOG task. MKCATALOG
+prompts the user for the observations file title, the id column name and
+width, and the names and widths of all the data columns.
+When column definition is complete, MKCATALOG writes the observations file
+definition information into the observations file header and the associated
+format description file and prompts for data.
+The format description file created by MKCATALOG may be used as input
+to MKCONFIG if the "catalog" keyword (see the example in the previous
+section) is changed to "observations".
+Type "help mkcatalog" for the details of task usage.
+.le
+.ls [4]
+With the text editor create or edit a standard star observations file
+which conforms to
+the requirements of PHOTCAL as described in the previous section.
+.le
+.ls [5]
+Write a local program to prepare the data for input to PHOTCAL.
+.le
+
+A sample image set file produced by MKIMSETS is shown below. The labels
+STD1, STD2, ..., STD7 stand for standard star fields 1, 2, ..., 7 and
+the c0* labels are the names of images of each field taken through filters
+U, B, and V respectively.
+
+.nf
+ STD1 : c023 c022 c021
+ STD2 : c024 c025 c026
+ STD3 : c029 c028 c027
+ STD4 : c033 c031 c032
+ STD5 : c061 c060 c059
+ STD6 : c064 c063 c062
+ STD7 : c069 c066 c065
+.fi
+
+The first few lines of the observations file produced by
+MKNOBSFILE using the above image set file both before and after the user
+has edited in the correct standard star ids is listed below.
+Note that there is usually more than 1 star in the field. In fact the
+data set above included 17 standard stars and 5 additional stars that
+the automatic star finding algorithm picked up.
+Note also that some known bad data points in the
+original observations file have been replaced with the undefined value
+INDEF.
+
+.nf
+
+before editing
+
+# FIELD FILTER OTIME AIRMASS XCENTER YCENTER MAG MERR
+
+STD1-1 1 INDEF 1.276 156.43 518.23 20.077 0.031
+* 2 INDEF 1.270 155.37 521.12 17.712 0.053
+* 3 INDEF 1.265 152.16 519.62 17.044 0.019
+STD1-2 1 INDEF 1.276 481.39 357.19 18.683 0.009
+* 2 INDEF 1.270 480.57 360.07 14.919 0.005
+* 3 INDEF 1.265 477.07 358.62 13.292 0.002
+STD1-3 1 INDEF 1.276 507.69 128.53 19.144 0.014
+* 2 INDEF 1.270 507.06 131.44 16.612 0.020
+* 3 INDEF 1.265 503.42 130.29 15.587 0.008
+STD2-1 1 INDEF 1.305 719.59 399.17 19.863 0.097
+* 2 INDEF 1.315 718.79 401.30 17.339 0.043
+* 3 INDEF 1.320 715.47 402.55 16.601 0.033
+STD2-2 1 INDEF 1.305 470.72 393.68 16.675 0.005
+* 2 INDEF 1.315 469.71 396.22 14.743 0.004
+* 3 INDEF 1.320 466.58 397.27 14.030 0.004
+STD2-3 1 INDEF 1.305 498.75 204.35 19.413 0.057
+* 2 INDEF 1.315 497.73 206.40 17.469 0.042
+* 3 INDEF 1.320 494.55 207.64 16.662 0.032
+STD2-4 1 INDEF 1.305 182.44 209.60 19.748 0.073
+* 2 INDEF 1.315 181.10 211.95 18.056 0.074
+* 3 INDEF 1.320 178.21 213.03 17.034 0.044
+STD3-1 1 INDEF 1.251 397.57 200.65 19.060 0.007
+* 2 INDEF 1.236 396.58 200.38 15.725 0.005
+* 3 INDEF 1.231 393.53 200.51 14.237 0.007
+
+after editing
+
+# FIELD FILTER OTIME AIRMASS XCENTER YCENTER MAG MERR
+
+STD1-1 1 INDEF 1.276 156.43 518.23 20.077 0.031
+* 2 INDEF 1.270 155.37 521.12 17.712 0.053
+* 3 INDEF 1.265 152.16 519.62 17.044 0.019
+105-405 1 INDEF 1.276 481.39 357.19 18.683 0.009
+* 2 INDEF 1.270 480.57 360.07 14.919 0.005
+* 3 INDEF 1.265 477.07 358.62 13.212 0.002
+105-411 1 INDEF 1.276 507.69 128.53 19.144 0.014
+* 2 INDEF 1.270 507.06 131.44 16.612 0.020
+* 3 INDEF 1.265 503.42 130.29 15.487 0.008
+STD2-1 1 INDEF 1.305 719.59 399.17 19.863 0.097
+* 2 INDEF 1.315 718.79 401.30 17.339 0.043
+* 3 INDEF 1.320 715.47 402.55 16.601 0.033
+105-257 1 INDEF 1.305 470.72 393.68 16.675 0.005
+* 2 INDEF 1.315 469.71 396.22 14.743 0.004
+* 3 INDEF 1.320 466.58 397.27 14.030 0.004
+105-262 1 INDEF 1.305 498.75 204.35 INDEF 0.057
+* 2 INDEF 1.315 497.73 206.40 17.469 0.042
+* 3 INDEF 1.320 494.55 207.64 INDEF 0.032
+STD2-4 1 INDEF 1.305 182.44 209.60 19.748 0.073
+* 2 INDEF 1.315 181.10 211.95 18.056 0.074
+* 3 INDEF 1.320 178.21 213.03 17.034 0.044
+106-575 1 INDEF 1.251 397.57 200.65 19.060 0.007
+* 2 INDEF 1.236 396.58 200.38 15.725 0.005
+* 3 INDEF 1.231 393.53 200.51 14.237 0.007
+.fi
+
+The accompanying format description file produced by MKNOBSFILE
+is listed below. This file associated column numbers with column
+names. The filter numbers 1, 2, 3 were written into the image
+headers by the data taking program, and subsequently picked up by the
+APPHOT package tasks computed the magnitudes. They stand for filters U, B and
+V respectively.
+
+.nf
+# Declare the observations file variables
+
+observations
+
+T1 3 # time of observation in filter 1
+X1 4 # airmass in filter 1
+x1 5 # x coordinate in filter 1
+y1 6 # y coordinate in filter 1
+m1 7 # instrumental magnitude in filter 1
+error(m1) 8 # magnitude error in filter 1
+
+T2 10 # time of observation in filter 2
+X2 11 # airmass in filter 2
+x2 12 # x coordinate in filter 2
+y2 13 # y coordinate in filter 2
+m2 14 # instrumental magnitude in filter 2
+error(m2) 15 # magnitude error in filter 2
+
+T3 17 # time of observation in filter 3
+X3 18 # airmass in filter 3
+x3 19 # x coordinate in filter 3
+y3 20 # y coordinate in filter 3
+m3 21 # instrumental magnitude in filter 3
+error(m3) 22 # magnitude error in filter 3
+.fi
+
+.ih
+V. PREPARE THE CONFIGURATION FILE
+
+The configuration file is a text file, created by the user, that specifies
+both the format of the input data and the form of the transformation equations.
+A detailed description of the grammar and syntax of the configuration file
+can be obtained by typing the following command.
+.nf
+
+ph> help config
+
+.fi
+The configuration file can be prepared in one of the following ways.
+
+.ls [1]
+Run the MKCONFIG task using the output of MKCATALOG or direct terminal input to
+define the catalog file format, the output of the MKNOBSFILE
+or MKOBSFILE tasks or direct terminal input to define the observations file
+format, and one of the standard template transformation section files or
+direct terminal input to define the transformation equations.
+Users are urged to use MKCONFIG if they are new to PHOTCAL,
+if the catalog file is one of the supported catalogs, or if the observations
+file was made with one of the standard preprocessors MKNOBSFILE or
+MKOBSFILE.
+.le
+.ls [2]
+Use the text editor to make small corrections to an existing functioning
+configuration file. This is the recommended method if the transformation
+equations have changed from a previous PHOTCAL reduction session but the
+format of the standard star and observations catalogs has not, or if
+the user has become familiar with the PHOTCAL configuration file format.
+.le
+.ls [3]
+Use the text editor to create a configuration file from scratch.
+.le
+
+The grammar and syntax of the configuration file can be checked with the
+CHKCONFIG task. If an error was found, the program will print the
+line and the word where the error was detected and the user must reedit the
+file until no errors are found.
+
+A sample configuration file is shown below.
+
+.nf
+
+# Declare the catalog file variables
+
+catalog
+
+V 2
+error(V) 3
+BV 4
+error(BV) 5
+UB 6
+error(UB) 7
+
+# Declare the observations file variables
+
+observations
+
+T1 3 # time of observation in filter 1
+X1 4 # airmass in filter 1
+x1 5 # x coordinate in filter 1
+y1 6 # y coordinate in filter 1
+m1 7 # instrumental magnitude in filter 1
+error(m1) 8 # magnitude error in filter 1
+
+T2 10 # time of observation in filter 2
+X2 11 # airmass in filter 2
+x2 12 # x coordinate in filter 2
+y2 13 # y coordinate in filter 2
+m2 14 # instrumental magnitude in filter 2
+error(m2) 15 # magnitude error in filter 2
+
+T3 17 # time of observation in filter 3
+X3 18 # airmass in filter 3
+x3 19 # x coordinate in filter 3
+y3 20 # y coordinate in filter 3
+m3 21 # instrumental magnitude in filter 3
+error(m3) 22 # magnitude error in filter 3
+
+
+transformation
+
+fit u1 = 0.0, u2 = -.07, u3 = 0.70
+UFIT : m1 = V + BV + UB + u1 + u2 * UB + u3 * X1
+
+fit b1 = 0.0, b2 = -.06, b3 = 0.30
+BFIT : m2 = V + BV + b1 + b2 * BV + b3 * X2
+
+fit v1 = 0.0, v2 = 0.05, v3 = 0.20
+VFIT : mv = V + v1 + v2 * BV + v3 * Xv
+.fi
+
+.ih
+VI. FITTING THE PARAMETERS OF THE TRANSFORMATION EQUATIONS
+
+The heart of the PHOTCAL package is the parameter fitting task FITPARAMS.
+A detailed description of this task and its parameters can be obtained by
+typing the following command.
+.nf
+
+ph> help fitparams
+
+.fi
+FITPARAMS takes the observation files, catalog files, and configuration file,
+and computes the value of the fit parameters for each of the
+transformation equations specified in the configuration file. Equations will
+be processed in the same order in which they occur in the configuration file.
+The output of FITPARAMS is a text database file containing one record,
+identified by the transformation equation label, for each equation fit.
+Successive fits are appended to the end of the database file. If more than
+one fit has the same label the last fit performed will be used by the
+evaluation tasks.
+
+Only standard stars with known instrumental magnitudes and photometric
+indices are used to compute the parameters of each transformation
+equation. Standard stars are identified by matching the id in the observations
+catalog against the list of ids in the standard star catalog.
+
+The fitting process can be either interactive or non-interactive. Interactive
+fitting is the default. In interactive mode, the user
+is presented with plots of the data and the fit, can reject points
+automatically using a k-sigma rejection algorithm, delete points interactively
+with the cursor, change which parameters are to be fit and which are to be
+held constant, and so on. A detailed description of
+all the interactive options and colon commands can be obtained by typing
+the following command.
+.nf
+
+ph> help inlfit
+
+.fi
+
+The database file produced by FITPARAMS for the catalog and
+observations files listed in sections III and IV and configuration file
+listed in section V is shown below.
+
+.nf
+# Mon 10:41:04 06-May-91
+begin UFIT
+ status 0 (Solution converged)
+ variance 4.965303E-4
+ stdeviation 0.02228296
+ avsqerror 1.
+ averror 1.
+ avsqscatter 0.
+ avscatter 0.
+ chisqr 4.965303E-4
+ msq 3.901309E-4
+ rms 0.01975173
+ reference mu
+ fitting V+BV+UB+u1+u2*UB+u3*Xu
+ weights uniform
+ parameters 3
+ u1 (fit)
+ u2 (fit)
+ u3 (fit)
+ derivatives 3
+ 0.1
+ 0.1
+ 0.1
+ values 3
+ 6.108767
+ -0.04842735
+ 0.7180178
+ errors 3
+ 0.05704632
+ 0.008730207
+ 0.04209311
+
+# Mon 10:41:14 06-May-91
+begin BFIT
+ status 0 (Solution converged)
+ variance 0.002550806
+ stdeviation 0.0505055
+ avsqerror 1.
+ averror 1.
+ avsqscatter 0.
+ avscatter 0.
+ chisqr 0.002550806
+ msq 0.00207253
+ rms 0.04552504
+ reference mb
+ fitting V+BV+b1+b2*BV+b3*Xb
+ weights uniform
+ parameters 3
+ b1 (fit)
+ b2 (fit)
+ b3 (fit)
+ derivatives 3
+ 0.1
+ 0.1
+ 0.1
+ values 3
+ 4.826268
+ -0.08220235
+ 0.275757
+ errors 3
+ 0.1189408
+ 0.02718129
+ 0.08517767
+
+# Mon 10:41:21 06-May-91
+begin VFIT
+ status 0 (Solution converged)
+ variance 9.547584E-4
+ stdeviation 0.03089917
+ avsqerror 1.
+ averror 1.
+ avsqscatter 0.
+ avscatter 0.
+ chisqr 9.547584E-4
+ msq 7.501673E-4
+ rms 0.02738918
+ reference mv
+ fitting V+v1+v2*BV+v3*Xv
+ weights uniform
+ parameters 3
+ v1 (fit)
+ v2 (fit)
+ v3 (fit)
+ derivatives 3
+ 0.1
+ 0.1
+ 0.1
+ values 3
+ 4.632307
+ 0.02190715
+ 0.1877689
+ errors 3
+ 0.07831987
+ 0.01721398
+ 0.0573602
+.fi
+
+.ih
+VII. APPLYING THE TRANSFORMATIONS TO THE STANDARD STARS
+
+This step is optional since the goodness of fit can be assessed more
+efficiently from within the FITPARAMS task. However in some cases
+the user may want a record of the fitted photometric indices for the
+standard stars and the residuals from the fit.
+
+There are two tasks for evaluating the transformation equations
+and which one the user must select depends on how he/she has
+defined the transformations equations.
+
+If all references to the catalog file variables are on the left-hand side
+of the transformation equations
+and the right-hand side is a function of the observations file
+variables only, then the user should use EVALFIT. The transformation equations
+used for reducing photoelectric photometry are often written in this manner.
+
+If the left-hand side
+of the transformation equation is a function of the observations file
+variables and all references to the catalog files variables are on
+the right-hand side of the transformation equations
+then the user must use INVERTFIT. The transformation equations
+for reducing CCD photometry are usually written in this manner.
+
+The full output of INVERTFIT for the partial catalog and observations
+files listed in section III and IV and the configuration file
+shown in section V are listed below.
+Only observations which were successively matched
+with objects in the standard star catalog files are shown. The fits for
+objects with undefined observational variables could not be successfully
+inverted producing a row of INDEF values.
+
+.nf
+# Tue 15:50:37 14-May-91
+# List of observations files:
+# ubv.std
+# Number of catalog files:
+# ubv.cat
+# Config: ubv.cfg
+# Parameters: ubv.fit
+#
+# Computed indices for standard objects only
+#
+# Columns:
+# 1 object id
+# 2 V
+# 3 error(V)
+# 4 resid(V)
+# 5 BV
+# 6 error(BV)
+# 7 resid(BV)
+# 8 UB
+# 9 error(UB)
+# 10 resid(UB)
+
+
+105-405 8.308 0.002 0.001 1.563 0.006 -0.042 1.878 0.011 0.027
+105-411 10.597 0.008 0.023 0.913 0.024 0.037 0.639 0.027 -0.019
+105-257 9.140 0.004 0.000 0.451 0.006 0.039 0.040 0.007 -0.020
+105-262 INDEF INDEF INDEF INDEF INDEF INDEF INDEF INDEF INDEF
+106-575 9.345 0.007 -0.004 1.322 0.010 -0.014 1.457 0.009 0.026
+106-728 INDEF INDEF INDEF INDEF INDEF INDEF INDEF INDEF INDEF
+107-998 10.399 0.010 0.041 0.602 0.018 0.028 0.217 0.020 -0.057
+107-991 INDEF INDEF INDEF INDEF INDEF INDEF INDEF INDEF INDEF
+107-990 9.555 0.005 0.005 0.455 0.009 0.035 0.047 0.009 -0.047
+114-473 8.514 0.004 0.006 1.005 0.007 0.005 0.832 0.008 -0.032
+114-353 INDEF INDEF INDEF INDEF INDEF INDEF INDEF INDEF INDEF
+114-151 10.708 0.005 -0.048 0.748 0.011 0.002 0.221 0.014 0.069
+114-236 10.446 0.005 0.034 0.687 0.010 -0.057 0.093 0.011 0.007
+111-775 INDEF INDEF INDEF INDEF INDEF INDEF INDEF INDEF INDEF
+111-773 8.980 0.005 -0.017 0.270 0.006 -0.064 -0.258 0.005 0.047
+111-1342 9.263 0.006 -0.043 1.702 0.009 -0.012 1.726 0.076 0.054
+111-733 9.219 0.006 -0.039 0.262 0.007 0.038 0.172 0.007 0.008
+.fi
+
+.ih
+VIII. PREPARE A PROGRAM STAR OBSERVATIONS FILE
+
+A program star observations file is prepared in the identical manner to
+the standard star observations file as described in section IV.
+In fact there is no intrinsic reason why standard star and program
+star observations cannot occupy the same observations file since
+they can be separated later by the EVALFIT and INVERTFIT tasks.
+In the sample observations
+file shown in section IV objects with names like 105-411 are the actual
+standard stars and those with names like STD* can, for the purpose
+of illustration, be regarded as program stars.
+
+.ih
+IX. APPLYING THE TRANSFORMATIONS TO THE PROGRAM STARS
+
+The transformation equations are applied to the program stars in the same
+way they are applied to the standard stars ad described in section VII.
+
+The output of INVERTFIT for the partial catalog and observations
+files listed in section III and IV and the configuration file
+shown in section V are listed below. Only observations
+which were not successfully matched
+with objects in the standard star files are shown.
+Note that the residuals from the fit cannot be computed for program
+objects and are therefore not output.
+
+.nf
+# Tue 16:17:11 14-May-91
+# List of observations files:
+# ubv.obs
+# Number of catalog files:
+# ubv.cat
+# Config: ubv.cfg
+# Parameters: ubv.fit
+#
+# Computed indices for program objects only
+#
+# Columns:
+# 1 object id
+# 2 V
+# 3 error(V)
+# 4 BV
+# 5 error(BV)
+# 6 UB
+# 7 error(UB)
+
+
+STD1-3 12.165 0.019 0.403 0.063 0.508 0.069
+STD2-2 12.136 0.045 0.796 0.096 -0.242 0.115
+STD2-4 11.710 0.034 0.479 0.061 0.660 0.113
+STD6-3 10.589 0.006 0.619 0.016 -0.069 0.022
+STD7-5 11.852 0.059 0.406 0.069 0.981 0.129
+.fi
+.endhelp
diff --git a/noao/digiphot/photcal/evalfit.par b/noao/digiphot/photcal/evalfit.par
new file mode 100644
index 00000000..c158dc44
--- /dev/null
+++ b/noao/digiphot/photcal/evalfit.par
@@ -0,0 +1,13 @@
+# The EVALFIT task parameter file
+
+observations,f,a,"",,,List of observations files
+config,f,a,"",,,Configuration file
+parameters,f,a,"",,,Fitted parameters file
+calib,f,a,"",,,Output calibrated standard indices file
+catalogs,f,h,"",,,List of standard catalog files
+errors,s,h,"obserrors","undefined|obserrors|equations",,"Error computation type (undefined,obserrors,equations)"
+objects,s,h,"all","all|program|standards",,"Objects to be fit (all,program,standards)"
+print,s,h,"",,,Optional list of variables to print
+format,s,h,"",,,Optional output format string
+append,b,h,no,,,Append output to an existing file ?
+catdir,s,h,")_.catdir",,,The standard star catalog directory
diff --git a/noao/digiphot/photcal/evaluate/README b/noao/digiphot/photcal/evaluate/README
new file mode 100644
index 00000000..879dfcee
--- /dev/null
+++ b/noao/digiphot/photcal/evaluate/README
@@ -0,0 +1,3 @@
+This subdirectory contains the code for evaluatin the fit found by FITCOEFFS
+either in the forward sense using the EVALUATE task or in the inverse sense
+using the INVEVAL task.
diff --git a/noao/digiphot/photcal/evaluate/invert.com b/noao/digiphot/photcal/evaluate/invert.com
new file mode 100644
index 00000000..96af60d9
--- /dev/null
+++ b/noao/digiphot/photcal/evaluate/invert.com
@@ -0,0 +1,15 @@
+pointer py # pointer to the reference equation values
+pointer pyfit # pointer to the fit equation values
+pointer pa # pointer to the parameters to be fit
+pointer pdelta # pointer to the parameter increments
+pointer pda # pointer to the temporary parameter increments
+pointer palpha # pointer to the accumulated matrix
+pointer pbeta # pointer to the accumulated right side vector
+pointer pik # pointer to working index array for matrix inversion
+pointer pjk # pointer to working index array for matrix inversion
+
+pointer pyerr # pointer to the error equation values
+pointer pafit # pointer to the temporary fit array
+
+common /invertcom / py, pyfit, pa, pdelta, pda, palpha, pbeta, pik, pjk
+common /invertcom / pyerr, pafit
diff --git a/noao/digiphot/photcal/evaluate/mkpkg b/noao/digiphot/photcal/evaluate/mkpkg
new file mode 100644
index 00000000..667d92e3
--- /dev/null
+++ b/noao/digiphot/photcal/evaluate/mkpkg
@@ -0,0 +1,18 @@
+# The MKPKG file for the INVEVALUATE and PHOTPROC task.
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ t_invertfit.x "../lib/io.h" "../lib/parser.h" <math/nlfit.h> \
+ <error.h> "../lib/preval.h"
+ t_evalfit.x "../lib/io.h" "../lib/parser.h" <math/nlfit.h> \
+ <error.h>
+ phinvert.x <mach.h> "invert.com" "../lib/parser.h"
+ pherrors.x "../lib/parser.h" "invert.com"
+ phprint.x "../lib/parser.h"
+ phcheck.x "../lib/parser.h" "../lib/preval.h"
+ phminv.f
+ ;
diff --git a/noao/digiphot/photcal/evaluate/phcheck.x b/noao/digiphot/photcal/evaluate/phcheck.x
new file mode 100644
index 00000000..2f729930
--- /dev/null
+++ b/noao/digiphot/photcal/evaluate/phcheck.x
@@ -0,0 +1,240 @@
+include "../lib/parser.h"
+include "../lib/preval.h"
+
+# PH_SETEQN -- Determine whether a PHOTCAL expression includes any set
+# equations which contain references to catalog variables. Return a YES
+# or NO status.
+
+int procedure ph_seteqn (code)
+
+pointer code # the photcal equation code
+
+int ip, ins
+pointer setcode
+int pr_geti(), pr_gsym(), ph_cateqn()
+pointer pr_gsymp()
+
+begin
+ # Return NO if there are no defined set equations.
+ if (pr_geti (NSETEQS) <= 0)
+ return (NO)
+
+ # Initialize.
+ ip = 0
+ ins = Memi[code+ip]
+
+ # Loop over the equation parsing instructions.
+ while (ins != PEV_EOC) {
+
+ switch (ins) {
+ case PEV_SETEQ:
+ ip = ip + 1
+ setcode = pr_gsymp (pr_gsym (Memi[code+ip], PTY_SETEQ),
+ PSEQRPNEQ)
+ if (ph_cateqn (setcode) == YES)
+ return (YES)
+ case PEV_NUMBER, PEV_CATVAR, PEV_OBSVAR, PEV_PARAM:
+ ip = ip + 1
+ case PEV_EXTEQ, PEV_TRNEQ:
+ ip = ip + 1
+ default:
+ # do nothing
+ }
+
+ ip = ip + 1
+ ins = Memi[code+ip]
+ }
+
+ return (NO)
+end
+
+
+# PH_CATEQN -- Given a PHOTCAL set equation determine whether there are any
+# references in it to catalog variables. Return a YES or NO status.
+
+int procedure ph_cateqn (code)
+
+pointer code # pointer to the equation code
+
+int ip, ins
+int pr_geti()
+
+begin
+ # Return NO if there are no catalog variables.
+ if (pr_geti (NCATVARS) <= 0)
+ return (NO)
+
+ # Initialize.
+ ip = 0
+ ins = Memi[code+ip]
+
+ # Loop over the equation parsing instructions.
+ while (ins != PEV_EOC) {
+
+ switch (ins) {
+ case PEV_CATVAR:
+ return (YES)
+ case PEV_NUMBER, PEV_OBSVAR, PEV_PARAM:
+ ip = ip + 1
+ case PEV_SETEQ, PEV_EXTEQ, PEV_TRNEQ:
+ ip = ip + 1
+ default:
+ # do nothing
+ }
+
+ ip = ip + 1
+ ins = Memi[code+ip]
+ }
+
+ return (NO)
+end
+
+
+# PH_SETVAR -- Check to see whether the fit expression portion of a PHOTCAL
+# transformation equation contains references to set equations which include
+# previously unreferenced catalog variables. Return the number of previously
+# unreferenced set equations.
+
+int procedure ph_setvar (eqn, sym, cmap, omap, tuservars, uservars, usererrs,
+ nstdvars, nobsvars, eqset, maxnset, userset, nset)
+
+int eqn # the equation number
+pointer sym # pointer to the equation symbol
+pointer cmap # pointer to catalog variable column map
+pointer omap # pointer to observations variable column map
+int tuservars[nstdvars,ARB] # list of active catalog variables per equation
+int uservars[ARB] # list of active catalog variables
+int usererrs[ARB] # list of active observational error columns
+int nstdvars # total number of catalog variables
+int nobsvars # total number of observations variables
+int eqset[maxnset,ARB] # set equation table
+int maxnset # maximum number of set equations
+int userset[ARB] # the list of active set equations
+int nset # number of set equations
+
+bool new
+int i, ip, ins, nvar
+pointer fitcode, setsym
+int pr_gsym(), ph_catvar()
+pointer pr_gsymp()
+
+begin
+ # Get the fit expression symbols.
+ fitcode = pr_gsymp (sym, PTEQRPNFIT)
+
+ # Initialize.
+ nvar = 0
+ ip = 0
+ ins = Memi[fitcode+ip]
+
+ # Loop over the fit expression.
+ while (ins != PEV_EOC) {
+
+ switch (ins) {
+ case PEV_SETEQ:
+ ip = ip + 1
+ setsym = pr_gsym (Memi[fitcode+ip], PTY_SETEQ)
+ if (ph_catvar (eqn, setsym, cmap, omap, tuservars, uservars,
+ usererrs, nstdvars, nobsvars) == YES) {
+ new = true
+ do i = 1, nset + nvar {
+ if (setsym != userset[i])
+ next
+ eqset[i,eqn] = setsym
+ new = false
+ break
+ }
+ if (new) {
+ nvar = nvar + 1
+ eqset[nset+nvar,eqn] = setsym
+ userset[nset+nvar] = setsym
+ }
+ }
+ case PEV_NUMBER, PEV_CATVAR, PEV_OBSVAR, PEV_PARAM:
+ ip = ip + 1
+ case PEV_EXTEQ, PEV_TRNEQ:
+ ip = ip + 1
+ default:
+ # do nothing
+ }
+
+ ip = ip + 1
+ ins = Memi[fitcode+ip]
+ }
+
+ return (nvar)
+end
+
+
+# PH_CATVAR -- Determine whether any catalog variables in the set
+# equation have not been previously referenced in the transformation
+# equations.
+
+int procedure ph_catvar (eqn, setsym, cmap, omap, tuservars, uservars,
+ usererrs, nstdvars, nobsvars)
+
+int eqn # the transformation equation number
+int setsym # the set equation symbol
+pointer cmap # pointer to catalog variable column map
+pointer omap # pointer to observations variable column map
+int tuservars[nstdvars,ARB] # active variables as a function of eqn
+int uservars[ARB] # currently active catalog variables
+int usererrs[ARB] # currently active observations varaiables errs
+int nstdvars # the total number of catalog variables
+int nobsvars # the total number of observations variables
+
+int setcode, ip, ins, stat, vcol, ecol
+pointer catsym, obsym
+int pr_gsym(), pr_gsymi(), pr_findmap1()
+pointer pr_gsymp()
+
+begin
+ # Get the set equation code.
+ setcode = pr_gsymp (setsym, PSEQRPNEQ)
+
+ # Initialize.
+ ip = 0
+ ins = Memi[setcode+ip]
+ stat = NO
+
+ while (ins != PEV_EOC) {
+
+ switch (ins) {
+ case PEV_CATVAR:
+ ip = ip + 1
+ catsym = pr_gsym (Memi[setcode+ip] - nobsvars, PTY_CATVAR)
+ vcol = pr_gsymi (catsym, PINPCOL)
+ vcol = pr_findmap1 (cmap, vcol)
+ if (uservars[vcol] <= 0) {
+ tuservars[vcol,eqn] = -(vcol + nobsvars)
+ uservars[vcol] = -(vcol + nobsvars)
+ stat = YES
+ }
+
+ case PEV_OBSVAR:
+ ip = ip + 1
+ obsym = pr_gsym (Memi[setcode+ip], PTY_OBSVAR)
+ vcol = pr_gsymi (obsym, PINPCOL)
+ ecol = pr_gsymi (obsym, PINPERRCOL)
+ vcol = pr_findmap1 (omap, vcol)
+ if (! IS_INDEFI(ecol))
+ ecol = pr_findmap1 (omap, ecol)
+ if (! IS_INDEFI(ecol))
+ usererrs[vcol] = ecol
+
+ case PEV_NUMBER, PEV_PARAM:
+ ip = ip + 1
+
+ case PEV_SETEQ, PEV_EXTEQ, PEV_TRNEQ:
+ ip = ip + 1
+
+ default:
+ # do nothing
+ }
+
+ ip = ip + 1
+ ins = Memi[setcode+ip]
+ }
+
+ return (stat)
+end
diff --git a/noao/digiphot/photcal/evaluate/pherrors.x b/noao/digiphot/photcal/evaluate/pherrors.x
new file mode 100644
index 00000000..77a95391
--- /dev/null
+++ b/noao/digiphot/photcal/evaluate/pherrors.x
@@ -0,0 +1,278 @@
+include "../lib/parser.h"
+
+define DET_TOL 1.0e-20
+
+# PH_IEREQN -- Compute error estimates for the photometric indices based
+# on the value of any user-supplied errors equations. Use the chi-fitting
+# method developed by Bevington.
+
+int procedure ph_iereqn (params, a, nobs, deltaa, aindex, errors, nstd,
+ seteqn, setvals, serrors, nset, nustd, eqindex, neq)
+
+pointer params[ARB] # input array of pointers to the fitted parameters
+real a[ARB] # array of observed and catalog variables
+int nobs # the number of observed variables
+real deltaa[ARB] # array of increments for the catalog variables
+int aindex[ARB] # list of active catalog variables
+real errors[ARB] # output array of error estimates
+int nstd # number of catalog variables to be fit
+int seteqn[ARB] # array of set equation codes
+real setvals[ARB] # the set equation values
+real serrors[ARB] # output array of set equation errors
+int nset # the number of set equations
+int nustd # the number of active catalog variables
+int eqindex[ARB] # array of equations indices
+int neq # number of equations
+
+int i, j, sym, nerrors
+pointer errcode
+real rms, det
+int pr_gsym()
+pointer pr_gsymp()
+real pr_eval(), ph_accum(), ph_incrms()
+
+include "invert.com"
+
+begin
+ # Evaluate the reference and error equations.
+ nerrors = 0
+ do i = 1, neq {
+
+ sym = pr_gsym (eqindex[i], PTY_TRNEQ)
+ Memr[py+i-1] = pr_eval (pr_gsymp (sym, PTEQRPNREF), a,
+ Memr[params[eqindex[i]]])
+ if (IS_INDEFR(Memr[py+i-1]))
+ return (0)
+
+ errcode = pr_gsymp (sym, PTEQRPNERROR)
+ if (errcode == NULL)
+ Memr[pyerr+i-1] = 0.0
+ else {
+ Memr[pyerr+i-1] = pr_eval (errcode, a,
+ Memr[params[eqindex[i]]])
+ if (IS_INDEFR(Memr[pyerr+i-1]))
+ Memr[pyerr+i-1] = 0.0
+ else
+ nerrors = nerrors + 1
+ }
+ }
+
+ # Return if there are no error equations.
+ if (nerrors <= 0)
+ return (0)
+
+ # Compute each equations contribution to the to the total error.
+ call aclrr (errors, nstd)
+ call aclrr (serrors, nset)
+ do i = 1, neq {
+
+ # Add in the appropriate error term.
+ if (Memr[pyerr+i-1] <= 0.0)
+ next
+ call amovr (a[nobs+1], Memr[pafit], nstd)
+ Memr[py+i-1] = Memr[py+i-1] + Memr[pyerr+i-1]
+
+ # Accumulate the matrices and vectors, do the inversion, and
+ # compute the new parameter increments.
+ rms = ph_accum (params, Memr[py], Memr[pyfit], eqindex, neq, a,
+ nobs, deltaa, aindex, Memr[pda], nstd, Memd[palpha],
+ Memr[pbeta], Memi[pik], Memi[pjk], nustd, det)
+
+ # Compute the contribution to the sum of the squares of the errors.
+ #if ((! IS_INDEFR(rms)) && (abs (det) >= DET_TOL)) {
+ if (! IS_INDEFR(rms)) {
+ rms = ph_incrms (params, Memr[py], Memr[pyfit], eqindex, neq,
+ a, nobs, Memr[pda], aindex, nstd, rms)
+ do j = 1, nstd {
+ if (aindex[j] == 0)
+ next
+ errors[j] = errors[j] + (a[nobs+j] - Memr[pafit+j-1]) ** 2
+ }
+ do j = 1, nset {
+ serrors[j] = serrors[j] + (pr_eval (seteqn[j], a,
+ Memr[params[1]]) - setvals[j]) ** 2
+ }
+ }
+
+ # Reset the error term.
+ Memr[py+i-1] = Memr[py+i-1] - Memr[pyerr+i-1]
+ call amovr (Memr[pafit], a[nobs+1], nstd)
+ }
+
+ # Compute the errors themselves.
+ do i = 1, nstd {
+ if (errors[i] <= 0.0)
+ errors[i] = 0.0
+ else
+ errors[i] = sqrt (errors[i])
+ }
+ do i = 1, nset {
+ if (serrors[i] <= 0.0)
+ serrors[i] = 0.0
+ else
+ serrors[i] = sqrt (serrors[i])
+ }
+
+
+ return (nerrors)
+end
+
+
+# PH_IERVAL -- Compute error estimates for the photometric indices based
+# on the value of any user-supplied errors equations.
+
+int procedure ph_ierval (params, a, eindex, nobs, deltaa, aindex, errors,
+ nstd, seteqn, setvals, serrors, nset, nustd, eqindex, neq)
+
+pointer params[ARB] # input array of pointers to the fitted parameters
+real a[ARB] # array of observed and catalog variables
+int eindex[ARB] # indices of observed and catalog variables with errors
+int nobs # the number of observed variables
+real deltaa[ARB] # array of increments for the catalog variables
+int aindex[ARB] # list of active catalog variables
+real errors[ARB] # output array of error estimates
+int nstd # number of catalog variables to be fit
+int seteqn[ARB] # array of set equation codes
+real setvals[ARB] # the set equation values
+real serrors[ARB] # output array of set equation errors
+int nset # the number of set equations
+int nustd # the number of active catalog variables
+int eqindex[ARB] # array of equation indices
+int neq # number of equations
+
+int i, j, k, sym, nerrors
+real atemp, rms, det
+int pr_gsym()
+pointer pr_gsymp()
+real pr_eval(), ph_accum(), ph_incrms()
+
+include "invert.com"
+
+begin
+ # Initialize.
+ nerrors = 0
+ call aclrr (errors, nstd)
+ call aclrr (serrors, nset)
+
+ # Loop over the observational variables.
+ do j = 1, nobs {
+
+ # Use only variables with errors.
+ if (eindex[j] <= 0)
+ next
+ nerrors = nerrors + 1
+ if (IS_INDEFR(a[eindex[j]]) || (a[eindex[j]] <= 0.0))
+ next
+
+ atemp = a[j]
+ a[j] = a[j] + a[eindex[j]]
+ call amovr (a[nobs+1], Memr[pafit], nstd)
+
+ # Evaluate the reference equations.
+ do i = 1, neq {
+ sym = pr_gsym (eqindex[i], PTY_TRNEQ)
+ Memr[py+i-1] = pr_eval (pr_gsymp (sym, PTEQRPNREF), a,
+ Memr[params[eqindex[i]]])
+ if (IS_INDEFR(Memr[py+i-1]))
+ return (0)
+ }
+
+ # Accumulate the matrices and vectors, do the inversion, and
+ # compute the new parameter increments.
+ #call eprintf ("errors before accum\n")
+ rms = ph_accum (params, Memr[py], Memr[pyfit], eqindex, neq, a,
+ nobs, deltaa, aindex, Memr[pda], nstd, Memd[palpha],
+ Memr[pbeta], Memi[pik], Memi[pjk], nustd, det)
+ #call eprintf ("errors after accum\n")
+
+ # Compute the contribution to the sum of the squares of the errors.
+ #if ((! IS_INDEFR(rms)) && (abs (det) >= DET_TOL)) {
+ if (! IS_INDEFR(rms)) {
+ #call eprintf ("errors before accum\n")
+ rms = ph_incrms (params, Memr[py], Memr[pyfit], eqindex, neq,
+ a, nobs, Memr[pda], aindex, nstd, rms)
+ #call eprintf ("errors before accum\n")
+
+ do k = 1, nstd {
+ if (aindex[k] <= 0)
+ next
+ errors[k] = errors[k] + (a[nobs+k] - Memr[pafit+k-1]) ** 2
+ }
+
+ a[j] = atemp
+ do k = 1, nset {
+ serrors[k] = serrors[k] + (pr_eval (seteqn[k], a,
+ Memr[params[1]]) - setvals[k]) ** 2
+ }
+ call amovr (Memr[pafit], a[nobs+1], nstd)
+
+ } else {
+
+ a[j] = atemp
+ call amovr (Memr[pafit], a[nobs+1], nstd)
+ }
+ }
+
+ # Compute the errors themselves.
+ do i = 1, nstd {
+ if (errors[i] <= 0.0)
+ errors[i] = 0.0
+ else
+ errors[i] = sqrt (errors[i])
+ }
+ do i = 1, nset {
+ if (serrors[i] <= 0.0)
+ serrors[i] = 0.0
+ else
+ serrors[i] = sqrt (serrors[i])
+ }
+
+ return (nerrors)
+end
+
+
+# PH_ERVAL -- Compute the error in an equation by summing the effects of errors
+# in the observational variables.
+
+real procedure ph_erval (symfit, fitval, params, a, aindex, eindex, nobsvars)
+
+pointer symfit # pointer to the fit equation
+real fitval # the best fit value
+real params[ARB] # the fitted equation parameters
+real a[ARB] # the observed and catalog variable values
+int aindex[ARB] # the list of active variables
+int eindex[ARB] # the list
+int nobsvars # the number of observed variables
+
+int i, nerrors
+real errval, afit
+real pr_eval()
+
+begin
+ # Initialize.
+ nerrors = 0
+ errval = 0.0
+
+ # Loop over the observed variables.
+ do i = 1, nobsvars {
+
+ # Skip observed variables with no errors.
+ if (eindex[i] <= 0)
+ next
+ nerrors = nerrors + 1
+ if ((IS_INDEFR(a[eindex[i]])) || (a[eindex[i]] <= 0.0))
+ next
+
+ # Evaluate the contribution of each observed variable to the
+ # total error.
+ afit = a[i]
+ a[i] = a[i] + a[eindex[i]]
+ errval = errval + (pr_eval (symfit, a, params) - fitval) ** 2
+ a[i] = afit
+ }
+
+ if (nerrors <= 0)
+ return (INDEFR)
+ else
+ return (sqrt (errval))
+end
diff --git a/noao/digiphot/photcal/evaluate/phinvert.x b/noao/digiphot/photcal/evaluate/phinvert.x
new file mode 100644
index 00000000..9d7ee14b
--- /dev/null
+++ b/noao/digiphot/photcal/evaluate/phinvert.x
@@ -0,0 +1,619 @@
+include <mach.h>
+include "../lib/parser.h"
+
+# PH_IVINIT -- Preallocate the space required by the inversion code.
+
+procedure ph_ivinit (nstd, nustd, neq)
+
+int nstd # number of catalog variables
+int nustd # number of catalog variables to be fit
+int neq # number of equations
+
+include "invert.com"
+
+begin
+ call malloc (py, neq, TY_REAL)
+ call malloc (pyfit, neq, TY_REAL)
+ call malloc (pa, nstd, TY_REAL)
+ call malloc (pdelta, nstd, TY_REAL)
+ call malloc (pda, nstd, TY_REAL)
+
+ call malloc (palpha, nustd * nustd, TY_DOUBLE)
+ call malloc (pbeta, nustd, TY_REAL)
+ call malloc (pik, nustd, TY_INT)
+ call malloc (pjk, nustd, TY_INT)
+
+ call malloc (pyerr, neq, TY_REAL)
+ call malloc (pafit, nstd, TY_REAL)
+end
+
+
+# PH_IVFREE -- Free the space required by the inversion code.
+
+procedure ph_ivfree ()
+
+include "invert.com"
+
+begin
+ call mfree (py, TY_REAL)
+ call mfree (pyfit, TY_REAL)
+ call mfree (pa, TY_REAL)
+ call mfree (pdelta, TY_REAL)
+ call mfree (pda, TY_REAL)
+
+ call mfree (palpha, TY_DOUBLE)
+ call mfree (pbeta, TY_REAL)
+ call mfree (pik, TY_INT)
+ call mfree (pjk, TY_INT)
+
+ call mfree (pyerr, TY_REAL)
+ call mfree (pafit, TY_REAL)
+end
+
+
+# PH_OBJCHECK -- Check that the equations for this particular star are
+# invertable.
+
+int procedure ph_objcheck (params, a, vartable, nstdvars, nreq, eqset,
+ maxnset, vindex, nvar, eqindex, neq)
+
+pointer params[ARB] # array of pointers to the fitted parameters
+real a[ARB] # array of observed and catalog variables
+int vartable[nstdvars,ARB] # table of variables as a function of equation
+int nstdvars # the total number of catalog variables
+int nreq # the total number of reference equations
+int eqset[maxnset,ARB] # set equation table
+int maxnset # maximum number of set equations
+int vindex[ARB] # output index of variables
+int nvar # number of variables used in the equations
+int eqindex[ARB] # output index of equations
+int neq # number of equations to be reduced
+
+int i, j, sym, ncat, nset
+real rval
+int pr_gsym()
+pointer pr_gsymp()
+real pr_eval()
+
+begin
+ # Initialize
+ call aclri (vindex, nstdvars)
+ call aclri (eqindex, nreq)
+
+ # Evalute the reference equations.
+ neq = 0
+ do i = 1, nreq {
+ sym = pr_gsym (i, PTY_TRNEQ)
+ rval = pr_eval (pr_gsymp (sym, PTEQRPNREF), a, Memr[params[i]])
+ if (IS_INDEFR(rval))
+ next
+ neq = neq + 1
+ eqindex[neq] = i
+ }
+
+ # If there is no data return.
+ if (neq <= 0)
+ return (ERR)
+
+ # Determine which variables are used by the reduced set of equations.
+ do i = 1, neq {
+ do j = 1, nstdvars {
+ if (vartable[j,eqindex[i]] == 0)
+ next
+ vindex[j] = vartable[j,eqindex[i]]
+ }
+ }
+
+ # Deterine which set equations are used by the reduced set of equations
+ nset = 0
+ do j = 1, maxnset {
+ do i = 1, neq {
+ if (eqset[j,eqindex[i]] == 0)
+ next
+ nset = nset + 1
+ break
+ }
+ }
+
+ # Count the number of variables.
+ nvar = 0
+ ncat = 0
+ do j = 1, nstdvars {
+ if (vindex[j] == 0)
+ next
+ nvar = nvar + 1
+ if (vindex[j] > 0)
+ ncat = ncat + 1
+ }
+
+ if ((ncat + nset) > neq)
+ return (ERR)
+
+ return (OK)
+end
+
+
+define MAX_NITER1 10 # maximum number of iterations
+define MAX_NITER2 50 # maximum number of trials
+define DET_TOL 1.0E-20 # minimum value of the determinant
+#define DET_TOL 0.0 # minimum value of the determinant
+define MIN_DELTA 0.01 # minimum absolute value of
+ # parameter increments
+
+# PH_INVERT -- Invert the transformation to compute the standard indices.
+
+int procedure ph_invert (params, a, nobs, deltaa, aindex, nstd,
+ nustd, eqindex, nueq)
+
+pointer params[ARB] # input array of pointers to the fitted parameters
+real a[ARB] # array of observed and catalog variables
+int nobs # the number of observed variables
+real deltaa[ARB] # array of increments for the catalog variables
+int aindex[ARB] # index of active catalog variables
+int nstd # total number of catalog variables
+int nustd # number of catalog variables to be fit
+int eqindex[ARB] # the equation index
+int nueq # total number of equations used
+
+int i, sym, niter
+real stdev1, stdev2, det, rms
+int pr_gsym()
+pointer pr_gsymp()
+real pr_eval(), ph_accum(), ph_incrms()
+
+include "invert.com"
+
+begin
+ # Evalute the reference equations.
+ do i = 1, nueq {
+ sym = pr_gsym (eqindex[i], PTY_TRNEQ)
+ Memr[py+i-1] = pr_eval (pr_gsymp (sym, PTEQRPNREF), a,
+ Memr[params[eqindex[i]]])
+ if (IS_INDEFR(Memr[py+i-1]))
+ return (ERR)
+ }
+
+ # Initialize the parameter increments. This will be incremented
+ # each time through the fitting loop.
+ call amovr (deltaa, Memr[pdelta], nstd)
+
+ # Accumulate the matrices and vectors, do the inversion and compute
+ # the new parameter increments. The fit will terminate when the
+ # determinant of the inversion matrix becomes < 1.0e-20, if the
+ # standard deviation of the fit begins to increase, if the rms of
+ # the fit < EPSILONR, or the maximum number of iterations is
+ # exceeded, whichever comes first.
+
+ niter = 0
+
+ repeat {
+
+ # Compute the curvature currection. Return INDEFR if there are
+ # bad data in the fit. Terminate the fit if the determinant of
+ # the curvature matrix is too close to zero.
+
+ stdev1 = ph_accum (params, Memr[py], Memr[pyfit], eqindex, nueq,
+ a, nobs, Memr[pdelta], aindex, Memr[pda], nstd,
+ Memd[palpha], Memr[pbeta], Memi[pik], Memi[pjk], nustd, det)
+
+ #call eprintf ("acc: niter=%d det=%g stdev1=%g\n")
+ #call pargi (niter+1)
+ #call pargr (det)
+ #call pargr (stdev1)
+
+ # Return if there is INDEF data in the fit.
+ if (IS_INDEFR(stdev1))
+ return (ERR)
+
+ # Check the size of the determinant but force at least one fit.
+ if ((abs (det) < DET_TOL) && (niter > 0))
+ break
+
+ # Find the new parameter values.
+ call amovr (a, Memr[pa], nstd)
+ stdev2 = ph_incrms (params, Memr[py], Memr[pyfit], eqindex, nueq,
+ a, nobs, Memr[pda], aindex, nstd, stdev1)
+
+ #call eprintf ("inc: niter=%d det=%g stdev2=%g\n")
+ #call pargi (niter+1)
+ #call pargr (det)
+ #call pargr (stdev2)
+
+ # Check the new values.
+ if (IS_INDEFR(stdev2) || (stdev2 >= stdev1)) {
+ if (niter == 0)
+ return (ERR)
+ else {
+ call amovr (Memr[pa], a, nstd)
+ return (OK)
+ }
+ }
+
+ # User the new deltas and increment the fit counters.
+ call anegr (Memr[pda], Memr[pdelta], nstd)
+ call ph_deltamin (Memr[pdelta], MIN_DELTA, Memr[pdelta], nstd)
+ niter = niter + 1
+ rms = sqrt (stdev2)
+
+ } until ((niter == MAX_NITER1) || (rms <= EPSILONR))
+
+ return (OK)
+end
+
+
+# PH_ACCUM -- Accumulate the matrix of second derivatives and vector
+# of first derivatives required for parabolic expansion of the rms
+# non-linear least squares fitting technique. This code is a modification
+# of the Bevington CHIFIT subroutine where the reduced chi-squared has
+# been replaced by the rms. The original CHIFIT cannot be used to fit the
+# case when there are n data points and n unknowns since the number of
+# degrees of freedom is zero and hence so is the reduced chi-squared.
+
+real procedure ph_accum (params, y, yfit, eqindex, neq, a, nobs, deltaa,
+ aindex, da, nstd, alpha, beta, ik, jk, nustd, det)
+
+pointer params[ARB] # input array of ptrs to the fitted parameters
+real y[ARB] # array of reference equation values
+real yfit[ARB] # array of fitted reference equation values
+int eqindex[ARB] # the equation indices
+int neq # number of equations to be inverted
+real a[ARB] # array of observed and catalog variables
+int nobs # the number of observed variables
+real deltaa[ARB] # array of increments for the catalog variables
+int aindex[ARB] # index of active catalog variables
+real da[ARB] # new array of parameter increments
+int nstd # number of catalog variables
+double alpha[nustd,ARB] # the matrix of second derivatives
+real beta[ARB] # the vector of first derivatives
+int ik[ARB] # working array for the matrix inversion
+int jk[ARB] # working array for the matrix inversion
+int nustd # The number of catalog variables to be fit
+real det # determinant of inverted matrix
+
+int i, j, k, nj, nk, sym
+real aj, ak, rms1, rms2, rms3
+int pr_gsym()
+pointer pr_gsymp()
+real pr_eval()
+
+begin
+ # Compute the initial rms, checking for INDEF valued variables.
+ rms1 = 0.0
+ do i = 1, neq {
+ sym = pr_gsym (eqindex[i], PTY_TRNEQ)
+ yfit[i] = pr_eval (pr_gsymp (sym, PTEQRPNFIT), a,
+ Memr[params[eqindex[i]]])
+ if (IS_INDEFR(yfit[i]))
+ return (INDEFR)
+ rms1 = rms1 + (y[i] - yfit[i]) ** 2
+ }
+ rms1 = rms1 / neq
+
+ nj = 0
+ do j = 1, nstd {
+
+ # Check the status of the parameter.
+ if (aindex[j] == 0)
+ next
+ nj = nj + 1
+
+ # Increment each parameter.
+ aj = a[j+nobs]
+ a[j+nobs] = aj + deltaa[j]
+
+ # Compute a new rms.
+ rms2 = 0.0
+ do i = 1, neq {
+ sym = pr_gsym (eqindex[i], PTY_TRNEQ)
+ yfit[i] = pr_eval (pr_gsymp (sym, PTEQRPNFIT), a,
+ Memr[params[eqindex[i]]])
+ rms2 = rms2 + (y[i] - yfit[i]) ** 2
+ }
+ rms2 = rms2 / neq
+
+ # Begin accumulating the diagonal elements .
+ alpha[nj,nj] = rms2 - 2.0 * rms1
+ beta[nj] = -rms2
+
+ # Accumulate the non-diagonal elements.
+ nk = 0
+ do k = 1, nstd {
+
+ if (aindex[k] == 0)
+ next
+ nk = nk + 1
+
+ if ((nk - nj) == 0)
+ next
+ else if ((nk - nj) < 0) {
+ alpha[nk,nj] = (alpha[nk,nj] - rms2) / 2.0
+ alpha[nj,nk] = alpha[nk,nj]
+ next
+ }
+
+ alpha[nj,nk] = rms1 - rms2
+ ak = a[k+nobs]
+ a[k+nobs] = ak + deltaa[k]
+
+ rms3 = 0.0
+ do i = 1, neq {
+ sym = pr_gsym (eqindex[i], PTY_TRNEQ)
+ yfit[i] = pr_eval (pr_gsymp (sym, PTEQRPNFIT), a,
+ Memr[params[eqindex[i]]])
+ rms3 = rms3 + (y[i] - yfit[i]) ** 2
+ }
+ rms3 = rms3 / neq
+
+ alpha[nj,nk] = alpha[nj,nk] + rms3
+ a[k+nobs] = ak
+ }
+
+ # Continue accumulating the diagonal elements.
+ a[j+nobs] = aj - deltaa[j]
+ rms3 = 0.0
+ do i = 1, neq {
+ sym = pr_gsym (eqindex[i], PTY_TRNEQ)
+ yfit[i] = pr_eval (pr_gsymp (sym, PTEQRPNFIT), a,
+ Memr[params[eqindex[i]]])
+ rms3 = rms3 + (y[i] - yfit[i]) ** 2
+ }
+ rms3 = rms3 / neq
+
+ a[j+nobs] = aj
+ alpha[nj,nj] = (alpha[nj,nj] + rms3) / 2.0
+ beta[nj] = (beta[nj] + rms3) / 4.0
+ }
+
+ # Eliminate any curvature from the matrix of second derivatives.
+ do j = 1, nj {
+ if (alpha[j,j] > 0.0)
+ next
+ if (alpha[j,j] < 0.0)
+ alpha[j,j] = -alpha[j,j]
+ else
+ alpha[j,j] = 0.01
+ do k = 1, nk {
+ if ((k - j) == 0)
+ next
+ alpha[j,k] = 0.0
+ alpha[k,j] = 0.0
+ }
+ }
+
+ # Invert the matrix.
+ call phminv (alpha, ik, jk, nj, det)
+
+ # Increment the parameters.
+ nj = 0
+ do j = 1, nstd {
+ da[j] = 0.0
+ if (aindex[j] == 0)
+ next
+ nj = nj + 1
+ nk = 0
+ do k = 1, nstd {
+ if (aindex[k] == 0)
+ next
+ nk = nk + 1
+ da[j] = da[j] + beta[nk] * alpha[nj,nk]
+ }
+ da[j] = 0.2 * da[j] * deltaa[j]
+ }
+
+ # If the determinate is too small increment the parameters by
+ # deltas and try again.
+ #if (abs (det) < DET_TOL) {
+ #call eprintf ("using approx\n")
+ #do j = 1, nstd {
+ #if (aindex[j] == 0) {
+ #da[j] = 0.0
+ #next
+ #}
+ #call eprintf ("i=%d dain=%g ")
+ #call pargi (j)
+ #call pargr (da[j])
+ #if (da[j] > 0.0)
+ #da[j] = abs (deltaa[j])
+ #else if (da[j] < 0.0)
+ #da[j] = -abs (deltaa[j])
+ #else
+ #da[j] = 0.0
+ #call eprintf ("daout=%g\n")
+ #call pargr (da[j])
+ #}
+ #}
+
+ return (rms1)
+end
+
+
+# PH_INCRMS -- Increment the parameters until three values of the rms are found
+# which bracket the best fitting data point and fit a parabola to the three
+# different rms points.
+
+real procedure ph_incrms (params, y, yfit, eqindex, neq, a, nobs, da, aindex,
+ nstd, rms1)
+
+pointer params[ARB] # input array of ptrs to the fitted parameters
+real y[ARB] # the array of reference equation values
+real yfit[ARB] # the array of fitted reference equation values
+int eqindex[ARB] # list of active equations
+int neq # the number of equations
+real a[ARB] # array of observed and fitted variables
+int nobs # number of observed variables
+real da[ARB] # the parameter increments
+int aindex[ARB] # the index of active catalog variables
+int nstd # number of catalog variables
+real rms1 # the first rms point
+
+int j, i, sym, niter
+real orms2, rms2, orms3, rms3, delta, rms
+int pr_gsym()
+pointer pr_gsymp()
+real pr_eval()
+
+begin
+ # Adjust the parameters.
+ rms = rms1
+ do j = 1, nstd {
+ if (aindex[j] == 0)
+ next
+ a[j+nobs] = a[j+nobs] + da[j]
+ }
+
+ # Alter the parameter increments until the rms starts to decrease.
+ orms2 = MAX_REAL
+ niter = 0
+ repeat {
+
+ rms2 = 0.0
+ do i = 1, neq {
+ sym = pr_gsym (eqindex[i], PTY_TRNEQ)
+ yfit[i] = pr_eval (pr_gsymp (sym, PTEQRPNFIT), a,
+ Memr[params[eqindex[i]]])
+ rms2 = rms2 + (y[i] - yfit[i]) ** 2
+ }
+ rms2 = rms2 / neq
+ #call eprintf (" niter=%d rms1=%g rms2=%g\n")
+ #call pargi (niter)
+ #call pargr (rms1)
+ #call pargr (rms2)
+ if (rms2 <= 0.0)
+ break
+ if ((rms1 - rms2) >= 0.0)
+ break
+
+ # If rms2 does not decrease and does not change from one iteration
+ # to the next we are probably near the precision limits of the
+ # computer or the computed curvature has the wrong sign. In that
+ # case quit.
+
+ if (orms2 < MAX_REAL) {
+ if (abs ((rms2 - orms2) / orms2) < EPSILONR)
+ return (rms)
+ }
+
+ orms2 = rms2
+ niter = niter + 1
+ if (niter >= MAX_NITER2)
+ return (rms)
+
+ do j = 1, nstd {
+ if (aindex[j] == 0)
+ next
+ #da[j] = da[j] / 2.0
+ a[j+nobs] = a[j+nobs] - da[j]
+ }
+
+
+ }
+
+ # Alter the parameter increments until the rms starts to increase.
+ orms3 = MAX_REAL
+ niter = 0
+ repeat {
+
+ do j = 1, nstd {
+ if (aindex[j] == 0)
+ next
+ a[j+nobs] = a[j+nobs] + da[j]
+ }
+
+ rms3 = 0.0
+ do i = 1, neq {
+ sym = pr_gsym (eqindex[i], PTY_TRNEQ)
+ yfit[i] = pr_eval (pr_gsymp (sym, PTEQRPNFIT), a,
+ Memr[params[eqindex[i]]])
+ rms3 = rms3 + (y[i] - yfit[i]) ** 2
+ }
+ rms3 = rms3 / neq
+ #call eprintf (" niter=%d rms1=%g rms2=%g rms3=%g\n")
+ #call pargi (niter)
+ #call pargr (rms1)
+ #call pargr (rms2)
+ #call pargr (rms3)
+ if ((rms3 - rms2) >= 0.0)
+ break
+
+ if (orms3 < MAX_REAL) {
+ if (abs ((rms3 - orms3) / orms3) < EPSILONR)
+ return (rms)
+ }
+
+ niter = niter + 1
+ if (niter >= MAX_NITER2)
+ return (rms)
+
+
+ orms3 = rms3
+ rms1 = rms2
+ rms2 = rms3
+
+ }
+
+ # Fit a parabola to the three values of the rms that bracket the fit.
+ if (rms3 <= rms2)
+ delta = 1.0
+ else
+ delta = 1.0 / (1.0 + (rms1 - rms2) / (rms3 - rms2)) + 0.5
+ do j = 1, nstd {
+ if (aindex[j] == 0)
+ next
+ a[nobs+j] = a[nobs+j] - delta * da[j]
+ }
+
+ rms = 0.0
+ do i = 1, neq {
+ sym = pr_gsym (eqindex[i], PTY_TRNEQ)
+ yfit[i] = pr_eval (pr_gsymp (sym, PTEQRPNFIT), a,
+ Memr[params[eqindex[i]]])
+ rms = rms + (y[i] - yfit[i]) ** 2
+ }
+ rms = rms / neq
+
+ if ((rms2 - rms) < 0.0) {
+ do j = 1, nstd {
+ if (aindex[j] == 0)
+ next
+ a[nobs+j] = a[nobs+j] + (delta - 1.) * da[j]
+ }
+ do i = 1, neq {
+ sym = pr_gsym (eqindex[i], PTY_TRNEQ)
+ yfit[i] = pr_eval (pr_gsymp (sym, PTEQRPNFIT), a,
+ Memr[params[eqindex[i]]])
+ }
+ rms = rms2
+ }
+
+ #call eprintf (" incr: rms1=%g rms2=%g rms3=%g rms=%g\n")
+ #call pargr (rms1)
+ #call pargr (rms2)
+ #call pargr (rms3)
+ #call pargr (rms)
+
+ return (rms)
+end
+
+
+# PH_DELTAMIN -- Check to make sure that the absolute value of the deltaa
+# is always greater than or equal to min_delta.
+
+procedure ph_deltamin (a, min_delta, b, npix)
+
+real a[ARB] # input vector
+real min_delta # minimum permitted absolute value
+real b[ARB] # output vector
+int npix # number of points
+
+int i
+
+begin
+ do i = 1, npix {
+ if (abs(a[i]) >= min_delta)
+ b[i] = a[i]
+ else if (a[i] < 0.0)
+ b[i] = -min_delta
+ else
+ b[i] = min_delta
+ }
+end
diff --git a/noao/digiphot/photcal/evaluate/phminv.f b/noao/digiphot/photcal/evaluate/phminv.f
new file mode 100644
index 00000000..44d7430e
--- /dev/null
+++ b/noao/digiphot/photcal/evaluate/phminv.f
@@ -0,0 +1,114 @@
+C SUBROUTINE PHMINV.F
+C
+C SOURCE
+C BEVINGTON, PAGES 302-303.
+C
+C PURPOSE
+C INVERT A SYMMETRIC MATRIX AND CALCULATE ITS DETERMINANT
+C
+C USAGE
+C CALL PHMINV (ARRAY, IK, JK, NORDER, DET)
+C
+C DESCRIPTION OF PARAMETERS
+C ARRAY - INPUT MATRIX WHICH IS REPLACED BY ITS INVERSE
+C IK - WORK ARRAY REQUIRED BY PHMINV
+C JK - WORK ARRAY REQUIRED BY PHMINV
+C NORDER - DEGREE OF MATRIX (ORDER OF DETERMINANT)
+C DET - DETERMINANT OF INPUT MATRIX
+C
+C SUBROUTINES AND FUNCTION SUBPROGRAMS REQUIRED
+C NONE
+C
+C COMMENT
+C DIMENSION STATEMENT VALID FOR NORDER UP TO 10
+C
+ SUBROUTINE PHMINV (ARRAY,IK,JK,NORDER,DET)
+ DOUBLE PRECISION ARRAY,AMAX,SAVE
+ DIMENSION ARRAY(NORDER,NORDER),IK(NORDER),JK(NORDER)
+C
+10 DET=1.
+11 DO 100 K=1,NORDER
+C
+C FIND LARGEST ELEMENT ARRAY(I,J) IN REST OF MATRIX
+C
+ AMAX=0.
+21 CONTINUE
+ IK(K) = K
+ JK(K) = K
+ DO 30 I=K,NORDER
+ DO 30 J=K,NORDER
+23 IF (DABS(AMAX)-DABS(ARRAY(I,J))) 24,24,30
+24 AMAX=ARRAY(I,J)
+ IK(K)=I
+ JK(K)=J
+30 CONTINUE
+C
+C INTERCHANGE ROWS AND COLUMNS TO PUT AMAX IN ARRAY(K,K)
+C
+41 I=IK(K)
+ IF (I-K) 21,51,43
+43 DO 50 J=1,NORDER
+ SAVE=ARRAY(K,J)
+ ARRAY(K,J)=ARRAY(I,J)
+50 ARRAY(I,J)=-SAVE
+51 J=JK(K)
+ IF (J-K) 21,600,53
+53 DO 60 I=1,NORDER
+ SAVE=ARRAY(I,K)
+ ARRAY(I,K)=ARRAY(I,J)
+60 ARRAY(I,J)=-SAVE
+
+C
+C CHECK FOR SINGULAR MATRIX
+C
+600 IF (AMAX) 61,610,61
+610 DET=0.
+ DO 700 I=1,NORDER
+ IF (I-K) 630,700,630
+630 ARRAY(I,K)=0.
+700 CONTINUE
+ DO 800 J=1,NORDER
+ IF (J-K) 730,800,730
+730 ARRAY(K,J)=0.
+800 CONTINUE
+ ARRAY(K,K)=0.
+ GOTO 100
+C
+C ACCUMULATE ELEMENTS OF INVERSE MATRIX
+C
+61 DO 70 I=1,NORDER
+ IF (I-K) 63,70,63
+63 ARRAY(I,K)=-ARRAY(I,K)/AMAX
+70 CONTINUE
+71 DO 80 I=1,NORDER
+ DO 80 J=1,NORDER
+ IF (I-K) 74,80,74
+74 IF (J-K) 75,80,75
+75 ARRAY(I,J)=ARRAY(I,J)+ARRAY(I,K)*ARRAY(K,J)
+80 CONTINUE
+81 DO 90 J=1,NORDER
+ IF (J-K) 83,90,83
+83 ARRAY(K,J)=ARRAY(K,J)/AMAX
+90 CONTINUE
+ ARRAY(K,K)=1./AMAX
+100 DET=DET*AMAX
+C
+C RESTORE ORDERING OF MATRIX
+C
+101 DO 130 L=1,NORDER
+ K=NORDER-L+1
+ J=IK(K)
+ IF (J-K) 111,111,105
+105 DO 110 I=1,NORDER
+ SAVE=ARRAY(I,K)
+ ARRAY(I,K)=-ARRAY(I,J)
+110 ARRAY(I,J)=SAVE
+111 I=JK(K)
+ IF (I-K) 130,130,113
+113 DO 120 J=1,NORDER
+ SAVE=ARRAY(K,J)
+ ARRAY(K,J)=-ARRAY(I,J)
+120 ARRAY(I,J)=SAVE
+130 CONTINUE
+140 RETURN
+ END
diff --git a/noao/digiphot/photcal/evaluate/phprint.x b/noao/digiphot/photcal/evaluate/phprint.x
new file mode 100644
index 00000000..94150792
--- /dev/null
+++ b/noao/digiphot/photcal/evaluate/phprint.x
@@ -0,0 +1,110 @@
+include "../lib/parser.h"
+
+# PH_MKPLIST -- Construct the list of variables to be printed.
+
+int procedure ph_mkplist (plist, cmap, omap, nobsvars, psym, pcols,
+ max_len_plist)
+
+int plist # pointer to the list of variables
+int cmap # catalog column to data column mapping
+int omap # observations column to data column mapping
+int nobsvars # number of observations variables
+int psym[ARB] # the output array of variable symbols
+int pcols[ARB] # offset in the data array of the symbol
+int max_len_plist # the maximum length of the variables list
+
+int len_plist, sym, col
+pointer sp, pname
+int fntgfnb(), pr_getsym(), pr_gsymi(), pr_findmap1()
+
+begin
+ call smark (sp)
+ call salloc (pname, SZ_FNAME, TY_CHAR)
+
+ len_plist = 0
+ while (fntgfnb (plist, Memc[pname], SZ_FNAME) != EOF) {
+ if (len_plist >= max_len_plist)
+ break
+ sym = pr_getsym (Memc[pname])
+ if (IS_INDEFI(sym))
+ next
+ switch (pr_gsymi (sym, PSYMTYPE)) {
+ case PTY_CATVAR:
+ psym[len_plist+1] = sym
+ col = pr_gsymi (sym, PINPCOL)
+ pcols[len_plist+1] = pr_findmap1 (cmap, col) + nobsvars
+ case PTY_OBSVAR:
+ psym[len_plist+1] = sym
+ col = pr_gsymi (sym, PINPCOL)
+ pcols[len_plist+1] = pr_findmap1 (omap, col)
+ case PTY_SETEQ:
+ psym[len_plist+1] = sym
+ pcols[len_plist+1] = 0
+ default:
+ next
+ }
+ len_plist = len_plist + 1
+ }
+
+ call sfree (sp)
+ return (len_plist)
+end
+
+
+# PH_OFORMAT -- Construct the output formatstr string.
+
+procedure ph_oformatstr (getid, ncols, formatstr, maxch)
+
+int getid # output the object id
+int ncols # number of columns in the output text file
+char formatstr[ARB] # the output formatstr string
+int maxch # maximum number of characters in the formatstr string
+
+int i, fcol
+
+begin
+ if (getid == YES) {
+ call strcpy ("%-10s ", formatstr, maxch)
+ fcol = 2
+ } else {
+ formatstr[1] = EOS
+ fcol = 1
+ }
+
+ do i = fcol, ncols {
+ if (i == ncols)
+ call strcat ("%-7.3f\n", formatstr, maxch)
+ else
+ call strcat ("%-7.3f ", formatstr, maxch)
+ }
+end
+
+
+# PH_OFIELDS -- Count the number of fields in the formatstr string.
+
+int procedure ph_ofields (formatstr)
+
+char formatstr[ARB] # the input formatstr string
+
+char percent
+int ip, findex, nfields
+int stridx()
+data percent /'%'/
+
+begin
+ nfields = 0
+
+ ip = 1
+ while (formatstr[ip] != EOS) {
+ findex = stridx (percent, formatstr[ip])
+ if (findex == 0)
+ break
+ ip = findex + ip
+ if (formatstr[ip] == percent)
+ ip = ip + 1
+ else
+ nfields = nfields + 1
+ }
+
+ return (nfields)
+end
diff --git a/noao/digiphot/photcal/evaluate/t_evalfit.x b/noao/digiphot/photcal/evaluate/t_evalfit.x
new file mode 100644
index 00000000..daf407c2
--- /dev/null
+++ b/noao/digiphot/photcal/evaluate/t_evalfit.x
@@ -0,0 +1,495 @@
+include <error.h>
+include <math/nlfit.h>
+include "../lib/io.h"
+include "../lib/parser.h"
+
+# Define the pointer Mem
+define MEMP Memi
+
+# T_EVALFIT - Main photometry processing task. This task will convert
+# intrumental photometric indices into standard indices, by using the
+# same configuration table and coefficients found by FITCOEFFS.
+
+procedure t_evalfit()
+
+pointer observations # pointer to the observations files list
+pointer catalogs # pointer to the catalogs files list
+pointer config # pointer to configuration file name
+pointer paramfile # pointer to fitted parameters file name
+pointer calibfile # pointer to the output file name
+int type # type of output to be processed
+int etype # algorithm for computing errors
+pointer print # pointer to the output variables list
+pointer formatstr # pointer to the output format string
+pointer catdir # pointer to the standard catalogs directory
+
+int i, j, getid, matchid, vcol, ecol, pindex, dummy, stat
+int obslist, stdlist, plist, ofd, ifd, sym, symvar, ncols
+int ntrneqs, nparams, nstd, nobsvars, nvars, len_plist
+pointer sp, input, starname, dummyname, stdtable, cmap, omap
+pointer vars, uservars, usererrs, fsym, rsym, esym, params, errors, psym, pcols
+real ref, fit, errval, resid, chisqr, rms, pval
+
+bool clgetb()
+int clgwrd(), open(), io_gcoeffs(), io_gobs(), pr_parse(), pr_geti()
+int pr_gsym(), pr_gsymi(), pr_findmap1(), pr_gvari(), fntopnb()
+int fntgfnb(), fntlenb(), ph_mkplist(), ph_header(), ph_ofields()
+pointer pr_gsymp(), pr_xgetname()
+real pr_eval(), ph_erval()
+errchk io_gcoeffs()
+
+begin
+ # Allocate space for file names and character strings.
+ call smark (sp)
+ call salloc (observations, SZ_LINE, TY_CHAR)
+ call salloc (catalogs, SZ_LINE, TY_CHAR)
+ call salloc (config, SZ_FNAME, TY_CHAR)
+ call salloc (paramfile, SZ_FNAME, TY_CHAR)
+ call salloc (calibfile, SZ_FNAME, TY_CHAR)
+ call salloc (input, SZ_FNAME, TY_CHAR)
+ call salloc (starname, SZ_LINE, TY_CHAR)
+ call salloc (dummyname, SZ_LINE, TY_CHAR)
+ call salloc (print, SZ_LINE, TY_CHAR)
+ call salloc (formatstr, SZ_LINE, TY_CHAR)
+ call salloc (catdir, SZ_FNAME, TY_CHAR)
+
+ # Get the input and output file lists and names.
+ call clgstr ("observations", Memc[observations], SZ_LINE)
+ call clgstr ("config", Memc[config], SZ_FNAME)
+ call clgstr ("parameters", Memc[paramfile], SZ_FNAME)
+ call clgstr ("calib", Memc[calibfile], SZ_FNAME)
+ call clgstr ("catalogs", Memc[catalogs], SZ_LINE)
+ call clgstr ("catdir", Memc[catdir], SZ_FNAME)
+
+ # Get output type flags.
+ etype = clgwrd ("errors", Memc[dummyname], SZ_LINE, ERR_OPTIONS)
+ type = clgwrd ("objects", Memc[dummyname], SZ_LINE, TYPE_STRING)
+ call clgstr ("print", Memc[print], SZ_LINE)
+ call clgstr ("format", Memc[formatstr], SZ_LINE)
+
+ # Open the output file.
+ iferr {
+ if (clgetb ("append"))
+ ofd = open (Memc[calibfile], APPEND, TEXT_FILE)
+ else
+ ofd = open (Memc[calibfile], NEW_FILE, TEXT_FILE)
+ } then {
+ call erract (EA_WARN)
+ call sfree (sp)
+ return
+ }
+
+ # Parse the configuration table.
+ if (pr_parse (Memc[config]) == ERR) {
+ call eprintf ("Error: Cannot parse the configuration file\n")
+ call close (ofd)
+ call sfree (sp)
+ return
+ }
+
+ # Get number of variables and allocate memory for their values.
+ # Program stars do not have standard indices (last values in
+ # the array), and they will remain undefined, and this will give
+ # undefined equation values for equations that use them.
+
+ nobsvars = pr_geti (NOBSVARS)
+ nvars = nobsvars + pr_geti (NCATVARS)
+ call salloc (vars, nvars, TY_REAL)
+ call salloc (uservars, nvars, TY_INT)
+ call aclri (Memi[uservars], nvars)
+ call salloc (usererrs, nvars, TY_INT)
+ call aclri (Memi[usererrs], nvars)
+
+ # Map observational and catalog columns. This has to be done here in
+ # order to avoid mapping columns every time a new program
+ # star is read.
+
+ call pr_catmap (cmap, dummy)
+ call pr_obsmap (omap, dummy)
+
+ # Get all the parameter values for all the equations. This has
+ # to be done outside the main loop to minimize disk i/o.
+ # Otherwise it would be necessary to fetch them for each
+ # star observation.
+
+ ntrneqs = pr_geti (NTRNEQS)
+ call salloc (fsym, ntrneqs, TY_POINTER)
+ call salloc (rsym, ntrneqs, TY_POINTER)
+ call salloc (esym, ntrneqs, TY_POINTER)
+ call salloc (params, ntrneqs, TY_POINTER)
+ call salloc (errors, ntrneqs, TY_POINTER)
+ do i = 1, ntrneqs {
+
+ # Get equation symbol and number of parameters for it.
+ sym = pr_gsym (i, PTY_TRNEQ)
+ nparams = pr_gsymi (sym, PTEQNPAR)
+
+ # Get the fit, reference and error equation pointers.
+ Memi[fsym+i-1] = pr_gsymp (sym, PTEQRPNFIT)
+ Memi[rsym+i-1] = pr_gsymp (sym, PTEQRPNREF)
+ Memi[esym+i-1] = pr_gsymp (sym, PTEQRPNERROR)
+
+ # Determine which catalog and observational variables were
+ # actually used in the reference equations and which have
+ # defined error columns.
+
+ do j = 1, pr_gsymi (sym, PTEQNRCAT) + pr_gsymi(sym, PTEQNROBS) {
+ symvar = pr_gvari (sym, j, PTEQREFVAR)
+ vcol = pr_gsymi (symvar, PINPCOL)
+ ecol = pr_gsymi (symvar, PINPERRCOL)
+ if (pr_gsymi (symvar, PSYMTYPE) == PTY_CATVAR) {
+ vcol = pr_findmap1 (cmap, vcol) + nobsvars
+ if (! IS_INDEFI(ecol))
+ ecol = pr_findmap1 (cmap, ecol) + nobsvars
+ } else {
+ vcol = pr_findmap1 (omap, vcol)
+ if (! IS_INDEFI(ecol))
+ ecol = pr_findmap1 (omap, ecol)
+ }
+ Memi[uservars+vcol-1] = vcol
+ if (! IS_INDEFI(ecol))
+ Memi[usererrs+vcol-1] = ecol
+ }
+
+ # Determine which catalog and observational variables were
+ # actually used in the fit equations and which have
+ # defined error columns.
+
+ do j = 1, pr_gsymi (sym, PTEQNFCAT) + pr_gsymi(sym, PTEQNFOBS) {
+ symvar = pr_gvari (sym, j, PTEQFITVAR)
+ vcol = pr_gsymi (symvar, PINPCOL)
+ ecol = pr_gsymi (symvar, PINPERRCOL)
+ if (pr_gsymi (symvar, PSYMTYPE) == PTY_CATVAR) {
+ vcol = pr_findmap1 (cmap, vcol) + nobsvars
+ if (! IS_INDEFI(ecol))
+ ecol = pr_findmap1 (cmap, ecol) + nobsvars
+ } else {
+ vcol = pr_findmap1 (omap, vcol)
+ if (! IS_INDEFI(ecol))
+ ecol = pr_findmap1 (omap, ecol)
+ }
+ Memi[uservars+vcol-1] = vcol
+ if (! IS_INDEFI(ecol))
+ Memi[usererrs+vcol-1] = ecol
+ }
+
+ # Allocate space for parameter values and errors,
+ # for the current equation, and read them from the
+ # parameters file.
+
+ call salloc (MEMP[params+i-1], nparams, TY_REAL)
+ call salloc (MEMP[errors+i-1], nparams, TY_REAL)
+ iferr {
+ if (io_gcoeffs (Memc[paramfile], sym, stat, chisqr, rms,
+ Memr[MEMP[params+i-1]], Memr[MEMP[errors+i-1]],
+ nparams) != nparams) {
+ call eprintf ("Warning: Error reading parameters for ")
+ call eprintf ("equation %s from %s\n")
+ call pargstr (Memc[pr_xgetname (sym)])
+ call pargstr (Memc[paramfile])
+ call amovkr (INDEFR, Memr[MEMP[params+i-1]], nparams)
+ call amovkr (INDEFR, Memr[MEMP[errors+i-1]], nparams)
+ }
+ } then {
+ call erract (EA_WARN)
+ call close (ofd)
+ call pr_unmap (cmap)
+ call pr_unmap (omap)
+ call pr_free()
+ call sfree (sp)
+ return
+ }
+
+ # Issue a warning if some of the equations in the system did
+ # not converge but proceed with the evaluation.
+ # didn't converge.
+
+ if (stat != DONE) {
+ call eprintf (
+ "Warning: The solution for equation %s did not converge")
+ call pargstr (Memc[pr_xgetname (sym)])
+ }
+ }
+
+ # Decide whether to use id and/or catalog matching or not.
+ if (pr_geti (MINCOL) <= 1) {
+ getid = NO
+ matchid = NO
+ stdtable = NULL
+ } else if (Memc[catalogs] == EOS) {
+ getid = YES
+ matchid = NO
+ stdtable = NULL
+ } else {
+ getid = YES
+ matchid = YES
+ }
+
+ # Get the list of optional variables to be printed. These variables
+ # may include any of the catalog or observations variables or the
+ # set equations. Variables which match any of these catagories
+ # will be ommited from the list to be printed.
+
+ plist = fntopnb (Memc[print], NO)
+ len_plist = fntlenb (plist)
+ if (len_plist > 0) {
+ call salloc (psym, len_plist, TY_INT)
+ call salloc (pcols, len_plist, TY_INT)
+ len_plist = ph_mkplist (plist, cmap, omap, nobsvars, Memi[psym],
+ Memi[pcols], len_plist)
+ }
+ call fntclsb (plist)
+
+ # Print the output header.
+ ncols = ph_header (ofd, Memc[observations], Memc[catalogs],
+ Memc[config], Memc[paramfile], type, getid, Memi[psym],
+ Memi[pcols], len_plist, etype, matchid)
+
+ # Set the formatstr string.
+ if (Memc[formatstr] == EOS) {
+ call ph_oformatstr (getid, ncols, Memc[formatstr], SZ_LINE)
+ } else if (ph_ofields (Memc[formatstr]) != ncols) {
+ call eprintf ("Warning: The number of formatstr string fields ")
+ call eprintf ("does not match the number of output columns\n")
+ call ph_oformatstr (getid, ncols, Memc[formatstr], SZ_LINE)
+ }
+
+ # If catalog matching is enabled, read in the catalog data.
+ if (matchid == YES) {
+ stdlist = fntopnb (Memc[catalogs], NO)
+ call io_gcatdat (Memc[catdir], stdlist, stdtable, nstd, dummy)
+ call fntclsb (stdlist)
+ }
+
+ # Loop over the observation files.
+ obslist = fntopnb (Memc[observations], NO)
+ while (fntgfnb (obslist, Memc[input], SZ_FNAME) != EOF) {
+
+ # Open the input file.
+ iferr (ifd = open (Memc[input], READ_ONLY, TEXT_FILE)) {
+ call erract (EA_WARN)
+ next
+ }
+
+ # Get observations and names for program stars. The call
+ # to io_getline_init() is necessary since it's not called
+ # inside io_gobs(), and it should be called at least once
+ # per input file.
+
+ call io_getline_init()
+ while (io_gobs (ifd, stdtable, omap, type, Memr[vars], nvars,
+ getid, Memc[starname], Memc[dummyname], SZ_LINE) != EOF) {
+
+ # Print the star name.
+ call fprintf (ofd, Memc[formatstr])
+ if (getid == YES)
+ call pargstr (Memc[starname])
+
+ # Print the extra variables.
+ do i = 1, len_plist {
+ pindex = Memi[pcols+i-1]
+ if (pindex > 0)
+ pval = Memr[vars+pindex-1]
+ else
+ pval = pr_eval (Memi[psym+i-1], Memr[vars],
+ Memr[MEMP[params]])
+ call pargr (pval)
+ }
+
+ # Loop over all the transformatstrion equations.
+ do i = 1, pr_geti (NTRNEQS) {
+
+ # Get the equation symbol.
+ sym = pr_gsym (i, PTY_TRNEQ)
+
+ # Compute the fit.
+ fit = pr_eval (Memi[fsym+i-1], Memr[vars],
+ Memr[MEMP[params+i-1]])
+ call pargr (fit)
+
+ # Compute the error.
+ if (etype != ERR_UNDEFINED) {
+ if (IS_INDEFR(fit))
+ errval = INDEFR
+ switch (etype) {
+ case ERR_OBSERRORS:
+ if (IS_INDEFR(fit))
+ errval = INDEFR
+ else
+ errval = ph_erval (Memi[fsym+i-1], fit,
+ Memr[MEMP[params+i-1]], Memr[vars],
+ Memi[uservars], Memi[usererrs], nobsvars)
+ case ERR_EQUATIONS:
+ if (Memi[esym+i-1] == NULL)
+ errval = INDEFR
+ else
+ errval = pr_eval (Memi[esym+i-1], Memr[vars],
+ Memr[MEMP[params+i-1]])
+ default:
+ errval = INDEFR
+ }
+ call pargr (errval)
+ }
+
+ # Compute the residual.
+ if (getid == NO || (matchid == YES &&
+ type != TYPE_PROGRAM)) {
+ if (IS_INDEFR (fit))
+ resid = INDEFR
+ else {
+ ref = pr_eval (Memi[rsym+i-1], Memr[vars],
+ Memr[MEMP[params+i-1]])
+ if (IS_INDEFR(ref))
+ resid = INDEFR
+ else
+ resid = ref - fit
+ }
+ call pargr (resid)
+ }
+ }
+ }
+
+ # Close the input file.
+ call close (ifd)
+ }
+
+ # Free memory.
+ call sfree (sp)
+ call pr_free()
+ call pr_unmap (cmap)
+ call pr_unmap (omap)
+
+ # Close all files.
+ if (stdtable != NULL)
+ call stclose (stdtable)
+ call close (ofd)
+ call fntclsb (obslist)
+end
+
+
+# PH_HEADER - Print the output file header.
+
+int procedure ph_header (fd, observations, catalogs, config, paramfile, type,
+ getid, psym, pcols, len_plist, etype, matchid)
+
+int fd # output file descriptor
+char observations[ARB] # observation file list
+char catalogs[ARB] # catalog file list
+char config[ARB] # configuration file name
+char paramfile[ARB] # fitted parameters file
+int type # type of object to output
+int getid # output the object id
+int psym[ARB] # list of additional variables to be output
+int pcols[ARB] # columns numbers of additional variables
+int len_plist # length of symbol list
+int etype # type of error output
+int matchid # is it possible to match ids
+
+int i, olist, slist, ncols
+pointer sp, time, name
+int fntopnb(), fntgfnb(), pr_geti(), pr_gsym()
+long clktime()
+pointer pr_gsymc(), pr_gsymp(), pr_xgetname()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (time, SZ_LINE, TY_CHAR)
+ call salloc (name, SZ_FNAME, TY_CHAR)
+
+ # Add the time stamp.
+ call cnvtime (clktime (0), Memc[time], SZ_LINE)
+ call fprintf (fd, "\n# %s\n")
+ call pargstr (Memc[time])
+
+ # Add the observation file names.
+ olist = fntopnb (observations, NO)
+ call fprintf (fd, "# List of observations files:\n")
+ while (fntgfnb (olist, Memc[name], SZ_FNAME) != EOF) {
+ call fprintf (fd, "#\t\t%s\n")
+ call pargstr (Memc[name])
+ }
+ call fntclsb (olist)
+
+ # Add the catalog file names.
+ if (matchid == YES) {
+ slist = fntopnb (catalogs, NO)
+ call fprintf (fd, "# List of catalog files:\n")
+ while (fntgfnb (slist, Memc[name], SZ_FNAME) != EOF) {
+ call fprintf (fd, "#\t\t%s\n")
+ call pargstr (Memc[name])
+ }
+ call fntclsb (slist)
+ }
+
+ # Add the configuration file name.
+ call fprintf (fd, "# Config:\t%s\n")
+ call pargstr (config)
+
+ # Add the parameters file name.
+ call fprintf (fd, "# Parameters:\t%s\n")
+ call pargstr (paramfile)
+
+ # Add the output options.
+ call fprintf (fd, "#\n")
+ if (matchid == YES) {
+ if (type == TYPE_ALL)
+ call fprintf (fd,
+ "# Computed indices for program and standard objects\n")
+ else if (type == TYPE_PROGRAM)
+ call fprintf (fd,
+ "# Computed indices for program objects only\n")
+ else if (type == TYPE_STANDARDS)
+ call fprintf (fd,
+ "# Computed indices for standard objects only\n")
+ } else
+ call fprintf (fd,
+ "# Computed indices for program and standard objects\n")
+
+ # Print the optional id header.
+ call fprintf (fd, "#\n")
+ call fprintf (fd, "# Columns:\n")
+ if (getid == YES) {
+ call fprintf (fd, "#\t1\tobject id\n")
+ ncols = 1
+ } else
+ ncols = 0
+
+ # Print headers for the variables in the print list and set any set
+ # equation offsets to pointers.
+ do i = 1, len_plist {
+ ncols = ncols + 1
+ call fprintf (fd, "#\t%d\t%s\n")
+ call pargi (ncols)
+ call pargstr (Memc[pr_xgetname(psym[i])])
+ if (pcols[i] <= 0)
+ psym[i] = pr_gsymp (psym[i], PSEQRPNEQ)
+ }
+
+
+ # Print the equation headers.
+ do i = 1, pr_geti (NTRNEQS) {
+ ncols = ncols + 1
+ call fprintf (fd, "#\t%d\t%s\n")
+ call pargi (ncols)
+ call pargstr (Memc[pr_gsymc(pr_gsym (i,PTY_TRNEQ),PTEQREF)])
+ if (etype != ERR_UNDEFINED) {
+ ncols = ncols + 1
+ call fprintf (fd, "#\t%d\terror(%s)\n")
+ call pargi (ncols)
+ call pargstr (Memc[pr_gsymc(pr_gsym (i,PTY_TRNEQ),PTEQREF)])
+ }
+ if (getid == NO || (matchid == YES && type != TYPE_PROGRAM)) {
+ ncols = ncols + 1
+ call fprintf (fd, "#\t%d\tresid(%s)\n")
+ call pargi (ncols)
+ call pargstr (Memc[pr_gsymc (pr_gsym(i,PTY_TRNEQ),PTEQREF)])
+ }
+ }
+
+ call fprintf (fd,"\n\n")
+
+ call sfree (sp)
+
+ return (ncols)
+end
diff --git a/noao/digiphot/photcal/evaluate/t_invertfit.x b/noao/digiphot/photcal/evaluate/t_invertfit.x
new file mode 100644
index 00000000..532d7f08
--- /dev/null
+++ b/noao/digiphot/photcal/evaluate/t_invertfit.x
@@ -0,0 +1,792 @@
+include <error.h>
+include <math/nlfit.h>
+include "../lib/io.h"
+include "../lib/parser.h"
+include "../lib/preval.h"
+
+# Define the pointer Mem
+define MEMP Memi
+
+# T_INVERTFIT - INVERTFIT converts intrumental photometric indices into
+# standard indices by using the configuration file, the coefficients
+# determined by FITPARAMS and inverting the transformations.
+
+procedure t_invertfit ()
+
+pointer observations # pointer to the observations file list
+pointer catalogs # pointer to the catalogs file list
+pointer config # pointer to configuration file name
+pointer paramfile # pointer to fitted parameters file name
+pointer calibfile # pointer to the output file name
+int type # type of output to be processed
+int etype # algorithm for computing the errors
+pointer print # pointer to output variables list
+pointer formatstr # pointer to the output format string
+pointer catdir # pointer to the standard star directory
+
+int i, j, vcol, ecol, pindex, dummy, stat, getid, matchid
+int obslist, stdlist, plist, ofd, ifd, sym, symvar, ncols, nstd, nset
+int ntrneqs, nparams, nstdvars, nustdvars, nobsvars, nvars, nueq, maxnset
+int len_plist, refcode
+pointer sp, input, starname, dummyname, stdtable, omap, cmap
+pointer vars, eqvartable, uservars, usererrs, userset, eqset, tvars
+pointer dtvars, avtvars, ervars, svars, servars, params, errors, psym, pcols
+pointer varindex, eqindex
+real resid, chisqr, rms, pval
+
+bool clgetb()
+int fntopnb(), fntgfnb(), clgwrd(), open(), io_gcoeffs(), io_gobs()
+int pr_parse(), pr_geti(), pr_gsym(), pr_gsymi(), pr_gvari(), ph_objcheck()
+int ph_invert(), pr_findmap1(), ph_iereqn(), ph_ierval(), ph_seteqn()
+int ph_mkplist(), fntlenb(), ph_ofields(), ph_iheader(), ph_setvar()
+pointer pr_xgetname(), pr_gsymp()
+real pr_eval()
+errchk io_gcoeffs()
+
+begin
+ # Allocate space for file names and character strings.
+
+ call smark (sp)
+ call salloc (observations, SZ_LINE, TY_CHAR)
+ call salloc (catalogs, SZ_LINE, TY_CHAR)
+ call salloc (config, SZ_FNAME, TY_CHAR)
+ call salloc (paramfile, SZ_FNAME, TY_CHAR)
+ call salloc (calibfile, SZ_FNAME, TY_CHAR)
+ call salloc (input, SZ_FNAME, TY_CHAR)
+ call salloc (starname, SZ_LINE, TY_CHAR)
+ call salloc (dummyname, SZ_LINE, TY_CHAR)
+ call salloc (print, SZ_LINE, TY_CHAR)
+ call salloc (formatstr, SZ_LINE, TY_CHAR)
+ call salloc (catdir, SZ_FNAME, TY_CHAR)
+
+ # Get the observations list, the catalog list, the configuration
+ # file, the parameters file, and the output file names.
+
+ call clgstr ("observations", Memc[observations], SZ_LINE)
+ call clgstr ("config", Memc[config], SZ_FNAME)
+ call clgstr ("parameters", Memc[paramfile], SZ_FNAME)
+ call clgstr ("calib", Memc[calibfile], SZ_FNAME)
+ call clgstr ("catalogs", Memc[catalogs], SZ_LINE)
+ call clgstr ("catdir", Memc[catdir], SZ_LINE)
+
+ # Get the output type flags.
+
+ etype = clgwrd ("errors", Memc[dummyname], SZ_LINE, ERR_OPTIONS)
+ type = clgwrd ("objects", Memc[dummyname], SZ_LINE, TYPE_STRING)
+ call clgstr ("print", Memc[print], SZ_LINE)
+ call clgstr ("format", Memc[formatstr], SZ_LINE)
+
+ # Open the output file.
+
+ iferr {
+ if (clgetb ("append"))
+ ofd = open (Memc[calibfile], APPEND, TEXT_FILE)
+ else
+ ofd = open (Memc[calibfile], NEW_FILE, TEXT_FILE)
+ } then {
+ call erract (EA_WARN)
+ call sfree (sp)
+ return
+ }
+
+ # Parse the configuration file.
+
+ if (pr_parse (Memc[config]) == ERR) {
+ call eprintf ("Error: Cannot parse the configuration file\n")
+ call close (ofd)
+ call sfree (sp)
+ return
+ }
+
+ # Fetch the total number of observed and catalog variables and
+ # the total number of equations in the configuration file.
+
+ nobsvars = pr_geti (NOBSVARS)
+ nstdvars = pr_geti (NCATVARS)
+ nvars = nobsvars + nstdvars
+ ntrneqs = pr_geti (NTRNEQS)
+
+ # Map observations file and catalog file columns.
+
+ call pr_catmap (cmap, dummy)
+ call pr_obsmap (omap, dummy)
+
+ # Check which catalog and observations variables are actually
+ # used in the equations to be inverted and determine whether the
+ # system of equations can actually be inverted. This step is the
+ # first pass through the system of equations. A second pass is
+ # necessary to deal with the set equations. Use this first pass
+ # to fetch the fitted parameters for the equations.
+
+ call salloc (eqvartable, nstdvars * ntrneqs, TY_INT)
+ call aclri (Memi[eqvartable], nstdvars * ntrneqs)
+ call salloc (uservars, nstdvars, TY_INT)
+ call aclri (Memi[uservars], nstdvars)
+ call salloc (usererrs, nobsvars, TY_INT)
+ call aclri (Memi[usererrs], nobsvars)
+ call salloc (params, ntrneqs, TY_POINTER)
+ call salloc (errors, ntrneqs, TY_POINTER)
+
+ do i = 1, ntrneqs {
+
+ # Get the equation symbol.
+ sym = pr_gsym (i, PTY_TRNEQ)
+
+ # Get the reference equation symbol.
+ refcode = pr_gsymp (sym, PTEQRPNREF)
+
+ # Quit if there are catalog variables in the function expression
+ # or if there are set equations containing references to the
+ # catalog variables in the reference equation.
+
+ if ((pr_gsymi (sym, PTEQNRCAT) > 0) || (ph_seteqn (refcode) ==
+ YES)) {
+ call eprintf ("Error: Cannot invert equations with catalog ")
+ call eprintf ("variables in the function expression\n")
+ call pr_unmap (cmap)
+ call pr_unmap (omap)
+ call close (ofd)
+ call sfree (sp)
+ return
+ }
+
+ # Determine which catalog and observational variables were
+ # actually used in the reference equations and which have
+ # defined error columns.
+
+ do j = 1, pr_gsymi (sym, PTEQNRCAT) + pr_gsymi(sym, PTEQNROBS) {
+ symvar = pr_gvari (sym, j, PTEQREFVAR)
+ vcol = pr_gsymi (symvar, PINPCOL)
+ ecol = pr_gsymi (symvar, PINPERRCOL)
+ if (pr_gsymi (symvar, PSYMTYPE) == PTY_CATVAR) {
+ vcol = pr_findmap1 (cmap, vcol)
+ Memi[eqvartable+(i-1)*nstdvars+vcol-1] = vcol + nobsvars
+ Memi[uservars+vcol-1] = vcol + nobsvars
+ } else {
+ vcol = pr_findmap1 (omap, vcol)
+ if (! IS_INDEFI(ecol))
+ ecol = pr_findmap1 (omap, ecol)
+ if (! IS_INDEFI(ecol))
+ Memi[usererrs+vcol-1] = ecol
+ }
+ }
+
+ # Determine which catalog and observational variables were
+ # actually used in the fit equations and which have
+ # defined error columns.
+
+ do j = 1, pr_gsymi (sym, PTEQNFCAT) + pr_gsymi(sym, PTEQNFOBS) {
+ symvar = pr_gvari (sym, j, PTEQFITVAR)
+ vcol = pr_gsymi (symvar, PINPCOL)
+ ecol = pr_gsymi (symvar, PINPERRCOL)
+ if (pr_gsymi (symvar, PSYMTYPE) == PTY_CATVAR) {
+ vcol = pr_findmap1 (cmap, vcol)
+ Memi[eqvartable+(i-1)*nstdvars+vcol-1] = vcol + nobsvars
+ Memi[uservars+vcol-1] = vcol + nobsvars
+ } else {
+ vcol = pr_findmap1 (omap, vcol)
+ if (! IS_INDEFI(ecol))
+ ecol = pr_findmap1 (omap, ecol)
+ if (! IS_INDEFI(ecol))
+ Memi[usererrs+vcol-1] = ecol
+ }
+ }
+
+ # Get the number of parameters for the equation.
+ # Allocate space for parameter values and errors, for the
+ # current equation, and read them from the coefficient file.
+
+ nparams = pr_gsymi (sym, PTEQNPAR)
+ call salloc (MEMP[params+i-1], nparams, TY_REAL)
+ call salloc (MEMP[errors+i-1], nparams, TY_REAL)
+ iferr {
+ if (io_gcoeffs (Memc[paramfile], sym, stat, chisqr, rms,
+ Memr[MEMP[params+i-1]], Memr[MEMP[errors+i-1]], nparams) !=
+ nparams) {
+ call eprintf ("Warning: Error reading parameters for ")
+ call eprintf ("equation %s from %s\n")
+ call pargstr (Memc[pr_xgetname(sym)])
+ call pargstr (Memc[paramfile])
+ call amovkr (INDEFR, Memr[MEMP[params+i-1]], nparams)
+ call amovkr (INDEFR, Memr[MEMP[errors+i-1]], nparams)
+ }
+ } then {
+ call erract (EA_WARN)
+ call close (ofd)
+ call pr_unmap (cmap)
+ call pr_unmap (omap)
+ call pr_free()
+ call sfree (sp)
+ return
+ }
+
+ # Issue a warning if any of the equations in the system to be
+ # inverted did not converge but proceed with the fit.
+
+ if (stat != DONE) {
+ call eprintf (
+ "Warning: The solution for equation %s did not converge")
+ call pargstr (Memc[pr_xgetname(sym)])
+ }
+
+ }
+
+ # Count the number of catalog variables used in the transformation
+ # equations.
+
+ nustdvars = 0
+ do i = 1, nstdvars {
+ if (Memi[uservars+i-1] != 0)
+ nustdvars = nustdvars + 1
+ }
+
+ # If the number of equations is less than the number of referenced
+ # catalog variables it is not possible to invert the transformation
+ # equations.
+
+ if (nustdvars > ntrneqs) {
+ call eprintf ("Error: The number of equations is less than ")
+ call eprintf ("the number of unknowns\n")
+ call close (ofd)
+ call pr_unmap (cmap)
+ call pr_unmap (omap)
+ call pr_free()
+ call sfree (sp)
+ return
+ }
+
+ # Loop over the transformation equations a second time searching for
+ # references to the set equations in the fit expressions. If a set
+ # equation reference is found, check to see whether it contains any
+ # reference to a catalog variable which is not referenced elsewhere
+ # in the transformation equations. Recompute the number of catalog
+ # variables used in the fit equations.
+
+ maxnset = max (1, pr_geti (NSETEQS))
+ call salloc (eqset, maxnset * ntrneqs, TY_INT)
+ call aclri (Memi[eqset], maxnset * ntrneqs)
+ nset = 0
+ if (pr_geti (NSETEQS) > 0) {
+
+ # Find the number of independent set equations.
+ call salloc (userset, pr_geti (NSETEQS), TY_INT)
+ call amovki (NULL, Memi[userset], pr_geti (NSETEQS))
+ do i = 1, ntrneqs {
+ sym = pr_gsym (i, PTY_TRNEQ)
+ nset = nset + ph_setvar (i, sym, cmap, omap, Memi[eqvartable],
+ Memi[uservars], Memi[usererrs], nstdvars, nobsvars,
+ Memi[eqset], pr_geti (NSETEQS), Memi[userset], nset)
+ }
+
+ # Is the system invertable?
+ if ((nustdvars + nset) > ntrneqs) {
+ call eprintf ("Error: The number of equations is less than ")
+ call eprintf ("the number of unknowns\n")
+ call close (ofd)
+ call pr_unmap (cmap)
+ call pr_unmap (omap)
+ call pr_free()
+ call sfree (sp)
+ return
+ }
+
+ # Recompute the number of independent catalog variables.
+ nustdvars = 0
+ do i = 1, nstdvars {
+ if (Memi[uservars+i-1] != 0)
+ nustdvars = nustdvars + 1
+ }
+
+ }
+
+
+ # Decide whether to use id/catalog matching or not. If id matching
+ # is enabled fetch the catalog data.
+
+ if (pr_geti (MINCOL) <= 1) {
+ getid = NO
+ matchid = NO
+ stdtable = NULL
+ } else if (Memc[catalogs] == EOS) {
+ getid = YES
+ matchid = NO
+ stdtable = NULL
+ } else {
+ getid = YES
+ matchid = YES
+ stdtable = NULL
+ }
+
+ # Get the list of optional variables to be printed. These variables
+ # may include any of the catalog or observations variables or the
+ # set equations. Variables which do not match any of these categories
+ # will be ommitted from the list to be printed.
+
+ plist = fntopnb (Memc[print], NO)
+ len_plist = fntlenb (plist)
+ if (len_plist > 0) {
+ call salloc (psym, len_plist, TY_INT)
+ call salloc (pcols, len_plist, TY_INT)
+ len_plist = ph_mkplist (plist, cmap, omap, nobsvars, Memi[psym],
+ Memi[pcols], len_plist)
+
+ }
+ call fntclsb (plist)
+
+ # Print the output header.
+ ncols = ph_iheader (ofd, Memc[observations], Memc[catalogs],
+ Memc[config], Memc[paramfile], type, getid, Memi[psym],
+ Memi[pcols], len_plist, Memi[uservars], nstdvars,
+ Memi[userset], nset, etype, matchid)
+
+ # Set the format string.
+ if (Memc[formatstr] == EOS) {
+ call ph_oformatstr (getid, ncols, Memc[formatstr], SZ_LINE)
+ } else if (ph_ofields (Memc[formatstr]) != ncols) {
+ call eprintf ("Warning: The number of format string fields ")
+ call eprintf ("does not match the number of output columns\n")
+ call ph_oformatstr (getid, ncols, Memc[formatstr], SZ_LINE)
+ }
+
+ # Read in the catalog data.
+ if (matchid == YES) {
+ stdlist = fntopnb (Memc[catalogs], NO)
+ call io_gcatdat (Memc[catdir], stdlist, stdtable, nstd, dummy)
+ call fntclsb (stdlist)
+ }
+
+ # Compute the initial values for the catalog variables and initial
+ # values for the delta-variable estimates. If a catalog is present
+ # the initial value of each catalog variable is the average value of
+ # that variable in the catalog. The standard deviation of the catalog
+ # variables is used as the initial value for the catalog variable
+ # increments.
+
+ call salloc (avtvars, nstdvars, TY_REAL)
+ call salloc (dtvars, nstdvars, TY_REAL)
+ call ph_avstdvars (stdtable, Memi[uservars], Memr[avtvars],
+ Memr[dtvars], nstdvars)
+
+ # Allocated space for the catalog variables and the fitted variables
+ # and their errors.
+ call salloc (vars, nvars, TY_REAL)
+ call salloc (tvars, nvars, TY_REAL)
+ if (nset > 0)
+ call salloc (svars, nset, TY_REAL)
+ call salloc (ervars, nstdvars, TY_REAL)
+ if (nset > 0)
+ call salloc (servars, nset, TY_REAL)
+ call salloc (varindex, nstdvars, TY_INT)
+ call salloc (eqindex, ntrneqs, TY_INT)
+
+ # Initialize the fit inversion code.
+ call ph_ivinit (nstdvars, nustdvars, ntrneqs)
+
+ # Loop over the observations files.
+ obslist = fntopnb (Memc[observations], NO)
+ while (fntgfnb (obslist, Memc[input], SZ_FNAME) != EOF) {
+
+ # Open the input file.
+ iferr (ifd = open (Memc[input], READ_ONLY, TEXT_FILE)) {
+ call erract (EA_WARN)
+ next
+ }
+
+ # Get observations and names for program stars. The call
+ # to io_getline_init() is necessary since it's not called
+ # inside io_gobs(), and it should be called at least once
+ # per input file.
+
+ call io_getline_init()
+ while (io_gobs (ifd, stdtable, omap, type, Memr[vars], nvars,
+ getid, Memc[starname], Memc[dummyname], SZ_LINE) != EOF) {
+
+ # Print star name.
+ call fprintf (ofd, Memc[formatstr])
+ if (getid == YES)
+ call pargstr (Memc[starname])
+ #call eprintf ("name=%s\n")
+ #call pargstr (Memc[starname])
+
+ # Print the extra variables.
+ do i = 1, len_plist {
+ pindex = Memi[pcols+i-1]
+ if (pindex > 0)
+ pval = Memr[vars+pindex-1]
+ else
+ pval = pr_eval (Memi[psym+i-1], Memr[vars],
+ Memr[MEMP[params]])
+ call pargr (pval)
+ }
+
+ # Initialize the fit.
+ call amovr (Memr[vars], Memr[tvars], nobsvars)
+ call amovr (Memr[avtvars], Memr[tvars+nobsvars], nstdvars)
+
+ # Invert the transformations and compute the errors.
+ if (ph_objcheck (MEMP[params], Memr[tvars], Memi[eqvartable],
+ nstdvars, ntrneqs, Memi[eqset], maxnset,
+ Memi[varindex], nustdvars, Memi[eqindex],
+ nueq) == ERR) {
+ call amovkr (INDEFR, Memr[tvars+nobsvars], nstdvars)
+ if (nset > 0)
+ call amovkr (INDEFR, Memr[svars], nset)
+ call amovkr (INDEFR, Memr[ervars], nstdvars)
+ if (nset > 0)
+ call amovkr (INDEFR, Memr[servars], nset)
+
+ } else if (ph_invert (MEMP[params], Memr[tvars], nobsvars,
+ Memr[dtvars], Memi[varindex], nstdvars,
+ nustdvars, Memi[eqindex], nueq) == ERR) {
+
+ call amovkr (INDEFR, Memr[tvars+nobsvars], nstdvars)
+ if (nset > 0)
+ call amovkr (INDEFR, Memr[svars], nset)
+ call amovkr (INDEFR, Memr[ervars], nstdvars)
+ if (nset > 0)
+ call amovkr (INDEFR, Memr[servars], nset)
+
+ } else {
+
+ # Set any unfitted variables to INDEF.
+ do i = nobsvars + 1, nvars {
+ if (Memi[varindex+i-nobsvars-1] == 0)
+ Memr[tvars+i-1] = INDEFR
+ }
+
+ # Evaluate the set equations.
+ if (nset > 0) {
+ do i = 1, nset
+ Memr[svars+i-1] = pr_eval (Memi[userset+i-1],
+ Memr[tvars], Memr[MEMP[params+i-1]])
+ }
+
+ # Evaluate the errors.
+ switch (etype) {
+ case ERR_UNDEFINED:
+ call amovkr (INDEFR, Memr[ervars], nstdvars)
+ if (nset > 0)
+ call amovkr (INDEFR, Memr[servars], nset)
+ case ERR_EQUATIONS:
+ if (ph_iereqn (MEMP[params], Memr[tvars], nobsvars,
+ Memr[dtvars], Memi[varindex], Memr[ervars],
+ nstdvars, Memi[userset], Memr[svars],
+ Memr[servars], nset, nustdvars, Memi[eqindex],
+ nueq) <= 0) {
+ call amovkr (INDEFR, Memr[ervars], nstdvars)
+ if (nset > 0)
+ call amovkr (INDEFR, Memr[servars], nset)
+ }
+ case ERR_OBSERRORS:
+ if (ph_ierval (MEMP[params], Memr[tvars],
+ Memi[usererrs], nobsvars, Memr[dtvars],
+ Memi[varindex], Memr[ervars], nstdvars,
+ Memi[userset], Memr[svars], Memr[servars], nset,
+ nustdvars, Memi[eqindex], nueq) <= 0) {
+ call amovkr (INDEFR, Memr[ervars], nstdvars)
+ if (nset > 0)
+ call amovkr (INDEFR, Memr[servars], nset)
+ }
+ default:
+ call amovkr (INDEFR, Memr[ervars], nstdvars)
+ }
+ }
+
+ # Write out the standard indices, errors and residuals.
+ do i = nobsvars + 1, nvars {
+
+ # Skip catalog variables not used in the equation.
+ if (Memi[uservars+i-nobsvars-1] <= 0)
+ next
+
+ call pargr (Memr[tvars+i-1])
+ if (etype != ERR_UNDEFINED) {
+ if (IS_INDEFR(Memr[tvars+i-1]))
+ call pargr (INDEFR)
+ else
+ call pargr (Memr[ervars+i-nobsvars-1])
+ }
+
+ # Compute the residual of the fit.
+ if (getid == NO || (matchid == YES &&
+ type != TYPE_PROGRAM)) {
+ if (IS_INDEFR (Memr[vars+i-1]) ||
+ IS_INDEFR (Memr[tvars+i-1]))
+ resid = INDEFR
+ else
+ resid = Memr[vars+i-1] - Memr[tvars+i-1]
+ call pargr (resid)
+ }
+ }
+
+ # Write out the set equations.
+ do i = 1, nset {
+
+ # Write out the set equation.
+ call pargr (Memr[svars+i-1])
+
+ # Evaluate the error. This is tricky at the moment.
+ if (etype != ERR_UNDEFINED) {
+ if (IS_INDEFR(Memr[svars+i-1]))
+ call pargr (INDEFR)
+ else
+ call pargr (Memr[servars+i-1])
+ }
+
+ # Compute the residual of the fit.
+ if (getid == NO || (matchid == YES &&
+ type != TYPE_PROGRAM)) {
+ resid = pr_eval (Memi[userset+i-1], Memr[vars],
+ Memr[MEMP[params+i-1]])
+ if (IS_INDEFR (Memr[svars+i-1]) || IS_INDEFR (resid))
+ resid = INDEFR
+ else
+ resid = resid - Memr[svars+i-1]
+ call pargr (resid)
+ }
+ }
+ }
+
+ # Close the input file.
+ call close (ifd)
+ }
+
+ # Free memory.
+ call sfree (sp)
+ call ph_ivfree()
+ call pr_free()
+ call pr_unmap (cmap)
+ call pr_unmap (omap)
+
+ # Close all the files.
+ if (stdtable != NULL)
+ call stclose (stdtable)
+ call close (ofd)
+ call fntclsb (obslist)
+end
+
+
+# PH_IHEADER - Print the output file header.
+
+int procedure ph_iheader (fd, observations, catalogs, config, paramfile, type,
+ getid, psym, pcols, len_plist, catvars, ncatvars, userset, nset,
+ etype, matchid)
+
+int fd # output file descriptor
+char observations[ARB] # the list of observations files
+char catalogs[ARB] # the list of catalog files
+char config[ARB] # the configuration file name
+char paramfile[ARB] # the fitted parameters file
+int type # the type of object to output
+int getid # output the object id ?
+int psym[ARB] # list of additional symbols to be printed
+int pcols[ARB] # column numbers of additional output variables
+int len_plist # length of symbol list
+int catvars[ARB] # the list of active catalog variables
+int ncatvars # number of catalog variables
+int userset[ARB] # list of set equations included in fit
+int nset # number of set equations
+int etype # type of error output
+int matchid # is it possible to match ids ?
+
+int i, olist, slist, ncols
+pointer sp, time, name, sym
+int fntopnb(), fntgfnb(), pr_gsym()
+long clktime()
+pointer pr_xgetname(), pr_gsymp()
+
+begin
+ # Allocate some working space.
+ call smark (sp)
+ call salloc (time, SZ_LINE, TY_CHAR)
+ call salloc (name, SZ_FNAME, TY_CHAR)
+
+ # Add the time stamp.
+ call cnvtime (clktime (0), Memc[time], SZ_LINE)
+ call fprintf (fd, "\n# %s\n")
+ call pargstr (Memc[time])
+
+ # Add the observation file names.
+ olist = fntopnb (observations, NO)
+ call fprintf (fd, "# List of observations files:\n")
+ while (fntgfnb (olist, Memc[name], SZ_FNAME) != EOF) {
+ call fprintf (fd, "#\t\t%s\n")
+ call pargstr (Memc[name])
+ }
+ call fntclsb (olist)
+
+ # Add the catalog file names.
+ if (matchid == YES) {
+ slist = fntopnb (catalogs, NO)
+ call fprintf (fd, "# Number of catalog files:\n")
+ while (fntgfnb (slist, Memc[name], SZ_FNAME) != EOF) {
+ call fprintf (fd, "#\t\t%s\n")
+ call pargstr (Memc[name])
+ }
+ call fntclsb (slist)
+ }
+
+ # Add the configuration file name.
+ call fprintf (fd, "# Config:\t%s\n")
+ call pargstr (config)
+
+ # Add the parameters file name.
+ call fprintf (fd, "# Parameters:\t%s\n")
+ call pargstr (paramfile)
+
+ # Write the output options.
+ call fprintf (fd, "#\n")
+ if (matchid == YES) {
+ if (type == TYPE_ALL)
+ call fprintf (fd,
+ "# Computed indices for program and standard objects\n")
+ else if (type == TYPE_PROGRAM)
+ call fprintf (fd,
+ "# Computed indices for program objects only\n")
+ else if (type == TYPE_STANDARDS)
+ call fprintf (fd,
+ "# Computed indices for standard objects only\n")
+ } else
+ call fprintf (fd,
+ "# Computed indices for program and standard objects\n")
+
+ # Print the optional id header
+ call fprintf (fd, "#\n")
+ call fprintf (fd, "# Columns: \n")
+ if (getid == YES) {
+ call fprintf (fd, "#\t1\tobject id\n")
+ ncols = 1
+ } else
+ ncols = 0
+
+ # Print headers for the variables in the print list and set any set
+ # equation offsets to pointers.
+ do i = 1, len_plist {
+ ncols = ncols + 1
+ call fprintf (fd, "#\t%d\t%s\n")
+ call pargi (ncols)
+ call pargstr (Memc[pr_xgetname(psym[i])])
+ if (pcols[i] <= 0)
+ psym[i] = pr_gsymp (psym[i], PSEQRPNEQ)
+ }
+
+ # Print the catalog variables headers.
+ do i = 1, ncatvars {
+ if (catvars[i] <= 0)
+ next
+ sym = pr_gsym (i, PTY_CATVAR)
+ ncols = ncols + 1
+ call fprintf (fd, "#\t%d\t%s\n")
+ call pargi (ncols)
+ call pargstr (Memc[pr_xgetname(sym)])
+ if (etype != ERR_UNDEFINED) {
+ ncols = ncols + 1
+ call fprintf (fd, "#\t%d\terror(%s)\n")
+ call pargi (ncols)
+ call pargstr (Memc[pr_xgetname(sym)])
+ }
+ if (getid == NO || (matchid == YES && type != TYPE_PROGRAM)) {
+ ncols = ncols + 1
+ call fprintf (fd, "#\t%d\tresid(%s)\n")
+ call pargi (ncols)
+ call pargstr (Memc[pr_xgetname(sym)])
+ }
+ }
+
+ # Print the set equation variables headers.
+ do i = 1, nset {
+ ncols = ncols + 1
+ call fprintf (fd, "#\t%d\t%s\n")
+ call pargi (ncols)
+ call pargstr (Memc[pr_xgetname(userset[i])])
+ if (etype != ERR_UNDEFINED) {
+ ncols = ncols + 1
+ call fprintf (fd, "#\t%d\terror(%s)\n")
+ call pargi (ncols)
+ call pargstr (Memc[pr_xgetname(userset[i])])
+ }
+ if (getid == NO || (matchid == YES && type != TYPE_PROGRAM)) {
+ ncols = ncols + 1
+ call fprintf (fd, "#\t%d\tresid(%s)\n")
+ call pargi (ncols)
+ call pargstr (Memc[pr_xgetname(userset[i])])
+ }
+ userset[i] = pr_gsymp (userset[i], PSEQRPNEQ)
+ }
+
+ call fprintf (fd, "\n\n")
+
+ call sfree (sp)
+
+ return (ncols)
+end
+
+
+# PH_AVSTDVARS -- Compute the mean and sigma of the variables in the
+# standard table to use as initial guesses for the math routines.
+# If the standard catalog is undefined or empty the mean values of the
+# variables are set to 0.0 and the sigmas are set to 1.0. If there is only
+# one catalog value the sigma is also set to 1.0.
+
+procedure ph_avstdvars (stable, index, avg, sigma, npts)
+
+pointer stable # pointer to the symbol table
+int index[ARB] # index of active catalog variables
+real avg[ARB] # the output array of averages
+real sigma[ARB] # the output array of standard deviations
+int npts # number of points
+
+int i, ndata
+pointer sym, sp, n
+real data
+pointer sthead(), stnext()
+
+begin
+ # Initialize and return if the standard table is undefined.
+ call amovkr (0.0, avg, npts)
+ if (stable == NULL) {
+ call amovkr (0.1, sigma, npts)
+ return
+ }
+
+ # Allocate some temporary space and intialize the accumulators.
+ call smark (sp)
+ call salloc (n, npts, TY_INT)
+ call aclri (Memi[n], npts)
+ call aclrr (sigma, npts)
+
+ # Read the symbol table and accumlate the sums.
+ sym = sthead (stable)
+ while (sym != NULL) {
+ do i = 1, npts {
+ if (index[i] == 0)
+ next
+ data = Memr[P2R(sym+i-1)]
+ if (IS_INDEFR(data))
+ next
+ avg[i] = avg[i] + data
+ sigma[i] = sigma[i] + data ** 2
+ Memi[n+i-1] = Memi[n+i-1] + 1
+ }
+ sym = stnext (stable, sym)
+ }
+
+ # Compute the averages.
+ do i = 1, npts {
+ ndata = Memi[n+i-1]
+ if (ndata == 0)
+ sigma[i] = 0.1
+ else if (ndata == 1)
+ sigma[i] = 0.1
+ else {
+ avg[i] = avg[i] / ndata
+ sigma[i] = (sigma[i] - avg[i] * avg[i] * ndata) / (ndata - 1)
+ if (sigma[i] <= 0.0)
+ sigma[i] = 0.1
+ else
+ sigma[i] = min (0.1, sqrt (sigma[i]))
+ }
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/photcal/fitparams.par b/noao/digiphot/photcal/fitparams.par
new file mode 100644
index 00000000..dea63cfd
--- /dev/null
+++ b/noao/digiphot/photcal/fitparams.par
@@ -0,0 +1,22 @@
+# The FITPARAMS parameter file
+
+observations,f,a,"",,,List of observations files
+catalogs,f,a,"",,,List of standard catalog files
+config,f,a,"",,,Configuration file
+parameters,f,a,"",,,Output parameters file
+weighting,s,h,"uniform","|uniform|photometric|equations|",,"Weighting type (uniform,photometric,equations)"
+addscatter,b,h,yes,,,Add a scatter term to the weights ?
+tolerance,r,h,3.0e-5,0.0,,Fit convergence tolerance
+maxiter,i,h,15,4,,Maximum number of fit iterations
+nreject,i,h,0,0,,Number of rejection iterations
+low_reject,r,h,3.0,0.0,,Low sigma rejection factor
+high_reject,r,h,3.0,0.0,,High sigma rejection factor
+grow,r,h,0.0,0.0,,Rejection growing radius
+interactive,b,h,yes,,,Solve fit interactively ?
+logfile,f,h,"STDOUT",,,Output log file
+log_unmatched,b,h,yes,,,Log any unmatched stars ?
+log_fit,b,h,no,,,Log the fit parameters and statistics ?
+log_results,b,h,no,,,Log the results ?
+catdir,s,h,")_.catdir",,,The standard star catalog directory
+graphics,s,h,"stdgraph",,,Output graphics device
+cursor,*gcur,h,"",,,Graphics cursor input
diff --git a/noao/digiphot/photcal/fitparams/README b/noao/digiphot/photcal/fitparams/README
new file mode 100644
index 00000000..26c7617b
--- /dev/null
+++ b/noao/digiphot/photcal/fitparams/README
@@ -0,0 +1,2 @@
+This subdirectory contains the code for the task FITCOEFFS which computes
+the coefficients of a user-defined fitting function.
diff --git a/noao/digiphot/photcal/fitparams/fteval.com b/noao/digiphot/photcal/fitparams/fteval.com
new file mode 100644
index 00000000..bba04823
--- /dev/null
+++ b/noao/digiphot/photcal/fitparams/fteval.com
@@ -0,0 +1,8 @@
+# Fitting function and derivatives evaluation common
+
+pointer eqcode # equation code
+pointer dercode # equation derivative codes
+pointer xpcode # x plotting equation code
+pointer ypcode # y plotting equation code
+
+common /ftevalcom/ eqcode, dercode, xpcode, ypcode
diff --git a/noao/digiphot/photcal/fitparams/fteval.x b/noao/digiphot/photcal/fitparams/fteval.x
new file mode 100644
index 00000000..cde0ff6a
--- /dev/null
+++ b/noao/digiphot/photcal/fitparams/fteval.x
@@ -0,0 +1,221 @@
+.help fteval
+Fit evaluation procedures.
+
+These procedures are called by the (I)NLFIT package to compute the fitting
+function, its derivatives at different points, and the plotting equations
+for all points.
+Pointers to the previous equation codes are stored in the evaluator common
+to speed up computations, since they are accessed for every data point.
+A buffer is allocated to store the derivative code pointers, since the
+number of derivatives is variable for each equation.
+.sp
+Code pointers are copied into the evaluator common by ft_evinit(). This
+procedure also allocates space for the derivative code pointers, before
+copying them. Space is freed by ft_evfree(). The fitting function is
+evaluated for a single point with ft_func(), derivatives are evaluated
+for a single point with ft_dfunc(), and the plot equations are evaluated
+for all points with ft_plot(). Plot equations are computed for each
+axis separately (two calls).
+
+Entry points:
+
+.nf
+
+ ft_evinit (sym, npars) Initialize fit
+ ft_evfree () Free space allocated
+ ft_func (x, nvars, p, npars, z) Fitting function called
+ ft_dfunc (x, nvars, p, dp, npars, z, der) Derivatives of fit func.
+ ft_plot (number, p, npars, x, y, z, npts, nvars) Plotting functions
+.fi
+.endhelp
+
+include <error.h>
+include "../lib/parser.h"
+
+# Pointer Mem
+define MEMP Memi
+
+
+# FT_EVINIT - Initialize fit by copying fitting function, its derivative,
+# and plotting function codes into the fit common.
+
+procedure ft_evinit (sym, npars)
+
+pointer sym # equation symbol
+int npars # number of parameters
+
+int np # parameter counter
+#bool clgetb()
+pointer pr_gsymp(), pr_gderp()
+
+include "fteval.com"
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.fitcode")) {
+ #call eprintf ("ft_evinit: (sym=%d) (npars=%d)\n")
+ #call pargi (sym)
+ #call pargi (npars)
+ #}
+
+ # Set fitting function code.
+ eqcode = pr_gsymp (sym, PTEQRPNFIT)
+ if (eqcode == NULL)
+ call error (0, "ft_evinit: Null function equation code")
+
+ # Allocate space for derivative code pointers, and copy them
+ # from the symbol table. This is to avoid an unnecessary
+ # overhead during the derivative evaluations.
+
+ call malloc (dercode, npars, TY_POINTER)
+ do np = 1, npars {
+ MEMP[dercode + np - 1] = pr_gderp (sym, np, PTEQRPNDER)
+ #if (MEMP[dercode + np - 1] == NULL)
+ #call error (0, "ft_evinit: Null derivative equation code")
+ }
+
+ # Set plotting equation codes. They could be null.
+ xpcode = pr_gsymp (sym, PTEQRPNXPLOT)
+ ypcode = pr_gsymp (sym, PTEQRPNYPLOT)
+
+ # Debug ?
+ #if (clgetb ("debug.fitcode")) {
+ #call eprintf ("ft_evinit: (eqcode=%d) ")
+ #call pargi (eqcode)
+ #do np = 1, npars {
+ #call eprintf (" (dercode%d=%d)")
+ #call pargi (np)
+ #call pargi (MEMP[dercode + np - 1])
+ #}
+ #call eprintf (" (xpcode=%d) (ypcode=%d)\n")
+ #call pargi (xpcode)
+ #call pargi (ypcode)
+ #}
+end
+
+
+# FT_EVFREE - Free space used in the fit common.
+
+procedure ft_evfree ()
+
+include "fteval.com"
+
+#bool clgetb()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.fitcode")) {
+ #call eprintf (
+ #"ft_evfree: (eqcode=%d) (dercode=%d) (xpcode=%d) (ypcode=%d)\n")
+ #call pargi (eqcode)
+ #call pargi (dercode)
+ #call pargi (xpcode)
+ #call pargi (ypcode)
+ #}
+
+ # Clear code pointers.
+ eqcode = NULL
+ xpcode = NULL
+ ypcode = NULL
+
+ # Free derivative buffer.
+ call mfree (dercode, TY_POINTER)
+end
+
+
+# FT_FUNC - Evaluate fitting function. This function must conform in
+# number and type of arguments to the requirements of the nlfit/inlfit
+# packages even though some arguments are not used in this case.
+
+procedure ft_func (x, nvars, p, npars, z)
+
+real x[ARB] # independent values
+int nvars # number of variables
+real p[ARB] # parameter values
+int npars # number of parameters
+real z # function value (output)
+
+include "fteval.com"
+
+real pr_eval()
+
+begin
+ # Evaluate the function value.
+ z = pr_eval (eqcode, x, p)
+end
+
+
+# FT_DFUNC - Evaluate fitting function, and derivatives of the fitting
+# function with respect to all the parameters. This function must conform in
+# number and type of arguments to the requirements of the nlfit/inlfit
+# packages even though some arguments are not used in this case.
+
+procedure ft_dfunc (x, nvars, p, dp, npars, z, der)
+
+real x[ARB] # independent values
+int nvars # number of variables
+real p[ARB] # parameter values
+real dp[ARB] # parameter derivatives
+int npars # number of parameters
+real z # function value (output)
+real der[ARB] # derivative values (output)
+
+int i
+pointer code
+real pi, zplus, zminus
+real pr_eval()
+
+include "fteval.com"
+
+begin
+ # Evaluate the function value.
+ z = pr_eval (eqcode, x, p)
+
+ # Evaluate each one of the derivatives.
+ do i = 1, npars {
+ code = MEMP[dercode+i-1]
+ if (code != NULL)
+ der[i] = pr_eval (code, x, p)
+ else {
+ pi = p[i]
+ p[i] = pi + 0.5 * dp[i]
+ zplus = pr_eval (eqcode, x, p)
+ p[i] = pi - 0.5 * dp[i]
+ zminus = pr_eval (eqcode, x, p)
+ der[i] = (zplus - zminus) / dp[i]
+ p[i] = pi
+ }
+ }
+end
+
+
+# FT_PLOT - Evaluate plot function(s) for all points.
+
+procedure ft_plot (number, p, npars, x, y, z, npts, nvars)
+
+int number # plot number
+real p[npars] # parameter values
+int npars # number of parameters (not used)
+real x[ARB] # independent values
+real y[npts] # dependent values (not used)
+real z[npts] # function values (output)
+int npts # number of points
+int nvars # number of variables
+
+int i
+pointer code
+real pr_eval()
+
+include "fteval.com"
+
+begin
+ # Determine plot equation to evaluate.
+ if (number == 1)
+ code = xpcode
+ else
+ code = ypcode
+
+ # Iterate over input points.
+ do i = 1, npts
+ z[i] = pr_eval (code, x[(i-1)*nvars+1], p)
+end
diff --git a/noao/digiphot/photcal/fitparams/ftindef.x b/noao/digiphot/photcal/fitparams/ftindef.x
new file mode 100644
index 00000000..943b82fd
--- /dev/null
+++ b/noao/digiphot/photcal/fitparams/ftindef.x
@@ -0,0 +1,184 @@
+include <error.h>
+include "../lib/fitparams.h"
+include "../lib/parser.h"
+
+
+# FT_INDEF - Set zero weight for all undefined input data.
+
+procedure ft_indef (sym, otable, rtable, wtable)
+
+int sym # equation symbol
+pointer otable # 2d observation table (modified)
+pointer rtable # 1d reference table (modified)
+pointer wtable # 1d weight table (modified)
+
+#bool clgetb()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.fitcode")) {
+ #call eprintf (
+ #"ft_indef: (sym=%d) (otable=%d) (rtable=%d) (wtable=%d)\n")
+ #call pargi (sym)
+ #call pargi (otable)
+ #call pargi (rtable)
+ #call pargi (wtable)
+ #}
+
+ # Check for INDEF values in reference table.
+ call ft_indefr (rtable, wtable)
+
+ # Check for INDEF values in fitting equation.
+ call ft_indefo (sym, otable, wtable)
+end
+
+
+# FT_INDEFR - Check reference table for INDEF values. If an INDEF value is
+# found, its corresponding weight (in the weight table) is set to zero, and
+# the INDEF value (in the refence table) replaced by a more suitable one.
+# The latter is because the INLFIT package does not handle INDEF values at
+# all, and it's better to feed it with reasonable values to avoid an overflow
+# or underflow condition.
+
+procedure ft_indefr (rtable, wtable)
+
+pointer rtable # reference table
+pointer wtable # weight table (modified)
+
+int npts # number of points
+int n
+real rval, replace
+
+#bool clgetb()
+int mct_nrows()
+real mct_getr()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.fitcode")) {
+ #call eprintf ("ft_indefr: (rtable=%d) (wtable=%d)\n")
+ #call pargi (rtable)
+ #call pargi (wtable)
+ #}
+
+ # Get the number of points.
+ npts = mct_nrows (rtable)
+
+ # Initialize replace value to first non-INDEF value,
+ # if any. Otherwise set it t zero.
+ replace = 0.0
+ do n = 1, npts {
+ rval = mct_getr (rtable, n, 1)
+ if (!IS_INDEFR (rval)) {
+ replace = rval
+ break
+ }
+ }
+
+ # Loop over all data in the table.
+ do n = 1, npts {
+
+ # Replace values if is INDEF. Otherwise just
+ # update the replace value.
+ rval = mct_getr (rtable, n, 1)
+ if (IS_INDEFR (rval)) {
+ call mct_putr (wtable, n, 1, 0.0)
+ call mct_putr (rtable, n, 1, replace)
+ } else
+ replace = rval
+ }
+
+ # Debug ?
+ #call dg_dweights ("from ft_indefr", wtable)
+ #call dg_dref ("from ft_indefr", rtable)
+end
+
+
+# FT_INDEFO - Check fitting equation for INDEF values. If an INDEF value is
+# found, its corresponding weight (in the weight table) is set to zero.
+# Undefined values in the table are set to more suitable values, so there
+# won't be problems when plotting data.
+
+procedure ft_indefo (sym, otable, wtable)
+
+int sym # equation symbol
+pointer otable # observation table (modified)
+pointer wtable # weight table (modified)
+
+int i, n
+int npts # number of points
+int nvars # number of variables
+real rval
+pointer code # fitting equation code
+pointer parval # parameter values
+pointer replace # replace values
+pointer sp
+
+#bool clgetb()
+int mct_nrows(), mct_maxcol()
+real mct_getr()
+real pr_eval()
+pointer mct_getrow()
+pointer pr_gsymp()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.fitcode")) {
+ #call eprintf ("ft_indef: (sym=%d) (otable=%d) (wtable=%d)\n")
+ #call pargi (sym)
+ #call pargi (otable)
+ #call pargi (wtable)
+ #}
+
+ # Get the number of variables and points.
+ npts = mct_nrows (otable)
+ nvars = mct_maxcol (otable)
+
+ # Allocate space for replace values.
+ call smark (sp)
+ call salloc (replace, nvars, TY_REAL)
+
+ # Initialize replace values to first non-undefined
+ # value, if any. Otherwise set it t zero.
+ call aclrr (Memr[replace], nvars)
+ do i = 1, nvars {
+ do n = 1, npts {
+ rval = mct_getr (otable, n, i)
+ if (!IS_INDEFR (rval)) {
+ Memr[replace + i - 1] = rval
+ break
+ }
+ }
+ }
+
+ # Get the parameter values, and equation code.
+ parval = pr_gsymp (sym, PTEQSPARVAL)
+ code = pr_gsymp (sym, PTEQRPNFIT)
+
+ # Iterate over all the observations.
+ do n = 1, npts {
+
+ # Evaluate fitting equation.
+ rval = pr_eval (code, Memr[mct_getrow (otable, n)], Memr[parval])
+
+ # Substitute weight.
+ if (IS_INDEFR (rval))
+ call mct_putr (wtable, n, 1, 0.0)
+
+ # Substitude undefined variable values.
+ do i = 1, nvars {
+ rval = mct_getr (otable, n, i)
+ if (IS_INDEFR (rval))
+ call mct_putr (otable, n, i, Memr[replace + i - 1])
+ else
+ Memr[replace + i - 1] = rval
+ }
+ }
+
+ # Free memory.
+ call sfree (sp)
+
+ # Debug ?
+ #call dg_dweights ("from ft_indefo", wtable)
+ #call dg_dcatobs ("from ft_indefo", otable)
+end
diff --git a/noao/digiphot/photcal/fitparams/ftref.x b/noao/digiphot/photcal/fitparams/ftref.x
new file mode 100644
index 00000000..0fab41c4
--- /dev/null
+++ b/noao/digiphot/photcal/fitparams/ftref.x
@@ -0,0 +1,50 @@
+include <error.h>
+include "../lib/parser.h"
+
+
+# FT_RFEVAL - Evaluate reference equation (left hand side) for all observations
+# and store them into a one column table, called the reference table (rtable).
+
+procedure ft_rfeval (code, otable, rtable)
+
+pointer code # equation code
+pointer otable # 2d observation table
+pointer rtable # 1d reference table (output)
+
+int n
+real rval
+real dummy[1]
+
+#bool clgetb()
+int mct_nrows()
+real pr_eval()
+pointer mct_getrow()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.fitcode")) {
+ #call eprintf ("ft_rfeval (code=%d) (otable=%d)\n")
+ #call pargi (code)
+ #call pargi (otable)
+ #}
+
+ # Allocate space for reference table.
+ # call mct_alloc (rtable, mct_nrows (otable), 1, TY_REAL)
+
+ # Loop over all data in the table.
+ do n = 1, mct_nrows (otable) {
+
+ # Evaluate the equation.
+ iferr (rval = pr_eval (code, Memr[mct_getrow (otable, n)], dummy)) {
+ call eprintf ("ft_ref (%d)\n")
+ call pargi (n)
+ call erract (EA_ERROR)
+ }
+
+ # Put data into reference table.
+ call mct_putr (rtable, n, 1, rval)
+ }
+
+ # Debug ?
+ #call dg_dref ("from ft_rfeval", rtable)
+end
diff --git a/noao/digiphot/photcal/fitparams/fttrneq.x b/noao/digiphot/photcal/fitparams/fttrneq.x
new file mode 100644
index 00000000..6cfb092a
--- /dev/null
+++ b/noao/digiphot/photcal/fitparams/fttrneq.x
@@ -0,0 +1,541 @@
+include <error.h>
+include <pkg/xtanswer.h>
+include <pkg/gtools.h>
+include <math/nlfit.h>
+include <pkg/inlfit.h>
+include "../lib/parser.h"
+include "../lib/fitparams.h"
+
+# Interactive commands
+
+define CMD_OPTIONS "|first|last|prev|next|again|go|quit|"
+define CMD_FIRST 1
+define CMD_LAST 2
+define CMD_PREV 3
+define CMD_NEXT 4
+define CMD_AGAIN 5
+define CMD_GO 6
+define CMD_QUIT 7
+define CMD_MIN CMD_FIRST
+define CMD_MAX CMD_QUIT
+
+# Prompt to save fit results into output file and equation structure
+
+define SAVE_PROMPT "Do you want to save fit results ?"
+define QUIT_PROMPT "Program will quit. Do you really want to do so ?"
+
+# Program labels
+
+define retry 9999
+
+
+# FT_TRNEQS - Fit all the transformation equations.
+
+procedure ft_trneqs (output, logfile, graphics, otable, ntable, wtflag,
+ addscatter, tol, itmax, interactive, high, low, niterate, grow,
+ log_fit, log_results)
+
+char output[ARB] # output file name
+char logfile[ARB] # the log file name
+char graphics[ARB] # graphics output device
+pointer otable # standard observation table
+pointer ntable # standard name table
+int wtflag # the type of weighting
+int addscatter # add a scatter term to the weights
+real tol # fit tolerance
+int itmax # max number of iterations
+bool interactive # interactive fit ?
+real high, low # rejection factors
+int niterate # number of rejection iterations
+real grow # rejection growing radius
+bool log_fit # log the fit statistics
+bool log_results # log the fit results
+
+int cmd, neq, maxeq, nobs, sym
+pointer rtable, wtable, totable, gp, gt
+
+#bool clgetb()
+int mct_nrows(), pr_gsym(), pr_geti(), ft_trnanswer()
+pointer gopen(), gt_init(), pr_gsymp()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.fitcode")) {
+ #call eprintf ("ft_trneqs (output=%s) (graphics=%s) (ot=%d) "
+ #call pargstr (output)
+ #call pargstr (graphics)
+ #call pargi (otable)
+ #call eprintf ("(tol=%g) (maxiter=%d) (int=%b)\n")
+ #call pargr (tol)
+ #call pargi (itmax)
+ #call pargb (interactive)
+ #call eprintf ("ft_trneqs (gp=%d) (gt=%d) (high=%g) (lo=%g) ")
+ #call pargi (gp)
+ #call pargi (gt)
+ #call pargr (high)
+ #call pargr (low)
+ #call eprintf ("(niter=%d) (grow=%g)\n")
+ #call pargi (niterate)
+ #call pargr (grow)
+ #}
+
+ # Get number of observations.
+ nobs = mct_nrows (otable)
+
+ # Allocate space for reference and weight tables. These tables
+ # store the values of the reference equation for all observations,
+ # and the weight for each of them, respectively.
+
+ totable = NULL
+ call mct_alloc (rtable, nobs, 1, TY_REAL)
+ call mct_alloc (wtable, nobs, 1, TY_REAL)
+
+ # Open graphics.
+
+ if (interactive) {
+ gp = gopen (graphics, NEW_FILE, STDGRAPH)
+ gt = gt_init()
+ } else {
+ gp = NULL
+ gt = NULL
+ }
+
+ # Loop over transformation equations, until the user
+ # sends a quit command.
+
+ neq = 1
+ cmd = CMD_NEXT
+ maxeq = pr_geti (NTRNEQS)
+ repeat {
+
+ # Get the equation symbol.
+
+ sym = pr_gsym (neq, PTY_TRNEQ)
+
+ # Evaluate the reference equation for catalog
+ # observations and store them into a table.
+
+ call ft_rfeval (pr_gsymp (sym, PTEQRPNREF), otable, rtable)
+
+ # Evaluate weights for the current equation. If an error
+ # condition is raised (due to a negative weight value) the
+ # program continues with the next equation in the list.
+
+ switch (wtflag) {
+ case FWT_UNIFORM:
+ call ft_wtuniform (otable, wtable)
+
+ case FWT_PHOTOMETRIC:
+ iferr (call ft_wtphoterrs (sym, otable, wtable)) {
+ call erract (EA_WARN)
+ next
+ }
+ case FWT_EQUATIONS:
+ iferr (call ft_wteqns (sym, otable, wtable)) {
+ call erract (EA_WARN)
+ next
+ }
+ default:
+ call ft_wtuniform (otable, wtable)
+ }
+
+ # Save original observations, and check for undefined values.
+
+ call mct_copy (otable, totable)
+ call ft_indef (sym, totable, rtable, wtable)
+
+ # Fit transformation equation.
+
+ call ft_trneq (output, logfile, sym, totable, wtable, rtable,
+ ntable, wtflag, addscatter, tol, itmax, interactive, gp, gt,
+ high, low, niterate, grow, log_fit, log_results)
+
+ # Reset the reference table.
+
+ call mct_reset (rtable)
+
+retry
+ # Prompt the user for command.
+ if (interactive)
+ call ft_trncmd (cmd)
+ else
+ cmd = CMD_NEXT
+
+ # Branch on command.
+ switch (cmd) {
+ case CMD_FIRST:
+ neq = 1
+ case CMD_LAST:
+ neq = maxeq
+ case CMD_PREV:
+ if (neq > 1)
+ neq = neq - 1
+ else
+ goto retry
+ case CMD_NEXT:
+ neq = neq + 1
+ case CMD_AGAIN:
+ ;
+ case CMD_GO:
+ interactive = false
+ neq = neq + 1
+ case CMD_QUIT:
+ if (ft_trnanswer (QUIT_PROMPT, YES) == YES)
+ break
+ default:
+ call error (0, "fttrneqs: Unknown command")
+ }
+
+ # Prompt to quit.
+ if (neq > maxeq) {
+ if (interactive && cmd != CMD_GO) {
+ if (ft_trnanswer (QUIT_PROMPT, YES) == NO) {
+ neq = maxeq
+ goto retry
+ } else
+ break
+ } else
+ break
+ }
+ }
+
+ # Close graphics.
+ if (gp != NULL)
+ call gclose (gp)
+ if (gt != NULL)
+ call gt_free (gt)
+
+ # Free tables.
+ call mct_free (rtable)
+ call mct_free (wtable)
+ call mct_free (totable)
+end
+
+
+# FT_TRNEQ - Fit single transformation equation.
+
+procedure ft_trneq (output, logfile, sym, otable, wtable, rtable, ntable,
+ wtflag, addscatter, tol, itmax, interactive, gp, gt high, low,
+ niterate, grow, log_fit, log_results)
+
+char output[ARB] # output file name
+char logfile[ARB] # log file name
+int sym # transformation equation symbol
+pointer otable # standard observation table
+pointer wtable # weight table
+pointer rtable # reference equation table
+pointer ntable # names table
+int wtflag # type of weighting
+int addscatter # add a scatter term to the weight equation
+real tol # fit tolerance
+int itmax # max number of iterations
+bool interactive # interactive fit ?
+pointer gp, gt # GIO and GTOOLS descriptors
+real high, low # rejection factors
+int niterate # number of rejection iterations
+real grow # rejection growing radius
+bool log_fit # log the fit statistics
+bool log_results # log the fit results
+
+int nobs, nvars, nparams, nfparams, len_name
+int i, stat, answer, psym, nlwtflag
+pointer sp, params, dparams, name, aux, plist, nl, in
+real chisqr, variance, scatter, rms
+
+#bool clgetb()
+bool streq()
+int locpr(), mct_nrows(), mct_maxcol(), pr_geti(), pr_gsym(), pr_gsymi()
+int pr_gpari(), ft_trnanswer()
+pointer pr_xgetname(), pr_gsymp(), pr_gsymc(), mct_getbuf(), in_getp()
+real pr_gsymr()
+extern ft_func(), ft_dfunc(), ft_plot()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.fitcode")) {
+ #call eprintf ("ft_trneq (output=%s) (sym=%d) (ot=%d) (wt=%d) "
+ #call pargstr (output)
+ #call pargi (sym)
+ #call pargi (otable)
+ #call pargi (wtable)
+ #call eprintf ("(rt=%d) (tol=%g) (maxiter=%d)\n")
+ #call pargi (rtable)
+ #call pargr (tol)
+ #call pargi (itmax)
+ #call eprintf ("ft_trneq (int=%b) (gp=%d) (gt=%d) (high=%g) "
+ #call pargb (interactive)
+ #call pargi (gp)
+ #call pargi (gt)
+ #call pargr (high)
+ #call eprintf ("(low=%g) (niter=%d) (grow=%g)\n")
+ #call pargr (low)
+ #call pargi (niterate)
+ #call pargr (grow)
+ #}
+
+ # Get number of observations, and variables for the observational data.
+
+ nobs = mct_nrows (otable)
+ nvars = mct_maxcol (otable)
+ len_name = mct_maxcol (ntable)
+
+ # Get number of parameters for the current equation.
+
+ nparams = pr_gsymi (sym, PTEQNPAR)
+
+ # Allocate stack space.
+ call smark (sp)
+ call salloc (aux, SZ_LINE, TY_CHAR)
+ call salloc (name, SZ_LINE, TY_CHAR)
+ call salloc (params, nparams, TY_REAL)
+ call salloc (dparams, nparams, TY_REAL)
+ call salloc (plist, nparams, TY_INT)
+
+ # Initialize parameters, errors, and parameter list.
+
+ call aclrr (Memr[params], nparams)
+ call aclrr (Memr[dparams], nparams)
+ do i = 1, nparams {
+ psym = pr_gpari (sym, i, PTEQPAR)
+ Memr[dparams+i-1] = pr_gsymr (psym, PFITDELTA)
+ }
+ call amovi (Memi[pr_gsymp (sym, PTEQSPLIST)], Memi[plist], nparams)
+
+ # Initialize the fit evaluation. This is necessary in order to
+ # set the equations called by the INLFIT procedures.
+
+ call ft_evinit (sym, nparams)
+
+ # Get number of fitting parameters for the current equation.
+ nfparams = pr_gsymi (sym, PTEQNFPAR)
+
+ # Initialize INLFIT.
+ call in_initr (in, locpr (ft_func), locpr (ft_dfunc),
+ Memr[pr_gsymp (sym, PTEQSPARVAL)], Memr[dparams],
+ nparams, Memi[plist], nfparams)
+
+ # Set INLFIT fitting parameters.
+ call in_putr (in, INLTOLERANCE, tol)
+ call in_puti (in, INLMAXITER, itmax)
+ call in_putr (in, INLHIGH, high)
+ call in_putr (in, INLLOW, low)
+ call in_puti (in, INLNREJECT, niterate)
+ call in_putr (in, INLGROW, grow)
+
+ # Put in the reference and fit equation names.
+ call sprintf (Memc[aux], SZ_LINE, "|%s|%s|")
+ call pargstr (Memc[pr_gsymc (sym, PTEQREF)])
+ call pargstr (Memc[pr_gsymc (sym, PTEQFIT)])
+ call in_pstr (in, INLFLABELS, Memc[aux])
+
+ # Put in the parameter names.
+ call strcpy ("|", Memc[aux], SZ_LINE)
+ do i = 1, nparams {
+ call strcat (Memc[pr_xgetname (pr_gpari (sym, i, PTEQPAR))],
+ Memc[aux], SZ_LINE)
+ call strcat ("|", Memc[aux], SZ_LINE)
+ }
+ call in_pstr (in, INLPLABELS, Memc[aux])
+
+ # Put in the variable names.
+ call strcpy ("|", Memc[aux], SZ_LINE)
+ do i = 1, pr_geti (NOBSVARS) {
+ call pr_vtran (Memc[pr_xgetname (pr_gsym (i, PTY_OBSVAR))],
+ Memc[name], SZ_LINE)
+ call strcat (Memc[name], Memc[aux], SZ_LINE)
+ call strcat ("|", Memc[aux], SZ_LINE)
+ }
+ do i = 1, pr_geti (NCATVARS) {
+ call pr_vtran (Memc[pr_xgetname (pr_gsym (i, PTY_CATVAR))],
+ Memc[name], SZ_LINE)
+ call strcat (Memc[name], Memc[aux], SZ_LINE)
+ call strcat ("|", Memc[aux], SZ_LINE)
+ }
+ call in_pstr (in, INLVLABELS, Memc[aux])
+
+ # Put plot equations and redefine graph keys, but only if
+ # both plot equations are defined. Otherwise leave the defaults.
+
+ if (pr_gsymp (sym, PTEQRPNXPLOT) != NULL &&
+ pr_gsymp (sym, PTEQRPNYPLOT) != NULL) {
+
+ # Put in the plot equation names.
+ call sprintf (Memc[aux], SZ_LINE, "|%s|%s|")
+ call pargstr (Memc[pr_gsymc (sym, PTEQXPLOT)])
+ call pargstr (Memc[pr_gsymc (sym, PTEQYPLOT)])
+ call in_pstr (in, INLUSERLABELS, Memc[aux])
+
+ # Put in the plot equation.
+ call in_puti (in, INLUAXES, locpr (ft_plot))
+
+ # Redefine the last graph key.
+ call in_puti (in, INLGKEY, INLNGKEYS)
+ call in_pkey (in, INLNGKEYS, 1, KEY_UAXIS, 1)
+ call in_pkey (in, INLNGKEYS, 2, KEY_UAXIS, 2)
+ }
+
+ # Call the appropiate version of fitting routine according to the
+ # value of the interactive flag.
+
+ if (wtflag == FWT_UNIFORM)
+ nlwtflag = WTS_USER
+ else if (addscatter == YES)
+ nlwtflag = WTS_SCATTER
+ else
+ nlwtflag = WTS_USER
+
+ if (interactive) {
+ call gt_setr (gt, GTXMIN, INDEFR)
+ call gt_setr (gt, GTXMAX, INDEFR)
+ call gt_setr (gt, GTYMIN, INDEFR)
+ call gt_setr (gt, GTYMAX, INDEFR)
+ call ing_fitr (in, gp, "cursor", gt, nl, Memr[mct_getbuf (otable)],
+ Memr[mct_getbuf (rtable)], Memr[mct_getbuf (wtable)],
+ Memc[mct_getbuf(ntable)], nobs, nvars, len_name, nlwtflag,
+ stat)
+ } else {
+ call in_fitr (in, nl, Memr[mct_getbuf (otable)],
+ Memr[mct_getbuf (rtable)], Memr[mct_getbuf (wtable)],
+ nobs, nvars, nlwtflag, stat)
+ }
+
+ # Decide whether to prompt the user for saving answer.
+ if (interactive)
+ answer = ft_trnanswer (SAVE_PROMPT, YES)
+ else
+ answer = YES
+
+ # Write the parameter values into output file.
+ if (answer == YES || answer == ALWAYSYES) {
+
+ # Get parameter values, and parameter list.
+ call nlpgetr (nl, Memr[params], nparams)
+ call amovi (Memi[in_getp (in, INLPLIST)], Memi[plist], nparams)
+
+ # Get the parameter errors.
+ call in_errorsr (in, nl, Memr[mct_getbuf (otable)],
+ Memr[mct_getbuf (rtable)], Memr[mct_getbuf (wtable)], nobs,
+ nvars, variance, chisqr, scatter, rms, Memr[dparams])
+
+ # Write parameters and errors into output file.
+ iferr (call io_pcoeffs (output, sym, stat, wtflag, variance, chisqr,
+ scatter, rms, Memr[params], Memr[dparams], Memi[plist],
+ nparams))
+ call erract (EA_WARN)
+
+ # Log the fit and results.
+ if (log_fit || log_results) {
+ if (interactive && streq (logfile, "STDOUT"))
+ call gdeactivate (gp, 0)
+ if (log_fit) {
+ iferr (call io_title (logfile, "#EQUATION:", sym))
+ ;
+ iferr (call ing_showr (in, logfile))
+ ;
+ iferr (call ing_errorsr (in, logfile, nl,
+ Memr[mct_getbuf(otable)], Memr[mct_getbuf(rtable)],
+ Memr[mct_getbuf(wtable)], nobs, nvars))
+ ;
+ }
+ if (log_results) {
+ iferr (call io_title (logfile, "#RESULTS:", sym))
+ ;
+ iferr (call ing_resultsr (in, logfile, nl,
+ Memr[mct_getbuf(otable)], Memr[mct_getbuf(rtable)],
+ Memr[mct_getbuf(wtable)], Memc[mct_getbuf(ntable)],
+ nobs, nvars, len_name))
+ ;
+ }
+ if (interactive && streq (logfile, "STDOUT"))
+ call greactivate (gp, 0)
+ }
+
+
+ # Update fitted parameter values into the equation symbol
+ # substructure if the fit was succesfull.
+ if (stat == DONE)
+ call amovr (Memr[params],
+ Memr[P2R(pr_gsymp (sym, PTEQSPARVAL))], nparams)
+ }
+
+ # Debug ?
+ #if (clgetb ("debug.nlfit"))
+ #call dg_inldump (in, nl)
+
+
+ # Free inlfit and nlfit descriptors.
+ call in_freer (in)
+ call nlfreer (nl)
+
+ # Free fit evaluation.
+ call ft_evfree ()
+
+ # Free stack space.
+ call sfree (sp)
+end
+
+
+# FT_TRNCMD -- Prompt the user for a command.
+
+procedure ft_trncmd (cmd)
+
+int cmd # command code
+
+char command[SZ_LINE]
+int scan(), strlen()
+int strdic(), io_strwrd()
+
+begin
+ # Get current command string.
+ if (io_strwrd (cmd, command, SZ_LINE, CMD_OPTIONS) == 0)
+ call error (0, "ft_trneqs: Unknown command")
+
+ # Keep prompting the user until there is a valid command.
+ repeat {
+
+ # Print current setting.
+ call printf ("Command (%s) (%s) : ")
+ call pargstr (CMD_OPTIONS)
+ call pargstr (command)
+ call flush (STDOUT)
+
+ # Get new command.
+ if (scan () == EOF)
+ command[1] = EOS
+ else
+ call gargstr (command, SZ_LINE)
+ if (strlen (command) == 0) {
+ if (io_strwrd (cmd, command, SZ_LINE, CMD_OPTIONS) <= 0)
+ ;
+ }
+
+ # Search for command in the dictionary.
+ cmd = strdic (command, command, SZ_LINE, CMD_OPTIONS)
+
+ # Test command.
+ if (cmd >= CMD_MIN && cmd <= CMD_MAX)
+ break
+ else
+ call printf ("\007")
+ }
+end
+
+
+# FT_TRNANSWER -- Get a YES/NO answer from the user, and return it
+# as the procedure value.
+
+int procedure ft_trnanswer (prompt, default)
+
+char prompt # prompt to the user
+int default # default answer
+
+int answer
+
+begin
+ answer = default
+ call xt_answer (prompt, answer)
+ if (answer == YES || answer == ALWAYSYES)
+ return (YES)
+ else
+ return (NO)
+end
diff --git a/noao/digiphot/photcal/fitparams/ftweights.x b/noao/digiphot/photcal/fitparams/ftweights.x
new file mode 100644
index 00000000..67482867
--- /dev/null
+++ b/noao/digiphot/photcal/fitparams/ftweights.x
@@ -0,0 +1,491 @@
+include "../lib/parser.h"
+include "../lib/preval.h"
+
+# FT_WTUNIFORM -- Set all the weights to 1.0.
+
+procedure ft_wtuniform (otable, wtable)
+
+pointer otable # observation table
+pointer wtable # weight table (output)
+
+int nobs
+int mct_nrows()
+
+begin
+ # Get number of observations.
+ nobs = mct_nrows (otable)
+
+ # Clear weight table with ones (uniform weighting), and enter
+ # data at the last observation set weight table counters.
+
+ call mct_clearr (wtable, 1.0)
+ call mct_putr (wtable, nobs, 1, 1.0)
+end
+
+
+# FT_WTEQNS -- Compute the value of the weights equation for each point.
+
+procedure ft_wteqns (sym, otable, wtable)
+
+int sym # equation symbol
+pointer otable # observation table
+pointer wtable # weight table (output)
+
+int n, nobs
+real wtval, minval, maxval
+pointer varptr, parptr
+pointer wtcode, mincode, maxcode
+
+#bool clgetb()
+int mct_nrows()
+pointer pr_gsymp(), mct_getrow()
+real pr_eval()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.fitcode"))
+ #call eprintf ("ft_wteval (sym=%d) (ot=%d) (wt=%d)\n") {
+ #call pargi (sym)
+ #call pargi (otable)
+ #call pargi (wtable)
+ #}
+
+ # Get number of observations.
+ nobs = mct_nrows (otable)
+
+ # Clear weight table with ones (uniform weighting), and enter
+ # data at the last observation set weight table counters.
+
+ call mct_clearr (wtable, 1.0)
+ call mct_putr (wtable, nobs, 1, 1.0)
+
+ # Compute weigths using the weight equation, if there is one defined.
+ wtcode = pr_gsymp (sym, PTEQRPNWEIGHT)
+ if (wtcode != NULL) {
+
+ # Get pointer to parameter values for the current equation.
+ parptr = pr_gsymp (sym, PTEQSPARVAL)
+
+ # Get minimum and maximum equation codes.
+ mincode = pr_gsymp (sym, PTEQRPNWTSMIN)
+ maxcode = pr_gsymp (sym, PTEQRPNWTSMAX)
+
+ # Iterate over all observations.
+ do n = 1, nobs {
+
+ # Get variable values for the current observation.
+ varptr = mct_getrow (otable, n)
+
+ # Compute weight value.
+ wtval = pr_eval (wtcode, Memr[varptr], Memr[parptr])
+ if (IS_INDEFR(wtval) || wtval < 0.0) {
+
+ call mct_putr (wtable, n, 1, 0.0)
+
+ } else {
+
+ # Check value against minimum.
+ if (mincode != NULL) {
+ minval = pr_eval (mincode, Memr[varptr], Memr[parptr])
+ if (! IS_INDEFR(minval) && minval >= 0.0)
+ wtval = min (wtval, minval)
+ }
+
+ # Check value against maximum.
+ if (maxcode != NULL) {
+ maxval = pr_eval (maxcode, Memr[varptr], Memr[parptr])
+ if (! IS_INDEFR(maxval) && maxval >= 0.0)
+ wtval = max (wtval, maxval)
+ }
+
+ # Enter value into weight table.
+ call mct_putr (wtable, n, 1, wtval)
+ }
+ }
+ }
+
+ # Debug ?
+ #call dg_dweigths ("from ft_wteval", wtable)
+end
+
+
+# FT_WTPHOTERRS -- Set all the weights to the correct statistical value assuming
+# that all the errors are in the photometric indices, that the errors are
+# independent, that the equations are linear in the photometric indices,
+# and that at least one of the observed or catalog variables in the equation
+# has a measured error.
+
+procedure ft_wtphoterrs (sym, otable, wtable)
+
+int sym # equation symbol
+pointer otable # observation table
+pointer wtable # weight table (output)
+
+double errval
+int n, i, nobs, nobsvars, ncatvars, nrvars, nfvars, nerrors, symvar, icol
+int itemp
+pointer omap, cmap, sp, rcount, rerrcol, fcount, ferrcol, refcode
+real val
+int mct_nrows(), pr_geti(), pr_gsymi(), pr_gvari(), pr_findmap1()
+int ft_seval()
+pointer pr_gsymp()
+#int mct_ncols()
+real mct_getr()
+errchk pr_gsymi()
+
+begin
+ # Get number of observations.
+ nobs = mct_nrows (otable)
+
+ # Clear weight table with ones (uniform weighting), and enter
+ # data at the last observation set weight table counters.
+
+ call mct_clearr (wtable, 1.0)
+ call mct_putr (wtable, nobs, 1, 1.0)
+
+ # Map the column numbers for the observed and catalog variables.
+ call pr_obsmap (omap, nobsvars)
+ call pr_catmap (cmap, ncatvars)
+
+ # Get the number of reference and fit equation variables.
+ nrvars = pr_gsymi (sym, PTEQNRCAT) + pr_gsymi (sym, PTEQNROBS)
+ nfvars = pr_gsymi (sym, PTEQNFCAT) + pr_gsymi (sym, PTEQNFOBS)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (rerrcol, nobsvars + ncatvars, TY_INT)
+ call amovi (NULL, Memi[rerrcol], nobsvars + ncatvars)
+ call salloc (rcount, nobsvars + ncatvars, TY_INT)
+ call aclri (Memi[rcount], nobsvars + ncatvars)
+ call salloc (ferrcol, nobsvars + ncatvars, TY_INT)
+ call amovi (NULL, Memi[ferrcol], nobsvars + ncatvars)
+ call salloc (fcount, nobsvars + ncatvars, TY_INT)
+ call aclri (Memi[fcount], nobsvars + ncatvars)
+
+ # Initialize.
+ nerrors = 0
+
+ # Compute the positions of the reference equation variable errors in
+ # the observations table.
+
+ do i = 1, nrvars {
+ Memi[rcount+i-1] = pr_gvari (sym, i, PTEQREFCNT)
+ symvar = pr_gvari (sym, i, PTEQREFVAR)
+ icol = pr_gsymi (symvar, PINPERRCOL)
+ if (IS_INDEFI(icol))
+ Memi[rerrcol+i-1] = NULL
+ else {
+ if (pr_gsymi (symvar, PSYMTYPE) == PTY_CATVAR)
+ Memi[rerrcol+i-1] = pr_findmap1 (cmap, icol) + nobsvars
+ else
+ Memi[rerrcol+i-1] = pr_findmap1 (omap, icol)
+ nerrors = nerrors + 1
+ }
+ }
+
+ # Evaluate the contribution of the set equations to the errors
+ # in the reference equation.
+
+ if (pr_geti (NSETEQS) > 0) {
+ refcode = pr_gsymp (sym, PTEQRPNREF)
+ itemp = ft_seval (refcode, cmap, omap, nobsvars,
+ Memi[rerrcol], Memi[rcount], nrvars)
+ nrvars = nrvars + itemp
+ nerrors = nerrors + itemp
+ }
+
+ # Compute the positions of the fit equation variable errors in the
+ # observations table.
+
+ do i = 1, nfvars {
+ Memi[fcount+i-1] = pr_gvari (sym, i, PTEQFITCNT)
+ symvar = pr_gvari (sym, i, PTEQFITVAR)
+ icol = pr_gsymi (symvar, PINPERRCOL)
+ if (IS_INDEFI(icol))
+ Memi[ferrcol+i-1] = NULL
+ else {
+ if (pr_gsymi (symvar, PSYMTYPE) == PTY_CATVAR)
+ Memi[ferrcol+i-1] = pr_findmap1 (cmap, icol) + nobsvars
+ else
+ Memi[ferrcol+i-1] = pr_findmap1 (omap, icol)
+ nerrors = nerrors + 1
+ }
+ }
+
+ # Evaluate the contribution of the set equations to the errors
+ # in the fit equation.
+
+ if (pr_geti (NSETEQS) > 0) {
+ refcode = pr_gsymp (sym, PTEQRPNFIT)
+ itemp = ft_seval (refcode, cmap, omap, nobsvars,
+ Memi[ferrcol], Memi[fcount], nfvars)
+ nfvars = nfvars + itemp
+ nerrors = nerrors + itemp
+ }
+
+ # Loop over the table rows.
+ if (nerrors > 0) {
+ do n = 1, nobs {
+
+ errval = 0.0d0
+
+ # Add contributions from the reference equation variables.
+ do i = 1, nrvars {
+ if (Memi[rerrcol+i-1] == NULL)
+ next
+ val = mct_getr (otable, n, Memi[rerrcol+i-1])
+ if (IS_INDEFR(val) || val < 0.0)
+ next
+ errval = errval + real (Memi[rcount+i-1]) * (val * val)
+ }
+
+ # Add contributions from the fitting equation variables.
+ do i = 1, nfvars {
+ if (Memi[ferrcol+i-1] == NULL)
+ next
+ val = mct_getr (otable, n, Memi[ferrcol+i-1])
+ if (IS_INDEFR(val) || val < 0.0)
+ next
+ errval = errval + real (Memi[fcount+i-1]) * (val * val)
+ }
+
+ # Check for negative and zero error values and enter value
+ # into weight table.
+ if (errval <= 0.0d0)
+ call mct_putr (wtable, n, 1, 0.0)
+ else
+ call mct_putr (wtable, n, 1, real (1.0d0 / errval))
+ }
+ }
+
+ call pr_unmap (cmap)
+ call pr_unmap (omap)
+
+ call sfree (sp)
+end
+
+
+# FT_SEVAL -- Locate any catalog and observations variables that are
+# defined in up to two levels of set equations.
+
+int procedure ft_seval (code, cmap, omap, nobsvars, errcol, ecount, nerrors)
+
+pointer code # the equation code
+pointer cmap # pointer to the catalog variable column map
+pointer omap # pointer to the observations variable column map
+int nobsvars # the number of observations variables
+int errcol[ARB] # the input/output error columns
+int ecount[ARB] # the input/output error column counts
+int nerrors # the previous number of errors
+
+int ip, ins, newerr
+pointer setcode
+int pr_gsym(), ft_scoeval()
+pointer pr_gsymp()
+
+begin
+ ip = 0
+ ins = Memi[code+ip]
+
+ newerr = 0
+ while (ins != PEV_EOC) {
+ switch (ins) {
+ case PEV_SETEQ:
+ ip = ip + 1
+ setcode = pr_gsymp (pr_gsym (Memi[code+ip], PTY_SETEQ),
+ PSEQRPNEQ)
+ newerr = newerr + ft_scoeval (setcode, cmap, omap, nobsvars,
+ errcol, ecount, nerrors + newerr)
+ case PEV_NUMBER, PEV_CATVAR, PEV_OBSVAR, PEV_PARAM:
+ ip = ip + 1
+ case PEV_EXTEQ, PEV_TRNEQ:
+ ip = ip + 1
+ default:
+ ;
+ }
+
+ ip = ip + 1
+ ins = Memi[code+ip]
+ }
+
+ return (newerr)
+end
+
+
+# FT_SCOEVAL -- Locate any catalog and observations variables as well as any
+# set equations that are defined in a previous set equation.
+
+int procedure ft_scoeval (code, cmap, omap, nobsvars, errcol, ecount, nerrors)
+
+pointer code # the equation code
+pointer cmap # pointer to the catalog variable column map
+pointer omap # pointer to the observations variable column map
+int nobsvars # the number of observations variables
+int errcol[ARB] # the input/output error columns
+int ecount[ARB] # the input/output error column counts
+int nerrors # the previous number of errors
+
+bool new
+int i, ip, ins, newerr, ecol
+pointer sym, setcode
+int pr_gsym(), pr_gsymi(), pr_findmap1(), ft_coeval()
+pointer pr_gsymp()
+
+begin
+ ip = 0
+ ins = Memi[code+ip]
+
+ newerr = 0
+ while (ins != PEV_EOC) {
+ switch (ins) {
+ case PEV_SETEQ:
+ ip = ip + 1
+ setcode = pr_gsymp (pr_gsym (Memi[code+ip], PTY_SETEQ),
+ PSEQRPNEQ)
+ newerr = newerr + ft_coeval (setcode, cmap, omap, nobsvars,
+ errcol, ecount, nerrors + newerr)
+ case PEV_CATVAR:
+ ip = ip + 1
+ sym = pr_gsym (Memi[code+ip] - nobsvars, PTY_CATVAR)
+ ecol = pr_gsymi (sym, PINPERRCOL)
+ if (! IS_INDEFI(ecol))
+ ecol = pr_findmap1 (cmap, ecol) + nobsvars
+ else
+ ecol = NULL
+ if (ecol != NULL) {
+ new = true
+ do i = 1, nerrors + newerr {
+ if (ecol != errcol[i])
+ next
+ new = false
+ ecount[i] = ecount[i] + 1
+ }
+ if (new) {
+ newerr = newerr + 1
+ errcol[nerrors+newerr] = ecol
+ ecount[nerrors+newerr] = 1
+ }
+ }
+ case PEV_OBSVAR:
+ ip = ip + 1
+ sym = pr_gsym (Memi[code+ip], PTY_OBSVAR)
+ ecol = pr_gsymi (sym, PINPERRCOL)
+ if (! IS_INDEFI(ecol))
+ ecol = pr_findmap1 (omap, ecol)
+ else
+ ecol = NULL
+ if (ecol != NULL) {
+ new = true
+ do i = 1, nerrors + newerr {
+ if (ecol != errcol[i])
+ next
+ new = false
+ ecount[i] = ecount[i] + 1
+ }
+ if (new) {
+ newerr = newerr + 1
+ errcol[nerrors+newerr] = ecol
+ ecount[nerrors+newerr] = 1
+ }
+ }
+ case PEV_NUMBER, PEV_PARAM:
+ ip = ip + 1
+ case PEV_EXTEQ, PEV_TRNEQ:
+ ip = ip + 1
+ default:
+ ;
+ }
+
+ ip = ip + 1
+ ins = Memi[code+ip]
+ }
+
+ return (newerr)
+end
+
+
+# FT_COEVAL -- Locate any catalog and observations variables that are defined i
+# a previous set equation.
+
+int procedure ft_coeval (code, cmap, omap, nobsvars, errcol, ecount, nerrors)
+
+pointer code # the equation code
+pointer cmap # pointer to the catalog variable column map
+pointer omap # pointer to the observations variable column map
+int nobsvars # the number of observations variables
+int errcol[ARB] # the input/output error columns
+int ecount[ARB] # the input/output error column counts
+int nerrors # the previous number of errors
+
+bool new
+int i, ip, ins, newerr, ecol
+pointer sym
+int pr_gsym(), pr_gsymi(), pr_findmap1()
+
+begin
+ ip = 0
+ ins = Memi[code+ip]
+
+ newerr = 0
+ while (ins != PEV_EOC) {
+ switch (ins) {
+ case PEV_SETEQ:
+ ip = ip + 1
+ case PEV_CATVAR:
+ ip = ip + 1
+ sym = pr_gsym (Memi[code+ip] - nobsvars, PTY_CATVAR)
+ ecol = pr_gsymi (sym, PINPERRCOL)
+ if (! IS_INDEFI(ecol))
+ ecol = pr_findmap1 (cmap, ecol) + nobsvars
+ else
+ ecol = NULL
+ if (ecol != NULL) {
+ new = true
+ do i = 1, nerrors + newerr {
+ if (ecol != errcol[i])
+ next
+ new = false
+ ecount[i] = ecount[i] + 1
+ }
+ if (new) {
+ newerr = newerr + 1
+ errcol[nerrors+newerr] = ecol
+ ecount[nerrors+newerr] = 1
+ }
+ }
+ case PEV_OBSVAR:
+ ip = ip + 1
+ sym = pr_gsym (Memi[code+ip], PTY_OBSVAR)
+ ecol = pr_gsymi (sym, PINPERRCOL)
+ if (! IS_INDEFI(ecol))
+ ecol = pr_findmap1 (omap, ecol)
+ else
+ ecol = NULL
+ if (ecol != NULL) {
+ new = true
+ do i = 1, nerrors + newerr {
+ if (ecol != errcol[i])
+ next
+ new = false
+ ecount[i] = ecount[i] + 1
+ }
+ if (new) {
+ newerr = newerr + 1
+ errcol[nerrors+newerr] = ecol
+ ecount[nerrors+newerr] = 1
+ }
+ }
+ case PEV_NUMBER, PEV_PARAM:
+ ip = ip + 1
+ case PEV_EXTEQ, PEV_TRNEQ:
+ ip = ip + 1
+ default:
+ ;
+ }
+
+ ip = ip + 1
+ ins = Memi[code+ip]
+ }
+
+ return (newerr)
+end
diff --git a/noao/digiphot/photcal/fitparams/mkpkg b/noao/digiphot/photcal/fitparams/mkpkg
new file mode 100644
index 00000000..c4681932
--- /dev/null
+++ b/noao/digiphot/photcal/fitparams/mkpkg
@@ -0,0 +1,16 @@
+# The MKPKG file for the FITPARAMS task.
+
+$checkout libpkg.a ../
+$update libpkg.a
+$checkin libpkg.a ../
+$exit
+
+libpkg.a:
+ fteval.x "../lib/parser.h" "fteval.com" <error.h>
+ ftindef.x "../lib/parser.h" "../lib/fitparams.h" <error.h>
+ ftref.x "../lib/parser.h" <error.h>
+ fttrneq.x <pkg/inlfit.h> <math/nlfit.h> <error.h> <pkg/gtools.h> \
+ <pkg/xtanswer.h> "../lib/parser.h" "../lib/fitparams.h"
+ ftweights.x "../lib/preval.h" "../lib/parser.h"
+ t_fitparams.x "../lib/parser.h" "../lib/fitparams.h"
+ ;
diff --git a/noao/digiphot/photcal/fitparams/t_fitparams.x b/noao/digiphot/photcal/fitparams/t_fitparams.x
new file mode 100644
index 00000000..d306124d
--- /dev/null
+++ b/noao/digiphot/photcal/fitparams/t_fitparams.x
@@ -0,0 +1,205 @@
+include "../lib/parser.h"
+include "../lib/fitparams.h"
+
+
+# T_FITPARAMS - Main fitting task. This task will determine the value of the
+# fitting parameters, either interactively or non-interactively, by using
+# the INLFIT package.
+
+procedure t_fitparams()
+
+pointer observations # list of observations files
+pointer catalogs # list of standard catalogs
+int stdlist # file list of standards
+pointer config # pointer to configuration file name
+pointer output # pointer to output file name
+pointer logfile # pointer to the output log file
+int wtflag # weighting type
+int addscatter # compute an additional scatter term
+real tol # fit tolerance
+int itmax # max number of iterations
+int niterate # number of rejection iterations
+real high, low # rejection thresholds
+real grow # rejection growing radius
+bool interactive # interactive fit ?
+pointer catdir # the standard catalogs directory
+pointer graphics # pointer to the graphics device name
+
+int obslist, nstd, nobs, nstdvars, getid
+pointer sp, dir, str, otable, ntable, stable
+
+bool clgetb()
+int fntopnb(), fntlenb(), clgeti(), clgwrd(), btoi(), pr_parse(), pr_geti()
+int fnldir(), access()
+real clgetr()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (observations, SZ_FNAME, TY_CHAR)
+ call salloc (catalogs, SZ_FNAME, TY_CHAR)
+ call salloc (config, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (logfile, SZ_FNAME, TY_CHAR)
+ call salloc (catdir, SZ_FNAME, TY_CHAR)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+ call salloc (dir, SZ_PATHNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Open the observations files list.
+ call clgstr ("observations", Memc[observations], SZ_FNAME)
+ obslist = fntopnb (Memc[observations], NO)
+ if (Memc[observations] == EOS || fntlenb (obslist) <= 0) {
+ call eprintf ("ERROR: The observations files list is empty\n")
+ call fntclsb (obslist)
+ call sfree (sp)
+ return
+ }
+
+ # Get the list of catalog files.
+ call clgstr ("catdir", Memc[catdir], SZ_FNAME)
+ call clgstr ("catalogs", Memc[catalogs], SZ_FNAME)
+
+ # Get the configuration file name.
+ call clgstr ("config", Memc[config], SZ_FNAME)
+ if (access (Memc[config], READ_ONLY, TEXT_FILE) == NO) {
+ call eprintf (
+ "ERROR: Cannot open the configuration file for reading\n")
+ call fntclsb (obslist)
+ call sfree (sp)
+ return
+ }
+
+ # Get the output parameters database nam and check that the user
+ # can create or append to the database.
+
+ call clgstr ("parameters", Memc[output], SZ_FNAME)
+ if (Memc[output] == EOS || access (Memc[output], 0,
+ DIRECTORY_FILE) == YES) {
+ call eprintf ("ERROR: The parameters file is undefined\n")
+ call fntclsb (obslist)
+ call sfree (sp)
+ return
+ } else if (access (Memc[output], 0, 0) == NO) {
+ if (fnldir (Memc[output], Memc[dir], SZ_LINE) == 0)
+ call strcpy (".", Memc[dir], SZ_LINE)
+ if (access (Memc[dir], APPEND, DIRECTORY_FILE) == NO) {
+ call eprintf ("ERROR: Cannot open directory %s for writing\n")
+ call pargstr (Memc[dir])
+ call fntclsb (obslist)
+ call sfree (sp)
+ return
+ }
+ } else if (access (Memc[output], APPEND, TEXT_FILE) == NO) {
+ call eprintf (
+ "ERROR: Cannot open existing parameters file %s for writing\n")
+ call pargstr (Memc[output])
+ call fntclsb (obslist)
+ call sfree (sp)
+ return
+ }
+
+ # Get the log file.
+ call clgstr ("logfile", Memc[logfile], SZ_FNAME)
+ if (Memc[logfile] != EOS)
+ call io_logtime (Memc[logfile])
+
+ # Get weighting parameters.
+ wtflag = clgwrd ("weighting", Memc[str], SZ_LINE, FWT_OPTIONS)
+ addscatter = btoi (clgetb ("addscatter"))
+
+ # Get the fitting parameters.
+ tol = clgetr ("tolerance")
+ itmax = clgeti ("maxiter")
+
+ # Get the rejection parameters.
+ low = clgetr ("low_reject")
+ high = clgetr ("high_reject")
+ niterate = clgeti ("nreject")
+ grow = clgetr ("grow")
+
+ # Get the graphics parameters.
+ interactive = clgetb ("interactive")
+ call clgstr ("graphics", Memc[graphics], SZ_LINE)
+
+ # Parse the configuration table.
+ if (pr_parse (Memc[config]) == ERR) {
+ call eprintf ("ERROR: Cannot parse the configuration file\n")
+ call fntclsb (obslist)
+ call sfree (sp)
+ return
+ }
+
+ # Read standard data catalog if the catalog section was in the
+ # configuration file, the catalog section is not empty and the
+ # catalogs files list. This can be tested by checking the value
+ # of the minimum input column, the number of catalog variables
+ # and the contents of the standard catalogs list respectively.
+
+ stable = NULL
+ ntable = NULL
+ nstd = 0
+
+ nstdvars = pr_geti (NCATVARS)
+ if (pr_geti (MINCOL) == 1) {
+ getid = NO
+ } else if (nstdvars == 0) {
+ getid = YES
+ } else if (Memc[catalogs] == EOS) {
+ getid = YES
+ call eprintf ("WARNING: Cannot load catalog variables from ")
+ call eprintf ("the empty catalog files list\n")
+ } else {
+ getid = YES
+ stdlist = fntopnb (Memc[catalogs], NO)
+ call io_gcatdat (Memc[catdir], stdlist, stable, nstd, nstdvars)
+ call fntclsb (stdlist)
+ }
+
+ # Quit if there is no data.
+ if (stable != NULL && nstd <= 0) {
+ call eprintf ("ERROR: No data was read from the catalog files")
+ call stclose (stable)
+ call fntclsb (obslist)
+ call pr_free ()
+ call sfree (sp)
+ return
+ }
+
+ # Read in the observations.
+ if (clgetb ("log_unmatched"))
+ call io_gcatobs (obslist, stable, nstdvars, getid, Memc[logfile],
+ otable, ntable, nobs)
+ else
+ call io_gcatobs (obslist, stable, nstdvars, getid, "", otable,
+ ntable, nobs)
+
+ # Free standard data table since it's no longer needed for the
+ # parameter fitting.
+
+ if (stable != NULL)
+ call stclose (stable)
+
+ # Process all transformation equations if there are enough observations.
+ if (nobs > 0) {
+ call ft_trneqs (Memc[output], Memc[logfile], Memc[graphics],
+ otable, ntable, wtflag, addscatter, tol, itmax, interactive,
+ high, low, niterate, grow, clgetb ("log_fit"),
+ clgetb ("log_results"))
+ } else if (nstd > 0) {
+ call eprintf ("ERROR: No observations could be matched with ")
+ call eprintf ("the catalog entries\n")
+ } else {
+ call eprintf ("ERROR: No observations could be read from ")
+ call eprintf ("the observations files\n")
+ }
+
+ # Free all space.
+ call pr_free()
+ call mct_free (otable)
+ if (ntable != NULL)
+ call mct_free (ntable)
+ call fntclsb (obslist)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/photcal/imgroup.par b/noao/digiphot/photcal/imgroup.par
new file mode 100644
index 00000000..1ee9db9f
--- /dev/null
+++ b/noao/digiphot/photcal/imgroup.par
@@ -0,0 +1,6 @@
+# Parameter file for IMGROUP
+
+imlist,f,a,,,,The name of the input image list
+imsetlist,f,a,,,,The name of the output image set list
+setvalues,s,a,,,,The list of permitted set definition field values
+rename,b,h,no,,,Prompt the user for a name for each image set ?
diff --git a/noao/digiphot/photcal/invertfit.par b/noao/digiphot/photcal/invertfit.par
new file mode 100644
index 00000000..a5d51898
--- /dev/null
+++ b/noao/digiphot/photcal/invertfit.par
@@ -0,0 +1,13 @@
+# The INVERTFIT task parameter file
+
+observations,f,a,"",,,List of observations files
+config,f,a,"",,,Configuration file
+parameters,f,a,"",,,Fitted parameters file
+calib,f,a,"",,,Output calibrated standard indices file
+catalogs,f,h,"",,,List of standard catalog files
+errors,s,h,"obserrors","undefined|obserrors|equations",,"Error computation type (undefined,obserrors,equations)"
+objects,s,h,"all","all|program|standards",,"Objects to be fit (all,program,standards)"
+print,s,h,"",,,Optional list of variables to print
+format,s,h,"",,,Optional output format string
+append,b,h,no,,,Append output to an existing file ?
+catdir,s,h,")_.catdir",,,The standard star catalog directory
diff --git a/noao/digiphot/photcal/io/README b/noao/digiphot/photcal/io/README
new file mode 100644
index 00000000..ffb5bab5
--- /dev/null
+++ b/noao/digiphot/photcal/io/README
@@ -0,0 +1,2 @@
+This subdirectory contains the the i/o routines for the FITCOEFFS, EVALUATE
+and INVEVAL tasks.
diff --git a/noao/digiphot/photcal/io/iocat.x b/noao/digiphot/photcal/io/iocat.x
new file mode 100644
index 00000000..81fb5aaa
--- /dev/null
+++ b/noao/digiphot/photcal/io/iocat.x
@@ -0,0 +1,376 @@
+include <error.h>
+include <time.h>
+include "../lib/io.h"
+
+
+# IO_GCATDAT - Get catalog data from a list of files. These data will be
+# stored in memory as a symbol table for later use.
+
+procedure io_gcatdat (catdir, list, ctable, ncat, nvars)
+
+char catdir[ARB] # name of the catalog directory
+int list # file list
+pointer ctable # catalog table (output)
+int ncat # number of table entries (output)
+int nvars # number of catalog variables
+
+int i, fd, num, col, ip, tp, index
+pointer sp, input, fname, line, token, dummy, indices, sym, map
+real rval
+
+#bool clgetb()
+int fntgfnb(), access(), ctowrd(), ctor(), open(), stnsymbols()
+int pr_findmap(), io_getline(), io_lineid()
+pointer stopen(), stfind(), stenter()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.iocode")) {
+ #call eprintf ("io_gcatdat.in: (list=%d) (nvars=%d)\n")
+ #call pargi (list)
+ #call pargi (nvars)
+ #}
+
+ # Map catalog variables.
+ call pr_catmap (map, nvars)
+
+ # Open a symbol table for catalog data.
+ ctable = stopen ("catalog", 2 * LEN_CATDAT, LEN_CATDAT,
+ 10 * LEN_CATDAT)
+
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (input, SZ_FNAME, TY_CHAR)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (line, MAX_CONT * SZ_LINE, TY_CHAR)
+ call salloc (token, SZ_LINE, TY_CHAR)
+ call salloc (dummy, SZ_LINE, TY_CHAR)
+ call salloc (indices, nvars, TY_INT)
+
+ # Read the catalog data.
+ call fntrewb (list)
+ while (fntgfnb (list, Memc[input], SZ_FNAME) != EOF) {
+
+ # Create the file name.
+ call sprintf (Memc[fname], SZ_FNAME, "%s%s.dat")
+ call pargstr (catdir)
+ call pargstr (Memc[input])
+ if (access (Memc[fname], READ_ONLY, TEXT_FILE) == NO)
+ call strcpy (Memc[input], Memc[fname], SZ_FNAME)
+
+ # Try to open the input file.
+ iferr (fd = open (Memc[fname], READ_ONLY, TEXT_FILE)) {
+ call erract (EA_WARN)
+ next
+ }
+
+ # Read the file lines.
+ call io_getline_init ()
+ while (io_getline (fd, Memc[line], MAX_CONT * SZ_LINE) != EOF) {
+
+ # Get the line id from the first column.
+ ip = 1
+ if (io_lineid (Memc[line], ip, Memc[dummy], Memc[token],
+ SZ_LINE) == 0)
+ next
+
+ # Enter the line identifier in the symbol table.
+ if (stfind (ctable, Memc[token]) == NULL) {
+ sym = stenter (ctable, Memc[token], nvars)
+ call amovkr (INDEFR, Memr[P2R(sym)], nvars)
+ } else
+ next
+
+ # Get the values from the next columns.
+ col = 2
+ while (ctowrd (Memc[line], ip, Memc[token], SZ_LINE) > 0) {
+
+ # Enter value into symbol table if it was declared in the
+ # configuration file.
+
+ tp = 1
+ if (ctor (Memc[token], tp, rval) > 0) {
+ num = pr_findmap (map, col, Memi[indices], nvars)
+ do i = 1, num {
+ index = Memi[indices+i-1]
+ if (! IS_INDEFI (index))
+ Memr[P2R(sym+index-1)] = rval
+ }
+ }
+
+ # Count columns
+ col = col + 1
+ }
+ }
+
+ # Close file
+ call close (fd)
+ }
+
+ # Get number of entries.
+ ncat = stnsymbols (ctable, 0)
+
+ # Free mapped variables.
+ call pr_unmap (map)
+
+ # Debug ?
+ #if (clgetb ("debug.iocode")) {
+ #call eprintf ("io_gcatdat.out: (ctable=%d) (ncat=%d) (nvars=%d)\n")
+ #call pargi (list)
+ #call pargi (ncat)
+ #call pargi (nvars)
+ #}
+ #call dg_dcatdat ("from io_gcatdat", ctable, nvars)
+
+ call sfree (sp)
+end
+
+
+# IO_GCATOBS - Get catalog observations from a list of files, and store them
+# in a multicolumn table. The catalog data will be appended to the last
+# columns of the table, so each line will be "complete".
+
+procedure io_gcatobs (list, ctable, ncatvars, getid, logfile, otable, ntable,
+ nobs)
+
+int list # file list
+pointer ctable # catalog table
+int ncatvars # number of catalog variables
+int getid # match the ids
+char logfile[ARB] # output log file
+pointer otable # catalog observations table (output)
+pointer ntable # name table (output)
+int nobs # number of observations (output)
+
+char eoschar
+int i, log, fd, nvars, num, col, ip, tp, index
+pointer sp, input, line, token, dummy, indices, map, sym
+real rval
+
+#bool clgetb()
+int fntgfnb(), ctowrd(), ctor(), open(), pr_findmap()
+int io_getline(), io_lineid()
+pointer stfind(), mct_getrow()
+
+data eoschar /EOS/
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.iocode")) {
+ #call eprintf ("io_gcatobs.in: (list=%d) (ctable=%d) (ncatv=%d)\n")
+ #call pargi (list)
+ #call pargi (ctable)
+ #call pargi (ncatvars)
+ #}
+
+ # Map the observational variables.
+ call pr_obsmap (map, nvars)
+
+ # Allocate the catalog observation table.
+ call mct_alloc (otable, LEN_CATOBS, nvars + ncatvars, TY_REAL)
+
+ # Allocate the star name table.
+ if (getid == YES)
+ call mct_alloc (ntable, LEN_CATOBS, SZ_FNAME + 1, TY_CHAR)
+ else
+ call mct_alloc (ntable, LEN_CATOBS, 2, TY_CHAR)
+
+ # Open the log file.
+ if (logfile[1] == EOS) {
+ log = NULL
+ } else {
+ iferr (log = open (logfile, APPEND, TEXT_FILE)) {
+ call erract (EA_WARN)
+ log = NULL
+ }
+ }
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (input, SZ_FNAME, TY_CHAR)
+ call salloc (line, MAX_CONT * SZ_LINE, TY_CHAR)
+ call salloc (token, SZ_LINE, TY_CHAR)
+ call salloc (dummy, SZ_LINE, TY_CHAR)
+ call salloc (indices, nvars, TY_INT)
+
+ # Print banner.
+ if (log != NULL)
+ call fprintf (log, "\n#UNMATCHED OBJECTS\n\n")
+
+ # Read the catalog observations.
+ nobs = 0
+ call fntrewb (list)
+ while (fntgfnb (list, Memc[input], SZ_LINE) != EOF) {
+
+ # Try to open the input file.
+ iferr (fd = open (Memc[input], READ_ONLY, TEXT_FILE)) {
+ call erract (EA_WARN)
+ next
+ }
+
+ # Read the file lines.
+ call io_getline_init ()
+ while (io_getline (fd, Memc[line], MAX_CONT * SZ_LINE) != EOF) {
+
+ # Get line id from first column if there is a catalog to
+ # match them. Otherwise assume that there is no catalog.
+
+ ip = 1
+ if (getid == YES) {
+ if (io_lineid (Memc[line], ip, Memc[dummy], Memc[token],
+ SZ_LINE) == 0)
+ next
+ col = 2
+ } else
+ col = 1
+
+ # Search for this string in the catalog symbol table if
+ # one is defined. If it's not found skip to the next
+ # line or observation.
+
+ if (ctable != NULL) {
+ sym = stfind (ctable, Memc[token])
+ if (sym == NULL) {
+ if (log != NULL) {
+ call fprintf (log,
+ "File: %s Object: %s was unmatched\n")
+ call pargstr (Memc[input])
+ call pargstr (Memc[token])
+ }
+ next
+ }
+ }
+
+ # Count the observations.
+ nobs = nobs + 1
+
+ # Add the symbol to the name table.
+ if (getid == YES) {
+ call mct_putc (ntable, nobs, 1, eoschar)
+ call strcpy (Memc[token], Memc[mct_getrow(ntable, nobs)],
+ SZ_FNAME)
+ } else
+ call mct_putc (ntable, nobs, 1, eoschar)
+
+ # Scan input colums and get all variable values.
+ while (ctowrd (Memc[line], ip, Memc[token], SZ_LINE) > 0) {
+
+ # Enter variable value into the observation table
+ # if it was declared in the configuration file.
+
+ tp = 1
+ if (ctor (Memc[token], tp, rval) > 0) {
+ num = pr_findmap (map, col, Memi[indices], nvars)
+ do i = 1, num {
+ index = Memi[indices+i-1]
+ if (!IS_INDEFI (index))
+ call mct_putr (otable, nobs, index, rval)
+ }
+ }
+
+ # Count input columns
+ col = col + 1
+ }
+
+ # Now append to the current row all the variable values
+ # from the catalog table for the same line id, if
+ # matching is enabled.
+
+ if (ncatvars > 0) {
+ if (ctable == NULL) {
+ do num = 1, ncatvars
+ call mct_putr (otable, nobs, nvars + num, INDEFR)
+ } else {
+ do num = 1, ncatvars {
+ rval = Memr[P2R(sym+num-1)]
+ call mct_putr (otable, nobs, nvars + num, rval)
+ }
+ }
+ }
+
+ }
+
+ # Close file.
+ call close (fd)
+ }
+
+ if (log != NULL) {
+ call fprintf (log, "\n")
+ call close (log)
+ }
+
+ # Free mapped variables.
+ call pr_unmap (map)
+
+ # Debug ?
+ #if (clgetb ("debug.iocode")) {
+ #call eprintf ("io_gcatobs.out: (otable=%d) (nobs=%d)\n")
+ #call pargi (otable)
+ #call pargi (nobs)
+ #}
+ #call dg_dcatobs ("from io_gcatobs", otable)
+
+ call sfree (sp)
+end
+
+
+# IO_LOGTIME -- Write a time stamp in the unmatched stars log file.
+
+procedure io_logtime (logfile)
+
+char logfile[ARB] # the name of the log file
+
+int log
+pointer sp, timestr
+int open()
+long clktime()
+
+begin
+ if (logfile[1] == EOS)
+ return
+
+ iferr (log = open (logfile, APPEND, TEXT_FILE)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call smark (sp)
+ call salloc (timestr, SZ_TIME, TY_CHAR)
+ call cnvtime (clktime(0), Memc[timestr], SZ_TIME)
+ call strupr (Memc[timestr])
+ call fprintf (log, "\n#%s\n")
+ call pargstr (Memc[timestr])
+ call sfree (sp)
+
+ call close (log)
+
+end
+
+
+# IO_TITLE -- Write the equation title to the logfile
+
+procedure io_title (logfile, title, sym)
+
+char logfile[ARB] # the name of the log file
+char title # title
+int sym # equation symbol
+
+int log
+int open()
+pointer pr_xgetname()
+
+begin
+ if (logfile[1] == EOS)
+ return
+
+ iferr (log = open (logfile, APPEND, TEXT_FILE)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call fprintf (log, "%s %s\n\n")
+ call pargstr (title)
+ call pargstr (Memc[pr_xgetname(sym)])
+
+ call close (log)
+end
diff --git a/noao/digiphot/photcal/io/iocoeffs.x b/noao/digiphot/photcal/io/iocoeffs.x
new file mode 100644
index 00000000..142a5f3e
--- /dev/null
+++ b/noao/digiphot/photcal/io/iocoeffs.x
@@ -0,0 +1,282 @@
+include "../lib/io.h"
+include "../lib/fitparams.h"
+include "../lib/parser.h"
+
+# IO_GCOEFFS - Get fit coefficients from a text database file
+
+int procedure io_gcoeffs (fname, sym, stat, chisqr, rms, params, errors,
+ nparams)
+
+char fname[ARB] # output database name
+int sym # equation symbol
+int stat # fit error code (output)
+real chisqr # reduced chi-squared of the fit
+real rms # RMS of the fit
+real params[nparams] # parameter values (output)
+real errors[nparams] # parameter errors (output)
+int nparams # number of parameters
+
+#int i
+int nread, rec
+pointer dt
+
+#bool clgetb()
+int dtlocate(), dtgeti()
+pointer dtmap(), pr_xgetname()
+real dtgetr()
+errchk dtmap()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.iocode")) {
+ #call eprintf ("io_gcoeffs.in: (fname=%s) (sym=%d) (npar=%d)\n")
+ #call pargstr (fname)
+ #call pargi (sym)
+ #call pargi (nparams)
+ #}
+
+ # Map database.
+ dt = dtmap (fname, READ_ONLY)
+
+ # Locate record for the equation.
+ iferr (rec = dtlocate (dt, Memc[pr_xgetname (sym)])) {
+ call dtunmap (dt)
+ return (0)
+ }
+
+ # Get fit status code, chisqr, and rms.
+ iferr (stat = dtgeti (dt, rec, STATUS))
+ stat = INDEFI
+ iferr (chisqr = dtgetr (dt, rec, CHISQR))
+ chisqr = INDEFR
+ iferr (rms = dtgetr (dt, rec, RMS))
+ rms = INDEFR
+
+ # Get parameter values and errors.
+ iferr (call dtgar (dt, rec, VALUES, params, nparams, nread))
+ nread = 0
+ iferr (call dtgar (dt, rec, ERRORS, errors, nparams, nread))
+ nread = 0
+
+ # Debug ?
+ #if (clgetb ("debug.iocode")) {
+ #call eprintf (
+ #"io_gcoeffs.out: (stat=%d) (chisqr=%g) (rms=%g) (nread=%s)")
+ #call pargi (stat)
+ #call pargr (chisqr)
+ #call pargr (rms)
+ #call pargi (nread)
+ #call eprintf ("\nvalues:")
+ #do i = 1, nread {
+ #call eprintf (" (%g)")
+ #call pargr (params[i])
+ #}
+ #call eprintf ("\nerrors:")
+ #do i = 1, nread {
+ #call eprintf (" (%g)")
+ #call pargr (errors[i])
+ #}
+ #call eprintf ("\n")
+ #}
+
+ # Unmap the database.
+ call dtunmap (dt)
+
+ # Return number of values read.
+ return (nread)
+end
+
+
+# IO_PCOEFFS - Put fit coefficients in the output file
+
+procedure io_pcoeffs (fname, sym, stat, wtflag, variance, chisqr, scatter,
+ rms, params, errors, plist, nparams)
+
+char fname[ARB] # output database name
+int sym # equation symbol
+int stat # fit error code
+int wtflag # type of weighting
+real variance # variance of the fit
+real chisqr # reduced chi-squared of the fit
+real scatter # additional scatter squared in the fit
+real rms # RMS of the fit
+real params[nparams] # parameter values
+real errors[nparams] # parameter errors
+int plist[nparams] # parameter list
+int nparams # number of parameters
+
+bool isfit
+char str[SZ_LINE]
+int i, j
+pointer dt
+real rval
+
+#bool clgetb()
+int pr_gpari()
+pointer pr_xgetname(), pr_gsymc(), pr_gsymp(), pr_gderc(), dtmap(), pr_gderp()
+real pr_gsymr()
+errchk dtmap()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.iocode")) {
+ #call eprintf ("io_pcoeffs: (fname=%s) (sym=%d) (stat=%d) "
+ #call pargstr (fname)
+ #call pargi (sym)
+ #call pargi (stat)
+ #call eprintf ("(chisqr=%g) (rms=%g) (npar=%d)\n")
+ #call pargr (chisqr)
+ #call pargr (rms)
+ #call pargi (nparams)
+ #}
+
+ # Map the database.
+ dt = dtmap (fname, APPEND)
+
+ # Put time stamp and record identification.
+ call dtptime (dt)
+ call dtput (dt, "begin\t%s\n")
+ call pargstr (Memc[pr_xgetname (sym)])
+
+ # Write fit status code and message.
+ call nlerrmsg (stat, str, SZ_LINE)
+ call dtput (dt, "\t%s\t%d\t(%s)\n")
+ call pargstr (STATUS)
+ call pargi (stat)
+ call pargstr (str)
+
+ # Write the variance and standard deviation.
+ call dtput (dt, "\t%s\t%g\n")
+ call pargstr (VARIANCE)
+ call pargr (variance)
+ call dtput (dt, "\t%s\t%g\n")
+ call pargstr (STDEV)
+ if (variance > 0.0)
+ call pargr (sqrt (variance))
+ else
+ call pargr (0.0)
+
+ # Write the average square error and the average error.
+ call dtput (dt, "\t%s\t%g\n")
+ call pargstr (AVSQERROR)
+ if (chisqr <= 0.0)
+ rval = 0.0
+ else
+ rval = variance / chisqr
+ call pargr (rval)
+ call dtput (dt, "\t%s\t\t%g\n")
+ call pargstr (AVERROR)
+ call pargr (sqrt (rval))
+
+ # Write out the average square scatter and the average scatter.
+ call dtput (dt, "\t%s\t%g\n")
+ call pargstr (AVSQSCATTER)
+ if (scatter <= 0.0)
+ rval = 0.0
+ else
+ rval = scatter
+ call pargr (rval)
+ call dtput (dt, "\t%s\t%g\n")
+ call pargstr (AVSCATTER)
+ call pargr (sqrt (rval))
+
+ # Write reduced chi-squared.
+ call dtput (dt, "\t%s\t\t%g\n")
+ call pargstr (CHISQR)
+ call pargr (chisqr)
+
+ # Write RMS.
+ call dtput (dt, "\t%s\t\t%g\n")
+ call pargstr (MSQ)
+ call pargr (rms * rms)
+ call dtput (dt, "\t%s\t\t%g\n")
+ call pargstr (RMS)
+ call pargr (rms)
+
+ # Write reference equation.
+ call dtput (dt, "\t%s\t%s\n")
+ call pargstr (REFERENCE)
+ call pargstr (Memc[pr_gsymc (sym, PTEQREF)])
+
+ # Write the fitting equation.
+ call dtput (dt, "\t%s\t\t%s\n")
+ call pargstr (FITTING)
+ call pargstr (Memc[pr_gsymc (sym, PTEQFIT)])
+
+ # Write the weighting information.
+ call dtput (dt, "\t%s\t\t%s\n")
+ switch (wtflag) {
+ case FWT_UNIFORM:
+ call pargstr (WEIGHTING)
+ call pargstr ("uniform")
+ case FWT_PHOTOMETRIC:
+ call pargstr (WEIGHTING)
+ call pargstr ("photometric")
+ case FWT_EQUATIONS:
+ call pargstr (WEIGHTING)
+ if (pr_gsymp (sym, PTEQRPNWEIGHT) == NULL)
+ call pargstr ("uniform")
+ else
+ call pargstr (Memc[pr_gsymc (sym, PTEQWEIGHT)])
+ default:
+ call pargstr (WEIGHTING)
+ call pargstr ("uniform")
+ }
+
+ # Write the parameter names.
+ call dtput (dt, "\t%s\t%d\n")
+ call pargstr (PARAMETERS)
+ call pargi (nparams)
+ do i = 1, nparams {
+ call dtput (dt, "\t\t%s\t(%s)\n")
+ call pargstr (Memc[pr_xgetname (pr_gpari (sym, i, PTEQPAR))])
+ isfit = false
+ do j = 1, nparams
+ if (plist[j] == i) {
+ isfit = true
+ break
+ }
+ if (isfit)
+ call pargstr ("fit")
+ else
+ call pargstr ("constant")
+ }
+
+ # Write the derivatives.
+ call dtput (dt, "\t%s\t%d\n")
+ call pargstr (DERIVATIVES)
+ call pargi (nparams)
+ do i = 1, nparams {
+ if (pr_gderp (sym, i, PTEQRPNDER) != NULL) {
+ call dtput (dt, "\t\t%s\n")
+ call pargstr (Memc[pr_gderc (sym, i, PTEQDER)])
+ } else {
+ call dtput (dt, "\t\t%g\n")
+ call pargr (pr_gsymr (pr_gpari (sym, i, PTEQPAR),
+ PFITDELTA))
+ }
+ }
+
+ # Write the parameter values.
+ call dtput (dt, "\t%s\t%d\n")
+ call pargstr (VALUES)
+ call pargi (nparams)
+ do i = 1, nparams {
+ call dtput (dt, "\t\t%g\n")
+ call pargr (params[i])
+ }
+
+ # Write the parameter errors.
+ call dtput (dt, "\t%s\t%d\n")
+ call pargstr (ERRORS)
+ call pargi (nparams)
+ do i = 1, nparams {
+ call dtput (dt, "\t\t%g\n")
+ call pargr (errors[i])
+ }
+
+ call dtput (dt,"\n")
+
+ # Close the database.
+ call dtunmap (dt)
+end
diff --git a/noao/digiphot/photcal/io/iogetline.x b/noao/digiphot/photcal/io/iogetline.x
new file mode 100644
index 00000000..040c4aeb
--- /dev/null
+++ b/noao/digiphot/photcal/io/iogetline.x
@@ -0,0 +1,89 @@
+include "../lib/io.h"
+
+
+# IO_GETLINE -- Get an input line from the data file. The line returned may
+# be composed by one or more physical lines in the output file, if subsequent
+# lines start with a continuation character. The continuation character must
+# be the first character in the subsequent lines. Comment and blank lines
+# are skipped.
+
+int procedure io_getline (fd, line, maxch)
+
+int fd # file descriptor
+char line[maxch] # line from file
+int maxch # line size
+
+bool first # first line ?
+int pending # pending line in buffer ?
+char buffer[SZ_LINE] # line buffer
+
+common /iogetcom/ pending
+
+int fscan()
+int strlen(), strmatch()
+
+begin
+ # Initialize flag to differentiate the first input line
+ # within the loop.
+ first = true
+
+ # Read lines until a non-comment and non-blank line is found, or
+ # the end of the file is reached. Lines starting with a continuation
+ # character are concatenated.
+ repeat {
+
+ # Get next line. If there is no pending line already in
+ # the buffer, read a new line from the file. Otherwise,
+ # use the pending line and clear the pending flag.
+ if (pending == NO) {
+ if (fscan (fd) != EOF)
+ call gargstr (buffer, SZ_LINE)
+ else if (first)
+ return (EOF)
+ else
+ return (OK)
+ } else
+ pending = NO
+
+ # Skip blank and comment lines
+ if (strlen (buffer) == 0)
+ next
+ if (strmatch (buffer, COMMENT) != 0)
+ next
+
+ # If the input line contains a continuation character, then
+ # concatenate it to the accumulated line. Otherwise, leave
+ # it in the buffer, and set the pending flag. For the first
+ # input line no continuation characters are allowed.
+ if (first) {
+ if (strmatch (buffer, CONTINUATION) != 0)
+ call error (0, "Continuation character found in first line")
+ else {
+ call strcpy (buffer, line, maxch)
+ first = false
+ next
+ }
+ } else {
+ if (strmatch (buffer, CONTINUATION) != 0) {
+ call strcat (buffer[2], line, maxch)
+ next
+ } else {
+ pending = YES
+ return (OK)
+ }
+ }
+ }
+end
+
+
+# IO_GETLINE_INIT -- Initialize get line.
+
+procedure io_getline_init ()
+
+int pending # pending line in buffer ?
+
+common /iogetcom/ pending
+
+begin
+ pending = NO
+end
diff --git a/noao/digiphot/photcal/io/iolineid.x b/noao/digiphot/photcal/io/iolineid.x
new file mode 100644
index 00000000..a7955c6e
--- /dev/null
+++ b/noao/digiphot/photcal/io/iolineid.x
@@ -0,0 +1,51 @@
+include <ctype.h>
+
+
+# IO_LINEID - Get the line identification string from input line and advance
+# pointer to next non-white character. Convert matching string to uppercase,
+# and keep characters in the [A..Z, 0..9] set, but return both the original
+# and compressed matching strings. The first one is intended for output to
+# the user, and the second for internal use to avoid typos.
+
+int procedure io_lineid (line, ip, uid, cid, maxch)
+
+char line[ARB] # input line
+int ip # input pointer
+char uid[ARB] # user's (original) line identification string
+char cid[ARB] # compressed line identification string
+int maxch # output chars
+
+int i, op
+
+begin
+ # Discard the leading whitespaces.
+ while (IS_WHITE (line[ip]) && line[ip] != EOS)
+ ip = ip + 1
+
+ # Get the line identifier.
+ for (op = 1; !IS_WHITE (line[ip]) && line[ip] != EOS && op <= maxch;
+ op = op + 1) {
+ uid[op] = line[ip]
+ ip = ip + 1
+ }
+ uid[op] = EOS
+
+ # Copy the orignal identifier into the compressed identifier,
+ # and convert the latter to upper case.
+ call strcpy (uid, cid, maxch)
+ call strupr (cid)
+
+ # Take out all characters not belonging to the [A-Z,0-9,+,-,_] set.
+ op = 1
+ for (i = 1; cid[i] != EOS; i = i + 1) {
+ if (IS_UPPER (cid[i]) || IS_DIGIT (cid[i]) || (cid[i] == '+') ||
+ (cid[i] == '-') || (cid[i] == '_')) {
+ cid[op] = cid[i]
+ op = op + 1
+ }
+ }
+ cid[op] = EOS
+
+ # Return number of characters in compressed identifier
+ return (op - 1)
+end
diff --git a/noao/digiphot/photcal/io/ioobs.x b/noao/digiphot/photcal/io/ioobs.x
new file mode 100644
index 00000000..cc9934d3
--- /dev/null
+++ b/noao/digiphot/photcal/io/ioobs.x
@@ -0,0 +1,150 @@
+include "../lib/io.h"
+
+# IO_GOBS - Get next observation from a file, either from data in the catalog
+# or not. For data found in the catalog return its catalog values at the end of
+# the array. Otherwise append INDEF values. If catalog matching is not being
+# used don't append anything. Return the number of variables read, or EOF.
+
+int procedure io_gobs (fd, ctable, map, type, vars, nvars, getid, ulineid,
+ clineid, maxch)
+
+int fd # file descriptor
+pointer ctable # catalog table
+pointer map # mapped columns
+int type # type of object to be processed
+real vars[nvars] # observations (output)
+int nvars # number of variables
+int getid # get the object id
+char ulineid[maxch] # user's line identifier (output)
+char clineid[maxch] # compresses line identifier (output)
+int maxch # max number of chars.
+
+int i, num, col, ip, tp, index, nread
+pointer sp, line, token, indices, sym
+real rval
+
+#bool clgetb()
+int ctowrd(), ctor(), pr_findmap(), io_getline(), io_lineid()
+pointer stfind()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.iocode")) {
+ #call eprintf ("io_obs.in: (fd=%d) (ctable=%d) (map=%d) ")
+ #call pargi (fd)
+ #call pargi (ctable)
+ #call pargi (map)
+ #call eprintf ("(nvars=%d) (maxch=%d)\n")
+ #call pargi (nvars)
+ #call pargi (maxch)
+ #}
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (line, MAX_CONT * SZ_LINE, TY_CHAR)
+ call salloc (token, SZ_LINE, TY_CHAR)
+ call salloc (indices, nvars, TY_INT)
+
+ # Loop reading lines until the next desired data is found.
+ # Return EOF if there are no more lines, and the number of
+ # variables read otherwise.
+
+ repeat {
+
+ # Get next line from file
+ if (io_getline (fd, Memc[line], MAX_CONT * SZ_LINE) == EOF) {
+ call sfree (sp)
+ return (EOF)
+ }
+
+ #if (clgetb ("debug.iocode")) {
+ #call eprintf ("[%s]\n")
+ #call pargstr (Memc[line])
+ #}
+
+ # Get the line id if catalog matching is being used.
+ ip = 1
+ if (getid == YES) {
+ if (io_lineid (Memc[line], ip, ulineid, clineid, maxch) == 0)
+ next
+ col = 2
+ } else {
+ col = 1
+ ulineid[1] = EOS
+ }
+
+ # Break the loop when the appropiate data type is found.
+ # This is always the case when all the data type is selected,
+ # or no catalog matching is being used.
+
+ if (ctable == NULL) {
+ sym = NULL
+ break
+ } else {
+ sym = stfind (ctable, clineid)
+ if (type == TYPE_ALL)
+ break
+ else if ((type == TYPE_PROGRAM) && (sym == NULL))
+ break
+ else if ((type == TYPE_STANDARDS) && (sym != NULL))
+ break
+ }
+ }
+
+ # Initialize the variables array to INDEF.
+ call amovkr (INDEFR, vars, nvars)
+
+ # Scan input colums and get all observational variable values.
+ nread = 0
+ while (ctowrd (Memc[line], ip, Memc[token], SZ_LINE) > 0) {
+
+ # Enter variable value into symbol table if it was declared
+ # in the configuration file.
+
+ tp = 1
+ if (ctor (Memc[token], tp, rval) > 0) {
+ num = pr_findmap (map, col, Memi[indices], nvars)
+ do i = 1, num {
+ index = Memi[indices+i-1]
+ if (IS_INDEFI (index))
+ next
+ if (index > nvars)
+ call error (0, "Array index out of bounds (io_gobs)")
+ vars[index] = rval
+ nread = max (nread, index)
+ }
+ } else if (col == 1 && getid == YES)
+ call strcpy (Memc[token], ulineid, SZ_LINE)
+
+ # Count the input columns.
+ col = col + 1
+ }
+
+ # If catalog matching is being used append to the output array
+ # all the catalog values from the catalog table. If these values
+ # are not defined (not found in the catalog) append INDEF values.
+
+ if (sym != NULL) {
+ do num = nread + 1, nvars
+ vars[num] = Memr[P2R(sym+num-nread-1)]
+ nread = nvars
+ }
+
+ # Debug ?
+ #if (clgetb ("debug.iocode")) {
+ #call eprintf ("io_obs.out: (nread=%d)")
+ #call pargi (nread)
+ #do ip = 1, nread {
+ #call eprintf (" (%g)")
+ #call pargr (vars[ip])
+ #}
+ #call eprintf (" (ulineid=%s) (clineid=%s)\n")
+ #call pargstr (ulineid)
+ #call pargstr (clineid)
+ #}
+
+ call sfree (sp)
+
+ # Return the number of variables read.
+ return (nread)
+end
diff --git a/noao/digiphot/photcal/io/iostrwrd.x b/noao/digiphot/photcal/io/iostrwrd.x
new file mode 100644
index 00000000..d7520451
--- /dev/null
+++ b/noao/digiphot/photcal/io/iostrwrd.x
@@ -0,0 +1,51 @@
+# IO_STRWRD -- Search a dictionary string for a given string index number.
+# This is the opposite function of strdic(), that returns the index for
+# given string. The entries in the dictionary string are separated by
+# a delimiter character which is the first character of the dictionary
+# string. The index of the string found is returned as the function value.
+# Otherwise, if there is no string for that index, a zero is returned.
+
+int procedure io_strwrd (index, outstr, maxch, dict)
+
+int index # String index
+char outstr[ARB] # Output string as found in dictionary
+int maxch # Maximum length of output string
+char dict[ARB] # Dictionary string
+
+int i, len, start, count
+
+int strlen()
+
+begin
+ # Clear output string
+ outstr[1] = EOS
+
+ # Return if the dictionary is not long enough
+ if (dict[1] == EOS)
+ return (0)
+
+ # Initialize counters
+ count = 1
+ len = strlen (dict)
+
+ # Search the dictionary string. This loop only terminates
+ # successfully if the index is found. Otherwise the procedure
+ # returns with and error condition.
+ for (start = 2; count < index; start = start + 1) {
+ if (dict[start] == dict[1])
+ count = count + 1
+ if (start == len)
+ return (0)
+ }
+
+ # Extract the output string from the dictionary
+ for (i = start; dict[i] != EOS && dict[i] != dict[1]; i = i + 1) {
+ if (i - start + 1 > maxch)
+ break
+ outstr[i - start + 1] = dict[i]
+ }
+ outstr[i - start + 1] = EOS
+
+ # Return index for output string
+ return (count)
+end
diff --git a/noao/digiphot/photcal/io/mkpkg b/noao/digiphot/photcal/io/mkpkg
new file mode 100644
index 00000000..32009504
--- /dev/null
+++ b/noao/digiphot/photcal/io/mkpkg
@@ -0,0 +1,16 @@
+# The MKPKG file for the io subdirectory.
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ iocat.x "../lib/io.h" <time.h> <error.h>
+ iocoeffs.x "../lib/parser.h" "../lib/fitparams.h"\
+ "../lib/io.h"
+ iogetline.x "../lib/io.h"
+ iolineid.x <ctype.h>
+ ioobs.x "../lib/io.h"
+ iostrwrd.x
+ ;
diff --git a/noao/digiphot/photcal/lib/apfile.h b/noao/digiphot/photcal/lib/apfile.h
new file mode 100644
index 00000000..16b3f18d
--- /dev/null
+++ b/noao/digiphot/photcal/lib/apfile.h
@@ -0,0 +1,117 @@
+# Set up the definitions for the required input photometry file fields
+
+define CAT_NFIELDS 10
+
+define CAT_IMAGE 1 # the image name
+define CAT_XCENTER 2 # x center position
+define CAT_YCENTER 3 # y center position
+define CAT_IFILTER 4
+define CAT_ITIME 5
+define CAT_XAIRMASS 6 # the airmass
+define CAT_OTIME 7 # the airmass
+define CAT_RAPERT 8 # list of aperture radii
+define CAT_MAG 9 # list of magnitudes
+define CAT_MERR 10 # list of magnitude errors
+
+# Set up the definitions for the required input airmass file fields
+
+define OBS_NFIELDS 5
+
+define OBS_IMAGE 1 # the image name
+define OBS_IFILTER 2 # filter id
+define OBS_ITIME 3 # exposure time
+define OBS_XAIRMASS 4 # the airmass
+define OBS_OTIME 5 # the time of observation
+
+# Define the image name symbol table data structure
+
+define LEN_IMT_STRUCT (8 + 2 * SZ_FNAME + 2)
+
+define IMT_IMNO Memi[$1] # the image sequence number
+define IMT_NENTRIES Memi[$1+1] # number of data entries
+define IMT_OFFSET Memi[$1+2] # offset to image data
+define IMT_RO Memr[P2R($1+3)] # the HWHM of the psf
+define IMT_ITIME Memr[P2R($1+4)] # the exposure time
+define IMT_XAIRMASS Memr[P2R($1+5)] # the airmass
+define IMT_NXAIRMASS Memr[P2R($1+6)] # the normalized airmass
+define IMT_OTIME Memr[P2R($1+7)] # the normalized airmass
+define IMT_IFILTER Memc[P2C($1+8)] # the filter id
+define IMT_IMNAME Memc[P2C($1+8+SZ_FNAME+1)] # the image name
+
+define LEN_IMTABLE 100 # initial length of the image table
+define DEF_BUFSIZE 1000 # default object data buffer size
+
+
+# Define the fitting code structures
+
+define LEN_AGRSTRUCT 35
+
+define AGR_DM Memi[$1] # pointer to model estimates
+define AGR_DDDR Memi[$1+1] # pointer to r0 derivative estimates
+define AGR_T Memi[$1+2] # pointer to parameter derivatives
+define AGR_U Memi[$1+3] # pointer to accumulation matrix
+define AGR_V Memi[$1+4] # pointer to accumulation vector
+define AGR_POLD Memi[$1+5] # pointer to previous parameters incr
+define AGR_DP Memi[$1+6] # pointer to parameter increments
+define AGR_PCLAMPS Memi[$1+7] # pointer to parameter clamps
+define AGR_PARAMS Memi[$1+8] # pointer to parameters
+define AGR_PERRORS Memi[$1+9] # pointer to parameter errors
+define AGR_RBAR Memi[$1+11] # pointer to mean radii
+define AGR_THEO Memi[$1+12] # pointer to the model estimates
+define AGR_W Memi[$1+13] # pointer to the working weight array
+define AGR_ADOPT Memi[$1+14] # pointer to the adopted differences
+define AGR_WOBS Memi[$1+15] # pointer to the weighted observations
+define AGR_OBS Memi[$1+16] # pointer to the observations
+define AGR_WADO Memi[$1+17] # pointer to the errors in observations
+define AGR_CUM Memi[$1+18] # pointer to the accumulated differences
+define AGR_TCUM Memi[$1+19] # pointer to the accumulated differences
+define AGR_WCUM Memi[$1+20] # pointer to the accumulated errors
+define AGR_MAGS Memi[$1+21] # the temporary magnitude array
+define AGR_CMAGS Memi[$1+22] # the summed magnitude array
+define AGR_TMAGS Memi[$1+23] # the total summed magnitude array
+define AGR_WMAGS Memi[$1+24] # the summed magnitude error array
+define AGR_AVE Memi[$1+25] # pointer to the model averages
+define AGR_RESID Memi[$1+26] # pointer to the residuals
+define AGR_RESSQ Memi[$1+27] # pointer to the residuals squared
+define AGR_WR Memi[$1+28] # pointer to the sum of the weights
+define AGR_TAVE Memi[$1+29] # pointer to the model averages
+define AGR_TRESID Memi[$1+30] # pointer to the residuals
+define AGR_TRESSQ Memi[$1+31] # pointer to the residuals squared
+define AGR_TWR Memi[$1+32] # pointer to the sum of the weights
+
+# Define some miscellaneous parameters
+
+define DEF_AIROFFSET 1.25
+define MAX_MTERMS 5
+define AGR_ITMAX 300
+
+# Define the permitted plot types
+
+define AGR_FIT 1
+define AGR_ARESIDUALS 2
+define AGR_CUMULATIVE 3
+define AGR_XRESIDUALS 4
+define AGR_YRESIDUALS 5
+define AGR_BRESIDUALS 6
+
+# Define the interactive colon commands
+
+define AGR_CMDS "|show|image|nparams|swings|pwings|pgauss|rgescale|\
+xwings|smallap|largeap|"
+
+define AGR_CMD_SHOW 1
+define AGR_CMD_IMAGE 2
+define AGR_CMD_MTERMS 3
+define AGR_CMD_SWINGS 4
+define AGR_CMD_PWINGS 5
+define AGR_CMD_PGAUSS 6
+define AGR_CMD_RGESCALE 7
+define AGR_CMD_XWINGS 8
+define AGR_CMD_SMALLAP 9
+define AGR_CMD_LARGEAP 10
+
+define AGR_SHOWCMDS "|model|seeing|parameters|"
+
+define AGR_CMD_MODEL 1
+define AGR_CMD_SEEING 2
+define AGR_CMD_PARAMETERS 3
diff --git a/noao/digiphot/photcal/lib/fitparams.h b/noao/digiphot/photcal/lib/fitparams.h
new file mode 100644
index 00000000..85a27782
--- /dev/null
+++ b/noao/digiphot/photcal/lib/fitparams.h
@@ -0,0 +1,7 @@
+# Define the weighting options.
+
+define FWT_OPTIONS "|uniform|photometric|equations|"
+
+define FWT_UNIFORM 1
+define FWT_PHOTOMETRIC 2
+define FWT_EQUATIONS 3
diff --git a/noao/digiphot/photcal/lib/io.h b/noao/digiphot/photcal/lib/io.h
new file mode 100644
index 00000000..f3f8e26f
--- /dev/null
+++ b/noao/digiphot/photcal/lib/io.h
@@ -0,0 +1,78 @@
+# The include file for PHOTCAL i/o
+
+# Formatting definitions for MKCATALOG
+
+define MKCAT_KYCATALOG "CATALOG:" # the catalog title keyword
+define MKCAT_KYNCOLS "NCOLS:" # the number of columns keyword
+define MKCAT_KYHDRLENGTH "HDRLENGTH:" # the column header length keyword
+
+define MKCAT_MAXCOLWIDTH 79 # the maximum column width
+define MKCAT_IDCOLWIDTH 15 # the default id column width
+define MKCAT_COLWIDTH 10 # the default data column width
+define MKCAT_NCOLS 10 # the default number of columns
+define MKCAT_SZGAP 2 # the size of the intercolumn gap
+
+define MKCAT_COMMENTSTR "# " # the comment string
+define MKCAT_CONTSTR "* " # the continuation string
+define MKCAT_BLANKSTR " " # the blank string
+define MKCAT_NULLSTR "" # the null string
+define MKCAT_SZSTR 2 # the size of MKCAT strings
+
+define MKCAT_COMMENTCHAR '#' # the comment character
+
+
+# Define the initial sizes for internal table storage.
+
+define LEN_CATDAT 100
+define LEN_CATOBS 100
+define LEN_OBSOBS 100
+
+
+# General catalog and observations formatting definitions
+
+define COMMENT "^\#" # the comment string
+define CONTINUATION "^\* " # the continuation character
+
+# Maximum number of continuation lines. This constant is used only for
+# memory allocation and not to check for the number of lines.
+
+define MAX_CONT 10
+
+
+# Record names for FITPARAMS output file. These are the record names
+# used by the DTTEXT procedures to identify records in a text database.
+
+define STATUS "status" # fit status
+define WEIGHTING "weights" # weights definition
+define ERRORS "errors" # error definition
+define VARIANCE "variance" # fit variance
+define STDEV "stdeviation" # fit standard deviation
+define AVSQERROR "avsqerror" # average error squared
+define AVERROR "averror" # average error
+define AVSQSCATTER "avsqscatter" # additional scatter-squared
+define AVSCATTER "avscatter" # additional scatter
+define MSQ "msq" # fit mean-square
+define RMS "rms" # fit root-mean-square
+define CHISQR "chisqr" # fit reduced chi-squared
+define REFERENCE "reference" # reference equation name
+define FITTING "fitting" # fitting equation name
+define DERIVATIVES "derivatives" # derivative equation names
+define PARAMETERS "parameters" # parameter names
+define VALUES "values" # parameter values
+define ERRORS "errors" # parameter errors
+
+
+# Define the permitted output types for EVALFIT and INVERTFIT
+
+define TYPE_ALL 1
+define TYPE_PROGRAM 2
+define TYPE_STANDARDS 3
+define TYPE_STRING ",all,program,standards,"
+
+
+# Define the permitted output error types for EVALFIT and INVERTFIT
+
+define ERR_UNDEFINED 1
+define ERR_OBSERRORS 2
+define ERR_EQUATIONS 3
+define ERR_OPTIONS ",undefined,obserrors,equations,"
diff --git a/noao/digiphot/photcal/lib/lexer.h b/noao/digiphot/photcal/lib/lexer.h
new file mode 100644
index 00000000..b3d610d4
--- /dev/null
+++ b/noao/digiphot/photcal/lib/lexer.h
@@ -0,0 +1,60 @@
+# Lexer structure lengths
+define LEN_ID SZ_LINE # string length
+define LEN_CODE SZ_LINE # code length
+define LEN_LEX (3+LEN_ID+LEN_CODE) # total structure length
+
+# Lexer structure
+define LEX_TOK Memi[$1+0] # token
+define LEX_VAL Memr[P2R($1+1)] # numeric value (if any)
+define LEX_ID Memc[P2C($1+2)] # character string
+define LEX_CLEN Memi[$1+LEN_ID+2] # code length
+define LEX_CODE ($1+LEN_ID+3) # RPN code buffer
+
+
+# Minimum number of characters required when a keyword is abbreviated
+define ABBREVIATE 3
+
+
+# Keywords
+define KEYWORDS "|catalog|observations|extinction|transformations|\
+ |fit|constant|delta|\
+ |error|weight|minimum|maximum|\
+ |set|derivative|plot|"
+
+# Keyword codes
+define K_CATALOG 1 # catalog section
+define K_OBSERVATION 2 # observation section
+define K_EXTINCTION 3 # extinction section
+define K_TRANSFORMATION 4 # transformation section
+ # newline 5
+define K_FIT 6 # fitting parameter declaration
+define K_CONSTANT 7 # constant parameter declaration
+define K_DELTA 8 # parameter delta declaration
+ # newline 9
+define K_ERROR 10 # error column/equation
+define K_WEIGHT 11 # weight column/equation
+define K_MIN 12 # minimum equation (error/weight)
+define K_MAX 13 # maximum equation (error/weight)
+ # newline 14
+define K_SET 15 # set equation
+define K_DERIVATIVE 16 # derivative equation
+define K_PLOT 17 # plot equations
+
+
+# Functions
+define FUNCTIONS "|abs|acos|asin|atan|cos|exp|log|log10|sin|\
+ |sqrt|tan|"
+
+# Function codes
+define K_ABS 1 # absolute value
+define K_ACOS 2 # arccosine
+define K_ASIN 3 # arcsine
+define K_ATAN 4 # arctangent
+define K_COS 5 # cosine
+define K_EXP 6 # sine
+define K_LOG 7 # natural logarithm
+define K_LOG10 8 # decimal logarithm
+define K_SIN 9 # sine
+ # newline 10
+define K_SQRT 11 # square root
+define K_TAN 12 # tangent
diff --git a/noao/digiphot/photcal/lib/mctable.h b/noao/digiphot/photcal/lib/mctable.h
new file mode 100644
index 00000000..70d8b9c9
--- /dev/null
+++ b/noao/digiphot/photcal/lib/mctable.h
@@ -0,0 +1,28 @@
+# Multicolumn table structure.
+
+# Pointer Mem
+define MEMP Memi
+
+# Magic number
+define MAGIC 1989
+
+# Growing factor computation. This formula is used to compute
+# the increment is memory allocation in terms of the memory
+# already allocated, but avoiding a zero or a large factor.
+# The real number in the formula represents the fraction to grow,
+# and it should be greater than zero and less than one, although
+# the formula takes care of out of range values.
+define GROWFACTOR min (max (int ($1 * 0.5), 1), $1) # 50%
+
+# Multi-column table structure
+define LEN_MCTABLE 10 # structure size
+define MCT_MAGIC Memi[$1+0] # magic number
+define MCT_TYPE Memi[$1+1] # table data type
+define MCT_MAXROW Memi[$1+2] # max number of rows (growing)
+define MCT_MAXCOL Memi[$1+3] # max number of columns (fixed)
+define MCT_INCROWS Memi[$1+4] # row growing increment
+define MCT_NPROWS Memi[$1+5] # highest row entered
+define MCT_NPCOLS Memi[$1+6] # highest column entered
+define MCT_NGROWS Memi[$1+7] # highest row gotten
+define MCT_NGCOLS Memi[$1+8] # highest column gotten
+define MCT_DATA MEMP[$1+9] # data buffer pointer
diff --git a/noao/digiphot/photcal/lib/obsfile.h b/noao/digiphot/photcal/lib/obsfile.h
new file mode 100644
index 00000000..e101428c
--- /dev/null
+++ b/noao/digiphot/photcal/lib/obsfile.h
@@ -0,0 +1,51 @@
+# Set up the definitions for the required input fields
+
+define CAT_NFIELDS 10
+
+define CAT_IMAGE 1 # the image name
+define CAT_XCENTER 2 # x center position
+define CAT_YCENTER 3 # y center position
+define CAT_IFILTER 4 # the filter id
+define CAT_ITIME 5 # the exposure time
+define CAT_XAIRMASS 6 # the airmass
+define CAT_OTIME 7 # the time of observation
+define CAT_MAG 8 # magnitude
+define CAT_MERR 9 # magnitude error
+define CAT_ID 10 # the object name
+
+define OBS_NFIELDS 5
+
+define OBS_IMAGE 1 # the image name
+define OBS_IFILTER 2 # the corrected filter id
+define OBS_ITIME 3 # the corrected exposure time
+define OBS_XAIRMASS 4 # the corrected airmass
+define OBS_OTIME 5 # the corrected time of observation
+
+# Define the IMTABLE data structure
+
+define LEN_IMT_STRUCT (10 + 3 * SZ_FNAME + 3)
+
+define IMT_IMSETNO Memi[$1] # the image set id number
+define IMT_IMNO Memi[$1+1] # the image sequence number
+define IMT_OFFSET Memi[$1+2] # offset to image data
+define IMT_NENTRIES Memi[$1+3] # number of data entries
+define IMT_XSHIFT Memr[P2R($1+4)] # x shift in pixels
+define IMT_YSHIFT Memr[P2R($1+5)] # y shift in pixels
+define IMT_APERCOR Memr[P2R($1+6)] # aperture corrections
+define IMT_ITIME Memr[P2R($1+7)] # the exposure times
+define IMT_XAIRMASS Memr[P2R($1+8)] # the airmasses
+define IMT_OTIME Memr[P2R($1+9)] # time of observations
+define IMT_IFILTER Memc[P2C($1+10)] # the filter ids
+define IMT_LABEL Memc[P2C($1+10+SZ_FNAME+1)] # image set labels
+define IMT_IMNAME Memc[P2C($1+10+2*SZ_FNAME+2)] # image names
+
+# Miscellaneous
+
+define LEN_IMTABLE 100 # initial length of the image table
+define DEF_BUFSIZE 1000 # default object data buffer size
+
+define FIRST_COLUMN 3
+define DELTA_COLUMN 2
+
+define DEF_LENLABEL 15 # the default object label length
+define DEF_LENINDEX 6 # the default index
diff --git a/noao/digiphot/photcal/lib/parser.h b/noao/digiphot/photcal/lib/parser.h
new file mode 100644
index 00000000..da88ffeb
--- /dev/null
+++ b/noao/digiphot/photcal/lib/parser.h
@@ -0,0 +1,169 @@
+# PARSER.H - Parser codes to use with the prget and prput procedures.
+
+
+# Parser tables (pointer)
+
+define SYMTABLE 1 # symbol table
+define OBSTABLE 2 # observational variable table
+define CATTABLE 3 # catalog variable table
+define PARTABLE 4 # fitting and constant parameter table
+define EXTTABLE 5 # extinction equation table
+define TRNTABLE 6 # transformation equation table
+define SETTABLE 7 # set equation table
+define TRCATTABLE 8 # temporary ref. catalog var. table
+define TROBSTABLE 9 # temporary ref. obs. var. table
+define TFCATTABLE 10 # temporary fit catalog var. table
+define TFOBSTABLE 11 # temporary fit obs. var. table
+define TPARTABLE 12 # temporary parameter table
+
+
+# Parser counters (int)
+
+define NERRORS 20 # errors
+define NWARNINGS 21 # warnings
+define NOBSVARS 22 # observational variables
+define NCATVARS 23 # catalog variables
+define NFITPARS 24 # fitting parameters
+define NTOTPARS 25 # parameters (fitting + constant)
+define NSETEQS 26 # set equations
+define NEXTEQS 27 # extinction equations
+define NTRNEQS 28 # transformation equations
+
+
+# Parser column limit values (int)
+
+define MINCOL 30 # min. input column
+define MINOBSCOL 31 # min. observational column
+define MAXOBSCOL 32 # max. observational column
+define MINCATCOL 33 # max. catalog column
+define MAXCATCOL 34 # max. catalog column
+
+
+# Parser flags (int)
+
+define FLAGEQSECT 40 # equation section
+define FLAGERRORS 41 # flag errors (YES/NO)
+
+
+# Symbol types (int)
+
+define PTY_OBSVAR 50 # observation input variable
+define PTY_CATVAR 51 # catalog input variable
+define PTY_FITPAR 52 # fitting parameter
+define PTY_CONST 53 # constant parameter
+define PTY_SETEQ 54 # set equation
+define PTY_EXTEQ 55 # extinction equation
+define PTY_TRNEQ 56 # transformation equation
+
+
+# Symbol attributes (int, pointer)
+
+define PSYMTYPE 60 # type (int)
+define PSYMNUM 61 # number (int)
+define PSYMSUB 62 # substructure (pointer)
+
+
+# Input variable attributes (int)
+
+define PINPCOL 70 # column
+define PINPERRCOL 71 # error column
+define PINPWTSCOL 72 # error column
+define PINPSPARE 73 # spare flag
+
+
+# Fitting parameter attributes (real)
+
+define PFITVALUE 80 # value
+define PFITDELTA 81 # delta
+
+
+# Set equation character strings (int)
+
+define PSEQEQ 90 # equation
+define PSEQERROR 91 # error
+define PSEQERRMIN 92 # minimum error
+define PSEQERRMAX 93 # maximum error
+define PSEQWEIGHT 94 # weight
+define PSEQWTSMIN 95 # minimum weight
+define PSEQWTSMAX 96 # maximum weight
+
+
+# Set equation code pointers (int)
+
+define PSEQRPNEQ 100 # equation
+define PSEQRPNERROR 101 # error
+define PSEQRPNERRMIN 102 # minimum error
+define PSEQRPNERRMAX 103 # maximum error
+define PSEQRPNWEIGHT 104 # weight
+define PSEQRPNWTSMIN 105 # minimum weight
+define PSEQRPNWTSMAX 106 # maximum weight
+
+
+# Transformation equation counters (int)
+
+define PTEQNRCAT 110 # number of catalog var. (reference)
+define PTEQNROBS 111 # number of obs. variables (reference)
+define PTEQNRVAR 112 # number of variables (reference)
+define PTEQNFCAT 113 # number of catalog variables (fit)
+define PTEQNFOBS 114 # number of obs. variables (fit)
+define PTEQNFVAR 115 # number of variables (fit)
+define PTEQNVAR 116 # total number of variables (ref + fit)
+define PTEQNPAR 117 # number of parameters
+define PTEQNFPAR 118 # number of fitting parameters
+
+
+# Transformation equation character strings (pointer)
+
+define PTEQFIT 120 # fit
+define PTEQREF 121 # reference
+define PTEQDER 122 # derivatives
+define PTEQERROR 123 # error
+define PTEQERRMIN 124 # minimum error
+define PTEQERRMAX 125 # maximum error
+define PTEQWEIGHT 126 # weight
+define PTEQWTSMIN 127 # minimum weight
+define PTEQWTSMAX 128 # maximum weight
+define PTEQXPLOT 129 # x plot
+define PTEQYPLOT 130 # y plot
+
+
+# Transformation equation codes (pointer)
+
+define PTEQRPNFIT 140 # fitting
+define PTEQRPNREF 141 # reference
+define PTEQRPNDER 142 # derivatives
+define PTEQRPNERROR 143 # error
+define PTEQRPNERRMIN 144 # minimum error
+define PTEQRPNERRMAX 145 # maximum error
+define PTEQRPNWEIGHT 146 # weight
+define PTEQRPNWTSMIN 147 # minimum weight
+define PTEQRPNWTSMAX 148 # maximum weight
+define PTEQRPNXPLOT 149 # x plot
+define PTEQRPNYPLOT 150 # y plot
+
+
+# Transformation equation buffers (pointer)
+
+define PTEQSPAR 160 # parameter symbols
+define PTEQSPARVAL 161 # parameter values
+define PTEQSPLIST 162 # parameter list
+define PTEQSREFVAR 163 # reference eq. variable symbols
+define PTEQSREFCNT 164 # reference eq. variable counters
+define PTEQSFITVAR 165 # fit eq. variable symbols
+define PTEQSFITCNT 166 # fit eq. variable counters
+
+
+# Transformaion equation variable symbols and counters (int)
+
+define PTEQREFVAR 170 # reference eq. variable symbols
+define PTEQREFCNT 171 # reference eq. counter
+define PTEQFITVAR 172 # fit eq. variable symbols
+define PTEQFITCNT 173 # fit eq. counter
+
+
+# Transformation equation fitting and constant parameter
+# attributes (int, real)
+
+define PTEQPAR 180 # parameter symbols (int)
+define PTEQPARVAL 181 # parameter values (real)
+define PTEQPLIST 182 # parameter list (int)
diff --git a/noao/digiphot/photcal/lib/prdefs.h b/noao/digiphot/photcal/lib/prdefs.h
new file mode 100644
index 00000000..3f60a528
--- /dev/null
+++ b/noao/digiphot/photcal/lib/prdefs.h
@@ -0,0 +1,30 @@
+# PRDEFS.H -- Parser definitions.
+
+
+# ----------------------------------------------------------------------
+# Severity error codes.
+define PERR_WARNING 1 # warning
+define PERR_SYNTAX 2 # syntax error
+define PERR_SEMANTIC 3 # semantic error
+define PERR_POSTPROC 4 # post processing error
+
+
+# ----------------------------------------------------------------------
+# Equation sections. Equations are divided in sections by the parser, to
+# take different semantic actions over expressions depending on the section.
+
+define PRS_SETEQ 1 # beginning of set equation
+
+define PRS_TRNREF 2 # transformation reference equation
+define PRS_TRNFIT 3 # transformation fitting equation
+define PRS_TRNDER 4 # transformation derivative equations
+define PRS_TRNPLOT 5 # transformation plot equations
+
+define PRS_ERREQ 6 # error equation
+define PRS_WTSEQ 7 # weight equation
+define PRS_LMTEQ 8 # limit equations
+
+# -------------------------------------------------------------------------
+# Define some default parameter values
+
+define DEF_PFITDELTA 0.1
diff --git a/noao/digiphot/photcal/lib/preval.h b/noao/digiphot/photcal/lib/preval.h
new file mode 100644
index 00000000..32e6f31c
--- /dev/null
+++ b/noao/digiphot/photcal/lib/preval.h
@@ -0,0 +1,41 @@
+# Evaluator codes. These codes are the only ones recognized by the
+# run-time expression evaluator, during the evaluation of the RPN
+# code generated by the parser.
+
+# End of code marker
+define PEV_EOC (-1)
+
+# Numbers
+define PEV_NUMBER 0 # real constant
+
+# Variables
+define PEV_OBSVAR 1 # observational variable
+define PEV_CATVAR 2 # catalog variable
+define PEV_PARAM 3 # fitting or constant parameter
+define PEV_SETEQ 4 # set equation
+define PEV_EXTEQ 5 # extinction equation
+define PEV_TRNEQ 6 # transformation equation
+
+# Unary operators
+define PEV_UPLUS 10 # unary plus
+define PEV_UMINUS 11 # unary minus
+
+# Binary operators
+define PEV_PLUS 20 # addition
+define PEV_MINUS 21 # substraction
+define PEV_STAR 22 # multiplication
+define PEV_SLASH 23 # division
+define PEV_EXPON 24 # exponentiation
+
+# Functions
+define PEV_ABS 30 # absolute value
+define PEV_ACOS 31 # arc cosine
+define PEV_ASIN 32 # arc sine
+define PEV_ATAN 33 # arc tangent
+define PEV_COS 34 # cosine
+define PEV_EXP 35 # exponential
+define PEV_LOG 36 # natural logarithm
+define PEV_LOG10 37 # decimal logarithm
+define PEV_SIN 38 # sine
+define PEV_SQRT 39 # square root
+define PEV_TAN 40 # tangent
diff --git a/noao/digiphot/photcal/lib/prstruct.h b/noao/digiphot/photcal/lib/prstruct.h
new file mode 100644
index 00000000..f5a25e73
--- /dev/null
+++ b/noao/digiphot/photcal/lib/prstruct.h
@@ -0,0 +1,344 @@
+# PRSTRUCT.H -- Parser symbol table structure.
+
+
+# Pointer access
+define MEMP Memi
+
+
+# ----------------------------------------------------------------------
+# Parser symbol structure. The symbol table is handled by the SYMTAB
+# procedures. The following is the definition of the structure associated
+# with each identifier in the table. The following diagram shows graphically
+# this structure:
+#
+# offset
+# +---------------------------------------+
+# 0 | symbol type |
+# +---------------------------------------+
+# 1 | symbol number |
+# +---------------------------------------+
+# 2 | substructure pointer | ->
+# +---------------------------------------+
+# 3 next free location
+#
+
+# Symbol structure length
+define LEN_PSYM 3
+
+# Symbol structure definition
+define PSYM_TYPE Memi[$1+0] # type
+define PSYM_NUM Memi[$1+1] # sequential number
+define PSYM_SUB MEMP[$1+2] # symbol substructure
+# next free location ($1 + 3) == LEN_PSYM !!!
+
+
+# ----------------------------------------------------------------------
+# Input column substructure. This substructure is supported for catalog
+# and observation input columns (PTY_CATCOL and PTY_OBSCOL). The following
+# diagram shows graphically this structure:
+#
+# offset
+# +---------------------------------------+
+# 0 | input column number |
+# +---------------------------------------+
+# 1 | error column number |
+# +---------------------------------------+
+# 2 | weight column number |
+# +---------------------------------------+
+# 3 | spare column flag |
+# +---------------------------------------+
+# 4 next free location
+#
+
+# Input column substructure length.
+define LEN_PINP 4
+
+# Input column substructure definition
+define PINP_COL Memi[$1+0] # input column
+define PINP_ERRCOL Memi[$1+1] # error column
+define PINP_WTSCOL Memi[$1+2] # weight column
+define PINP_SPARE Memi[$1+3] # spare flag (YES/NO)
+# next free location ($1 + 4) == LEN_PINP !!!
+
+
+# ----------------------------------------------------------------------
+# Fitting parameter substructure. This substructure is supported for
+# fitting and constant parameters (PTY_FITPAR and PTY_CONST). The
+# following diagram shows graphically this structure:
+#
+# offset
+# +---------------------------------------+
+# 0 | parameter value |
+# +---------------------------------------+
+# 1 | parameter delta |
+# +---------------------------------------+
+# 2 next free location
+#
+
+# Fitting parameter substructure length.
+define LEN_PFIT 2
+
+# Fitting parameter substructure definition
+define PFIT_VALUE Memr[P2R($1+0)] # parameter value
+define PFIT_DELTA Memr[P2R($1+1)] # parameter delta
+# next free location ($1 + 2) == LEN_PFIT !!!
+
+
+# ----------------------------------------------------------------------
+# Set equation substructure. This substructure is supported for set
+# equation symbols (PTY_SETEQ). The length of this substructure is
+# fixed.
+#
+# offset
+# +---------------------------------------+
+# 0 | set equation string offset |
+# +---------------------------------------+
+# 1 | error equation string offset |
+# +---------------------------------------+
+# 2 | min error equation string offset |
+# +---------------------------------------+
+# 3 | max error equation string offset |
+# +---------------------------------------+
+# 4 | weight equation string offset |
+# +---------------------------------------+
+# 5 | min weight equation string offset |
+# +---------------------------------------+
+# 6 | max weight equation string offset |
+# +---------------------------------------+
+# 7 | weight equation string offset |
+# +---------------------------------------+
+# 8 | error equation code pointer | ->
+# +---------------------------------------+
+# 9 | min error equation code pointer | ->
+# +---------------------------------------+
+# 10 | max error equation code pointer | ->
+# +---------------------------------------+
+# 11 | weight equation code pointer | ->
+# +---------------------------------------+
+# 12 | min weight equation code pointer | ->
+# +---------------------------------------+
+# 13 | max weight equation code pointer | ->
+# +---------------------------------------+
+# 14 next free location
+#
+
+# Set equation substructure length.
+define LEN_PSEQ 14
+
+# Set equation substructure definition
+define PSEQ_EQ Memi[$1 + 0] # equation string offset
+define PSEQ_ERROR Memi[$1 + 1] # error equation string offset
+define PSEQ_ERRMIN Memi[$1 + 2] # min error equation string offset
+define PSEQ_ERRMAX Memi[$1 + 3] # max error equation string offset
+define PSEQ_WEIGHT Memi[$1 + 4] # weight equation string offset
+define PSEQ_WTSMIN Memi[$1 + 5] # min weight equation string offset
+define PSEQ_WTSMAX Memi[$1 + 6] # max weight equation string offset
+define PSEQ_RPNEQ MEMP[$1 + 7] # equation code
+define PSEQ_RPNERROR MEMP[$1 + 8] # error equation code
+define PSEQ_RPNERRMIN MEMP[$1 + 9] # min error equation code
+define PSEQ_RPNERRMAX MEMP[$1 + 10] # max error equation code
+define PSEQ_RPNWEIGHT MEMP[$1 + 11] # weigt equation code
+define PSEQ_RPNWTSMIN MEMP[$1 + 12] # min weight equation code
+define PSEQ_RPNWTSMAX MEMP[$1 + 13] # max weight equation code
+# next free location ($1 + 14) == LEN_PSEQ !!!
+
+
+# ----------------------------------------------------------------------
+# Transformation equation substructure. This substructure is supported
+# for transformation equation symbols (PTY_TRNEQ). The length of this
+# substructure is variable, and depends on the total number of variables
+# (nvar) and parameters (npar) in the equation. The following diagram
+# shows graphically this structure:
+#
+# offset
+# +---------------------------------------+
+# 0 | number of ref. catalog var. = nrcat |
+# +---------------------------------------+
+# 1 | number of ref. obs. var. = nrobs |
+# +---------------------------------------+
+# 2 | total number of ref. var. = nrvar |
+# +---------------------------------------+
+# 3 | number of fit catalog var. = nfcat |
+# +---------------------------------------+
+# 4 | number of fit obs. var. = nfobs |
+# +---------------------------------------+
+# 5 | total number of fit var. = nfvar |
+# +---------------------------------------+
+# 6 | total number of variables = nvar |
+# +---------------------------------------+
+# 7 | ref. variable symbol offsets (nrvar) |
+# | ... |
+# | ... |
+# +---------------------------------------+
+# 1 * nrvar + 7 | ref. variable counters (nrvar) |
+# | ... |
+# | ... |
+# +---------------------------------------+
+# 2 * nrvar + 7 | fit variable symbol offsets (nfvar) |
+# | ... |
+# | ... |
+# +---------------------------------------+
+# 2 * nrvar + 1 * nfvar + 7 | fit variable counters (nfvar) |
+# | ... |
+# | ... |
+# +---------------------------------------+
+# 2 * nvar + 7 | number of parameters = npar |
+# +---------------------------------------+
+# 2 * nvar + 8 | number of fitting parameters |
+# +---------------------------------------+
+# 2 * nvar + 9 | parameter symbol offsets (npar) |
+# | ... |
+# | ... |
+# +---------------------------------------+
+# 2 * nvar + 1 * npar + 9 | parameter values (npar) |
+# | ... |
+# | ... |
+# +---------------------------------------+
+# 2 * nvar + 2 * npar + 9 | parameter list (npar) |
+# | ... |
+# | ... |
+# +---------------------------------------+
+# 2 * nvar + 3 * npar + 9 | fit equation string offset |
+# +---------------------------------------+
+# 2 * nvar + 3 * npar + 10 | reference equation string offset |
+# +---------------------------------------+
+# 2 * nvar + 3 * npar + 11 | error equation string offset |
+# +---------------------------------------+
+# 2 * nvar + 3 * npar + 12 | min error equation string offset |
+# +---------------------------------------+
+# 2 * nvar + 3 * npar + 13 | max error equation string offset |
+# +---------------------------------------+
+# 2 * nvar + 3 * npar + 14 | weight equation string offset |
+# +---------------------------------------+
+# 2 * nvar + 3 * npar + 15 | min weight equation string offset |
+# +---------------------------------------+
+# 2 * nvar + 3 * npar + 16 | max weight equation string offset |
+# +---------------------------------------+
+# 2 * nvar + 3 * npar + 17 | X plot equation string offset |
+# +---------------------------------------+
+# 2 * nvar + 3 * npar + 18 | Y plot equation string offset |
+# +---------------------------------------+
+# 2 * nvar + 3 * npar + 19 | derivative equation offsets (npar) |
+# | ... |
+# | ... |
+# +---------------------------------------+
+# 2 * nvar + 4 * npar + 19 | fit equation code pointer | ->
+# +---------------------------------------+
+# 2 * nvar + 4 * npar + 20 | reference equation code pointer | ->
+# +---------------------------------------+
+# 2 * nvar + 4 * npar + 21 | error equation code pointer | ->
+# +---------------------------------------+
+# 2 * nvar + 4 * npar + 22 | min error equation code pointer | ->
+# +---------------------------------------+
+# 2 * nvar + 4 * npar + 23 | max error equation code pointer | ->
+# +---------------------------------------+
+# 2 * nvar + 4 * npar + 24 | weight equation code pointer | ->
+# +---------------------------------------+
+# 2 * nvar + 4 * npar + 25 | min weight equation code pointer | ->
+# +---------------------------------------+
+# 2 * nvar + 4 * npar + 26 | max weight equation code pointer | ->
+# +---------------------------------------+
+# 2 * nvar + 4 * npar + 27 | X plot equation code pointer | ->
+# +---------------------------------------+
+# 2 * nvar + 4 * npar + 28 | Y plot equation code pointer | ->
+# +---------------------------------------+
+# 2 * nvar + 4 * npar + 29 | deriv. equation code pointers (npar) | ->
+# | ... | ->
+# | ... | ->
+# +---------------------------------------+
+# 2 * nvar + 5 * npar + 29 next free location
+#
+
+# Transformation equation substructure length. The macro parameters are
+# the total number of variables (npar), and the number of parameters (npar)
+# for the equation.
+define LEN_PTEQ (2 * $1 + 5 * $2 + 29)
+
+# Transformation equation substructure definition
+# - number of catalog and observation variables, and total number of variables
+# for reference equation.
+define PTEQ_NRCAT Memi[$1 + 0]
+define PTEQ_NROBS Memi[$1 + 1]
+define PTEQ_NRVAR Memi[$1 + 2]
+# - number of catalog and observation variables, and total number of variables
+# for fit equation.
+define PTEQ_NFCAT Memi[$1 + 3]
+define PTEQ_NFOBS Memi[$1 + 4]
+define PTEQ_NFVAR Memi[$1 + 5]
+# - total number of variables in the reference and fit equations.
+define PTEQ_NVAR Memi[$1 + 6]
+# - start of reference variable symbol offsets, and variable counters
+define PTEQ_SREFVAR ($1 + 7)
+define PTEQ_SREFCNT ($1 + 1 * PTEQ_NRVAR($1) + 7)
+# - start of fit variable symbol offsets, and variable counters
+define PTEQ_SFITVAR ($1 + 2 * PTEQ_NRVAR($1) + 7)
+define PTEQ_SFITCNT ($1 + 2 * PTEQ_NRVAR($1) + 1 * PTEQ_NFVAR($1) + 7)
+# - total number of parameters and number of parameters to be fitted.
+define PTEQ_NPAR Memi[$1 + 2 * PTEQ_NVAR($1) + 7]
+define PTEQ_NFPAR Memi[$1 + 2 * PTEQ_NVAR($1) + 8]
+# - Start of parameter offsets, parameter values, parameter list
+define PTEQ_SPAR ($1 + 2 * PTEQ_NVAR($1) + 9)
+define PTEQ_SPARVAL ($1 + 2 * PTEQ_NVAR($1) + 1 * PTEQ_NPAR($1) + 9)
+define PTEQ_SPLIST ($1 + 2 * PTEQ_NVAR($1) + 2 * PTEQ_NPAR($1) + 9)
+# - fitting and reference equation string offsets
+define PTEQ_FIT Memi[$1 + 2 * PTEQ_NVAR($1) + 3 * PTEQ_NPAR($1) + 9]
+define PTEQ_REF Memi[$1 + 2 * PTEQ_NVAR($1) + 3 * PTEQ_NPAR($1) + 10]
+# - error, minimum error, and maximum error equation string offsets
+define PTEQ_ERROR Memi[$1 + 2 * PTEQ_NVAR($1) + 3 * PTEQ_NPAR($1) + 11]
+define PTEQ_ERRMIN Memi[$1 + 2 * PTEQ_NVAR($1) + 3 * PTEQ_NPAR($1) + 12]
+define PTEQ_ERRMAX Memi[$1 + 2 * PTEQ_NVAR($1) + 3 * PTEQ_NPAR($1) + 13]
+# - weight, minimum weight, and maximum weight equation string offsets
+define PTEQ_WEIGHT Memi[$1 + 2 * PTEQ_NVAR($1) + 3 * PTEQ_NPAR($1) + 14]
+define PTEQ_WTSMIN Memi[$1 + 2 * PTEQ_NVAR($1) + 3 * PTEQ_NPAR($1) + 15]
+define PTEQ_WTSMAX Memi[$1 + 2 * PTEQ_NVAR($1) + 3 * PTEQ_NPAR($1) + 16]
+# - plot equation string offsets
+define PTEQ_XPLOT Memi[$1 + 2 * PTEQ_NVAR($1) + 3 * PTEQ_NPAR($1) + 17]
+define PTEQ_YPLOT Memi[$1 + 2 * PTEQ_NVAR($1) + 3 * PTEQ_NPAR($1) + 18]
+# - derivative equation string offsets
+define PTEQ_SDER ($1 + 2 * PTEQ_NVAR($1) + 3 * PTEQ_NPAR($1) + 19)
+# - fitting and reference equation codes
+define PTEQ_RPNFIT MEMP[$1 + 2 * PTEQ_NVAR($1) + 4 * PTEQ_NPAR($1) + 19]
+define PTEQ_RPNREF MEMP[$1 + 2 * PTEQ_NVAR($1) + 4 * PTEQ_NPAR($1) + 20]
+# - error equation, minimum error, and maximum error codes
+define PTEQ_RPNERROR MEMP[$1 + 2 * PTEQ_NVAR($1) + 4 * PTEQ_NPAR($1) + 21]
+define PTEQ_RPNERRMIN MEMP[$1 + 2 * PTEQ_NVAR($1) + 4 * PTEQ_NPAR($1) + 22]
+define PTEQ_RPNERRMAX MEMP[$1 + 2 * PTEQ_NVAR($1) + 4 * PTEQ_NPAR($1) + 23]
+# - weigth, minimum weight, maximum weight equation codes
+define PTEQ_RPNWEIGHT MEMP[$1 + 2 * PTEQ_NVAR($1) + 4 * PTEQ_NPAR($1) + 24]
+define PTEQ_RPNWTSMIN MEMP[$1 + 2 * PTEQ_NVAR($1) + 4 * PTEQ_NPAR($1) + 25]
+define PTEQ_RPNWTSMAX MEMP[$1 + 2 * PTEQ_NVAR($1) + 4 * PTEQ_NPAR($1) + 26]
+# - plot equation code3
+define PTEQ_RPNXPLOT MEMP[$1 + 2 * PTEQ_NVAR($1) + 4 * PTEQ_NPAR($1) + 27]
+define PTEQ_RPNYPLOT MEMP[$1 + 2 * PTEQ_NVAR($1) + 4 * PTEQ_NPAR($1) + 28]
+# - start of derivarive equation codes
+define PTEQ_SRPNDER ($1 + 2 * PTEQ_NVAR($1) + 4 * PTEQ_NPAR($1) + 29)
+# - next free location == LEN_PTEQ
+# ($1 + 2 * PTEQ_NVAR($1) + 5 * PTEQ_NPAR($1) + 29)
+
+# Vector access
+define PTEQ_AREFVAR Memi[PTEQ_SREFVAR($1)] # ref. variable sym. off.
+define PTEQ_AREFCNT Memi[PTEQ_SREFCNT($1)] # ref. variable counters
+define PTEQ_AFITVAR Memi[PTEQ_SFITVAR($1)] # fit variable sym. off.
+define PTEQ_AFITCNT Memi[PTEQ_SFITCNT($1)] # fit variable counters
+define PTEQ_APAR Memi[PTEQ_SPAR($1)] # parameter sym. offsets
+define PTEQ_APARVAL Memr[P2R(PTEQ_SPARVAL($1))] # parameter values
+define PTEQ_APLIST Memi[PTEQ_SPLIST($1)] # fitting parameter list
+define PTEQ_ADER Memi[PTEQ_SDER($1)] # derivative string offsets
+define PTEQ_ARPNDER MEMP[PTEQ_SRPNDER($1)] # derivative code
+
+# Individual access for variable symbols and counters.
+define PTEQ_REFVAR Memi[PTEQ_SREFVAR($1) + $2 - 1] # ref. var. symbol off.
+define PTEQ_REFCNT Memi[PTEQ_SREFCNT($1) + $2 - 1] # ref. var. counter
+define PTEQ_FITVAR Memi[PTEQ_SFITVAR($1) + $2 - 1] # fit var. symbol off.
+define PTEQ_FITCNT Memi[PTEQ_SFITCNT($1) + $2 - 1] # fit var. counter
+
+# Individual access for fitting parameter symbols, values and list. The
+# second argument is the parameter number, relative to the equation.
+define PTEQ_PAR Memi[PTEQ_SPAR($1) + $2 - 1] # symbol offset
+define PTEQ_PARVAL Memr[P2R(PTEQ_SPARVAL($1) + $2 - 1)] # value
+define PTEQ_PLIST Memi[PTEQ_SPLIST($1) + $2 - 1] # list element
+
+# Individual access for derivative equation string offsets and codes. The
+# second argument is the parameter number relative to the equation.
+define PTEQ_DER Memi[PTEQ_SDER($1) + $2 - 1] # string offset
+define PTEQ_RPNDER Memi[PTEQ_SRPNDER($1) + $2 - 1] # code
diff --git a/noao/digiphot/photcal/lib/prtoken.h b/noao/digiphot/photcal/lib/prtoken.h
new file mode 100644
index 00000000..8b3119a8
--- /dev/null
+++ b/noao/digiphot/photcal/lib/prtoken.h
@@ -0,0 +1,42 @@
+define OBSSECT 257
+define CATSECT 258
+define EXTSECT 259
+define TRNSECT 260
+define FITID 261
+define CONSTID 262
+define DELTAID 263
+define ERRORID 264
+define WEIGHTID 265
+define MINID 266
+define MAXID 267
+define DERIVID 268
+define PLOTID 269
+define SETID 270
+define F_ABS 271
+define F_ACOS 272
+define F_ASIN 273
+define F_ATAN 274
+define F_COS 275
+define F_EXP 276
+define F_LOG 277
+define F_LOG10 278
+define F_SIN 279
+define F_SQRT 280
+define F_TAN 281
+define IDENTIFIER 282
+define INUMBER 283
+define RNUMBER 284
+define PLUS 285
+define MINUS 286
+define STAR 287
+define SLASH 288
+define EXPON 289
+define COLON 290
+define SEMICOLON 291
+define COMMA 292
+define EQUAL 293
+define LPAR 294
+define RPAR 295
+define EOFILE 296
+define UPLUS 297
+define UMINUS 298
diff --git a/noao/digiphot/photcal/lib/warning.dat b/noao/digiphot/photcal/lib/warning.dat
new file mode 100644
index 00000000..4611b226
--- /dev/null
+++ b/noao/digiphot/photcal/lib/warning.dat
@@ -0,0 +1,11 @@
+
+
+ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+ WARNING FROM THE PHOTCAL PACKAGE LOADER
+ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+
+ The SDAS external package TABLES optionally used by some of the
+ PHOTCAL tasks is not available. The tasks MKNOBSFILE and
+ MKOBSFILE will run only on APPHOT/DAOPHOT output files written
+ in text database format (the default), but will not run on
+ files written in ST tables format.
diff --git a/noao/digiphot/photcal/mctable/mctable.hlp b/noao/digiphot/photcal/mctable/mctable.hlp
new file mode 100644
index 00000000..cdf1fdac
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctable.hlp
@@ -0,0 +1,90 @@
+.help mctable Aug89
+Multicolumn Table Handler.
+
+This package contains routines to handle a contiguous memory buffer as a
+table with one or more columns. The number of columns is fixed at creation
+time, but the number of rows can increase dynamicaly if needed. The table
+data type is fixed at creation time as well.
+.sp
+This package makes a distinction between the physical and logical size of
+the table. The first one is the amount of memory allocated to the table, and
+can increase if more space is needed. The physical size of a table can
+increase dinamycaly when entering data and can decrease up to the logical
+size unless the table is freed.
+The logical size is the amount of memory used by the data in the table,
+and is always less or equal to the physical size. The logical size of a
+table can also increase dinamycaly when entering data, and is zero
+if no data have been entered.
+.sp
+The procedures mct_maxrow() and mct_maxcol() return the amount of physical
+memory used by the table, and the procedures mct_nrows() and mct_ncols() return
+the highest row and column (in the highest row) used by the data in the table,
+i.e. the logical size.
+.sp
+The physical size can be reduced up to the logical size with the mct_shrink()
+procedure. This returns to the system any unused memory used by the table.
+This procedures should ne used with tables that are not intended to grow
+anymore.
+.sp
+The logical size can be set to zero with the mct_reset() procedure. This
+procedure clears all the counters used to keep track of the logical size
+of the table, and also fills all the physical memory with INDEF values.
+.sp
+The mct_clear() procedure fills all the physical memory with a specified
+value, but does not modify the logical size of the table.
+.sp
+It is possible to enter data into the table either sequentially, randomly,
+or a combination of both. The mct_put() procedures enter data randomly into
+the table at given row and column. The mct_sput() procedures enter data
+sequentially into the table after the highest row and column, i.e., they
+start after the last element in table, increasing the logical size by one
+element. The physical size is increased automaticaly if needed.
+.sp
+Data can be retrieved from the table as a pointer to the whole data buffer,
+a pointer to a single row, randomly, or sequentially. The mct_getbuf() returns
+a pointer to the data buffer, the mct_getrow() returns a pointer to the
+beginning of a given row, the mct_get() procedures return a single data
+value for a given row and column, and the mct_sget() procedures return the
+next single data value. Sequential retrieval starts from the last retrieval
+made, either sequential or ramdom. The mct_rew() procedure can be used to
+reset the sequential retrieval counters.
+.sp
+A table can be saved into a file and restored later with the mct_save() and
+mct_restore() procedures. These procedures use the file name instead of a
+file descriptor. When saving only the WRITE_ONLY, READ_WRITE, NEW_FILE, and
+TEMP_FILE file modes are allowed.
+.sp
+.nf
+Entry points:
+
+ mct_alloc (table, nrows, ncols, type) Allocate table space
+ mct_free (table) Free table space
+ mct_shrink (table) Free unused memory
+ mct_copy (itable, otable) Copy table
+
+ mct_save (fname, fmode, table) Save table to file
+ mct_restore (fname, table) Restore table from file
+
+ mct_rew (table) Reset seq. (get) counters
+ mct_reset (table) Reset all table counters
+
+ mct_clear[csilrdxp] (table, value) Clear table with value
+
+nrows = mct_nrows (table) Return highest row used
+ncols = mct_ncols (table) Return highest col. used
+
+nrow = mct_maxrow (table) Return max. number of rows
+ncols = mct_maxcol (table) Return max. number of col.
+
+type = mct_type (table) Return table type
+
+pval = mct_getbuf (table) Get buffer pointer
+pval = mct_getrow (table, row) Get row pointer
+
+value = mct_get[csilrdxp] (table, row, col) Get value randomly
+ mct_put[csilrdxp] (table, row, col, value) Put value randomly
+
+ mct_sput[csilrdxp] (table, value) Put value sequentially
+stat = mct_sget[csilrdxp] (table, value) Get value sequentially
+.fi
+.endhelp
diff --git a/noao/digiphot/photcal/mctable/mctalloc.x b/noao/digiphot/photcal/mctable/mctalloc.x
new file mode 100644
index 00000000..82c6c93c
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctalloc.x
@@ -0,0 +1,48 @@
+include "../lib/mctable.h"
+
+
+# MCT_ALLOC - Allocate table space, reset all table counters, and clear
+# table values to INDEF.
+
+procedure mct_alloc (table, nrows, ncols, type)
+
+pointer table # table descriptor (output)
+int nrows # number of rows
+int ncols # number of columns
+int type # data type
+
+errchk mct_reset()
+
+begin
+ # Test number of rows and colums.
+ if (nrows < 1)
+ call error (0, "mct_alloc: Zero or negative rows")
+ if (ncols < 1)
+ call error (0, "mct_alloc: Zero or negative columns")
+
+ # Check for supported data types.
+ if (type != TY_CHAR &&
+ type != TY_SHORT && type != TY_INT && type != TY_LONG &&
+ type != TY_REAL && type != TY_DOUBLE &&
+ type != TY_COMPLEX &&
+ type != TY_POINTER)
+ call error (0, "mct_alloc: Unknown type")
+
+ # Allocate table structure and initialize it. The only
+ # value that can change in the future is the maximum number
+ # of rows. All others will remain constant.
+
+ call malloc (table, LEN_MCTABLE, TY_STRUCT)
+ MCT_MAGIC (table) = MAGIC
+ MCT_TYPE (table) = type
+ MCT_MAXROW (table) = nrows
+ MCT_MAXCOL (table) = ncols
+ MCT_INCROWS (table) = GROWFACTOR (nrows)
+
+ # Allocate data buffer and undefine it.
+ call malloc (MCT_DATA (table), nrows * ncols, type)
+ call mct_indef (table, MCT_DATA (table), nrows * ncols)
+
+ # Reset table.
+ call mct_reset (table)
+end
diff --git a/noao/digiphot/photcal/mctable/mctclear.gx b/noao/digiphot/photcal/mctable/mctclear.gx
new file mode 100644
index 00000000..58eacba9
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctclear.gx
@@ -0,0 +1,33 @@
+include "../lib/mctable.h"
+
+
+$for (csilrdxp)
+# MCT_CLEAR - Clear all table values with given value. Do not reset any
+# table counter.
+
+procedure mct_clear$t (table, value)
+
+pointer table # table descriptor
+PIXEL value # value
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_clear: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_clear: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_PIXEL)
+ call error (0, "mct_clear: Wrong table type")
+
+ # Move value to data buffer
+ $if (datatype == p)
+ call amovki (value, Memi[MCT_DATA (table)],
+ MCT_MAXROW (table) * MCT_MAXCOL (table))
+ $else
+ call amovk$t (value, Mem$t[MCT_DATA (table)],
+ MCT_MAXROW (table) * MCT_MAXCOL (table))
+ $endif
+end
+$endfor
diff --git a/noao/digiphot/photcal/mctable/mctclear.x b/noao/digiphot/photcal/mctable/mctclear.x
new file mode 100644
index 00000000..0c9e9080
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctclear.x
@@ -0,0 +1,195 @@
+include "../lib/mctable.h"
+
+
+
+# MCT_CLEAR - Clear all table values with given value. Do not reset any
+# table counter.
+
+procedure mct_clearc (table, value)
+
+pointer table # table descriptor
+char value # value
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_clear: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_clear: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_CHAR)
+ call error (0, "mct_clear: Wrong table type")
+
+ # Move value to data buffer
+ call amovkc (value, Memc[MCT_DATA (table)],
+ MCT_MAXROW (table) * MCT_MAXCOL (table))
+end
+
+# MCT_CLEAR - Clear all table values with given value. Do not reset any
+# table counter.
+
+procedure mct_clears (table, value)
+
+pointer table # table descriptor
+short value # value
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_clear: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_clear: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_SHORT)
+ call error (0, "mct_clear: Wrong table type")
+
+ # Move value to data buffer
+ call amovks (value, Mems[MCT_DATA (table)],
+ MCT_MAXROW (table) * MCT_MAXCOL (table))
+end
+
+# MCT_CLEAR - Clear all table values with given value. Do not reset any
+# table counter.
+
+procedure mct_cleari (table, value)
+
+pointer table # table descriptor
+int value # value
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_clear: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_clear: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_INT)
+ call error (0, "mct_clear: Wrong table type")
+
+ # Move value to data buffer
+ call amovki (value, Memi[MCT_DATA (table)],
+ MCT_MAXROW (table) * MCT_MAXCOL (table))
+end
+
+# MCT_CLEAR - Clear all table values with given value. Do not reset any
+# table counter.
+
+procedure mct_clearl (table, value)
+
+pointer table # table descriptor
+long value # value
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_clear: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_clear: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_LONG)
+ call error (0, "mct_clear: Wrong table type")
+
+ # Move value to data buffer
+ call amovkl (value, Meml[MCT_DATA (table)],
+ MCT_MAXROW (table) * MCT_MAXCOL (table))
+end
+
+# MCT_CLEAR - Clear all table values with given value. Do not reset any
+# table counter.
+
+procedure mct_clearr (table, value)
+
+pointer table # table descriptor
+real value # value
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_clear: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_clear: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_REAL)
+ call error (0, "mct_clear: Wrong table type")
+
+ # Move value to data buffer
+ call amovkr (value, Memr[MCT_DATA (table)],
+ MCT_MAXROW (table) * MCT_MAXCOL (table))
+end
+
+# MCT_CLEAR - Clear all table values with given value. Do not reset any
+# table counter.
+
+procedure mct_cleard (table, value)
+
+pointer table # table descriptor
+double value # value
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_clear: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_clear: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_DOUBLE)
+ call error (0, "mct_clear: Wrong table type")
+
+ # Move value to data buffer
+ call amovkd (value, Memd[MCT_DATA (table)],
+ MCT_MAXROW (table) * MCT_MAXCOL (table))
+end
+
+# MCT_CLEAR - Clear all table values with given value. Do not reset any
+# table counter.
+
+procedure mct_clearx (table, value)
+
+pointer table # table descriptor
+complex value # value
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_clear: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_clear: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_COMPLEX)
+ call error (0, "mct_clear: Wrong table type")
+
+ # Move value to data buffer
+ call amovkx (value, Memx[MCT_DATA (table)],
+ MCT_MAXROW (table) * MCT_MAXCOL (table))
+end
+
+# MCT_CLEAR - Clear all table values with given value. Do not reset any
+# table counter.
+
+procedure mct_clearp (table, value)
+
+pointer table # table descriptor
+pointer value # value
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_clear: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_clear: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_POINTER)
+ call error (0, "mct_clear: Wrong table type")
+
+ # Move value to data buffer
+ call amovki (value, Memi[MCT_DATA (table)],
+ MCT_MAXROW (table) * MCT_MAXCOL (table))
+end
diff --git a/noao/digiphot/photcal/mctable/mctcopy.gx b/noao/digiphot/photcal/mctable/mctcopy.gx
new file mode 100644
index 00000000..c30f321a
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctcopy.gx
@@ -0,0 +1,63 @@
+include "../lib/mctable.h"
+
+
+# MCT_COPY - Copy one table into another. The destination table is allocated
+# or reallocated if necessary.
+
+procedure mct_copy (itable, otable)
+
+pointer itable # input table descriptor
+pointer otable # output table descriptor
+
+int isize, osize # table sizes
+
+errchk mct_alloc()
+
+begin
+ # Check input pointer and magic number.
+ if (itable == NULL)
+ call error (0, "mct_copy: Null input table pointer")
+ if (MCT_MAGIC (itable) != MAGIC)
+ call error (0, "mct_copy: Bad input magic number")
+
+ # Compute input table size.
+ isize = MCT_MAXROW (itable) * MCT_MAXCOL (itable)
+
+ # Check output pointer. Try to minimize space allocation.
+ if (otable == NULL)
+ call mct_alloc (otable, MCT_MAXROW (itable), MCT_MAXCOL (itable),
+ MCT_TYPE (itable))
+ else if (MCT_MAGIC (otable) == MAGIC) {
+ osize = MCT_MAXROW (otable) * MCT_MAXCOL (otable)
+ if (isize != osize || MCT_TYPE (itable) != MCT_TYPE (otable))
+ call realloc (MCT_DATA (otable), isize, MCT_TYPE (itable))
+ } else
+ call error (0, "mct_copy: Bad output magic number")
+
+ # Copy structure.
+ MCT_MAGIC (otable) = MCT_MAGIC (itable)
+ MCT_TYPE (otable) = MCT_TYPE (itable)
+ MCT_MAXROW (otable) = MCT_MAXROW (itable)
+ MCT_MAXCOL (otable) = MCT_MAXCOL (itable)
+ MCT_INCROWS (otable) = MCT_INCROWS (itable)
+ MCT_NPROWS (otable) = MCT_NPROWS (itable)
+ MCT_NPCOLS (otable) = MCT_NPCOLS (itable)
+ MCT_NGROWS (otable) = MCT_NGROWS (itable)
+ MCT_NGCOLS (otable) = MCT_NGCOLS (itable)
+
+ # Copy data buffer.
+ switch (MCT_TYPE (otable)) {
+ $for (csilrdxp)
+ case TY_PIXEL:
+ $if (datatype == p)
+ call amovi (Memi[MCT_DATA (itable)], Memi[MCT_DATA (otable)],
+ isize)
+ $else
+ call amov$t (Mem$t[MCT_DATA (itable)], Mem$t[MCT_DATA (otable)],
+ isize)
+ $endif
+ $endfor
+ default:
+ call error (0, "mct_copy: Unknown table type")
+ }
+end
diff --git a/noao/digiphot/photcal/mctable/mctcopy.x b/noao/digiphot/photcal/mctable/mctcopy.x
new file mode 100644
index 00000000..bcf54f9c
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctcopy.x
@@ -0,0 +1,86 @@
+include "../lib/mctable.h"
+
+
+# MCT_COPY - Copy one table into another. The destination table is allocated
+# or reallocated if necessary.
+
+procedure mct_copy (itable, otable)
+
+pointer itable # input table descriptor
+pointer otable # output table descriptor
+
+int isize, osize # table sizes
+
+errchk mct_alloc()
+
+begin
+ # Check input pointer and magic number.
+ if (itable == NULL)
+ call error (0, "mct_copy: Null input table pointer")
+ if (MCT_MAGIC (itable) != MAGIC)
+ call error (0, "mct_copy: Bad input magic number")
+
+ # Compute input table size.
+ isize = MCT_MAXROW (itable) * MCT_MAXCOL (itable)
+
+ # Check output pointer. Try to minimize space allocation.
+ if (otable == NULL)
+ call mct_alloc (otable, MCT_MAXROW (itable), MCT_MAXCOL (itable),
+ MCT_TYPE (itable))
+ else if (MCT_MAGIC (otable) == MAGIC) {
+ osize = MCT_MAXROW (otable) * MCT_MAXCOL (otable)
+ if (isize != osize || MCT_TYPE (itable) != MCT_TYPE (otable))
+ call realloc (MCT_DATA (otable), isize, MCT_TYPE (itable))
+ } else
+ call error (0, "mct_copy: Bad output magic number")
+
+ # Copy structure.
+ MCT_MAGIC (otable) = MCT_MAGIC (itable)
+ MCT_TYPE (otable) = MCT_TYPE (itable)
+ MCT_MAXROW (otable) = MCT_MAXROW (itable)
+ MCT_MAXCOL (otable) = MCT_MAXCOL (itable)
+ MCT_INCROWS (otable) = MCT_INCROWS (itable)
+ MCT_NPROWS (otable) = MCT_NPROWS (itable)
+ MCT_NPCOLS (otable) = MCT_NPCOLS (itable)
+ MCT_NGROWS (otable) = MCT_NGROWS (itable)
+ MCT_NGCOLS (otable) = MCT_NGCOLS (itable)
+
+ # Copy data buffer.
+ switch (MCT_TYPE (otable)) {
+
+ case TY_CHAR:
+ call amovc (Memc[MCT_DATA (itable)], Memc[MCT_DATA (otable)],
+ isize)
+
+ case TY_SHORT:
+ call amovs (Mems[MCT_DATA (itable)], Mems[MCT_DATA (otable)],
+ isize)
+
+ case TY_INT:
+ call amovi (Memi[MCT_DATA (itable)], Memi[MCT_DATA (otable)],
+ isize)
+
+ case TY_LONG:
+ call amovl (Meml[MCT_DATA (itable)], Meml[MCT_DATA (otable)],
+ isize)
+
+ case TY_REAL:
+ call amovr (Memr[MCT_DATA (itable)], Memr[MCT_DATA (otable)],
+ isize)
+
+ case TY_DOUBLE:
+ call amovd (Memd[MCT_DATA (itable)], Memd[MCT_DATA (otable)],
+ isize)
+
+ case TY_COMPLEX:
+ call amovx (Memx[MCT_DATA (itable)], Memx[MCT_DATA (otable)],
+ isize)
+
+ case TY_POINTER:
+ call amovi (Memi[MCT_DATA (itable)], Memi[MCT_DATA (otable)],
+ isize)
+
+ default:
+ call error (0, "mct_copy: Unknown table type")
+ }
+end
diff --git a/noao/digiphot/photcal/mctable/mctfree.x b/noao/digiphot/photcal/mctable/mctfree.x
new file mode 100644
index 00000000..f7f3e2c0
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctfree.x
@@ -0,0 +1,20 @@
+include "../lib/mctable.h"
+
+
+# MCT_FREE - Free table structure and data buffer associated with it.
+
+procedure mct_free (table)
+
+pointer table # table descriptor
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_free: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_free: Bad magic number")
+
+ # Free the table.
+ call mfree (MCT_DATA (table), MCT_TYPE (table))
+ call mfree (table, TY_STRUCT)
+end
diff --git a/noao/digiphot/photcal/mctable/mctget.gx b/noao/digiphot/photcal/mctable/mctget.gx
new file mode 100644
index 00000000..f79379c8
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctget.gx
@@ -0,0 +1,46 @@
+include "../lib/mctable.h"
+
+
+$for (csilrdxp)
+# MCT_GET - Get a single value from the table (generic).
+
+PIXEL procedure mct_get$t (table, row, col)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+
+pointer mct_getrow()
+errchk mct_getrow()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_get: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_get: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_PIXEL)
+ call error (0, "mct_get: Wrong table type")
+
+ # Check the row and column range.
+ if (row < 1 || row > MCT_NPROWS (table))
+ call error (0, "mct_get: Bad row number")
+ if (row == MCT_NPROWS (table) && (col < 1 || col > MCT_NPCOLS (table)))
+ call error (0, "mct_get: Bad column number at last row")
+ if (row != MCT_NPROWS (table) && (col < 1 || col > MCT_MAXCOL (table)))
+ call error (0, "mct_get: Bad column number")
+
+ # Update the counters.
+ MCT_NGROWS (table) = row
+ MCT_NGCOLS (table) = col
+
+ # Return value.
+ $if (datatype == p)
+ return (MEMP[mct_getrow (table, row) + col - 1])
+ $else
+ return (Mem$t[mct_getrow (table, row) + col - 1])
+ $endif
+end
+$endfor
diff --git a/noao/digiphot/photcal/mctable/mctget.x b/noao/digiphot/photcal/mctable/mctget.x
new file mode 100644
index 00000000..1ca2b9fa
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctget.x
@@ -0,0 +1,307 @@
+include "../lib/mctable.h"
+
+
+
+# MCT_GET - Get a single value from the table (generic).
+
+char procedure mct_getc (table, row, col)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+
+pointer mct_getrow()
+errchk mct_getrow()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_get: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_get: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_CHAR)
+ call error (0, "mct_get: Wrong table type")
+
+ # Check the row and column range.
+ if (row < 1 || row > MCT_NPROWS (table))
+ call error (0, "mct_get: Bad row number")
+ if (row == MCT_NPROWS (table) && (col < 1 || col > MCT_NPCOLS (table)))
+ call error (0, "mct_get: Bad column number at last row")
+ if (row != MCT_NPROWS (table) && (col < 1 || col > MCT_MAXCOL (table)))
+ call error (0, "mct_get: Bad column number")
+
+ # Update the counters.
+ MCT_NGROWS (table) = row
+ MCT_NGCOLS (table) = col
+
+ # Return value.
+ return (Memc[mct_getrow (table, row) + col - 1])
+end
+
+# MCT_GET - Get a single value from the table (generic).
+
+short procedure mct_gets (table, row, col)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+
+pointer mct_getrow()
+errchk mct_getrow()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_get: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_get: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_SHORT)
+ call error (0, "mct_get: Wrong table type")
+
+ # Check the row and column range.
+ if (row < 1 || row > MCT_NPROWS (table))
+ call error (0, "mct_get: Bad row number")
+ if (row == MCT_NPROWS (table) && (col < 1 || col > MCT_NPCOLS (table)))
+ call error (0, "mct_get: Bad column number at last row")
+ if (row != MCT_NPROWS (table) && (col < 1 || col > MCT_MAXCOL (table)))
+ call error (0, "mct_get: Bad column number")
+
+ # Update the counters.
+ MCT_NGROWS (table) = row
+ MCT_NGCOLS (table) = col
+
+ # Return value.
+ return (Mems[mct_getrow (table, row) + col - 1])
+end
+
+# MCT_GET - Get a single value from the table (generic).
+
+int procedure mct_geti (table, row, col)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+
+pointer mct_getrow()
+errchk mct_getrow()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_get: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_get: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_INT)
+ call error (0, "mct_get: Wrong table type")
+
+ # Check the row and column range.
+ if (row < 1 || row > MCT_NPROWS (table))
+ call error (0, "mct_get: Bad row number")
+ if (row == MCT_NPROWS (table) && (col < 1 || col > MCT_NPCOLS (table)))
+ call error (0, "mct_get: Bad column number at last row")
+ if (row != MCT_NPROWS (table) && (col < 1 || col > MCT_MAXCOL (table)))
+ call error (0, "mct_get: Bad column number")
+
+ # Update the counters.
+ MCT_NGROWS (table) = row
+ MCT_NGCOLS (table) = col
+
+ # Return value.
+ return (Memi[mct_getrow (table, row) + col - 1])
+end
+
+# MCT_GET - Get a single value from the table (generic).
+
+long procedure mct_getl (table, row, col)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+
+pointer mct_getrow()
+errchk mct_getrow()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_get: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_get: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_LONG)
+ call error (0, "mct_get: Wrong table type")
+
+ # Check the row and column range.
+ if (row < 1 || row > MCT_NPROWS (table))
+ call error (0, "mct_get: Bad row number")
+ if (row == MCT_NPROWS (table) && (col < 1 || col > MCT_NPCOLS (table)))
+ call error (0, "mct_get: Bad column number at last row")
+ if (row != MCT_NPROWS (table) && (col < 1 || col > MCT_MAXCOL (table)))
+ call error (0, "mct_get: Bad column number")
+
+ # Update the counters.
+ MCT_NGROWS (table) = row
+ MCT_NGCOLS (table) = col
+
+ # Return value.
+ return (Meml[mct_getrow (table, row) + col - 1])
+end
+
+# MCT_GET - Get a single value from the table (generic).
+
+real procedure mct_getr (table, row, col)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+
+pointer mct_getrow()
+errchk mct_getrow()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_get: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_get: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_REAL)
+ call error (0, "mct_get: Wrong table type")
+
+ # Check the row and column range.
+ if (row < 1 || row > MCT_NPROWS (table))
+ call error (0, "mct_get: Bad row number")
+ if (row == MCT_NPROWS (table) && (col < 1 || col > MCT_NPCOLS (table)))
+ call error (0, "mct_get: Bad column number at last row")
+ if (row != MCT_NPROWS (table) && (col < 1 || col > MCT_MAXCOL (table)))
+ call error (0, "mct_get: Bad column number")
+
+ # Update the counters.
+ MCT_NGROWS (table) = row
+ MCT_NGCOLS (table) = col
+
+ # Return value.
+ return (Memr[mct_getrow (table, row) + col - 1])
+end
+
+# MCT_GET - Get a single value from the table (generic).
+
+double procedure mct_getd (table, row, col)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+
+pointer mct_getrow()
+errchk mct_getrow()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_get: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_get: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_DOUBLE)
+ call error (0, "mct_get: Wrong table type")
+
+ # Check the row and column range.
+ if (row < 1 || row > MCT_NPROWS (table))
+ call error (0, "mct_get: Bad row number")
+ if (row == MCT_NPROWS (table) && (col < 1 || col > MCT_NPCOLS (table)))
+ call error (0, "mct_get: Bad column number at last row")
+ if (row != MCT_NPROWS (table) && (col < 1 || col > MCT_MAXCOL (table)))
+ call error (0, "mct_get: Bad column number")
+
+ # Update the counters.
+ MCT_NGROWS (table) = row
+ MCT_NGCOLS (table) = col
+
+ # Return value.
+ return (Memd[mct_getrow (table, row) + col - 1])
+end
+
+# MCT_GET - Get a single value from the table (generic).
+
+complex procedure mct_getx (table, row, col)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+
+pointer mct_getrow()
+errchk mct_getrow()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_get: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_get: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_COMPLEX)
+ call error (0, "mct_get: Wrong table type")
+
+ # Check the row and column range.
+ if (row < 1 || row > MCT_NPROWS (table))
+ call error (0, "mct_get: Bad row number")
+ if (row == MCT_NPROWS (table) && (col < 1 || col > MCT_NPCOLS (table)))
+ call error (0, "mct_get: Bad column number at last row")
+ if (row != MCT_NPROWS (table) && (col < 1 || col > MCT_MAXCOL (table)))
+ call error (0, "mct_get: Bad column number")
+
+ # Update the counters.
+ MCT_NGROWS (table) = row
+ MCT_NGCOLS (table) = col
+
+ # Return value.
+ return (Memx[mct_getrow (table, row) + col - 1])
+end
+
+# MCT_GET - Get a single value from the table (generic).
+
+pointer procedure mct_getp (table, row, col)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+
+pointer mct_getrow()
+errchk mct_getrow()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_get: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_get: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_POINTER)
+ call error (0, "mct_get: Wrong table type")
+
+ # Check the row and column range.
+ if (row < 1 || row > MCT_NPROWS (table))
+ call error (0, "mct_get: Bad row number")
+ if (row == MCT_NPROWS (table) && (col < 1 || col > MCT_NPCOLS (table)))
+ call error (0, "mct_get: Bad column number at last row")
+ if (row != MCT_NPROWS (table) && (col < 1 || col > MCT_MAXCOL (table)))
+ call error (0, "mct_get: Bad column number")
+
+ # Update the counters.
+ MCT_NGROWS (table) = row
+ MCT_NGCOLS (table) = col
+
+ # Return value.
+ return (MEMP[mct_getrow (table, row) + col - 1])
+end
diff --git a/noao/digiphot/photcal/mctable/mctgetbuf.x b/noao/digiphot/photcal/mctable/mctgetbuf.x
new file mode 100644
index 00000000..a9c6dbbb
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctgetbuf.x
@@ -0,0 +1,23 @@
+include "../lib/mctable.h"
+
+
+# MCT_GETBUF - Get pointer to data buffer.
+
+pointer procedure mct_getbuf (table)
+
+pointer table # table descriptor
+
+pointer mct_getrow()
+
+errchk mct_getrow()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_getbuf: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_getbuf: Bad magic number")
+
+ # Return pointer to data buffer.
+ return (mct_getrow (table, 1))
+end
diff --git a/noao/digiphot/photcal/mctable/mctgetrow.x b/noao/digiphot/photcal/mctable/mctgetrow.x
new file mode 100644
index 00000000..bc46b06e
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctgetrow.x
@@ -0,0 +1,25 @@
+include "../lib/mctable.h"
+
+
+# MCT_GETROW - Get pointer to row data values.
+
+pointer procedure mct_getrow (table, row)
+
+pointer table # table descriptor
+int row # row number
+
+begin
+ # Check the pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_getrow: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_getrow: Bad magic number")
+
+ # Return the pointer to a row buffer, or NULL.
+ # if row is out of range
+ if (row < 1 || row > MCT_NPROWS (table))
+ call error (0, "mct_getrow: Bad row number")
+
+ # Return row pointer.
+ return (MCT_DATA (table) + (row - 1) * MCT_MAXCOL (table))
+end
diff --git a/noao/digiphot/photcal/mctable/mctindef.x b/noao/digiphot/photcal/mctable/mctindef.x
new file mode 100644
index 00000000..f3e3427c
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctindef.x
@@ -0,0 +1,40 @@
+include "../lib/mctable.h"
+
+
+# MCT_INDEF - Fill table buffer with undefined values, acording to the
+# data type used.
+
+procedure mct_indef (table, buffer, npts)
+
+pointer table # table descriptor
+pointer buffer # buffer to clear
+int npts # number of untis to clear
+
+char cval
+short sval
+
+begin
+ # Clear according to data type.
+ switch (MCT_TYPE (table)) {
+ case TY_CHAR:
+ cval = '\000'
+ call amovkc (cval, Memc[buffer], npts)
+ case TY_SHORT:
+ sval = INDEFS
+ call amovks (sval, Mems[buffer], npts)
+ case TY_INT:
+ call amovki (INDEFI, Memi[buffer], npts)
+ case TY_LONG:
+ call amovkl (INDEFL, Meml[buffer], npts)
+ case TY_REAL:
+ call amovkr (INDEFR, Memr[buffer], npts)
+ case TY_DOUBLE:
+ call amovkd (INDEFD, Memd[buffer], npts)
+ case TY_COMPLEX:
+ call amovkx (INDEFX, Memx[buffer], npts)
+ case TY_POINTER:
+ call amovki (NULL, Memi[buffer], npts)
+ default:
+ call error (0, "mct_indef: Unknown data type")
+ }
+end
diff --git a/noao/digiphot/photcal/mctable/mctmaxcol.x b/noao/digiphot/photcal/mctable/mctmaxcol.x
new file mode 100644
index 00000000..74f341ae
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctmaxcol.x
@@ -0,0 +1,19 @@
+include "../lib/mctable.h"
+
+
+# MCT_MAXCOL - Return the maximum number of columns in the table.
+
+int procedure mct_maxcol (table)
+
+pointer table # table descriptor
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_maxcol: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_maxcol: Bad magic number")
+
+ # Return max number of columns
+ return (MCT_MAXCOL (table))
+end
diff --git a/noao/digiphot/photcal/mctable/mctmaxrow.x b/noao/digiphot/photcal/mctable/mctmaxrow.x
new file mode 100644
index 00000000..25d21067
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctmaxrow.x
@@ -0,0 +1,19 @@
+include "../lib/mctable.h"
+
+
+# MCT_MAXROW - Return the maximum number of rows of the table.
+
+int procedure mct_maxrow (table)
+
+pointer table # table descriptor
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_mxrow: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_mxrow: Bad magic number")
+
+ # Return max number of rows.
+ return (MCT_MAXROW (table))
+end
diff --git a/noao/digiphot/photcal/mctable/mctncols.x b/noao/digiphot/photcal/mctable/mctncols.x
new file mode 100644
index 00000000..65baea8d
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctncols.x
@@ -0,0 +1,20 @@
+include "../lib/mctable.h"
+
+
+# MCT_NCOLS - Return the highest column number for the highest row, entered
+# into the table
+
+int procedure mct_ncols (table)
+
+pointer table # table descriptor
+
+begin
+ # Check the pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_ncols: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_ncols: Bad magic number")
+
+ # Return column counter.
+ return (MCT_NPCOLS (table))
+end
diff --git a/noao/digiphot/photcal/mctable/mctnrows.x b/noao/digiphot/photcal/mctable/mctnrows.x
new file mode 100644
index 00000000..06c688c9
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctnrows.x
@@ -0,0 +1,19 @@
+include "../lib/mctable.h"
+
+
+# MCT_NROWS - Return the highest row number entered into the table
+
+int procedure mct_nrows (table)
+
+pointer table # table descriptor
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_nrows: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_nrows: Bad magic number")
+
+ # Return row counter.
+ return (MCT_NPROWS (table))
+end
diff --git a/noao/digiphot/photcal/mctable/mctput.gx b/noao/digiphot/photcal/mctable/mctput.gx
new file mode 100644
index 00000000..893678b1
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctput.gx
@@ -0,0 +1,68 @@
+include "../lib/mctable.h"
+
+$for (csilrdxp)
+# MCT_PUT - Put value randomly (generic)
+
+procedure mct_put$t (table, row, col, value)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+PIXEL value # data value
+
+int offset
+pointer base
+errchk mct_indef()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_put: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_put: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_PIXEL)
+ call error (0, "mct_put: Wrong table type")
+
+ # Test row and column values.
+ if (row < 1)
+ call error (0, "mct_put: Row number less than one")
+ if (col < 1 || col > MCT_MAXCOL (table))
+ call error (0, "mct_put: Column out of range")
+
+ # Reallocate space if necessary.
+ if (row > MCT_MAXROW (table)) {
+
+ # Compute offset of new area.
+ offset = MCT_MAXROW (table) * MCT_MAXCOL (table)
+
+ # Recompute new number of rows and reallocate buffer.
+ MCT_MAXROW (table) = MCT_MAXROW (table) + MCT_INCROWS (table)
+ call realloc (MCT_DATA (table),
+ MCT_MAXROW (table) * MCT_MAXCOL (table), TY_PIXEL)
+
+ # Compute base address of new area and clear it with INDEF.
+ base = MCT_DATA (table) + offset
+ call mct_indef (table, base,
+ MCT_INCROWS (table) * MCT_MAXCOL (table))
+ }
+
+ # Update row and column counter, only if the new entries are beyond
+ # the old limits.
+
+ if (row > MCT_NPROWS (table)) {
+ MCT_NPROWS (table) = row
+ MCT_NPCOLS (table) = col
+ } else if (col > MCT_NPCOLS (table))
+ MCT_NPCOLS (table) = col
+
+ # Enter variable.
+ base = MCT_DATA (table) + (row - 1) * MCT_MAXCOL (table)
+ $if (datatype == p)
+ MEMP[base + col - 1] = value
+ $else
+ Mem$t[base + col - 1] = value
+ $endif
+end
+$endfor
diff --git a/noao/digiphot/photcal/mctable/mctput.x b/noao/digiphot/photcal/mctable/mctput.x
new file mode 100644
index 00000000..8c3c91f2
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctput.x
@@ -0,0 +1,490 @@
+include "../lib/mctable.h"
+
+
+# MCT_PUT - Put value randomly (generic)
+
+procedure mct_putc (table, row, col, value)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+char value # data value
+
+int offset
+pointer base
+errchk mct_indef()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_put: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_put: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_CHAR)
+ call error (0, "mct_put: Wrong table type")
+
+ # Test row and column values.
+ if (row < 1)
+ call error (0, "mct_put: Row number less than one")
+ if (col < 1 || col > MCT_MAXCOL (table))
+ call error (0, "mct_put: Column out of range")
+
+ # Reallocate space if necessary.
+ if (row > MCT_MAXROW (table)) {
+
+ # Compute offset of new area.
+ offset = MCT_MAXROW (table) * MCT_MAXCOL (table)
+
+ # Recompute new number of rows and reallocate buffer.
+ MCT_MAXROW (table) = MCT_MAXROW (table) + MCT_INCROWS (table)
+ call realloc (MCT_DATA (table),
+ MCT_MAXROW (table) * MCT_MAXCOL (table), TY_CHAR)
+
+ # Compute base address of new area and clear it with INDEF.
+ base = MCT_DATA (table) + offset
+ call mct_indef (table, base,
+ MCT_INCROWS (table) * MCT_MAXCOL (table))
+ }
+
+ # Update row and column counter, only if the new entries are beyond
+ # the old limits.
+
+ if (row > MCT_NPROWS (table)) {
+ MCT_NPROWS (table) = row
+ MCT_NPCOLS (table) = col
+ } else if (col > MCT_NPCOLS (table))
+ MCT_NPCOLS (table) = col
+
+ # Enter variable.
+ base = MCT_DATA (table) + (row - 1) * MCT_MAXCOL (table)
+ Memc[base + col - 1] = value
+end
+
+# MCT_PUT - Put value randomly (generic)
+
+procedure mct_puts (table, row, col, value)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+short value # data value
+
+int offset
+pointer base
+errchk mct_indef()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_put: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_put: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_SHORT)
+ call error (0, "mct_put: Wrong table type")
+
+ # Test row and column values.
+ if (row < 1)
+ call error (0, "mct_put: Row number less than one")
+ if (col < 1 || col > MCT_MAXCOL (table))
+ call error (0, "mct_put: Column out of range")
+
+ # Reallocate space if necessary.
+ if (row > MCT_MAXROW (table)) {
+
+ # Compute offset of new area.
+ offset = MCT_MAXROW (table) * MCT_MAXCOL (table)
+
+ # Recompute new number of rows and reallocate buffer.
+ MCT_MAXROW (table) = MCT_MAXROW (table) + MCT_INCROWS (table)
+ call realloc (MCT_DATA (table),
+ MCT_MAXROW (table) * MCT_MAXCOL (table), TY_SHORT)
+
+ # Compute base address of new area and clear it with INDEF.
+ base = MCT_DATA (table) + offset
+ call mct_indef (table, base,
+ MCT_INCROWS (table) * MCT_MAXCOL (table))
+ }
+
+ # Update row and column counter, only if the new entries are beyond
+ # the old limits.
+
+ if (row > MCT_NPROWS (table)) {
+ MCT_NPROWS (table) = row
+ MCT_NPCOLS (table) = col
+ } else if (col > MCT_NPCOLS (table))
+ MCT_NPCOLS (table) = col
+
+ # Enter variable.
+ base = MCT_DATA (table) + (row - 1) * MCT_MAXCOL (table)
+ Mems[base + col - 1] = value
+end
+
+# MCT_PUT - Put value randomly (generic)
+
+procedure mct_puti (table, row, col, value)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+int value # data value
+
+int offset
+pointer base
+errchk mct_indef()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_put: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_put: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_INT)
+ call error (0, "mct_put: Wrong table type")
+
+ # Test row and column values.
+ if (row < 1)
+ call error (0, "mct_put: Row number less than one")
+ if (col < 1 || col > MCT_MAXCOL (table))
+ call error (0, "mct_put: Column out of range")
+
+ # Reallocate space if necessary.
+ if (row > MCT_MAXROW (table)) {
+
+ # Compute offset of new area.
+ offset = MCT_MAXROW (table) * MCT_MAXCOL (table)
+
+ # Recompute new number of rows and reallocate buffer.
+ MCT_MAXROW (table) = MCT_MAXROW (table) + MCT_INCROWS (table)
+ call realloc (MCT_DATA (table),
+ MCT_MAXROW (table) * MCT_MAXCOL (table), TY_INT)
+
+ # Compute base address of new area and clear it with INDEF.
+ base = MCT_DATA (table) + offset
+ call mct_indef (table, base,
+ MCT_INCROWS (table) * MCT_MAXCOL (table))
+ }
+
+ # Update row and column counter, only if the new entries are beyond
+ # the old limits.
+
+ if (row > MCT_NPROWS (table)) {
+ MCT_NPROWS (table) = row
+ MCT_NPCOLS (table) = col
+ } else if (col > MCT_NPCOLS (table))
+ MCT_NPCOLS (table) = col
+
+ # Enter variable.
+ base = MCT_DATA (table) + (row - 1) * MCT_MAXCOL (table)
+ Memi[base + col - 1] = value
+end
+
+# MCT_PUT - Put value randomly (generic)
+
+procedure mct_putl (table, row, col, value)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+long value # data value
+
+int offset
+pointer base
+errchk mct_indef()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_put: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_put: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_LONG)
+ call error (0, "mct_put: Wrong table type")
+
+ # Test row and column values.
+ if (row < 1)
+ call error (0, "mct_put: Row number less than one")
+ if (col < 1 || col > MCT_MAXCOL (table))
+ call error (0, "mct_put: Column out of range")
+
+ # Reallocate space if necessary.
+ if (row > MCT_MAXROW (table)) {
+
+ # Compute offset of new area.
+ offset = MCT_MAXROW (table) * MCT_MAXCOL (table)
+
+ # Recompute new number of rows and reallocate buffer.
+ MCT_MAXROW (table) = MCT_MAXROW (table) + MCT_INCROWS (table)
+ call realloc (MCT_DATA (table),
+ MCT_MAXROW (table) * MCT_MAXCOL (table), TY_LONG)
+
+ # Compute base address of new area and clear it with INDEF.
+ base = MCT_DATA (table) + offset
+ call mct_indef (table, base,
+ MCT_INCROWS (table) * MCT_MAXCOL (table))
+ }
+
+ # Update row and column counter, only if the new entries are beyond
+ # the old limits.
+
+ if (row > MCT_NPROWS (table)) {
+ MCT_NPROWS (table) = row
+ MCT_NPCOLS (table) = col
+ } else if (col > MCT_NPCOLS (table))
+ MCT_NPCOLS (table) = col
+
+ # Enter variable.
+ base = MCT_DATA (table) + (row - 1) * MCT_MAXCOL (table)
+ Meml[base + col - 1] = value
+end
+
+# MCT_PUT - Put value randomly (generic)
+
+procedure mct_putr (table, row, col, value)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+real value # data value
+
+int offset
+pointer base
+errchk mct_indef()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_put: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_put: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_REAL)
+ call error (0, "mct_put: Wrong table type")
+
+ # Test row and column values.
+ if (row < 1)
+ call error (0, "mct_put: Row number less than one")
+ if (col < 1 || col > MCT_MAXCOL (table))
+ call error (0, "mct_put: Column out of range")
+
+ # Reallocate space if necessary.
+ if (row > MCT_MAXROW (table)) {
+
+ # Compute offset of new area.
+ offset = MCT_MAXROW (table) * MCT_MAXCOL (table)
+
+ # Recompute new number of rows and reallocate buffer.
+ MCT_MAXROW (table) = MCT_MAXROW (table) + MCT_INCROWS (table)
+ call realloc (MCT_DATA (table),
+ MCT_MAXROW (table) * MCT_MAXCOL (table), TY_REAL)
+
+ # Compute base address of new area and clear it with INDEF.
+ base = MCT_DATA (table) + offset
+ call mct_indef (table, base,
+ MCT_INCROWS (table) * MCT_MAXCOL (table))
+ }
+
+ # Update row and column counter, only if the new entries are beyond
+ # the old limits.
+
+ if (row > MCT_NPROWS (table)) {
+ MCT_NPROWS (table) = row
+ MCT_NPCOLS (table) = col
+ } else if (col > MCT_NPCOLS (table))
+ MCT_NPCOLS (table) = col
+
+ # Enter variable.
+ base = MCT_DATA (table) + (row - 1) * MCT_MAXCOL (table)
+ Memr[base + col - 1] = value
+end
+
+# MCT_PUT - Put value randomly (generic)
+
+procedure mct_putd (table, row, col, value)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+double value # data value
+
+int offset
+pointer base
+errchk mct_indef()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_put: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_put: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_DOUBLE)
+ call error (0, "mct_put: Wrong table type")
+
+ # Test row and column values.
+ if (row < 1)
+ call error (0, "mct_put: Row number less than one")
+ if (col < 1 || col > MCT_MAXCOL (table))
+ call error (0, "mct_put: Column out of range")
+
+ # Reallocate space if necessary.
+ if (row > MCT_MAXROW (table)) {
+
+ # Compute offset of new area.
+ offset = MCT_MAXROW (table) * MCT_MAXCOL (table)
+
+ # Recompute new number of rows and reallocate buffer.
+ MCT_MAXROW (table) = MCT_MAXROW (table) + MCT_INCROWS (table)
+ call realloc (MCT_DATA (table),
+ MCT_MAXROW (table) * MCT_MAXCOL (table), TY_DOUBLE)
+
+ # Compute base address of new area and clear it with INDEF.
+ base = MCT_DATA (table) + offset
+ call mct_indef (table, base,
+ MCT_INCROWS (table) * MCT_MAXCOL (table))
+ }
+
+ # Update row and column counter, only if the new entries are beyond
+ # the old limits.
+
+ if (row > MCT_NPROWS (table)) {
+ MCT_NPROWS (table) = row
+ MCT_NPCOLS (table) = col
+ } else if (col > MCT_NPCOLS (table))
+ MCT_NPCOLS (table) = col
+
+ # Enter variable.
+ base = MCT_DATA (table) + (row - 1) * MCT_MAXCOL (table)
+ Memd[base + col - 1] = value
+end
+
+# MCT_PUT - Put value randomly (generic)
+
+procedure mct_putx (table, row, col, value)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+complex value # data value
+
+int offset
+pointer base
+errchk mct_indef()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_put: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_put: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_COMPLEX)
+ call error (0, "mct_put: Wrong table type")
+
+ # Test row and column values.
+ if (row < 1)
+ call error (0, "mct_put: Row number less than one")
+ if (col < 1 || col > MCT_MAXCOL (table))
+ call error (0, "mct_put: Column out of range")
+
+ # Reallocate space if necessary.
+ if (row > MCT_MAXROW (table)) {
+
+ # Compute offset of new area.
+ offset = MCT_MAXROW (table) * MCT_MAXCOL (table)
+
+ # Recompute new number of rows and reallocate buffer.
+ MCT_MAXROW (table) = MCT_MAXROW (table) + MCT_INCROWS (table)
+ call realloc (MCT_DATA (table),
+ MCT_MAXROW (table) * MCT_MAXCOL (table), TY_COMPLEX)
+
+ # Compute base address of new area and clear it with INDEF.
+ base = MCT_DATA (table) + offset
+ call mct_indef (table, base,
+ MCT_INCROWS (table) * MCT_MAXCOL (table))
+ }
+
+ # Update row and column counter, only if the new entries are beyond
+ # the old limits.
+
+ if (row > MCT_NPROWS (table)) {
+ MCT_NPROWS (table) = row
+ MCT_NPCOLS (table) = col
+ } else if (col > MCT_NPCOLS (table))
+ MCT_NPCOLS (table) = col
+
+ # Enter variable.
+ base = MCT_DATA (table) + (row - 1) * MCT_MAXCOL (table)
+ Memx[base + col - 1] = value
+end
+
+# MCT_PUT - Put value randomly (generic)
+
+procedure mct_putp (table, row, col, value)
+
+pointer table # table descriptor
+int row # row number
+int col # column number
+pointer value # data value
+
+int offset
+pointer base
+errchk mct_indef()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_put: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_put: Bad magic number")
+
+ # Check the table type.
+ if (MCT_TYPE (table) != TY_POINTER)
+ call error (0, "mct_put: Wrong table type")
+
+ # Test row and column values.
+ if (row < 1)
+ call error (0, "mct_put: Row number less than one")
+ if (col < 1 || col > MCT_MAXCOL (table))
+ call error (0, "mct_put: Column out of range")
+
+ # Reallocate space if necessary.
+ if (row > MCT_MAXROW (table)) {
+
+ # Compute offset of new area.
+ offset = MCT_MAXROW (table) * MCT_MAXCOL (table)
+
+ # Recompute new number of rows and reallocate buffer.
+ MCT_MAXROW (table) = MCT_MAXROW (table) + MCT_INCROWS (table)
+ call realloc (MCT_DATA (table),
+ MCT_MAXROW (table) * MCT_MAXCOL (table), TY_POINTER)
+
+ # Compute base address of new area and clear it with INDEF.
+ base = MCT_DATA (table) + offset
+ call mct_indef (table, base,
+ MCT_INCROWS (table) * MCT_MAXCOL (table))
+ }
+
+ # Update row and column counter, only if the new entries are beyond
+ # the old limits.
+
+ if (row > MCT_NPROWS (table)) {
+ MCT_NPROWS (table) = row
+ MCT_NPCOLS (table) = col
+ } else if (col > MCT_NPCOLS (table))
+ MCT_NPCOLS (table) = col
+
+ # Enter variable.
+ base = MCT_DATA (table) + (row - 1) * MCT_MAXCOL (table)
+ MEMP[base + col - 1] = value
+end
diff --git a/noao/digiphot/photcal/mctable/mctreset.x b/noao/digiphot/photcal/mctable/mctreset.x
new file mode 100644
index 00000000..c90959d2
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctreset.x
@@ -0,0 +1,28 @@
+include "../lib/mctable.h"
+
+
+# MCT_RESET - Reset table counters, and set all table values to INDEF.
+
+procedure mct_reset (table)
+
+pointer table # table descriptor
+
+errchk mct_indef()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_reset: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_reset: Bad magic number")
+
+ # Clear table counters.
+ MCT_NPCOLS (table) = 0
+ MCT_NPROWS (table) = 0
+ MCT_NGCOLS (table) = 0
+ MCT_NGROWS (table) = 0
+
+ # Clear table buffer.
+ call mct_indef (table, MCT_DATA (table),
+ MCT_NPROWS (table) * MCT_NPCOLS (table))
+end
diff --git a/noao/digiphot/photcal/mctable/mctrestore.gx b/noao/digiphot/photcal/mctable/mctrestore.gx
new file mode 100644
index 00000000..2e0a807f
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctrestore.gx
@@ -0,0 +1,135 @@
+include "../lib/mctable.h"
+
+
+# MCT_RESTORE - Restore table from a text file.
+
+procedure mct_restore (fname, table)
+
+char fname[ARB] # file name
+pointer table # table descriptor
+
+char cval
+short sval
+int fd, magic, type, row, col, nprows, npcols
+int maxcol, maxrow, lastcol, ival
+long lval
+pointer pval
+real rval
+double dval
+complex xval
+
+int open(), fscan(), nscan()
+errchk mct_alloc()
+errchk mct_putc(), mct_puts(), mct_puti(), mct_putl()
+errchk mct_putr(), mct_putd(), mct_putx(), mct_putp()
+
+begin
+ # Open file.
+ iferr (fd = open (fname, READ_ONLY, TEXT_FILE))
+ call error (0, "mct_restore: Cannot open file")
+
+ # Read and check magic number.
+ if (fscan (fd) != EOF) {
+ call gargi (magic)
+ if (magic != MAGIC)
+ call error (0, "mct_restore: Bad magic number")
+ } else
+ call error (0, "mct_restore: Unexpected end of file (magic)")
+
+ # Read type.
+ if (fscan (fd) != EOF)
+ call gargi (type)
+ else
+ call error (0, "mct_restore: Unexpected end of file (type)")
+
+ # Read max number of rows.
+ if (fscan (fd) != EOF)
+ call gargi (maxrow)
+ else
+ call error (0, "mct_restore: Unexpected end of file (maxrow)")
+
+ # Read max number of columns.
+ if (fscan (fd) != EOF)
+ call gargi (maxcol)
+ else
+ call error (0, "mct_restore: Unexpected end of file (maxcol)")
+
+ # Discard row increment.
+ if (fscan (fd) != EOF)
+ call gargi (ival)
+ else
+ call error (0, "mct_restore: Unexpected end of file (incrows)")
+
+ # Read number of rows entered.
+ if (fscan (fd) != EOF)
+ call gargi (nprows)
+ else
+ call error (0, "mct_restore: Unexpected end of file (nprows)")
+
+ # Read number of columns entered.
+ if (fscan (fd) != EOF)
+ call gargi (npcols)
+ else
+ call error (0, "mct_restore: Unexpected end of file (npcols)")
+
+ # Read number of rows gotten.
+ if (fscan (fd) != EOF)
+ call gargi (ival)
+ else
+ call error (0, "mct_restore: Unexpected end of file (ngrows)")
+
+ # Read number of columns gotten
+ if (fscan (fd) != EOF)
+ call gargi (ival)
+ else
+ call error (0, "mct_restore: Unexpected end of file (ngcols)")
+
+ # Discard data pointer.
+ if (fscan (fd) != EOF)
+ call gargi (ival)
+ else
+ call error (0, "mct_restore: Unexpected end of file (pointer)")
+
+ # Allocate table.
+ call mct_alloc (table, maxrow, maxcol, type)
+
+ # Loop over rows.
+ lastcol = maxcol
+ do row = 1, nprows {
+
+ # In the last row the column loop should go only until the
+ # highest column.
+ if (row == nprows)
+ lastcol = npcols
+
+ # Start scanning next line.
+ if (fscan (fd) == EOF)
+ call error (0, "mct_restore: Unexpected end of file (row)")
+
+ # Loop over columns.
+ for (col = 1; col <= lastcol; col = col + 1) {
+
+ # Read data.
+ switch (MCT_TYPE (table)) {
+ $for (csilrdxp)
+ case TY_PIXEL:
+ $if (datatype == p)
+ call gargi ($tval)
+ $else
+ call garg$t ($tval)
+ $endif
+ call mct_put$t (table, row, col, $tval)
+ $endfor
+ default:
+ call error (0, "mct_save: Unknown data type")
+ }
+
+ # Check column read.
+ if (nscan () != col)
+ call error (0, "mct_restore: Unexpcted end of file (col)")
+ }
+ }
+
+ # Close file.
+ call close (fd)
+end
diff --git a/noao/digiphot/photcal/mctable/mctrestore.x b/noao/digiphot/photcal/mctable/mctrestore.x
new file mode 100644
index 00000000..f080afd6
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctrestore.x
@@ -0,0 +1,159 @@
+include "../lib/mctable.h"
+
+
+# MCT_RESTORE - Restore table from a text file.
+
+procedure mct_restore (fname, table)
+
+char fname[ARB] # file name
+pointer table # table descriptor
+
+char cval
+short sval
+int fd, magic, type, row, col, nprows, npcols
+int maxcol, maxrow, lastcol, ival
+long lval
+pointer pval
+real rval
+double dval
+complex xval
+
+int open(), fscan(), nscan()
+errchk mct_alloc()
+errchk mct_putc(), mct_puts(), mct_puti(), mct_putl()
+errchk mct_putr(), mct_putd(), mct_putx(), mct_putp()
+
+begin
+ # Open file.
+ iferr (fd = open (fname, READ_ONLY, TEXT_FILE))
+ call error (0, "mct_restore: Cannot open file")
+
+ # Read and check magic number.
+ if (fscan (fd) != EOF) {
+ call gargi (magic)
+ if (magic != MAGIC)
+ call error (0, "mct_restore: Bad magic number")
+ } else
+ call error (0, "mct_restore: Unexpected end of file (magic)")
+
+ # Read type.
+ if (fscan (fd) != EOF)
+ call gargi (type)
+ else
+ call error (0, "mct_restore: Unexpected end of file (type)")
+
+ # Read max number of rows.
+ if (fscan (fd) != EOF)
+ call gargi (maxrow)
+ else
+ call error (0, "mct_restore: Unexpected end of file (maxrow)")
+
+ # Read max number of columns.
+ if (fscan (fd) != EOF)
+ call gargi (maxcol)
+ else
+ call error (0, "mct_restore: Unexpected end of file (maxcol)")
+
+ # Discard row increment.
+ if (fscan (fd) != EOF)
+ call gargi (ival)
+ else
+ call error (0, "mct_restore: Unexpected end of file (incrows)")
+
+ # Read number of rows entered.
+ if (fscan (fd) != EOF)
+ call gargi (nprows)
+ else
+ call error (0, "mct_restore: Unexpected end of file (nprows)")
+
+ # Read number of columns entered.
+ if (fscan (fd) != EOF)
+ call gargi (npcols)
+ else
+ call error (0, "mct_restore: Unexpected end of file (npcols)")
+
+ # Read number of rows gotten.
+ if (fscan (fd) != EOF)
+ call gargi (ival)
+ else
+ call error (0, "mct_restore: Unexpected end of file (ngrows)")
+
+ # Read number of columns gotten
+ if (fscan (fd) != EOF)
+ call gargi (ival)
+ else
+ call error (0, "mct_restore: Unexpected end of file (ngcols)")
+
+ # Discard data pointer.
+ if (fscan (fd) != EOF)
+ call gargi (ival)
+ else
+ call error (0, "mct_restore: Unexpected end of file (pointer)")
+
+ # Allocate table.
+ call mct_alloc (table, maxrow, maxcol, type)
+
+ # Loop over rows.
+ lastcol = maxcol
+ do row = 1, nprows {
+
+ # In the last row the column loop should go only until the
+ # highest column.
+ if (row == nprows)
+ lastcol = npcols
+
+ # Start scanning next line.
+ if (fscan (fd) == EOF)
+ call error (0, "mct_restore: Unexpected end of file (row)")
+
+ # Loop over columns.
+ for (col = 1; col <= lastcol; col = col + 1) {
+
+ # Read data.
+ switch (MCT_TYPE (table)) {
+
+ case TY_CHAR:
+ call gargc (cval)
+ call mct_putc (table, row, col, cval)
+
+ case TY_SHORT:
+ call gargs (sval)
+ call mct_puts (table, row, col, sval)
+
+ case TY_INT:
+ call gargi (ival)
+ call mct_puti (table, row, col, ival)
+
+ case TY_LONG:
+ call gargl (lval)
+ call mct_putl (table, row, col, lval)
+
+ case TY_REAL:
+ call gargr (rval)
+ call mct_putr (table, row, col, rval)
+
+ case TY_DOUBLE:
+ call gargd (dval)
+ call mct_putd (table, row, col, dval)
+
+ case TY_COMPLEX:
+ call gargx (xval)
+ call mct_putx (table, row, col, xval)
+
+ case TY_POINTER:
+ call gargi (pval)
+ call mct_putp (table, row, col, pval)
+
+ default:
+ call error (0, "mct_save: Unknown data type")
+ }
+
+ # Check column read.
+ if (nscan () != col)
+ call error (0, "mct_restore: Unexpcted end of file (col)")
+ }
+ }
+
+ # Close file.
+ call close (fd)
+end
diff --git a/noao/digiphot/photcal/mctable/mctrew.x b/noao/digiphot/photcal/mctable/mctrew.x
new file mode 100644
index 00000000..a7ad2ad5
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctrew.x
@@ -0,0 +1,20 @@
+include "../lib/mctable.h"
+
+
+# MCT_REW - Rewinding the sequential get counters.
+
+procedure mct_rew (table)
+
+pointer table # table descriptor
+
+begin
+ # Check the pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_rew: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_rew: Bad magic number")
+
+ # Clear get counters.
+ MCT_NGCOLS (table) = 0
+ MCT_NGROWS (table) = 0
+end
diff --git a/noao/digiphot/photcal/mctable/mctsave.x b/noao/digiphot/photcal/mctable/mctsave.x
new file mode 100644
index 00000000..dc71fd56
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctsave.x
@@ -0,0 +1,113 @@
+include "../lib/mctable.h"
+
+
+# MCT_SAVE - Save table into a text file
+
+procedure mct_save (fname, fmode, table)
+
+char fname[ARB] # file name
+int fmode # file mode
+pointer table # table descriptor
+
+int fd # file descriptor
+int row, col
+int nrows, lastcol
+
+int open()
+char mct_getc()
+short mct_gets()
+int mct_geti()
+long mct_getl()
+real mct_getr()
+double mct_getd()
+complex mct_getx()
+pointer mct_getp()
+
+errchk mct_getc(), mct_gets(), mct_geti(), mct_getl()
+errchk mct_getr(), mct_getd(), mct_getx(), mct_getp()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_save: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_save: Bad magic number")
+
+ # Check file mode.
+ if (fmode != WRITE_ONLY && fmode != NEW_FILE &&
+ fmode != NEW_FILE && fmode != TEMP_FILE)
+ call error (0, "mct_save: Bad file mode")
+
+ # Open file.
+ iferr (fd = open (fname, fmode, TEXT_FILE))
+ call error (0, "mct_save: Cannot open file")
+
+ # Write table structure.
+ call fprintf (fd, "%d # MCT_MAGIC\n")
+ call pargi (MCT_MAGIC (table))
+ call fprintf (fd, "%d # MCT_TYPE\n")
+ call pargi (MCT_TYPE (table))
+ call fprintf (fd, "%d # MCT_MAXROW\n")
+ call pargi (MCT_MAXROW (table))
+ call fprintf (fd, "%d # MCT_MAXCOL\n")
+ call pargi (MCT_MAXCOL (table))
+ call fprintf (fd, "%d # MCT_INCROWS\n")
+ call pargi (MCT_INCROWS (table))
+ call fprintf (fd, "%d # MCT_NPROWS\n")
+ call pargi (MCT_NPROWS (table))
+ call fprintf (fd, "%d # MCT_NPCOLS\n")
+ call pargi (MCT_NPCOLS (table))
+ call fprintf (fd, "%d # MCT_NGROWS\n")
+ call pargi (MCT_NGROWS (table))
+ call fprintf (fd, "%d # MCT_NGCOLS\n")
+ call pargi (MCT_NGCOLS (table))
+ call fprintf (fd, "%d # MCT_DATA\n")
+ call pargi (MCT_DATA (table))
+
+ # Loop over rows.
+ nrows = MCT_NPROWS (table)
+ lastcol = MCT_MAXCOL (table)
+ do row = 1, nrows {
+
+ # In the last row the column loop should go only until the highest
+ # column.
+ if (row == nrows)
+ lastcol = MCT_NPCOLS (table)
+
+ # Loop over columns.
+ for (col = 1; col <= lastcol; col = col + 1) {
+ switch (MCT_TYPE (table)) {
+ case TY_CHAR:
+ call fprintf (fd, "%c ")
+ call pargc (mct_getc (table, row, col))
+ case TY_SHORT:
+ call fprintf (fd, "%d ")
+ call pargs (mct_gets (table, row, col))
+ case TY_INT:
+ call fprintf (fd, "%d ")
+ call pargi (mct_geti (table, row, col))
+ case TY_LONG:
+ call fprintf (fd, "%d ")
+ call pargl (mct_getl (table, row, col))
+ case TY_REAL:
+ call fprintf (fd, "%g ")
+ call pargr (mct_getr (table, row, col))
+ case TY_DOUBLE:
+ call fprintf (fd, "%g ")
+ call pargd (mct_getd (table, row, col))
+ case TY_COMPLEX:
+ call fprintf (fd, "%z ")
+ call pargx (mct_getx (table, row, col))
+ case TY_POINTER:
+ call fprintf (fd, "%d ")
+ call pargi (mct_getp (table, row, col))
+ default:
+ call error (0, "mct_save: Unknown data type")
+ }
+ }
+ call fprintf (fd, "\n")
+ }
+
+ # Close file.
+ call close (fd)
+end
diff --git a/noao/digiphot/photcal/mctable/mctsget.gx b/noao/digiphot/photcal/mctable/mctsget.gx
new file mode 100644
index 00000000..3f8d6bfb
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctsget.gx
@@ -0,0 +1,42 @@
+include "../lib/mctable.h"
+
+
+$for (csilrdxp)
+# MCT_SGET - Get value sequentally (generic)
+
+int procedure mct_sget$t (table, value)
+
+pointer table # table descriptor
+PIXEL value # data value (output)
+
+int row, col # next row, and column
+PIXEL mct_get$t()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_sget: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sget: Bad magic number")
+
+ # Check table type.
+ if (MCT_TYPE (table) != TY_PIXEL)
+ call error (0, "mct_sget: Wrong table type")
+
+ # Get next position.
+ row = max (MCT_NGROWS (table), 1)
+ col = MCT_NGCOLS (table) + 1
+
+ # Test if it's necessary to go to the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Get value and return status.
+ iferr (value = mct_get$t (table, row, col))
+ return (EOF)
+ else
+ return (OK)
+end
+$endfor
diff --git a/noao/digiphot/photcal/mctable/mctsget.x b/noao/digiphot/photcal/mctable/mctsget.x
new file mode 100644
index 00000000..b0361841
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctsget.x
@@ -0,0 +1,307 @@
+include "../lib/mctable.h"
+
+
+
+# MCT_SGET - Get value sequentally (generic)
+
+int procedure mct_sgetc (table, value)
+
+pointer table # table descriptor
+char value # data value (output)
+
+int row, col # next row, and column
+char mct_getc()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_sget: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sget: Bad magic number")
+
+ # Check table type.
+ if (MCT_TYPE (table) != TY_CHAR)
+ call error (0, "mct_sget: Wrong table type")
+
+ # Get next position.
+ row = max (MCT_NGROWS (table), 1)
+ col = MCT_NGCOLS (table) + 1
+
+ # Test if it's necessary to go to the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Get value and return status.
+ iferr (value = mct_getc (table, row, col))
+ return (EOF)
+ else
+ return (OK)
+end
+
+# MCT_SGET - Get value sequentally (generic)
+
+int procedure mct_sgets (table, value)
+
+pointer table # table descriptor
+short value # data value (output)
+
+int row, col # next row, and column
+short mct_gets()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_sget: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sget: Bad magic number")
+
+ # Check table type.
+ if (MCT_TYPE (table) != TY_SHORT)
+ call error (0, "mct_sget: Wrong table type")
+
+ # Get next position.
+ row = max (MCT_NGROWS (table), 1)
+ col = MCT_NGCOLS (table) + 1
+
+ # Test if it's necessary to go to the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Get value and return status.
+ iferr (value = mct_gets (table, row, col))
+ return (EOF)
+ else
+ return (OK)
+end
+
+# MCT_SGET - Get value sequentally (generic)
+
+int procedure mct_sgeti (table, value)
+
+pointer table # table descriptor
+int value # data value (output)
+
+int row, col # next row, and column
+int mct_geti()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_sget: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sget: Bad magic number")
+
+ # Check table type.
+ if (MCT_TYPE (table) != TY_INT)
+ call error (0, "mct_sget: Wrong table type")
+
+ # Get next position.
+ row = max (MCT_NGROWS (table), 1)
+ col = MCT_NGCOLS (table) + 1
+
+ # Test if it's necessary to go to the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Get value and return status.
+ iferr (value = mct_geti (table, row, col))
+ return (EOF)
+ else
+ return (OK)
+end
+
+# MCT_SGET - Get value sequentally (generic)
+
+int procedure mct_sgetl (table, value)
+
+pointer table # table descriptor
+long value # data value (output)
+
+int row, col # next row, and column
+long mct_getl()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_sget: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sget: Bad magic number")
+
+ # Check table type.
+ if (MCT_TYPE (table) != TY_LONG)
+ call error (0, "mct_sget: Wrong table type")
+
+ # Get next position.
+ row = max (MCT_NGROWS (table), 1)
+ col = MCT_NGCOLS (table) + 1
+
+ # Test if it's necessary to go to the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Get value and return status.
+ iferr (value = mct_getl (table, row, col))
+ return (EOF)
+ else
+ return (OK)
+end
+
+# MCT_SGET - Get value sequentally (generic)
+
+int procedure mct_sgetr (table, value)
+
+pointer table # table descriptor
+real value # data value (output)
+
+int row, col # next row, and column
+real mct_getr()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_sget: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sget: Bad magic number")
+
+ # Check table type.
+ if (MCT_TYPE (table) != TY_REAL)
+ call error (0, "mct_sget: Wrong table type")
+
+ # Get next position.
+ row = max (MCT_NGROWS (table), 1)
+ col = MCT_NGCOLS (table) + 1
+
+ # Test if it's necessary to go to the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Get value and return status.
+ iferr (value = mct_getr (table, row, col))
+ return (EOF)
+ else
+ return (OK)
+end
+
+# MCT_SGET - Get value sequentally (generic)
+
+int procedure mct_sgetd (table, value)
+
+pointer table # table descriptor
+double value # data value (output)
+
+int row, col # next row, and column
+double mct_getd()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_sget: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sget: Bad magic number")
+
+ # Check table type.
+ if (MCT_TYPE (table) != TY_DOUBLE)
+ call error (0, "mct_sget: Wrong table type")
+
+ # Get next position.
+ row = max (MCT_NGROWS (table), 1)
+ col = MCT_NGCOLS (table) + 1
+
+ # Test if it's necessary to go to the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Get value and return status.
+ iferr (value = mct_getd (table, row, col))
+ return (EOF)
+ else
+ return (OK)
+end
+
+# MCT_SGET - Get value sequentally (generic)
+
+int procedure mct_sgetx (table, value)
+
+pointer table # table descriptor
+complex value # data value (output)
+
+int row, col # next row, and column
+complex mct_getx()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_sget: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sget: Bad magic number")
+
+ # Check table type.
+ if (MCT_TYPE (table) != TY_COMPLEX)
+ call error (0, "mct_sget: Wrong table type")
+
+ # Get next position.
+ row = max (MCT_NGROWS (table), 1)
+ col = MCT_NGCOLS (table) + 1
+
+ # Test if it's necessary to go to the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Get value and return status.
+ iferr (value = mct_getx (table, row, col))
+ return (EOF)
+ else
+ return (OK)
+end
+
+# MCT_SGET - Get value sequentally (generic)
+
+int procedure mct_sgetp (table, value)
+
+pointer table # table descriptor
+pointer value # data value (output)
+
+int row, col # next row, and column
+pointer mct_getp()
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_sget: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sget: Bad magic number")
+
+ # Check table type.
+ if (MCT_TYPE (table) != TY_POINTER)
+ call error (0, "mct_sget: Wrong table type")
+
+ # Get next position.
+ row = max (MCT_NGROWS (table), 1)
+ col = MCT_NGCOLS (table) + 1
+
+ # Test if it's necessary to go to the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Get value and return status.
+ iferr (value = mct_getp (table, row, col))
+ return (EOF)
+ else
+ return (OK)
+end
diff --git a/noao/digiphot/photcal/mctable/mctshrink.x b/noao/digiphot/photcal/mctable/mctshrink.x
new file mode 100644
index 00000000..6a88f230
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctshrink.x
@@ -0,0 +1,31 @@
+include "../lib/mctable.h"
+
+
+# MCT_SHRINK - Free unused table memory
+
+procedure mct_shrink (table)
+
+pointer table # table descriptor
+
+int lsize, psize
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_shrink: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_shrink: Bad magic number")
+
+ # Compute aproximate logical size, and exact physical
+ # sizes. This might produce a little bit of space wasted.
+
+ lsize = MCT_NPROWS (table) * MCT_MAXCOL (table)
+ psize = MCT_MAXROW (table) * MCT_MAXCOL (table)
+
+ # Reallocate table sapace and update physical size.
+ if (lsize != psize) {
+ call realloc (MCT_DATA (table), lsize, MCT_TYPE (table))
+ MCT_MAXROW (table) = MCT_NPROWS (table)
+ MCT_INCROWS (table) = GROWFACTOR (MCT_MAXROW (table))
+ }
+end
diff --git a/noao/digiphot/photcal/mctable/mctsput.gx b/noao/digiphot/photcal/mctable/mctsput.gx
new file mode 100644
index 00000000..5b1b92f2
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctsput.gx
@@ -0,0 +1,40 @@
+include "../lib/mctable.h"
+
+
+$for (csilrdxp)
+# MCT_SPUT - Put value sequentally (generic)
+
+procedure mct_sput$t (table, value)
+
+pointer table # table descriptor
+PIXEL value # data value
+
+int row, col # nxt row, and column
+errchk mct_put$t
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_sput: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sput: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_PIXEL)
+ call error (0, "mct_sput: Wrong table type")
+
+ # Get next position
+ row = max (MCT_NPROWS (table), 1)
+ col = MCT_NPCOLS (table) + 1
+
+ # Test if it's necessary to go to
+ # the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Enter value
+ call mct_put$t (table, row, col, value)
+end
+$endfor
diff --git a/noao/digiphot/photcal/mctable/mctsput.x b/noao/digiphot/photcal/mctable/mctsput.x
new file mode 100644
index 00000000..e5adbba5
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mctsput.x
@@ -0,0 +1,291 @@
+include "../lib/mctable.h"
+
+
+
+# MCT_SPUT - Put value sequentally (generic)
+
+procedure mct_sputc (table, value)
+
+pointer table # table descriptor
+char value # data value
+
+int row, col # nxt row, and column
+errchk mct_putc
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_sput: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sput: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_CHAR)
+ call error (0, "mct_sput: Wrong table type")
+
+ # Get next position
+ row = max (MCT_NPROWS (table), 1)
+ col = MCT_NPCOLS (table) + 1
+
+ # Test if it's necessary to go to
+ # the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Enter value
+ call mct_putc (table, row, col, value)
+end
+
+# MCT_SPUT - Put value sequentally (generic)
+
+procedure mct_sputs (table, value)
+
+pointer table # table descriptor
+short value # data value
+
+int row, col # nxt row, and column
+errchk mct_puts
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_sput: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sput: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_SHORT)
+ call error (0, "mct_sput: Wrong table type")
+
+ # Get next position
+ row = max (MCT_NPROWS (table), 1)
+ col = MCT_NPCOLS (table) + 1
+
+ # Test if it's necessary to go to
+ # the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Enter value
+ call mct_puts (table, row, col, value)
+end
+
+# MCT_SPUT - Put value sequentally (generic)
+
+procedure mct_sputi (table, value)
+
+pointer table # table descriptor
+int value # data value
+
+int row, col # nxt row, and column
+errchk mct_puti
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_sput: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sput: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_INT)
+ call error (0, "mct_sput: Wrong table type")
+
+ # Get next position
+ row = max (MCT_NPROWS (table), 1)
+ col = MCT_NPCOLS (table) + 1
+
+ # Test if it's necessary to go to
+ # the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Enter value
+ call mct_puti (table, row, col, value)
+end
+
+# MCT_SPUT - Put value sequentally (generic)
+
+procedure mct_sputl (table, value)
+
+pointer table # table descriptor
+long value # data value
+
+int row, col # nxt row, and column
+errchk mct_putl
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_sput: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sput: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_LONG)
+ call error (0, "mct_sput: Wrong table type")
+
+ # Get next position
+ row = max (MCT_NPROWS (table), 1)
+ col = MCT_NPCOLS (table) + 1
+
+ # Test if it's necessary to go to
+ # the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Enter value
+ call mct_putl (table, row, col, value)
+end
+
+# MCT_SPUT - Put value sequentally (generic)
+
+procedure mct_sputr (table, value)
+
+pointer table # table descriptor
+real value # data value
+
+int row, col # nxt row, and column
+errchk mct_putr
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_sput: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sput: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_REAL)
+ call error (0, "mct_sput: Wrong table type")
+
+ # Get next position
+ row = max (MCT_NPROWS (table), 1)
+ col = MCT_NPCOLS (table) + 1
+
+ # Test if it's necessary to go to
+ # the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Enter value
+ call mct_putr (table, row, col, value)
+end
+
+# MCT_SPUT - Put value sequentally (generic)
+
+procedure mct_sputd (table, value)
+
+pointer table # table descriptor
+double value # data value
+
+int row, col # nxt row, and column
+errchk mct_putd
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_sput: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sput: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_DOUBLE)
+ call error (0, "mct_sput: Wrong table type")
+
+ # Get next position
+ row = max (MCT_NPROWS (table), 1)
+ col = MCT_NPCOLS (table) + 1
+
+ # Test if it's necessary to go to
+ # the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Enter value
+ call mct_putd (table, row, col, value)
+end
+
+# MCT_SPUT - Put value sequentally (generic)
+
+procedure mct_sputx (table, value)
+
+pointer table # table descriptor
+complex value # data value
+
+int row, col # nxt row, and column
+errchk mct_putx
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_sput: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sput: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_COMPLEX)
+ call error (0, "mct_sput: Wrong table type")
+
+ # Get next position
+ row = max (MCT_NPROWS (table), 1)
+ col = MCT_NPCOLS (table) + 1
+
+ # Test if it's necessary to go to
+ # the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Enter value
+ call mct_putx (table, row, col, value)
+end
+
+# MCT_SPUT - Put value sequentally (generic)
+
+procedure mct_sputp (table, value)
+
+pointer table # table descriptor
+pointer value # data value
+
+int row, col # nxt row, and column
+errchk mct_putp
+
+begin
+ # Check pointer and magic number
+ if (table == NULL)
+ call error (0, "mct_sput: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_sput: Bad magic number")
+
+ # Check table type
+ if (MCT_TYPE (table) != TY_POINTER)
+ call error (0, "mct_sput: Wrong table type")
+
+ # Get next position
+ row = max (MCT_NPROWS (table), 1)
+ col = MCT_NPCOLS (table) + 1
+
+ # Test if it's necessary to go to
+ # the next row.
+ if (col > MCT_MAXCOL (table)) {
+ col = 1
+ row = row + 1
+ }
+
+ # Enter value
+ call mct_putp (table, row, col, value)
+end
diff --git a/noao/digiphot/photcal/mctable/mcttype.x b/noao/digiphot/photcal/mctable/mcttype.x
new file mode 100644
index 00000000..a31bbf10
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mcttype.x
@@ -0,0 +1,19 @@
+include "../lib/mctable.h"
+
+
+# MCT_TYPE - Return table type.
+
+int procedure mct_type (table)
+
+pointer table # table descriptor
+
+begin
+ # Check pointer and magic number.
+ if (table == NULL)
+ call error (0, "mct_type: Null table pointer")
+ if (MCT_MAGIC (table) != MAGIC)
+ call error (0, "mct_type: Bad magic number")
+
+ # Return type.
+ return (MCT_TYPE (table))
+end
diff --git a/noao/digiphot/photcal/mctable/mkpkg b/noao/digiphot/photcal/mctable/mkpkg
new file mode 100644
index 00000000..a9e1e7d0
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/mkpkg
@@ -0,0 +1,71 @@
+# mctable mkpkg file (Mon Jan 21 14:53:01 CST 1991)
+
+$checkout libpkg.a ../
+$update libpkg.a
+$checkin libpkg.a ../
+$exit
+
+generic:
+ $set GEN = "$$generic -k -t csilrdxp"
+
+ $ifnewer (mctclear.gx, mctclear.x)
+ $generic -k -o mctclear.x mctclear.gx
+ $endif
+ $ifnewer (mctcopy.gx, mctcopy.x)
+ $generic -k -o mctcopy.x mctcopy.gx
+ $endif
+ $ifnewer (mctget.gx, mctget.x)
+ $generic -k -o mctget.x mctget.gx
+ $endif
+ $ifnewer (mctput.gx, mctput.x)
+ $generic -k -o mctput.x mctput.gx
+ $endif
+ $ifnewer (mctrestore.gx, mctrestore.x)
+ $generic -k -o mctrestore.x mctrestore.gx
+ $endif
+ $ifnewer (mctsget.gx, mctsget.x)
+ $generic -k -o mctsget.x mctsget.gx
+ $endif
+ $ifnewer (mctsput.gx, mctsput.x)
+ $generic -k -o mctsput.x mctsput.gx
+ $endif
+
+ ;
+
+libpkg.a:
+ $ifeq (USE_GENERIC, yes) $call generic $endif
+
+ mctalloc.x "../lib/mctable.h"
+ mctclear.x "../lib/mctable.h"
+ mctcopy.x "../lib/mctable.h"
+ mctfree.x "../lib/mctable.h"
+ mctget.x "../lib/mctable.h"
+ mctgetbuf.x "../lib/mctable.h"
+ mctgetrow.x "../lib/mctable.h"
+ mctindef.x "../lib/mctable.h"
+ mctmaxcol.x "../lib/mctable.h"
+ mctmaxrow.x "../lib/mctable.h"
+ mctncols.x "../lib/mctable.h"
+ mctnrows.x "../lib/mctable.h"
+ mctput.x "../lib/mctable.h"
+ mctreset.x "../lib/mctable.h"
+ mctrestore.x "../lib/mctable.h"
+ mctrew.x "../lib/mctable.h"
+ mctsave.x "../lib/mctable.h"
+ mctsget.x "../lib/mctable.h"
+ mctshrink.x "../lib/mctable.h"
+ mctsput.x "../lib/mctable.h"
+ mcttype.x "../lib/mctable.h"
+ ;
+
+zzdebug:
+ $ifeq (USE_GENERIC, yes)
+ $ifnewer (zzdebug.gx, zzdebug.x)
+ $generic -k -o zzdebug.x zzdebug.gx
+ $endif
+ $endif
+
+ $omake zzdebug.x
+ $link zzdebug.o ../../libpkg.a -o zzdebug.e
+ $delete zzdebug.o
+ ;
diff --git a/noao/digiphot/photcal/mctable/zzdebug.gx b/noao/digiphot/photcal/mctable/zzdebug.gx
new file mode 100644
index 00000000..b7c091a7
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/zzdebug.gx
@@ -0,0 +1,1318 @@
+include <ctotok.h>
+include <error.h>
+include <ctype.h>
+include "mctable.h"
+
+task mctable = t_mctable
+
+# Types
+define TYPES "|char|short|int|long|real|double|complex|pointer|"
+define TYPE_CHAR 1
+define TYPE_SHORT 2
+define TYPE_INT 3
+define TYPE_LONG 4
+define TYPE_REAL 5
+define TYPE_DOUBLE 6
+define TYPE_COMPLEX 7
+define TYPE_POINTER 8
+
+# File modes
+define MODES "|write_only|read_write|new_file|temp_file|"
+define MODE_WRITE_ONLY 1
+define MODE_READ_WRITE 2
+define MODE_NEW_FILE 3
+define MODE_TEMP_FILE 4
+
+# Commands
+define COMMANDS "|allocate|free|copy|save|restore|\
+ |reset|shrink|clear|nrows|ncols|maxrows|maxcol|type|\
+ |getbuf|getrow|getrandom|putrandom|\
+ |rewind|getsequential|putsequential|\
+ |data|header|help|tables|time|quit|"
+define ALLOCATE 1
+define FREE 2
+define COPY 3
+define SAVE 4
+define RESTORE 5
+# newline 6
+define RESET 7
+define SHRINK 8
+define CLEAR 9
+define NROWS 10
+define NCOLS 11
+define MAXROW 12
+define MAXCOL 13
+define TYPE 14
+# newline 15
+define GETBUF 16
+define GETROW 17
+define GETRAN 18
+define PUTRAN 19
+# newline 20
+define REWIND 21
+define GETSEQ 22
+define PUTSEQ 23
+# newline 24
+define DATA 25
+define HEADER 26
+define HELP 27
+define TABLES 28
+define TIME 29
+define QUIT 30
+
+# Max number of tables
+define MAX_TABLES 10
+
+
+# MCTABLE -- Test MCTABLE package.
+
+procedure t_mctable()
+
+bool timeit # time commands ?
+char line[SZ_LINE] # input line
+char key[SZ_FNAME]
+char cmd[SZ_LINE] # command string
+int ncmd # command number
+int i, ip
+long svtime[2]
+pointer table[MAX_TABLES] # table pointers
+
+int getline()
+int strdic(), strlen()
+int strext()
+
+begin
+ # Clear table pointers
+ call amovki (NULL, table, MAX_TABLES)
+
+ # Do not time commands
+ timeit = false
+
+ # Print initial message
+ call printf ("Multicolumn table test program\n")
+ call printf ("Type `help` to get a list of commands\n\n")
+
+ # Loop reading commands
+ repeat {
+
+ # Get next command
+ call printf ("mctable> ")
+ call flush (STDOUT)
+ if (getline (STDIN, line) == EOF) {
+ call printf ("\n")
+ break
+ }
+ line[strlen (line)] = EOS
+
+ # Extract command from line
+ ip = 1
+ if (strext (line, ip, " ", YES, cmd, SZ_LINE) == 0)
+ next
+ ncmd = strdic (cmd, cmd, SZ_LINE, COMMANDS)
+ if (ncmd == 0) {
+ call eprintf ("Unknown or ambiguous command (%s)\n")
+ call pargstr (cmd)
+ next
+ }
+
+ # Time command
+ if (timeit)
+ call sys_mtime (svtime)
+
+ switch (ncmd) {
+ case ALLOCATE:
+ call zzallocate (table, line, ip)
+
+ case FREE:
+ call zzfree (table, line, ip)
+
+ case COPY:
+ call zzcopy (table, line, ip)
+
+ case SAVE:
+ call zzsave (table, line, ip)
+
+ case RESTORE:
+ call zzrestore (table, line, ip)
+
+ case RESET:
+ call zzreset (table, line, ip)
+
+ case SHRINK:
+ call zzshrink (table, line, ip)
+
+ case CLEAR:
+ call zzclear (table, line, ip)
+
+ case NROWS:
+ call zznrows (table, line, ip)
+
+ case NCOLS:
+ call zzncols (table, line, ip)
+
+ case MAXROW:
+ call zzmaxrow (table, line, ip)
+
+ case MAXCOL:
+ call zzmaxcol (table, line, ip)
+
+ case TYPE:
+ call zztype (table, line, ip)
+
+ case GETBUF:
+ call zzgetbuf (table, line, ip)
+
+ case GETROW:
+ call zzgetrow (table, line, ip)
+
+ case GETRAN:
+ call zzgetran (table, line, ip)
+
+ case PUTRAN:
+ call zzputran (table, line, ip)
+
+ case REWIND:
+ call zzrewind (table, line, ip)
+
+ case GETSEQ:
+ call zzgetseq (table, line, ip)
+
+ case PUTSEQ:
+ call zzputseq (table, line, ip)
+
+ case DATA:
+ call zzdata (table, line, ip)
+
+ case HEADER:
+ call zzheader (table, line, ip)
+
+ case HELP:
+ call zzhelp (STDOUT)
+
+ case TABLES:
+ call printf ("table..\n")
+ do i = 1, MAX_TABLES {
+ call printf ("%d\t%d\n")
+ call pargi (i)
+ call pargi (table[i])
+ }
+ call flush (STDOUT)
+
+ case TIME:
+ timeit = !timeit
+ if (timeit)
+ call printf ("time..\n")
+ else
+ call printf ("do not time..\n")
+ call flush (STDOUT)
+
+ case QUIT:
+ call printf ("quit..\n")
+ call flush (STDOUT)
+ return
+
+ default:
+ call eprintf ("Syntax error\n")
+ }
+
+ if (timeit)
+ call sys_ptime (STDOUT, key, svtime)
+ }
+end
+
+
+# ZZALLOCATE -- Allocate table.
+
+procedure zzallocate (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # character pointer
+
+int tnum, nrows, ncols, type
+
+begin
+ call printf ("allocate..\n")
+
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgtype (line, ip, type)
+ call zzgeti (line, ip, nrows)
+ call zzgeti (line, ip, ncols)
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (call mct_alloc (table[tnum], nrows, ncols, type)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d) allocated, nrows = (%d), ncols = (%d), type = (%d)\n")
+ call pargi (tnum)
+ call pargi (nrows)
+ call pargi (ncols)
+ call pargi (type)
+
+ call flush (STDOUT)
+end
+
+
+# ZZFREE -- Free table.
+
+procedure zzfree (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum
+
+begin
+ call printf ("free..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (call mct_free (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d) freed\n")
+ call pargi (tnum)
+
+ call flush (STDOUT)
+end
+
+
+# ZZCOPY -- Copy one table into another.
+
+procedure zzcopy (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum1, tnum2
+
+begin
+ call printf ("copy..\n")
+ iferr {
+ call zzgtable (line, ip, tnum1)
+ call zzgtable (line, ip, tnum2)
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+ iferr (call mct_copy (table[tnum1], table[tnum2])) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf ("Table (%d) copied into table (%d)\n")
+ call pargi (tnum1)
+ call pargi (tnum2)
+
+ call flush (STDOUT)
+end
+
+
+# ZZSAVE -- Save table into a file.
+
+procedure zzsave (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+char fname[SZ_FNAME]
+int fmode, tnum
+
+begin
+ call printf ("save..\n")
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgstr (line, ip, fname)
+ call zzgmode (line, ip, fmode)
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+ iferr (call mct_save (fname, fmode, table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf ("Table (%d) saved into file (%s)\n")
+ call pargi (tnum)
+ call pargstr (fname)
+
+ call flush (STDOUT)
+end
+
+
+# ZZRESTORE -- Restore table from a file.
+
+procedure zzrestore (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+char fname[SZ_FNAME]
+int tnum
+
+begin
+ call printf ("restore..\n")
+
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgstr (line, ip, fname, SZ_FNAME)
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (call mct_restore (fname, table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d) restored from file (%s)\n")
+ call pargi (tnum)
+ call pargstr (fname)
+
+ call flush (STDOUT)
+end
+
+
+# ZZRESET -- Reset table counters.
+
+procedure zzreset (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum
+
+begin
+ call printf ("reset..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (call mct_reset (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d) reseted\n")
+ call pargi (tnum)
+
+ call flush (STDOUT)
+end
+
+
+# ZZSHRINK -- Shibk table.
+
+procedure zzshrink (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum
+
+begin
+ call printf ("shrink..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (call mct_shrink (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d) shrunk\n")
+ call pargi (tnum)
+
+ call flush (STDOUT)
+end
+
+
+# ZZCLEAR -- Clear table.
+
+procedure zzclear (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int type, tnum
+$for (csilrdxp)
+PIXEL $tval
+$endfor
+
+begin
+ call printf ("clear..\n")
+
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgtype (line, ip, type)
+ switch (type) {
+ $for (csilrdxp)
+ case TY_PIXEL:
+ call zzget$t (line, ip, $tval)
+ $endfor
+ }
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+
+ switch (type) {
+ $for (csilrdxp)
+ case TY_PIXEL:
+ iferr (call mct_clear$t (table[tnum], $tval)) {
+ call erract (EA_WARN)
+ return
+ }
+ $endfor
+ }
+
+ call printf ("Table (%d) cleared\n")
+ call pargi (tnum)
+
+ call flush (STDOUT)
+end
+
+
+# ZZNROWS -- Get number of rows in table.
+
+procedure zznrows (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum, nrows
+
+int mct_nrows()
+
+begin
+ call printf ("nrows..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (nrows = mct_nrows (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d), nrows = (%d)\n")
+ call pargi (tnum)
+ call pargi (nrows)
+
+ call flush (STDOUT)
+end
+
+
+# ZZNCOLS -- Get number of columns in table.
+
+procedure zzncols (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum, ncols
+
+int mct_ncols()
+
+begin
+ call printf ("ncols..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (ncols = mct_ncols (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d), ncols = (%d)\n")
+ call pargi (tnum)
+ call pargi (ncols)
+
+ call flush (STDOUT)
+end
+
+
+# ZZMAXROW -- Get maximum number of rows in table.
+
+procedure zzmaxrow (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum, nrows
+
+int mct_maxrow()
+
+begin
+ call printf ("maxrow..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (nrows = mct_maxrow (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d), maxrow = (%d)\n")
+ call pargi (tnum)
+ call pargi (nrows)
+
+ call flush (STDOUT)
+end
+
+
+# ZZMAXCOL -- Get maximum number of columns in table.
+
+procedure zzmaxcol (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum, ncols
+
+int mct_maxcol()
+
+begin
+ call printf ("maxcol..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (ncols = mct_maxcol (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d), maxcol = (%d)\n")
+ call pargi (tnum)
+ call pargi (ncols)
+
+ call flush (STDOUT)
+end
+
+
+# ZZTYPE -- Get table type.
+
+procedure zztype (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum, type
+
+int mct_type()
+
+begin
+ call printf ("type..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (type = mct_type (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d), type = (%d)\n")
+ call pargi (tnum)
+ call pargi (type)
+
+ call flush (STDOUT)
+end
+
+
+# ZZGETBUF -- Get data buffer pointer.
+
+procedure zzgetbuf (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum
+pointer pval
+
+pointer mct_getbuf()
+
+begin
+ call printf ("getbuf..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (pval = mct_getbuf (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d), buffer = (%d)\n")
+ call pargi (tnum)
+ call pargi (pval)
+
+ call flush (STDOUT)
+end
+
+
+# ZZGETROW -- Get row pointer.
+
+procedure zzgetrow (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum, row
+pointer pval
+
+pointer mct_getrow()
+
+begin
+ call printf ("getrow..\n")
+
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgeti (line, ip, row)
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (pval = mct_getrow (table[tnum], row)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d), row buffer (%d) = (%d)\n")
+ call pargi (tnum)
+ call pargi (row)
+ call pargi (pval)
+
+ call flush (STDOUT)
+end
+
+
+# ZZGETRAN -- Get value randomly from table.
+
+procedure zzgetran (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int type, tnum, row, col
+$for (csilrdxp)
+PIXEL $tval
+$endfor
+
+$for (csilrdxp)
+PIXEL mct_get$t()
+$endfor
+
+begin
+ call printf ("getrandom..\n")
+
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgtype (line, ip, type)
+ call zzgeti (line, ip, row)
+ call zzgeti (line, ip, col)
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+
+ switch (type) {
+ $for (csilrdxp)
+ case TY_PIXEL:
+ iferr ($tval = mct_get$t (table[tnum], row, col)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table get (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ $if (datatype == p)
+ call pargi ($tval)
+ $else
+ call parg$t ($tval)
+ $endif
+ $endfor
+ }
+
+ call flush (STDOUT)
+end
+
+
+# ZZPUTRAN -- Put value randomly in table.
+
+procedure zzputran (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int type, tnum, row, col
+$for (csilrdxp)
+PIXEL $tval
+$endfor
+
+begin
+ call printf ("putrandom..\n")
+
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgtype (line, ip, type)
+ call zzgeti (line, ip, row)
+ call zzgeti (line, ip, col)
+ switch (type) {
+ $for (csilrdxp)
+ case TY_PIXEL:
+ call zzget$t (line, ip, $tval)
+ $endfor
+ }
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+
+ switch (type) {
+ $for (csilrdxp)
+ case TY_PIXEL:
+ iferr (call mct_put$t (table[tnum], row, col, $tval)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table put (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ $if (datatype == p)
+ call pargi ($tval)
+ $else
+ call parg$t ($tval)
+ $endif
+ $endfor
+ }
+
+ call flush (STDOUT)
+end
+
+
+# ZZREWIND -- Rewind table.
+
+procedure zzrewind (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum
+
+begin
+ call printf ("rewind..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (call mct_rew (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d) rewound\n")
+ call pargi (tnum)
+
+ call flush (STDOUT)
+end
+
+
+# ZZGETSEQ -- Get value sequentialy from table.
+
+procedure zzgetseq (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int type, tnum, stat
+$for (csilrdxp)
+PIXEL $tval
+$endfor
+
+$for (csilrdxp)
+int mct_sget$t()
+$endfor
+
+begin
+ call printf ("getsequential..\n")
+
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgtype (line, ip, type)
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+
+ switch (type) {
+ $for (csilrdxp)
+ case TY_PIXEL:
+ iferr (stat = mct_sget$t (table[tnum], $tval)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table getsequential (%d), type = (%s), value = (%g) (stat=%s)\n")
+ call pargi (tnum)
+ call pargi (type)
+ $if (datatype == p)
+ call pargi ($tval)
+ $else
+ call parg$t ($tval)
+ if (stat == EOF)
+ call pargstr ("EOF")
+ else if (stat == OK)
+ call pargstr ("OK")
+ else
+ call pargstr ("???")
+ $endif
+ $endfor
+ }
+
+ call flush (STDOUT)
+end
+
+
+# ZZPUTSEQ -- Put value sequentaly.
+
+procedure zzputseq (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int type, tnum
+$for (csilrdxp)
+PIXEL $tval
+$endfor
+
+begin
+ call printf ("putsequential..\n")
+
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgtype (line, ip, type)
+ switch (type) {
+ $for (csilrdxp)
+ case TY_PIXEL:
+ call zzget$t (line, ip, $tval)
+ $endfor
+ }
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+
+ switch (type) {
+ $for (csilrdxp)
+ case TY_PIXEL:
+ iferr (call mct_sput$t (table[tnum], $tval)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table putsequential (%d), type = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ $if (datatype == p)
+ call pargi ($tval)
+ $else
+ call parg$t ($tval)
+ $endif
+ $endfor
+ }
+
+ call flush (STDOUT)
+end
+
+
+# ZZDATA -- Display table data.
+
+procedure zzdata (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum, type, offset
+int row, row1, row2, col
+$for (csilrdxp)
+PIXEL $tval
+$endfor
+
+begin
+ call printf ("data..\n")
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+ iferr (call zzgeti (line, ip, row1))
+ row1 = 1
+ else
+ row1 = min (max (row1, 1), MCT_MAXROW (table[tnum]))
+ iferr (call zzgeti (line, ip, row2))
+ row2 = MCT_MAXROW (table[tnum])
+ else
+ row2 = max (min (row2, MCT_MAXROW (table[tnum])), row1)
+
+call eprintf ("table[%d]=%d\n")
+call pargi (tnum)
+call pargi (table[tnum])
+
+ if (table[tnum] == NULL) {
+ call eprintf ("ERROR: Null table pointer\n")
+ return
+ }
+ if (MCT_DATA (table[tnum]) == NULL) {
+ call eprintf ("ERROR: Null data pointer\n")
+ return
+ }
+
+ type = MCT_TYPE (table[tnum])
+
+ call printf ("(%d x %d) -> (%d:%d)\n")
+ call pargi (MCT_MAXROW (table[tnum]))
+ call pargi (MCT_MAXCOL (table[tnum]))
+ call pargi (row1)
+ call pargi (row2)
+
+ do row = row1, row2 {
+
+ call printf ("%d\t")
+ call pargi (row)
+
+ do col = 1, MCT_MAXCOL (table[tnum]) {
+
+ offset = MCT_MAXCOL (table[tnum]) * (row - 1) + col - 1
+
+ switch (type) {
+ $for (csilrdxp)
+ case TY_PIXEL:
+ $if (datatype == p)
+ $tval = Memi[MCT_DATA (table[tnum]) + offset]
+ $else
+ $tval = Mem$t[MCT_DATA (table[tnum]) + offset]
+ $endif
+ call printf (" %g")
+ $if (datatype == p)
+ call pargi ($tval)
+ $else
+ call parg$t ($tval)
+ $endif
+ $endfor
+ }
+ }
+
+ call printf ("\n")
+ call flush (STDOUT)
+ }
+
+ call flush (STDOUT)
+end
+
+
+# ZZHEADER -- Print table header.
+
+procedure zzheader (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum
+
+begin
+ call printf ("header..\n")
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+ if (table[tnum] == NULL) {
+ call eprintf ("ERROR: Null table pointer\n")
+ return
+ }
+ call printf ("magic %d\n")
+ call pargi (MCT_MAGIC (table[tnum]))
+ call printf ("type %d\n")
+ call pargi (MCT_TYPE (table[tnum]))
+ call printf ("incrow %d\n")
+ call pargi (MCT_INCROWS (table[tnum]))
+ call printf ("maxrow %d\n")
+ call pargi (MCT_MAXROW (table[tnum]))
+ call printf ("maxcol %d\n")
+ call pargi (MCT_MAXCOL (table[tnum]))
+ call printf ("nprows %d\n")
+ call pargi (MCT_NPROWS (table[tnum]))
+ call printf ("npcols %d\n")
+ call pargi (MCT_NPCOLS (table[tnum]))
+ call printf ("ngrows %d\n")
+ call pargi (MCT_NGROWS (table[tnum]))
+ call printf ("ngcols %d\n")
+ call pargi (MCT_NGCOLS (table[tnum]))
+ call printf ("data %d\n")
+ call pargi (MCT_DATA (table[tnum]))
+
+ call flush (STDOUT)
+end
+
+
+# ZZHELP -- Print command dictionary for interpreter.
+
+procedure zzhelp ()
+
+begin
+ call printf ("help..\n")
+ call printf ("allocate <table> <type> <nrows> <ncols>\n")
+ call printf ("free <table>\n")
+ call printf ("copy <table> <table>\n\n")
+ call printf ("save <table> <fname> <fmode>\n")
+ call printf ("restore <table> <fname>\n\n")
+ call printf ("reset <table>\n")
+ call printf ("rewind <table>\n")
+ call printf ("clear <table> <value>\n\n")
+ call printf ("maxrow <table>\n")
+ call printf ("maxcol <table>\n")
+ call printf ("nrows <table>\n")
+ call printf ("ncols <table>\n")
+ call printf ("type <table>\n\n")
+ call printf ("getbuf <table>\n")
+ call printf ("getrow <table> <row>\n\n")
+ call printf ("getrandom <table> <type> <row> <col>\n")
+ call printf ("putrandom <table> <type> <row> <col> <value>\n\n")
+ call printf ("putsequential <table> <type> <value>\n")
+ call printf ("getsequential <table> <type>\n\n")
+ call printf ("tables\n")
+ call printf ("header <table>\n")
+ call printf ("data <table> <row1> <row2>\n")
+ call printf ("help\n")
+ call printf ("quit\n")
+ call printf ("\nwhere:\n")
+ call printf (" <table> = 1..10\n")
+ call printf (" <type> = %s\n")
+ call pargstr (TYPES)
+ call printf (" <fmode> = %s\n")
+ call pargstr (MODES)
+
+ call flush (STDOUT)
+end
+
+
+# ZZGTABLE -- Get table number and check its range.
+
+procedure zzgtable (line, ip, num)
+
+char line[ARB] # command line
+int ip # input character pointer
+int num # table number
+
+errchk zzgeti()
+
+begin
+ call zzgeti (line, ip, num)
+ if (num < 1 || num > MAX_TABLES)
+ call error (0, "Table number out of range")
+end
+
+
+# ZZGTYPE -- Convert from string to integer type
+
+procedure zzgtype (line, ip, type)
+
+char line[ARB] # input line
+int ip # input character pointer
+int type # table type (output)
+
+char strval[SZ_LINE]
+int ntype
+
+int strdic()
+
+begin
+ call zzgstr (line, ip, strval, SZ_LINE)
+
+ ntype = strdic (strval, strval, SZ_LINE, TYPES)
+
+ switch (ntype) {
+ case TYPE_CHAR:
+ type = TY_CHAR
+ case TYPE_SHORT:
+ type = TY_SHORT
+ case TYPE_INT:
+ type = TY_INT
+ case TYPE_LONG:
+ type = TY_LONG
+ case TYPE_REAL:
+ type = TY_REAL
+ case TYPE_DOUBLE:
+ type = TY_DOUBLE
+ case TYPE_COMPLEX:
+ type = TY_COMPLEX
+ case TYPE_POINTER:
+ type = TY_POINTER
+ default:
+ call error (0, "Unknown table type")
+ }
+end
+
+
+# ZZGMODE -- Get mode string and convert it into a file mode.
+
+procedure zzgmode (line, ip, mode)
+
+char line[ARB] # input line
+int ip # input character pointer
+int mode # file mode (output)
+
+char strval[SZ_LINE]
+int nmode
+
+int strdic()
+
+begin
+ call zzgstr (line, ip, strval, SZ_LINE)
+
+ nmode = strdic (strval, strval, SZ_LINE, MODES)
+
+ switch (nmode) {
+ case MODE_WRITE_ONLY:
+ mode = WRITE_ONLY
+ case MODE_READ_WRITE:
+ mode = READ_WRITE
+ case MODE_NEW_FILE:
+ mode = NEW_FILE
+ case MODE_TEMP_FILE:
+ mode = TEMP_FILE
+ default:
+ call error (0, "zzgmode: Unknown file mode")
+ }
+end
+
+
+$for (csilrdxp)
+# ZZGET -- Get number from command line
+
+procedure zzget$t (line, ip, $tval)
+
+char line[ARB] # command line
+int ip # input character pointer
+PIXEL $tval # number
+
+char number[SZ_LINE]
+int op
+
+$if (datatype == csp)
+$if (datatype == c)
+int cctoc()
+$endif
+$if (datatype == s)
+int ctoi()
+$endif
+$if (datatype == p)
+int ctoi()
+$endif
+$else
+int cto$t()
+$endif
+int strext()
+
+begin
+ if (strext (line, ip, " ", YES, number, SZ_LINE) == 0)
+ call error (0, "Missing numeric parameter\n")
+
+ op = 1
+ $if (datatype == csp)
+ $if (datatype == c)
+ if (cctoc (number, op, cval) == 0)
+ call error (0, "zzget: Impossible number conversion\n")
+ $endif
+ $if (datatype == s)
+ if (ctoi (number, op, int (sval)) == 0)
+ call error (0, "zzget: Impossible number conversion\n")
+ $endif
+ $if (datatype == p)
+ if (ctoi (number, op, pval) == 0)
+ call error (0, "zzget: Impossible number conversion\n")
+ $endif
+ $else
+ if (cto$t (number, op, $tval) == 0)
+ call error (0, "zzget: Impossible number conversion\n")
+ $endif
+end
+$endfor
+
+
+# ZZGSTR -- Get string from command line
+
+int procedure zzgstr (line, ip, strval, maxch)
+
+char line[ARB] # command line
+int ip # input character pointer
+char strval[maxch] # output string
+int maxch # max number of characters
+
+int strext()
+
+begin
+ if (strext (line, ip, " ", YES, strval, maxch) == 0)
+ call error (0, "Missing string parameter")
+end
diff --git a/noao/digiphot/photcal/mctable/zzdebug.x b/noao/digiphot/photcal/mctable/zzdebug.x
new file mode 100644
index 00000000..e234e6d0
--- /dev/null
+++ b/noao/digiphot/photcal/mctable/zzdebug.x
@@ -0,0 +1,2066 @@
+include <ctotok.h>
+include <error.h>
+include <ctype.h>
+include "../lib/mctable.h"
+
+task mctable = t_mctable
+
+# Types
+define TYPES "|char|short|int|long|real|double|complex|pointer|"
+define TYPE_CHAR 1
+define TYPE_SHORT 2
+define TYPE_INT 3
+define TYPE_LONG 4
+define TYPE_REAL 5
+define TYPE_DOUBLE 6
+define TYPE_COMPLEX 7
+define TYPE_POINTER 8
+
+# File modes
+define MODES "|write_only|read_write|new_file|temp_file|"
+define MODE_WRITE_ONLY 1
+define MODE_READ_WRITE 2
+define MODE_NEW_FILE 3
+define MODE_TEMP_FILE 4
+
+# Commands
+define COMMANDS "|allocate|free|copy|save|restore|\
+ |reset|shrink|clear|nrows|ncols|maxrows|maxcol|type|\
+ |getbuf|getrow|getrandom|putrandom|\
+ |rewind|getsequential|putsequential|\
+ |data|header|help|tables|time|quit|"
+define ALLOCATE 1
+define FREE 2
+define COPY 3
+define SAVE 4
+define RESTORE 5
+# newline 6
+define RESET 7
+define SHRINK 8
+define CLEAR 9
+define NROWS 10
+define NCOLS 11
+define MAXROW 12
+define MAXCOL 13
+define TYPE 14
+# newline 15
+define GETBUF 16
+define GETROW 17
+define GETRAN 18
+define PUTRAN 19
+# newline 20
+define REWIND 21
+define GETSEQ 22
+define PUTSEQ 23
+# newline 24
+define DATA 25
+define HEADER 26
+define HELP 27
+define TABLES 28
+define TIME 29
+define QUIT 30
+
+# Max number of tables
+define MAX_TABLES 10
+
+
+# MCTABLE -- Test MCTABLE package.
+
+procedure t_mctable()
+
+bool timeit # time commands ?
+char line[SZ_LINE] # input line
+char key[SZ_FNAME]
+char cmd[SZ_LINE] # command string
+int ncmd # command number
+int i, ip
+long svtime[2]
+pointer table[MAX_TABLES] # table pointers
+
+int getline()
+int strdic(), strlen()
+int strext()
+
+begin
+ # Clear table pointers
+ call amovki (NULL, table, MAX_TABLES)
+
+ # Do not time commands
+ timeit = false
+
+ # Print initial message
+ call printf ("Multicolumn table test program\n")
+ call printf ("Type `help` to get a list of commands\n\n")
+
+ # Loop reading commands
+ repeat {
+
+ # Get next command
+ call printf ("mctable> ")
+ call flush (STDOUT)
+ if (getline (STDIN, line) == EOF) {
+ call printf ("\n")
+ break
+ }
+ line[strlen (line)] = EOS
+
+ # Extract command from line
+ ip = 1
+ if (strext (line, ip, " ", YES, cmd, SZ_LINE) == 0)
+ next
+ ncmd = strdic (cmd, cmd, SZ_LINE, COMMANDS)
+ if (ncmd == 0) {
+ call eprintf ("Unknown or ambiguous command (%s)\n")
+ call pargstr (cmd)
+ next
+ }
+
+ # Time command
+ if (timeit)
+ call sys_mtime (svtime)
+
+ switch (ncmd) {
+ case ALLOCATE:
+ call zzallocate (table, line, ip)
+
+ case FREE:
+ call zzfree (table, line, ip)
+
+ case COPY:
+ call zzcopy (table, line, ip)
+
+ case SAVE:
+ call zzsave (table, line, ip)
+
+ case RESTORE:
+ call zzrestore (table, line, ip)
+
+ case RESET:
+ call zzreset (table, line, ip)
+
+ case SHRINK:
+ call zzshrink (table, line, ip)
+
+ case CLEAR:
+ call zzclear (table, line, ip)
+
+ case NROWS:
+ call zznrows (table, line, ip)
+
+ case NCOLS:
+ call zzncols (table, line, ip)
+
+ case MAXROW:
+ call zzmaxrow (table, line, ip)
+
+ case MAXCOL:
+ call zzmaxcol (table, line, ip)
+
+ case TYPE:
+ call zztype (table, line, ip)
+
+ case GETBUF:
+ call zzgetbuf (table, line, ip)
+
+ case GETROW:
+ call zzgetrow (table, line, ip)
+
+ case GETRAN:
+ call zzgetran (table, line, ip)
+
+ case PUTRAN:
+ call zzputran (table, line, ip)
+
+ case REWIND:
+ call zzrewind (table, line, ip)
+
+ case GETSEQ:
+ call zzgetseq (table, line, ip)
+
+ case PUTSEQ:
+ call zzputseq (table, line, ip)
+
+ case DATA:
+ call zzdata (table, line, ip)
+
+ case HEADER:
+ call zzheader (table, line, ip)
+
+ case HELP:
+ call zzhelp ()
+
+ case TABLES:
+ call printf ("table..\n")
+ do i = 1, MAX_TABLES {
+ call printf ("%d\t%d\n")
+ call pargi (i)
+ call pargi (table[i])
+ }
+ call flush (STDOUT)
+
+ case TIME:
+ timeit = !timeit
+ if (timeit)
+ call printf ("time..\n")
+ else
+ call printf ("do not time..\n")
+ call flush (STDOUT)
+
+ case QUIT:
+ call printf ("quit..\n")
+ call flush (STDOUT)
+ return
+
+ default:
+ call eprintf ("Syntax error\n")
+ }
+
+ if (timeit)
+ call sys_ptime (STDOUT, key, svtime)
+ }
+end
+
+
+# ZZALLOCATE -- Allocate table.
+
+procedure zzallocate (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # character pointer
+
+int tnum, nrows, ncols, type
+
+begin
+ call printf ("allocate..\n")
+
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgtype (line, ip, type)
+ call zzgeti (line, ip, nrows)
+ call zzgeti (line, ip, ncols)
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (call mct_alloc (table[tnum], nrows, ncols, type)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d) allocated, nrows = (%d), ncols = (%d), type = (%d)\n")
+ call pargi (tnum)
+ call pargi (nrows)
+ call pargi (ncols)
+ call pargi (type)
+
+ call flush (STDOUT)
+end
+
+
+# ZZFREE -- Free table.
+
+procedure zzfree (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum
+
+begin
+ call printf ("free..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (call mct_free (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d) freed\n")
+ call pargi (tnum)
+
+ call flush (STDOUT)
+end
+
+
+# ZZCOPY -- Copy one table into another.
+
+procedure zzcopy (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum1, tnum2
+
+begin
+ call printf ("copy..\n")
+ iferr {
+ call zzgtable (line, ip, tnum1)
+ call zzgtable (line, ip, tnum2)
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+ iferr (call mct_copy (table[tnum1], table[tnum2])) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf ("Table (%d) copied into table (%d)\n")
+ call pargi (tnum1)
+ call pargi (tnum2)
+
+ call flush (STDOUT)
+end
+
+
+# ZZSAVE -- Save table into a file.
+
+procedure zzsave (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+char fname[SZ_FNAME]
+int fmode, tnum
+
+begin
+ call printf ("save..\n")
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgstr (line, ip, fname, SZ_FNAME)
+ call zzgmode (line, ip, fmode)
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+ iferr (call mct_save (fname, fmode, table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf ("Table (%d) saved into file (%s)\n")
+ call pargi (tnum)
+ call pargstr (fname)
+
+ call flush (STDOUT)
+end
+
+
+# ZZRESTORE -- Restore table from a file.
+
+procedure zzrestore (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+char fname[SZ_FNAME]
+int tnum
+
+begin
+ call printf ("restore..\n")
+
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgstr (line, ip, fname, SZ_FNAME)
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (call mct_restore (fname, table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d) restored from file (%s)\n")
+ call pargi (tnum)
+ call pargstr (fname)
+
+ call flush (STDOUT)
+end
+
+
+# ZZRESET -- Reset table counters.
+
+procedure zzreset (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum
+
+begin
+ call printf ("reset..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (call mct_reset (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d) reseted\n")
+ call pargi (tnum)
+
+ call flush (STDOUT)
+end
+
+
+# ZZSHRINK -- Shibk table.
+
+procedure zzshrink (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum
+
+begin
+ call printf ("shrink..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (call mct_shrink (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d) shrunk\n")
+ call pargi (tnum)
+
+ call flush (STDOUT)
+end
+
+
+# ZZCLEAR -- Clear table.
+
+procedure zzclear (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int type, tnum
+
+char cval
+
+short sval
+
+int ival
+
+long lval
+
+real rval
+
+double dval
+
+complex xval
+
+pointer pval
+
+
+begin
+ call printf ("clear..\n")
+
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgtype (line, ip, type)
+ switch (type) {
+
+ case TY_CHAR:
+ call zzgetc (line, ip, cval)
+
+ case TY_SHORT:
+ call zzgets (line, ip, sval)
+
+ case TY_INT:
+ call zzgeti (line, ip, ival)
+
+ case TY_LONG:
+ call zzgetl (line, ip, lval)
+
+ case TY_REAL:
+ call zzgetr (line, ip, rval)
+
+ case TY_DOUBLE:
+ call zzgetd (line, ip, dval)
+
+ case TY_COMPLEX:
+ call zzgetx (line, ip, xval)
+
+ case TY_POINTER:
+ call zzgetp (line, ip, pval)
+
+ }
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+
+ switch (type) {
+
+ case TY_CHAR:
+ iferr (call mct_clearc (table[tnum], cval)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ case TY_SHORT:
+ iferr (call mct_clears (table[tnum], sval)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ case TY_INT:
+ iferr (call mct_cleari (table[tnum], ival)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ case TY_LONG:
+ iferr (call mct_clearl (table[tnum], lval)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ case TY_REAL:
+ iferr (call mct_clearr (table[tnum], rval)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ case TY_DOUBLE:
+ iferr (call mct_cleard (table[tnum], dval)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ case TY_COMPLEX:
+ iferr (call mct_clearx (table[tnum], xval)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ case TY_POINTER:
+ iferr (call mct_clearp (table[tnum], pval)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ }
+
+ call printf ("Table (%d) cleared\n")
+ call pargi (tnum)
+
+ call flush (STDOUT)
+end
+
+
+# ZZNROWS -- Get number of rows in table.
+
+procedure zznrows (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum, nrows
+
+int mct_nrows()
+
+begin
+ call printf ("nrows..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (nrows = mct_nrows (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d), nrows = (%d)\n")
+ call pargi (tnum)
+ call pargi (nrows)
+
+ call flush (STDOUT)
+end
+
+
+# ZZNCOLS -- Get number of columns in table.
+
+procedure zzncols (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum, ncols
+
+int mct_ncols()
+
+begin
+ call printf ("ncols..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (ncols = mct_ncols (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d), ncols = (%d)\n")
+ call pargi (tnum)
+ call pargi (ncols)
+
+ call flush (STDOUT)
+end
+
+
+# ZZMAXROW -- Get maximum number of rows in table.
+
+procedure zzmaxrow (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum, nrows
+
+int mct_maxrow()
+
+begin
+ call printf ("maxrow..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (nrows = mct_maxrow (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d), maxrow = (%d)\n")
+ call pargi (tnum)
+ call pargi (nrows)
+
+ call flush (STDOUT)
+end
+
+
+# ZZMAXCOL -- Get maximum number of columns in table.
+
+procedure zzmaxcol (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum, ncols
+
+int mct_maxcol()
+
+begin
+ call printf ("maxcol..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (ncols = mct_maxcol (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d), maxcol = (%d)\n")
+ call pargi (tnum)
+ call pargi (ncols)
+
+ call flush (STDOUT)
+end
+
+
+# ZZTYPE -- Get table type.
+
+procedure zztype (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum, type
+
+int mct_type()
+
+begin
+ call printf ("type..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (type = mct_type (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d), type = (%d)\n")
+ call pargi (tnum)
+ call pargi (type)
+
+ call flush (STDOUT)
+end
+
+
+# ZZGETBUF -- Get data buffer pointer.
+
+procedure zzgetbuf (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum
+pointer pval
+
+pointer mct_getbuf()
+
+begin
+ call printf ("getbuf..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (pval = mct_getbuf (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d), buffer = (%d)\n")
+ call pargi (tnum)
+ call pargi (pval)
+
+ call flush (STDOUT)
+end
+
+
+# ZZGETROW -- Get row pointer.
+
+procedure zzgetrow (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum, row
+pointer pval
+
+pointer mct_getrow()
+
+begin
+ call printf ("getrow..\n")
+
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgeti (line, ip, row)
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (pval = mct_getrow (table[tnum], row)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d), row buffer (%d) = (%d)\n")
+ call pargi (tnum)
+ call pargi (row)
+ call pargi (pval)
+
+ call flush (STDOUT)
+end
+
+
+# ZZGETRAN -- Get value randomly from table.
+
+procedure zzgetran (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int type, tnum, row, col
+
+char cval
+
+short sval
+
+int ival
+
+long lval
+
+real rval
+
+double dval
+
+complex xval
+
+pointer pval
+
+
+
+char mct_getc()
+
+short mct_gets()
+
+int mct_geti()
+
+long mct_getl()
+
+real mct_getr()
+
+double mct_getd()
+
+complex mct_getx()
+
+pointer mct_getp()
+
+
+begin
+ call printf ("getrandom..\n")
+
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgtype (line, ip, type)
+ call zzgeti (line, ip, row)
+ call zzgeti (line, ip, col)
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+
+ switch (type) {
+
+ case TY_CHAR:
+ iferr (cval = mct_getc (table[tnum], row, col)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table get (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ call pargc (cval)
+
+ case TY_SHORT:
+ iferr (sval = mct_gets (table[tnum], row, col)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table get (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ call pargs (sval)
+
+ case TY_INT:
+ iferr (ival = mct_geti (table[tnum], row, col)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table get (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ call pargi (ival)
+
+ case TY_LONG:
+ iferr (lval = mct_getl (table[tnum], row, col)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table get (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ call pargl (lval)
+
+ case TY_REAL:
+ iferr (rval = mct_getr (table[tnum], row, col)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table get (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ call pargr (rval)
+
+ case TY_DOUBLE:
+ iferr (dval = mct_getd (table[tnum], row, col)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table get (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ call pargd (dval)
+
+ case TY_COMPLEX:
+ iferr (xval = mct_getx (table[tnum], row, col)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table get (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ call pargx (xval)
+
+ case TY_POINTER:
+ iferr (pval = mct_getp (table[tnum], row, col)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table get (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ call pargi (pval)
+
+ }
+
+ call flush (STDOUT)
+end
+
+
+# ZZPUTRAN -- Put value randomly in table.
+
+procedure zzputran (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int type, tnum, row, col
+
+char cval
+
+short sval
+
+int ival
+
+long lval
+
+real rval
+
+double dval
+
+complex xval
+
+pointer pval
+
+
+begin
+ call printf ("putrandom..\n")
+
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgtype (line, ip, type)
+ call zzgeti (line, ip, row)
+ call zzgeti (line, ip, col)
+ switch (type) {
+
+ case TY_CHAR:
+ call zzgetc (line, ip, cval)
+
+ case TY_SHORT:
+ call zzgets (line, ip, sval)
+
+ case TY_INT:
+ call zzgeti (line, ip, ival)
+
+ case TY_LONG:
+ call zzgetl (line, ip, lval)
+
+ case TY_REAL:
+ call zzgetr (line, ip, rval)
+
+ case TY_DOUBLE:
+ call zzgetd (line, ip, dval)
+
+ case TY_COMPLEX:
+ call zzgetx (line, ip, xval)
+
+ case TY_POINTER:
+ call zzgetp (line, ip, pval)
+
+ }
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+
+ switch (type) {
+
+ case TY_CHAR:
+ iferr (call mct_putc (table[tnum], row, col, cval)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table put (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ call pargc (cval)
+
+ case TY_SHORT:
+ iferr (call mct_puts (table[tnum], row, col, sval)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table put (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ call pargs (sval)
+
+ case TY_INT:
+ iferr (call mct_puti (table[tnum], row, col, ival)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table put (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ call pargi (ival)
+
+ case TY_LONG:
+ iferr (call mct_putl (table[tnum], row, col, lval)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table put (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ call pargl (lval)
+
+ case TY_REAL:
+ iferr (call mct_putr (table[tnum], row, col, rval)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table put (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ call pargr (rval)
+
+ case TY_DOUBLE:
+ iferr (call mct_putd (table[tnum], row, col, dval)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table put (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ call pargd (dval)
+
+ case TY_COMPLEX:
+ iferr (call mct_putx (table[tnum], row, col, xval)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table put (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ call pargx (xval)
+
+ case TY_POINTER:
+ iferr (call mct_putp (table[tnum], row, col, pval)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf (
+ "Table put (%d), type = (%d), row = (%d), col = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (row)
+ call pargi (col)
+ call pargi (pval)
+
+ }
+
+ call flush (STDOUT)
+end
+
+
+# ZZREWIND -- Rewind table.
+
+procedure zzrewind (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum
+
+begin
+ call printf ("rewind..\n")
+
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+
+ iferr (call mct_rew (table[tnum])) {
+ call erract (EA_WARN)
+ return
+ }
+
+ call printf ("Table (%d) rewound\n")
+ call pargi (tnum)
+
+ call flush (STDOUT)
+end
+
+
+# ZZGETSEQ -- Get value sequentialy from table.
+
+procedure zzgetseq (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int type, tnum, stat
+
+char cval
+
+short sval
+
+int ival
+
+long lval
+
+real rval
+
+double dval
+
+complex xval
+
+pointer pval
+
+
+
+int mct_sgetc()
+
+int mct_sgets()
+
+int mct_sgeti()
+
+int mct_sgetl()
+
+int mct_sgetr()
+
+int mct_sgetd()
+
+int mct_sgetx()
+
+int mct_sgetp()
+
+
+begin
+ call printf ("getsequential..\n")
+
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgtype (line, ip, type)
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+
+ switch (type) {
+
+ case TY_CHAR:
+ iferr (stat = mct_sgetc (table[tnum], cval)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table getsequential (%d), type = (%s), value = (%g) (stat=%s)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargc (cval)
+ if (stat == EOF)
+ call pargstr ("EOF")
+ else if (stat == OK)
+ call pargstr ("OK")
+ else
+ call pargstr ("???")
+
+ case TY_SHORT:
+ iferr (stat = mct_sgets (table[tnum], sval)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table getsequential (%d), type = (%s), value = (%g) (stat=%s)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargs (sval)
+ if (stat == EOF)
+ call pargstr ("EOF")
+ else if (stat == OK)
+ call pargstr ("OK")
+ else
+ call pargstr ("???")
+
+ case TY_INT:
+ iferr (stat = mct_sgeti (table[tnum], ival)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table getsequential (%d), type = (%s), value = (%g) (stat=%s)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (ival)
+ if (stat == EOF)
+ call pargstr ("EOF")
+ else if (stat == OK)
+ call pargstr ("OK")
+ else
+ call pargstr ("???")
+
+ case TY_LONG:
+ iferr (stat = mct_sgetl (table[tnum], lval)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table getsequential (%d), type = (%s), value = (%g) (stat=%s)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargl (lval)
+ if (stat == EOF)
+ call pargstr ("EOF")
+ else if (stat == OK)
+ call pargstr ("OK")
+ else
+ call pargstr ("???")
+
+ case TY_REAL:
+ iferr (stat = mct_sgetr (table[tnum], rval)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table getsequential (%d), type = (%s), value = (%g) (stat=%s)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargr (rval)
+ if (stat == EOF)
+ call pargstr ("EOF")
+ else if (stat == OK)
+ call pargstr ("OK")
+ else
+ call pargstr ("???")
+
+ case TY_DOUBLE:
+ iferr (stat = mct_sgetd (table[tnum], dval)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table getsequential (%d), type = (%s), value = (%g) (stat=%s)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargd (dval)
+ if (stat == EOF)
+ call pargstr ("EOF")
+ else if (stat == OK)
+ call pargstr ("OK")
+ else
+ call pargstr ("???")
+
+ case TY_COMPLEX:
+ iferr (stat = mct_sgetx (table[tnum], xval)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table getsequential (%d), type = (%s), value = (%g) (stat=%s)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargx (xval)
+ if (stat == EOF)
+ call pargstr ("EOF")
+ else if (stat == OK)
+ call pargstr ("OK")
+ else
+ call pargstr ("???")
+
+ case TY_POINTER:
+ iferr (stat = mct_sgetp (table[tnum], pval)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table getsequential (%d), type = (%s), value = (%g) (stat=%s)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (pval)
+
+ }
+
+ call flush (STDOUT)
+end
+
+
+# ZZPUTSEQ -- Put value sequentaly.
+
+procedure zzputseq (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int type, tnum
+
+char cval
+
+short sval
+
+int ival
+
+long lval
+
+real rval
+
+double dval
+
+complex xval
+
+pointer pval
+
+
+begin
+ call printf ("putsequential..\n")
+
+ iferr {
+ call zzgtable (line, ip, tnum)
+ call zzgtype (line, ip, type)
+ switch (type) {
+
+ case TY_CHAR:
+ call zzgetc (line, ip, cval)
+
+ case TY_SHORT:
+ call zzgets (line, ip, sval)
+
+ case TY_INT:
+ call zzgeti (line, ip, ival)
+
+ case TY_LONG:
+ call zzgetl (line, ip, lval)
+
+ case TY_REAL:
+ call zzgetr (line, ip, rval)
+
+ case TY_DOUBLE:
+ call zzgetd (line, ip, dval)
+
+ case TY_COMPLEX:
+ call zzgetx (line, ip, xval)
+
+ case TY_POINTER:
+ call zzgetp (line, ip, pval)
+
+ }
+ } then {
+ call erract (EA_WARN)
+ return
+ }
+
+ switch (type) {
+
+ case TY_CHAR:
+ iferr (call mct_sputc (table[tnum], cval)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table putsequential (%d), type = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargc (cval)
+
+ case TY_SHORT:
+ iferr (call mct_sputs (table[tnum], sval)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table putsequential (%d), type = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargs (sval)
+
+ case TY_INT:
+ iferr (call mct_sputi (table[tnum], ival)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table putsequential (%d), type = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (ival)
+
+ case TY_LONG:
+ iferr (call mct_sputl (table[tnum], lval)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table putsequential (%d), type = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargl (lval)
+
+ case TY_REAL:
+ iferr (call mct_sputr (table[tnum], rval)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table putsequential (%d), type = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargr (rval)
+
+ case TY_DOUBLE:
+ iferr (call mct_sputd (table[tnum], dval)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table putsequential (%d), type = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargd (dval)
+
+ case TY_COMPLEX:
+ iferr (call mct_sputx (table[tnum], xval)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table putsequential (%d), type = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargx (xval)
+
+ case TY_POINTER:
+ iferr (call mct_sputp (table[tnum], pval)) {
+ call erract (EA_WARN)
+ return
+ }
+ call printf (
+ "Table putsequential (%d), type = (%d), value = (%g)\n")
+ call pargi (tnum)
+ call pargi (type)
+ call pargi (pval)
+
+ }
+
+ call flush (STDOUT)
+end
+
+
+# ZZDATA -- Display table data.
+
+procedure zzdata (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum, type, offset
+int row, row1, row2, col
+
+char cval
+
+short sval
+
+int ival
+
+long lval
+
+real rval
+
+double dval
+
+complex xval
+
+pointer pval
+
+
+begin
+ call printf ("data..\n")
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+ iferr (call zzgeti (line, ip, row1))
+ row1 = 1
+ else
+ row1 = min (max (row1, 1), MCT_MAXROW (table[tnum]))
+ iferr (call zzgeti (line, ip, row2))
+ row2 = MCT_MAXROW (table[tnum])
+ else
+ row2 = max (min (row2, MCT_MAXROW (table[tnum])), row1)
+
+call eprintf ("table[%d]=%d\n")
+call pargi (tnum)
+call pargi (table[tnum])
+
+ if (table[tnum] == NULL) {
+ call eprintf ("ERROR: Null table pointer\n")
+ return
+ }
+ if (MCT_DATA (table[tnum]) == NULL) {
+ call eprintf ("ERROR: Null data pointer\n")
+ return
+ }
+
+ type = MCT_TYPE (table[tnum])
+
+ call printf ("(%d x %d) -> (%d:%d)\n")
+ call pargi (MCT_MAXROW (table[tnum]))
+ call pargi (MCT_MAXCOL (table[tnum]))
+ call pargi (row1)
+ call pargi (row2)
+
+ do row = row1, row2 {
+
+ call printf ("%d\t")
+ call pargi (row)
+
+ do col = 1, MCT_MAXCOL (table[tnum]) {
+
+ offset = MCT_MAXCOL (table[tnum]) * (row - 1) + col - 1
+
+ switch (type) {
+
+ case TY_CHAR:
+ cval = Memc[MCT_DATA (table[tnum]) + offset]
+ call printf (" %g")
+ call pargc (cval)
+
+ case TY_SHORT:
+ sval = Mems[MCT_DATA (table[tnum]) + offset]
+ call printf (" %g")
+ call pargs (sval)
+
+ case TY_INT:
+ ival = Memi[MCT_DATA (table[tnum]) + offset]
+ call printf (" %g")
+ call pargi (ival)
+
+ case TY_LONG:
+ lval = Meml[MCT_DATA (table[tnum]) + offset]
+ call printf (" %g")
+ call pargl (lval)
+
+ case TY_REAL:
+ rval = Memr[MCT_DATA (table[tnum]) + offset]
+ call printf (" %g")
+ call pargr (rval)
+
+ case TY_DOUBLE:
+ dval = Memd[MCT_DATA (table[tnum]) + offset]
+ call printf (" %g")
+ call pargd (dval)
+
+ case TY_COMPLEX:
+ xval = Memx[MCT_DATA (table[tnum]) + offset]
+ call printf (" %g")
+ call pargx (xval)
+
+ case TY_POINTER:
+ pval = Memi[MCT_DATA (table[tnum]) + offset]
+ call printf (" %g")
+ call pargi (pval)
+
+ }
+ }
+
+ call printf ("\n")
+ call flush (STDOUT)
+ }
+
+ call flush (STDOUT)
+end
+
+
+# ZZHEADER -- Print table header.
+
+procedure zzheader (table, line, ip)
+
+pointer table[MAX_TABLES] # table array
+char line[ARB] # command line
+int ip # input character pointer
+
+int tnum
+
+begin
+ call printf ("header..\n")
+ iferr (call zzgtable (line, ip, tnum)) {
+ call erract (EA_WARN)
+ return
+ }
+ if (table[tnum] == NULL) {
+ call eprintf ("ERROR: Null table pointer\n")
+ return
+ }
+ call printf ("magic %d\n")
+ call pargi (MCT_MAGIC (table[tnum]))
+ call printf ("type %d\n")
+ call pargi (MCT_TYPE (table[tnum]))
+ call printf ("incrow %d\n")
+ call pargi (MCT_INCROWS (table[tnum]))
+ call printf ("maxrow %d\n")
+ call pargi (MCT_MAXROW (table[tnum]))
+ call printf ("maxcol %d\n")
+ call pargi (MCT_MAXCOL (table[tnum]))
+ call printf ("nprows %d\n")
+ call pargi (MCT_NPROWS (table[tnum]))
+ call printf ("npcols %d\n")
+ call pargi (MCT_NPCOLS (table[tnum]))
+ call printf ("ngrows %d\n")
+ call pargi (MCT_NGROWS (table[tnum]))
+ call printf ("ngcols %d\n")
+ call pargi (MCT_NGCOLS (table[tnum]))
+ call printf ("data %d\n")
+ call pargi (MCT_DATA (table[tnum]))
+
+ call flush (STDOUT)
+end
+
+
+# ZZHELP -- Print command dictionary for interpreter.
+
+procedure zzhelp ()
+
+begin
+ call printf ("help..\n")
+ call printf ("allocate <table> <type> <nrows> <ncols>\n")
+ call printf ("free <table>\n")
+ call printf ("copy <table> <table>\n\n")
+ call printf ("save <table> <fname> <fmode>\n")
+ call printf ("restore <table> <fname>\n\n")
+ call printf ("reset <table>\n")
+ call printf ("rewind <table>\n")
+ call printf ("clear <table> <value>\n\n")
+ call printf ("maxrow <table>\n")
+ call printf ("maxcol <table>\n")
+ call printf ("nrows <table>\n")
+ call printf ("ncols <table>\n")
+ call printf ("type <table>\n\n")
+ call printf ("getbuf <table>\n")
+ call printf ("getrow <table> <row>\n\n")
+ call printf ("getrandom <table> <type> <row> <col>\n")
+ call printf ("putrandom <table> <type> <row> <col> <value>\n\n")
+ call printf ("putsequential <table> <type> <value>\n")
+ call printf ("getsequential <table> <type>\n\n")
+ call printf ("tables\n")
+ call printf ("header <table>\n")
+ call printf ("data <table> <row1> <row2>\n")
+ call printf ("help\n")
+ call printf ("quit\n")
+ call printf ("\nwhere:\n")
+ call printf (" <table> = 1..10\n")
+ call printf (" <type> = %s\n")
+ call pargstr (TYPES)
+ call printf (" <fmode> = %s\n")
+ call pargstr (MODES)
+
+ call flush (STDOUT)
+end
+
+
+# ZZGTABLE -- Get table number and check its range.
+
+procedure zzgtable (line, ip, num)
+
+char line[ARB] # command line
+int ip # input character pointer
+int num # table number
+
+errchk zzgeti()
+
+begin
+ call zzgeti (line, ip, num)
+ if (num < 1 || num > MAX_TABLES)
+ call error (0, "Table number out of range")
+end
+
+
+# ZZGTYPE -- Convert from string to integer type
+
+procedure zzgtype (line, ip, type)
+
+char line[ARB] # input line
+int ip # input character pointer
+int type # table type (output)
+
+char strval[SZ_LINE]
+int ntype
+
+int strdic()
+
+begin
+ call zzgstr (line, ip, strval, SZ_LINE)
+
+ ntype = strdic (strval, strval, SZ_LINE, TYPES)
+
+ switch (ntype) {
+ case TYPE_CHAR:
+ type = TY_CHAR
+ case TYPE_SHORT:
+ type = TY_SHORT
+ case TYPE_INT:
+ type = TY_INT
+ case TYPE_LONG:
+ type = TY_LONG
+ case TYPE_REAL:
+ type = TY_REAL
+ case TYPE_DOUBLE:
+ type = TY_DOUBLE
+ case TYPE_COMPLEX:
+ type = TY_COMPLEX
+ case TYPE_POINTER:
+ type = TY_POINTER
+ default:
+ call error (0, "Unknown table type")
+ }
+end
+
+
+# ZZGMODE -- Get mode string and convert it into a file mode.
+
+procedure zzgmode (line, ip, mode)
+
+char line[ARB] # input line
+int ip # input character pointer
+int mode # file mode (output)
+
+char strval[SZ_LINE]
+int nmode
+
+int strdic()
+
+begin
+ call zzgstr (line, ip, strval, SZ_LINE)
+
+ nmode = strdic (strval, strval, SZ_LINE, MODES)
+
+ switch (nmode) {
+ case MODE_WRITE_ONLY:
+ mode = WRITE_ONLY
+ case MODE_READ_WRITE:
+ mode = READ_WRITE
+ case MODE_NEW_FILE:
+ mode = NEW_FILE
+ case MODE_TEMP_FILE:
+ mode = TEMP_FILE
+ default:
+ call error (0, "zzgmode: Unknown file mode")
+ }
+end
+
+
+
+# ZZGET -- Get number from command line
+
+procedure zzgetc (line, ip, cval)
+
+char line[ARB] # command line
+int ip # input character pointer
+char cval # number
+
+char number[SZ_LINE]
+int op
+
+int cctoc()
+int strext()
+
+begin
+ if (strext (line, ip, " ", YES, number, SZ_LINE) == 0)
+ call error (0, "Missing numeric parameter\n")
+
+ op = 1
+ if (cctoc (number, op, cval) == 0)
+ call error (0, "zzget: Impossible number conversion\n")
+end
+
+# ZZGET -- Get number from command line
+
+procedure zzgets (line, ip, sval)
+
+char line[ARB] # command line
+int ip # input character pointer
+short sval # number
+
+char number[SZ_LINE]
+int op
+
+int ctoi()
+int strext()
+
+begin
+ if (strext (line, ip, " ", YES, number, SZ_LINE) == 0)
+ call error (0, "Missing numeric parameter\n")
+
+ op = 1
+ if (ctoi (number, op, int (sval)) == 0)
+ call error (0, "zzget: Impossible number conversion\n")
+end
+
+# ZZGET -- Get number from command line
+
+procedure zzgeti (line, ip, ival)
+
+char line[ARB] # command line
+int ip # input character pointer
+int ival # number
+
+char number[SZ_LINE]
+int op
+
+int ctoi()
+int strext()
+
+begin
+ if (strext (line, ip, " ", YES, number, SZ_LINE) == 0)
+ call error (0, "Missing numeric parameter\n")
+
+ op = 1
+ if (ctoi (number, op, ival) == 0)
+ call error (0, "zzget: Impossible number conversion\n")
+end
+
+# ZZGET -- Get number from command line
+
+procedure zzgetl (line, ip, lval)
+
+char line[ARB] # command line
+int ip # input character pointer
+long lval # number
+
+char number[SZ_LINE]
+int op
+
+int ctol()
+int strext()
+
+begin
+ if (strext (line, ip, " ", YES, number, SZ_LINE) == 0)
+ call error (0, "Missing numeric parameter\n")
+
+ op = 1
+ if (ctol (number, op, lval) == 0)
+ call error (0, "zzget: Impossible number conversion\n")
+end
+
+# ZZGET -- Get number from command line
+
+procedure zzgetr (line, ip, rval)
+
+char line[ARB] # command line
+int ip # input character pointer
+real rval # number
+
+char number[SZ_LINE]
+int op
+
+int ctor()
+int strext()
+
+begin
+ if (strext (line, ip, " ", YES, number, SZ_LINE) == 0)
+ call error (0, "Missing numeric parameter\n")
+
+ op = 1
+ if (ctor (number, op, rval) == 0)
+ call error (0, "zzget: Impossible number conversion\n")
+end
+
+# ZZGET -- Get number from command line
+
+procedure zzgetd (line, ip, dval)
+
+char line[ARB] # command line
+int ip # input character pointer
+double dval # number
+
+char number[SZ_LINE]
+int op
+
+int ctod()
+int strext()
+
+begin
+ if (strext (line, ip, " ", YES, number, SZ_LINE) == 0)
+ call error (0, "Missing numeric parameter\n")
+
+ op = 1
+ if (ctod (number, op, dval) == 0)
+ call error (0, "zzget: Impossible number conversion\n")
+end
+
+# ZZGET -- Get number from command line
+
+procedure zzgetx (line, ip, xval)
+
+char line[ARB] # command line
+int ip # input character pointer
+complex xval # number
+
+char number[SZ_LINE]
+int op
+
+int ctox()
+int strext()
+
+begin
+ if (strext (line, ip, " ", YES, number, SZ_LINE) == 0)
+ call error (0, "Missing numeric parameter\n")
+
+ op = 1
+ if (ctox (number, op, xval) == 0)
+ call error (0, "zzget: Impossible number conversion\n")
+end
+
+# ZZGET -- Get number from command line
+
+procedure zzgetp (line, ip, pval)
+
+char line[ARB] # command line
+int ip # input character pointer
+pointer pval # number
+
+char number[SZ_LINE]
+int op
+
+int ctoi()
+int strext()
+
+begin
+ if (strext (line, ip, " ", YES, number, SZ_LINE) == 0)
+ call error (0, "Missing numeric parameter\n")
+
+ op = 1
+ if (ctoi (number, op, pval) == 0)
+ call error (0, "zzget: Impossible number conversion\n")
+end
+
+
+
+# ZZGSTR -- Get string from command line
+
+procedure zzgstr (line, ip, strval, maxch)
+
+char line[ARB] # command line
+int ip # input character pointer
+char strval[maxch] # output string
+int maxch # max number of characters
+
+int strext()
+
+begin
+ if (strext (line, ip, " ", YES, strval, maxch) == 0)
+ call error (0, "Missing string parameter")
+end
diff --git a/noao/digiphot/photcal/mkapfile.cl b/noao/digiphot/photcal/mkapfile.cl
new file mode 100644
index 00000000..086bb735
--- /dev/null
+++ b/noao/digiphot/photcal/mkapfile.cl
@@ -0,0 +1,187 @@
+# MKAPFILE -- Create an aperture corrections file suitable for input to the
+# PHOTCAL preprocessor tasks MKNOBSFILE, MKOBSFILE, and OBSFILE from a list of
+# APPHOT/DAOPHOT text or ST table photometry files.
+
+procedure mkapfile (photfiles, naperts, apercors)
+
+file photfiles {prompt="The input list of APPHOT/DAOPHOT databases"}
+int naperts {prompt="The number of apertures to extract"}
+file apercors {prompt="The output aperture corrections file"}
+int smallap {1, prompt="The first aperture for the correction"}
+int largeap {0, prompt="The last aperture for the correction"}
+file magfile {"", prompt="The optional output best magnitudes file"}
+file logfile {"", prompt="The optional output log file"}
+file plotfile {"", prompt="The optional output plot file"}
+file obsparams {"", prompt="The observing parameters file"}
+string obscolumns {"2 3 4 5", prompt="The observing parameters file format"}
+bool append {no, prompt="Open log and plot files in append mode"}
+real maglim {.10, prompt="The maximum permitted magnitude error"}
+int nparams {3, prompt="Number of cog model parameters to fit"}
+real swings {1.2, prompt="The power law slope of the stellar wings"}
+real pwings {0.1,
+prompt="The fraction of the total power in the stellar wings"}
+real pgauss {0.5,
+prompt="The fraction of the core power in the gaussian core"}
+real rgescale {0.9, prompt="The exponential / gaussian radial scales"}
+real xwings {0.0, prompt="The extinction coefficient"}
+bool interactive {yes, prompt="Do the fit interactively ?"}
+bool verify {no, prompt="Verify interactive user input ?"}
+gcur gcommands {"", prompt="The graphics cursor"}
+string graphics {"stdgraph", prompt="The graphics device"}
+
+begin
+ # Declare local variables.
+
+ bool tappend
+ int tnaperts, tsmallap, tlargeap, td2, tr2, tpwidth, tpagwidth
+ string tfiles, tapercors, tmagfile, tlogfile, tplotfile
+ string tobsparams, tobscolumns, tmplist, tdatafile
+ string tainfields, tsinfields, trstr, tmstr, testr, fname
+
+ # Get the parameters and test for the existence of various files.
+
+ tfiles = photfiles
+
+ tnaperts = naperts
+ if (tnaperts < 2) {
+ error (0, "Naperts must be > 1")
+ }
+
+ tapercors = apercors
+ if (access (tapercors)) {
+ error (0,
+ "The output aperture corrections file " // tapercors //
+ " already exists")
+ }
+
+ tsmallap = smallap
+ tlargeap = largeap
+ tsmallap = max (1, min (tsmallap, tnaperts))
+ if (tlargeap == 0) {
+ tlargeap = tnaperts
+ } else {
+ tlargeap = max (1, min (tlargeap, tnaperts))
+ }
+ if (tsmallap > tlargeap) {
+ error (0, "Lastap must be > tsmallap")
+ }
+
+ tmagfile = magfile
+ if (tmagfile != "" && access (tmagfile)) {
+ error (0,
+ "The output magfile file " // tmagfile // " already exists")
+ }
+
+ tappend = append
+ tlogfile = logfile
+ if (tlogfile != "" && ! tappend) {
+ if (access (tlogfile))
+ error (0,
+ "The output logfile " // tlogfile // " already exists")
+ }
+ tplotfile = plotfile
+ if (tplotfile != "" && ! tappend) {
+ if (access (tplotfile))
+ error (0,
+ "The output plotfile " // tplotfile // " already exists")
+ }
+
+ tobsparams = obsparams
+ if (tobsparams == "") {
+ tobscolumns = ""
+ } else {
+ tobscolumns = obscolumns
+ if (! access (tobsparams))
+ error (0,
+ "The obsparmas file " // tobsparams // " does not exist")
+ }
+
+
+ # Change columns named "RAPERT", "MAG" and "MERR" to "RAPERT[1]",
+ # "MAG[1]" and "MERR[1]" in any ST tables files. Non-ST format files
+ # are skipped.
+
+ tbcrename (tfiles, "RAPERT,MAG,MERR", "RAPERT\[1],MAG\[1],MERR\[1]")
+
+ # Add the image, scale, ifilter, itime and xairmass columns to any
+ # files in ST tables format. Non-ST format files are skipped.
+
+ tbkeycol (tfiles, "IMAGE,XAIRMASS")
+
+ # Construct the string describing the fields to be extracted
+ # making sure to specify the correct aperture number. Extract
+ # the data and store the results in the temporary file tdatafile.
+
+ tainfields = "IM,XC,YC,IF,IT,XA,OT,RAPERT[1-" // tnaperts // "]" //
+ ",MAG[1-" // tnaperts // "]" // ",MERR[1-" // tnaperts // "]"
+
+ tsinfields = "IM*,XC*,YC*,IF*,IT*,XA*,OT*"
+ td2 = tnaperts / 10
+ tr2 = mod (tnaperts, 10)
+ for (i = 0; i <= td2; i = i + 1) {
+ if (td2 == 0) {
+ trstr = ",RA*\[[1-" // tr2 // "]]"
+ tmstr = ",MAG\[[1-" // tr2 // "]]"
+ testr = ",MERR\[[1-" // tr2 // "]]"
+ } else if (i == 0) {
+ trstr = ",RA*\[[1-9]]"
+ tmstr = ",MAG\[[1-9]]"
+ testr = ",MERR\[[1-9]]"
+ } else if (i == td2) {
+ trstr = trstr // ",RA*\[" // td2 // "[0-" // tr2 // "]]"
+ tmstr = tmstr // ",MAG\[" // td2 // "[0-" // tr2 // "]]"
+ testr = testr // ",MERR\[" // td2 // "[0-" // tr2 // "]]"
+ } else if (i == 1) {
+ trstr = trstr // ",RA*\[[1-" // td2-1 // "][1-9]]"
+ tmstr = tmstr // ",MAG\[[1-" // td2-1 // "][1-9]]"
+ testr = testr // ",MERR\[[1-" // td2-1 // "][1-9]]"
+ }
+ }
+ tsinfields = tsinfields // trstr // "," // tmstr // "," // testr
+
+ # Create input file list.
+
+ tmplist = mktemp ("tmp$")
+ files (tfiles, sort=no, > tmplist)
+
+ # Create temporary file names to store the intermediate image list.
+
+ tdatafile = mktemp ("tmp$")
+ list = tmplist
+ while (fscan (list, fname) != EOF) {
+ istable (fname)
+ if (istable.table) {
+ tpagwidth = tbdump.pagwidth
+ #tpwidth = tdump.pwidth.p_max
+ tdump.pwidth.p_max = 5000
+ tbdump (fname, tsinfields, "yes", cdfile="", pfile="",
+ datafile="STDOUT", rows="-", pagwidth=5000,
+ >> tdatafile)
+ #tdump.pwidth.p_max = tpwidth
+ tbdump.pagwidth = tpagwidth
+ } else if (istable.text) {
+ txdump (fname, tainfields, "yes", headers=no, parameters=yes,
+ >> tdatafile)
+ } else {
+ print ("ERROR: Cannot run MKAPFILE on file: " // fname)
+ }
+ }
+
+ # Run APFILE.
+
+ tainfields = "1,2,3,4,5,6,7,8," // 8+tnaperts // "," // 8+2*tnaperts
+ apfile (tdatafile, tainfields, tnaperts, tapercors,
+ smallap=tsmallap, largeap=tlargeap, magfile=tmagfile,
+ logfile=tlogfile, plotfile=tplotfile, append=tappend,
+ obsparams=tobsparams,obscolumns=tobscolumns,maglim=maglim,
+ nparams=nparams,swings=swings,pwings=pwings, pgauss=pgauss,
+ rgescale=rgescale, xwings=xwings, interactive=interactive,
+ verify=verify, gcommands=gcommands, graphics=graphics)
+
+ # Delete the temporary files.
+
+ delete (tdatafile, go_ahead+, verify-, default_action+,
+ allversions+, subfiles+, > "dev$null")
+ delete (tmplist, go_ahead+, verify-, default_action+,
+ allversions+, subfiles+, > "dev$null")
+end
diff --git a/noao/digiphot/photcal/mkcatalog.cl b/noao/digiphot/photcal/mkcatalog.cl
new file mode 100644
index 00000000..8c9b0e20
--- /dev/null
+++ b/noao/digiphot/photcal/mkcatalog.cl
@@ -0,0 +1,25 @@
+# MKCATALOG -- Create / edit a catalog of photometric standards.
+
+procedure mkcatalog (catalog)
+
+file catalog {prompt="The name of the output catalog"}
+bool review {no, prompt="Verify each existing catalog record"}
+bool verify {no, prompt="Verify each new catalog record"}
+bool edit {yes,prompt="Check the output catalog with the editor"}
+
+
+begin
+ # Declare local variables
+ file cat
+
+ # Get the positional parameters
+ cat = catalog
+
+ # Make a new catalog or edit an existing catalog.
+ catalog (cat, review=review, verify=verify)
+
+ # Edit the catalog with the editor.
+ print ("")
+ if (access (cat) && edit)
+ edit (cat)
+end
diff --git a/noao/digiphot/photcal/mkcatalog/README b/noao/digiphot/photcal/mkcatalog/README
new file mode 100644
index 00000000..0c58b3d3
--- /dev/null
+++ b/noao/digiphot/photcal/mkcatalog/README
@@ -0,0 +1,2 @@
+This subdirectory contains the code for the CATALOG task which is called by
+the MKCATALOG script.
diff --git a/noao/digiphot/photcal/mkcatalog/mkpkg b/noao/digiphot/photcal/mkcatalog/mkpkg
new file mode 100644
index 00000000..93af09b0
--- /dev/null
+++ b/noao/digiphot/photcal/mkcatalog/mkpkg
@@ -0,0 +1,11 @@
+# The MKPKG file for the mkcatalog subdirectory.
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ t_catalog.x "../lib/io.h" <fset.h> <ctotok.h> <ctype.h>
+ phrecord.x "../lib/io.h"
+ ;
diff --git a/noao/digiphot/photcal/mkcatalog/phrecord.x b/noao/digiphot/photcal/mkcatalog/phrecord.x
new file mode 100644
index 00000000..0f8ef400
--- /dev/null
+++ b/noao/digiphot/photcal/mkcatalog/phrecord.x
@@ -0,0 +1,243 @@
+include "../lib/io.h"
+
+# PH_GHDR_RECORD -- Reconstruct a formated header record from an input catalog
+# produced by MKCATALOG by joining lines which compose a single record.
+# All header records begin with a '#' followed by a blank character. If
+# the header record is empty it is skipped. Header reading is terminated
+# when an empty line is encountered. Lines which begin with a '*' in column
+# one followed by a blank are part of the previous record.
+
+int procedure ph_ghdr_record (fd, record, sz_hdr_record)
+
+int fd # the input file descriptor
+char record[ARB] # the output record
+int sz_hdr_record # size of the record
+
+int stat, nchars, ip, op
+pointer sp, line
+int getline(), strncmp()
+
+begin
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+
+ op = 1
+ repeat {
+
+ # Read lines from the catalog. Header reading is terminated
+ # by an empty line.
+
+ stat = getline (fd, Memc[line])
+ if (stat == EOF) {
+ call sfree (sp)
+ return (EOF)
+ }
+ if (Memc[line] == EOS || Memc[line] == '\n') {
+ call sfree (sp)
+ return (EOF)
+ }
+
+ # Empty records are skipped.
+ if ((strncmp (MKCAT_COMMENTSTR, Memc[line], MKCAT_SZSTR) == 0) &&
+ (Memc[line+MKCAT_SZSTR] == '\n'))
+ next
+
+ # Strip off the newline from the record.
+ if (Memc[line+stat-1] == '\n')
+ nchars = stat - 1
+ else
+ nchars = stat
+
+ # Reconstruct the output record. Terminate the reconstruction
+ # when the number of characters copied is the same as the
+ # size of the record plus the comments marker string.
+
+ if (strncmp (MKCAT_CONTSTR, Memc[line], MKCAT_SZSTR) == 0)
+ ip = 1 + MKCAT_SZSTR
+ else
+ ip = 1
+ call strcpy (Memc[line+ip-1], record[op], nchars - ip + 1)
+ op = op + nchars - ip + 1
+
+ } until (op > (sz_hdr_record + MKCAT_SZSTR))
+
+ call sfree (sp)
+
+ return (op - 1)
+end
+
+
+# PH_GDRECORD_INIT -- Initialize data record reading.
+
+procedure ph_gdrecord_init ()
+
+int pending # pending line in buffer ?
+
+common /phgetcom/ pending
+
+begin
+ pending = NO
+end
+
+
+# PH_GDRECORD -- Get an input data record from a catalog created with
+# MKCATALOG. The returned record may be composed by one or more physical
+# lines in the catalog file. Lines which begin with a '*' in column 1
+# followed by a blank are part of the previous record. Blank records and
+# comment records are passed to the output unless they occur in the middle
+# of a long record.
+
+int procedure ph_gdrecord (fd, line, maxch)
+
+int fd # file descriptor
+char line[maxch] # line from file
+int maxch # line size
+
+bool first # first line ?
+int pending # pending line in buffer ?
+char buffer[SZ_LINE] # line buffer
+
+common /phgetcom/ pending
+
+int fscan(), strmatch()
+
+begin
+ # Initialize flag to differentiate the first input line
+ # within the loop.
+ first = true
+
+ # Read lines until the end of the file is reached. Lines starting
+ # with a continuation character are concatenated.
+ repeat {
+
+ # Get next line. If there is no pending line already in
+ # the buffer, read a new line from the file. Otherwise,
+ # use the pending line and clear the pending flag.
+
+ if (pending == NO) {
+ if (fscan (fd) != EOF)
+ call gargstr (buffer, SZ_LINE)
+ else if (first)
+ return (EOF)
+ else
+ return (OK)
+ } else
+ pending = NO
+
+ # If the input line contains a continuation character, then
+ # concatenate it to the accumulated line. Otherwise, leave
+ # it in the buffer, and set the pending flag. For the first
+ # input line no continuation characters are allowed.
+
+ if (first) {
+ if (strmatch (buffer, CONTINUATION) != 0)
+ call error (0,
+ "Continuation character found in first line of catalog record")
+ else {
+ call strcpy (buffer, line, maxch)
+ first = false
+ next
+ }
+ } else {
+ if (strmatch (buffer, CONTINUATION) != 0) {
+ if (buffer[1] != EOS && buffer[1] != 'n' && buffer[1] !=
+ '#')
+ call strcat (buffer[3], line, maxch)
+ next
+ } else {
+ pending = YES
+ return (OK)
+ }
+ }
+ }
+end
+
+
+# PH_PDRECORD -- Write the formatted record to the output catalog, breaking
+# the record into chunks which hold an integral number of columns and that
+# are less that or equal to maxch_perline characters long.
+
+procedure ph_pdrecord (fd, record, sz_record, wcols, ncols, rectype,
+ maxch_perline)
+
+int fd # the output file descriptor
+char record[ARB] # the input record
+int sz_record # the size of the input record
+int wcols[ARB] # widths of the input record columns
+int ncols # number of columns
+char rectype[ARB] # string identifying the output record type
+int maxch_perline # maximum number of characters output per line
+
+int i, ip, nlines, length
+int strlen()
+
+begin
+ # Initialize.
+ nlines = 1
+ ip = 1
+
+ # Write out the string defining the record type. The record
+ # types are comment, data and blank.
+ length = strlen (rectype)
+ call fprintf (fd, "%*.*s")
+ call pargi (-MKCAT_SZSTR)
+ call pargi (MKCAT_SZSTR)
+ call pargstr (rectype)
+
+ # Construct the record piece by piece.
+ for (i = 1; i <= ncols; i = i + 1) {
+
+ # Compute the contribution of each field to the length of the
+ # output line which must less than or equal to maxch_perline
+ # characters. Fields may not be broken apart by a continutation
+ # marker.
+
+ length = length + wcols[i]
+ if (length < maxch_perline)
+ next
+ if (length > maxch_perline) {
+ length = length - wcols[i]
+ i = i - 1
+ }
+
+ # Output portions of the record to the catalog file.
+ # If nlines is greater than 1 prepend the continuations
+ # string to the record.
+
+ if (nlines == 1) {
+ call fprintf (fd, "%*.*s\n")
+ call pargi (-(length - MKCAT_SZSTR))
+ call pargi (length - MKCAT_SZSTR)
+ call pargstr (record[ip])
+ ip = ip + length - MKCAT_SZSTR
+ } else {
+ call fprintf (fd, "%*.*s")
+ call pargi (-MKCAT_SZSTR)
+ call pargi (MKCAT_SZSTR)
+ call pargstr ("* ")
+ call fprintf (fd, "%*.*s\n")
+ call pargi (-(length - MKCAT_SZSTR))
+ call pargi (length - MKCAT_SZSTR)
+ call pargstr (record[ip])
+ ip = ip + length - MKCAT_SZSTR
+ }
+
+ nlines = nlines + 1
+ length = MKCAT_SZSTR
+ }
+
+ # Output any remaining piece of the record.
+ if (ip <= sz_record) {
+ if (nlines == 1) {
+ call fprintf (fd, "%s\n")
+ call pargstr (record[ip])
+ } else {
+ call fprintf (fd, "%*.*s%s\n")
+ call pargi (-MKCAT_SZSTR)
+ call pargi (MKCAT_SZSTR)
+ call pargstr (MKCAT_CONTSTR)
+ call pargstr (record[ip])
+ }
+ }
+
+end
diff --git a/noao/digiphot/photcal/mkcatalog/t_catalog.x b/noao/digiphot/photcal/mkcatalog/t_catalog.x
new file mode 100644
index 00000000..6b2c4008
--- /dev/null
+++ b/noao/digiphot/photcal/mkcatalog/t_catalog.x
@@ -0,0 +1,902 @@
+include <fset.h>
+include <ctotok.h>
+include <ctype.h>
+include "../lib/io.h"
+
+# T_CATALOG -- The CATALOG task is a simple tool designed to aid the user
+# in creating and formating catalogs of standard stars. CATALOG queries
+# the user for the name of the output catalog, a catalog title,
+# and then prompts the user for input. If the catalog already exists
+# CATALOG enters append mode and permits the user to add new records to
+# the end of the catalog. Options exist to review old items in the catalog
+# and to verify new ones.
+
+procedure t_catalog ()
+
+pointer output # pointer to the name of the output catalog
+pointer title # pointer to the title of the output catalog
+pointer format # pointer to the name of the output format file
+int review # review the data in a pre-existing catalog ?
+int verify # verify all new user input ?
+
+int i, sz_record, ncols, newfile, fd, fdfmt, tfd, imin, imax
+pointer sp, otitle, toutput, names, widths
+bool clgetb()
+int access(), open(), btoi(), ph_open(), ph_rhdr(), strmatch(), ph_setcols()
+
+begin
+ # Set up the standard output to flush on a newline.
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (toutput, SZ_FNAME, TY_CHAR)
+ call salloc (title, SZ_FNAME, TY_CHAR)
+ call salloc (otitle, SZ_FNAME, TY_CHAR)
+ call salloc (format, SZ_FNAME, TY_CHAR)
+
+ # Get the parameters.
+ call clgstr ("catalog", Memc[output], SZ_FNAME)
+ call sprintf (Memc[format], SZ_FNAME, "f%s.dat")
+ call pargstr (Memc[output])
+ verify = btoi (clgetb ("verify"))
+
+ # Determine whether the catalog is a new catalog or an existing
+ # catalog. If the catalog is a new catalog get the number of columns,
+ # the column names and column widths from the user. If the catalog
+ # is an old catalog open the catalog, read the number of columns, the
+ # column names and the column widths from the catalog header and
+ # match the catalog title with the catalog file name.
+
+ names = NULL
+ widths = NULL
+ call strcpy (Memc[output], Memc[title], SZ_FNAME)
+
+ if (access (Memc[output], 0, 0) == NO) {
+
+ fd = open (Memc[output], NEW_FILE, TEXT_FILE)
+ if (access (Memc[format], 0, 0) == YES)
+ call delete (Memc[format])
+ fdfmt = open (Memc[format], NEW_FILE, TEXT_FILE)
+ ncols = ph_setcols (names, widths, MKCAT_MAXCOLWIDTH, MKCAT_NCOLS,
+ verify)
+
+ if (ncols == 0) {
+ call eprintf (
+ "\n<Error> Catalog %s in file %s has no id column\n\n")
+ call pargstr (Memc[title])
+ call pargstr (Memc[output])
+
+ } else if (ncols == 1) {
+ call eprintf (
+ "\n<Error> Catalog %s in file %s has no data columns\n\n")
+ call pargstr (Memc[title])
+ call pargstr (Memc[output])
+ ncols = 0
+
+ } else {
+ call printf ("\nCatalog %s in file %s has %d columns\n")
+ call pargstr (Memc[title])
+ call pargstr (Memc[output])
+ call pargi (ncols)
+ do i = 1, ncols {
+ call printf ("\tColumn %d: %*.*s\n")
+ call pargi (i)
+ call pargi (-Memi[widths+i-1])
+ call pargi (Memi[widths+i-1])
+ call pargstr (Memc[names+(i-1)* (MKCAT_MAXCOLWIDTH+1)])
+ }
+ call printf ("\n")
+ }
+
+ newfile = YES
+ review = NO
+
+ } else {
+
+ fd = open (Memc[output], READ_WRITE, TEXT_FILE)
+ ncols = ph_open (fd, sz_record, Memc[otitle], SZ_FNAME)
+
+ # The catalog was not created with MKCATALOG.
+ if (ncols <= 1) {
+ call eprintf (
+ "\n<Warning> File %s was not created with MKCATALOG\n")
+ call pargstr (Memc[output])
+ ncols = 0
+
+ # The user title does not match the catalog title.
+ } else if (strmatch (Memc[otitle], Memc[title]) <= 0) {
+ call eprintf ("\n<Error> The input title %s does not match ")
+ call pargstr (Memc[title])
+ call eprintf ("the catalog title %s.\n")
+ call pargstr (Memc[otitle])
+ ncols = 0
+
+ # Read in the column names and widths.
+ } else {
+ call malloc (names, MKCAT_MAXCOLWIDTH * ncols, TY_CHAR)
+ call malloc (widths, ncols, TY_INT)
+ if (ph_rhdr (fd, Memc[names], MKCAT_MAXCOLWIDTH, Memi[widths],
+ ncols, sz_record) < ncols) {
+ call eprintf (
+ "\n<Error> Error reading catalog %s in file %s\n")
+ call pargstr (Memc[title])
+ call pargstr (Memc[output])
+ ncols = 0
+ } else {
+ call printf ("\nCatalog %s in file %s has %d columns\n")
+ call pargstr (Memc[title])
+ call pargstr (Memc[output])
+ call pargi (ncols)
+ do i = 1, ncols {
+ call printf ("\tColumn %d: %s\n")
+ call pargi (i)
+ call pargstr (Memc[names+(i-1)*(MKCAT_MAXCOLWIDTH+
+ 1)])
+ }
+ call printf ("\n")
+ }
+ }
+
+ newfile = NO
+ review = btoi (clgetb ("review"))
+ }
+
+ # Exit CATALOG if the output file exists but is not an IRAF
+ # photometry catalog; if it has fewer than two columns, since
+ # the first column must contain an identifier; or in the case of
+ # a prexisting catalog if the user supplied title does not match
+ # the catalog title.
+
+ if (ncols <= 1) {
+ call sfree (sp)
+ return
+ }
+
+ # Create/edit the catalog. If the output catalog is a new file
+ # write out the catalog header and query the user for the catalog
+ # data. If the output catalog is a prexisting catalog read the
+ # catalog header. If review is no then move to the end of the
+ # catalog and query the user for new records. If review is yes
+ # then open a temporary catalog, verify and copy each record to the
+ # temporary file, query the user for new data, delete the original
+ # catalog and rename the temporary catalog to the same name
+ # as the original one.
+
+ # Create a new catalog and accompanying format file.
+ if (newfile == YES) {
+
+ # Read in the catalog data and write it to a file.
+ call ph_whdr (fd, Memc[title], Memc[names], MKCAT_MAXCOLWIDTH,
+ Memi[widths], ncols)
+ call ph_rdata (fd, Memc[names], MKCAT_MAXCOLWIDTH, Memi[widths],
+ ncols, verify)
+ call close (fd)
+
+ # Write out the format file.
+ call alimi (Memi[widths], ncols, imin, imax)
+ call fprintf (fdfmt,
+ "# Declare the catalog variables\n\n")
+ call fprintf (fdfmt, "catalog\n\n")
+ do i = 2, ncols {
+ call fprintf (fdfmt, "%*.*s %d\n")
+ call pargi (-imax)
+ call pargi (imax)
+ call pargstr (Memc[names+(i-1)*(MKCAT_MAXCOLWIDTH+1)])
+ call pargi (i)
+ }
+ call fprintf (fdfmt, "\n")
+ call close (fdfmt)
+
+ # Review the existing records and enter new ones.
+ } else if (review == YES) {
+
+ call mktemp ("tmp", Memc[toutput], SZ_FNAME)
+ tfd = open (Memc[toutput], NEW_FILE, TEXT_FILE)
+ call ph_whdr (tfd, Memc[title], Memc[names], MKCAT_MAXCOLWIDTH,
+ Memi[widths], ncols)
+ call ph_review (fd, tfd, Memc[names], MKCAT_MAXCOLWIDTH,
+ Memi[widths], ncols)
+ call ph_rdata (tfd, Memc[names], MKCAT_MAXCOLWIDTH, Memi[widths],
+ ncols, verify)
+ call close (fd)
+ call close (tfd)
+ call delete (Memc[output])
+ call rename (Memc[toutput], Memc[output])
+
+ # Add new records to the end of an an existing catalog.
+ } else {
+
+ call seek (fd, EOF)
+ call ph_rdata (fd, Memc[names], MKCAT_MAXCOLWIDTH, Memi[widths],
+ ncols, verify)
+ call close (fd)
+
+ }
+
+ # Release memory.
+ if (names != NULL)
+ call mfree (names, TY_CHAR)
+ if (widths != NULL)
+ call mfree (widths, TY_INT)
+ call sfree (sp)
+end
+
+
+# PH_SETCOLS -- Decode the list of column names and widths into an
+# array of column names and an array of column lengths.
+
+int procedure ph_setcols (names, widths, max_lencolid, def_ncols, verify)
+
+pointer names # pointer to array of column names
+pointer widths # pointer to array of column widths
+int max_lencolid # maximum length of column name not including EOS
+int def_ncols # default initial number of columns
+int verify # verify the input
+
+int i, bufsize, errcol, ncols, ival
+pointer sp, str, pnptr, nptr
+bool ph_isident()
+int scan(), nscan(), strmatch()
+
+begin
+ # Allocate temporary working space.
+ call smark (sp)
+ call salloc (str, max_lencolid, TY_CHAR)
+
+ # Allocate space for the column name and width buffers.
+ bufsize = def_ncols
+ call malloc (names, (max_lencolid + 1) * bufsize, TY_CHAR)
+ call malloc (widths, bufsize, TY_INT)
+
+ call printf ("\n")
+
+ ncols = 0
+ errcol = NO
+ pnptr = names
+ nptr = names
+ repeat {
+
+ # Print the column name prompt.
+ if (ncols == 0) {
+ call printf ("Enter the id column name ")
+ call printf ("(name, <CR>=ID, <EOF>=quit entry): ")
+ } else if (errcol == NO) {
+ call printf ("Enter a name for column %d ")
+ call pargi (ncols+1)
+ call printf ("(name, <CR>=COL%d, <EOF>=quit entry): ")
+ call pargi (ncols+1)
+ } else if (errcol == YES) {
+ call printf ("Enter a name for error column %d ")
+ call pargi (ncols+1)
+ call printf ("(name, <CR>=error(%s), <->=skip): ")
+ call pargstr (Memc[pnptr])
+ }
+ call flush (STDOUT)
+
+ # Terminate column definition on EOF.
+ if (scan () == EOF) {
+ call printf ("\n")
+ break
+ }
+
+ # Read the column name.
+ call gargwrd (Memc[nptr], max_lencolid)
+ if (Memc[nptr] == EOS) {
+ if (ncols == 0) {
+ call strcpy ("ID", Memc[nptr], max_lencolid)
+ } else if (errcol == NO) {
+ call sprintf (Memc[nptr], max_lencolid, "COL%d")
+ call pargi (ncols+1)
+ } else if (errcol == YES) {
+ call sprintf (Memc[nptr], max_lencolid, "error(%s)")
+ call pargstr (Memc[pnptr])
+ }
+ } else if (! ph_isident (Memc[nptr]) &&
+ strmatch (Memc[nptr], "error(") == 0) {
+ if (Memc[nptr] == '-')
+ errcol = NO
+ else {
+ call printf ("%s is not a legal column name - skipping\n")
+ call pargstr (Memc[nptr])
+ }
+ next
+ }
+
+ # Print the column width prompt.
+ if (ncols == 0) {
+ call printf ("\tEnter width of id column (width, <CR>=%d): ")
+ call pargi (MKCAT_IDCOLWIDTH)
+ } else {
+ call printf ("\tEnter width of column %d (width, <CR>=%d): ")
+ call pargi (ncols+1)
+ call pargi (MKCAT_COLWIDTH)
+ }
+ call flush (STDOUT)
+
+ # Read the column width.
+ if (ncols == 0)
+ Memi[widths+ncols] = MKCAT_IDCOLWIDTH
+ else
+ Memi[widths+ncols] = MKCAT_COLWIDTH
+ if (scan () != EOF) {
+ call gargi (ival)
+ if (nscan() == 1)
+ Memi[widths+ncols] = ival
+ }
+
+ # Increment the buffer pointers.
+ ncols = ncols + 1
+ pnptr = nptr
+ nptr = names + ncols * (max_lencolid + 1)
+
+ # Is the next column an error column ?
+ if (ncols <= 1)
+ errcol = NO
+ else if (errcol == YES)
+ errcol = NO
+ else
+ errcol = YES
+
+ # Expand the buffer space if necessary.
+ if (ncols < bufsize)
+ next
+ bufsize = bufsize + def_ncols
+ call realloc (names, (max_lencolid + 1) * bufsize, TY_CHAR)
+ call realloc (widths, bufsize, TY_INT)
+ }
+
+ call printf ("\n")
+
+ # Do not verify if the verify switch is off or if there are fewer
+ # than 2 columns in the catalog.
+
+ if ((verify == NO) || (ncols < 2)) {
+ call sfree (sp)
+ return (ncols)
+ }
+
+ # Verify the name and width for each column.
+ do i = 1, ncols {
+
+ nptr = names + (i - 1) * (max_lencolid + 1)
+
+ # Issue the verify prompt for the column name.
+ call printf ( "Verify name of column %d (%s) (name, <CR>=ok): ")
+ call pargi (i)
+ call pargstr (Memc[nptr])
+ call flush (STDOUT)
+
+ # Confirm old or read new column name value.
+ call strcpy (Memc[nptr], Memc[str], max_lencolid)
+ if (scan() == EOF)
+ call printf ("\n")
+ else
+ call gargwrd (Memc[nptr], max_lencolid)
+ if (Memc[nptr] == EOS)
+ call strcpy (Memc[str], Memc[nptr], max_lencolid)
+ else if (! ph_isident (Memc[nptr]) && strmatch (Memc[nptr],
+ "error(") == 0)
+ call strcpy (Memc[str], Memc[nptr], max_lencolid)
+ call printf ("\tOld name: %s New name: %s\n")
+ call pargstr (Memc[str])
+ call pargstr (Memc[nptr])
+
+ # Issue the verify prompt for the column width.
+ call printf (
+ "Verify the width of column %d (%d) (width, <CR>=ok): ")
+ call pargi (i)
+ call pargi (Memi[widths+i-1])
+ call flush (STDOUT)
+
+ # Confirm the old or read the new column width value.
+ ival = Memi[widths+i-1]
+ if (scan() != EOF) {
+ call gargi (Memi[widths+i-1])
+ if (nscan() != 1)
+ Memi[widths+i-1] = ival
+ }
+
+ call printf ("\tOld width: %d New width: %d\n")
+ call pargi (ival)
+ call pargi (Memi[widths+i-1])
+
+ }
+
+ call printf ("\n")
+
+ call sfree (sp)
+ return (ncols)
+end
+
+
+# PH_OPEN -- Open an existing catalog, check that it is a valid
+# photometry catalog, and return the title of the catalog and the number
+# of columns in the catalog.
+
+int procedure ph_open (fd, sz_record, otitle, max_lentitle)
+
+int fd # the catalog file descriptor
+int sz_record # the length of the catalog record
+char otitle[ARB] # the original catalog title
+int max_lentitle # the maximum length of the title
+
+int ncols
+pointer sp, str
+int fscan(), nscan(), strmatch()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ otitle[1] = EOS
+ ncols = 0
+ sz_record = 0
+
+ # Decode the title and the number of columns.
+ while (fscan (fd) != EOF) {
+
+ # Check for the leading # sign. Quit if a blank line is
+ # encountered or the line does not begin with # followed
+ # by a blank.
+ call gargwrd (Memc[str], SZ_LINE)
+ if (Memc[str] == EOS)
+ break
+ if (Memc[str] != MKCAT_COMMENTCHAR)
+ break
+
+ # Get the keyword.
+ call gargwrd (Memc[str], SZ_LINE)
+ if (Memc[str] == EOS)
+ next
+
+ # Decode the title and the number of columns.
+ if (strmatch (Memc[str], MKCAT_KYCATALOG) > 0) {
+ call gargstr (otitle, max_lentitle)
+ } else if (strmatch (Memc[str], MKCAT_KYNCOLS) > 0) {
+ call gargi (ncols)
+ if (nscan() != 3)
+ ncols = 0
+ } else if (strmatch (Memc[str], MKCAT_KYHDRLENGTH) > 0) {
+ call gargi (sz_record)
+ if (nscan() != 3)
+ sz_record = 0
+ break
+ }
+ }
+
+ call sfree (sp)
+ return (ncols)
+end
+
+
+# PH_RHDR -- Read the names and widths of the catalog columns from
+# the catalog header.
+
+int procedure ph_rhdr (fd, names, max_lencolid, widths, ncols, sz_record)
+
+int fd # file descriptor of the catalog
+char names[max_lencolid,ARB] # the list of column names
+int max_lencolid # the maximum length of the column names
+int widths[ARB] # the list of column widths
+int ncols # the number of catalog columns
+int sz_record # the size of the catalog record
+
+int nc, ip
+pointer sp, record, wrd
+int ph_ghdr_record(), ctoi()
+
+begin
+ call smark (sp)
+ call salloc (record, MAX_CONT * SZ_LINE, TY_CHAR)
+ call salloc (wrd, max_lencolid, TY_CHAR)
+
+ # Initialize the column names and widths.
+ do nc = 1, ncols {
+ names[1,nc] = EOS
+ widths[nc] = 0
+ }
+
+ # Decode the column names and widths.
+ while (ph_ghdr_record (fd, Memc[record], sz_record) != EOF) {
+
+ # Scan the string.
+ call sscan (Memc[record])
+
+ # Check for the leading pound sign.
+ call gargwrd (Memc[wrd], max_lencolid)
+ if (Memc[wrd] != MKCAT_COMMENTCHAR)
+ break
+
+ # Skip lines that contain only a # sign.
+ call gargwrd (Memc[wrd], max_lencolid)
+ if (Memc[wrd] == EOS)
+ next
+
+ # Decode the columns widths and the column names.
+ do nc = 1, ncols {
+ ip = 1
+ if (names[1,nc] == EOS)
+ call strcpy (Memc[wrd], names[1,nc], max_lencolid)
+ else if (ctoi (Memc[wrd], ip, widths[nc]) <= 0)
+ widths[nc] = 0
+ call gargwrd (Memc[wrd], max_lencolid)
+ if (Memc[wrd] == EOS)
+ break
+ }
+ }
+
+ call sfree (sp)
+
+ return (nc)
+end
+
+
+# PH_WHDR -- Write the header of the output catalog. All the header records
+# begin with a # sign. A blank line signifies the end of the header block
+# and the beginning of the data records. The header block consists of
+# two lines which define the title of the catalog and the number of columns
+# followed by the column names and widths.
+
+procedure ph_whdr (fd, title, names, max_lencolid, widths, ncols)
+
+int fd # output catalog file descriptor
+char title[ARB] # title of the catalog
+char names[max_lencolid,ARB] # array of column names
+int max_lencolid # maximum width of the column id field
+int widths[ARB] # array of column widths
+int ncols # number of columns
+
+int i, ip, sz_hdr_record
+pointer sp, twidths, record
+
+begin
+ # Allocate space for an output record.
+ call smark (sp)
+ call salloc (twidths, ncols, TY_INT)
+ call salloc (record, MAX_CONT * SZ_LINE, TY_CHAR)
+
+ # Compute the size of a record.
+ sz_hdr_record = 0
+ do i = 1, ncols {
+ if (i == ncols)
+ Memi[twidths+i-1] = widths[i]
+ else
+ Memi[twidths+i-1] = widths[i] + MKCAT_SZGAP
+ sz_hdr_record = sz_hdr_record + Memi[twidths+i-1]
+ }
+
+ # Write out the header banner.
+ call fprintf (fd, "%s%s %s\n")
+ call pargstr (MKCAT_COMMENTSTR)
+ call pargstr (MKCAT_KYCATALOG)
+ call pargstr (title)
+ call fprintf (fd, "%s%s %d\n")
+ call pargstr (MKCAT_COMMENTSTR)
+ call pargstr (MKCAT_KYNCOLS)
+ call pargi (ncols)
+ call fprintf (fd, "%s%s %d\n")
+ call pargstr (MKCAT_COMMENTSTR)
+ call pargstr (MKCAT_KYHDRLENGTH)
+ call pargi (sz_hdr_record)
+ call fprintf (fd, "%s\n")
+ call pargstr (MKCAT_COMMENTSTR)
+
+ # Construct the column labels record.
+ ip = 1
+ do i = 1, ncols {
+ call sprintf (Memc[record+ip-1], max_lencolid, "%*.*s")
+ call pargi (-Memi[twidths+i-1])
+ call pargi (widths[i])
+ call pargstr (names[1,i])
+ ip = ip + Memi[twidths+i-1]
+ }
+
+ # Write the label record to the output file.
+ call ph_pdrecord (fd, Memc[record], sz_hdr_record, Memi[twidths], ncols,
+ MKCAT_COMMENTSTR, SZ_LINE - 1)
+
+ # Construct the column widths record.
+ ip = 1
+ do i = 1, ncols {
+ call sprintf (Memc[record+ip-1], max_lencolid, "%*.*d")
+ call pargi (-Memi[twidths+i-1])
+ call pargi (widths[i])
+ call pargi (widths[i])
+ ip = ip + Memi[twidths+i-1]
+ }
+
+ # Write the column widths record to the output file.
+ call ph_pdrecord (fd, Memc[record], sz_hdr_record, Memi[twidths], ncols,
+ MKCAT_COMMENTSTR, SZ_LINE - 1)
+
+ # Append a trailing blank line to indicate the end of the header.
+ call fprintf (fd, "\n")
+
+ call sfree (sp)
+end
+
+
+# PH_RDATA -- Read in new catalog data from the standard input.
+
+procedure ph_rdata (fd, names, max_lencolid, widths, ncols, verify)
+
+int fd # pointer to the output catalog
+char names[max_lencolid,ARB] # array of column names
+int max_lencolid # maximum length of a column name
+int widths[ARB] # array of column widths
+int ncols # number of columns
+int verify # verify each new entry
+
+int ip, i, rip, stat, sz_record
+pointer sp, twidths, wrd, twrd, record, trecord
+int scan(), ctowrd()
+
+begin
+ # Allocate working memory.
+ call smark (sp)
+ call salloc (twidths, ncols, TY_INT)
+ call salloc (wrd, max_lencolid, TY_CHAR)
+ call salloc (twrd, max_lencolid, TY_CHAR)
+ call salloc (record, MAX_CONT * SZ_LINE, TY_CHAR)
+ call salloc (trecord, MAX_CONT * SZ_LINE, TY_CHAR)
+
+ # Compute the size of a record.
+ sz_record = 0
+ do i = 1, ncols {
+ if (i == ncols)
+ Memi[twidths+i-1] = widths[i]
+ else
+ Memi[twidths+i-1] = widths[i] + MKCAT_SZGAP
+ sz_record = sz_record + Memi[twidths+i-1]
+ }
+
+ # Read in records from the standard input.
+ repeat {
+
+ # Intialize the record.
+ ip = 1
+ Memc[record] = EOS
+
+ # Read in each record.
+ do i = 1, ncols {
+
+ # Issue the column values prompt.
+ if (i == 1) {
+ call printf (
+ "\nEnter %s (value, <CR>=blank line, <EOF>=quit entry): ")
+ } else {
+ call printf ("\tEnter %s (value, <CR>=INDEF): ")
+ }
+ call pargstr (names[1,i])
+ call flush (STDOUT)
+
+ # Read in the new value.
+ stat = scan()
+ if (stat == EOF) {
+ if (i == 1)
+ break
+ else
+ Memc[wrd] = EOS
+ } else
+ call gargstr (Memc[wrd], max_lencolid)
+
+ # Fill in unknown values with INDEF.
+ if (Memc[wrd] == EOS) {
+ if (i == 1)
+ break
+ else
+ call strcpy ("INDEF", Memc[wrd], max_lencolid)
+ }
+
+ # Format the output record.
+ call sprintf (Memc[record+ip-1], max_lencolid, "%*.*s")
+ call pargi (-Memi[twidths+i-1])
+ call pargi (widths[i])
+ call pargstr (Memc[wrd])
+ ip = ip + Memi[twidths+i-1]
+ }
+
+ # EOF terminates input.
+ if (stat == EOF)
+ break
+
+ # Write out blank lines.
+ if (Memc[record] == EOS) {
+ call fprintf (fd, "\n")
+ next
+ }
+
+ # Write out the record at this point if verify is off.
+ if (verify == NO) {
+ call ph_pdrecord (fd, Memc[record], sz_record, Memi[twidths],
+ ncols, MKCAT_BLANKSTR, SZ_LINE - 1)
+ next
+ }
+
+ # Verify.
+ ip = 1
+ rip = 1
+ Memc[trecord] = EOS
+
+ do i = 1, ncols {
+
+ if (ctowrd (Memc[record], rip, Memc[twrd], max_lencolid) <= 0)
+ break
+
+ # Issue a prompt to the user.
+ if (i == 1)
+ call printf ("\nVerify %s (%s) (value, <CR>=ok): ")
+ else
+ call printf ("\tVerify %s (%s) (value, <CR>=ok): ")
+ call pargstr (names[1,i])
+ call pargstr (Memc[twrd])
+ call flush (STDOUT)
+
+ # Scan the standard input for a new value.
+ if (scan() == EOF) {
+ call printf ("\n")
+ Memc[wrd] = EOS
+ } else
+ call gargstr (Memc[wrd], max_lencolid)
+ if (Memc[wrd] == EOS)
+ call strcpy (Memc[twrd], Memc[wrd], max_lencolid)
+ else {
+ call printf ("\t%s old: %s new: %s\n")
+ call pargstr (names[1,i])
+ call pargstr (Memc[twrd])
+ call pargstr (Memc[wrd])
+ }
+
+ # Format the verified output record.
+ call sprintf (Memc[trecord+ip-1], max_lencolid, "%*.*s")
+ call pargi (-Memi[twidths+i-1])
+ call pargi (widths[i])
+ call pargstr (Memc[wrd])
+ ip = ip + Memi[twidths+i-1]
+ }
+
+ # Write out the verified record.
+ call ph_pdrecord (fd, Memc[trecord], sz_record, Memi[twidths],
+ ncols, MKCAT_BLANKSTR, SZ_LINE - 1)
+ }
+
+ call printf ("\n")
+ call sfree (sp)
+end
+
+
+# PH_REVIEW -- Review the previous catalog entries and make changes.
+
+procedure ph_review (fd, tfd, names, max_lencolid, widths, ncols)
+
+int fd # pointer to the original output catalog
+int tfd # pointer to the temporary output catalog
+char names[max_lencolid,ARB] # array of column names
+int max_lencolid # maximum length of a column name
+int widths[ARB] # array of column widths
+int ncols # number of columns
+
+int stat, i, ip, lip, sz_record
+pointer sp, twidths, record, trecord, wrd, twrd
+int ph_gdrecord(), strncmp(), scan(), ctowrd()
+
+begin
+ call smark (sp)
+ call salloc (twidths, ncols, TY_INT)
+ call salloc (record, MAX_CONT * SZ_LINE, TY_CHAR)
+ call salloc (trecord, MAX_CONT * SZ_LINE, TY_CHAR)
+ call salloc (wrd, max_lencolid, TY_CHAR)
+ call salloc (twrd, max_lencolid, TY_CHAR)
+
+ # Compute the size of a record. This number is equal to the sum
+ # of all the column widths plus the the inter-column gap which
+ # is normally two characters.
+
+ sz_record = 0
+ do i = 1, ncols {
+ if (i == ncols)
+ Memi[twidths+i-1] = widths[i]
+ else
+ Memi[twidths+i-1] = widths[i] + MKCAT_SZGAP
+ sz_record = sz_record + Memi[twidths+i-1]
+ }
+
+ # Initialize the catalog data record reading routine.
+
+ call ph_gdrecord_init()
+
+ # Loop over the records in the original output catalog.
+ repeat {
+
+ # Fetch a record from the original output catalog. If the
+ # record is blank output a blank line to the temporary
+ # output catalog. If the record is a comment simply copy
+ # it to the temporary output catalog.
+
+ if (ph_gdrecord (fd, Memc[record], MAX_CONT * SZ_LINE) == EOF)
+ break
+ if (Memc[record] == EOS || Memc[record] == '\n') {
+ call fprintf (tfd, "\n")
+ next
+ } else if (strncmp (MKCAT_COMMENTSTR, Memc[record],
+ MKCAT_SZSTR) == 0) {
+ call fprintf (tfd, "%s\n")
+ call pargstr (Memc[record])
+ next
+ }
+
+ # Initialize each new record.
+ lip = 1
+ ip = 1
+ Memc[trecord] = EOS
+
+ # Loop over the columns.
+ do i = 1, ncols {
+
+ # Decode the record skipping blank lines.
+ if (ctowrd (Memc[record], lip, Memc[twrd], max_lencolid) <= 0)
+ break
+
+ # Issue the review prompt.
+ if (i == 1) {
+ call printf (
+ "\nReview OBJECT %s (%s) (value, <CR>=ok, <EOF>=quit review): ")
+ } else {
+ call printf ("\tReview %s (%s) (value, <CR>=ok): ")
+ }
+ call pargstr (names[1,i])
+ call pargstr (Memc[twrd])
+ call flush (STDOUT)
+
+ # Scan the standard input for a corrected value.
+ stat = scan()
+ if (stat == EOF) {
+ if (i == 1)
+ break
+ else
+ Memc[wrd] = EOS
+ } else
+ call gargstr (Memc[wrd], max_lencolid)
+ if (Memc[wrd] == EOS)
+ call strcpy (Memc[twrd], Memc[wrd], max_lencolid)
+ else {
+ call printf ("\t%s old: %s new: %s\n")
+ call pargstr (names[1,i])
+ call pargstr (Memc[twrd])
+ call pargstr (Memc[wrd])
+ }
+
+ # Format the output record.
+ call sprintf (Memc[trecord+ip-1], max_lencolid, "%*.*s")
+ call pargi (-Memi[twidths+i-1])
+ call pargi (widths[i])
+ call pargstr (Memc[wrd])
+ ip = ip + Memi[twidths+i-1]
+ }
+
+ # Output the current record.
+ if (stat == EOF) {
+ call ph_pdrecord (tfd, Memc[record+MKCAT_SZSTR], sz_record,
+ Memi[twidths], ncols, MKCAT_BLANKSTR, SZ_LINE - 1)
+ break
+ } else if (Memc[trecord] == EOS)
+ call fprintf (tfd, "\n")
+ else
+ call ph_pdrecord (tfd, Memc[trecord], sz_record, Memi[twidths],
+ ncols, MKCAT_BLANKSTR, SZ_LINE - 1)
+ }
+
+ # Copy any remaining records that were not reviewed.
+ while (ph_gdrecord (fd, Memc[record], MAX_CONT * SZ_LINE) != EOF) {
+ if (Memc[record] == EOS)
+ call fprintf (tfd, "\n")
+ else
+ call ph_pdrecord (tfd, Memc[record+MKCAT_SZSTR], sz_record,
+ Memi[twidths], ncols, MKCAT_BLANKSTR, SZ_LINE - 1)
+ }
+
+ call printf ("\n")
+ call sfree (sp)
+end
diff --git a/noao/digiphot/photcal/mkconfig.cl b/noao/digiphot/photcal/mkconfig.cl
new file mode 100644
index 00000000..7f2ad642
--- /dev/null
+++ b/noao/digiphot/photcal/mkconfig.cl
@@ -0,0 +1,99 @@
+# MKCONFIG -- Create / edit a PHOTCAL configuration file.
+
+procedure mkconfig (config, catalog, observations, transform)
+
+file config {prompt="The new configuration file"}
+file catalog {"STDIN",
+ prompt="The source of the catalog format specification"}
+file observations {"STDIN",
+ prompt="The source of the observations file format specification"}
+file transform {"STDIN",
+ prompt="The source of the transformation equations"}
+file template {"", prompt="An existing template configuration file"}
+string catdir {")_.catdir",prompt="The standard star catalog directory"}
+bool verify {no, prompt="Verify each new entry"}
+bool edit {yes,prompt="Edit the new configuration file"}
+bool check {yes,prompt="Check the configuration file"}
+bool verbose {no, prompt="Verbose output"}
+
+
+begin
+ # Declare local variables
+
+ file con, temp, tcat, cat, tobs, obs, ttrans, trans
+ string cdir
+
+ string junk
+
+ # Get the output and template files.
+
+ con = config
+ if (access (con))
+ error (0, "The configuration file " // con // " already exists")
+ temp = template
+
+ # Define the source of the catalog, observation and transformation
+ # sections.
+
+ if (access (temp)) {
+
+ cat = ""
+ obs = ""
+ trans = ""
+
+ } else {
+
+ cdir = catdir
+
+ tcat = catalog
+ cat = "f" // tcat // ".dat"
+ if (! access (cat)) {
+ cat = cdir // cat
+ if (! access (cat)) {
+ cat = tcat
+ if (! access (cat))
+ error (0,
+ "Cannot find " // tcat //
+ " in current or standards directory")
+ }
+ }
+
+ tobs = observations
+ obs = "f" // tobs // ".dat"
+ if (! access (obs)) {
+ obs = tobs
+ if (! access (obs))
+ error (0,
+ "Cannot find " // tobs // " in current directory")
+ }
+
+ ttrans=transform
+ trans = "t" // ttrans // ".dat"
+ if (! access (trans)) {
+ trans = cdir // trans
+ if (! access (trans)) {
+ trans = ttrans
+ if (! access (trans))
+ error (0,
+ "Cannot find " // ttrans //
+ " in current or standards directory")
+ }
+ }
+ }
+
+ # Make a new configuration file.
+
+ config (con, catalog=cat, observations=obs, transform=trans,
+ template=temp, verify=verify)
+
+ # Edit the catalog with the editor.
+
+ print ("")
+ if (edit)
+ edit (con)
+
+ # Check the configuration file for semantic and syntax errors.
+ print ("")
+ if (check)
+ chkconfig (con, verbose=verbose)
+end
diff --git a/noao/digiphot/photcal/mkconfig/catlist.key b/noao/digiphot/photcal/mkconfig/catlist.key
new file mode 100644
index 00000000..e118de34
--- /dev/null
+++ b/noao/digiphot/photcal/mkconfig/catlist.key
@@ -0,0 +1,20 @@
+
+ ******************************************************************************
+ * *
+ * THE STANDARD STAR CATALOG FORMAT SPECIFICATION *
+ * *
+ * The source of the catalog format specification must be one of the *
+ * following: *
+ * *
+ * elias - the Elias JHKL catalog *
+ * landolt - the Landolt UBVRI catalog *
+ * nlandolt - the new Landolt UBVRI catalog *
+ * odewahn - the Odewahn cluster BVR catalog *
+ * porter - the Porter cluster UBVRI catalog *
+ * ukirt - the UKIRT JHK catalog *
+ * catalog - a catalog created with MKCATALOG *
+ * STDIN - the standard input *
+ * filename - a user supplied file *
+ * *
+ * *
+ ******************************************************************************
diff --git a/noao/digiphot/photcal/mkconfig/catsection.key b/noao/digiphot/photcal/mkconfig/catsection.key
new file mode 100644
index 00000000..1cda33e6
--- /dev/null
+++ b/noao/digiphot/photcal/mkconfig/catsection.key
@@ -0,0 +1,42 @@
+THE CATALOG SECTION
+
+ The catalog section is used to assign names to columns in the
+ standard star catalog, and optionally, to associate error columns
+ with the named columns.
+
+ The catalog section begins with the keyword catalog, followed by
+ any number of name and error(name), column associations.
+
+ Syntax
+ catalog
+
+ name number
+
+ error(name) number
+
+ The first declaration creates a name column number association. It
+ consists of a name followed by a column number. The name becomes
+ the variable name for that column.
+
+ The second declaration creates an error (name) column number
+ association. It begins with the keyword error, followed by a name
+ in brackets and a column number. The name must be the name of an
+ input column previously declared in the catalog section. The error
+ declarations are optional.
+
+ The column number must be a decimal integer greater than two, since
+ catalog files always reserve the first column for a matching name.
+ This name is used to match objects in the catalog file with objects
+ in the observations file.
+
+ Example
+ # Sample catalog section for the UBV system.
+
+ catalog
+
+ V 2
+ error(V) 3
+ BV 4
+ error(BV) 5
+ UB 6
+ error(UB) 7
diff --git a/noao/digiphot/photcal/mkconfig/mkpkg b/noao/digiphot/photcal/mkconfig/mkpkg
new file mode 100644
index 00000000..4e93c805
--- /dev/null
+++ b/noao/digiphot/photcal/mkconfig/mkpkg
@@ -0,0 +1,10 @@
+# The MKPKG file for the mkconfig subdirectory.
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ t_config.x <ctype.h> <fset.h> <lexnum.h>
+ ;
diff --git a/noao/digiphot/photcal/mkconfig/obsection.key b/noao/digiphot/photcal/mkconfig/obsection.key
new file mode 100644
index 00000000..e5d74140
--- /dev/null
+++ b/noao/digiphot/photcal/mkconfig/obsection.key
@@ -0,0 +1,43 @@
+THE OBSERVATION SECTION
+
+ The observation section is used to assign names to columns in the
+ observations files, and to optionally, associate error columns with
+ the named columns.
+
+ The observations section begins with the keyword observation,
+ followed by any number of name and error (name) column associations.
+
+ Syntax
+ observation
+
+ name number
+
+ error(name) number
+
+ The first declaration creates a name column number association. It
+ consists of a name followed by a column number. The name becomes
+ the variable name for that column.
+
+ The second declaration creates an error (name) column number
+ association. It starts with the keyword error, followed by a name
+ in brackets, and a column number. The name must be the name of an
+ input column previously declared in the observation section. The
+ error declarations are optional.
+
+ The column number must be a decimal integer greater two, since the
+ first column of the observations file is reserved for a matching
+ name. This name is used to match objects in the observations file
+ with objects in the catalog file.
+
+ Example
+ # Sample observation section for the UBV system.
+
+ observation
+
+ u 2
+ error(u) 3
+ b 4
+ error(b) 5
+ v 6
+ error(v) 7
+ x 8
diff --git a/noao/digiphot/photcal/mkconfig/obslist.key b/noao/digiphot/photcal/mkconfig/obslist.key
new file mode 100644
index 00000000..ba36b8c0
--- /dev/null
+++ b/noao/digiphot/photcal/mkconfig/obslist.key
@@ -0,0 +1,18 @@
+
+ ******************************************************************************
+ * *
+ * THE OBSERVATIONS FILE FORMAT SPECIFICATION *
+ * *
+ * The source of the observations file format specification must be one of *
+ * the following: *
+ * *
+ * observations - the observations file written by (MK*)OBSFILE *
+ * catalog - a catalog written by MKCATALOG *
+ * STDIN - the standard input *
+ * filename - a user supplied file *
+ * *
+ * Note that the MKCATALOG task can be used to type in a set of *
+ * observations, although it is more usually used to type in standard star *
+ * data. *
+ * *
+ ******************************************************************************
diff --git a/noao/digiphot/photcal/mkconfig/t_config.x b/noao/digiphot/photcal/mkconfig/t_config.x
new file mode 100644
index 00000000..a3a19767
--- /dev/null
+++ b/noao/digiphot/photcal/mkconfig/t_config.x
@@ -0,0 +1,1013 @@
+include <ctype.h>
+include <fset.h>
+include <lexnum.h>
+
+# define some of the working space parameters
+
+define CFG_MAXLENEQN SZ_LINE # maximum length of an expression
+define CFG_MAXLENLINE 78 # maximum length of an output line
+define CFG_MAXLENTRANS 16000 # maximum length of transformation area
+define CFG_MAXLENPARAM 160 # maximum length of parameter area
+
+# define the internal help pages
+
+define CFG_CATHELP "photcal$mkconfig/catsection.key"
+define CFG_OBSHELP "photcal$mkconfig/obsection.key"
+define CFG_TRANSHELP "photcal$mkconfig/transection.key"
+
+# T_CONFIG -- Create the configuration file.
+
+procedure t_config()
+
+pointer output # pointer to the output configuration file
+pointer template # pointer to template configuration file
+pointer catalog # pointer to the template catalog section file
+pointer observation # pointer to the template observation section file
+pointer transform # pointer to the template transformation section file
+pointer deriv # pointer to the derivative syntax string
+int verify # verify each user entry
+
+int fd, cfd, ofd, tfd
+pointer sp
+bool clgetb()
+int access(), open(), btoi()
+
+begin
+ # Set the standard output to flush on a newline.
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (template, SZ_FNAME, TY_CHAR)
+ call salloc (catalog, SZ_FNAME, TY_CHAR)
+ call salloc (observation, SZ_FNAME, TY_CHAR)
+ call salloc (transform, SZ_FNAME, TY_CHAR)
+ call salloc (deriv, SZ_FNAME, TY_CHAR)
+
+ # Get the parameters.
+ call clgstr ("config", Memc[output], SZ_FNAME)
+ verify = btoi (clgetb ("verify"))
+
+ # Make the configuration file. If a template configuration file
+ # is supplied and exists then simply copy the template into the
+ # output configuration file. If no template is supplied begin
+ # prompting user for input. The user may supply a default
+ # catalog, observation or transformation section file in place of
+ # entering any given section by hand.
+
+ call clgstr ("template", Memc[template], SZ_FNAME)
+ if (access (Memc[template], 0, 0) == YES) {
+ call fcopy (Memc[template], Memc[output])
+ } else {
+
+ fd = open (Memc[output], NEW_FILE, TEXT_FILE)
+
+ call clgstr ("catalog", Memc[catalog], SZ_FNAME)
+ if (access (Memc[catalog], READ_ONLY, TEXT_FILE) == YES)
+ cfd = open (Memc[catalog], READ_ONLY, TEXT_FILE)
+ else
+ cfd = NULL
+ call clgstr ("observations", Memc[observation], SZ_FNAME)
+ if (access (Memc[observation], READ_ONLY, TEXT_FILE) == YES)
+ ofd = open (Memc[observation], READ_ONLY, TEXT_FILE)
+ else
+ ofd = NULL
+ call clgstr ("transform", Memc[transform], SZ_FNAME)
+ if (access (Memc[transform], READ_ONLY, TEXT_FILE) == YES)
+ tfd = open (Memc[transform], READ_ONLY, TEXT_FILE)
+ else
+ tfd = NULL
+
+ call ph_wconfig (fd, cfd, ofd, tfd, verify)
+
+ call close (fd)
+ if (cfd != NULL)
+ call close (cfd)
+ if (ofd != NULL)
+ call close (ofd)
+ if (tfd != NULL)
+ call close (tfd)
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_WCONFIG -- Write the catalog, observation and transfromation section
+# of the configuration file by prompting the user. If the file descriptor
+# to the transformation file is not NULL then copy the template
+# transformation file into the tranformation section of the configuration
+# file.
+
+procedure ph_wconfig (fd, cfd, ofd, tfd, verify)
+
+int fd # the output configuration file descriptor
+int cfd # the input catalog file descriptor
+int ofd # the input observation file descriptor
+int tfd # the input transformation file descriptor
+int verify # verify each user entry
+
+begin
+ # Enter the catalog section.
+ if ((cfd != NULL) && (cfd != STDIN))
+ call fcopyo (cfd, fd)
+ else
+ call ph_rcsection (fd, "catalog", verify)
+
+ # Enter the observation section.
+ if ((ofd != NULL) && (ofd != STDIN))
+ call fcopyo (ofd, fd)
+ else
+ call ph_rosection (fd, "observation", verify)
+
+ # Enter the transformation section.
+ if ((tfd != NULL) && (tfd != STDIN))
+ call fcopyo (tfd, fd)
+ else
+ call ph_rtsection (fd, "transformation", verify)
+end
+
+
+# PH_RCSECTION -- Write the catalog section of the configuration file by
+# prompting the user.
+
+procedure ph_rcsection (fd, keyword, verify)
+
+int fd # file descriptor for the output configuration file
+char keyword[ARB] # keyword defining the configuration file section
+int verify # verify each user entry
+
+int stat, number, newnumber
+pointer sp, column, newcolumn
+int ph_rcolnumber()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (column, SZ_LINE, TY_CHAR)
+ call salloc (newcolumn, SZ_LINE, TY_CHAR)
+
+ # Write the section title.
+ call fprintf (fd, "\n%s\n\n")
+ call pargstr (keyword)
+
+ # Scan the standard input.
+ call printf (
+ "\nENTER THE STANDARD STAR CATALOG FORMAT DESCRIPTION\n\n")
+ repeat {
+
+ # Read the column name and number.
+ stat = ph_rcolnumber (CFG_CATHELP, Memc[column], SZ_LINE, number)
+ if (stat == EOF)
+ break
+ if (stat <= 0)
+ next
+
+ # Verify and/or write the definition.
+ if (verify == NO) {
+
+ # Write the definition.
+ call fprintf (fd, "%s %d\n")
+ call pargstr (Memc[column])
+ call pargi (number)
+ next
+
+ } else {
+
+ call ph_vcolnumber (Memc[column], Memc[newcolumn], SZ_LINE,
+ number, newnumber)
+ call fprintf (fd, "%s %d\n")
+ call pargstr (Memc[newcolumn])
+ call pargi (newnumber)
+
+ }
+ }
+ call printf ("\n")
+
+ call sfree (sp)
+end
+
+
+# PH_ROSECTION -- Write the observation section of the configuration file by
+# prompting the user.
+
+procedure ph_rosection (fd, keyword, verify)
+
+int fd # file descriptor for the output configuration file
+char keyword[ARB] # keyword defining the configuration file section
+int verify # verify each user entry
+
+int stat, number, newnumber
+pointer sp, column, newcolumn
+int ph_rcolnumber()
+
+begin
+ call smark (sp)
+ call salloc (column, SZ_LINE, TY_CHAR)
+ call salloc (newcolumn, SZ_LINE, TY_CHAR)
+
+ # Write the section title.
+ call fprintf (fd, "\n%s\n\n")
+ call pargstr (keyword)
+
+ # Scan the standard input.
+ call printf ("\nENTER THE OBSERVATIONS FILE FORMAT DESCRIPTION\n\n")
+ repeat {
+
+ # Read the column name and number.
+ stat = ph_rcolnumber (CFG_OBSHELP, Memc[column], SZ_LINE, number)
+ if (stat == EOF)
+ break
+ if (stat <= 0)
+ next
+
+ # Verify and/or write the definition.
+ if (verify == NO) {
+
+ call fprintf (fd, "%s %d\n")
+ call pargstr (Memc[column])
+ call pargi (number)
+ next
+
+ } else {
+
+ call ph_vcolnumber (Memc[column], Memc[newcolumn], SZ_LINE,
+ number, newnumber)
+ call fprintf (fd, "%s %d\n")
+ call pargstr (Memc[newcolumn])
+ call pargi (newnumber)
+
+ }
+ }
+ call printf ("\n")
+
+ call sfree (sp)
+end
+
+
+# PH_RTSECTION -- Write the observation section of the configuration file by
+# prompting the user.
+
+procedure ph_rtsection (fd, keyword, verify)
+
+pointer fd # file descriptor for the output configuration file
+char keyword[ARB] # keyword defining the section
+int verify # verify each user entry
+
+int tfd, ffd, cfd, len_label, len_expr, len_dexpr
+int neq, nparam, stat
+pointer sp, label, param, str, expr, dexpr, trans, fit, const
+int ph_rlabel(), ph_rexpr(), ph_rlist(), stropen()
+
+begin
+ # Allocate temporary working space.
+ call smark (sp)
+ call salloc (label, SZ_LINE, TY_CHAR)
+ call salloc (param, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (expr, CFG_MAXLENEQN, TY_CHAR)
+ call salloc (dexpr, CFG_MAXLENEQN, TY_CHAR)
+
+ # Open the temporary string files.
+ call malloc (trans, CFG_MAXLENTRANS, TY_CHAR)
+ call malloc (fit, CFG_MAXLENPARAM, TY_CHAR)
+ call malloc (const, CFG_MAXLENTRANS, TY_CHAR)
+ tfd = stropen (Memc[trans], CFG_MAXLENTRANS, NEW_FILE)
+ ffd = stropen (Memc[fit], CFG_MAXLENPARAM, NEW_FILE)
+ cfd = stropen (Memc[const], CFG_MAXLENPARAM, NEW_FILE)
+
+ # Write the section title.
+ call fprintf (fd, "\n%s\n\n")
+ call pargstr (keyword)
+
+ call printf ("\nENTER THE TRANSFORMATION EQUATIONS\n")
+
+ # Scan the standard input.
+ neq = 0
+ repeat {
+
+ # Get the parameters for each equation.
+ call printf (
+ "\nEnter the label and functional form for EQUATION %d\n\n")
+ call pargi (neq + 1)
+
+ # Fetch and verify the equation label.
+ len_label = ph_rlabel ("label (e.g. VFIT)", Memc[label],
+ SZ_LINE, verify)
+ if (len_label == EOF)
+ break
+ if (len_label <= 0)
+ next
+
+ # Fetch and verify the transformation equation.
+ len_expr = ph_rexpr ("equation", Memc[expr], CFG_MAXLENEQN, neq + 1,
+ verify)
+ if (len_expr == EOF)
+ next
+ if (len_expr <= 0) {
+ call printf ("<Error> The function expression is blank\n")
+ next
+ }
+
+ # Write the equation to a temporary string file.
+ iferr {
+ call ph_wequation (tfd, Memc[label], len_label, Memc[expr],
+ len_expr)
+ } then
+ break
+
+ # Get the fitted parameters.
+ call printf ("\nEnter initial values for the ")
+ call printf ("parameters to be fit in EQUATION %d\n\n")
+ call pargi (neq + 1)
+ nparam = 1
+ len_dexpr = 1
+ repeat {
+ call sprintf (Memc[str], SZ_LINE, "%s %d")
+ call pargstr ("parameter")
+ call pargi (nparam)
+ stat = ph_rlist (Memc[dexpr], len_dexpr, CFG_MAXLENEQN,
+ Memc[str], verify)
+ if (stat == EOF)
+ break
+ if (stat <= 0) {
+ call printf ("\n")
+ call ph_wequation (STDOUT, Memc[label], len_label,
+ Memc[expr], len_expr)
+ call printf ("\n")
+ next
+ } else
+ nparam = nparam + 1
+ }
+
+ # Write the fitted parameters.
+ iferr {
+ if (nparam > 1)
+ call ph_wparam (ffd, "fit", 3, Memc[dexpr], len_dexpr - 3)
+ } then
+ break
+
+ # Get the constant parameters.
+ call printf ("\nEnter initial values for the ")
+ call printf ("parameters to be held constant in EQUATION %d\n\n")
+ call pargi (neq + 1)
+ nparam = 1
+ len_dexpr = 1
+ repeat {
+ call sprintf (Memc[str], SZ_LINE, "%s%d and value")
+ call pargstr ("parameter")
+ call pargi (nparam)
+ stat = ph_rlist (Memc[dexpr], len_dexpr, CFG_MAXLENEQN,
+ Memc[str], verify)
+ if (stat == EOF)
+ break
+ if (stat <= 0) {
+ call printf ("\n")
+ call ph_wequation (STDOUT, Memc[label], len_label,
+ Memc[expr], len_expr)
+ call printf ("\n")
+ next
+ } else
+ nparam = nparam + 1
+ }
+
+ # Write the constant parameters.
+ iferr {
+ if (nparam > 1)
+ call ph_wparam (cfd, "const", 5, Memc[dexpr], len_dexpr - 3)
+ } then
+ break
+
+ neq = neq + 1
+ }
+
+ call printf ("\n")
+
+ # Close the string files.
+ call strclose (tfd)
+ call strclose (ffd)
+ call strclose (cfd)
+
+ # Write output results to a file
+ call ph_wfile (fd, Memc[fit], CFG_MAXLENPARAM, Memc[const],
+ CFG_MAXLENPARAM, Memc[trans], CFG_MAXLENTRANS)
+
+ # Free memory.
+ call mfree (trans, TY_CHAR)
+ call mfree (fit, TY_CHAR)
+ call mfree (const, TY_CHAR)
+ call sfree (sp)
+end
+
+
+# PH_RCOLNUMBER -- Read in the column name and number as an identifier and
+# a number respectively.
+
+int procedure ph_rcolnumber (helpfile, column, max_lcolname, number)
+
+char helpfile[ARB] # name of the helpfile
+char column[ARB] # name of the column
+int max_lcolname # maximum length of the column name
+int number # column number
+
+bool streq(), ph_isident()
+int scan(), strmatch(), nscan()
+
+begin
+ # Issue the prompt.
+ call printf (
+ "Enter column definition (name number, ?=help, <EOF>=quit entry): ")
+ call flush (STDOUT)
+
+ if (scan () == EOF)
+ return (EOF)
+ call gargwrd (column, max_lcolname)
+ call gargi (number)
+
+ # Check for errors.
+ if (streq (column, "?")) {
+ call pagefile (helpfile, "")
+ return (0)
+ } else if (! ph_isident (column) && strmatch (column, "error(") == 0) {
+ call printf (
+ "<Error> %s is not a legal column name\n")
+ call pargstr (column)
+ return (0)
+ } else if (nscan() != 2) {
+ call printf ("<Error> Cannot decode the column number\n")
+ return (0)
+ } else if (number <= 1) {
+ call printf (
+ "<Error> Column 1 is reserved for the object name\n")
+ return (0)
+ }
+
+ return (nscan())
+end
+
+
+# PH_VCOLNUMBER -- Verify the column name and number.
+
+procedure ph_vcolnumber (column, newcolumn, max_lcolname, number, newnumber)
+
+char column[ARB] # input column name
+char newcolumn[ARB] # new column name
+int max_lcolname # maximum length of the column name
+int number # original column number
+int newnumber # new column number
+
+bool ph_isident()
+int scan(), nscan()
+
+begin
+ # Issue the verify prompt.
+ call printf ("\tVerify (%s %d) (name number, <CR>=ok): ")
+ call pargstr (column)
+ call pargi (number)
+ call flush (STDOUT)
+
+ # Get the new values.
+ if (scan () == EOF) {
+ newcolumn[1] = EOS
+ call printf ("\n")
+ call flush (STDOUT)
+ } else
+ call gargstr (newcolumn, max_lcolname)
+
+ # If the new input is not valid use the original values.
+ if (newcolumn[1] != EOS) {
+ call sscan (newcolumn)
+ call gargwrd (newcolumn, max_lcolname)
+ call gargi (newnumber)
+ if (! ph_isident(newcolumn))
+ call strcpy (column, newcolumn, max_lcolname)
+ if (nscan() != 2)
+ newnumber = number
+ else if (newnumber <= 1)
+ newnumber = number
+ } else {
+ call strcpy (column, newcolumn, max_lcolname)
+ newnumber = number
+ }
+end
+
+
+# PH_RLABEL -- Read a legal identifier or label.
+
+int procedure ph_rlabel (keyword, label, max_lenlabel, verify)
+
+char keyword[ARB] # the identfier or label keyword
+char label[ARB] # the output label
+int max_lenlabel # maximum length of the label
+int verify # verify the expression
+
+int len_label
+pointer sp, newlabel
+bool streq(), ph_isident()
+int scan(), strlen()
+
+begin
+ # Prompt for the label of the specified equation.
+ call printf ("Enter %s (label, ?=help, <EOF>=quit entry): ")
+ call pargstr (keyword)
+ call flush (STDOUT)
+
+ # Read the label value.
+ if (scan () == EOF) {
+ call printf ("\n")
+ return (EOF)
+ } else
+ call gargwrd (label, max_lenlabel)
+
+ # Check for errors.
+ if (streq (label, "?")) {
+ call pagefile (CFG_TRANSHELP, "")
+ return (0)
+ } else if (! ph_isident (label)) {
+ call printf ("<Error> %s is not a legal label\n")
+ call pargstr (label)
+ return (0)
+ } else {
+ len_label = strlen (label)
+ }
+
+ if (verify == NO)
+ return (len_label)
+
+ # Verify the label.
+ call smark (sp)
+ call salloc (newlabel, max_lenlabel, TY_CHAR)
+
+ # Issue the verify prompt.
+ call printf ("\tVerify (%s) (label, <CR>=ok): ")
+ call pargstr (label)
+ call flush (STDOUT)
+
+ # Read the new value. Restore the old values if the input is invalid.
+ if (scan () == EOF) {
+ Memc[newlabel] = EOS
+ call printf ("\n")
+ call flush (STDOUT)
+ } else
+ call gargwrd (Memc[newlabel], max_lenlabel)
+
+ # Check the value.
+ if (Memc[newlabel] != EOS) {
+ if (! ph_isident(Memc[newlabel]))
+ call strcpy (label, Memc[newlabel], max_lenlabel)
+ } else
+ call strcpy (label, Memc[newlabel], max_lenlabel)
+ len_label = strlen (Memc[newlabel])
+
+ call sfree (sp)
+
+ return (len_label)
+end
+
+
+# PH_REXPR -- Read in an expression. The expression can span multiple lines.
+
+int procedure ph_rexpr (keyword, expr, max_lenexpr, neq, verify)
+
+char keyword[ARB] # name of the expression
+char expr[ARB] # expression
+int max_lenexpr # the maximum length of an expression
+int neq # the equation number
+int verify # verify the expression
+
+int ip, op, len_expr, sz_expr
+pointer sp, newexpr
+bool streq()
+int strlen(), scan(), gstrcpy()
+
+begin
+ # Issue the prompt.
+ call printf ("Enter %s (equation, equation\=continue, ?=help, ")
+ call pargstr (keyword)
+ call printf ("<EOF>=quit entry):\n")
+
+ # Read in the expression.
+ ip = 1
+ repeat {
+
+ # Get a chunk of the equation.
+ if (scan () == EOF) {
+ call printf ("\n")
+ return (EOF)
+ } else
+ call gargstr (expr[ip], max_lenexpr)
+
+ # Decode the expresssion.
+ if (expr[ip] == EOS) {
+ break
+ } else if (streq (expr[ip], "?")) {
+ call pagefile (CFG_TRANSHELP, "")
+ call printf (
+ "Equation %d enter %s (?=help, \=continue, EOF=quit):\n")
+ call pargi (neq)
+ call pargstr (keyword)
+ next
+ } else {
+ ip = ip + strlen (expr[ip])
+ if (expr[ip-1] == '\\')
+ ip = ip - 1
+ else
+ break
+ }
+ }
+
+ # Return length of expression if verify is off.
+ len_expr = ip - 1
+ if (verify == NO)
+ return (len_expr)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (newexpr, max_lenexpr, TY_CHAR)
+
+ # Issue the verify prompt.
+ call printf ("Verify (equation, <CR>=ok):\n")
+ call pargstr (keyword)
+
+ # Read the new values.
+ ip = 1
+ op = 1
+ while (ip <= len_expr) {
+
+ # Print a chunk of the existing equation.
+ sz_expr = min (len_expr - ip + 1, CFG_MAXLENLINE - 2)
+ call printf ("%*.*s\n")
+ call pargi (-sz_expr)
+ call pargi (sz_expr)
+ call pargstr (expr[ip])
+ call flush (STDOUT)
+
+ # Get a chunk of the new equation.
+ if (scan() == EOF) {
+ Memc[newexpr+op-1] = EOS
+ call printf ("\n")
+ call flush (STDOUT)
+ } else
+ call gargstr (Memc[newexpr+op-1], CFG_MAXLENLINE)
+
+ if (Memc[newexpr+op-1] == EOS) {
+ op = op + gstrcpy (expr[ip], Memc[newexpr+op-1], sz_expr)
+ #} else if (Memc[newexpr+op-1] == '\\') {
+ #if (scan() == EOF)
+ #Memc[newexpr+op-1] = EOS
+ #else
+ #call gargstr (Memc[newexpr+op-1], CFG_MAXLENLINE)
+ #op = op + strlen (Memc[newexpr+op-1])
+ } else
+ op = op + strlen (Memc[newexpr+op-1])
+
+ ip = ip + sz_expr
+ }
+
+ # Copy the new expression into the output buffer.
+ if (Memc[newexpr] != EOS)
+ call strcpy (Memc[newexpr], expr, max_lenexpr)
+
+ call sfree (sp)
+
+ return (op - 1)
+end
+
+
+# PH_RLIST -- Get a list of parameter = value strings.
+
+int procedure ph_rlist (list, op, max_lenlist, keyword, verify)
+
+char list[ARB] # list of parameter=value strings
+int op # pointer into the parameter list
+int max_lenlist # maximum length of parameter list
+char keyword[ARB] # prompt keyword
+int verify # verify the parameter values
+
+int stat
+pointer sp, param, number
+int ph_rpar(), gstrcpy()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (param, SZ_LINE, TY_CHAR)
+ call salloc (number, SZ_LINE, TY_CHAR)
+
+ # Read the parameter and its associated value.
+ stat = ph_rpar (CFG_TRANSHELP, keyword, Memc[param], Memc[number],
+ SZ_LINE, verify)
+
+ # Copy the values into the fitted parameter string.
+ if (stat >= 2) {
+ op = op + gstrcpy (Memc[param], list[op], max_lenlist - op + 1)
+ op = op + gstrcpy (" = ", list[op], max_lenlist - op + 1)
+ op = op + gstrcpy (Memc[number], list[op], max_lenlist - op + 1)
+ op = op + gstrcpy (", ", list[op], max_lenlist - op + 1)
+ }
+
+ call sfree (sp)
+
+ return (stat)
+end
+
+
+# PH_RPAR -- Read in a user supplied parameter and value.
+
+int procedure ph_rpar (helpfile, keyword, param, number, max_lenparam,
+ verify)
+
+char helpfile[ARB] # name of the helpfile
+char keyword[ARB] # name of the keyword
+char param[ARB] # name of the parameter
+char number[ARB] # parameter value
+int max_lenparam # maximum length of parameter name and value
+int verify # verify the values
+
+int ip, nchars
+pointer sp, newparam, newnumber
+bool streq(), ph_isident()
+int scan(), nscan(), lexnum()
+
+begin
+ # Issue the prompt.
+ call printf (
+ "Enter %s (name value, ?=help, <EOF>=quit entry):")
+ call pargstr (keyword)
+ call flush (STDOUT)
+
+ # Read the values.
+ if (scan () == EOF) {
+ call printf ("\n")
+ return (EOF)
+ } else {
+ call gargwrd (param, max_lenparam)
+ call gargwrd (number, max_lenparam)
+ }
+
+ # Check for errors.
+ ip = 1
+ if (streq (param, "?")) {
+ call pagefile (helpfile, "")
+ return (0)
+ } else if (! ph_isident (param)) {
+ call printf ("<Error> %s is not a legal parameter name\n")
+ call pargstr (param)
+ return (0)
+ } else if (nscan() != 2) {
+ call printf ("<Error> Cannot decode the parameter value\n")
+ return (0)
+ } else if (lexnum (number, ip, nchars) == LEX_NONNUM) {
+ call printf (
+ "<Error> The parameter value %s is not a legal number\n")
+ call pargstr (number)
+ return (0)
+ } else if (verify == NO) {
+ return (nscan())
+ }
+
+ call smark (sp)
+ call salloc (newparam, max_lenparam, TY_CHAR)
+ call salloc (newnumber, max_lenparam, TY_CHAR)
+
+ # Issue the verify prompt.
+ call printf ("\tVerify (%s %s) (name value, <CR>=ok):")
+ call pargstr (param)
+ call pargstr (number)
+ call flush (STDOUT)
+
+ # Read the new values.
+ ip = 1
+ if (scan () == EOF)
+ Memc[newparam] = EOS
+ else
+ call gargstr (Memc[newparam], max_lenparam)
+
+ if (Memc[newparam] != EOS) {
+ call sscan (Memc[newparam])
+ call gargwrd (Memc[newparam], max_lenparam)
+ call gargwrd (Memc[newnumber], max_lenparam)
+ if (ph_isident (Memc[newparam]))
+ call strcpy (Memc[newparam], param, max_lenparam)
+ if ((nscan() == 2) && (lexnum (Memc[newnumber], ip, nchars) !=
+ LEX_NONNUM))
+ call strcpy (number, Memc[newnumber], max_lenparam)
+ }
+
+ call sfree (sp)
+
+ return (2)
+end
+
+
+# PH_WEQUATION -- Format and write a transformation equation to the
+# configuration file.
+
+procedure ph_wequation (fd, label, len_label, expr, len_expr)
+
+int fd # the output configuration file descriptor
+char label[ARB] # the equation label
+int len_label # length of the label
+char expr[ARB] # the left-hand side or function expression
+int len_expr # length of the function expression
+
+int op
+pointer sp, line
+errchk ph_write, putline
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (line, CFG_MAXLENLINE + 1, TY_CHAR)
+ op = 1
+
+ # Initialize the output buffer and copy the label, the colon
+ # character label delimiter, te function expression, the equal
+ # sign and the fit expression to the configurationf file.
+
+ call ph_write (fd, label, len_label, Memc[line], CFG_MAXLENLINE, op)
+ call ph_write (fd, " : ", 3, Memc[line], CFG_MAXLENLINE, op)
+ call ph_write (fd, expr, len_expr, Memc[line], CFG_MAXLENLINE, op)
+
+ # Flush the remainder of the output.
+ if (op > 1)
+ call putline (fd, Memc[line])
+
+ call sfree (sp)
+end
+
+
+# PH_WDERIV -- Write the derivative expression for the equation to the
+# output file.
+
+procedure ph_wderiv (fd, label, len_label, param, len_param, dexpr, len_dexpr)
+
+int fd # pointer to the output file descriptor
+char label[ARB] # the equation label
+int len_label # length of the label
+char param[ARB] # the derivative parameter name
+int len_param # length of the derivative parameter name
+char dexpr[ARB] # the derivative expression
+int len_dexpr # length of the derivative expression
+
+int op
+pointer sp, line
+errchk ph_write, putline
+
+begin
+ call smark (sp)
+ call salloc (line, CFG_MAXLENLINE + 1, TY_CHAR)
+ op = 1
+
+ # Copy the keyword and opening bracket, the equation label, the
+ # separating comma, the parameter name, the closing bracket and
+ # equal sign, and the derivative expression to the output file .
+
+ call ph_write (fd, "deriv (", 7, Memc[line], CFG_MAXLENLINE, op)
+ call ph_write (fd, label, len_label, Memc[line], CFG_MAXLENLINE, op)
+ call ph_write (fd, ",", 1, Memc[line], CFG_MAXLENLINE, op)
+ call ph_write (fd, param, len_param, Memc[line], CFG_MAXLENLINE, op)
+ call ph_write (fd, ") = ", 4, Memc[line], CFG_MAXLENLINE, op)
+ call ph_write (fd, dexpr, len_dexpr, Memc[line], CFG_MAXLENLINE, op)
+
+ # Flush the remainder of the output.
+ if (op > 1)
+ call putline (fd, Memc[line])
+
+ call sfree (sp)
+end
+
+
+# PH_WPARAM -- Write the fitted and constant parameters to the configuration
+# file.
+
+procedure ph_wparam (fd, keyword, len_keyword, paramlist, len_list)
+
+int fd # output file descriptor
+char keyword[ARB] # statement keyword
+int len_keyword # length of the keyword
+char paramlist[ARB] # fitted parameter list
+int len_list # length of fitted parameter list
+
+int op
+pointer sp, line
+errchk ph_write, putline
+
+begin
+ call smark (sp)
+ call salloc (line, CFG_MAXLENLINE + 1, TY_CHAR)
+
+ # Write the keyword, two blanks, and the parameter list.
+ op = 1
+ call ph_write (fd, keyword, len_keyword, Memc[line], CFG_MAXLENLINE, op)
+ call ph_write (fd, " ", 2, Memc[line], CFG_MAXLENLINE, op)
+ call ph_write (fd, paramlist, len_list, Memc[line], CFG_MAXLENLINE, op)
+
+ # Flush the remainder of the output.
+ if (op > 1)
+ call putline (fd, Memc[line])
+
+ call sfree (sp)
+end
+
+
+# PH_WFILE -- Write the stored strings files to the output file.
+
+procedure ph_wfile (fd, fit, max_lfit, const, max_lconst, trans, max_ltrans)
+
+int fd # the output file descriptor
+char fit[ARB] # the fitted parameter array
+int max_lfit # the maximum length of the fit array
+char const[ARB] # the constant parameter array
+int max_lconst # the maximum length of the constant array
+char trans[ARB] # the equation section
+int max_ltrans # the maximum length of the equation section
+
+int tfd, ffd, cfd
+pointer sp, line
+int stropen(), getline()
+
+begin
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+
+ ffd = stropen (fit, max_lfit, READ_ONLY)
+ cfd = stropen (const, max_lconst, READ_ONLY)
+ tfd = stropen (trans, max_ltrans, READ_ONLY)
+
+ while (getline (ffd, Memc[line]) != EOF)
+ call putline (fd, Memc[line])
+ call putline (fd, "\n")
+ while (getline (cfd, Memc[line]) != EOF)
+ call putline (fd, Memc[line])
+ call putline (fd, "\n")
+ while (getline (tfd, Memc[line]) != EOF)
+ call putline (fd, Memc[line])
+
+ call strclose (tfd)
+ call strclose (ffd)
+ call strclose (cfd)
+
+ call sfree (sp)
+end
+
+
+# PH_WRITE -- Write an output record from the input stream.
+
+procedure ph_write (fd, input, max_linput, output, max_loutput, op)
+
+int fd # the output file descriptor
+char input[ARB] # the input array
+int max_linput # maximum length of the input array
+char output[ARB] # the output array
+int max_loutput # maximum length of the output array
+int op # the output array pointer
+
+int ip, nchars
+errchk putline
+
+begin
+ ip = 1
+
+ repeat {
+ nchars = min (max_linput - ip + 1, max_loutput - op + 1)
+ call amovc (input[ip], output[op], nchars)
+ ip = ip + nchars
+ op = op + nchars
+ if (op > max_loutput) {
+ output[op] = '\n'
+ output[op+1] = EOS
+ call putline (fd, output)
+ op = 1
+ }
+ } until (ip > max_linput)
+
+ output[op] = '\n'
+ output[op+1] = EOS
+end
+
+
+# PH_ISIDENT -- Check to see if a string is a legal identifier.
+
+bool procedure ph_isident (ident)
+
+char ident[ARB] # string to be tested
+
+bool isident
+int ip
+
+begin
+ if (ident[1] == EOS)
+ return (false)
+ if (! IS_ALPHA(ident[1]))
+ return (false)
+
+ isident = true
+ for (ip = 2; isident && (ident[ip] != EOS); ip = ip + 1) {
+ if ((! IS_ALPHA(ident[ip])) && (! IS_DIGIT(ident[ip])))
+ isident = false
+ }
+
+ return (isident)
+end
diff --git a/noao/digiphot/photcal/mkconfig/tranlist.key b/noao/digiphot/photcal/mkconfig/tranlist.key
new file mode 100644
index 00000000..6d6cf9a3
--- /dev/null
+++ b/noao/digiphot/photcal/mkconfig/tranlist.key
@@ -0,0 +1,19 @@
+
+ ******************************************************************************
+ * *
+ * THE TRANSFORMATION EQUATION SPECIFICATION *
+ * *
+ * The source of the transformation equation specifications must be one *
+ * of the following: *
+ * *
+ * landolt - a sample set of transformations to the Landolt UBVRI system *
+ * STDIN - the standard input *
+ * filename - a user supplied file *
+ * *
+ * Currently the landolt UBVRI standards catalogs are the only supported *
+ * photometric standards catalogs. Usually the user will have to edit the *
+ * sample Landolt transformation equations so that they conform to the *
+ * filter set he/she used and the variable names defined in the catalog *
+ * and observations section specifications. *
+ * *
+ ******************************************************************************
diff --git a/noao/digiphot/photcal/mkconfig/transection.key b/noao/digiphot/photcal/mkconfig/transection.key
new file mode 100644
index 00000000..3c99ec0c
--- /dev/null
+++ b/noao/digiphot/photcal/mkconfig/transection.key
@@ -0,0 +1,94 @@
+THE TRANSFORMATION SECTION
+
+ The transformation section is used to define the transformation
+ equations, to specify which parameters are to be altered and which
+ are to be held constant during the fitting process, and to assign
+ initial values to the parameters.
+
+ The transformation section begins with the keyword transformation,
+ followed by the list of parameter declarations, followed by the
+ transformation equation.
+
+ Syntax
+ transformation
+
+ fit parameter = value, parameter = value, ...
+
+ constant parameter = value, parameter = value, ...
+
+ label : expression = expression
+ (function) (fit)
+
+ The fit keyword begins a list of the parameters to be fit. The
+ named parameters will be fit if they are present in a
+ transformation equation. The fit parameter values are used as the
+ initial guesses for the parameters.
+
+ The constant keyword begins a list of the parameters to be held
+ constant. The named parameters will not be fit. Instead the values
+ are regarded as constant values in any transformation equation in
+ which they appear. Constant parameter declarations are used to fix
+ values if they are known, or to restrict the degrees of freedom of
+ the fit.
+
+ All parameters, both fit and constant, must be declared before the
+ first equations in which they appear. There may be any number of
+ fit and constant parameter declaration statements. Redefinitions
+ are allowed, i.e., it is possible to declare a parameter with the
+ fit keyword, and redefine it later with the constant keyword. The
+ inverse is also true.
+
+ The transformation equations are composed of three elements: the
+ equation label, the function expression, and the fit expression.
+
+ The label is used to assign a name to the equation and fit
+ expression. The label can be any name not already in use. The ":"
+ after the label is necessary to delimit it from the rest of the
+ transformation equation defintion. Labels are used primarily to
+ associate the optional error, weight and plot equations with the
+ appropriate transformation equations. However these labels can
+ also be used in expressions belonging to subsequent equations, an
+ action equivalent to replacing them with the fit expression they
+ reference, before performing the actual evaluation.
+
+ The function expression (left hand side of the "=" sign) is used as
+ a reference expression, i.e. an expression that has no fitting or
+ constant parameters in it. The function expression contains only
+ values computed from the input data which are known before the fit
+ starts.
+
+ The fit expression (right hand side of the "=" sign) is an
+ expression which contains the parameters, both those to be fit and
+ those that are fixed. If this expression contains names defined in
+ the catalog section , it will be possible to perform the fit, but
+ will not be possible to apply the transformations in the forward
+ sense to program observations that don't have matching catalog
+ values. If the number of transformations equations is greater than
+ or equal to the total number of catalog variables used in the
+ transformation equations, it MAY be possible to invert the system
+ of equations and so evaluate the catalog variables for program
+ objects.
+
+
+ Example
+
+ # Sample transformation section for the UBV system
+
+ transform
+
+ # V equation
+
+ fit v1 = 25.0, v2=1.03, v3=-0.17
+ VFIT : V = v1 + v + v2 * (b - v) + v3 * x
+
+ # B - V equation
+
+ fit b1 = 2.10, b2 = 1.15, b3=-0.12
+ const b4 = 0.0
+ BVFIT : BV = b1 + b2 * (b - v) + b3 * x + b4 * (b - v) * x
+
+ # U - B equation
+
+ fit u1 = 3.45, u2 = 1.063, u3=-0.30
+ const u4=0.0
+ UBFIT : UB = u1 + u2 * (u - b) + u3 * x + u4 * (u - b) * x
diff --git a/noao/digiphot/photcal/mkimsets.cl b/noao/digiphot/photcal/mkimsets.cl
new file mode 100644
index 00000000..2d90a321
--- /dev/null
+++ b/noao/digiphot/photcal/mkimsets.cl
@@ -0,0 +1,186 @@
+# MKIMSETS -- Create an image set file which describes which images of a given
+# region of the sky form a complete observation.
+#
+# This script requires the IMAGES task HSELECT, the PTOOLS task DUMP, and
+# the PROTO task FIELDS. THE IRAF core system tasks UNIQUE (LISTS package),
+# FILES, DELETE, RENAME, CONCATENATE, and MATCH (SYSTEM package) and FSCAN,
+# ACCESS, MKTEMP and EDIT (LANGUAGE package) are also used.
+
+procedure mkimsets (imlist, idfilters, imsets)
+
+file imlist {prompt="The input image list"}
+string idfilters {prompt="The list of filter ids"}
+file imsets {prompt="The output image set file"}
+file imobsparams {"", prompt="The output image observing parameters file"}
+
+string input {"photfiles", enum="images|photfiles|user",
+ prompt="The source of the input image list"}
+string filter {prompt="The filter keyword"}
+string fields {"", prompt="Additional image list fields"}
+
+string sort {"", prompt="The image list field to be sorted on"}
+bool edit {yes, prompt="Edit the input image list before grouping"}
+bool rename {yes, prompt="Prompt the user for image set names"}
+bool review {yes, prompt="Review the image set file with the editor"}
+
+struct *list
+
+begin
+ # Declare local variables.
+ int tcolumn, nfields
+ string tlist, tidfilters, timsets, tobsparams, tfields, tfilter, tsort
+ string tfile1, tfile2, tstr
+
+ # Get the parameters.
+ tlist = imlist
+ tidfilters = idfilters
+ timsets = imsets
+ if (access (timsets)) {
+ error (1,
+ "The image observation set file " // timsets // " already exists")
+ }
+ tobsparams = imobsparams
+ if (access (tobsparams)) {
+ error (1,
+ "The observing parameters file " // tobsparams // " already exists")
+ }
+
+ # Create temporary file names to store the intermediate sets of images.
+
+ tfile1 = mktemp ("tmp$")
+
+ # Construct the initial list of images and write them to a file.
+ # Sort on the image name and remove duplicate lines.
+
+ if (input == "photfiles") {
+
+ tfilter = "IFILTER"
+ tfields = "ITIME,XAIRMASS,OTIME" // "," // fields
+ tbkeycol (tlist, "IMAGE," // tfilter // "," // tfields)
+ pdump (tlist, "IMAGE," // tfilter // "," // tfields,
+ "yes", headers=no, parameters=yes) |
+ system.sort ("STDIN", column=0, ignore_white=no,
+ numeric_sort=no, reverse_sort=no) |
+ unique ("STDIN", > tfile1)
+
+ } else if (input == "images") {
+
+ tfilter = filter
+ tfields = fields
+ hselect (tlist, "$I," // tfilter // "," // tfields, yes) |
+ system.sort ("STDIN", column=0, ignore_white=no,
+ numeric_sort=no, reverse_sort=no) |
+ unique ("STDIN", > tfile1)
+
+ } else if (input == "user") {
+
+ tfilter = filter
+ tfields = fields
+ fields (tlist, "1," // tfilter // "," // tfields,
+ lines="1-9999", quit_if_missing=no,
+ print_file_name=no) |
+ unique ("STDIN", > tfile1)
+
+ }
+
+ # Create temporary file names to store the intermediate sets of images.
+
+ tfile2 = mktemp ("tmp$")
+
+ # Determine the column to be sorted on and store it in the parameter
+ # tcolumn. The files routine breaks up the fields parameter into
+ # its component parts and removes any imbedded commas.
+
+ tsort = sort
+ if (tsort == "") {
+ tcolumn = 0
+ } else if (tsort == "image") {
+ tcolumn = 1
+ } else if (tsort == tfilter) {
+ tcolumn = 2
+ } else {
+ files (tfields, sort=no, > tfile2)
+ tcolumn = 0
+ nfields = 0
+ list = tfile2
+ while (fscan (list, tstr) != EOF) {
+ nfields = nfields + 1
+ if (tsort != tstr)
+ next
+ tcolumn = nfields + 2
+ break
+ }
+ list = ""
+ delete (tfile2, verify-, default_action+, allversions+,
+ subfiles+, >& "dev$null")
+ }
+
+ # Create a temporary file name to store the sorted list.
+
+ tfile2 = mktemp ("tmp$")
+
+ # Sort the image list on the user defined column.
+
+ if (tcolumn > 0) {
+ system.sort (tfile1, column=tcolumn, ignore_white-,
+ numeric_sort+, reverse_sort-, > tfile2)
+ delete (tfile1, verify-, default_action+, allversions+, subfiles+,
+ >& "dev$null")
+ rename (tfile2, tfile1)
+ }
+
+ # Insert an explanatory message at the beginning of the temporary
+ # image list file.
+
+ concatenate ("photcal$mkimsets/imlist.key" // "," // tfile1,
+ tfile2, out_type="in_type", append=no)
+ delete (tfile1, verify-, default_action+, allversions+, subfiles+,
+ >& "dev$null")
+
+ # Allow the user to edit the temporary image list file.
+
+ if (edit)
+ edit (tfile2)
+
+ # Group the images in the image list file and optionally supply a
+ # name for each image set.
+
+ tfile1 = mktemp ("tmp$")
+ imgroup (tfile2, timsets, tidfilters, rename=rename,
+ >& tfile1, > "STDOUT")
+
+ # Remove the leading message and write the output obsparams file.
+
+ if (tobsparams != "")
+ match ("^ \#", tfile2, metacharacters+, stop+,
+ print_file_names+, > tobsparams)
+
+ # Delete the temporary file.
+
+ delete (tfile2, verify-, default_action+, allversions+, subfiles+,
+ >& "dev$null")
+
+ # Allow the user to edit the new image sets file. If review is yes
+ # prepend the error message file to the image set file and enter
+ # the editor. Other wise simply type the error messages to the
+ # standard output.
+
+ if (review) {
+ concatenate ("photcal$mkimsets/imsets.key," // tfile1 //
+ "," // timsets, tfile2, out_type="in_type", append=no)
+ edit (tfile2)
+ delete (timsets, verify-, default_action+, allversions+, subfiles+,
+ >& "dev$null")
+ match ("^<", tfile2, metacharacters+, stop+, print_file_names+) |
+ match ("^ \#", "STDIN", metacharacters+, stop+, print_file_names+,
+ > timsets)
+ delete (tfile2, verify-, default_action+, allversions+, subfiles+,
+ >& "dev$null")
+ } else
+ type (tfile1)
+
+ # Delete the temporary file.
+
+ delete (tfile1, verify-, default_action+, allversions+, subfiles+,
+ >& "dev$null")
+end
diff --git a/noao/digiphot/photcal/mkimsets/imlist.key b/noao/digiphot/photcal/mkimsets/imlist.key
new file mode 100644
index 00000000..8e15e68f
--- /dev/null
+++ b/noao/digiphot/photcal/mkimsets/imlist.key
@@ -0,0 +1,35 @@
+
+ ##############################################################################
+ # #
+ # This file is a temporary file containing the entire list of images from #
+ # which the final list of image sets wil be formed. The image name #
+ # appears in column 1. The image filter id appears in column 2. Additional #
+ # fields, if defined, appear in succeeding columns. #
+ # #
+ # At the this point the user must edit the temporary image list to 1) #
+ # remove unwanted images from the list 2) correct bad filter id values #
+ # 3) correct other bad field values, for example incorrect airmass or #
+ # exposure time values if defined 4) reorder the image names so that the #
+ # images in an observation set are adjacent to each other in the temporary #
+ # image list 4) enter an image name of "INDEF" and the correct filter id #
+ # for any missing images. #
+ # #
+ # It is not necessary to remove images which have filter ids which are #
+ # not in the filter id set as these will be removed by the grouping #
+ # process. #
+ # #
+ # Example: #
+ # #
+ # Before editing After editing #
+ # #
+ # image2 B STD1 image1 U STD1 #
+ # image3 V STD1 image2 B STD1 #
+ # image5 B STD2 image3 V STD1 #
+ # image6 V STD2 INDEF U STD2 #
+ # image7 V STD3 image5 B STD2 #
+ # image8 B STD3 image6 V STD2 #
+ # image9 U STD3 image7 U STD3 #
+ # image1 U STD1 image8 B STD3 #
+ # image9 V STD3 #
+ # #
+ ##############################################################################
diff --git a/noao/digiphot/photcal/mkimsets/imsets.key b/noao/digiphot/photcal/mkimsets/imsets.key
new file mode 100644
index 00000000..52cf7ff2
--- /dev/null
+++ b/noao/digiphot/photcal/mkimsets/imsets.key
@@ -0,0 +1,30 @@
+
+ ##############################################################################
+ # #
+ # This file is a temporary file containing the named image sets produced #
+ # by MKIMSETS, preceded by any errors or warnings produced by the image #
+ # grouping algorithm. The image set name appears in column 1 followed by #
+ # a space, colon, space and the individual member image names in filter #
+ # order, as specified by the idfilters parameter. #
+ # #
+ # At this point the user may edit the temporary image set file to 1) #
+ # correct any erroneous image set names, keeping in mind that image set #
+ # names for single standard star observations should match those in the #
+ # standard star catalog, 2) remove unwanted image sets from the image set #
+ # file, 3) correct any image sets where the grouping process did not #
+ # function correctly. It is not necessary to remove the warning and error #
+ # messages if present. They will be automatically deleted before the final #
+ # image set file is written. #
+ # #
+ # Example: #
+ # #
+ # Before editing After editing #
+ # #
+ # <Warning> Set 3 image im8 filter b is not a member of filter set U B V #
+ # #
+ # std1 : im1 im2 im3 std1 : im1 im2 im3 #
+ # std22 : im4 im5 im6 std2 : im4 im5 im6 #
+ # std3 : im7 INDEF im9 std3 : im7 im8 im9 #
+ # m92 : im10 im11 im12 #
+ # #
+ ##############################################################################
diff --git a/noao/digiphot/photcal/mkimsets/mkpkg b/noao/digiphot/photcal/mkimsets/mkpkg
new file mode 100644
index 00000000..cd7264fe
--- /dev/null
+++ b/noao/digiphot/photcal/mkimsets/mkpkg
@@ -0,0 +1,10 @@
+# The MKPKG file for the mkimsets subdirectory.
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ t_imgroup.x <fset.h> <ctotok.h>
+ ;
diff --git a/noao/digiphot/photcal/mkimsets/t_imgroup.x b/noao/digiphot/photcal/mkimsets/t_imgroup.x
new file mode 100644
index 00000000..fd560cff
--- /dev/null
+++ b/noao/digiphot/photcal/mkimsets/t_imgroup.x
@@ -0,0 +1,430 @@
+include <fset.h>
+include <ctotok.h>
+
+define IMG_DEFSZSET 15
+define IMG_DEFSZNAME 79
+
+# Reformat a file containing a list of images into an image set file using
+# a set definition field and a list of permitted set definition values.
+# The input image list is assumed to have the image name in column 1 and the
+# value of the set definition field in column 2. All the rest of the columns
+# are ignored. The image set definition field is checked against the list
+# of permitted set defintion field values and the image is rejected if the
+# two do not match. The number of permitted values defines the size of each
+# set.
+
+procedure t_imgroup ()
+
+pointer imlist # pointer to the input image list
+pointer imsetlist # pointer to the output image set
+pointer setvals # pointer to the permitted list of set values
+int rename # prompt the user for image set names
+
+int in, out, nvalues
+pointer sp, valnames
+bool clgetb()
+int btoi(), open(), ph_listset()
+
+begin
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (imlist, SZ_FNAME, TY_CHAR)
+ call salloc (imsetlist, SZ_FNAME, TY_CHAR)
+ call salloc (setvals, SZ_FNAME, TY_CHAR)
+
+ # Get the parameters.
+ call clgstr ("imlist", Memc[imlist], SZ_FNAME)
+ call clgstr ("imsetlist", Memc[imsetlist], SZ_FNAME)
+ call clgstr ("setvalues", Memc[setvals], SZ_FNAME)
+ rename = btoi (clgetb ("rename"))
+
+ # Open the input and output files.
+ in = open (Memc[imlist], READ_ONLY, TEXT_FILE)
+ out = open (Memc[imsetlist], NEW_FILE, TEXT_FILE)
+
+ # Group the sets.
+ valnames = NULL
+ nvalues = ph_listset (Memc[setvals], valnames, IMG_DEFSZNAME,
+ IMG_DEFSZSET)
+ if (nvalues > 0)
+ call ph_group (in, out, Memc[setvals], Memc[valnames],
+ IMG_DEFSZNAME, nvalues, rename)
+ else
+ call eprintf (
+ "<Error>: The list of permitted set values is empty\n")
+
+ # Close files.
+ call close (in)
+ call close (out)
+
+ if (valnames != NULL)
+ call mfree (valnames, TY_CHAR)
+ call sfree (sp)
+end
+
+
+# PH_LISTSET -- Extract the individual set defintion values.
+
+int procedure ph_listset (setvals, values, max_lvalue, def_nvalues)
+
+char setvals[ARB] # the list of set values
+pointer values # pointer to the array of extracted names
+int max_lvalue # maximum length of a value
+int def_nvalues # the default number of set values
+
+int ip, tp, op, token, nc, bufsize, vptr
+pointer sp, temp
+int ctowrd(), ctotok(), strlen()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (temp, SZ_LINE, TY_CHAR)
+ bufsize = def_nvalues
+ call malloc (values, (max_lvalue + 1) * bufsize, TY_CHAR)
+
+ # Decode the individual values.
+ nc = 0
+ ip = 1
+ vptr = values
+ while (setvals[ip] != EOS) {
+
+ # Extract whitespace separated strings.
+ if (ctowrd (setvals, ip, Memc[temp], SZ_LINE) <= 0)
+ break
+
+ # Initialize token extraction.
+ tp = 1
+ op = 1
+
+ # Check the extracted string for imbedded punctuation.
+ # Only commas and semi-colons are recognized.
+
+ while (Memc[temp+tp-1] != EOS) {
+ token = ctotok (Memc[temp], tp, Memc[vptr+op-1], max_lvalue)
+ if (Memc[vptr+op-1] == EOS)
+ next
+ if (token == TOK_UNKNOWN || token == TOK_CHARCON)
+ next
+ if ((token == TOK_PUNCTUATION) && (Memc[vptr+op-1] == ',' ||
+ Memc[vptr+op-1] == ';')) {
+ Memc[vptr+op-1] = EOS
+ nc = nc + 1
+ op = 1
+ } else
+ op = op + strlen (Memc[vptr+op-1])
+ vptr = values + nc * (max_lvalue + 1)
+ if (nc < def_nvalues)
+ next
+ bufsize = bufsize + def_nvalues
+ call realloc (values, (max_lvalue + 1) * bufsize, TY_CHAR)
+ }
+
+ if (op > 1)
+ nc = nc + 1
+ vptr = values + nc * (max_lvalue + 1)
+ if (nc < def_nvalues)
+ next
+ bufsize = bufsize + def_nvalues
+ call realloc (values, (max_lvalue + 1) * bufsize, TY_CHAR)
+ }
+
+ call sfree (sp)
+
+ # Return the number of values successfully decoded.
+ call realloc (values, (max_lvalue + 1) * nc, TY_CHAR)
+ return (nc)
+end
+
+
+# PH_GROUP -- Group the data into sets.
+
+procedure ph_group (in, out, filters, values, max_lvalue, nvalues, rename)
+
+int in # the input file descriptor
+int out # the output file descriptor
+char filters[ARB] # the filter set
+char values[max_lvalue,ARB] # list of permitted set values
+int max_lvalue # maximum length of a set value
+int nvalues # the number of permitted values
+int rename # prompt for the image set names
+
+int i, numindex, ns, nsets, op, num
+pointer sp, image, setval, name, tname, index, record
+int fscan(), nscan(), ph_member(), gstrcpy()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (setval, SZ_LINE, TY_CHAR)
+ call salloc (tname, SZ_FNAME, TY_CHAR)
+ call salloc (name, SZ_FNAME, TY_CHAR)
+ call salloc (index, nvalues, TY_INT)
+ call salloc (record, SZ_LINE, TY_CHAR)
+
+ # Issue explanatory message.
+ if (rename == YES) {
+ call printf ("\n")
+ call printf ("Enter/Confirm Names for Each Image Set\n")
+ call printf ("\n")
+ }
+
+ # Initialize.
+ ns = 0
+ nsets = 0
+ op = 1
+ call amovki (0, Memi[index], nvalues)
+
+ # Read the input file.
+ while (fscan (in) != EOF) {
+
+ # Get the image name and set definition from columns 1 and 2.
+ call gargwrd (Memc[image], SZ_FNAME)
+ call gargwrd (Memc[setval], SZ_LINE)
+ if (nscan() < 1)
+ next
+ if (Memc[image] == '#')
+ next
+ if (nscan() < 2)
+ Memc[setval] = EOS
+
+ # Check for set membership.
+ if ((nvalues == 1) && (values[1,1] == EOS))
+ num = 1
+ else {
+ num = ph_member (Memc[setval], values, max_lvalue, nvalues)
+ if (num == 0) {
+ call eprintf ("<Warning>: Image %s filter id %s ")
+ call pargstr (Memc[image])
+ call pargstr (Memc[setval])
+ call eprintf (
+ " does not belong to the filter set %s\n")
+ call pargstr (filters)
+ next
+ }
+ }
+
+ # Check to see if a particular slot is already filled.
+ # Terminate the set if a duplicate set member is found.
+
+ numindex = Memi[index+num-1]
+ if (numindex != 0) {
+ call eprintf ("<Warning> Set %d image %s has the same ")
+ call pargi (nsets + 1)
+ call pargstr (Memc[image])
+ call eprintf ("filter id %s as image %s\n")
+ call pargstr (Memc[setval])
+ call pargstr (Memc[record+numindex-1])
+ do i = 1, nvalues {
+ if (Memi[index+i-1] != 0)
+ next
+ Memi[index+i-1] = op
+ op = op + gstrcpy ("INDEF", Memc[record+op-1],
+ SZ_LINE - op + 1) + 1
+ ns = ns + 1
+ }
+ } else {
+ Memi[index+num-1] = op
+ ns = ns + 1
+ op = op + gstrcpy (Memc[image], Memc[record+op-1],
+ SZ_LINE - op + 1) + 1
+ }
+
+ # Write out the new set and begin working on the next set.
+ if (ns == nvalues) {
+
+ nsets = nsets + 1
+
+ # Get the set name.
+ call sprintf (Memc[tname], SZ_LINE, "OBS%d")
+ call pargi (nsets)
+ if (rename == YES) {
+ call ph_swrite (STDOUT, Memc[tname], Memc[record],
+ Memi[index], nvalues)
+ call ph_rname (Memc[tname], Memc[name], SZ_LINE)
+ } else
+ call strcpy (Memc[tname], Memc[name], SZ_LINE)
+
+ # Write out the new set.
+ call ph_swrite (out, Memc[name], Memc[record], Memi[index],
+ nvalues)
+
+ # Reinitialize.
+ ns = 0
+ op = 1
+ call amovki (0, Memi[index], nvalues)
+ }
+
+ if (numindex != 0) {
+ Memi[index+num-1] = op
+ ns = ns + 1
+ op = op + gstrcpy (Memc[image], Memc[record+op-1],
+ SZ_LINE - op + 1) + 1
+ }
+ }
+
+ # Write out the last record to the output file.
+ if (ns > 0) {
+
+ # Fill in the missing values.
+ do i = 1, nvalues {
+ if (Memi[index+i-1] != 0)
+ next
+ Memi[index+i-1] = op
+ op = op + gstrcpy ("INDEF", Memc[record+op-1],
+ SZ_LINE - op + 1) + 1
+ }
+
+ nsets = nsets + 1
+
+ # Prompt for the image set name.
+ call sprintf (Memc[tname], SZ_LINE, "OBS%d")
+ call pargi (nsets)
+ if (rename == YES) {
+ call ph_swrite (STDOUT, Memc[tname], Memc[record], Memi[index],
+ nvalues)
+ call ph_rname (Memc[tname], Memc[name], SZ_LINE)
+ } else
+ call strcpy (Memc[tname], Memc[name], SZ_LINE)
+
+ # Write the record.
+ call ph_swrite (out, Memc[name], Memc[record], Memi[index],
+ nvalues)
+ }
+
+ # Warn the user if the set is empty.
+ if (nsets <= 0)
+ call eprintf ("\n<Warning> The image set file is empty\n\n")
+ else
+ call eprintf ("\n")
+
+ call sfree (sp)
+end
+
+
+# PH_MEMBER -- Test whether the string belongs to a permitted list
+# of values.
+
+int procedure ph_member (setval, values, max_lvalue, nvalues)
+
+char setval[ARB] # the set value
+char values[max_lvalue,ARB] # the permitted list of possible set values
+int max_lvalue # maximum length of the set value
+int nvalues # the number of set values
+
+int nc, i
+bool streq()
+
+begin
+ nc = 0
+ do i = 1, nvalues {
+ if (streq (setval, values[1,i]))
+ nc = i
+ }
+
+ return (nc)
+end
+
+
+# PH_SWRITE -- Write out the finshed set to a file.
+
+procedure ph_swrite (out, name, record, index, nvalues)
+
+int out # output file descriptor
+char name[ARB] # the name of the output field
+char record[ARB] # the name of the output record
+int index[ARB] # array of indices
+int nvalues # number of values
+
+pointer sp, str
+int i
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ call fprintf (out, "%s :")
+ call pargstr (name)
+
+ do i = 1, nvalues {
+ call ph_imroot (record[index[i]], Memc[str], SZ_FNAME)
+ call fprintf (out, " %s")
+ #call pargstr (record[index[i]])
+ call pargstr (Memc[str])
+ }
+
+ call fprintf (out, "\n")
+
+ call sfree (sp)
+end
+
+
+# PH_RNAME -- Prompt the user for a field name.
+
+procedure ph_rname (tname, name, max_lname)
+
+char tname[ARB] # temporary input name
+char name[ARB] # the final output name
+int max_lname # the maximum length of the name
+
+int scan()
+
+begin
+ # Issue a prompt to the user
+ call printf ("\tEnter new name for field %s (name, <CR>=ok): ")
+ call pargstr (tname)
+ call flush (STDOUT)
+
+ # Get the new value
+ if (scan () == EOF)
+ name[1] = EOS
+ else
+ call gargwrd (name, max_lname)
+ if (name[1] == EOS)
+ call strcpy (tname, name, max_lname)
+
+ call printf ("\n")
+end
+
+
+# PH_IMROOT -- Fetch the root image name minus the directory specification
+# and the section notation.
+
+procedure ph_imroot (image, root, maxch)
+
+char image[ARB] # image specification
+char root[ARB] # output root name
+int maxch # maximum number of characters
+
+pointer sp, imroot, kernel, section, str
+int clindex, clsize, nchars
+int fnldir()
+
+begin
+ call smark (sp)
+ call salloc (imroot, SZ_PATHNAME, TY_CHAR)
+ call salloc (kernel, SZ_FNAME, TY_CHAR)
+ call salloc (section, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_PATHNAME, TY_CHAR)
+
+ call imparse (image, Memc[imroot], SZ_PATHNAME, Memc[kernel], SZ_FNAME,
+ Memc[section], SZ_FNAME, clindex, clsize)
+ nchars = fnldir (Memc[imroot], Memc[str], SZ_PATHNAME)
+ if (clindex >= 0) {
+ call sprintf (root, maxch, "%s[%d]%s%s")
+ call pargstr (Memc[imroot+nchars])
+ call pargi (clindex)
+ call pargstr (Memc[kernel])
+ call pargstr (Memc[section])
+ } else {
+ call sprintf (root, maxch, "%s%s%s")
+ call pargstr (Memc[imroot+nchars])
+ call pargstr (Memc[kernel])
+ call pargstr (Memc[section])
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/photcal/mknobsfile.cl b/noao/digiphot/photcal/mknobsfile.cl
new file mode 100644
index 00000000..5f827ded
--- /dev/null
+++ b/noao/digiphot/photcal/mknobsfile.cl
@@ -0,0 +1,108 @@
+# MKNOBSFILE -- Create a catalog of observations suitable for input to
+# FITPARAMS or the evaluation routines EVALFIT and INVERTFIT from a list of
+# APPHOT/DAOPHOT text or ST table databases. This script is optimized for
+# creating an observations file from a large number of observations of
+# single stars. MKNOBSFILE is generally the preprocessor of choice for standard
+# star observations.
+
+procedure mknobsfile (photfiles, idfilters, imsets, observations)
+
+file photfiles {prompt="The input list of APPHOT/DAOPHOT databases"}
+string idfilters {prompt="The list of filter ids"}
+file imsets {prompt="The input image set file"}
+file observations {prompt="The output observations file"}
+bool wrap {yes, prompt="Format output file for easy reading ?"}
+file obsparams {"", prompt="The input observing parameters file"}
+string obscolumns {"2 3 4 5", prompt="The format of obsparams"}
+real minmagerr {0.001, min=0.0, prompt="The minimum error magnitude"}
+file shifts {"", prompt="The input x and y coordinate shifts file"}
+file apercors {"", prompt="The input aperture corrections file"}
+int aperture {1,
+ prompt="The aperture number of the extracted magnitude"}
+real tolerance {5.0,
+ prompt="The tolerance in pixels for position matching"}
+bool allfilters {no, prompt="Output only objects matched in all filters"}
+bool verify {no, prompt="Verify interactive user input ?"}
+bool verbose {yes, prompt="Print status, warning and error messages ?"}
+
+begin
+ # Declare local variables.
+ string tfiles, timsets, tidfilters, tobsfile, tformat, tobscolumns
+ string tdatafile, tinfields
+
+ # Get the parameters and test for the existence of various files.
+
+ tfiles = photfiles
+ tidfilters = idfilters
+
+ timsets = imsets
+ if (! access (timsets))
+ error (0, "The image set file " // timsets // " does not exist")
+
+ tobsfile = observations
+ if (access (tobsfile))
+ error (0,
+ "The output catalog file " // tobsfile // " already exists")
+ tformat = "f" // tobsfile // ".dat"
+ if (access (tformat))
+ delete (tformat, go_ahead+, verify-, default_action+,
+ allversions+, subfiles+, > "dev$null")
+
+ if (obsparams == "") {
+ tobscolumns = ""
+ } else {
+ tobscolumns = obscolumns
+ if (! access (obsparams))
+ error (0,
+ "The obsparams file " // obsparams // " does not exist")
+ }
+
+ if (shifts != "") {
+ if (! access (shifts))
+ error (0,
+ "The shifts file " // shifts // " does not exist")
+ }
+
+ if (apercors != "") {
+ if (! access (apercors))
+ error (0,
+ "The apercors file " // apercors // " does not exist")
+ }
+
+ # Create temporary file names to store the intermediate image list.
+ tdatafile = mktemp ("tmp$")
+
+ # Change columns named "MAG" and "MERR" to "MAG[1]" and "MERR[1]"
+ # in any ST tables files. Non-ST format files are skipped.
+
+ tbcrename (tfiles, "MAG,MERR", "MAG\[1],MERR\[1]")
+
+ # Add the image, ifilter, itime and xairmass columns to any
+ # files in ST tables format. Non-ST format files are skipped.
+
+ tbkeycol (tfiles, "IMAGE,IFILTER,ITIME,XAIRMASS,OTIME")
+
+ # Construct the string describing the fields to be extracted
+ # making sure to specify the correct aperture number. Extract
+ # the data and store the results in the temporary file tdatafile.
+
+ tinfields = ",IMAGE,XCENTER,YCENTER," //
+ "MAG[" // aperture // "]" // ",MERR[" // aperture // "]," //
+ "MAG\[" // aperture // "]" // ",MERR\[" // aperture // "]," //
+ "IFILTER,XAIRMASS,OTIME,ITIME"
+ pdump (tfiles, tinfields, "yes", headers=no, parameters=yes,
+ > tdatafile)
+
+ # Create the observations file.
+
+ obsfile (tdatafile, "1,2,3,6,9,7,8,4,5,0", tidfilters, timsets,
+ tobsfile, wrap=wrap, obsparams=obsparams, minmagerr=minmagerr,
+ normtime=no, tolerance=tolerance, allfilters=allfilters,
+ obscolumns="1," // tobscolumns, shifts=shifts, apercors=apercors,
+ verify=verify, verbose=verbose)
+
+ # Delete the temporary file.
+
+ delete (tdatafile, go_ahead+, verify-, default_action+,
+ allversions+, subfiles+, > "dev$null")
+end
diff --git a/noao/digiphot/photcal/mkobsfile.cl b/noao/digiphot/photcal/mkobsfile.cl
new file mode 100644
index 00000000..c81dca6c
--- /dev/null
+++ b/noao/digiphot/photcal/mkobsfile.cl
@@ -0,0 +1,152 @@
+# MKOBSFILE -- Create a catalog of observations suitable for input to
+# FITPARAMS or the evaluation routines EVALFIT and INVERTFIT from a list of
+# APPHOT/DAOPHOT text databases.
+
+procedure mkobsfile (photfiles, idfilters, observations)
+
+file photfiles {prompt="The input list of APPHOT/DAOPHOT databases"}
+string idfilters {prompt="The list of filter ids"}
+file observations {prompt="The output observations file"}
+bool wrap {yes, prompt="Format the output file for easy reading ?"}
+file imsets {"STDIN", prompt="The input image set file"}
+file obsparams {"", prompt="The observing parameters file"}
+string obscolumns {"2 3 4 5", prompt="The format of obsparams"}
+real minmagerr {0.001, min=0.0, prompt="The minimum magnitude error"}
+file shifts {"STDIN", prompt="The x and y coordinate shifts file"}
+file apercors {"STDIN", prompt="The aperture corrections file"}
+int aperture {1,
+ prompt="The aperture number of the extracted magnitude"}
+real tolerance {5.0,
+ prompt="The tolerance in pixels for position matching"}
+bool allfilters {no, prompt="Output only objects matched in all filters"}
+bool verify {no, prompt="Verify interactive user input ?"}
+bool verbose {yes, prompt="Print status, warning and error messages ?"}
+
+begin
+ # Declare local variables.
+ string tfiles, tidfilters, tobsfile, tformat
+ string iimsets, iobsparams, ishifts, iapercors
+ string timsets, tobsparams, tobscolumns, tshifts, tapercors
+ string tdatafile, tinfields
+
+ # Get the parameters.
+ tfiles = photfiles
+ tidfilters = idfilters
+
+ tobsfile = observations
+ if (access (tobsfile))
+ error (0,
+ "The output catalog file " // tobsfile // " already exists")
+ tformat = "f" // tobsfile // ".dat"
+ if (access (tformat))
+ delete (tformat, go_ahead+, verify-, default_action+,
+ allversions+, subfiles+)
+
+ iimsets = imsets
+ if (iimsets != "") {
+ if (iimsets == "STDIN")
+ timsets = mktemp ("tmp$")
+ else if (! access (iimsets))
+ error (0, "The image set file " // timsets // " does not exist")
+ else
+ timsets = iimsets
+ } else
+ timsets = ""
+
+ iobsparams = obsparams
+ if (iobsparams != "") {
+ if (iobsparams == "STDIN") {
+ tobsparams = mktemp ("tmp$")
+ tobscolumns = "2 3 4 5"
+ } else if (! access (iobsparams)) {
+ error (0, "The obsparams file " // iobsparams //
+ " does not exist")
+ } else {
+ tobsparams = iobsparams
+ tobscolumns = obscolumns
+ }
+ } else {
+ tobsparams = ""
+ tobscolumns = "2 3 4 5"
+ }
+
+ ishifts = shifts
+ if (ishifts != "") {
+ if (ishifts == "STDIN")
+ tshifts = mktemp ("tmp$")
+ else if (! access (ishifts))
+ error (0,
+ "The shifts file " // ishifts // " does not exist")
+ else
+ tshifts = ishifts
+ } else
+ tshifts = ""
+
+ iapercors = apercors
+ if (iapercors != "") {
+ if (iapercors == "STDIN")
+ tapercors = mktemp ("tmp$")
+ else if (! access (iapercors))
+ error (0,
+ "The apercors file " // iapercors // " does not exist")
+ else
+ tapercors = iapercors
+ } else
+ tapercors = ""
+
+ # Query the user for input.
+ mkphotcors (timsets, tidfilters, tobsparams, tshifts, tapercors,
+ obscolumns=tobscolumns, verify=verify, verbose=verbose)
+
+ # Create temporary file names to store the intermediate image list.
+ tdatafile = mktemp ("tmp$")
+
+ # Change columns named "MAG" and "MERR" to "MAG[1]" and "MERR[1]"
+ # in any ST tables databases.
+
+ tbcrename (tfiles, "MAG,MERR", "MAG\[1],MERR\[1]")
+
+ # Add the image, ifilter, itime, and xairmass columns to any files
+ # in ST tables format.
+
+ tbkeycol (tfiles, "IMAGE,IFILTER,ITIME,XAIRMASS,OTIME")
+
+ # Construct the string describing the fields to be extracted
+ # making sure to specify the correct aperture number. Extract
+ # the data, sort on the image name which is in the first column,
+ # remove any duplicate records, and store the results in the
+ # temporary file tdatafile.
+
+ tinfields = ",IMAGE,XCENTER,YCENTER," //
+ "MAG[" // aperture // "]" // ",MERR[" // aperture // "]," //
+ "MAG\[" // aperture // "]" // ",MERR\[" // aperture // "]," //
+ "IFILTER,XAIRMASS,OTIME,ITIME"
+
+ pdump (tfiles, tinfields, "yes", headers=no, parameters=yes,
+ > tdatafile)
+
+ # Create the output catalog.
+
+ obsfile (tdatafile, "1,2,3,6,9,7,8,4,5,0", tidfilters, timsets,
+ tobsfile, wrap=wrap, obsparams=tobsparams, minmagerr=minmagerr,
+ normtime=no, tolerance=tolerance, allfilters=allfilters,
+ obscolumns="1," // tobscolumns, shifts=tshifts,
+ apercors=tapercors, verify-, verbose=verbose)
+
+ # Delete the temporary files.
+
+ delete (tdatafile, go_ahead+, verify-, default_action+, allversions+,
+ subfiles+)
+ if (iimsets == "STDIN")
+ delete (timsets, go_ahead+, verify-, default_action+,
+ allversions+, subfiles+)
+ if (iobsparams == "STDIN")
+ delete (tobsparams, go_ahead+, verify-, default_action+,
+ allversions+, subfiles+)
+ if (ishifts == "STDIN")
+ delete (tshifts, go_ahead+, verify-, default_action+,
+ allversions+, subfiles+)
+ if (iapercors == "STDIN")
+ delete (tapercors, go_ahead+, verify-, default_action+,
+ allversions+, subfiles+)
+end
diff --git a/noao/digiphot/photcal/mkobsfile/apfile.key b/noao/digiphot/photcal/mkobsfile/apfile.key
new file mode 100644
index 00000000..b6cdd1f6
--- /dev/null
+++ b/noao/digiphot/photcal/mkobsfile/apfile.key
@@ -0,0 +1,36 @@
+ Keystroke Commands
+
+? Print help
+w Print computed aperture correction
+c Print coordinates of star nearest cursor
+f Compute a new fit
+d Delete point(s) nearest the cursor
+u Undelete point(s) nearest the cursor
+m Plot the observed and model cog versus radius
+r Plot the cog residuals versus radius
+b Plot the cog residuals versus magnitude
+x Plot the cog residuals versus the x coordinate
+y Plot the cog residuals versus the y coordinate
+a Plot the aperture correction versus radius
+g Redraw the current plot
+n Move to the next image
+p Move to the previous image
+q Quit task
+
+ Colon commands
+
+:show parameters Show the initial cog model parameter values
+:show model Show the fitted cog model parameters
+:show seeing Show the computed seeing radii for all images
+:image [value] Show/set the image to be analyzed
+
+ Colon Parameter Editing Commands
+
+:nparams [value] Show/set the number of parameters in model to fit
+:swings [value] Show/set initial power law slope of stellar wings
+:pwings [value] Show/set fraction of total power in stellar wings
+:pgauss [value] Show/set fraction of total core power in gaussian
+:rgescale [value] Show/set ratio of exponential to gaussian radial scales
+:xwings [values] Show/set the extinction coefficient
+:smallap [value] The index of the smallest aperture
+:largeap [value] The index of the largest aperture
diff --git a/noao/digiphot/photcal/mkobsfile/dinvers.f b/noao/digiphot/photcal/mkobsfile/dinvers.f
new file mode 100644
index 00000000..5b1d8a5f
--- /dev/null
+++ b/noao/digiphot/photcal/mkobsfile/dinvers.f
@@ -0,0 +1,53 @@
+c
+c subroutine dinver (a, max, n, iflag)
+c
+c Arguments
+c
+c a (input/output) is a square matrix of dimension N. The inverse
+c of the input matrix A is returned in A.
+c
+c max (input) is the size assigned to the matrix A in the calling
+c routine. It's needed for the dimension statement below.
+c
+c iflag (output) is an error flag. iflag = 1 if the matrix could not
+c be inverted; iflag = 0 if it could.
+c
+ subroutine dinver (a, max, n, iflag)
+c
+ implicit none
+ integer max, n, iflag
+ double precision a(max,max)
+ integer i, j, k
+c
+ iflag = 0
+ i = 1
+ 300 if (a(i,i) .eq. 0.0d0) go to 9100
+ a(i,i) = 1.0e0 / a(i,i)
+ j = 1
+ 301 if (j .eq. i) go to 304
+ a(j,i) = -a(j,i) * a(i,i)
+ k = 1
+ 302 if (k .eq. i) go to 303
+ a(j,k) = a(j,k) + a(j,i) * a(i,k)
+ 303 if (k .eq. n) go to 304
+ k = k + 1
+ go to 302
+ 304 if (j .eq. n) go to 305
+ j = j + 1
+ go to 301
+ 305 k = 1
+ 306 if (k .eq. i) go to 307
+ a(i,k) = a(i,k) * a(i,i)
+ 307 if (k .eq. n) go to 308
+ k = k + 1
+ go to 306
+ 308 if (i .eq. n) return
+ i = i+1
+ go to 300
+c
+c Error: zero on the diagonal.
+c
+ 9100 iflag = 1
+ return
+c
+ end
diff --git a/noao/digiphot/photcal/mkobsfile/mkpkg b/noao/digiphot/photcal/mkobsfile/mkpkg
new file mode 100644
index 00000000..6ba9935f
--- /dev/null
+++ b/noao/digiphot/photcal/mkobsfile/mkpkg
@@ -0,0 +1,19 @@
+# The MKPKG file for the mkobsfile subdirectory.
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ t_obsfile.x "../lib/obsfile.h" <fset.h> <ctotok.h> <ctype.h>
+ t_mkphotcors.x "../lib/obsfile.h"
+ phimtable.x "../lib/obsfile.h" <fset.h>
+ phsort.x "../lib/obsfile.h"
+ phmatch.x <mach.h> "../lib/obsfile.h"
+ t_apfile.x "../lib/apfile.h" <fset.h> <ctotok.h> <ctype.h>
+ phaimtable.x "../lib/apfile.h" <fset.h>
+ phagrow.x "../lib/apfile.h" <time.h> <mach.h> <fset.h>
+ phaigrow.x "../lib/apfile.h" <time.h> <mach.h> <gset.h>
+ dinvers.f
+ ;
diff --git a/noao/digiphot/photcal/mkobsfile/phagrow.x b/noao/digiphot/photcal/mkobsfile/phagrow.x
new file mode 100644
index 00000000..a8c6dfce
--- /dev/null
+++ b/noao/digiphot/photcal/mkobsfile/phagrow.x
@@ -0,0 +1,1982 @@
+include <time.h>
+include <mach.h>
+include <fset.h>
+include "../lib/apfile.h"
+
+
+# PH_AGROW - Compute the curve of growth using the data from the input
+# photometry files, optional airmasses from the airmass file, and the
+# initial values of the parameters.
+
+procedure ph_agrow (apcat, magfd, logfd, mgd, imtable, id, x, y, nap, rap,
+ mag, merr, naperts, params, lterms, smallap, largeap)
+
+int apcat # the aperture correction file descriptor
+int magfd # the output magnitude file descriptor
+int logfd # the log file descriptor
+pointer mgd # pointer to the plot metacode file
+pointer imtable # pointer to the image symbol table
+int id[ARB] # the star ids
+real x[ARB] # the star x coordinates
+real y[ARB] # the star y coordinates
+int nap[ARB] # the array of aperture numbers
+real rap[naperts,ARB] # input array of aperture radii
+real mag[naperts,ARB] # input array of magnitudes / differences
+real merr[naperts,ARB] # input array of magnitude errors
+int naperts # the number of input apertures
+double params[ARB] # the initial values of the parameters
+int lterms # the number of terms to be fit
+int smallap # the small aperture number
+int largeap # the large aperture number
+
+int nimages
+pointer agr
+int stnsymbols()
+int ph_amfit()
+
+begin
+ if (logfd != NULL)
+ call ph_logtitle (logfd, apcat)
+
+ nimages = stnsymbols (imtable, 0)
+ if (nimages <= 0) {
+ call printf ("Error: There is no input data to fit\n")
+ if (logfd != NULL)
+ call fprintf (logfd, "There is no input data to fit\n")
+ return
+ }
+
+ # Allocate memory required for fitting.
+ call ph_ameminit (agr, lterms, naperts)
+
+ # Fit the seeing radii and the cog model parameters.
+ if (ph_amfit (imtable, agr, nap, rap, mag, merr, naperts, params,
+ lterms) == ERR) {
+ call printf ("Error: The cog model fit did not converge\n")
+ if (logfd != NULL) {
+ call ph_ishow (logfd, params, lterms)
+ call ph_pshow (logfd, agr, lterms)
+ call ph_rshow (logfd, imtable)
+ call fprintf (logfd,
+ "Error: The cog model fit did not converge\n")
+ }
+ } else {
+ if (logfd != NULL) {
+ call ph_ishow (logfd, params, lterms)
+ call ph_pshow (logfd, agr, lterms)
+ call ph_rshow (logfd, imtable)
+ }
+ call ph_aeval (imtable, agr, apcat, magfd, logfd, mgd, id, x, y,
+ nap, rap, mag, merr, naperts, smallap, largeap)
+ if (logfd != NULL)
+ call ph_tfshow (logfd, agr, naperts)
+ }
+
+ # Free memory required for fitting.
+ call ph_amemfree (agr)
+end
+
+
+# PH_LOGTITLE -- Print the title for the new log file entry
+
+procedure ph_logtitle (logfd, apcat)
+
+int logfd # the log file descriptor
+int apcat # the aperture correction file descriptor
+
+pointer sp, afname, date
+long clktime()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (afname, SZ_FNAME, TY_CHAR)
+ call salloc (date, SZ_TIME, TY_CHAR)
+
+ # Get the file name and the times.
+ call fstats (apcat, F_FILENAME, Memc[afname], SZ_FNAME)
+ call cnvtime (clktime (long(0)), Memc[date], SZ_TIME)
+
+ call fprintf (logfd, "NEW LOGFILE ENTRY AT: %s\n")
+ call pargstr (Memc[date])
+ call fprintf (logfd, "APFILE: %s\n\n")
+ call pargstr (Memc[afname])
+
+ call sfree (sp)
+end
+
+
+# PH_AMEMINIT -- Allocate memory for doing the fit.
+
+procedure ph_ameminit (agr, lterms, naperts)
+
+pointer agr # pointer to the fitting structure
+int lterms # the number of terms to fit
+int naperts # the number of apertures
+
+begin
+ call malloc (agr, LEN_AGRSTRUCT, TY_STRUCT)
+
+ call malloc (AGR_DM(agr), naperts, TY_DOUBLE)
+ call malloc (AGR_DDDR(agr), naperts, TY_DOUBLE)
+ call malloc (AGR_T(agr), lterms * naperts, TY_DOUBLE)
+ call malloc (AGR_U(agr), lterms * lterms, TY_DOUBLE)
+ call malloc (AGR_V(agr), lterms, TY_DOUBLE)
+ call malloc (AGR_POLD(agr), lterms, TY_DOUBLE)
+ call malloc (AGR_DP(agr), lterms, TY_DOUBLE)
+ call malloc (AGR_PARAMS(agr), MAX_MTERMS, TY_DOUBLE)
+ call malloc (AGR_PERRORS(agr), MAX_MTERMS, TY_DOUBLE)
+ call malloc (AGR_PCLAMPS(agr), MAX_MTERMS, TY_DOUBLE)
+
+ call malloc (AGR_RBAR(agr), naperts, TY_REAL)
+ call malloc (AGR_W(agr), naperts, TY_REAL)
+ call malloc (AGR_THEO(agr), naperts, TY_REAL)
+ call malloc (AGR_ADOPT(agr), naperts, TY_REAL)
+ call malloc (AGR_WOBS(agr), naperts, TY_REAL)
+ call malloc (AGR_OBS(agr), naperts, TY_REAL)
+ call malloc (AGR_WADO(agr), naperts, TY_REAL)
+
+ call malloc (AGR_CUM(agr), naperts + 1, TY_REAL)
+ call malloc (AGR_TCUM(agr), naperts + 1, TY_REAL)
+ call malloc (AGR_WCUM(agr), naperts + 1, TY_REAL)
+ call malloc (AGR_MAGS(agr), naperts, TY_REAL)
+ call malloc (AGR_CMAGS(agr), naperts, TY_REAL)
+ call malloc (AGR_TMAGS(agr), naperts, TY_REAL)
+ call malloc (AGR_WMAGS(agr), naperts, TY_REAL)
+
+ call calloc (AGR_AVE(agr), naperts, TY_REAL)
+ call calloc (AGR_RESID(agr), naperts, TY_REAL)
+ call calloc (AGR_RESSQ(agr), naperts, TY_REAL)
+ call calloc (AGR_WR(agr), naperts, TY_REAL)
+ call calloc (AGR_TAVE(agr), naperts, TY_REAL)
+ call calloc (AGR_TRESID(agr), naperts, TY_REAL)
+ call calloc (AGR_TRESSQ(agr), naperts, TY_REAL)
+ call calloc (AGR_TWR(agr), naperts, TY_REAL)
+end
+
+
+# PH_AMFIT -- Fit the seeing disk widths and the model parameters.
+
+int procedure ph_amfit (imtable, agr, nap, rap, mag, merr, naperts, params,
+ lterms)
+
+pointer imtable # pointer to the image symbol table
+pointer agr # pointer to the fitting structure
+int nap[ARB] # the array of aperture numbers
+real rap[naperts,ARB] # input array of aperture radii
+real mag[naperts,ARB] # input array of magnitudes / differences
+real merr[naperts,ARB] # input array of magnitude errors
+int naperts # the number of input apertures
+double params[ARB] # the parameters to be fit
+int lterms # number of terms to fit
+
+double pold, sumd, sumw, sumn, sumr, sumy, old
+int niter, i, j, k, nimages, ipow, nterms, iflag, ntimes, ngood
+pointer sp, sym, symbol
+real gain, rold, rclamp, dr
+int stnsymbols()
+pointer sthead(), stnext()
+
+begin
+ nimages = stnsymbols (imtable, 0)
+ if (nimages <= 0)
+ return (ERR)
+
+ # Allocate temporary space
+ call smark (sp)
+ call salloc (sym, nimages, TY_POINTER)
+
+ # Order the symbol table.
+ symbol = sthead (imtable)
+ do k = nimages, 1, -1 {
+ Memi[sym+k-1] = symbol
+ symbol = stnext (imtable, symbol)
+ }
+
+ # Initialize some variables
+ ipow = 1
+ nterms = 0
+ gain = 0.0
+ pold = 0.0d0
+ call aclrd (Memd[AGR_POLD(agr)], lterms)
+ call ph_apinit (params, Memd[AGR_PARAMS(agr)], Memd[AGR_PERRORS(agr)],
+ Memd[AGR_PCLAMPS(agr)])
+
+ # Compute an improved value for ro and for the stellar profile
+ # model parameters.
+
+ for (niter = 1; niter <= AGR_ITMAX; niter = niter + 1) {
+
+ sumd = 0.0d0
+ sumw = 0.0d0
+ sumn = 0.0d0
+
+ # Compute the number of terms to be fit this iteration.
+ call ph_anterms (niter, lterms, gain, nterms)
+
+ # Zero the accumulation matrix and vector
+ call aclrd (Memd[AGR_U(agr)], lterms * lterms)
+ call aclrd (Memd[AGR_V(agr)], lterms)
+
+ do k = 1, nimages {
+
+ # Get the current symbol.
+ symbol = Memi[sym+k-1]
+
+ # Check to see if there is any data.
+ if (IMT_NENTRIES(symbol) <= 0) {
+ IMT_RO(symbol) = INDEFR
+ next
+ }
+
+ # Check to see if there is any good data.
+ ngood = 0
+ do i = 1, IMT_NENTRIES(symbol) {
+ do j = 2, nap[i]
+ ngood = ngood + 1
+ }
+ if (ngood <= 0) {
+ IMT_RO(symbol) = INDEFR
+ next
+ }
+
+ # Get better estimage of ro.
+ if (niter == 1) {
+ if (k > 1 && ! IS_INDEFR(IMT_RO(Memi[sym+k-2]))) {
+ IMT_RO(symbol) = IMT_RO(Memi[sym+k-2])
+ } else
+ IMT_RO(symbol) = 0.5 * rap[1,1]
+ }
+
+ # Set the model derivative vector
+ call ph_adddr (rap[1,IMT_OFFSET(symbol)], Memd[AGR_DDDR(agr)],
+ naperts, Memd[AGR_PARAMS(agr)], IMT_RO(symbol),
+ IMT_NXAIRMASS(symbol))
+
+ # Get the new estimate of ro
+ rold = 0.0
+ rclamp = IMT_RO(symbol) / 4.0
+ ntimes = 0
+ repeat {
+
+ sumr = 0.0d0
+ sumy = 0.0d0
+
+ call ph_adddrdm (rap[1,IMT_OFFSET(symbol)],
+ Memd[AGR_DM(agr)], Memd[AGR_DDDR(agr)], naperts,
+ Memd[AGR_PARAMS(agr)], IMT_RO(symbol),
+ IMT_NXAIRMASS(symbol), niter)
+
+ call ph_awsum (nap[IMT_OFFSET(symbol)],
+ mag[1,IMT_OFFSET(symbol)],
+ merr[1,IMT_OFFSET(symbol)], Memd[AGR_DM(agr)],
+ Memr[AGR_W(agr)], Memd[AGR_DDDR(agr)], naperts,
+ IMT_NENTRIES(symbol), ipow, sumr, sumy)
+
+ if (sumy > 0.0d0) {
+ dr = sumr / sumy
+ if (dr * rold < 0.0)
+ rclamp = 0.5 * rclamp
+ IMT_RO(symbol) = IMT_RO(symbol) - dr / (1.0 + abs (dr /
+ rclamp))
+ if (IMT_RO(symbol) <= EPSILONR) {
+ IMT_RO(symbol) = INDEFR
+ call sfree (sp)
+ return (ERR)
+ }
+ rold = dr
+ if (abs (dr / IMT_RO(symbol)) <= 3.0e-4)
+ break
+ } else {
+ IMT_RO(symbol) = INDEFR
+ break
+ }
+
+ ntimes = ntimes + 1
+ if (ntimes >= 100) {
+ IMT_RO(symbol) = INDEFR
+ call sfree (sp)
+ return (ERR)
+ }
+ }
+
+ call ph_adp (rap[1,IMT_OFFSET(symbol)], Memd[AGR_DM(agr)],
+ Memd[AGR_T(agr)], naperts, lterms, nterms,
+ Memd[AGR_PARAMS(agr)], IMT_RO(symbol),
+ IMT_NXAIRMASS(symbol))
+
+ call ph_aaccum (nap[IMT_OFFSET(symbol)],
+ mag[1,IMT_OFFSET(symbol)], merr[1,IMT_OFFSET(symbol)],
+ Memd[AGR_DM(agr)], Memr[AGR_W(agr)], naperts,
+ IMT_NENTRIES(symbol), Memd[AGR_T(agr)], Memd[AGR_U(agr)],
+ Memd[AGR_V(agr)], lterms, nterms, ipow, sumd, sumw, sumn)
+ }
+
+ # Invert the matrix.
+ call dinver (Memd[AGR_U(agr)], lterms, nterms, iflag)
+ if (iflag != 0) {
+ call sfree (sp)
+ return (ERR)
+ }
+
+ # Get new values for the parameters.
+ call dmvmul (Memd[AGR_U(agr)], lterms, nterms, Memd[AGR_V(agr)],
+ Memd[AGR_DP(agr)])
+ call ph_apsolve (Memd[AGR_POLD(agr)], Memd[AGR_PARAMS(agr)],
+ Memd[AGR_DP(agr)], Memd[AGR_PCLAMPS(agr)], nterms, ipow)
+
+ # Test the fit.
+ #if (sumn > 6.0)
+ if (sumn > (nterms + 1.0))
+ #sumn = sqrt (sumd / (sumn - 6.0))
+ sumn = sqrt (sumd / (sumn - (nterms + 1.0)))
+ else
+ sumn = 0.0
+ sumd = sqrt (sumd / sumw)
+ gain = 2.0 * abs (old - sumd) / (old + sumd)
+ old = sumd
+ if ((nterms < lterms) || (gain > 0.001)) {
+ next
+ } else if (ipow <= 2) {
+ ipow = 3
+ call amovkd (0.1d0, Memd[AGR_PCLAMPS(agr)], 4)
+ next
+ } else
+ break
+ }
+
+ if (niter > AGR_ITMAX) {
+ call sfree (sp)
+ return (ERR)
+ }
+
+ # Compute the errors.
+ do k = 1, nterms {
+ if (Memd[AGR_U(agr)+(k-1)*lterms+k-1] > 0.0)
+ Memd[AGR_PERRORS(agr)+k-1] =
+ sumn * sqrt (Memd[AGR_U(agr)+(k-1)*lterms+k-1])
+ else
+ Memd[AGR_PERRORS(agr)+k-1] = 0.0d0
+ }
+
+
+ call sfree (sp)
+ return (OK)
+end
+
+
+# PH_ISHOW -- Show the initial values of the parameters.
+
+procedure ph_ishow (fd, params, mterms)
+
+int fd # pointer to the output file descriptor
+double params[ARB] # the parameter values
+int mterms # the number of terms to be fit
+
+int i
+
+begin
+ # Print out the best fit parameters.
+ call fprintf (fd,
+ "\nThe initial cog model parameter values for nparams %d\n")
+ call pargi (mterms)
+ do i = 1, MAX_MTERMS {
+ call fprintf (fd, "\t%10s: %15.7g\n")
+ switch (i) {
+ case 1:
+ call pargstr ("swings")
+ case 2:
+ call pargstr ("pwings")
+ case 3:
+ call pargstr ("pgauss")
+ case 4:
+ call pargstr ("rgescale")
+ case 5:
+ call pargstr ("xwings")
+ }
+ call pargd (params[i])
+ }
+ call fprintf (fd, "\n")
+end
+
+
+# PH_PSHOW -- Show the results of the parameter fitting.
+
+procedure ph_pshow (fd, agr, mterms)
+
+int fd # the output file descriptor
+pointer agr # the pointer to the fitting descriptor
+int mterms # the number of parameters to fit
+
+begin
+ call ph_pwrite (fd, Memd[AGR_PARAMS(agr)], Memd[AGR_PERRORS(agr)],
+ MAX_MTERMS, mterms)
+end
+
+
+# PH_RSHOW -- Show the computed seeing parameters as a function of image.
+
+procedure ph_rshow (fd, imtable)
+
+int fd # the output file descriptor
+pointer imtable # pointer to the symbol table
+
+int i, nimages
+pointer sp, sym, symbol
+int stnsymbols()
+pointer sthead(), stnext()
+
+begin
+ nimages = stnsymbols (imtable, 0)
+ if (nimages <= 0)
+ return
+
+ # Allocate temporary space
+ call smark (sp)
+ call salloc (sym, nimages, TY_POINTER)
+
+ # Order the symbol table.
+ symbol = sthead (imtable)
+ do i = nimages, 1, -1 {
+ Memi[sym+i-1] = symbol
+ symbol = stnext (imtable, symbol)
+ }
+
+ call fprintf (fd,
+ "\nThe seeing radius and assumed airmass for each image\n")
+ do i = 1, nimages {
+ symbol = Memi[sym+i-1]
+ call fprintf (fd, "%30s %8.4f %8.3f\n")
+ call pargstr (IMT_IMNAME(symbol))
+ call pargr (IMT_RO(symbol))
+ call pargr (IMT_XAIRMASS(symbol))
+ }
+ call fprintf (fd, "\n")
+
+ call sfree (sp)
+end
+
+
+# PH_AEVAL -- Evaluate the fit for all the images.
+
+procedure ph_aeval (imtable, agr, apcat, magfd, logfd, mgd, id, x, y, nap,
+ rap, mag, merr, naperts, smallap, largeap)
+
+pointer imtable # pointer to the image symbol table
+pointer agr # pointer to the fitting structure
+int apcat # the aperture correction file descriptor
+int magfd # the best magnitudes file descriptor
+int logfd # the log file descriptor
+pointer mgd # pointer to the plot metacode file
+int id[ARB] # the star ids
+real x[ARB] # the star x coordinates
+real y[ARB] # the star y coordinates
+int nap[ARB] # the array of aperture numbers
+real rap[naperts,ARB] # input array of aperture radii
+real mag[naperts,ARB] # input array of magnitudes / differences
+real merr[naperts,ARB] # input array of magnitude errors
+int naperts # the number of input apertures
+int smallap # the small aperture number
+int largeap # the large aperture number
+
+int k, nimages
+pointer sp, sym, symbol
+int stnsymbols()
+pointer sthead(), stnext()
+
+begin
+ nimages = stnsymbols (imtable, 0)
+ if (nimages <= 0)
+ return
+
+ # Initialize some vectors.
+ call aclrr (Memr[AGR_TAVE(agr)], naperts)
+ call aclrr (Memr[AGR_TRESID(agr)], naperts)
+ call aclrr (Memr[AGR_TRESSQ(agr)], naperts)
+ call aclrr (Memr[AGR_TWR(agr)], naperts)
+
+ # Allocate temporary space
+ call smark (sp)
+ call salloc (sym, nimages, TY_POINTER)
+
+ # Order the symbol table.
+ symbol = sthead (imtable)
+ do k = nimages, 1, -1 {
+ Memi[sym+k-1] = symbol
+ symbol = stnext (imtable, symbol)
+ }
+
+ # Write the banner for the apfile.
+ call fprintf (apcat,
+ "# The aperture correction from apertures %d to %d in magnitudes\n\n")
+ call pargi (smallap)
+ call pargi (largeap)
+
+ # Write the banner for the magfile.
+ if (magfd != NULL) {
+ call fprintf (magfd, "# Magnitudes corrected to aperture %d\n\n")
+ call pargi (largeap)
+ call fprintf (magfd,
+"#%19tImage%30tFilter%39tExptime%47tAirmass%62tOtime%70tXcenter%80tYcenter\
+%93tMag%101tMerr%107tRadius\n\n")
+ }
+
+ # Compute the aperture corrections.
+ do k = 1, nimages {
+
+ symbol = Memi[sym+k-1]
+
+ # Initialize some vectors.
+ call aclrr (Memr[AGR_AVE(agr)], naperts)
+ call aclrr (Memr[AGR_RESID(agr)], naperts)
+ call aclrr (Memr[AGR_RESSQ(agr)], naperts)
+ call aclrr (Memr[AGR_WR(agr)], naperts)
+
+ call aclrr (Memr[AGR_ADOPT(agr)], naperts)
+ call aclrr (Memr[AGR_WADO(agr)], naperts)
+ call aclrr (Memr[AGR_WOBS(agr)], naperts)
+
+ call ph_rinit (rap[1,IMT_OFFSET(symbol)], Memr[AGR_RBAR(agr)],
+ naperts)
+ call ph_tinit (rap[1,IMT_OFFSET(symbol)], Memr[AGR_THEO(agr)],
+ naperts, Memd[AGR_PARAMS(agr)], IMT_RO(symbol),
+ IMT_NXAIRMASS(symbol))
+
+ # Accumulate the difference data.
+ call ph_taccum (nap[IMT_OFFSET(symbol)], mag[1,IMT_OFFSET(symbol)],
+ merr[1,IMT_OFFSET(symbol)], Memr[AGR_THEO(agr)],
+ Memr[AGR_W(agr)], Memr[AGR_ADOPT(agr)],
+ Memr[AGR_WOBS(agr)], Memr[AGR_AVE(agr)],
+ Memr[AGR_RESID(agr)], Memr[AGR_RESSQ(agr)],
+ Memr[AGR_WR(agr)], Memr[AGR_OBS(agr)], Memr[AGR_WADO(agr)],
+ naperts, IMT_NENTRIES(symbol))
+
+ # Compute the cumulative differences.
+ call ph_tcum (rap[1,IMT_OFFSET(symbol)], Memr[AGR_ADOPT(agr)],
+ Memr[AGR_WADO(agr)], Memr[AGR_CUM(agr)], Memr[AGR_TCUM(agr)],
+ Memr[AGR_WCUM(agr)], naperts, Memd[AGR_PARAMS(agr)],
+ IMT_RO(symbol), IMT_NXAIRMASS(symbol))
+
+ # Write the aperture photometry file.
+ call ph_wapcat (apcat, IMT_IMNAME(symbol), IMT_RO(symbol),
+ Memr[AGR_ADOPT(agr)], Memr[AGR_WADO(agr)], naperts, smallap,
+ largeap)
+
+ if (logfd != NULL) {
+ call ph_twrite (logfd, IMT_IMNAME(symbol), IMT_RO(symbol),
+ IMT_XAIRMASS(symbol), Memr[AGR_RBAR(agr)],
+ Memr[AGR_THEO(agr)], Memr[AGR_OBS(agr)],
+ Memr[AGR_WOBS(agr)], Memr[AGR_ADOPT(agr)],
+ Memr[AGR_WADO(agr)], rap[1,IMT_OFFSET(symbol)],
+ Memr[AGR_CUM(agr)], Memr[AGR_TCUM(agr)],
+ Memr[AGR_WCUM(agr)], naperts)
+ call fprintf (logfd, "\n")
+ call ph_tmags (logfd, id[IMT_OFFSET(symbol)],
+ x[IMT_OFFSET(symbol)], y[IMT_OFFSET(symbol)],
+ nap[IMT_OFFSET(symbol)], rap[1,IMT_OFFSET(symbol)],
+ mag[1,IMT_OFFSET(symbol)], merr[1,IMT_OFFSET(symbol)],
+ Memr[AGR_ADOPT(agr)], Memr[AGR_W(agr)],
+ Memr[AGR_CUM(agr)], Memr[AGR_TCUM(agr)],
+ Memr[AGR_WCUM(agr)], Memr[AGR_MAGS(agr)],
+ Memr[AGR_CMAGS(agr)], Memr[AGR_TMAGS(agr)],
+ Memr[AGR_WMAGS(agr)], naperts, IMT_NENTRIES(symbol))
+ call ph_papcor (logfd, IMT_IMNAME(symbol), IMT_RO(symbol),
+ rap[1,IMT_OFFSET(symbol)], Memr[AGR_ADOPT(agr)],
+ Memr[AGR_WADO(agr)], naperts, smallap, largeap)
+ call fprintf (logfd, "\n")
+ }
+
+ if (magfd != NULL) {
+ call ph_wmags (magfd, symbol, x[IMT_OFFSET(symbol)],
+ y[IMT_OFFSET(symbol)], nap[IMT_OFFSET(symbol)],
+ rap[1,IMT_OFFSET(symbol)], mag[1,IMT_OFFSET(symbol)],
+ merr[1,IMT_OFFSET(symbol)], Memr[AGR_ADOPT(agr)],
+ Memr[AGR_WADO(agr)], Memr[AGR_W(agr)], Memr[AGR_CUM(agr)],
+ Memr[AGR_WCUM(agr)], Memr[AGR_MAGS(agr)],
+ Memr[AGR_CMAGS(agr)], Memr[AGR_WMAGS(agr)], naperts,
+ IMT_NENTRIES(symbol), largeap)
+ }
+
+ if (mgd != NULL) {
+ call ph_gimfit (mgd, agr, IMT_IMNAME(symbol), IMT_RO(symbol),
+ IMT_XAIRMASS(symbol), nap[IMT_OFFSET(symbol)],
+ nap[IMT_OFFSET(symbol)], rap[1,IMT_OFFSET(symbol)],
+ mag[1,IMT_OFFSET(symbol)], naperts,
+ IMT_NENTRIES(symbol), YES)
+ if (! IS_INDEFR(IMT_RO(symbol))) {
+ call ph_gaimres (mgd, agr, IMT_IMNAME(symbol),
+ IMT_RO(symbol), IMT_XAIRMASS(symbol),
+ nap[IMT_OFFSET(symbol)], nap[IMT_OFFSET(symbol)],
+ rap[1,IMT_OFFSET(symbol)], mag[1,IMT_OFFSET(symbol)],
+ naperts, IMT_NENTRIES(symbol), YES)
+ call ph_gbimres (mgd, agr, IMT_IMNAME(symbol),
+ IMT_RO(symbol), IMT_XAIRMASS(symbol),
+ nap[IMT_OFFSET(symbol)], nap[IMT_OFFSET(symbol)],
+ mag[1,IMT_OFFSET(symbol)], naperts,
+ IMT_NENTRIES(symbol), YES)
+ call ph_gaximres (mgd, agr, IMT_IMNAME(symbol),
+ IMT_RO(symbol), IMT_XAIRMASS(symbol),
+ nap[IMT_OFFSET(symbol)], nap[IMT_OFFSET(symbol)],
+ x[IMT_OFFSET(symbol)], mag[1,IMT_OFFSET(symbol)],
+ naperts, IMT_NENTRIES(symbol), YES)
+ call ph_gayimres (mgd, agr, IMT_IMNAME(symbol),
+ IMT_RO(symbol), IMT_XAIRMASS(symbol),
+ nap[IMT_OFFSET(symbol)], nap[IMT_OFFSET(symbol)],
+ y[IMT_OFFSET(symbol)], mag[1,IMT_OFFSET(symbol)],
+ naperts, IMT_NENTRIES(symbol), YES)
+ call ph_gacum (mgd, agr, IMT_IMNAME(symbol),
+ IMT_RO(symbol), IMT_XAIRMASS(symbol),
+ nap[IMT_OFFSET(symbol)], nap[IMT_OFFSET(symbol)],
+ rap[1,IMT_OFFSET(symbol)], mag[1,IMT_OFFSET(symbol)],
+ naperts, IMT_NENTRIES(symbol), smallap, largeap, YES)
+ }
+ }
+
+ if (! IS_INDEFR(IMT_RO(symbol))) {
+ call aaddr (Memr[AGR_AVE(agr)], Memr[AGR_TAVE(agr)],
+ Memr[AGR_TAVE(agr)], naperts)
+ call aaddr (Memr[AGR_RESID(agr)], Memr[AGR_TRESID(agr)],
+ Memr[AGR_TRESID(agr)], naperts)
+ call aaddr (Memr[AGR_RESSQ(agr)], Memr[AGR_TRESSQ(agr)],
+ Memr[AGR_TRESSQ(agr)], naperts)
+ call aaddr (Memr[AGR_WR(agr)], Memr[AGR_TWR(agr)],
+ Memr[AGR_TWR(agr)], naperts)
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_A1EVAL -- Evaluate the fit for all the images.
+
+procedure ph_a1eval (agr, image, r0, xairmass, nap, rap, mag, merr,
+ naperts, npts)
+
+pointer agr # pointer to the fitting structure
+char image[ARB] # the image name
+real r0 # the seeing radius
+real xairmass # the airmass value
+int nap[ARB] # the number of apertures array
+real rap[naperts,ARB] # the list of aperture radii
+real mag[naperts,ARB] # the magnitude difference array
+real merr[naperts,ARB] # the magnitude error array
+int naperts # the number of apertures
+int npts # the number of points
+
+begin
+ # Initialize some vectors.
+ call aclrr (Memr[AGR_AVE(agr)], naperts)
+ call aclrr (Memr[AGR_RESID(agr)], naperts)
+ call aclrr (Memr[AGR_RESSQ(agr)], naperts)
+ call aclrr (Memr[AGR_WR(agr)], naperts)
+ call aclrr (Memr[AGR_ADOPT(agr)], naperts)
+ call aclrr (Memr[AGR_WOBS(agr)], naperts)
+
+ # Compute the theoretical curve
+ call ph_rinit (rap, Memr[AGR_RBAR(agr)], naperts)
+ call ph_tinit (rap, Memr[AGR_THEO(agr)], naperts,
+ Memd[AGR_PARAMS(agr)], r0, xairmass)
+
+ # Accumulate the difference data.
+ call ph_taccum (nap, mag, merr, Memr[AGR_THEO(agr)], Memr[AGR_W(agr)],
+ Memr[AGR_ADOPT(agr)], Memr[AGR_WOBS(agr)], Memr[AGR_AVE(agr)],
+ Memr[AGR_RESID(agr)], Memr[AGR_RESSQ(agr)], Memr[AGR_WR(agr)],
+ Memr[AGR_OBS(agr)], Memr[AGR_WADO(agr)], naperts, npts)
+
+ # Compute the cumulative differences.
+ call ph_tcum (rap, Memr[AGR_ADOPT(agr)], Memr[AGR_WADO(agr)],
+ Memr[AGR_CUM(agr)], Memr[AGR_TCUM(agr)], Memr[AGR_WCUM(agr)],
+ naperts, Memd[AGR_PARAMS(agr)], r0, xairmass)
+end
+
+
+# PH_TFSHOW -- Compute and print the summary statistics.
+
+procedure ph_tfshow (fd, agr, naperts)
+
+int fd # the output file descriptor
+pointer agr # the pointer to the fit structure
+int naperts # the number of apertures
+
+begin
+ call ph_rwrite (fd, Memr[AGR_TAVE(agr)], Memr[AGR_TWR(agr)],
+ Memr[AGR_TRESID(agr)], Memr[AGR_TRESSQ(agr)], naperts)
+end
+
+
+# PH_AMEMFREE -- Free the memory used for doing the fit
+
+procedure ph_amemfree (agr)
+
+pointer agr # pointer to the fitting structure
+
+begin
+ call mfree (AGR_DM(agr), TY_DOUBLE)
+ call mfree (AGR_DDDR(agr), TY_DOUBLE)
+ call mfree (AGR_T(agr), TY_DOUBLE)
+ call mfree (AGR_U(agr), TY_DOUBLE)
+ call mfree (AGR_V(agr), TY_DOUBLE)
+ call mfree (AGR_POLD(agr), TY_DOUBLE)
+ call mfree (AGR_DP(agr), TY_DOUBLE)
+ call mfree (AGR_PARAMS(agr), TY_DOUBLE)
+ call mfree (AGR_PERRORS(agr), TY_DOUBLE)
+ call mfree (AGR_PCLAMPS(agr), TY_DOUBLE)
+
+ call mfree (AGR_RBAR(agr), TY_REAL)
+ call mfree (AGR_W(agr), TY_REAL)
+ call mfree (AGR_THEO(agr), TY_REAL)
+ call mfree (AGR_WR(agr), TY_REAL)
+ call mfree (AGR_ADOPT(agr), TY_REAL)
+ call mfree (AGR_WOBS(agr), TY_REAL)
+ call mfree (AGR_OBS(agr), TY_REAL)
+ call mfree (AGR_WADO(agr), TY_REAL)
+
+ call mfree (AGR_CUM(agr), TY_REAL)
+ call mfree (AGR_TCUM(agr), TY_REAL)
+ call mfree (AGR_WCUM(agr), TY_REAL)
+ call mfree (AGR_MAGS(agr), TY_REAL)
+ call mfree (AGR_CMAGS(agr), TY_REAL)
+ call mfree (AGR_TMAGS(agr), TY_REAL)
+ call mfree (AGR_WMAGS(agr), TY_REAL)
+
+ call mfree (AGR_AVE(agr), TY_REAL)
+ call mfree (AGR_RESID(agr), TY_REAL)
+ call mfree (AGR_RESSQ(agr), TY_REAL)
+ call mfree (AGR_TAVE(agr), TY_REAL)
+ call mfree (AGR_TRESID(agr), TY_REAL)
+ call mfree (AGR_TRESSQ(agr), TY_REAL)
+ call mfree (AGR_TWR(agr), TY_REAL)
+
+ call mfree (agr, TY_STRUCT)
+end
+
+
+# PH_AGETP -- Fetch the initial values of the parameters for the cog model.
+
+procedure ph_agetp (params)
+
+double params[ARB]
+
+real clgetr()
+
+begin
+ params[1] = clgetr ("swings")
+ params[2] = clgetr ("pwings")
+ params[3] = clgetr ("pgauss")
+ params[4] = clgetr ("rgescale")
+ params[5] = clgetr ("xwings")
+end
+
+
+# PH_APINIT -- Set the initial values for the curve of growth model parameters.
+
+procedure ph_apinit (iparams, oparams, perrors, pclamps)
+
+double iparams[ARB] # the input parameters array
+double oparams[ARB] # the output parameters array
+double perrors[ARB] # the parameter errors array
+double pclamps[ARB] # array of parameter clamps
+
+begin
+ call amovd (iparams, oparams, MAX_MTERMS)
+ call aclrd (perrors, MAX_MTERMS)
+ call amovkd (0.2d0, pclamps, MAX_MTERMS)
+ pclamps[4] = 0.5d0
+end
+
+
+# PH_ANTERMS -- Compute the number of terms to use in the fit.
+
+procedure ph_anterms (niter, lterms, gain, nterms)
+
+int niter # the current iteration
+int lterms # the maximum number of terms to be fit
+real gain # the current value of the gain
+int nterms # the current number of terms to be fit
+
+int n
+
+begin
+ n = 1
+ if (nterms >= 1 && gain <= 0.04) {
+ n = 2
+ if (nterms >= 2 && gain <= 0.016) {
+ n = 3
+ if (nterms >= 3 && gain <= 0.006) {
+ n = 4
+ if (nterms >= 4 && gain <= 0.0025)
+ n = 5
+ }
+ }
+ }
+
+ nterms = min (n, lterms)
+end
+
+
+# PH_ADDDR -- Compute the derivative wrt ro vector.
+
+procedure ph_adddr (rap, dddr, naperts, params, r0, xairmass)
+
+real rap[ARB] # array of aperture radii
+double dddr[ARB] # the output derivatives array
+int naperts # the number of apertures
+double params[ARB] # the input parameter array
+real r0 # the current value of r0
+real xairmass # the current value of the airmass
+
+int i
+double ph_dmag()
+
+begin
+ do i = 2, naperts {
+ dddr[i] = 500.0d0 * (ph_dmag (rap[i-1], rap[i], xairmass,
+ r0 - 0.001, params) - ph_dmag (rap[i-1], rap[i], xairmass,
+ r0 + 0.001, params))
+ }
+end
+
+
+# PH_ADDDRDM -- Compute the derivative wrt ro vector.
+
+procedure ph_adddrdm (rap, dm, dddr, naperts, params, r0, xairmass, niter)
+
+real rap[ARB] # array of aperture radii
+double dm[ARB] # the output model differences array
+double dddr[ARB] # the output derivatives array
+int naperts # the number of apertures
+double params[ARB] # the input parameter array
+real r0 # the current value of r0
+real xairmass # the current value of the airmass
+int niter # the current iteratiom
+
+int i
+double ph_dmag()
+
+begin
+ do i = 2, naperts {
+ dm[i] = ph_dmag (rap[i-1], rap[i], xairmass, r0, params)
+ #if (niter == 1)
+ dddr[i] = 500.0d0 * (ph_dmag (rap[i-1], rap[i], xairmass,
+ r0 - 0.001, params) - ph_dmag (rap[i-1], rap[i], xairmass,
+ r0 + 0.001, params))
+ }
+end
+
+
+# PH_AWSUM -- Accumulate the weighted sums necessary to fit r0.
+
+procedure ph_awsum (nap, mag, merr, dm, w, dddr, naperts, npts, ipow,
+ sumr, sumy)
+
+int nap[ARB] # array of aperture numbers
+real mag[naperts,ARB] # array of magnitude difference
+real merr[naperts,ARB] # array of magnitude errors
+double dm[ARB] # array of model differences
+real w[ARB] # array of weights
+double dddr[ARB] # array of model derivatives
+int naperts # number of apertures
+int npts # number of data points
+int ipow # weighting power factor
+double sumr, sumy # the output sums
+
+int i, j
+real diff, wt
+
+begin
+ do i = 1, npts {
+ w[1] = 1.0d0
+ if (nap[i] <= 1)
+ next
+ do j = 2, nap[i] {
+ diff = mag[j,i] - dm[j]
+ w[j] = 1.0 / (1.0 + abs (diff / (2.0 * merr[j,i])) **
+ ipow)
+ w[j] = min (w[j], w[j-1])
+ wt = w[j] / merr[j,i] ** 2
+ sumr = sumr + wt * diff * dddr[j]
+ sumy = sumy + wt * dddr[j] ** 2
+ }
+ }
+end
+
+
+# PH_ADP -- Compute the parameter derivative vector with the new
+# value of r0.
+
+procedure ph_adp (rap, dm, t, naperts, lterms, nterms, params, r0, xairmass)
+
+real rap[ARB] # array of aperture radii
+double dm[ARB] # the new model differences
+double t[lterms,ARB] # the parameter derivatives matrix
+int naperts # the number of apertures
+int lterms # the size of the derivatives matrix
+int nterms # the number of terms to be fit
+double params[ARB] # the current model parameter values
+real r0 # the current r0 value
+real xairmass # the current airmass
+
+int i, j
+double ph_dmag()
+
+begin
+ do j = 2, naperts {
+ dm[j] = ph_dmag (rap[j-1], rap[j], xairmass, r0, params)
+ do i = 1, nterms {
+ params[i] = params[i] - 0.001
+ t[i,j] = ph_dmag (rap[j-1], rap[j], xairmass, r0, params)
+ params[i] = params[i] + 0.002
+ t[i,j] = 500.0d0 * (t[i,j] - ph_dmag (rap[j-1], rap[j],
+ xairmass, r0, params))
+ params[i] = params[i] - 0.001
+ }
+ }
+end
+
+
+# PH_AACCUM -- Accumulate the matrix and vector required to solve for the
+# parameter increments
+
+procedure ph_aaccum (nap, mag, merr, dm, w, naperts, npts, t, u, v, lterms,
+ nterms, ipow, sumd, sumw, sumn)
+
+int nap[ARB] # array of aperture numbers
+real mag[naperts,ARB] # array of magnitude difference
+real merr[naperts,ARB] # array of magnitude errors
+double dm[ARB] # array of model differences
+real w[ARB] # array of weights
+int naperts # number of apertures
+int npts # number of data points
+double t[lterms,ARB] # the array of parameter derivatives
+double u[lterms,ARB] # the matrix to be accumulated
+double v[ARB] # the vector to be accumulated
+int lterms # the maximum number of terms to fit
+int nterms # the current number of terms to fit
+int ipow # power factor for the weights
+double sumd # sum of the differences
+double sumw # sum of the scatter
+double sumn # sum of the weights
+
+int i, j, l, m
+real diff, wt
+
+begin
+ do i = 1, npts {
+ w[1] = 1.0
+ if (nap[i] <= 1)
+ next
+ do j = 2, nap[i] {
+ diff = mag[j,i] - dm[j]
+ w[j] = 1.0 / (1.0 + abs (diff / (2.0 * merr[j,i])) ** ipow)
+ w[j] = min (w[j], w[j-1])
+ wt = w[j] / merr[j,i] ** 2
+ sumd = sumd + wt * diff ** 2
+ sumw = sumw + wt
+ sumn = sumn + w[j]
+ do l = 1, nterms {
+ v[l] = v[l] + wt * diff * t[l,j]
+ do m = 1, nterms
+ u[l,m] = u[l,m] + wt * t[l,j] * t[m,j]
+ }
+ }
+ }
+end
+
+
+# PH_APSOLVE -- Solve for new values of the parameters.
+
+procedure ph_apsolve (pold, params, dp, pclamps, nterms, ipow)
+
+double pold[ARB] # the previous parameter imcrement values
+double params[ARB] # the current values of the parameters
+double dp[ARB] # the parameter increment values
+double pclamps[ARB] # the parameter clamp values
+int nterms # the number of terms that were fit
+int ipow # the current weighting factor
+
+int i
+
+begin
+ do i = 1, nterms {
+ if (dp[i] * pold[i] < 0.0d0)
+ pclamps[i] = 0.5 * pclamps[i]
+ pold[i] = dp[i]
+ }
+
+ params[1] = params[1] - dp[1] / ( 1.0d0 + abs (dp[1] / (pclamps[1] *
+ (params[1] - 1.0d0))))
+ if (nterms >= 2) {
+ params[2] = params[2] - dp[2] / (1.0d0 + abs (dp[2] / (pclamps[2] *
+ params[2] * (1.0d0 - params[2]))))
+ if (nterms >= 3) {
+ params[3] = params[3] - dp[3] / (1.0d0 + abs (dp[3] /
+ (pclamps[3] * params[3] * (1.0d0 - params[3]))))
+ if (ipow == 1) {
+ ipow = 2
+ pclamps[1] = 0.1d0
+ pclamps[2] = 0.1d0
+ }
+ if (nterms >= 4) {
+ params[4] = params[4] - dp[4] / (1.0d0 + abs (dp[4] /
+ (pclamps[4] * params[4])))
+ if (nterms >= 5)
+ params[5] = params[5] - dp[5] / (1.0d0 + abs (dp[5] /
+ (pclamps[5] * params[2])))
+ }
+ }
+ }
+end
+
+# PH_PWRITE -- Write out the theoetical model parameters.
+
+procedure ph_pwrite (fd, params, perrors, max_nterms, nterms)
+
+int fd # the output file descriptor
+double params[ARB] # the current model parameter values
+double perrors[ARB] # the current parameter errors
+int max_nterms # the number of terms
+int nterms # the number of terms to fit
+
+int i
+
+begin
+ # Print out the best fit parameters.
+ call fprintf (fd,
+ "\nThe computed cog model parameters and their errors for nparams %d\n")
+ call pargi (nterms)
+ do i = 1, max_nterms {
+ call fprintf (fd, "\t%10s: %15.7g +/- %15.7g\n")
+ switch (i) {
+ case 1:
+ call pargstr ("swings")
+ case 2:
+ call pargstr ("pwings")
+ case 3:
+ call pargstr ("pgauss")
+ case 4:
+ call pargstr ("rgescale")
+ case 5:
+ call pargstr ("xwings")
+ }
+ call pargd (params[i])
+ call pargd (perrors[i])
+ }
+ call fprintf (fd, "\n")
+end
+
+# PH_RINIT -- Initialize the rbar vector.
+
+procedure ph_rinit (rap, rbar, naperts)
+
+real rap[ARB] # the array of aperture radii
+real rbar[ARB] # the mean radius estimates
+int naperts # the number of aperture radii
+
+int j
+
+begin
+ do j = 2, naperts
+ rbar[j] = 0.5 * (rap[j-1] + rap[j])
+end
+
+# PH_TINIT -- Initialize the rbar vector and compute the theoretical estimates.
+
+procedure ph_tinit (rap, theo, naperts, params, r0, airmass)
+
+real rap[ARB] # the array of aperture radii
+real theo[ARB] # the current model estimates
+int naperts # the number of aperture radii
+double params[ARB] # the current parameter estimates
+real r0 # the seeing radius
+real airmass # the airmass value
+
+int j
+double ph_dmag()
+
+begin
+ if (IS_INDEFR(r0))
+ call amovkr (INDEFR, theo[2], naperts - 1)
+ else {
+ do j = 2, naperts
+ theo[j] = ph_dmag (rap[j-1], rap[j], airmass, r0, params)
+ }
+end
+
+
+# PH_TACCUM -- Accumulate the data.
+
+procedure ph_taccum (nap, mag, merr, theo, w, adopt, wobs, ave, resid, ressq,
+ wr, obs, wado, naperts, npts)
+
+int nap[ARB] # array of aperture numbers
+real mag[naperts,ARB] # the array of magnitude differences
+real merr[naperts,ARB] # the array of magnitude errors
+real theo[ARB] # the current model values
+real w[ARB] # the working weight array
+real adopt[ARB] # the adopted weight differences
+real wobs[ARB] # the sum of the weights
+real ave[ARB] # the average model values
+real resid[ARB] # the residuals
+real ressq[ARB] # the residuals squared
+real wr[ARB] # the sum of the weights
+real obs[ARB] # the observations
+real wado[ARB] # the error in the observations
+int naperts # the number of apertures
+int npts # the number of npts
+
+int i, j
+real diff, wt, scale
+
+begin
+ do i = 1, npts {
+ w[1] = 1.0
+ if (nap[i] <= 1)
+ next
+ do j = 2, nap[i] {
+ if (IS_INDEFR(theo[j])) {
+ wt = 1.0 / merr[j,i] ** 2
+ ave[1] = INDEFR
+ ave[j] = INDEFR
+ resid[1] = INDEFR
+ resid[j] = INDEFR
+ ressq[1] = INDEFR
+ ressq[j] = INDEFR
+ wr[1] = INDEFR
+ wr[j] = INDEFR
+ } else {
+ diff = mag[j,i] - theo[j]
+ w[j] = 1.0 / (1.0 + abs (diff / (2.0 * merr[j,i])))
+ w[j] = min (w[j], w[j-1])
+ wt = w[j] / merr[j,i] ** 2
+ ave[1] = ave[1] + wt * theo[j]
+ ave[j] = ave[j] + wt * theo[j]
+ resid[1] = resid[1] + wt * diff
+ resid[j] = resid[j] + wt * diff
+ ressq[1] = ressq[1] + wt * diff ** 2
+ ressq[j] = ressq[j] + wt * diff ** 2
+ wr[1] = wr[1] + wt
+ wr[j] = wr[j] + wt
+ }
+ adopt[j] = adopt[j] + wt * mag[j,i]
+ wobs[j] = wobs[j] + wt
+ }
+ }
+
+ do j = 2, naperts {
+ if (wobs[j] <= 0.0)
+ next
+ obs[j] = adopt[j] / wobs[j]
+ adopt[j] = 0.0
+ wobs[j] = 0.0
+ }
+
+ do i = 1, npts {
+ w[1] = 1.0
+ if (nap[i] <= 1)
+ next
+ do j = 2, nap[i] {
+ diff = mag[j,i] - obs[j]
+ w[j] = 1.0 / (1.0 + abs (diff / (2.0 * merr[j,i])) ** 2)
+ w[j] = min (w[j], w[j-1])
+ wt = w[j] / merr[j,i] ** 2
+ adopt[j] = adopt[j] + wt * mag[j,i]
+ wobs[j] = wobs[j] + wt
+ }
+ }
+
+ do j = 2, naperts {
+ if (wobs[j] <= 0.0)
+ next
+ obs[j] = adopt[j] / wobs[j]
+ adopt[j] = 0.0
+ wobs[j] = 0.0
+ }
+
+ do i = 1, npts {
+ w[1] = 1.0
+ if (nap[i] <= 1)
+ next
+ do j = 2, nap[i] {
+ diff = mag[j,i] - obs[j]
+ w[j] = 1.0 / (1.0 + abs (diff / (2.0 * merr[j,i])) ** 3)
+ w[j] = min (w[j], w[j-1])
+ wt = w[j] / merr[j,i] ** 2
+ adopt[j] = adopt[j] + wt * mag[j,i]
+ wobs[j] = wobs[j] + wt
+ }
+ }
+
+ scale = 0.1
+ do j = 2, naperts {
+ if (wobs[j] > 0.0) {
+ obs[j] = adopt[j] / wobs[j]
+ if (IS_INDEFR(theo[j]))
+ wt = 0.0
+ else {
+ wt = 1.0 / (scale * theo[j]) ** 2
+ adopt[j] = adopt[j] + wt * theo[j]
+ }
+ wt = 1.0 / (wobs[j] + wt)
+ adopt[j] = wt * adopt[j]
+ #wado[j] = sqrt (wt)
+ wado[j] = sqrt (wt + (scale * adopt[j]) ** 2)
+ wobs[j] = sqrt (1.0 / wobs[j])
+ } else {
+ adopt[j] = theo[j]
+ if (IS_INDEFR(theo[j])) {
+ wado[j] = INDEFR
+ obs[j] = INDEFR
+ wobs[j] = INDEFR
+ } else
+ wado[j] = 2.0 * scale * abs (theo[j])
+ }
+ }
+end
+
+
+# PH_TCUM -- Compute the cumulative differences.
+
+procedure ph_tcum (rap, adopt, wado, cum, tcum, wcum, naperts, params,
+ r0, airmass)
+
+real rap[ARB] # the list of aperture radii
+real adopt[ARB] # the adopted differences
+real wado[ARB] # the errors in the adopted differences
+real cum[ARB] # the accumulated differences
+real tcum[ARB] # the total accumulated differences
+real wcum[ARB] # the accumulated difference errors
+int naperts # the number of aperture radii
+double params[ARB] # the current parameter values
+real r0 # the seeing radius
+real airmass # the airmass
+
+int i
+double ph_dmag()
+
+begin
+ if (IS_INDEFR(r0)) {
+ call amovkr (INDEFR, cum, naperts + 1)
+ call amovkr (INDEFR, tcum, naperts + 1)
+ call amovkr (INDEFR, wcum, naperts + 1)
+ } else {
+ cum[naperts+1] = 0.0
+ tcum[naperts+1] = ph_dmag (rap[naperts], 2.0 * rap[naperts],
+ airmass, r0, params)
+ wcum[naperts+1] = 0.0
+ do i = naperts, 2, -1 {
+ cum[i] = adopt[i] + cum[i+1]
+ tcum[i] = adopt[i] + tcum[i+1]
+ wcum[i] = wado[i] ** 2 + wcum[i+1]
+ }
+ }
+end
+
+
+# PH_WAPCAT -- Write the image entry to the aperture correction catalog.
+
+procedure ph_wapcat (apcat, image, r0, adopt, wado, naperts, smallap, largeap)
+
+int apcat # the aperture correction catalog descriptor
+char image[ARB] # the image name
+real r0 # the seeing radius
+real adopt[ARB] # the adopted difference values
+real wado[ARB] # the adopted difference errors
+int naperts # the number of apertures
+int smallap # the small aperture number
+int largeap # the large aperture number
+
+int i
+real cum, wcum
+
+begin
+ if (IS_INDEFR(r0)) {
+ cum = INDEFR
+ wcum = INDEFR
+ } else {
+ cum = 0.0
+ wcum = 0.0
+ do i = largeap, smallap + 1, -1 {
+ cum = cum + adopt[i]
+ wcum = wcum + wado[i] ** 2
+ }
+ wcum = sqrt (wcum)
+ }
+ call fprintf (apcat, "%s %g %g\n")
+ call pargstr (image)
+ call pargr (cum)
+ call pargr (wcum)
+end
+
+
+# PH_PAPCOR -- Print the aperture correction on the standard output.
+
+procedure ph_papcor (fd, image, r0, rap, adopt, wado, naperts, smallap, largeap)
+
+int fd # the output file descriptor
+char image[ARB] # the image name
+real r0 # the seeing radius
+real rap[ARB] # the aperture radii
+real adopt[ARB] # the adopted difference values
+real wado[ARB] # the adopted difference errors
+int naperts # the number of apertures
+int smallap # the small aperture number
+int largeap # the large aperture number
+
+int i
+real cum, wcum
+
+begin
+ if (IS_INDEFR(r0)) {
+ cum = INDEFR
+ wcum = INDEFR
+ } else {
+ cum = 0.0
+ wcum = 0.0
+ do i = largeap, smallap + 1, -1 {
+ cum = cum + adopt[i]
+ wcum = wcum + wado[i] ** 2
+ }
+ wcum = sqrt (wcum)
+ }
+
+ call fprintf (fd,
+ "Image: %s rin=%.2f rout=%.2f apercor=%.3f +/- %.4f\n")
+ call pargstr (image)
+ call pargr (rap[smallap])
+ call pargr (rap[largeap])
+ call pargr (cum)
+ call pargr (wcum)
+end
+
+
+define NPERLINE 7
+
+# PH_TWRITE -- Write the results to the output file.
+
+procedure ph_twrite (fd, image, r0, xairmass, rbar, theo, obs, wobs, adopt,
+ wado, rap, cum, tcum, wcum, naperts)
+
+int fd # the file descriptor
+char image # the iamge name
+real r0 # the seeing disk
+real xairmass # the assumed airmass
+real rbar[ARB] # the list of mean aperture radii
+real theo[ARB] # the theoretical model differences
+real obs[ARB] # the observed differences
+real wobs[ARB] # the observed difference errors
+real adopt[ARB] # the adopted differences
+real wado[ARB] # the adopted difference errors
+real rap[ARB] # the list of aperture radii
+real cum[ARB] # the cumulative differences
+real tcum[ARB] # the total cumulative differences
+real wcum[ARB] # the errors in the cumulative differences
+int naperts # the number of aperture
+
+int j
+real sqwcum
+
+begin
+ # Print the title.
+ call fprintf (fd, "\nThe cog for image %s from radius %.2f to %.2f\n")
+ call pargstr (image)
+ call pargr (rbar[2])
+ call pargr (rbar[naperts])
+
+ # Print the mean aperture radius.
+ do j = 2, naperts {
+ if (j == 2) {
+ call fprintf (fd, " radius %9.4f")
+ call pargr (rbar[j])
+ } else if (mod (j, NPERLINE) == 1) {
+ call fprintf (fd, "%9.4f\n")
+ call pargr (rbar[j])
+ } else if (mod (j, NPERLINE) == 2) {
+ call fprintf (fd, " %9.4f")
+ call pargr (rbar[j])
+ } else {
+ call fprintf (fd, "%9.4f")
+ call pargr (rbar[j])
+ }
+ }
+ if (mod (naperts, NPERLINE) != 1)
+ call fprintf (fd, "\n")
+
+ # Print the theoretical model.
+ do j = 2, naperts {
+ if (j == 2) {
+ call fprintf (fd, " model %9.4f")
+ call pargr (theo[j])
+ } else if (mod (j, NPERLINE) == 1) {
+ call fprintf (fd, "%9.4f\n")
+ call pargr (theo[j])
+ } else if (mod (j, NPERLINE) == 2) {
+ call fprintf (fd, " %9.4f")
+ call pargr (theo[j])
+ } else {
+ call fprintf (fd, "%9.4f")
+ call pargr (theo[j])
+ }
+ }
+ if (mod (naperts, NPERLINE) != 1)
+ call fprintf (fd, "\n")
+
+ # Print the observed cog.
+ do j = 2, naperts {
+ if (j == 2) {
+ call fprintf (fd, "observed %9.4f")
+ call pargr (obs[j])
+ } else if (mod (j, NPERLINE) == 1) {
+ call fprintf (fd, "%9.4f\n")
+ call pargr (obs[j])
+ } else if (mod (j, NPERLINE) == 2) {
+ call fprintf (fd, " %9.4f")
+ call pargr (obs[j])
+ } else {
+ call fprintf (fd, "%9.4f")
+ call pargr (obs[j])
+ }
+ }
+ if (mod (naperts, NPERLINE) != 1)
+ call fprintf (fd, "\n")
+
+ # Print the errors in the observed cog.
+ do j = 2, naperts {
+ if (j == 2) {
+ call fprintf (fd, " sigma %9.4f")
+ call pargr (wobs[j])
+ } else if (mod (j, NPERLINE) == 1) {
+ call fprintf (fd, "%9.4f\n")
+ call pargr (wobs[j])
+ } else if (mod (j, NPERLINE) == 2) {
+ call fprintf (fd, " %9.4f")
+ call pargr (wobs[j])
+ } else {
+ call fprintf (fd, "%9.4f")
+ call pargr (wobs[j])
+ }
+ }
+ if (mod (naperts, NPERLINE) != 1)
+ call fprintf (fd, "\n")
+
+ # Print the adopted cog.
+ do j = 2, naperts {
+ if (j == 2) {
+ call fprintf (fd, " adopted %9.4f")
+ call pargr (adopt[j])
+ } else if (mod (j, NPERLINE) == 1) {
+ call fprintf (fd, "%9.4f\n")
+ call pargr (adopt[j])
+ } else if (mod (j, NPERLINE) == 2) {
+ call fprintf (fd, " %9.4f")
+ call pargr (adopt[j])
+ } else {
+ call fprintf (fd, "%9.4f")
+ call pargr (adopt[j])
+ }
+ }
+ if (mod (naperts, NPERLINE) != 1)
+ call fprintf (fd, "\n")
+
+ # Print the errors in the adopted cog.
+ do j = 2, naperts {
+ if (j == 2) {
+ call fprintf (fd, " sigma %9.4f")
+ call pargr (wado[j])
+ } else if (mod (j, NPERLINE) == 1) {
+ call fprintf (fd, "%9.4f\n")
+ call pargr (wado[j])
+ } else if (mod (j, NPERLINE) == 2) {
+ call fprintf (fd, " %9.4f")
+ call pargr (wado[j])
+ } else {
+ call fprintf (fd, "%9.4f")
+ call pargr (wado[j])
+ }
+ }
+ if (mod (naperts, NPERLINE) != 1)
+ call fprintf (fd, "\n")
+
+ # Print the title.
+ call fprintf (fd,
+ "\nThe aperture correction for image %s from radius %.2f to %.2f\n")
+ call pargstr (image)
+ call pargr (rap[1])
+ call pargr (rap[naperts])
+
+ # Print the aperture radii.
+ do j = 1, naperts {
+ if (j == 1) {
+ call fprintf (fd, " radius %9.4f")
+ call pargr (rap[j])
+ } else if (mod (j, NPERLINE) == 0) {
+ call fprintf (fd, "%9.4f\n")
+ call pargr (rap[j])
+ } else if (mod (j, NPERLINE) == 1) {
+ call fprintf (fd, " %9.4f")
+ call pargr (rap[j])
+ } else {
+ call fprintf (fd, "%9.4f")
+ call pargr (rap[j])
+ }
+ }
+ if (mod (naperts, NPERLINE) != 0)
+ call fprintf (fd, "\n")
+
+ # Print the aperture correction.
+ do j = 2, naperts {
+ if (j == 2) {
+ call fprintf (fd, " apercor %9.4f")
+ call pargr (cum[j])
+ } else if (mod (j, NPERLINE) == 1) {
+ call fprintf (fd, "%9.4f\n")
+ call pargr (cum[j])
+ } else if (mod (j, NPERLINE) == 2) {
+ call fprintf (fd, " %9.4f")
+ call pargr (cum[j])
+ } else {
+ call fprintf (fd, "%9.4f")
+ call pargr (cum[j])
+ }
+ }
+ if (mod (naperts, NPERLINE) != 1)
+ call fprintf (fd, "\n")
+
+
+ # Print the error in the aperture correction.
+ do j = 2, naperts {
+ sqwcum = wcum[j]
+ if (j == 2) {
+ call fprintf (fd, " sigma %9.4f")
+ call pargr (sqwcum)
+ } else if (mod (j, NPERLINE) == 1) {
+ call fprintf (fd, "%9.4f\n")
+ call pargr (sqwcum)
+ } else if (mod (j, NPERLINE) == 2) {
+ call fprintf (fd, " %9.4f")
+ call pargr (sqwcum)
+ } else {
+ call fprintf (fd, "%9.4f")
+ call pargr (sqwcum)
+ }
+ }
+ if (mod (naperts, NPERLINE) != 1)
+ call fprintf (fd, "\n")
+
+ # Print the title.
+ call fprintf (fd,
+ "\nThe aperture correction for image %s from radius %.2f to %.2f\n")
+ call pargstr (image)
+ call pargr (rap[1])
+ call pargr (2.0 * rap[naperts])
+
+ # Print the total aperture correction.
+ do j = 2, naperts + 1 {
+ if (j == 2) {
+ call fprintf (fd, "tapercor %9.4f")
+ call pargr (tcum[j])
+ } else if (mod (j, NPERLINE) == 1) {
+ call fprintf (fd, "%9.4f\n")
+ call pargr (tcum[j])
+ } else if (mod (j, NPERLINE) == 2) {
+ call fprintf (fd, " %9.4f")
+ call pargr (tcum[j])
+ } else {
+ call fprintf (fd, "%9.4f")
+ call pargr (tcum[j])
+ }
+ }
+ if (mod (naperts + 1, NPERLINE) != 1)
+ call fprintf (fd, "\n")
+
+ call fprintf (fd, "\n")
+end
+
+
+# PH_TMAGS -- Compute the correction to the last computed magnitude for
+# each star and the total magnitude as a function of aperture.
+
+procedure ph_tmags (logfd, id, x, y, nap, rap, mag, merr, adopt, w, cum,
+ tcum, wcum, tmpmags, obs, tobs, wobs, naperts, npts)
+
+int logfd # the output file descriptor
+int id[ARB] # stellar id numbers
+real x[ARB] # stellar x coordinates
+real y[ARB] # stellar y coordinates
+int nap[ARB] # array of aperture numbers
+real rap[naperts,ARB] # the list of aperture radii
+real mag[naperts,ARB] # the input magnitude difference array
+real merr[naperts,ARB] # the input magnitude error array
+real adopt[ARB] # the adopted difference values
+real w[ARB] # the working weight array
+real cum[ARB] # the accumulated difference array
+real tcum[ARB] # the total accumulated difference array
+real wcum[ARB] # the errors in the accumulated diff array
+real tmpmags[ARB] # temporary magnitude array
+real obs[ARB] # the accumulated magnitude array
+real tobs[ARB] # the total accumulated magnitude array
+real wobs[ARB] # the observations array
+int naperts # number of apertures
+int npts # number of points
+
+int i, j
+real diff
+
+begin
+ # Print the logfile banner.
+ if (logfd != NULL) {
+ call fprintf (logfd, "\nThe observed, and corrected to radii %.2f ")
+ call pargr (rap[naperts,1])
+ call fprintf (logfd, "and %.2f, magnitudes\n")
+ call pargr (2.0 * rap[naperts,1])
+ }
+
+ do i = 1, npts {
+
+ # Compute the observed, correctged and estimated total
+ # magnitudes.
+ tmpmags[1] = mag[1,i]
+ do j = 1, nap[i] {
+ if (j == 1)
+ w[j] = 1.0
+ else {
+ diff = mag[j,i] - adopt[j]
+ tmpmags[j] = tmpmags[j-1] + mag[j,i]
+ w[j] = 1.0 / (1.0 + (diff / (2.0 * merr[j,i])) ** 2)
+ w[j] = min (w[j], w[j-1])
+ }
+ if (IS_INDEFR(cum[j+1])) {
+ obs[j] = INDEFR
+ tobs[j] = INDEFR
+ wobs[j] = INDEFR
+ } else {
+ obs[j] = tmpmags[j] + cum[j+1]
+ tobs[j] = tmpmags[j] + tcum[j+1]
+ wobs[j] = sqrt (wcum[j+1] + merr[j,i] ** 2 / w[j])
+ }
+ }
+ do j = nap[i] + 1, naperts {
+ obs[j] = INDEFR
+ tobs[j] = INDEFR
+ wobs[j] = INDEFR
+ }
+
+ # Write out the results for the star to the log file.
+
+ # Print the banner of the star.
+ call fprintf (logfd, "Star: %d x: %.3f y: %.3f\n")
+ call pargi (id[i])
+ call pargr (x[i])
+ call pargr (y[i])
+
+ # Print the aperture radii.
+ do j = 1, naperts {
+ if (j == 1) {
+ call fprintf (logfd, " radius %9.4f")
+ call pargr (rap[j,i])
+ } else if (mod (j, NPERLINE) == 0) {
+ call fprintf (logfd, "%9.4f\n")
+ call pargr (rap[j,i])
+ } else if (mod (j, NPERLINE) == 1) {
+ call fprintf (logfd, " %9.4f")
+ call pargr (rap[j,i])
+ } else {
+ call fprintf (logfd, "%9.4f")
+ call pargr (rap[j,i])
+ }
+ }
+ if (mod (naperts, NPERLINE) != 0)
+ call fprintf (logfd, "\n")
+
+ # Print the observed magnitudes.
+ do j = 1, naperts {
+ if (j == 1) {
+ call fprintf (logfd, " mags %9.4f")
+ call pargr (tmpmags[j])
+ } else if (mod (j, NPERLINE) == 0) {
+ call fprintf (logfd, "%9.4f\n")
+ call pargr (tmpmags[j])
+ } else if (mod (j, NPERLINE) == 1) {
+ call fprintf (logfd, " %9.4f")
+ call pargr (tmpmags[j])
+ } else {
+ call fprintf (logfd, "%9.4f")
+ call pargr (tmpmags[j])
+ }
+ }
+ if (mod (naperts, NPERLINE) != 0)
+ call fprintf (logfd, "\n")
+
+ # Print the corrected magnitudes.
+ do j = 1, naperts {
+ if (j == 1) {
+ call fprintf (logfd, " cmags %9.4f")
+ call pargr (obs[j])
+ } else if (mod (j, NPERLINE) == 0) {
+ call fprintf (logfd, "%9.4f\n")
+ call pargr (obs[j])
+ } else if (mod (j, NPERLINE) == 1) {
+ call fprintf (logfd, " %9.4f")
+ call pargr (obs[j])
+ } else {
+ call fprintf (logfd, "%9.4f")
+ call pargr (obs[j])
+ }
+ }
+ if (mod (naperts, NPERLINE) != 0)
+ call fprintf (logfd, "\n")
+
+ # Print the estimated total corrected magnitudes.
+ do j = 1, naperts {
+ if (j == 1) {
+ call fprintf (logfd, " tcmags %9.4f")
+ call pargr (tobs[j])
+ } else if (mod (j, NPERLINE) == 0) {
+ call fprintf (logfd, "%9.4f\n")
+ call pargr (tobs[j])
+ } else if (mod (j, NPERLINE) == 1) {
+ call fprintf (logfd, " %9.4f")
+ call pargr (tobs[j])
+ } else {
+ call fprintf (logfd, "%9.4f")
+ call pargr (tobs[j])
+ }
+ }
+ if (mod (naperts, NPERLINE) != 0)
+ call fprintf (logfd, "\n")
+
+ # Print the errors in the total magnitudes
+ do j = 1, naperts {
+ if (j == 1) {
+ call fprintf (logfd, " sigma %9.4f")
+ call pargr (wobs[j])
+ } else if (mod (j, NPERLINE) == 0) {
+ call fprintf (logfd, "%9.4f\n")
+ call pargr (wobs[j])
+ } else if (mod (j, NPERLINE) == 1) {
+ call fprintf (logfd, " %9.4f")
+ call pargr (wobs[j])
+ } else {
+ call fprintf (logfd, "%9.4f")
+ call pargr (wobs[j])
+ }
+ }
+ if (mod (naperts, NPERLINE) != 0)
+ call fprintf (logfd, "\n")
+ }
+
+ call fprintf (logfd, "\n")
+end
+
+
+# PH_WMAGS -- Compute the correction to the last computed magnitude for
+# each star and the total magnitude as a function of aperture.
+
+procedure ph_wmags (magfd, imsymbol, x, y, nap, rap, mag, merr, adopt, wado,
+ w, cum, wcum, tmpmags, obs, wobs, naperts, npts, largeap)
+
+int magfd # the best magnitudes file descriptor
+pointer imsymbol # the image symbol
+real x[ARB] # stellar x coordinates
+real y[ARB] # stellar y coordinates
+int nap[ARB] # array of aperture numbers
+real rap[naperts,ARB] # the input aperture radii
+real mag[naperts,ARB] # the input magnitude difference array
+real merr[naperts,ARB] # the input magnitude error array
+real adopt[ARB] # the adopted difference values
+real wado[ARB] # the adopted difference errors
+real w[ARB] # the working weight array
+real cum[ARB] # the accumulated difference array
+real wcum[ARB] # the errors in the accumulated diff array
+real tmpmags[ARB] # temporary magnitude array
+real obs[ARB] # the accumulated magnitude array
+real wobs[ARB] # the observations array
+int naperts # number of apertures
+int npts # number of points
+int largeap # the largest aperture
+
+int i, j, jfinal
+real diff, sigmin, sigcor
+real assqr()
+
+begin
+ do i = 1, npts {
+
+ # Compute the observed, correctged and estimated total magnitudes.
+ tmpmags[1] = mag[1,i]
+ sigmin = MAX_REAL
+ #jfinal = min (nap[i], largeap)
+ jfinal = largeap
+ if (largeap < nap[i])
+ sigcor = assqr (wado[largeap+1], nap[i] - largeap)
+ else
+ sigcor = 0.0
+ do j = 1, min (nap[i], largeap) {
+ if (j == 1)
+ w[j] = 1.0
+ else {
+ diff = mag[j,i] - adopt[j]
+ tmpmags[j] = tmpmags[j-1] + mag[j,i]
+ w[j] = 1.0 / (1.0 + (diff / (2.0 * merr[j,i])) ** 2)
+ w[j] = min (w[j], w[j-1])
+ }
+ if (IS_INDEFR(cum[j+1])) {
+ obs[j] = INDEFR
+ wobs[j] = INDEFR
+ } else {
+ obs[j] = tmpmags[j] + cum[j+1] - cum[largeap+1]
+ wobs[j] = sqrt (wcum[j+1] - sigcor + merr[j,i] ** 2 / w[j])
+ if (wobs[j] < sigmin) {
+ jfinal = j
+ sigmin = wobs[j]
+ }
+ }
+ }
+
+ # Write out the best magnitude.
+ if (magfd != NULL) {
+ call fprintf (magfd,
+"%23.23s %10.10s %8.2f %6.3f %11.1h %8.2f %8.2f %7.3f %7.3f %6.3f\n")
+ call pargstr (IMT_IMNAME(imsymbol))
+ call pargstr (IMT_IFILTER(imsymbol))
+ call pargr (IMT_ITIME(imsymbol))
+ call pargr (IMT_XAIRMASS(imsymbol))
+ call pargr (IMT_OTIME(imsymbol))
+ call pargr (x[i])
+ call pargr (y[i])
+ call pargr (obs[jfinal])
+ call pargr (wobs[jfinal])
+ call pargr (rap[jfinal,i])
+ }
+ }
+end
+
+
+# PH_ACHI -- Compute the chi statistic.
+
+real procedure ph_achi (wr, resid, ressq, naperts)
+
+real wr[ARB] # the weights
+real resid[ARB] # the residuals
+real ressq[ARB] # the residuals
+int naperts # the number of apertures
+
+double sumwr, sumres, sumressq
+real chi
+real asumr()
+
+begin
+ sumwr = asumr (wr, naperts)
+ sumres = asumr (resid, naperts)
+ sumressq = asumr (ressq, naperts)
+ if (sumwr <= 0.0d0)
+ chi = 0.0
+ else
+ chi = sumressq / sumwr - (sumres / sumwr) ** 2
+ if (chi <= 0.0 || chi > MAX_REAL)
+ return (INDEFR)
+ else
+ return (chi)
+end
+
+
+# PH_RWRITE -- Write out the fit statistics for each aperture.
+
+procedure ph_rwrite (fd, ave, wr, resid, ressq, naperts)
+
+int fd # the output file descriptor
+real ave[ARB] # the average values
+real wr[ARB] # the weights
+real resid[ARB] # the residuals
+real ressq[ARB] # the residuals
+int naperts # the number of apertures
+
+int j
+real rtmp
+
+begin
+ call fprintf (fd, "\nAverage model cog, residual, and rms residual ")
+ call fprintf (fd, "for each aperture all images\n")
+ do j = 1, naperts {
+ if (wr[j] <= 0.0) {
+ ave[j] = INDEFR
+ resid[j] = INDEFR
+ ressq[j] = INDEFR
+ } else {
+ ave[j] = ave[j] / wr[j]
+ resid[j] = resid[j] / wr[j]
+ rtmp = ressq[j] / wr[j] - resid[j] ** 2
+ if (rtmp <= 0.0)
+ ressq[j] = 0.0
+ else
+ ressq[j] = sqrt (rtmp)
+ }
+ call fprintf (fd, "\t%3d %9.5f %9.5f %9.5f\n")
+ call pargi (j)
+ call pargr (ave[j])
+ call pargr (resid[j])
+ call pargr (ressq[j])
+ }
+ call fprintf (fd, "\n")
+end
+
+
+# PH_DMAG -- Compute the integral of the magnitude between two radii
+# assuming that the stellar profile can be approximated by a circular
+# Moffat function.
+
+double procedure ph_dmag (r1, r2, x, r0, params)
+
+real r1 # beginning radius for the integration
+real r2 # ending radius for the integration
+real x # the airmass value
+real r0 # the hwhm of the psf
+double params[ARB] # the model parameter array
+
+double bpex, pm1, x1, x2, x1sq, x2sq, d1, d2, i1, i2, dmag
+
+begin
+ bpex = params[2] + params[5] * x
+ pm1 = params[1] - 1.0d0
+ x1 = (r1 / r0)
+ x2 = (r2 / r0)
+ x1sq = x1 ** 2
+ x2sq = x2 ** 2
+ x1 = x1 / params[4]
+ x2 = x2 / params[4]
+ d1 = 1.0d0 + r1 ** 2
+ d2 = 1.0d0 + r2 ** 2
+ i1 = bpex * (1.0d0 - 1.0d0 / d1 ** pm1) + (1.0d0 - bpex) *
+ (params[3] * (1.0d0 - exp (-0.5d0 * x1sq)) + (1.0d0 - params[3]) *
+ (1.0d0 - (1.0d0 + x1) * exp (-x1)))
+ i2 = bpex * (1.0d0 - 1.0d0 / d2 ** pm1) + (1.0d0 - bpex) *
+ (params[3] * (1.0d0 - exp (-0.5d0 * x2sq)) + (1.0d0 - params[3]) *
+ (1.0d0 - (1.0d0 + x2) * exp (-x2)))
+ dmag = -2.5d0 * log10 (i2 / i1)
+
+ return (dmag)
+end
+
+
+# DMVMUL -- Multply a matrix (left-hand side) by a one dimensional vector
+# (right-hand side) and return the resultant vector.
+
+procedure dmvmul (matrix, maxdim, dim, vector, result)
+
+double matrix [maxdim, maxdim] # input matrix
+int maxdim # maximum size of input matrix
+int dim # dimension of matrix and vectors
+double vector[maxdim] # input vector
+double result[maxdim] # iutput vector
+
+double sum
+int i, j
+
+begin
+ do i = 1, dim {
+ sum = 0.0d0
+ do j = 1, dim
+ sum = sum + (matrix[j,i] * vector[j])
+ result[i] = sum
+ }
+end
diff --git a/noao/digiphot/photcal/mkobsfile/phaigrow.x b/noao/digiphot/photcal/mkobsfile/phaigrow.x
new file mode 100644
index 00000000..7fa32ce0
--- /dev/null
+++ b/noao/digiphot/photcal/mkobsfile/phaigrow.x
@@ -0,0 +1,1635 @@
+include <time.h>
+include <mach.h>
+include <gset.h>
+include "../lib/apfile.h"
+
+define HELPFILE "photcal$mkobsfile/apfile.key"
+
+# PH_AIGROW - Compute the curve of growth using the data from the input
+# photometry files, optional airmasses from the obsparams file, and the
+# initial values of the parameters using interactive graphics.
+
+procedure ph_aigrow (gd, apcat, magfd, logfd, mgd, imtable, id, x, y, nap,
+ rap, mag, merr, naperts, params, lterms, smallap, largeap)
+
+pointer gd # pointer to the graphics descriptor
+int apcat # the aperture correction file descriptor
+int magfd # the best magnitudes file descriptor
+int logfd # the output log file descriptor
+pointer mgd # pointer to the metacode graphics stream
+pointer imtable # pointer to the image symbol table
+int id[ARB] # the star ids
+real x[ARB] # the star x coordinates
+real y[ARB] # the star y coordinates
+int nap[ARB] # the array of aperture numbers
+real rap[naperts,ARB] # input array of aperture radii
+real mag[naperts,ARB] # input array of magnitudes / differences
+real merr[naperts,ARB] # input array of magnitude errors
+int naperts # the number of input apertures
+double params[ARB] # the initial values for the parameters
+int lterms # the number of terms to be fit
+int smallap # the small aperture number
+int largeap # the large aperture number
+
+int k, nimages, newfit, fitok, wcs, key, isymbol, newgraph, newimage
+int graphtype, ndata
+pointer sp, sym, symbol, agr, cmd, inap
+real wx, wy
+int stnsymbols(), ph_amfit(), clgcur(), ph_audelete()
+pointer sthead(), stnext()
+
+begin
+ if (logfd != NULL)
+ call ph_logtitle (logfd, apcat)
+
+ nimages = stnsymbols (imtable, 0)
+ if (nimages <= 0) {
+ call printf ("Error: There is no input data to fit\n")
+ if (logfd != NULL)
+ call fprintf (logfd, "Error: There is no input data to fit\n")
+ return
+ }
+
+ # Allocate temporary working space
+ call smark (sp)
+ call salloc (sym, nimages, TY_POINTER)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Order the symbol table.
+ symbol = sthead (imtable)
+ ndata = 0
+ do k = nimages, 1, -1 {
+ Memi[sym+k-1] = symbol
+ ndata = ndata + IMT_NENTRIES(symbol)
+ symbol = stnext (imtable, symbol)
+ }
+
+ # Allocate memory required for fitting.
+ call ph_ameminit (agr, lterms, naperts)
+
+ # Do the initial a parameter and seeing fit.
+ if (ph_amfit (imtable, agr, nap, rap, mag, merr, naperts, params,
+ lterms) == ERR)
+ fitok = NO
+ else
+ fitok = YES
+ newfit = NO
+
+ # Define the current image to be the first image and evaluate the fit.
+ symbol = Memi[sym]
+ isymbol = 1
+ call ph_a1eval (agr, IMT_IMNAME(symbol), IMT_RO(symbol),
+ IMT_NXAIRMASS(symbol), nap[IMT_OFFSET(symbol)],
+ rap[1,IMT_OFFSET(symbol)], mag[1,IMT_OFFSET(symbol)],
+ merr[1,IMT_OFFSET(symbol)], naperts, IMT_NENTRIES(symbol))
+ newimage = NO
+
+ # Plot the initial graph.
+ call ph_gimfit (gd, agr, IMT_IMNAME(symbol), IMT_RO(symbol),
+ IMT_XAIRMASS(symbol), nap[IMT_OFFSET(symbol)],
+ nap[IMT_OFFSET(symbol)], rap[1,IMT_OFFSET(symbol)],
+ mag[1,IMT_OFFSET(symbol)], naperts, IMT_NENTRIES(symbol), fitok)
+ graphtype = AGR_FIT
+ newgraph = NO
+
+ # Print the status report.
+ call ph_aeprint (agr, IMT_IMNAME(symbol), IMT_RO(symbol),
+ rap[1,IMT_OFFSET(symbol)], naperts, smallap, largeap, fitok,
+ newfit)
+
+ # Allocate the rejection array
+ call malloc (inap, ndata, TY_INT)
+ call amovi (nap, Memi[inap], ndata)
+
+ # Examine the fit.
+ while (clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+
+ switch (key) {
+
+ # Quit the program.
+ case 'q':
+ break
+
+ # Print help
+ case '?':
+ call gpagefile (gd, HELPFILE, "")
+
+ # Execute colon commands.
+ case ':':
+ call ph_acolon (gd, imtable, agr, symbol, isymbol, params,
+ lterms, naperts, smallap, largeap, Memc[cmd], fitok, newfit,
+ newimage, newgraph)
+
+ # Compute a new fit.
+ case 'f':
+ if (newfit == YES) {
+ call ph_amemfree (agr)
+ call ph_ameminit (agr, lterms, naperts)
+ }
+ if (ph_amfit (imtable, agr, Memi[inap], rap, mag, merr, naperts,
+ params, lterms) == ERR)
+ fitok = NO
+ else
+ fitok = YES
+ newfit = NO
+ newimage = YES
+ newgraph = YES
+ isymbol = 1
+ symbol = Memi[sym+isymbol-1]
+
+
+ # Print out the id of a particular object
+ case 'c':
+ call ph_pnearest (gd, graphtype, wx, wy, agr,
+ id[IMT_OFFSET(symbol)], x[IMT_OFFSET(symbol)],
+ y[IMT_OFFSET(symbol)], Memi[inap+IMT_OFFSET(symbol)-1],
+ nap[IMT_OFFSET(symbol)], rap[1,IMT_OFFSET(symbol)],
+ mag[1,IMT_OFFSET(symbol)], naperts, IMT_NENTRIES(symbol),
+ smallap, largeap)
+
+ # Write the answer for the current image.
+ case 'w':
+ call ph_aeprint (agr, IMT_IMNAME(symbol), IMT_RO(symbol),
+ rap[1,IMT_OFFSET(symbol)], naperts, smallap, largeap,
+ fitok, newfit)
+
+ # Delete points.
+ case 'd':
+ if (ph_audelete (gd, graphtype, wx, wy, agr,
+ x[IMT_OFFSET(symbol)], y[IMT_OFFSET(symbol)],
+ Memi[inap+IMT_OFFSET(symbol)-1], nap[IMT_OFFSET(symbol)],
+ rap[1,IMT_OFFSET(symbol)], mag[1,IMT_OFFSET(symbol)],
+ naperts, IMT_NENTRIES(symbol), smallap, largeap, YES) ==
+ YES)
+ newfit = YES
+
+ # Undelete points.
+ case 'u':
+ if (ph_audelete (gd, graphtype, wx, wy, agr,
+ x[IMT_OFFSET(symbol)], y[IMT_OFFSET(symbol)],
+ Memi[inap+IMT_OFFSET(symbol)-1], nap[IMT_OFFSET(symbol)],
+ rap[1,IMT_OFFSET(symbol)], mag[1,IMT_OFFSET(symbol)],
+ naperts, IMT_NENTRIES(symbol), smallap, largeap, NO) ==
+ YES)
+ newfit = YES
+
+ # Redraw the graph.
+ case 'g':
+ newgraph = YES
+
+ # Graph the model fit.
+ case 'm':
+ if (graphtype != AGR_FIT) {
+ graphtype = AGR_FIT
+ newgraph = YES
+ }
+
+ # Graph the resdiduals from the adopted model as a function of
+ # aperture.
+ case 'r':
+ if (fitok == YES && ! IS_INDEFR(IMT_RO(symbol)) &&
+ graphtype != AGR_ARESIDUALS) {
+ graphtype = AGR_ARESIDUALS
+ newgraph = YES
+ }
+
+ # Graph the residuals from the adopted model as a function of
+ # magnitude.
+ case 'b':
+ if (fitok == YES && ! IS_INDEFR(IMT_RO(symbol)) &&
+ graphtype != AGR_BRESIDUALS) {
+ graphtype = AGR_BRESIDUALS
+ newgraph = YES
+ }
+
+ # Graph the residuals as a fucntion of x.
+ case 'x':
+ if (fitok == YES && ! IS_INDEFR(IMT_RO(symbol)) &&
+ graphtype != AGR_XRESIDUALS) {
+ graphtype = AGR_XRESIDUALS
+ newgraph = YES
+ }
+
+ # Graph the residuals as a function of y.
+ case 'y':
+ if (fitok == YES && ! IS_INDEFR(IMT_RO(symbol)) &&
+ graphtype != AGR_YRESIDUALS) {
+ graphtype = AGR_YRESIDUALS
+ newgraph = YES
+ }
+
+ # Graph the cumulative aperture correction.
+ case 'a':
+ if (fitok == YES && ! IS_INDEFR(IMT_RO(symbol)) &&
+ graphtype != AGR_CUMULATIVE) {
+ graphtype = AGR_CUMULATIVE
+ newgraph = YES
+ }
+
+ # Move to the previous image.
+ case 'p':
+ if (isymbol == 1)
+ call printf ("Already at beginning of image list\n")
+ else {
+ isymbol = isymbol - 1
+ symbol = Memi[sym+isymbol-1]
+ newimage = YES
+ newgraph = YES
+ }
+
+ # Move to the next image.
+ case 'n':
+ if (isymbol == nimages)
+ call printf ("Already at end of image list\n")
+ else {
+ isymbol = isymbol + 1
+ symbol = Memi[sym+isymbol-1]
+ newimage = YES
+ newgraph = YES
+ }
+ }
+
+ if (newimage == YES) {
+ call ph_a1eval (agr, IMT_IMNAME(symbol), IMT_RO(symbol),
+ IMT_NXAIRMASS(symbol), Memi[inap+IMT_OFFSET(symbol)-1],
+ rap[1,IMT_OFFSET(symbol)], mag[1,IMT_OFFSET(symbol)],
+ merr[1,IMT_OFFSET(symbol)], naperts, IMT_NENTRIES(symbol))
+ newimage = NO
+ }
+
+ if (newgraph == YES) {
+ switch (graphtype) {
+ case AGR_FIT:
+ call ph_gimfit (gd, agr, IMT_IMNAME(symbol), IMT_RO(symbol),
+ IMT_XAIRMASS(symbol), Memi[inap+IMT_OFFSET(symbol)-1],
+ nap[IMT_OFFSET(symbol)], rap[1,IMT_OFFSET(symbol)],
+ mag[1,IMT_OFFSET(symbol)], naperts,
+ IMT_NENTRIES(symbol), fitok)
+ case AGR_ARESIDUALS:
+ call ph_gaimres (gd, agr, IMT_IMNAME(symbol),
+ IMT_RO(symbol), IMT_XAIRMASS(symbol),
+ Memi[inap+IMT_OFFSET(symbol)-1],
+ nap[IMT_OFFSET(symbol)], rap[1,IMT_OFFSET(symbol)],
+ mag[1,IMT_OFFSET(symbol)], naperts,
+ IMT_NENTRIES(symbol), fitok)
+ case AGR_BRESIDUALS:
+ call ph_gbimres (gd, agr, IMT_IMNAME(symbol),
+ IMT_RO(symbol), IMT_XAIRMASS(symbol),
+ Memi[inap+IMT_OFFSET(symbol)-1],
+ nap[IMT_OFFSET(symbol)], mag[1,IMT_OFFSET(symbol)],
+ naperts, IMT_NENTRIES(symbol), fitok)
+ case AGR_XRESIDUALS:
+ call ph_gaximres (gd, agr, IMT_IMNAME(symbol),
+ IMT_RO(symbol), IMT_XAIRMASS(symbol),
+ Memi[inap+IMT_OFFSET(symbol)-1],
+ nap[IMT_OFFSET(symbol)], x[IMT_OFFSET(symbol)],
+ mag[1,IMT_OFFSET(symbol)], naperts,
+ IMT_NENTRIES(symbol), fitok)
+ case AGR_YRESIDUALS:
+ call ph_gayimres (gd, agr, IMT_IMNAME(symbol),
+ IMT_RO(symbol), IMT_XAIRMASS(symbol),
+ Memi[inap+IMT_OFFSET(symbol)-1],
+ nap[IMT_OFFSET(symbol)], y[IMT_OFFSET(symbol)],
+ mag[1,IMT_OFFSET(symbol)], naperts,
+ IMT_NENTRIES(symbol), fitok)
+ case AGR_CUMULATIVE:
+ call ph_gacum (gd, agr, IMT_IMNAME(symbol),
+ IMT_RO(symbol), IMT_XAIRMASS(symbol),
+ Memi[inap+IMT_OFFSET(symbol)-1],
+ nap[IMT_OFFSET(symbol)], rap[1,IMT_OFFSET(symbol)],
+ mag[1,IMT_OFFSET(symbol)], naperts,
+ IMT_NENTRIES(symbol), smallap, largeap, fitok)
+ default:
+ call ph_gimfit (gd, agr, IMT_IMNAME(symbol), IMT_RO(symbol),
+ IMT_XAIRMASS(symbol), Memi[inap+IMT_OFFSET(symbol)-1],
+ nap[IMT_OFFSET(symbol)], rap[1,IMT_OFFSET(symbol)],
+ mag[1,IMT_OFFSET(symbol)], naperts,
+ IMT_NENTRIES(symbol), fitok)
+ }
+ call ph_aeprint (agr, IMT_IMNAME(symbol), IMT_RO(symbol),
+ rap[1,IMT_OFFSET(symbol)], naperts, smallap, largeap,
+ fitok, newfit)
+ newgraph = NO
+ }
+ }
+
+ # Output the results.
+
+ # Fit the seeing radii and the cog model parameters.
+ if (fitok == NO) {
+ call printf ("Error: The cog model fit did not converge\n")
+ if (logfd != NULL) {
+ call ph_ishow (logfd, params, lterms)
+ call ph_pshow (logfd, agr, lterms)
+ call ph_rshow (logfd, imtable)
+ call fprintf (logfd,
+ "Error: The cog model fit did not converge\n")
+ }
+ } else {
+ if (newfit == YES) {
+ call printf ("Warning: The cog model fit is out-of-date\n")
+ if (logfd != NULL)
+ call fprintf (logfd,
+ "Warning: The cog model fit is out-of-date\n")
+ }
+ if (logfd != NULL) {
+ call ph_ishow (logfd, params, lterms)
+ call ph_pshow (logfd, agr, lterms)
+ call ph_rshow (logfd, imtable)
+ }
+ call ph_aeval (imtable, agr, apcat, magfd, logfd, mgd, id, x, y,
+ Memi[inap], rap, mag, merr, naperts, smallap, largeap)
+ if (logfd != NULL)
+ call ph_tfshow (logfd, agr, naperts)
+ }
+
+ # Free memory required for fitting.
+ call ph_amemfree (agr)
+
+ call mfree (inap, TY_INT)
+ call sfree (sp)
+end
+
+
+# PH_GIMFIT -- Graph the data and fit for a particular image.
+
+procedure ph_gimfit (gd, agr, image, r0, xairmass, inap, nap, rap, mag, naperts,
+ npts, fitok)
+
+pointer gd # pointer to the graphics descriptor
+pointer agr # pointer to the fit structure
+char image[ARB] # the image name
+real r0 # the seeing radius
+real xairmass # the airmass of the image
+int inap[ARB] # the array of good aperture numbers
+int nap[ARB] # the array of aperture numbers
+real rap[naperts,ARB] # input array of aperture radii
+real mag[naperts,ARB] # input array of magnitudes / differences
+int naperts # the number of input apertures
+int npts # the number of points
+int fitok # is the fit ok
+
+int i, j
+pointer sp, title
+real rmin, rmax, dr, mmin, mmax, dm
+int strlen()
+real ph_achi()
+
+begin
+ if (gd == NULL)
+ return
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (title, 2 * SZ_LINE, TY_CHAR)
+
+ # Compute the data window in x.
+ call alimr (rap, naperts * npts, rmin, rmax)
+ dr = rmax - rmin
+ rmin = rmin - 0.1 * dr
+ rmax = rmax + 0.1 * dr
+
+ # Compute the data window in y.
+ mmin = MAX_REAL
+ mmax = -MAX_REAL
+ do i = 1, npts {
+ do j = 2, nap[i] {
+ if (mag[j,i] < mmin)
+ mmin = mag[j,i]
+ if (mag[j,i] > mmax)
+ mmax = mag[j,i]
+ }
+ }
+ if (mmin > mmax) {
+ mmin = -0.1
+ mmax = 0.1
+ } else {
+ dm = mmax - mmin
+ mmin = mmin - 0.1 * dm
+ mmax = mmax + 0.1 * dm
+ }
+
+ # Clear the screen and set the data window.
+ call gclear (gd)
+ call gswind (gd, rmin, rmax, mmin, mmax)
+
+ # Set up the title and the axis labels.
+ call sysid (Memc[title], 2 * SZ_LINE)
+ call sprintf (Memc[title+strlen(Memc[title])],
+ 2 * SZ_LINE - strlen(Memc[title]),
+ "\nImage: %s Ro: %.3f X: %.3f Rms: %.3g")
+ call pargstr (image)
+ call pargr (r0)
+ call pargr (xairmass)
+ if (fitok == YES && ! IS_INDEFR(r0))
+ call pargr (sqrt (ph_achi (Memr[AGR_WR(agr)],
+ Memr[AGR_RESID(agr)], Memr[AGR_RESSQ(agr)], naperts)))
+ else
+ call pargr (INDEFR)
+ if (fitok == YES && ! IS_INDEFR(r0)) {
+ call sprintf (Memc[title+strlen(Memc[title])],
+ 2 * SZ_LINE - strlen (Memc[title]),
+ "\nDashed line: theoretical cog ")
+ call sprintf (Memc[title+strlen(Memc[title])],
+ 2 * SZ_LINE - strlen (Memc[title]), "Solid line: adopted cog")
+ }
+ call glabax (gd, Memc[title], "Aperture Radius", "Curve of Growth")
+
+ # Draw the fitted and rejected data.
+ do i = 1, npts {
+ call gpmark (gd, Memr[AGR_RBAR(agr)+1], mag[2,i], inap[i] - 1,
+ GM_PLUS, 2.0, 2.0)
+ if (nap[i] > inap[i])
+ call gpmark (gd, Memr[AGR_RBAR(agr)+inap[i]],
+ mag[inap[i]+1,i], nap[i] - inap[i], GM_CROSS, 2.0, 2.0)
+ }
+
+ # Plot the theoretical and adopt models.
+ if (fitok == YES && ! IS_INDEFR(r0)) {
+ call gseti (gd, G_PLTYPE, GL_DASHED)
+ call gpline (gd, Memr[AGR_RBAR(agr)+1], Memr[AGR_THEO(agr)+1],
+ naperts - 1)
+ call gseti (gd, G_PLTYPE, GL_SOLID)
+ call gpline (gd, Memr[AGR_RBAR(agr)+1], Memr[AGR_ADOPT(agr)+1],
+ naperts - 1)
+ }
+
+ call gflush (gd)
+ call sfree (sp)
+end
+
+
+# PH_GAIMRES -- Graph the residuals from the adopted model for a particular
+# image.
+
+procedure ph_gaimres (gd, agr, image, r0, xairmass, inap, nap, rap, mag,
+ naperts, npts, fitok)
+
+pointer gd # pointer to the graphics descriptor
+pointer agr # pointer to the fit structure
+char image[ARB] # the image name
+real r0 # the seeing radius
+real xairmass # the airmass of the image
+int inap[ARB] # the array of good aperture numbers
+int nap[ARB] # the array of aperture numbers
+real rap[naperts,ARB] # input array of aperture radii
+real mag[naperts,ARB] # input array of magnitudes / differences
+int naperts # the number of input apertures
+int npts # the number of points
+int fitok # is the fit ok
+
+int i
+pointer sp, title, diff
+real rmin, rmax, dr, dmin, dmax, ddmin, ddmax, dd
+int strlen()
+real ph_achi()
+
+begin
+ call smark (sp)
+ call salloc (title, 2 * SZ_LINE, TY_CHAR)
+ call salloc (diff, naperts, TY_REAL)
+
+ # Set the data window.
+ call alimr (rap, naperts * npts, rmin, rmax)
+ dr = rmax - rmin
+ rmin = rmin - 0.1 * dr
+ rmax = rmax + 0.1 * dr
+
+ dmin = MAX_REAL
+ dmax = -MAX_REAL
+ do i = 1, npts {
+ call asubr (mag[2,i], Memr[AGR_ADOPT(agr)+1], Memr[diff+1],
+ nap[i] - 1)
+ call alimr (Memr[diff+1], nap[i] - 1, ddmin, ddmax)
+ if (ddmin < dmin)
+ dmin = ddmin
+ if (ddmax > dmax)
+ dmax = ddmax
+ }
+ if (dmin > dmax) {
+ dmin = -0.1
+ dmax = 0.1
+ } else {
+ dd = dmax - dmin
+ dmin = dmin - 0.1 * dd
+ dmax = dmax + 0.1 * dd
+ }
+
+ call gclear (gd)
+ call gswind (gd, rmin, rmax, dmin, dmax)
+
+ # Set up the axes and the axis labels.
+ call sysid (Memc[title], 2 * SZ_LINE)
+ call sprintf (Memc[title+strlen(Memc[title])], 2 * SZ_LINE -
+ strlen(Memc[title]), "\nImage: %s Ro: %.3f X: %.3f Rms: %.3g\n")
+ call pargstr (image)
+ call pargr (r0)
+ call pargr (xairmass)
+ call pargr (sqrt (ph_achi (Memr[AGR_WR(agr)], Memr[AGR_RESID(agr)],
+ Memr[AGR_RESSQ(agr)], naperts)))
+ call glabax (gd, Memc[title], "Aperture Radius", "Residuals")
+
+ # Draw the data.
+ do i = 1, npts {
+ call asubr (mag[2,i], Memr[AGR_ADOPT(agr)+1], Memr[diff+1],
+ nap[i] - 1)
+ call gpmark (gd, Memr[AGR_RBAR(agr)+1], Memr[diff+1], inap[i] - 1,
+ GM_PLUS, 2.0, 2.0)
+ if (nap[i] > inap[i])
+ call gpmark (gd, Memr[AGR_RBAR(agr)+inap[i]],
+ Memr[diff+inap[i]], nap[i] - inap[i], GM_CROSS, 2.0, 2.0)
+ }
+
+ call gseti (gd, G_PLTYPE, GL_SOLID)
+ call gamove (gd, rmin, 0.0)
+ call gadraw (gd, rmax, 0.0)
+ call gpline (gd, Memr[AGR_RBAR(agr)+1], Memr[AGR_AVE(agr)+1],
+ naperts - 1)
+
+ call gflush (gd)
+ call sfree (sp)
+end
+
+
+
+# PH_GBIMRES -- Graph the residuals from the adopted model for a particular
+# image as a function of magnitude in the first aperture.
+
+procedure ph_gbimres (gd, agr, image, r0, xairmass, inap, nap, mag,
+ naperts, npts, fitok)
+
+pointer gd # pointer to the graphics descriptor
+pointer agr # pointer to the fit structure
+char image[ARB] # the image name
+real r0 # the seeing radius
+real xairmass # the airmass of the image
+int inap[ARB] # the array of good aperture numbers
+int nap[ARB] # the array of aperture numbers
+real mag[naperts,ARB] # input array of magnitudes / differences
+int naperts # the number of input apertures
+int npts # the number of points
+int fitok # is the fit ok
+
+int i, j
+pointer sp, title, diff
+real rmin, rmax, dr, dmin, dmax, ddmin, ddmax, dd
+int strlen()
+real ph_achi()
+
+begin
+ call smark (sp)
+ call salloc (title, 2 * SZ_LINE, TY_CHAR)
+ call salloc (diff, naperts, TY_REAL)
+
+ # Set the data window.
+ rmin = MAX_REAL
+ rmax = -MAX_REAL
+ do i = 1, npts {
+ if (mag[1,i] < rmin)
+ rmin = mag[1,i]
+ if (mag[1,i] > rmax)
+ rmax = mag[1,i]
+ }
+ if (rmin > rmax) {
+ rmin = -0.1
+ rmax = 0.1
+ } else {
+ dr = rmax - rmin
+ rmin = rmin - 0.1 * dr
+ rmax = rmax + 0.1 * dr
+ }
+
+ dmin = MAX_REAL
+ dmax = -MAX_REAL
+ do i = 1, npts {
+ call asubr (mag[2,i], Memr[AGR_ADOPT(agr)+1], Memr[diff+1],
+ nap[i] - 1)
+ call alimr (Memr[diff+1], nap[i] - 1, ddmin, ddmax)
+ if (ddmin < dmin)
+ dmin = ddmin
+ if (ddmax > dmax)
+ dmax = ddmax
+ }
+ if (dmin > dmax) {
+ dmin = -0.1
+ dmax = 0.1
+ } else {
+ dd = dmax - dmin
+ dmin = dmin - 0.1 * dd
+ dmax = dmax + 0.1 * dd
+ }
+
+ call gclear (gd)
+ call gswind (gd, rmin, rmax, dmin, dmax)
+
+ # Set up the axes and the axis labels.
+ call sysid (Memc[title], 2 * SZ_LINE)
+ call sprintf (Memc[title+strlen(Memc[title])], 2 * SZ_LINE -
+ strlen(Memc[title]), "\nImage: %s Ro: %.3f X: %.3f Rms: %.3g\n")
+ call pargstr (image)
+ call pargr (r0)
+ call pargr (xairmass)
+ call pargr (sqrt (ph_achi (Memr[AGR_WR(agr)], Memr[AGR_RESID(agr)],
+ Memr[AGR_RESSQ(agr)], naperts)))
+ call glabax (gd, Memc[title], "Magnitude", "Residuals")
+
+ # Draw the data.
+ do i = 1, npts {
+ call asubr (mag[2,i], Memr[AGR_ADOPT(agr)+1], Memr[diff+1],
+ nap[i] - 1)
+ do j = 2, inap[i]
+ call gmark (gd, mag[1,i], Memr[diff+j-1], GM_PLUS, 2.0, 2.0)
+ do j = inap[i] + 1, nap[i]
+ call gmark (gd, mag[1,i], Memr[diff+j-1], GM_CROSS, 2.0, 2.0)
+ }
+
+ call gseti (gd, G_PLTYPE, GL_SOLID)
+ call gamove (gd, rmin, 0.0)
+ call gadraw (gd, rmax, 0.0)
+
+ call gflush (gd)
+ call sfree (sp)
+end
+
+
+# PH_GAXIMRES -- Graph the residuals from the adopted model for a particular
+# image.
+
+procedure ph_gaximres (gd, agr, image, r0, xairmass, inap, nap, x, mag,
+ naperts, npts, fitok)
+
+pointer gd # pointer to the graphics descriptor
+pointer agr # pointer to the fit structure
+char image[ARB] # the image name
+real r0 # the seeing radius
+real xairmass # the airmass of the image
+int inap[ARB] # the array of good aperture numbers
+int nap[ARB] # the array of aperture numbers
+real x[ARB] # the array of x values
+real mag[naperts,ARB] # input array of magnitudes / differences
+int naperts # the number of input apertures
+int npts # the number of points
+int fitok # is the fit ok
+
+int i, j
+pointer sp, title, diff
+real xmin, xmax, dx, dmin, dmax, ddmin, ddmax, dd
+int strlen()
+real ph_achi()
+
+begin
+ call smark (sp)
+ call salloc (title, 2 * SZ_LINE, TY_CHAR)
+ call salloc (diff, naperts, TY_REAL)
+
+ # Set the x data window.
+ call alimr (x, npts, xmin, xmax)
+ dx = xmax - xmin
+ xmin = xmin - 0.1 * dx
+ xmax = xmax + 0.1 * dx
+
+ # Set the y data window.
+ dmin = MAX_REAL
+ dmax = -MAX_REAL
+ do i = 1, npts {
+ call asubr (mag[2,i], Memr[AGR_ADOPT(agr)+1], Memr[diff+1],
+ nap[i] - 1)
+ call alimr (Memr[diff+1], nap[i] - 1, ddmin, ddmax)
+ if (ddmin < dmin)
+ dmin = ddmin
+ if (ddmax > dmax)
+ dmax = ddmax
+ }
+ if (dmin > dmax) {
+ dmin = -0.1
+ dmax = 0.1
+ } else {
+ dd = dmax - dmin
+ dmin = dmin - 0.1 * dd
+ dmax = dmax + 0.1 * dd
+ }
+
+ # Initialize the plot.
+ call gclear (gd)
+ call gswind (gd, xmin, xmax, dmin, dmax)
+
+ # Set up the axes and the axis labels.
+ call sysid (Memc[title], 2 * SZ_LINE)
+ call sprintf (Memc[title+strlen(Memc[title])], 2 * SZ_LINE -
+ strlen(Memc[title]), "\nImage: %s Ro: %.3f X: %.3f Rms: %.3g\n")
+ call pargstr (image)
+ call pargr (r0)
+ call pargr (xairmass)
+ call pargr (sqrt (ph_achi (Memr[AGR_WR(agr)], Memr[AGR_RESID(agr)],
+ Memr[AGR_RESSQ(agr)], naperts)))
+ call glabax (gd, Memc[title], "X Coordinate", "Residuals")
+
+ # Draw the data.
+ do i = 1, npts {
+ call asubr (mag[2,i], Memr[AGR_ADOPT(agr)+1], Memr[diff+1],
+ nap[i] - 1)
+ do j = 2, inap[i]
+ call gmark (gd, x[i], Memr[diff+j-1], GM_PLUS, 2.0, 2.0)
+ do j = inap[i] + 1, nap[i]
+ call gmark (gd, x[i], Memr[diff+j-1], GM_CROSS, 2.0, 2.0)
+ }
+
+ call gseti (gd, G_PLTYPE, GL_SOLID)
+ call gamove (gd, xmin, 0.0)
+ call gadraw (gd, xmax, 0.0)
+
+ call gflush (gd)
+ call sfree (sp)
+end
+
+
+# PH_GAYIMRES -- Graph the residuals from the adopted model for a particular
+# image.
+
+procedure ph_gayimres (gd, agr, image, r0, xairmass, inap, nap, y, mag,
+ naperts, npts, fitok)
+
+pointer gd # pointer to the graphics descriptor
+pointer agr # pointer to the fit structure
+char image[ARB] # the image name
+real r0 # the seeing radius
+real xairmass # the airmass of the image
+int inap[ARB] # the array of good aperture numbers
+int nap[ARB] # the array of aperture numbers
+real y[ARB] # the array of y values
+real mag[naperts,ARB] # input array of magnitudes / differences
+int naperts # the number of input apertures
+int npts # the number of points
+int fitok # is the fit ok
+
+int i, j
+pointer sp, title, diff
+real ymin, ymax, dy, dmin, dmax, ddmin, ddmax, dd
+int strlen()
+real ph_achi()
+
+begin
+ call smark (sp)
+ call salloc (title, 2 * SZ_LINE, TY_CHAR)
+ call salloc (diff, naperts, TY_REAL)
+
+ # Set the y data window.
+ call alimr (y, npts, ymin, ymax)
+ dy = ymax - ymin
+ ymin = ymin - 0.1 * dy
+ ymax = ymax + 0.1 * dy
+
+ # Set the y data window.
+ dmin = MAX_REAL
+ dmax = -MAX_REAL
+ do i = 1, npts {
+ call asubr (mag[2,i], Memr[AGR_ADOPT(agr)+1], Memr[diff+1],
+ nap[i] - 1)
+ call alimr (Memr[diff+1], nap[i] - 1, ddmin, ddmax)
+ if (ddmin < dmin)
+ dmin = ddmin
+ if (ddmax > dmax)
+ dmax = ddmax
+ }
+ if (dmin > dmax) {
+ dmin = -0.1
+ dmax = 0.1
+ } else {
+ dd = dmax - dmin
+ dmin = dmin - 0.1 * dd
+ dmax = dmax + 0.1 * dd
+ }
+
+ # Initialize the plot.
+ call gclear (gd)
+ call gswind (gd, ymin, ymax, dmin, dmax)
+
+ # Set up the axes and the axis labels.
+ call sysid (Memc[title], 2 * SZ_LINE)
+ call sprintf (Memc[title+strlen(Memc[title])], 2 * SZ_LINE -
+ strlen(Memc[title]), "\nImage: %s Ro: %.3f X: %.3f Rms: %.3g\n")
+ call pargstr (image)
+ call pargr (r0)
+ call pargr (xairmass)
+ call pargr (sqrt (ph_achi (Memr[AGR_WR(agr)], Memr[AGR_RESID(agr)],
+ Memr[AGR_RESSQ(agr)], naperts)))
+ call glabax (gd, Memc[title], "Y Coordinate", "Residuals")
+
+ # Draw the data.
+ do i = 1, npts {
+ call asubr (mag[2,i], Memr[AGR_ADOPT(agr)+1], Memr[diff+1],
+ nap[i] - 1)
+ do j = 2, inap[i]
+ call gmark (gd, y[i], Memr[diff+j-1], GM_PLUS, 2.0, 2.0)
+ do j = inap[i] + 1, nap[i]
+ call gmark (gd, y[i], Memr[diff+j-1], GM_CROSS, 2.0, 2.0)
+ }
+
+ call gseti (gd, G_PLTYPE, GL_SOLID)
+ call gamove (gd, ymin, 0.0)
+ call gadraw (gd, ymax, 0.0)
+
+ call gflush (gd)
+ call sfree (sp)
+end
+
+
+# PH_GACUM -- Plot the cumulative profile.
+
+procedure ph_gacum (gd, agr, image, r0, xairmass, inap, nap, rap, mag, naperts,
+ npts, smallap, largeap, fitok)
+
+pointer gd # pointer to the graphics descriptor
+pointer agr # pointer to the fit structure
+char image[ARB] # the image name
+real r0 # the seeing radius
+real xairmass # the airmass of the image
+int inap[ARB] # the array of good number apertures
+int nap[ARB] # the array of number of apertures
+real rap[ARB] # input array of aperture radii
+real mag[naperts,ARB] # the array of magnitudes
+int naperts # the number of input apertures
+int npts # the number of points
+int smallap # small aperture number
+int largeap # large aperture number
+int fitok # is the fit ok
+
+int i, j
+pointer sp, title, cmags, ctheo, cadopt, caderr, cptr
+real rmin, rmax, dr, dmin, dmax, ddmin, ddmax, dd
+int strlen()
+real ph_achi()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (title, SZ_LINE, TY_CHAR)
+ call salloc (cmags, (naperts + 1) * npts, TY_REAL)
+ call salloc (ctheo, naperts + 1, TY_REAL)
+ call salloc (cadopt, naperts + 1, TY_REAL)
+ call salloc (caderr, naperts + 1, TY_REAL)
+
+ # Compute the data.
+ call aclrr (Memr[cmags], (naperts + 1) * npts)
+ cptr = cmags
+ do j = 1, npts {
+ do i = largeap, 2, -1 {
+ if (i > nap[j])
+ Memr[cptr+i-1] = Memr[AGR_ADOPT(agr)+i-1] + Memr[cptr+i]
+ else
+ Memr[cptr+i-1] = mag[i,j] + Memr[cptr+i]
+ }
+ cptr = cptr + naperts + 1
+ }
+
+ # Compute the model.
+ call aclrr (Memr[ctheo], naperts + 1)
+ call aclrr (Memr[cadopt], naperts + 1)
+ call aclrr (Memr[caderr], naperts + 1)
+ do i = largeap, 2, -1 {
+ Memr[ctheo+i-1] = Memr[AGR_THEO(agr)+i-1] + Memr[ctheo+i]
+ Memr[cadopt+i-1] = Memr[AGR_ADOPT(agr)+i-1] + Memr[cadopt+i]
+ Memr[caderr+i-1] = Memr[AGR_WADO(agr)+i-1] ** 2 + Memr[caderr+i]
+ }
+
+ # Set the x data window.
+ call alimr (rap, naperts, rmin, rmax)
+ dr = rmax - rmin
+ rmin = rmin - 0.1 * dr
+ rmax = rmax + 0.1 * dr
+
+ # Set the y data window.
+ dmin = MAX_REAL
+ dmax = -MAX_REAL
+ call alimr (Memr[cmags], (naperts + 1) * npts, ddmin, ddmax)
+ if (ddmin < dmin)
+ dmin = ddmin
+ if (ddmax > dmax)
+ dmax = ddmax
+ dd = dmax - dmin
+ dmin = dmin - 0.1 * dd
+ dmax = dmax + 0.1 * dd
+
+ call gclear (gd)
+ call gswind (gd, rmin, rmax, dmax, dmin)
+
+ # Set up the title and the axis labels.
+ call sysid (Memc[title], 2 * SZ_LINE)
+ call sprintf (Memc[title+strlen(Memc[title])], 2 * SZ_LINE -
+ strlen(Memc[title]), "\nImage: %s Ro: %.3f X: %.3f Rms: %.3g")
+ call pargstr (image)
+ call pargr (r0)
+ call pargr (xairmass)
+ call pargr (sqrt (ph_achi (Memr[AGR_WR(agr)], Memr[AGR_RESID(agr)],
+ Memr[AGR_RESSQ(agr)], naperts)))
+ call sprintf (Memc[title+strlen(Memc[title])], 2 * SZ_LINE -
+ strlen (Memc[title]), "\nDashed line: theoretical apcor ")
+ call sprintf (Memc[title+strlen(Memc[title])], 2 * SZ_LINE -
+ strlen (Memc[title]), "Solid line: adopted apcor")
+ call glabax (gd, Memc[title], "Aperture Radius", "Aperture Correction")
+
+ # Draw the data.
+ cptr = cmags
+ do j = 1, npts {
+ if (largeap < inap[j])
+ call gpmark (gd, rap, Memr[cptr+1], largeap - 1, GM_PLUS,
+ 2.0, 2.0)
+ else
+ call gpmark (gd, rap, Memr[cptr+1], inap[j] - 1, GM_PLUS,
+ 2.0, 2.0)
+ if (largeap > inap[j])
+ call gpmark (gd, rap[inap[j]], Memr[cptr+inap[j]],
+ largeap - inap[j], GM_CROSS, 2.0, 2.0)
+ cptr = cptr + naperts + 1
+ }
+
+ # Draw the zero correction line.
+ call gamove (gd, rmin, 0.0)
+ call gadraw (gd, rmax, 0.0)
+
+ # Draw the aperture limits.
+ if (smallap > rap[1]) {
+ call gseti (gd, G_PLTYPE, GL_DASHED)
+ call gamove (gd, rap[1], dmin)
+ call gadraw (gd, rap[1], dmax)
+ call gseti (gd, G_PLTYPE, GL_SOLID)
+ }
+ call gamove (gd, rap[smallap], dmin)
+ call gadraw (gd, rap[smallap], dmax)
+ call gamove (gd, rap[largeap], dmin)
+ call gadraw (gd, rap[largeap], dmax)
+ if (rap[naperts] > largeap) {
+ call gseti (gd, G_PLTYPE, GL_DASHED)
+ call gamove (gd, rap[naperts], dmin)
+ call gadraw (gd, rap[naperts], dmax)
+ call gseti (gd, G_PLTYPE, GL_SOLID)
+ }
+
+ # Draw the model.
+ call gseti (gd, G_PLTYPE, GL_DASHED)
+ call gpline (gd, rap, Memr[ctheo+1], naperts)
+ call gseti (gd, G_PLTYPE, GL_SOLID)
+ call gpline (gd, rap, Memr[cadopt+1], naperts)
+
+ call gflush (gd)
+ call sfree (sp)
+end
+
+
+# PH_PNEAREST -- Print basic information for the nearest object
+
+procedure ph_pnearest (gd, graphtype, wx, wy, agr, id, x, y, inap, nap, rap,
+ mag, naperts, npts, smallap, largeap)
+
+pointer gd # pointer to the graphics stream
+int graphtype # the current graphtype
+real wx, wy # the coordinates of the point to be un/deleted
+pointer agr # pointer to the fitting structure
+int id[ARB] # array of star ids
+real x[ARB] # the x coordinates
+real y[ARB] # the y coordinates
+int inap[ARB] # the number of good apertures
+int nap[ARB] # the number of measured apertures
+real rap[naperts,ARB] # the list of aperture radii
+real mag[naperts,ARB] # the list of magnitude differences
+int naperts # the number of apertures
+int npts # the number of points
+int smallap # the small aperture number
+int largeap # the large aperture number
+
+int i, j
+pointer sp, xin, yin, iap, inpts, index
+real r2min, r2, xc, yc
+real ph_nearest()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (xin, naperts + 1, TY_REAL)
+ call salloc (yin, naperts + 1, TY_REAL)
+
+ # Initialize.
+ r2min = MAX_REAL
+ iap = 0
+ inpts = 0
+
+ # Find the nearest point.
+ switch (graphtype) {
+ case AGR_FIT:
+
+ do i = 1, npts {
+ r2 = ph_nearest (gd, wx, wy, Memr[AGR_RBAR(agr)+1], mag[2,i],
+ nap[i] - 1, nap[i] - 1, index, YES)
+ if (r2 < r2min) {
+ r2min = r2
+ iap = index + 1
+ inpts = i
+ xc = Memr[AGR_RBAR(agr)+iap-1]
+ yc = mag[iap,inpts]
+ }
+ }
+
+ case AGR_ARESIDUALS:
+
+ do i = 1, npts {
+ call asubr (mag[2,i], Memr[AGR_ADOPT(agr)+1], Memr[yin+1],
+ nap[i] - 1)
+ r2 = ph_nearest (gd, wx, wy, Memr[AGR_RBAR(agr)+1], Memr[yin+1],
+ nap[i] - 1, nap[i] - 1, index, YES)
+ if (r2 < r2min) {
+ r2min = r2
+ iap = index + 1
+ inpts = i
+ xc = Memr[AGR_RBAR(agr)+iap-1]
+ yc = mag[iap,inpts] - Memr[AGR_ADOPT(agr)+iap-1]
+ }
+ }
+
+ case AGR_BRESIDUALS:
+ do i = 1, npts {
+ call amovkr (mag[1,i], Memr[xin+1], nap[i] - 1)
+ call asubr (mag[2,i], Memr[AGR_ADOPT(agr)+1], Memr[yin+1],
+ nap[i] - 1)
+ r2 = ph_nearest (gd, wx, wy, Memr[xin+1], Memr[yin+1],
+ nap[i] - 1, nap[i] - 1, index, YES)
+ if (r2 < r2min) {
+ r2min = r2
+ iap = index + 1
+ inpts = i
+ xc = mag[1,inpts]
+ yc = mag[iap,inpts] - Memr[AGR_ADOPT(agr)+iap-1]
+ }
+ }
+
+ case AGR_XRESIDUALS:
+
+ do i = 1, npts {
+ call amovkr (x[i], Memr[xin+1], nap[i] - 1)
+ call asubr (mag[2,i], Memr[AGR_ADOPT(agr)+1], Memr[yin+1],
+ nap[i] - 1)
+ r2 = ph_nearest (gd, wx, wy, Memr[xin+1], Memr[yin+1],
+ nap[i] - 1, nap[i] - 1, index, YES)
+ if (r2 < r2min) {
+ r2min = r2
+ iap = index + 1
+ inpts = i
+ xc = x[inpts]
+ yc = mag[iap,inpts] - Memr[AGR_ADOPT(agr)+iap-1]
+ }
+ }
+
+ case AGR_YRESIDUALS:
+
+ do i = 1, npts {
+ call amovkr (y[i], Memr[xin+1], nap[i] - 1)
+ call asubr (mag[2,i], Memr[AGR_ADOPT(agr)+1], Memr[yin+1],
+ nap[i] - 1)
+ r2 = ph_nearest (gd, wx, wy, Memr[xin+1], Memr[yin+1],
+ nap[i] - 1, nap[i] - 1, index, YES)
+ if (r2 < r2min) {
+ r2min = r2
+ iap = index + 1
+ inpts = i
+ xc = y[inpts]
+ yc = mag[iap,inpts] - Memr[AGR_ADOPT(agr)+iap-1]
+ }
+ }
+
+ case AGR_CUMULATIVE:
+
+ do i = 1, npts {
+ call aclrr (Memr[yin], naperts + 1)
+ do j = largeap, 2, -1 {
+ if (j > nap[i])
+ Memr[yin+j-1] = Memr[AGR_ADOPT(agr)+j-1] + Memr[yin+j]
+ else
+ Memr[yin+j-1] = mag[j,i] + Memr[yin+j]
+ }
+ r2 = ph_nearest (gd, wx, wy, rap[1,i], Memr[yin+1],
+ nap[i] - 1, nap[i] - 1, index, YES)
+ if (r2 < r2min) {
+ r2min = r2
+ iap = index + 1
+ inpts = i
+ xc = rap[iap,inpts]
+ yc = Memr[yin+iap-1]
+ }
+ }
+ }
+
+ if (iap != 0 && inpts != 0) {
+ switch (graphtype) {
+ case AGR_FIT:
+ call printf (
+ "Star: %d x: %.3f y: %.3f radius: %.3f delta mag: %.3f\n")
+ call pargi (id[inpts])
+ call pargr (x[inpts])
+ call pargr (y[inpts])
+ call pargr (xc)
+ call pargr (yc)
+ case AGR_ARESIDUALS:
+ call printf (
+ "Star: %d x: %.3f y: %.3f radius: %.3f residual: %.3f\n")
+ call pargi (id[inpts])
+ call pargr (x[inpts])
+ call pargr (y[inpts])
+ call pargr (xc)
+ call pargr (yc)
+ case AGR_BRESIDUALS:
+ call printf (
+ "Star: %d x: %.3f y: %.3f mag[1]: %.3f residual: %.3f\n")
+ call pargi (id[inpts])
+ call pargr (x[inpts])
+ call pargr (y[inpts])
+ call pargr (xc)
+ call pargr (yc)
+ case AGR_XRESIDUALS:
+ call printf (
+ "Star: %d x: %.3f y: %.3f x: %.3f residual: %.3f\n")
+ call pargi (id[inpts])
+ call pargr (x[inpts])
+ call pargr (y[inpts])
+ call pargr (xc)
+ call pargr (yc)
+ case AGR_YRESIDUALS:
+ call printf (
+ "Star: %d x: %.3f y: %.3f y: %.3f residual: %.3f\n")
+ call pargi (id[inpts])
+ call pargr (x[inpts])
+ call pargr (y[inpts])
+ call pargr (xc)
+ call pargr (yc)
+ case AGR_CUMULATIVE:
+ call printf (
+ "Star: %d x: %.3f y: %.3f y: %.3f apercor: %.3f\n")
+ call pargi (id[inpts])
+ call pargr (x[inpts])
+ call pargr (y[inpts])
+ call pargr (xc)
+ call pargr (yc)
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_AUDELETE -- Delete or undelete points from the current graph.
+
+int procedure ph_audelete (gd, graphtype, wx, wy, agr, x, y, inap, nap, rap,
+ mag, naperts, npts, smallap, largeap, delete)
+
+pointer gd # pointer to the graphics stream
+int graphtype # the current graphtype
+real wx, wy # the coordinates of the point to be un/deleted
+pointer agr # pointer to the fitting structure
+real x[ARB] # the x coordinates
+real y[ARB] # the y coordinates
+int inap[ARB] # the number of good apertures
+int nap[ARB] # the number of measured apertures
+real rap[naperts,ARB] # the list of aperture radii
+real mag[naperts,ARB] # the list of magnitude differences
+int naperts # the number of apertures
+int npts # the number of points
+int smallap # the small aperture number
+int largeap # the large aperture number
+int delete # delete points ?, otherwise undelete
+
+int i, j, iap, inpts, index, stat
+pointer sp, xin, yin
+real r2min, r2
+real ph_nearest()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (xin, naperts + 1, TY_REAL)
+ call salloc (yin, naperts + 1, TY_REAL)
+
+ # Initialize.
+ r2min = MAX_REAL
+ iap = 0
+ inpts = 0
+
+ # Find the nearest point.
+ switch (graphtype) {
+ case AGR_FIT:
+
+ do i = 1, npts {
+ r2 = ph_nearest (gd, wx, wy, Memr[AGR_RBAR(agr)+1], mag[2,i],
+ inap[i] - 1, nap[i] - 1, index, delete)
+ if (r2 < r2min) {
+ r2min = r2
+ iap = index + 1
+ inpts = i
+ }
+ }
+
+ case AGR_ARESIDUALS:
+
+ do i = 1, npts {
+ call asubr (mag[2,i], Memr[AGR_ADOPT(agr)+1], Memr[yin+1],
+ nap[i] - 1)
+ r2 = ph_nearest (gd, wx, wy, Memr[AGR_RBAR(agr)+1], Memr[yin+1],
+ inap[i] - 1, nap[i] - 1, index, delete)
+ if (r2 < r2min) {
+ r2min = r2
+ iap = index + 1
+ inpts = i
+ }
+ }
+
+ case AGR_BRESIDUALS:
+ do i = 1, npts {
+ call amovkr (mag[1,i], Memr[xin+1], nap[i] - 1)
+ call asubr (mag[2,i], Memr[AGR_ADOPT(agr)+1], Memr[yin+1],
+ nap[i] - 1)
+ r2 = ph_nearest (gd, wx, wy, Memr[xin+1], Memr[yin+1],
+ inap[i] - 1, nap[i] - 1, index, delete)
+ if (r2 < r2min) {
+ r2min = r2
+ iap = index + 1
+ inpts = i
+ }
+ }
+
+ case AGR_XRESIDUALS:
+
+ do i = 1, npts {
+ call amovkr (x[i], Memr[xin+1], nap[i] - 1)
+ call asubr (mag[2,i], Memr[AGR_ADOPT(agr)+1], Memr[yin+1],
+ nap[i] - 1)
+ r2 = ph_nearest (gd, wx, wy, Memr[xin+1], Memr[yin+1],
+ inap[i] - 1, nap[i] - 1, index, delete)
+ if (r2 < r2min) {
+ r2min = r2
+ iap = index + 1
+ inpts = i
+ }
+ }
+
+ case AGR_YRESIDUALS:
+
+ do i = 1, npts {
+ call amovkr (y[i], Memr[xin+1], nap[i] - 1)
+ call asubr (mag[2,i], Memr[AGR_ADOPT(agr)+1], Memr[yin+1],
+ nap[i] - 1)
+ r2 = ph_nearest (gd, wx, wy, Memr[xin+1], Memr[yin+1],
+ inap[i] - 1, nap[i] - 1, index, delete)
+ if (r2 < r2min) {
+ r2min = r2
+ iap = index + 1
+ inpts = i
+ }
+ }
+
+ case AGR_CUMULATIVE:
+
+ do i = 1, npts {
+ call aclrr (Memr[yin], naperts + 1)
+ do j = largeap, 2, -1 {
+ if (j > nap[i])
+ Memr[yin+j-1] = Memr[AGR_ADOPT(agr)+j-1] + Memr[yin+j]
+ else
+ Memr[yin+j-1] = mag[j,i] + Memr[yin+j]
+ }
+ r2 = ph_nearest (gd, wx, wy, rap[1,i], Memr[yin+1],
+ inap[i] - 1, nap[i] - 1, index, delete)
+ if (r2 < r2min) {
+ r2min = r2
+ iap = index + 1
+ inpts = i
+ }
+ }
+ }
+
+ # Delete or undelete the point and mark it.
+ if (iap != 0 && inpts != 0) {
+
+ switch (graphtype) {
+ case AGR_FIT:
+ call amovr (Memr[AGR_RBAR(agr)+1], Memr[xin+1], nap[inpts] - 1)
+ call amovr (mag[2,inpts], Memr[yin+1], nap[inpts] - 1)
+ case AGR_ARESIDUALS:
+ call amovr (Memr[AGR_RBAR(agr)+1], Memr[xin+1], nap[inpts] - 1)
+ call asubr (mag[2,inpts], Memr[AGR_ADOPT(agr)+1], Memr[yin+1],
+ nap[inpts] - 1)
+ case AGR_BRESIDUALS:
+ call amovkr (mag[1,inpts], Memr[xin+1], nap[inpts] - 1)
+ call asubr (mag[2,inpts], Memr[AGR_ADOPT(agr)+1], Memr[yin+1],
+ nap[inpts] - 1)
+ case AGR_XRESIDUALS:
+ call amovkr (x[inpts], Memr[xin+1], nap[inpts] - 1)
+ call asubr (mag[2,inpts], Memr[AGR_ADOPT(agr)+1], Memr[yin+1],
+ nap[inpts] - 1)
+ case AGR_YRESIDUALS:
+ call amovkr (y[inpts], Memr[xin+1], nap[inpts] - 1)
+ call asubr (mag[2,inpts], Memr[AGR_ADOPT(agr)+1], Memr[yin+1],
+ nap[inpts] - 1)
+ case AGR_CUMULATIVE:
+ call amovr (rap[1,inpts], Memr[xin+1], nap[inpts] - 1)
+ do j = largeap, 2, -1 {
+ if (j > nap[inpts])
+ Memr[yin+j-1] = Memr[AGR_ADOPT(agr)+j-1] + Memr[yin+j]
+ else
+ Memr[yin+j-1] = mag[j,inpts] + Memr[yin+j]
+ }
+ }
+
+ if (delete == YES) {
+ inap[inpts] = iap - 1
+ do i = inap[inpts] + 1, nap[inpts] {
+ call gscur (gd, Memr[xin+i-1], Memr[yin+i-1])
+ call gmark (gd, Memr[xin+i-1], Memr[yin+i-1], GM_CROSS,
+ 2.0, 2.0)
+ }
+ } else {
+ do i = inap[inpts]+1, iap {
+ call gscur (gd, Memr[xin+i-1], Memr[yin+i-1])
+ call gseti (gd, G_PMLTYPE, GL_CLEAR)
+ call gmark (gd, Memr[xin+i-1], Memr[yin+i-1], GM_CROSS,
+ 2.0, 2.0)
+ call gseti (gd, G_PMLTYPE, GL_SOLID)
+ call gmark (gd, Memr[xin+i-1], Memr[yin+i-1], GM_PLUS,
+ 2.0, 2.0)
+ }
+ inap[inpts] = iap
+ }
+
+ stat = YES
+
+ } else
+ stat = NO
+
+ call sfree (sp)
+ return (stat)
+end
+
+
+# PH_AEPRINT -- Print the appropriate error message under the plot.
+
+procedure ph_aeprint (agr, image, r0, rap, naperts, smallap, largeap, fitok,
+ newfit)
+
+pointer agr # pointer to the fitting structure
+char image[ARB] # the image name
+real r0 # the seing rdius
+real rap[ARB] # the lists of aperture radii
+int naperts # the number of aperture radii
+int smallap # the index of the small aperture radius
+int largeap # the index of the large aperture radius
+int fitok # did the fit converge ?
+int newfit # is the fit out-of-date ?
+
+begin
+ if (fitok == NO) {
+ call printf ("Error: The cog model fit did not converge\n")
+ } else if (newfit == YES) {
+ call printf ("Warning: The cog model fit is out-of-date\n")
+ } else if (IS_INDEFR(r0)) {
+ call printf ("Warning: Unable to fit RO for image %s\n")
+ call pargstr (image)
+ } else {
+ call ph_papcor (STDOUT, image, r0, rap, Memr[AGR_ADOPT(agr)],
+ Memr[AGR_WADO(agr)], naperts, smallap, largeap)
+ }
+end
+
+
+# PH_NEAREST -- Find the nearest data point to the coordinates.
+
+real procedure ph_nearest (gd, wx, wy, x, y, inpts, npts, index, delete)
+
+pointer gd # the graphics descriptor
+real wx, wy # the cursor coordinates
+real x[ARB] # the x values
+real y[ARB] # the y values
+int inpts # the number of good points
+int npts # the number of points
+int index # the index of the nearest point
+int delete # delete or undelete points
+
+int i, ib, ie
+real r2min, r2, nwx, nwy, nx, ny
+
+begin
+ r2min = MAX_REAL
+ index = 0
+ if (delete == YES) {
+ ib = 1
+ ie = inpts
+ } else {
+ ib = inpts + 1
+ ie = npts
+ }
+ call gctran (gd, wx, wy, nwx, nwy, 1, 0)
+
+ do i = ib, ie {
+ call gctran (gd, x[i], y[i], nx, ny, 1, 0)
+ r2 = (nx - nwx) ** 2 + (ny - nwy) ** 2
+ if (r2 < r2min) {
+ r2min = r2
+ index = i
+ }
+ }
+
+ return (r2min)
+end
+
+
+# PH_ACOLON -- Execute the apfile colon commands.
+
+procedure ph_acolon (gd, imtable, agr, symbol, isymbol, params, lterms,
+ naperts, smallap, largeap, cmd, fitok, newfit, newimage, newgraph)
+
+pointer gd # pointer to the graphics stream
+pointer imtable # pointer to the image name symbol table
+pointer agr # pointer to the fitting structure
+pointer symbol # the current image symbol
+int isymbol # the index of the current image symbol
+double params[ARB] # the initial parameters
+int lterms # the number of parameters to fit
+int naperts # the number of apertures
+int smallap # the small aperture number
+int largeap # the large aperture number
+char cmd[ARB] # the colon command
+int fitok # is the fit ok
+int newfit # compute a new fit
+int newimage # evaluate the fit for a new image
+int newgraph # plot a new graph
+
+int ncmd, ival
+pointer sp, incmd, outcmd, newsymbol
+real rval
+int strdic(), nscan(), stnsymbols()
+pointer stfind(), sthead(), stnext()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (incmd, SZ_LINE, TY_CHAR)
+ call salloc (outcmd, SZ_LINE, TY_CHAR)
+
+ # Get the command.
+ call sscan (cmd)
+ call gargwrd (Memc[incmd], SZ_LINE)
+ if (Memc[incmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+ ncmd = strdic (Memc[incmd], Memc[incmd], SZ_LINE, AGR_CMDS)
+
+ switch (ncmd) {
+ case AGR_CMD_SHOW:
+
+ call gargwrd (Memc[outcmd], SZ_LINE)
+ ncmd = strdic (Memc[outcmd], Memc[outcmd], SZ_LINE, AGR_SHOWCMDS)
+ switch (ncmd) {
+ case AGR_CMD_MODEL:
+ if (fitok == NO) {
+ call printf ("Error: The cog model fit did not converge\n")
+ } else {
+ if (newfit == YES)
+ call printf (
+ "Warning: The cog model fit is out-of-date\n")
+ call gdeactivate (gd, 0)
+ call ph_pshow (STDOUT, agr, lterms)
+ call greactivate (gd, 0)
+ }
+ case AGR_CMD_SEEING:
+ if (fitok == NO) {
+ call printf ("Error: The cog model fit did not converge\n")
+ } else {
+ if (newfit == YES)
+ call printf (
+ "Warning: The cog model fit is out-of-date\n")
+ call gdeactivate (gd, 0)
+ call ph_rshow (STDOUT, imtable)
+ call greactivate (gd, 0)
+ }
+ case AGR_CMD_PARAMETERS:
+ call gdeactivate (gd, 0)
+ call ph_ishow (STDOUT, params, lterms)
+ call greactivate (gd, 0)
+ default:
+ if (fitok == NO) {
+ call printf ("Error: The cog model fit did not converge\n")
+ } else {
+ if (newfit == YES)
+ call printf (
+ "Warning: The cog model fit is out-of-date\n")
+ call gdeactivate (gd, 0)
+ call ph_pshow (STDOUT, agr, lterms)
+ call greactivate (gd, 0)
+ }
+ }
+
+ case AGR_CMD_IMAGE:
+ call gargwrd (Memc[outcmd], SZ_LINE)
+ if (nscan() == 1) {
+ call printf ("Image: %s R0: %7.3f X: %5.3f\n")
+ call pargstr (IMT_IMNAME(symbol))
+ call pargr (IMT_RO(symbol))
+ call pargr (IMT_XAIRMASS(symbol))
+ } else {
+ newsymbol = stfind (imtable, Memc[outcmd])
+ if (newsymbol == NULL) {
+ call printf ("Image: %s not found in data\n")
+ call pargstr (Memc[outcmd])
+ } else {
+ symbol = newsymbol
+ isymbol = 1
+ newsymbol = sthead (imtable)
+ while (newsymbol != NULL) {
+ if (newsymbol == symbol)
+ break
+ isymbol = isymbol + 1
+ newsymbol = stnext (imtable, newsymbol)
+ }
+ isymbol = stnsymbols(imtable, 0) - isymbol + 1
+ newimage = YES
+ newgraph = YES
+ }
+ }
+
+ case AGR_CMD_MTERMS:
+ call gargi (ival)
+ if (nscan() == 1) {
+ call printf ("nparams = %d\n")
+ call pargi (lterms)
+ } else {
+ lterms = max (1, min (ival, MAX_MTERMS))
+ newfit = YES
+ }
+
+ case AGR_CMD_SWINGS:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("swings = %g\n")
+ call pargr (real(params[1]))
+ } else {
+ params[1] = max (1.0, rval)
+ }
+
+ case AGR_CMD_PWINGS:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("pwings = %g\n")
+ call pargr (real(params[2]))
+ } else {
+ params[2] = max (0.0, min (1.0, rval))
+ }
+
+ case AGR_CMD_PGAUSS:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("pgauss = %g\n")
+ call pargr (real(params[3]))
+ } else {
+ params[3] = max (0.0, min (1.0, rval))
+ }
+
+ case AGR_CMD_RGESCALE:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("rgescale = %g\n")
+ call pargr (real(params[4]))
+ } else {
+ params[4] = max (0.0, rval)
+ }
+
+ case AGR_CMD_XWINGS:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("xwings = %g\n")
+ call pargr (real(params[5]))
+ } else {
+ params[5] = rval
+ }
+
+ case AGR_CMD_SMALLAP:
+ call gargi (ival)
+ if (nscan() == 1) {
+ call printf ("smallap = %d\n")
+ call pargi (smallap)
+ } else {
+ smallap = max (1, min (ival, naperts))
+ }
+
+ case AGR_CMD_LARGEAP:
+ call gargi (ival)
+ if (nscan() == 1) {
+ call printf ("largeap = %d\n")
+ call pargi (largeap)
+ } else {
+ largeap = max (1, min (ival, naperts))
+ }
+
+ default:
+ call printf ("Ambiguous or undefined command\7\n")
+ }
+
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/photcal/mkobsfile/phaimtable.x b/noao/digiphot/photcal/mkobsfile/phaimtable.x
new file mode 100644
index 00000000..a1e8cd94
--- /dev/null
+++ b/noao/digiphot/photcal/mkobsfile/phaimtable.x
@@ -0,0 +1,409 @@
+include <fset.h>
+include "../lib/apfile.h"
+
+# PH_EAOBSIMTABLE -- Enter the correct values of the filterid, exposure time,
+# and airmass into the image symbol table from the standard input.
+
+procedure ph_eaobsimtable (imtable, verify)
+
+pointer imtable # pointer to the symbol table
+int verify # verify the user input
+
+int nimages, i
+pointer sp, sym, filterid, symbol
+real itime, xairmass, otime
+int stnsymbols(), scan(), nscan(), strncmp()
+pointer sthead(), stnext()
+
+begin
+ nimages = stnsymbols (imtable, 0)
+ if (nimages <= 0)
+ return
+
+ call smark (sp)
+ call salloc (sym, nimages, TY_POINTER)
+ call salloc (filterid, SZ_FNAME, TY_CHAR)
+
+ # Reverse the order of the symbols in the symbol table.
+
+ symbol = sthead (imtable)
+ do i = nimages, 1, -1 {
+ Memi[sym+i-1] = symbol
+ symbol = stnext (imtable, symbol)
+ }
+
+ call printf ("\n")
+ call printf ("Enter filterid, exposure time and airmass\n")
+
+ # Loop over the images.
+ do i = 1, nimages {
+
+ symbol = Memi[sym+i-1]
+
+ # Issue the prompt for each image.
+ call printf (
+ " Image %s (f t X T, <CR>=4 X INDEF, <EOF>=quit entry): " )
+ call pargstr (IMT_IMNAME(symbol))
+ call flush (STDOUT)
+
+ # Scan the standard input.
+ if (scan() == EOF) {
+ call printf ("\n")
+ break
+ }
+
+ # Read in the airmass.
+ call gargwrd (Memc[filterid], SZ_FNAME)
+ call gargr (itime)
+ call gargr (xairmass)
+ call gargr (otime)
+ if (nscan() < 1) {
+ call strcpy ("INDEF", Memc[filterid], SZ_FNAME)
+ itime = INDEFR
+ xairmass = INDEFR
+ otime = INDEFR
+ } else if (nscan() < 2) {
+ itime = INDEFR
+ xairmass = INDEFR
+ otime = INDEFR
+ } else if (nscan() < 3) {
+ xairmass = INDEFR
+ otime = INDEFR
+ } else if (nscan() < 4) {
+ otime = INDEFR
+ }
+
+ # Update the symbol table.
+ if (strncmp (Memc[filterid], "INDEF", 5) != 0)
+ call strcpy (Memc[filterid], IMT_IFILTER(symbol), SZ_FNAME)
+ if (! IS_INDEFR(itime))
+ IMT_ITIME(symbol) = itime
+ if (! IS_INDEFR(xairmass)) {
+ IMT_XAIRMASS(symbol) = xairmass
+ IMT_NXAIRMASS(symbol) = xairmass - DEF_AIROFFSET
+ } else {
+ IMT_XAIRMASS(symbol) = DEF_AIROFFSET
+ IMT_NXAIRMASS(symbol) = 0.0
+ call printf (
+ " Warning: Setting airmass for image %s to %g\n")
+ call pargstr (IMT_IMNAME(symbol))
+ call pargr (DEF_AIROFFSET)
+ }
+ if (! IS_INDEFR(otime))
+ IMT_OTIME(symbol) = otime
+
+ # Verify the input.
+ if (verify == NO)
+ next
+
+ # Issue the verify prompt.
+ call printf (" Verify (f t X T, <CR>=%s %g %g %0.1h): ")
+ call pargstr (IMT_IFILTER(symbol))
+ call pargr (IMT_ITIME(symbol))
+ call pargr (IMT_XAIRMASS(symbol))
+ call pargr (IMT_OTIME(symbol))
+ call flush (STDOUT)
+
+ # Scan the standard input.
+ if (scan() == EOF) {
+ call printf ("\n")
+ next
+ }
+
+ # Read in the airmass.
+ call gargwrd (Memc[filterid], SZ_FNAME)
+ call gargr (itime)
+ call gargr (xairmass)
+ call pargr (otime)
+ if (nscan() == 4) {
+ call strcpy (Memc[filterid], IMT_IFILTER(symbol), SZ_FNAME)
+ IMT_ITIME(symbol) = itime
+ if (! IS_INDEFR(xairmass)) {
+ IMT_XAIRMASS(symbol) = xairmass
+ IMT_NXAIRMASS(symbol) = xairmass - DEF_AIROFFSET
+ } else {
+ IMT_XAIRMASS(symbol) = DEF_AIROFFSET
+ IMT_NXAIRMASS(symbol) = 0.0
+ call printf (
+ " Warning: Setting airmass for image %s to %g\n")
+ call pargstr (IMT_IMNAME(symbol))
+ call pargr (DEF_AIROFFSET)
+ }
+ IMT_OTIME(symbol) = otime
+ } else if (nscan() == 3) {
+ call strcpy (Memc[filterid], IMT_IFILTER(symbol), SZ_FNAME)
+ IMT_ITIME(symbol) = itime
+ if (! IS_INDEFR(xairmass)) {
+ IMT_XAIRMASS(symbol) = xairmass
+ IMT_NXAIRMASS(symbol) = xairmass - DEF_AIROFFSET
+ } else {
+ IMT_XAIRMASS(symbol) = DEF_AIROFFSET
+ IMT_NXAIRMASS(symbol) = 0.0
+ call printf (
+ " Warning: Setting airmass for image %s to %g\n")
+ call pargstr (IMT_IMNAME(symbol))
+ call pargr (DEF_AIROFFSET)
+ }
+ } else if (nscan() == 2) {
+ call strcpy (Memc[filterid], IMT_IFILTER(symbol), SZ_FNAME)
+ IMT_ITIME(symbol) = itime
+ } else if (nscan() == 1)
+ call strcpy (Memc[filterid], IMT_IFILTER(symbol), SZ_FNAME)
+ }
+
+ call printf ("\n")
+
+ call sfree (sp)
+end
+
+
+# PH_AOBSIMTABLE -- Enter the correct values of the filterid, exposure time,
+# and airmass into the image table.
+
+procedure ph_aobsimtable (imtable, fd, columns)
+
+pointer imtable # pointer to the symbol table
+int fd # file descriptor of the input text file
+int columns[ARB] # the list of input columns
+
+int stat, lbufsize
+pointer sp, image, fname, filterid, line, sym
+real itime, airmass, otime
+bool streq()
+int ph_anxtimage()
+pointer stfind()
+
+begin
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (filterid, SZ_FNAME, TY_CHAR)
+
+ Memc[image] = EOS
+ call fstats (fd, F_FILENAME, Memc[fname], SZ_FNAME)
+
+ line = NULL
+ lbufsize = 0
+
+ repeat {
+
+ # Get the image name.
+ stat = ph_anxtimage (fd, columns, Memc[image], line, lbufsize)
+ if (stat == EOF)
+ break
+
+ # Locate the image name in the symbol table.
+ sym = stfind (imtable, Memc[image])
+ if (sym == NULL) {
+ call printf (
+ "Warning: File: %s image: %s ")
+ call pargstr (Memc[fname])
+ call pargstr (Memc[image])
+ call printf ("is not in the input image list\n")
+ next
+ }
+
+ # Decode the data.
+ call ph_aobsdata (Memc[line], columns, Memc[filterid], SZ_FNAME,
+ itime, airmass, otime)
+
+ # Enter the data in the symbol table.
+ if (! streq (Memc[filterid], "INDEF"))
+ call strcpy (Memc[filterid], IMT_IFILTER(sym), SZ_FNAME)
+ if (! IS_INDEFR(itime))
+ IMT_ITIME(sym) = itime
+ if (! IS_INDEFR(airmass)) {
+ IMT_XAIRMASS(sym) = airmass
+ IMT_NXAIRMASS(sym) = airmass - DEF_AIROFFSET
+ } else {
+ IMT_XAIRMASS(sym) = DEF_AIROFFSET
+ IMT_NXAIRMASS(sym) = 0.0
+ call printf (
+ " Warning: Setting airmass for image %s to %g\n")
+ call pargstr (IMT_IMNAME(sym))
+ call pargr (DEF_AIROFFSET)
+ }
+ if (! IS_INDEFR(otime))
+ IMT_OTIME(sym) = otime
+ }
+
+ if (line != NULL) {
+ call mfree (line, TY_CHAR)
+ line = NULL
+ lbufsize = 0
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_AMKIMTABLE -- Create the image table using the input text file(s)
+# and the list of column numbers defining the fields required by the
+# program.
+
+int procedure ph_amkimtable (imtable, fd, columns, naperts, imid, id, x, y,
+ nap, rap, mag, merr, nptr, sortimid, magerr)
+
+pointer imtable # pointer to the symbol table
+int fd # file descriptor of the input text file
+int columns[ARB] # the list of input columns
+int naperts # the number of apertures
+pointer imid # pointer to the image id
+pointer id # pointer to the image ids
+pointer x # pointer to the x coordinate array
+pointer y # pointer to the y coordinate array
+pointer nap # pointer to the number of apertures array
+pointer rap # pointer to the aperture radii array
+pointer mag # pointer to the magnitude array
+pointer merr # pointer to the magnitude error array
+int nptr # pointer to the current data point
+int sortimid # does data need to be sorted on imid or id
+real magerr # the maximum magnitude error
+
+int stat, dbufsize, lbufsize
+pointer sp, fname, image, imname, filterid, line, sym
+real itime, airmass, otime
+
+bool streq()
+int ph_anxtimage(), ph_astardata(), ph_agetimage(), stnsymbols()
+pointer stfind(), stenter()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+ call salloc (filterid, SZ_FNAME, TY_CHAR)
+
+ # Allocate some initial buffer space.
+ if (nptr == 0) {
+ dbufsize = DEF_BUFSIZE
+ call malloc (imid, dbufsize, TY_INT)
+ call malloc (id, dbufsize, TY_INT)
+ call malloc (x, dbufsize, TY_REAL)
+ call malloc (y, dbufsize, TY_REAL)
+ call malloc (nap, dbufsize, TY_INT)
+ call malloc (rap, naperts * dbufsize, TY_REAL)
+ call malloc (mag, naperts * dbufsize, TY_REAL)
+ call malloc (merr, naperts * dbufsize, TY_REAL)
+ }
+
+ # Initialize.
+ Memc[image] = EOS
+ call fstats (fd, F_FILENAME, Memc[fname], SZ_FNAME)
+
+ # Find the first image.
+ lbufsize = 0
+ line = NULL
+ stat = ph_anxtimage (fd, columns, Memc[image], line, lbufsize)
+
+ # Read the data.
+ while (stat != EOF) {
+
+ # Check to see if the image name is already in the symbol table
+ # and if not enter it.
+ sym = stfind (imtable, Memc[image])
+ if (sym == NULL) {
+ sym = stenter (imtable, Memc[image], LEN_IMT_STRUCT)
+ IMT_IMNO(sym) = stnsymbols (imtable, 0)
+ IMT_NENTRIES(sym) = 0
+ IMT_RO(sym) = INDEFR
+ IMT_OFFSET(sym) = 0
+ call strcpy ("INDEF", IMT_IFILTER(sym), SZ_FNAME)
+ IMT_ITIME(sym) = INDEFR
+ IMT_XAIRMASS(sym) = INDEFR
+ IMT_NXAIRMASS(sym) = INDEFR
+ IMT_OTIME(sym) = INDEFR
+ call strcpy (Memc[image], IMT_IMNAME(sym), SZ_FNAME)
+ }
+
+ # Decode the airmass information.
+ call ph_aimdata (Memc[line], columns, Memc[filterid], SZ_FNAME,
+ itime, airmass, otime)
+
+ # Enter the new filterid, itime, and airmass only if there are no
+ # previous entries for that image.
+
+ if (streq (IMT_IFILTER(sym), "INDEF"))
+ call strcpy (Memc[filterid], IMT_IFILTER(sym), SZ_FNAME)
+ if (IS_INDEFR(IMT_ITIME(sym))) {
+ if (IS_INDEFR(itime))
+ IMT_ITIME(sym) = 1.0
+ else
+ IMT_ITIME(sym) = itime
+ }
+ if (IS_INDEFR(IMT_XAIRMASS(sym))) {
+ if (! IS_INDEFR(airmass)) {
+ IMT_XAIRMASS(sym) = airmass
+ IMT_NXAIRMASS(sym) = airmass - DEF_AIROFFSET
+ } else {
+ IMT_XAIRMASS(sym) = DEF_AIROFFSET
+ IMT_NXAIRMASS(sym) = 0.0
+ call printf (
+ " Warning: Setting airmass for image %s to %g\n")
+ call pargstr (IMT_IMNAME(sym))
+ call pargr (DEF_AIROFFSET)
+ }
+ }
+ if (IS_INDEFR(IMT_OTIME(sym)))
+ IMT_OTIME(sym) = otime
+
+ # Does the data need to be sorted on image or id. This should
+ # usually not be necessary for most DAOPHOT or APPHOT data
+ # but will be necessary if data from the same images is contained
+ # in more than 1 file.
+
+ if (IMT_NENTRIES(sym) > 0)
+ sortimid = YES
+ else
+ IMT_OFFSET(sym) = nptr + 1
+
+ # Get the data.
+ repeat {
+
+ # Decode x, y, magnitude and error.
+ if (ph_astardata (Memc[line], columns, Memr[x+nptr],
+ Memr[y+nptr], Memi[nap+nptr], Memr[rap+naperts*nptr],
+ Memr[mag+naperts*nptr], Memr[merr+naperts*nptr],
+ naperts, magerr) == OK) {
+ Memi[imid+nptr] = IMT_IMNO(sym)
+ IMT_NENTRIES(sym) = IMT_NENTRIES(sym) + 1
+ if (IMT_NENTRIES(sym) == 1)
+ IMT_RO(sym) = 0.5 * Memr[rap]
+ Memi[id+nptr] = IMT_NENTRIES(sym)
+ nptr = nptr + 1
+ }
+
+ # Allocate more buffer space if necessary.
+ if (nptr >= dbufsize) {
+ dbufsize = dbufsize + DEF_BUFSIZE
+ call realloc (imid, dbufsize, TY_INT)
+ call realloc (id, dbufsize, TY_INT)
+ call realloc (x, dbufsize, TY_REAL)
+ call realloc (y, dbufsize, TY_REAL)
+ call realloc (nap, dbufsize, TY_INT)
+ call realloc (rap, naperts * dbufsize, TY_REAL)
+ call realloc (mag, naperts * dbufsize, TY_REAL)
+ call realloc (merr, naperts * dbufsize, TY_REAL)
+ }
+
+ # Decode the next data.
+ stat = ph_agetimage (fd, columns, Memc[imname], line, lbufsize)
+
+ } until ((stat == EOF) || (! streq (Memc[imname], Memc[image])))
+
+ call strcpy (Memc[imname], Memc[image], SZ_FNAME)
+
+ }
+
+ if (line != NULL) {
+ call mfree (line, TY_CHAR)
+ line = NULL
+ lbufsize = 0
+ }
+
+ call sfree (sp)
+
+ return (nptr)
+end
diff --git a/noao/digiphot/photcal/mkobsfile/phimtable.x b/noao/digiphot/photcal/mkobsfile/phimtable.x
new file mode 100644
index 00000000..dbbadb9e
--- /dev/null
+++ b/noao/digiphot/photcal/mkobsfile/phimtable.x
@@ -0,0 +1,971 @@
+include <fset.h>
+include "../lib/obsfile.h"
+
+# PH_ESETIMTABLE -- Read in the image set name and image names from the
+# standard input and initialize the table fields.
+
+int procedure ph_esetimtable (imtable, nfilters, verify)
+
+pointer imtable # pointer to the image symbol table
+int nfilters # the number of filters in the filter set
+int verify # verify the user input
+
+int setno, nsymbols, field, stat
+pointer sp, name, image, str, sym
+bool streq()
+int scan(), nscan(), strlen()
+pointer stenter()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (name, SZ_FNAME, TY_CHAR)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Initialize the set and image counters.
+ setno = 0
+ nsymbols = 0
+ field = 1
+ call printf ("\n")
+
+ # Loop over the user defined image sets.
+ repeat {
+
+ if (field == 1) {
+
+ # Print the prompt for the image set name.
+ call printf (
+ "Enter name of image set %d (name, <EOF>=quit entry): ")
+ call pargi (setno + 1)
+ call flush (STDOUT)
+
+ # Read the image set name.
+ stat = scan()
+ if (stat == EOF) {
+ call printf ("\n")
+ break
+ } else {
+ call gargwrd (Memc[name], SZ_FNAME)
+ if (nscan() != 1)
+ next
+ }
+
+ # Verify the image set name.
+ if (verify == YES) {
+ call printf (" Verify name (name, <CR>=%s): ")
+ call pargstr (Memc[name])
+ call flush (STDOUT)
+ stat = scan()
+ if (stat == EOF)
+ call printf ("\n")
+ else {
+ call gargwrd (Memc[str], SZ_FNAME)
+ if (nscan() == 1)
+ call strcpy (Memc[str], Memc[name], SZ_FNAME)
+ }
+ }
+
+ # Prepare for the next image set field.
+ field = field + 1
+ setno = setno + 1
+ next
+
+ } else if (field <= (nfilters + 1)) {
+
+ # Prompt for the image name.
+ call printf (
+ " Enter image name %d (name, <CR>=INDEF): ")
+ call pargi (field - 1)
+ call flush (STDOUT)
+
+ # Get the next image name.
+ stat = scan ()
+ if (stat == EOF) {
+ call printf ("\n")
+ next
+ } else {
+ call gargwrd (Memc[image], SZ_FNAME)
+ if (nscan() != 1)
+ call strcpy ("INDEF", Memc[image], SZ_FNAME)
+ }
+
+ # Verify
+ if (verify == YES) {
+ call printf (
+ " Verify name (name, <CR>=%s): ")
+ call pargstr (Memc[image])
+ call flush (STDOUT)
+ stat = scan ()
+ if (stat == EOF)
+ call printf ("\n")
+ else {
+ call gargwrd (Memc[str], SZ_FNAME)
+ if (nscan() == 1)
+ call strcpy (Memc[str], Memc[image], SZ_FNAME)
+ }
+ }
+
+ nsymbols = nsymbols + 1
+ field = field + 1
+
+ # Enter the new symbol name.
+ if (streq (Memc[image], "INDEF")) {
+ call sprintf (Memc[image+strlen(Memc[image])], SZ_FNAME,
+ "%d")
+ call pargi (nsymbols)
+ }
+ sym = stenter (imtable, Memc[image], LEN_IMT_STRUCT)
+
+ IMT_IMSETNO(sym) = setno
+ IMT_IMNO(sym) = nsymbols
+ IMT_OFFSET(sym) = 0
+ IMT_NENTRIES(sym) = 0
+
+ IMT_XSHIFT(sym) = 0.0
+ IMT_YSHIFT(sym) = 0.0
+ IMT_APERCOR(sym) = 0.0
+ IMT_ITIME(sym) = INDEFR
+ IMT_OTIME(sym) = INDEFR
+ IMT_XAIRMASS(sym) = INDEFR
+ call strcpy ("INDEF", IMT_IFILTER(sym), SZ_FNAME)
+
+ call strcpy (Memc[name], IMT_LABEL(sym), SZ_FNAME)
+ call strcpy (Memc[image], IMT_IMNAME(sym), SZ_FNAME)
+
+ next
+
+ } else {
+ field = 1
+ }
+ }
+
+ # Print a newline.
+ call printf ("\n")
+
+ call sfree (sp)
+
+ return (nsymbols)
+end
+
+
+# PH_SETIMTABLE -- Read in the image names from the image sets file
+# and initialize the fields.
+
+int procedure ph_setimtable (imtable, fd, nfilters, verbose)
+
+pointer imtable # pointer to the symbol table
+int fd # file descriptor of the input text file
+int nfilters # the number of filters in the set
+int verbose # verbose mode
+
+char colon
+int field, setno, nsymbols, nimages
+pointer sp, name, image, sym
+bool streq()
+int fscan(), nscan(), strlen(), itoc()
+pointer stenter()
+
+begin
+ call smark (sp)
+ call salloc (name, SZ_FNAME, TY_CHAR)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+
+ setno = 0
+ nsymbols = 0
+
+ while (fscan (fd) != EOF) {
+
+ # Initialize.
+ nimages = 0
+ field = 1
+ colon = ' '
+
+ # Decode the image set name and the image names for each set.
+ # Skip blank lines and lines beginning with a pound sign.
+
+ repeat {
+
+ if (field == 1) {
+ call gargwrd (Memc[name], SZ_FNAME)
+ if (Memc[name] == EOS || Memc[name] == '#')
+ break
+ field = field + 1
+ if (Memc[name] == ':') {
+ Memc[name] = EOS
+ colon = ':'
+ } else
+ call gargc (colon)
+ if ((nscan() != field) || (colon != ':'))
+ break
+ field = field + 1
+ setno = setno + 1
+ if (Memc[name] == EOS) {
+ if (itoc (setno, Memc[name], SZ_FNAME) <= 0)
+ Memc[name] = EOS
+ }
+ next
+ } else {
+ call gargwrd (Memc[image], SZ_FNAME)
+ if (nscan() != field)
+ break
+ field = field + 1
+ }
+
+ nimages = nimages + 1
+ nsymbols = nsymbols + 1
+
+ if (streq (Memc[image], "INDEF")) {
+ call sprintf (Memc[image+strlen(Memc[image])], SZ_FNAME,
+ "%d")
+ call pargi (nsymbols)
+ }
+
+ # Enter the new symbol name.
+ sym = stenter (imtable, Memc[image], LEN_IMT_STRUCT)
+
+ IMT_IMSETNO(sym) = setno
+ IMT_IMNO(sym) = nsymbols
+ IMT_OFFSET(sym) = 0
+ IMT_NENTRIES(sym) = 0
+
+ IMT_XSHIFT(sym) = 0.0
+ IMT_YSHIFT(sym) = 0.0
+ IMT_APERCOR(sym) = 0.0
+ IMT_ITIME(sym) = INDEFR
+ IMT_XAIRMASS(sym) = INDEFR
+ IMT_OTIME(sym) = INDEFR
+ call strcpy ("INDEF", IMT_IFILTER(sym), SZ_FNAME)
+
+ call strcpy (Memc[name], IMT_LABEL(sym), SZ_FNAME)
+ call strcpy (Memc[image], IMT_IMNAME(sym), SZ_FNAME)
+ }
+
+ # Test for error conditions.
+ if (verbose == NO)
+ next
+ if (Memc[name] == EOS || Memc[name] == '#') {
+ # blank lines and comment lines are skipped
+ } else if (colon != ':') {
+ call eprintf ("Warning: Error decoding image set %s\n")
+ call pargstr (Memc[name])
+ } else if (nimages == 0) {
+ call eprintf ("Warning: Image set %d name %s is empty\n")
+ call pargi (setno)
+ call pargstr (Memc[name])
+ } else if (nimages < nfilters) {
+ call eprintf ("Warning: Image set %d name %s is incomplete\n")
+ call pargi (setno)
+ call pargstr (Memc[name])
+ } else if (nimages > nfilters) {
+ call eprintf ("Warning: Image set %d name %s ")
+ call pargi (setno)
+ call pargstr (Memc[name])
+ call eprintf ("has more than %d images\n")
+ call pargi (nimages)
+ }
+ }
+
+ call sfree (sp)
+
+ return (nsymbols)
+end
+
+
+# PH_ESHIMTABLE -- Enter the correct values of the x-y coordinate shifts
+# the image symbol table from the standard input.
+
+procedure ph_eshimtable (imtable, nimages, verify)
+
+pointer imtable # pointer to the symbol table
+int nimages # number of images
+int verify # verify the user input
+
+char comma
+int i, osetno, setno
+pointer sp, sym, symbol
+real xshift, yshift
+int scan(), nscan()
+pointer sthead(), stnext()
+
+begin
+ if (nimages <= 0)
+ return
+
+ call smark (sp)
+ call salloc (sym, nimages, TY_POINTER)
+
+ # Reverse the order of the symbols in the symbol table.
+
+ symbol = sthead (imtable)
+ do i = nimages, 1, -1 {
+ Memi[sym+i-1] = symbol
+ symbol = stnext (imtable, symbol)
+ }
+
+ call printf ("\n")
+
+ # Loop over the images.
+ osetno = 0
+ do i = 1, nimages {
+
+ symbol = Memi[sym+i-1]
+ setno = IMT_IMSETNO(symbol)
+
+ # Issue the prompt for each set.
+ if (setno != osetno) {
+ call printf ("Image set %d (%s): ")
+ call pargi (setno)
+ call pargstr (IMT_LABEL(symbol))
+ call printf ("Enter the shift in x and y\n")
+ }
+
+ # Issue the prompt for each image.
+ call printf (
+ " Image %s (xshift yshift, <CR>=0.0 0.0, <EOF>=quit entry): " )
+ call pargstr (IMT_IMNAME(symbol))
+ call flush (STDOUT)
+
+ # Initialize
+ osetno = setno
+
+ # Read a line from STDIN.
+ if (scan() == EOF) {
+ call printf ("\n")
+ break
+ }
+
+ # Decode the x and y shifts and update the symbol table.
+ call gargr (xshift)
+ call gargr (yshift)
+ if (nscan() < 1) {
+ xshift = 0.0
+ yshift = 0.0
+ } else if (nscan() < 2) {
+ call reset_scan()
+ call gargr (xshift)
+ call gargc (comma)
+ call gargr (yshift)
+ if (nscan() < 3 || comma != ',')
+ yshift = 0.0
+ }
+ IMT_XSHIFT(symbol) = xshift
+ IMT_YSHIFT(symbol) = yshift
+
+ # Verify the input.
+ if (verify == NO)
+ next
+
+ # Issue the verify prompt for each image.
+ call printf (
+ " Verify (xshift yshift, <CR>=%g %g): " )
+ call pargr (IMT_XSHIFT(symbol))
+ call pargr (IMT_YSHIFT(symbol))
+ call flush (STDOUT)
+
+ # Read a line from STDIN.
+ if (scan() == EOF) {
+ call printf ("\n")
+ next
+ }
+
+ # Decode the x and y shifts.
+ call gargr (xshift)
+ call gargr (yshift)
+ if (nscan() == 2) {
+ IMT_XSHIFT(symbol) = xshift
+ IMT_YSHIFT(symbol) = yshift
+ } else if (nscan() == 1) {
+ call reset_scan()
+ call gargr (xshift)
+ call gargc (comma)
+ call gargr (yshift)
+ IMT_XSHIFT(symbol) = xshift
+ if (nscan() == 3 && comma == ',')
+ IMT_YSHIFT(symbol) = yshift
+ }
+ }
+
+ call printf ("\n")
+
+ call sfree (sp)
+end
+
+
+# PH_SHIMTABLE -- Read in the x and y shifts file and enter the correct
+# x and y shifts in the symbol table.
+
+procedure ph_shimtable (imtable, fd, verbose)
+
+pointer imtable # pointer to the symbol table
+int fd # file descriptor of the input text file
+int verbose # verbose mode
+
+pointer sp, image, fname, sym
+int fscan(), nscan()
+pointer stfind()
+real xoffset, yoffset
+
+begin
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call fstats (fd, F_FILENAME, Memc[fname], SZ_FNAME)
+
+ while (fscan (fd) != EOF) {
+
+ # Get the image name and the x and y shifts data.
+ call gargwrd (Memc[image], SZ_FNAME)
+ call gargr (xoffset)
+ call gargr (yoffset)
+ if (nscan () != 3)
+ next
+
+ # Locate the image name in the symbol table and enter the shifts.
+ sym = stfind (imtable, Memc[image])
+ if (sym == NULL) {
+ if (verbose == YES) {
+ call eprintf (
+ "Warning: File: %s image: %s is ")
+ call pargstr (Memc[fname])
+ call pargstr (Memc[image])
+ call eprintf ("not in the image sets file\n")
+ }
+ next
+ }
+
+ IMT_XSHIFT(sym) = xoffset
+ IMT_YSHIFT(sym) = yoffset
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_EAPIMTABLE -- Enter the correct values of the aperture correction in
+# the image symbol table from the standard input.
+
+procedure ph_eapimtable (imtable, nimages, verify)
+
+pointer imtable # pointer to the symbol table
+int nimages # number of images
+int verify # verify the user input
+
+int i, osetno, setno
+pointer sp, sym, symbol
+real apercor
+int scan(), nscan()
+pointer sthead(), stnext()
+
+begin
+ if (nimages <= 0)
+ return
+
+ call smark (sp)
+ call salloc (sym, nimages, TY_POINTER)
+
+ # Reverse the order of the symbols in the symbol table.
+
+ symbol = sthead (imtable)
+ do i = nimages, 1, -1 {
+ Memi[sym+i-1] = symbol
+ symbol = stnext (imtable, symbol)
+ }
+
+ call printf ("\n")
+
+ # Loop over the images.
+ osetno = 0
+ do i = 1, nimages {
+
+ symbol = Memi[sym+i-1]
+ setno = IMT_IMSETNO(symbol)
+
+ # Issue the prompt for each set.
+ if (setno != osetno) {
+ call printf ("Image set %d (%s): ")
+ call pargi (setno)
+ call pargstr (IMT_LABEL(symbol))
+ call printf ("Enter the aperture correction\n")
+ }
+
+ # Issue the prompt for each image.
+ call printf (
+ " Image %s (magnitude, <CR>=0.0, <EOF>=quit entry): " )
+ call pargstr (IMT_IMNAME(symbol))
+ call flush (STDOUT)
+
+ # Initialize
+ osetno = setno
+
+ # Scan the standard input.
+ if (scan() == EOF) {
+ call printf ("\n")
+ break
+ }
+
+ # Decode the aperture correction and update the symbl table.
+ call gargr (apercor)
+ if (nscan() < 1)
+ apercor = 0.0
+ IMT_APERCOR(symbol) = apercor
+
+ # Optionally verify the input.
+ if (verify == NO)
+ next
+
+ # Issue the verify prompt.
+ call printf (
+ " Verify (magnitude, <CR>=%g): " )
+ call pargr (IMT_APERCOR(symbol))
+ call flush (STDOUT)
+
+ # Scan the standard input.
+ if (scan() == EOF) {
+ call printf ("\n")
+ next
+ }
+
+ # Decode the aperture correction.
+ call gargr (apercor)
+ if (nscan() == 1)
+ IMT_APERCOR(symbol) = apercor
+ }
+
+ call printf ("\n")
+
+ call sfree (sp)
+end
+
+
+# PH_APIMTABLE -- Read in the aperture corrections file and enter the correct
+# aperture correction in the symbol table.
+
+procedure ph_apimtable (imtable, fd, verbose)
+
+pointer imtable # pointer to the symbol table
+int fd # file descriptor of the input text file
+int verbose # print status, warning and error messages
+
+pointer sp, image, fname, sym
+int fscan(), nscan()
+pointer stfind()
+real apercor
+
+begin
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call fstats (fd, F_FILENAME, Memc[fname], SZ_FNAME)
+
+ while (fscan (fd) != EOF) {
+
+ # Get the image name and the x and y shifts data.
+ call gargwrd (Memc[image], SZ_FNAME)
+ call gargr (apercor)
+ if (nscan () != 2)
+ next
+
+ # Locate the image name in the symbol table and enter the shifts.
+ sym = stfind (imtable, Memc[image])
+ if (sym == NULL) {
+ if (verbose == YES) {
+ call eprintf (
+ "Warning: File: %s image: %s ")
+ call pargstr (Memc[fname])
+ call pargstr (Memc[image])
+ call eprintf ("is not in the image sets file\n")
+ }
+ next
+ }
+
+ IMT_APERCOR(sym) = apercor
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_EOBSIMTABLE -- Enter the correct values of the filterid, exposure time and
+# and airmass into the image symbol table from the standard input.
+
+procedure ph_eobsimtable (imtable, nimages, verify)
+
+pointer imtable # pointer to the symbol table
+int nimages # number of images
+int verify # verify the user input
+
+int i, osetno, setno
+pointer sp, sym, filterid, symbol
+real itime, xairmass, otime
+int scan(), nscan(), strncmp()
+pointer sthead(), stnext()
+
+begin
+ if (nimages <= 0)
+ return
+
+ call smark (sp)
+ call salloc (sym, nimages, TY_POINTER)
+ call salloc (filterid, SZ_FNAME, TY_CHAR)
+
+ # Reverse the order of the symbols in the symbol table.
+
+ symbol = sthead (imtable)
+ do i = nimages, 1, -1 {
+ Memi[sym+i-1] = symbol
+ symbol = stnext (imtable, symbol)
+ }
+
+ call printf ("\n")
+
+ # Loop over the images.
+ osetno = 0
+ do i = 1, nimages {
+
+ symbol = Memi[sym+i-1]
+ setno = IMT_IMSETNO(symbol)
+
+ # Issue the prompt for each set.
+ if (setno != osetno) {
+ call printf ("Image set %d (%s): ")
+ call pargi (setno)
+ call pargstr (IMT_LABEL(symbol))
+ call printf (
+ "Enter filter id, exposure time, airmass, observation time\n")
+ }
+
+ # Issue the prompt for each image.
+ call printf (
+ " Image %s (f t X T, <CR>=4 X (INDEF), <EOF>=quit entry): " )
+ call pargstr (IMT_IMNAME(symbol))
+ call flush (STDOUT)
+
+ # Initialize.
+ osetno = setno
+
+ # Scan the standard input.
+ if (scan() == EOF) {
+ call printf ("\n")
+ break
+ }
+
+ # Read in the filterid, exposure time and airmass.
+ call gargwrd (Memc[filterid], SZ_FNAME)
+ call gargr (itime)
+ call gargr (xairmass)
+ call gargr (otime)
+ if (nscan() < 1) {
+ call strcpy ("INDEF", Memc[filterid], SZ_FNAME)
+ itime = INDEFR
+ xairmass = INDEFR
+ otime = INDEFR
+ } else if (nscan() < 2) {
+ itime = INDEFR
+ xairmass = INDEFR
+ otime = INDEFR
+ } else if (nscan() < 3) {
+ xairmass = INDEFR
+ otime = INDEFR
+ } else if (nscan() < 4) {
+ otime = INDEFR
+ }
+
+ # Update the symbol table.
+ if (strncmp (IMT_IFILTER(symbol), "INDEF", 5) == 0)
+ call strcpy (Memc[filterid], IMT_IFILTER(symbol), SZ_FNAME)
+ if (! IS_INDEFR(itime))
+ IMT_ITIME(symbol) = itime
+ if (! IS_INDEFR(xairmass))
+ IMT_XAIRMASS(symbol) = xairmass
+ if (! IS_INDEFR(otime))
+ IMT_OTIME(symbol) = otime
+
+ # Verify the input.
+ if (verify == NO)
+ next
+
+ # Issue the verify prompt.
+ call printf (
+ " Verify (f t X T, <CR>=%s %g %g %0.1h): ")
+ call pargstr (IMT_IFILTER(symbol))
+ call pargr (IMT_ITIME(symbol))
+ call pargr (IMT_XAIRMASS(symbol))
+ call pargr (IMT_OTIME(symbol))
+ call flush (STDOUT)
+
+ # Scan the standard input.
+ if (scan() == EOF) {
+ call printf ("\n")
+ next
+ }
+
+ # Read in the filterid, exposure time and airmass.
+ call gargwrd (Memc[filterid], SZ_FNAME)
+ call gargr (itime)
+ call gargr (xairmass)
+ call gargr (otime)
+ if (nscan() == 4) {
+ call strcpy (Memc[filterid], IMT_IFILTER(symbol), SZ_FNAME)
+ IMT_ITIME(symbol) = itime
+ IMT_XAIRMASS(symbol) = xairmass
+ IMT_OTIME(symbol) = otime
+ } else if (nscan() == 3) {
+ call strcpy (Memc[filterid], IMT_IFILTER(symbol), SZ_FNAME)
+ IMT_ITIME(symbol) = itime
+ IMT_XAIRMASS(symbol) = xairmass
+ } else if (nscan() == 2) {
+ call strcpy (Memc[filterid], IMT_IFILTER(symbol), SZ_FNAME)
+ IMT_ITIME(symbol) = itime
+ } else if (nscan() == 1)
+ call strcpy (Memc[filterid], IMT_IFILTER(symbol), SZ_FNAME)
+ }
+
+ call printf ("\n")
+
+ call sfree (sp)
+end
+
+
+# PH_OBSIMTABLE -- Enter the correct values of the exposure time, airmass and
+# and filter id into the image table. The exposure time entered into the
+# image table is the effective exposure time required to convert the
+# computed magnitudes to the new exposure time.
+
+procedure ph_obsimtable (imtable, fd, columns, verbose)
+
+pointer imtable # pointer to the symbol table
+int fd # file descriptor of the input text file
+int columns[ARB] # the list of input columns
+int verbose # print status, warning and error messages
+
+int stat, lbufsize
+pointer sp, image, fname, filterid, line, sym
+real itime, airmass, otime
+bool streq()
+int ph_nxtimage()
+pointer stfind()
+
+begin
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (filterid, SZ_FNAME, TY_CHAR)
+
+ Memc[image] = EOS
+ call fstats (fd, F_FILENAME, Memc[fname], SZ_FNAME)
+
+ line = NULL
+ lbufsize = 0
+ repeat {
+
+ # Get the image name.
+ stat = ph_nxtimage (fd, columns, Memc[image], line, lbufsize)
+ if (stat == EOF)
+ break
+
+ # Locate the image name in the symbol table.
+ sym = stfind (imtable, Memc[image])
+ if (sym == NULL) {
+ if (verbose == YES) {
+ call eprintf (
+ "Warning: File: %s image: %s ")
+ call pargstr (Memc[fname])
+ call pargstr (Memc[image])
+ call eprintf ("is not in the image sets file\n")
+ }
+ next
+ }
+
+ # Decode the data.
+ call ph_obsdata (Memc[line], columns, Memc[filterid], SZ_FNAME,
+ itime, airmass, otime)
+
+ # Enter the data in the symbol table.
+ if (! IS_INDEFR(itime))
+ IMT_ITIME(sym) = itime
+ if (! IS_INDEFR(airmass))
+ IMT_XAIRMASS(sym) = airmass
+ if (! IS_INDEFR(otime))
+ IMT_OTIME(sym) = otime
+ if (! streq (Memc[filterid], "INDEF"))
+ call strcpy (Memc[filterid], IMT_IFILTER(sym), SZ_FNAME)
+ }
+
+ if (line != NULL) {
+ call mfree (line, TY_CHAR)
+ line = NULL
+ lbufsize = 0
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_MKIMTABLE -- Create the image table using the input text file(s)
+# and the list of column numbers defining the fields required by the
+# program.
+
+int procedure ph_mkimtable (imtable, fd, columns, objid, x, y, mag, merr,
+ imid, id, nptr, normtime, sortimid, verbose)
+
+pointer imtable # pointer to the symbol table
+int fd # file descriptor of the input text file
+int columns[ARB] # the list of input columns
+pointer objid # pointer to the id array
+pointer x # pointer to the x coordinate array
+pointer y # pointer to the y coordinate array
+pointer mag # pointer to the magnitude array
+pointer merr # pointer to the magnitude error array
+pointer imid # pointer to the image id
+pointer id # pointer to the image ids
+int nptr # pointer to the current data point
+int normtime # normalize exposure times
+int sortimid # does data need to be sorted on imid or id
+int verbose # print status, warning and error messages
+
+int idcol, stat, dbufsize, lbufsize
+pointer sp, fname, image, imname, filterid, objname, line, sym
+real itime, airmass, otime
+
+bool streq()
+int ph_nxtimage(), ph_stardata(), ph_getimage()
+pointer stfind()
+
+begin
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+ call salloc (filterid, SZ_FNAME, TY_CHAR)
+ call salloc (objname, DEF_LENLABEL, TY_CHAR)
+
+ # Is there id information.
+ idcol = columns[CAT_ID]
+
+ # Allocate some initial buffer space.
+ if (nptr == 0) {
+ dbufsize = DEF_BUFSIZE
+ if (idcol > 0)
+ call malloc (objid, dbufsize * (DEF_LENLABEL+ 1), TY_CHAR)
+ call malloc (x, dbufsize, TY_REAL)
+ call malloc (y, dbufsize, TY_REAL)
+ call malloc (mag, dbufsize, TY_REAL)
+ call malloc (merr, dbufsize, TY_REAL)
+ call malloc (imid, dbufsize, TY_INT)
+ call malloc (id, dbufsize, TY_INT)
+ }
+
+ # Initialize.
+ Memc[image] = EOS
+ call fstats (fd, F_FILENAME, Memc[fname], SZ_FNAME)
+
+ # Find the first image.
+ lbufsize = 0
+ line = NULL
+ stat = ph_nxtimage (fd, columns, Memc[image], line, lbufsize)
+
+ # Read the data.
+ while (stat != EOF) {
+
+ # Locate the image name in the symbol table.
+ sym = stfind (imtable, Memc[image])
+ if (sym == NULL) {
+ if (Memc[image] != EOS && verbose == YES) {
+ call eprintf (
+ "Warning: File: %s Image: %s ")
+ call pargstr (Memc[fname])
+ call pargstr (Memc[image])
+ call eprintf ("is not in the image sets file\n")
+ }
+ stat = ph_nxtimage (fd, columns, Memc[image], line, lbufsize)
+ next
+ }
+
+ # Decode the filter, exposure time and airmass information.
+ call ph_imdata (Memc[line], columns, Memc[filterid], SZ_FNAME,
+ itime, airmass, otime)
+
+ # Enter the new values in the symbol table.
+ if (IS_INDEFR(IMT_ITIME(sym))) {
+ if (IS_INDEFR(itime))
+ IMT_ITIME(sym) = 1.0
+ else if (normtime == NO)
+ IMT_ITIME(sym) = 1.0
+ else
+ IMT_ITIME(sym) = itime
+ } else if (IMT_NENTRIES(sym) > 0) {
+ # do nothing
+ } else if (IS_INDEFR(itime)) {
+ if (normtime == NO)
+ IMT_ITIME(sym) = 1.0
+ } else {
+ IMT_ITIME(sym) = IMT_ITIME(sym) / itime
+ }
+ if (IS_INDEFR(IMT_XAIRMASS(sym)))
+ IMT_XAIRMASS(sym) = airmass
+ if (IS_INDEFR(IMT_OTIME(sym)))
+ IMT_OTIME(sym) = otime
+ if (streq (IMT_IFILTER(sym), "INDEF"))
+ call strcpy (Memc[filterid], IMT_IFILTER(sym), SZ_FNAME)
+
+ # Does the data need to be sorted on image or id. This should
+ # usually not be necessary for most DAOPHOT or APPHOT data
+ # but will be necessary if data from the same images is contained
+ # in more than 1 file.
+
+ if (IMT_NENTRIES(sym) > 0)
+ sortimid = YES
+ else
+ IMT_OFFSET(sym) = nptr + 1
+
+ # Get the data.
+ repeat {
+
+ # Decode x, y, magnitude and error.
+ if (ph_stardata (Memc[line], columns, Memc[objname],
+ Memr[x+nptr], Memr[y+nptr], Memr[mag+nptr],
+ Memr[merr+nptr]) == OK) {
+ if (idcol > 0)
+ call strcpy (Memc[objname],
+ Memc[objid+nptr*(DEF_LENLABEL+1)],
+ DEF_LENLABEL)
+ Memi[imid+nptr] = IMT_IMNO(sym)
+ IMT_NENTRIES(sym) = IMT_NENTRIES(sym) + 1
+ Memi[id+nptr] = IMT_NENTRIES(sym)
+ nptr = nptr + 1
+ }
+
+ # Allocate more buffer space if necessary.
+ if (nptr >= dbufsize) {
+ dbufsize = dbufsize + DEF_BUFSIZE
+ if (idcol > 0)
+ call realloc (objid, dbufsize * (DEF_LENLABEL + 1),
+ TY_CHAR)
+ call realloc (x, dbufsize, TY_REAL)
+ call realloc (y, dbufsize, TY_REAL)
+ call realloc (mag, dbufsize, TY_REAL)
+ call realloc (merr, dbufsize, TY_REAL)
+ call realloc (imid, dbufsize, TY_INT)
+ call realloc (id, dbufsize, TY_INT)
+ }
+
+ # Decode the next data.
+ stat = ph_getimage (fd, columns, Memc[imname], line, lbufsize)
+
+ } until ((stat == EOF) || (! streq (Memc[imname], Memc[image])))
+
+ call strcpy (Memc[imname], Memc[image], SZ_FNAME)
+
+ }
+
+ if (line != NULL) {
+ call mfree (line, TY_CHAR)
+ line = NULL
+ lbufsize = 0
+ }
+
+ call sfree (sp)
+
+ return (nptr)
+end
diff --git a/noao/digiphot/photcal/mkobsfile/phmatch.x b/noao/digiphot/photcal/mkobsfile/phmatch.x
new file mode 100644
index 00000000..59fadb60
--- /dev/null
+++ b/noao/digiphot/photcal/mkobsfile/phmatch.x
@@ -0,0 +1,487 @@
+include <mach.h>
+include "../lib/obsfile.h"
+
+# PH_JOIN -- For each individual field join the data from each image
+# line for line.
+
+procedure ph_join (out, label, sym, filters, nfilters, objid, x, y, mag, merr,
+ allfilters, wrap, verbose)
+
+int out # the output file descriptor
+char label[ARB] # the label string
+pointer sym[ARB] # list of pointers to the image set data
+char filters[ARB] # the filter id string
+int nfilters # number of filters in an image set
+char objid[DEF_LENLABEL,ARB] # array of object ids
+real x[ARB] # array of shifted x coordinates
+real y[ARB] # array of shifted y coordinates
+real mag[ARB] # array of corrected magnitudes
+real merr[ARB] # array of magnitude errors
+int allfilters # match objects in all filters ?
+int wrap # format the output file for easy reading ?
+int verbose # print status, warning and error messages ?
+
+int i, j, nobjs, dptr, len_label, useid
+pointer sp, outfilter, idlabel, newlabel, bptrs, eptrs
+bool streq()
+int ph_nthlabel(), strlen()
+
+begin
+ # Find the maximum length of the output. Return if there is no data
+ # in any of the frames, or if there is no data in one frame and
+ # the match in all filters switch is on.
+
+ if (allfilters == YES) {
+ nobjs = MAX_INT
+ do i = 1, nfilters {
+ if (sym[i] == NULL) {
+ nobjs = 0
+ break
+ }
+ if (IMT_NENTRIES(sym[i]) == 0) {
+ nobjs = 0
+ break
+ }
+ nobjs = min (nobjs, IMT_NENTRIES(sym[i]))
+ }
+ } else {
+ nobjs = 0
+ do i = 1, nfilters {
+ if (sym[i] == NULL)
+ next
+ nobjs = max (nobjs, IMT_NENTRIES(sym[i]))
+ }
+ }
+
+
+ # Return if there is no data.
+ if (nobjs <= 0) {
+ if (verbose == YES) {
+ call printf (
+ "\tImage set: %s 0 stars written to the observations file\n")
+ call pargstr (label)
+ }
+ return
+ }
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (idlabel, SZ_FNAME, TY_CHAR)
+ call salloc (newlabel, SZ_FNAME, TY_CHAR)
+ call salloc (outfilter, SZ_FNAME, TY_CHAR)
+ call salloc (bptrs, nfilters, TY_INT)
+ call salloc (eptrs, nfilters, TY_INT)
+
+ # Determine whether or not to use the object id as the object label
+ # and determine the length of the label.
+
+ if (objid[1,1] == EOS) {
+ useid = NO
+ if (nobjs == 1)
+ len_label = max (DEF_LENLABEL, strlen (label))
+ else
+ len_label = max (DEF_LENLABEL, strlen (label)+DEF_LENINDEX)
+ } else {
+ useid = YES
+ len_label = DEF_LENLABEL
+ }
+
+ # Initialize the arrays which point to the beginning and ending of
+ # the data for each image in the set.
+
+ do j = 1, nfilters {
+ if (sym[j] == NULL) {
+ Memi[bptrs+j-1] = 0
+ Memi[eptrs+j-1] = 0
+ } else {
+ Memi[bptrs+j-1] = IMT_OFFSET(sym[j])
+ Memi[eptrs+j-1] = IMT_OFFSET(sym[j]) + IMT_NENTRIES(sym[j]) - 1
+ }
+ }
+
+ # Write out the output.
+ do i = 1, nobjs {
+
+ # Determine the object id. This is the object id of the first
+ # defined filter.
+ if (useid == YES) {
+ Memc[idlabel] = EOS
+ do j = 1, nfilters {
+ if (Memi[bptrs+j-1] == 0)
+ next
+ call strcpy (objid[1,Memi[bptrs+j-1]], Memc[idlabel],
+ DEF_LENLABEL)
+ break
+ }
+ }
+
+ do j = 1, nfilters {
+
+ # Write the label.
+ if (j == 1) {
+ if (useid == YES && Memc[idlabel] != EOS) {
+ call fprintf (out, "%*.*s ")
+ call pargi (-len_label)
+ call pargi (len_label)
+ call pargstr (Memc[idlabel])
+ } else if (nobjs == 1) {
+ call fprintf (out, "%*.*s ")
+ call pargi (-len_label)
+ call pargi (len_label)
+ call pargstr (label)
+ } else {
+ call sprintf (Memc[newlabel], SZ_FNAME, "%s-%d")
+ call pargstr (label)
+ call pargi (i)
+ call fprintf (out, "%*.*s ")
+ call pargi (-len_label)
+ call pargi (len_label)
+ call pargstr (Memc[newlabel])
+ }
+ } else if (wrap == YES) {
+ call fprintf (out, "%*.*s ")
+ call pargi (-len_label)
+ call pargi (len_label)
+ call pargstr ("*")
+ } else {
+ call fprintf (out, " ")
+ }
+
+ # Write the results.
+ if (ph_nthlabel (filters, j, Memc[outfilter], SZ_FNAME) != j)
+ Memc[outfilter] = EOS
+ dptr = Memi[bptrs+j-1]
+ if (dptr == 0) {
+ call fprintf (out,
+ "%-10.10s %11.1h %6.3f %9.3f %9.3f %7.3f %6.3f")
+ call pargstr (Memc[outfilter])
+ call pargr (INDEFR)
+ call pargr (INDEFR)
+ call pargr (INDEFR)
+ call pargr (INDEFR)
+ call pargr (INDEFR)
+ call pargr (INDEFR)
+ } else {
+ if (IMT_OTIME(sym[j]) >= 0.0 && IMT_OTIME(sym[j]) <= 24.0)
+ call fprintf (out,
+ "%-10.10s %11.1h %6.3f %9.3f %9.3f %7.3f %6.3f")
+ else
+ call fprintf (out,
+ "%-10.10s %11g %6.3f %9.3f %9.3f %7.3f %6.3f")
+ if (streq (IMT_IFILTER(sym[j]), "INDEF"))
+ call pargstr (Memc[outfilter])
+ else
+ call pargstr (IMT_IFILTER(sym[j]))
+ call pargr (IMT_OTIME(sym[j]))
+ call pargr (IMT_XAIRMASS(sym[j]))
+ call pargr (x[dptr] - IMT_XSHIFT(sym[j]))
+ call pargr (y[dptr] - IMT_YSHIFT(sym[j]))
+ call pargr (mag[dptr])
+ call pargr (merr[dptr])
+ }
+ if (wrap == YES)
+ call fprintf (out, "\n")
+ else if (j == nfilters)
+ call fprintf (out, "\n")
+
+ # Increment the data pointers making sure to check for non-
+ # existent data and unequal length object lists.
+
+ if (dptr == 0)
+ next
+ if (dptr >= Memi[eptrs+j-1])
+ dptr = 0
+ else
+ Memi[bptrs+j-1] = dptr + 1
+ }
+ }
+
+ if (verbose == YES) {
+ call printf (
+ "\tImage set: %s %d stars written to the observations file\n")
+ call pargstr (label)
+ call pargi (nobjs)
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_MERGE -- For an individual field join the data from each image (filter) in
+# the image (filter) set by matching the x-y positions.
+
+procedure ph_merge (out, label, sym, filters, nfilters, objid, x, y, mag, merr,
+ ysort, match, index, ndata, tolerance, allfilters, wrap, verbose)
+
+int out # the output file descriptor
+char label[ARB] # label string
+pointer sym[ARB] # list of pointers to the image set data
+char filters[ARB] # filter string
+int nfilters # number of images an image set
+char objid[DEF_LENLABEL,ARB] # array of object ids
+real x[ARB] # array of x coordinates
+real y[ARB] # array of y coordinates
+real mag[ARB] # array of magnitudes
+real merr[ARB] # array of magnitude errors
+int ysort[ARB] # the y sort index
+int match[ARB] # the matching array
+int index[ndata,ARB] # the matching index array
+int ndata # the number of data points
+real tolerance # tolerance in pixels
+int allfilters # match objects in all filters
+int wrap # format the output file for easy reading ?
+int verbose # print status, warning and error messages
+
+int i, j, k, l, biptr, eiptr, bjptr, ejptr, len_label
+int ntimes, nframe, nobjs, nmatch, starok, lsort, useid
+pointer sp, idlabel, newlabel, outfilter
+real tol2, dx, dy, maxrsq, distsq
+bool streq()
+int ph_nthlabel(), strlen()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (idlabel, SZ_FNAME, TY_CHAR)
+ call salloc (newlabel, SZ_FNAME, TY_CHAR)
+ call salloc (outfilter, SZ_FNAME, TY_CHAR)
+
+ # Initialize.
+ nframe = 0
+ do i = 1, nfilters {
+ if (sym[i] != NULL) {
+ call amovki (NO, match[IMT_OFFSET(sym[i])],
+ IMT_NENTRIES(sym[i]))
+ if (IMT_NENTRIES(sym[i]) > 0)
+ nframe = nframe + 1
+ }
+ }
+ tol2 = tolerance ** 2
+ nobjs = 0
+ if (allfilters == YES)
+ ntimes = 1
+ else
+ ntimes = nfilters
+
+ # Loop over the filters.
+ do i = 1, ntimes {
+
+ # Find the data pointers for the first frame.
+ if (sym[i] == NULL)
+ next
+ biptr = IMT_OFFSET(sym[i])
+ if (biptr == 0)
+ next
+ eiptr = biptr + IMT_NENTRIES(sym[i]) - 1
+
+ # Initialize.
+ nmatch = 0
+
+ # Clear the index array.
+ do j = 1, nfilters
+ call aclri (index[1,j], ndata)
+
+ # Loop over the other frames matching stars.
+ do j = i + 1, nfilters {
+
+ # Find the data pointers for the second frame.
+ if (sym[j] == NULL)
+ next
+ bjptr = IMT_OFFSET(sym[j])
+ if (bjptr == 0)
+ next
+ ejptr = bjptr + IMT_NENTRIES(sym[j]) - 1
+
+ # Loop over the stars in the first frame.
+ nmatch = 0
+ do k = biptr, eiptr {
+
+ if (match[ysort[k]] == YES)
+ next
+ if (IS_INDEFR(x[ysort[k]]) || IS_INDEFR(y[ysort[k]]))
+ next
+ nmatch = nmatch + 1
+ index[ysort[k]-biptr+1,i] = ysort[k]
+ maxrsq = tol2
+ lsort = 0
+
+ do l = bjptr, ejptr {
+ if (match[ysort[l]] == YES)
+ next
+ if (IS_INDEFR(x[ysort[l]]) || IS_INDEFR(y[ysort[l]]))
+ next
+ dy = y[ysort[l]] - y[ysort[k]]
+ if (dy > tolerance)
+ break
+ dx = x[ysort[l]] - x[ysort[k]]
+ distsq = dx * dx + dy * dy
+ if (distsq > maxrsq)
+ next
+ if (lsort > 0)
+ match[ysort[lsort]] = NO
+ match[ysort[l]] = YES
+ index[ysort[k]-biptr+1,j] = ysort[l]
+ maxrsq = distsq
+ lsort = l
+ }
+ }
+
+ # If all the stars have been matched quit the loop.
+ if (nmatch == 0)
+ break
+ }
+
+ # Search for unmatched stars in the last frame.
+ if ((nframe == 1) || (allfilters == NO && i == nfilters)) {
+ do k = biptr, eiptr {
+ if (match[ysort[k]] == YES)
+ next
+ if (IS_INDEFR(x[ysort[k]]) || IS_INDEFR(y[ysort[k]]))
+ next
+ nmatch = nmatch + 1
+ index[ysort[k]-biptr+1,i] = ysort[k]
+ }
+ }
+
+ # Use the individual star id.
+ if (objid[1,1] == EOS)
+ useid = NO
+ else
+ useid = YES
+
+ # Write the results.
+ do j = 1, eiptr - biptr + 1 {
+
+ # Break if no stars were matched.
+ if (nmatch <= 0)
+ break
+ #next
+
+ # If the allfilters switch is on only print points with
+ # data for all the filters, otherwise print all the objects.
+
+ if (allfilters == YES) {
+ starok = YES
+ do k = 1, nfilters {
+ if (index[j,k] > 0)
+ next
+ starok = NO
+ break
+ }
+ } else {
+ starok = NO
+ do k = 1, nfilters {
+ if (index[j,k] <= 0)
+ next
+ starok = YES
+ break
+ }
+ }
+ if (starok == NO)
+ next
+
+ if (useid == YES)
+ len_label = DEF_LENLABEL
+ else if (nobjs == 1)
+ len_label = max (DEF_LENLABEL, strlen (label))
+ else
+ len_label = max (DEF_LENLABEL, strlen (label)+DEF_LENINDEX)
+
+ # Find the label.
+ if (useid == YES) {
+ Memc[idlabel] = EOS
+ do k = 1, nfilters {
+ if (index[j,k] == 0)
+ next
+ call strcpy (objid[1,index[j,k]], Memc[idlabel],
+ DEF_LENLABEL)
+ break
+ }
+ }
+
+ # Loop over the filters, writing the data for each point.
+ do k = 1, nfilters {
+
+ # Write the label.
+ if (k == 1) {
+ if (useid == YES && Memc[idlabel] != EOS) {
+ call fprintf (out, "%*.*s ")
+ call pargi (-len_label)
+ call pargi (len_label)
+ call pargstr (Memc[idlabel])
+ } else if ((nmatch == 1) && (nobjs == 0)) {
+ call fprintf (out, "%*.*s ")
+ call pargi (-len_label)
+ call pargi (len_label)
+ call pargstr (label)
+ } else {
+ call sprintf (Memc[newlabel], SZ_FNAME, "%s-%d")
+ call pargstr (label)
+ call pargi (nobjs + 1)
+ call fprintf (out, "%*.*s ")
+ call pargi (-len_label)
+ call pargi (len_label)
+ call pargstr (Memc[newlabel])
+ }
+ } else if (wrap == YES) {
+ call fprintf (out, "%*.*s ")
+ call pargi (-len_label)
+ call pargi (len_label)
+ call pargstr ("*")
+ } else {
+ call fprintf (out, " ")
+ }
+
+ # Write the data.
+ if (ph_nthlabel (filters, k, Memc[outfilter],
+ SZ_FNAME) != k)
+ Memc[outfilter] = EOS
+ if (index[j,k] == 0) {
+ call fprintf (out,
+ "%-10.10s %11.1h %6.3f %9.3f %9.3f %7.3f %6.3f")
+ call pargstr (Memc[outfilter])
+ call pargr (INDEFR)
+ call pargr (INDEFR)
+ call pargr (INDEFR)
+ call pargr (INDEFR)
+ call pargr (INDEFR)
+ call pargr (INDEFR)
+ } else {
+ if (IMT_OTIME(sym[k]) >= 0.0 &&
+ IMT_OTIME(sym[k]) <= 24.0)
+ call fprintf (out,
+ "%-10.10s %11.1h %6.3f %9.3f %9.3f %7.3f %6.3f")
+ else
+ call fprintf (out,
+ "%-10.10s %11g %6.3f %9.3f %9.3f %7.3f %6.3f")
+ if (streq (IMT_IFILTER(sym[k]), "INDEF"))
+ call pargstr (Memc[outfilter])
+ else
+ call pargstr (IMT_IFILTER(sym[k]))
+ call pargr (IMT_OTIME(sym[k]))
+ call pargr (IMT_XAIRMASS(sym[k]))
+ call pargr (x[index[j,k]] - IMT_XSHIFT(sym[k]))
+ call pargr (y[index[j,k]] - IMT_YSHIFT(sym[k]))
+ call pargr (mag[index[j,k]])
+ call pargr (merr[index[j,k]])
+ }
+ if (wrap == YES)
+ call fprintf (out, "\n")
+ else if (k == nfilters)
+ call fprintf (out, "\n")
+
+ }
+
+ nobjs = nobjs + 1
+ }
+ }
+
+ if (verbose == YES) {
+ call printf (
+ "\tImage set: %s %d stars written to the observations file\n")
+ call pargstr (label)
+ call pargi (nobjs)
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/photcal/mkobsfile/phsort.x b/noao/digiphot/photcal/mkobsfile/phsort.x
new file mode 100644
index 00000000..a29920b0
--- /dev/null
+++ b/noao/digiphot/photcal/mkobsfile/phsort.x
@@ -0,0 +1,528 @@
+include "../lib/obsfile.h"
+
+define LOGPTR 32 # log2(maxpts) (4e9)
+
+# PH_1C4R2ISORT -- Vector quicksort on the first and second indices arrays,
+# where the second index is used to resolve ambiguities in the first index.
+# An additional 4 input arrays are sorted as well.
+
+procedure ph_1c4r2isort (label, d1, d2, d3, d4, findex, sindex, npix)
+
+char label[DEF_LENLABEL,ARB] # the char array
+real d1[ARB] # the first input data array
+real d2[ARB] # the second input data array
+real d3[ARB] # the third input data array
+real d4[ARB] # the fourth input data array
+int findex[ARB] # first index array which is sorted on
+int sindex[ARB] # second index array which is sorted on
+int npix # number of pixels
+
+real tempr
+int fpivot, spivot, tempi
+int i, j, k, p, lv[LOGPTR], uv[LOGPTR]
+char tempc[DEF_LENLABEL]
+int ph_2icompare()
+define swapi {tempi=$1;$1=$2;$2=tempi}
+define swapr {tempr=$1;$1=$2;$2=tempr}
+define swapc {call strcpy ($1, tempc, DEF_LENLABEL);call strcpy ($2, $1, DEF_LENLABEL);call strcpy (tempc, $2, DEF_LENLABEL)}
+
+begin
+ lv[1] = 1
+ uv[1] = npix
+ p = 1
+
+ while (p > 0) {
+ if (lv[p] >= uv[p]) # only one elem in this subset
+ p = p - 1 # pop stack
+ else {
+ # Dummy do loop to trigger the Fortran optimizer.
+ do p = p, ARB {
+ i = lv[p] - 1
+ j = uv[p]
+
+ # Select as the pivot the element at the center of the
+ # array, to avoid quadratic behavior on an already sorted
+ # array.
+
+ k = (lv[p] + uv[p]) / 2
+ swapr (d1[j], d1[k])
+ swapr (d2[j], d2[k])
+ swapr (d3[j], d3[k])
+ swapr (d4[j], d4[k])
+ swapc (label[1,j], label[1,k])
+ swapi (findex[j], findex[k])
+ swapi (sindex[j], sindex[k])
+ fpivot = findex[j] # pivot line
+ spivot = sindex[j]
+
+ while (i < j) {
+ for (i=i+1; ph_2icompare (findex[i], sindex[i], fpivot,
+ spivot) < 0; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (ph_2icompare (findex[j], sindex[j], fpivot,
+ spivot) <= 0)
+ break
+ if (i < j) { # switch elements
+ swapr (d1[i], d1[j])
+ swapr (d2[i], d2[j])
+ swapr (d3[i], d3[j])
+ swapr (d4[i], d4[j])
+ swapc (label[1,i], label[1,j])
+ swapi (sindex[i], sindex[j])
+ swapi (findex[i], findex[j]) # interchange elements
+ }
+ }
+
+ j = uv[p] # move pivot to position i
+ swapr (d1[i], d1[j])
+ swapr (d2[i], d2[j])
+ swapr (d3[i], d3[j])
+ swapr (d4[i], d4[j])
+ swapc (label[1,i], label[1,j])
+ swapi (sindex[i], sindex[j])
+ swapi (findex[i], findex[j]) # interchange elements
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ break
+ }
+ p = p + 1 # push onto stack
+ }
+ }
+end
+
+
+# PH_4R2ISORT -- Vector quicksort on the first and second indices arrays,
+# where the second index is used to resolve ambiguities in the first index.
+# An additional 4 input arrays are sorted as well.
+
+procedure ph_4r2isort (d1, d2, d3, d4, findex, sindex, npix)
+
+real d1[ARB] # the first input data array
+real d2[ARB] # the second input data array
+real d3[ARB] # the third input data array
+real d4[ARB] # the fourth input data array
+int findex[ARB] # first index array which is sorted on
+int sindex[ARB] # second index array which is sorted on
+int npix # number of pixels
+
+int fpivot, spivot, tempi
+int i, j, k, p, lv[LOGPTR], uv[LOGPTR]
+real tempr
+int ph_2icompare()
+define swapi {tempi=$1;$1=$2;$2=tempi}
+define swapr {tempr=$1;$1=$2;$2=tempr}
+
+begin
+ lv[1] = 1
+ uv[1] = npix
+ p = 1
+
+ while (p > 0) {
+ if (lv[p] >= uv[p]) # only one elem in this subset
+ p = p - 1 # pop stack
+ else {
+ # Dummy do loop to trigger the Fortran optimizer.
+ do p = p, ARB {
+ i = lv[p] - 1
+ j = uv[p]
+
+ # Select as the pivot the element at the center of the
+ # array, to avoid quadratic behavior on an already sorted
+ # array.
+
+ k = (lv[p] + uv[p]) / 2
+ swapr (d1[j], d1[k])
+ swapr (d2[j], d2[k])
+ swapr (d3[j], d3[k])
+ swapr (d4[j], d4[k])
+ swapi (findex[j], findex[k])
+ swapi (sindex[j], sindex[k])
+ fpivot = findex[j] # pivot line
+ spivot = sindex[j]
+
+ while (i < j) {
+ for (i=i+1; ph_2icompare (findex[i], sindex[i], fpivot,
+ spivot) < 0; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (ph_2icompare (findex[j], sindex[j], fpivot,
+ spivot) <= 0)
+ break
+ if (i < j) { # switch elements
+ swapr (d1[i], d1[j])
+ swapr (d2[i], d2[j])
+ swapr (d3[i], d3[j])
+ swapr (d4[i], d4[j])
+ swapi (sindex[i], sindex[j])
+ swapi (findex[i], findex[j]) # interchange elements
+ }
+ }
+
+ j = uv[p] # move pivot to position i
+ swapr (d1[i], d1[j])
+ swapr (d2[i], d2[j])
+ swapr (d3[i], d3[j])
+ swapr (d4[i], d4[j])
+ swapi (sindex[i], sindex[j])
+ swapi (findex[i], findex[j]) # interchange elements
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ break
+ }
+ p = p + 1 # push onto stack
+ }
+ }
+end
+
+
+# PH_3RIRSORT -- Vector quicksort on the index and the rindex array,
+# where the rindex array is used to resolve ambiguities in the index array.
+# The three real arrays are sorted as well.
+
+procedure ph_3rirsort (d1, d2, d3, index, rindex, npix)
+
+real d1[ARB] # the first input data array
+real d2[ARB] # the second input data array
+real d3[ARB] # the third input data array
+int index[ARB] # first index array which is sorted on
+real rindex[ARB] # second index array which is sorted on
+int npix # number of pixels
+
+int fpivot, tempi
+int i, j, k, p, lv[LOGPTR], uv[LOGPTR]
+real rpivot, tempr
+int ph_ircompare()
+define swapi {tempi=$1;$1=$2;$2=tempi}
+define swapr {tempr=$1;$1=$2;$2=tempr}
+
+begin
+ lv[1] = 1
+ uv[1] = npix
+ p = 1
+
+ while (p > 0) {
+ if (lv[p] >= uv[p]) # only one elem in this subset
+ p = p - 1 # pop stack
+ else {
+ # Dummy do loop to trigger the Fortran optimizer.
+ do p = p, ARB {
+ i = lv[p] - 1
+ j = uv[p]
+
+ # Select as the pivot the element at the center of the
+ # array, to avoid quadratic behavior on an already sorted
+ # array.
+
+ k = (lv[p] + uv[p]) / 2
+ swapr (d1[j], d1[k])
+ swapr (d2[j], d2[k])
+ swapr (d3[j], d3[k])
+ swapi (index[j], index[k])
+ swapr (rindex[j], rindex[k])
+ fpivot = index[j] # pivot line
+ rpivot = rindex[j]
+
+ while (i < j) {
+ for (i=i+1; ph_ircompare (index[i], rindex[i], fpivot,
+ rpivot) < 0; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (ph_ircompare (index[j], rindex[j], fpivot,
+ rpivot) <= 0)
+ break
+ if (i < j) { # switch elements
+ swapr (d1[i], d1[j])
+ swapr (d2[i], d2[j])
+ swapr (d3[i], d3[j])
+ swapr (rindex[i], rindex[j])
+ swapi (index[i], index[j]) # interchange elements
+ }
+ }
+
+ j = uv[p] # move pivot to position i
+ swapr (d1[i], d1[j])
+ swapr (d2[i], d2[j])
+ swapr (d3[i], d3[j])
+ swapr (rindex[i], rindex[j])
+ swapi (index[i], index[j]) # interchange elements
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ break
+ }
+ p = p + 1 # push onto stack
+ }
+ }
+end
+
+
+# PH_QSORT -- Vector quicksort. In this version the index array is
+# sorted.
+
+procedure ph_qsort (data, index, npix, offset)
+
+real data[ARB] # data array
+int index[ARB] # index array
+int npix # number of pixels
+int offset # the index offset
+
+int i, j, lv[LOGPTR], p, uv[LOGPTR], temp
+real pivot
+
+begin
+ # Initialize the indices for an inplace sort.
+ do i = 1, npix
+ index[i] = i
+
+ p = 1
+ lv[1] = 1
+ uv[1] = npix
+ while (p > 0) {
+
+ # If only one elem in subset pop stack otherwise pivot line.
+ if (lv[p] >= uv[p])
+ p = p - 1
+ else {
+ i = lv[p] - 1
+ j = uv[p]
+ pivot = data[index[j]]
+
+ while (i < j) {
+ for (i=i+1; data[index[i]] < pivot; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (data[index[j]] <= pivot)
+ break
+ if (i < j) { # out of order pair
+ temp = index[j] # interchange elements
+ index[j] = index[i]
+ index[i] = temp
+ }
+ }
+
+ j = uv[p] # move pivot to position i
+ temp = index[j] # interchange elements
+ index[j] = index[i]
+ index[i] = temp
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ p = p + 1 # push onto stack
+ }
+ }
+
+ do i = 1, npix
+ index[i] = index[i] + offset - 1
+end
+
+
+# PH_2ICOMPARE -- Comparison routine for PH_4R2ISORT.
+
+int procedure ph_2icompare (findex, sindex, fpivot, spivot)
+
+int findex # the first index value
+int sindex # the second index value
+int fpivot # the first pivot value
+int spivot # the second pivot value
+
+begin
+ if (findex < fpivot)
+ return (-1)
+ else if (findex > fpivot)
+ return (1)
+ else if (sindex < spivot)
+ return (-1)
+ else if (sindex > spivot)
+ return (1)
+ else
+ return (0)
+end
+
+
+# PH_IRCOMPARE -- Comparison routine for PH_3RIRSORT.
+
+int procedure ph_ircompare (findex, sindex, fpivot, spivot)
+
+int findex # the first index value
+real sindex # the second index value
+int fpivot # the first pivot value
+real spivot # the second pivot value
+
+begin
+ if (findex < fpivot)
+ return (-1)
+ else if (findex > fpivot)
+ return (1)
+ else if (sindex < spivot)
+ return (-1)
+ else if (sindex > spivot)
+ return (1)
+ else
+ return (0)
+end
+
+
+# PH_5R3ISORT -- Vector quicksort on the first and second indices arrays,
+# where the second index is used to resolve ambiguities in the first index.
+# An additional 5 input arrays are sorted as well.
+
+procedure ph_5r3isort (findex, sindex, i1, d1, d2, d3, d4, d5, naperts, npix)
+
+int findex[ARB] # first index array which is sorted on
+int sindex[ARB] # second index array which is sorted on
+int i1[ARB] # the 3 integer array
+real d1[ARB] # the first input data array
+real d2[ARB] # the second input data array
+real d3[naperts,ARB] # the third input data array
+real d4[naperts,ARB] # the fourth input data array
+real d5[naperts,ARB] # the fifth input data array
+int naperts # number of apertures
+int npix # number of pixels
+
+int fpivot, spivot, tempi
+int i, j, k, l,p, lv[LOGPTR], uv[LOGPTR]
+real tempr
+int ph_2aicompare()
+define swapi {tempi=$1;$1=$2;$2=tempi}
+define swapr {tempr=$1;$1=$2;$2=tempr}
+
+begin
+ lv[1] = 1
+ uv[1] = npix
+ p = 1
+
+ while (p > 0) {
+ if (lv[p] >= uv[p]) # only one elem in this subset
+ p = p - 1 # pop stack
+ else {
+ # Dummy do loop to trigger the Fortran optimizer.
+ do p = p, ARB {
+ i = lv[p] - 1
+ j = uv[p]
+
+ # Select as the pivot the element at the center of the
+ # array, to avoid quadratic behavior on an already sorted
+ # array.
+
+ k = (lv[p] + uv[p]) / 2
+ swapi (findex[j], findex[k])
+ swapi (sindex[j], sindex[k])
+ swapi (i1[j], i1[k])
+ swapr (d1[j], d1[k])
+ swapr (d2[j], d2[k])
+ do l = 1, naperts {
+ swapr (d3[l,j], d3[l,k])
+ swapr (d4[l,j], d4[l,k])
+ swapr (d5[l,j], d5[l,k])
+ }
+ fpivot = findex[j] # pivot line
+ spivot = sindex[j]
+
+ while (i < j) {
+ for (i=i+1; ph_2aicompare (findex[i], sindex[i], fpivot,
+ spivot) < 0; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (ph_2aicompare (findex[j], sindex[j], fpivot,
+ spivot) <= 0)
+ break
+ if (i < j) { # switch elements
+ swapi (sindex[i], sindex[j])
+ swapi (findex[i], findex[j]) # interchange elements
+ swapi (i1[i], i1[j])
+ swapr (d1[i], d1[j])
+ swapr (d2[i], d2[j])
+ do l = 1, naperts {
+ swapr (d3[l,i], d3[l,j])
+ swapr (d4[l,i], d5[l,j])
+ swapr (d5[l,i], d5[l,j])
+ }
+ }
+ }
+
+ j = uv[p] # move pivot to position i
+ swapi (sindex[i], sindex[j])
+ swapi (findex[i], findex[j]) # interchange elements
+ swapi (i1[i], i1[j])
+ swapr (d1[i], d1[j])
+ swapr (d2[i], d2[j])
+ do l = 1, naperts {
+ swapr (d3[l,i], d3[l,j])
+ swapr (d4[l,i], d4[l,j])
+ swapr (d5[l,i], d5[l,j])
+ }
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ break
+ }
+ p = p + 1 # push onto stack
+ }
+ }
+end
+
+
+# PH_2AICOMPARE -- Comparison routine for PH_5R3ISORT.
+
+int procedure ph_2aicompare (findex, sindex, fpivot, spivot)
+
+int findex # the first index value
+int sindex # the second index value
+int fpivot # the first pivot value
+int spivot # the second pivot value
+
+begin
+ if (findex < fpivot)
+ return (-1)
+ else if (findex > fpivot)
+ return (1)
+ else if (sindex < spivot)
+ return (-1)
+ else if (sindex > spivot)
+ return (1)
+ else
+ return (0)
+end
diff --git a/noao/digiphot/photcal/mkobsfile/t_apfile.x b/noao/digiphot/photcal/mkobsfile/t_apfile.x
new file mode 100644
index 00000000..59bfb7ec
--- /dev/null
+++ b/noao/digiphot/photcal/mkobsfile/t_apfile.x
@@ -0,0 +1,727 @@
+include <fset.h>
+include <ctotok.h>
+include <ctype.h>
+include "../lib/apfile.h"
+
+# T_APFILE -- Compute apperture corrections using the data extracted
+# from a simple text file written by the user and an optional corrections
+# file. APFILE expects to see the following nine quantities in the input data
+# file(s): image name, xcenter, ycenter, filterid, exposure time, xairmass,
+# list of apertures, list of magnitudes and list of magnitude errors, and
+# uses a simple list of columns to determine which data is in which column.
+# The obsparams file is decoded in the same way.
+
+procedure t_apfile ()
+
+int photfiles # pointer to the list of photometry files
+pointer columnstr # pointer to the list of columns
+int naperts # number of apertures to extract
+int mode # the file mode for the log and plot files
+int smallap # the index of the smallest aperture to use
+int largeap # the index of the largest aperture to use
+real maglim # the maximum magnitude error
+int mterms # the maximum number of terms in the cog model to fit
+int interactive # interactive mode
+pointer graphics # the default graphics device
+int verify # verify interactive user input
+
+int incat, apcat, magfd, logfd, plotfd, obs, csp, cp, nincolumns, npts
+pointer sp, column, incolumns, obscolumns, fname, params
+pointer imtable, imid, id, x, y, nap, rap, mag, merr, sortimid, gd, mgd
+bool clgetb()
+int clpopnu(), clplen(), ph_agrange(), open(), btoi(), clgeti()
+int ctoi(), clgfil(), ph_amkimtable(), fstati()
+pointer stopen(), gopen()
+real clgetr()
+
+begin
+ # Setup to flush on a newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Allocate working memory.
+ call smark (sp)
+ call salloc (columnstr, SZ_LINE, TY_CHAR)
+ call salloc (column, SZ_FNAME, TY_CHAR)
+ call salloc (incolumns, CAT_NFIELDS, TY_INT)
+ call salloc (obscolumns, OBS_NFIELDS, TY_INT)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (params, MAX_MTERMS, TY_DOUBLE)
+
+ # Get the input file list.
+ photfiles = clpopnu ("photfiles")
+ if (clplen (photfiles) <= 0)
+ call error (0, "The input file list is empty")
+
+ # Decode the input columns list. There must be at least CAT_RAPERT
+ # range specifiers in the incolumns list. The number 0 can be used as
+ # a place holder for missing columns.
+
+ call clgstr ("incolumns", Memc[columnstr], SZ_LINE)
+ call amovki (0, Memi[incolumns], CAT_NFIELDS)
+ nincolumns = 0
+ csp = 1
+ while (ph_agrange (Memc[columnstr], csp, Memc[column], SZ_FNAME) !=
+ EOF) {
+
+ # Decode the individual ranges.
+ if (nincolumns >= CAT_NFIELDS)
+ call error (0,
+ "Too many fields specified in the incolumns parameter")
+ cp = 1
+ if (ctoi (Memc[column], cp, Memi[incolumns+nincolumns]) > 0)
+ nincolumns = nincolumns + 1
+ else
+ break
+ }
+
+ # Check that sufficient fields have been defined.
+ if (nincolumns < CAT_MERR)
+ call error (0, "Too few fields defined in the incolumns parameter")
+
+ naperts = clgeti ("naperts")
+ smallap = max (1, min (naperts, clgeti ("smallap")))
+ largeap = clgeti ("largeap")
+ if (IS_INDEFI(largeap) || largeap <= 0)
+ largeap = naperts
+ else
+ largeap = max (1, min (naperts, largeap))
+ if (largeap <= smallap)
+ call error (0,
+ "The large aperture is less than or equal to the large aperture\n")
+
+ # Open the output catalog file.
+ call clgstr ("apercors", Memc[fname], SZ_FNAME)
+ apcat = open (Memc[fname], NEW_FILE, TEXT_FILE)
+
+ # Determine the access mode for the plot and log files.
+ if (clgetb ("append"))
+ mode = APPEND
+ else
+ mode = NEW_FILE
+
+ # Open the best magnitudes file if any.
+ call clgstr ("magfile", Memc[fname], SZ_FNAME)
+ if (Memc[fname] == EOS)
+ magfd = NULL
+ else
+ magfd = open (Memc[fname], NEW_FILE, TEXT_FILE)
+
+ # Open the logfile if any.
+ call clgstr ("logfile", Memc[fname], SZ_FNAME)
+ if (Memc[fname] == EOS)
+ logfd = NULL
+ else
+ logfd = open (Memc[fname], mode, TEXT_FILE)
+
+ # Open the plot file if any.
+ call clgstr ("graphics", Memc[graphics], SZ_FNAME)
+ call clgstr ("plotfile", Memc[fname], SZ_FNAME)
+ if (Memc[fname] == EOS)
+ plotfd = NULL
+ else
+ plotfd = open (Memc[fname], mode, BINARY_FILE)
+ if (plotfd != NULL)
+ mgd = gopen (Memc[graphics], NEW_FILE, plotfd)
+ else
+ mgd = NULL
+
+ # Open the observing parameters file and decode the column list.
+
+ call clgstr ("obsparams", Memc[fname], SZ_FNAME)
+ if (Memc[fname] == EOS)
+ obs = NULL
+ else {
+ obs = open (Memc[fname], READ_ONLY, TEXT_FILE)
+ call amovki (0, Memi[obscolumns], OBS_NFIELDS)
+ if (obs != STDIN) {
+ call clgstr ("obscolumns", Memc[columnstr], SZ_LINE)
+ csp = 1
+ nincolumns = 1
+ Memi[obscolumns] = 1
+ while (ph_agrange (Memc[columnstr], csp, Memc[column],
+ SZ_FNAME) != EOF && (nincolumns < OBS_NFIELDS)) {
+ cp = 1
+ if (ctoi (Memc[column], cp,
+ Memi[obscolumns+nincolumns]) <= 0)
+ Memi[obscolumns+nincolumns] = 0
+ else if (Memi[obscolumns+nincolumns] == 1)
+ nincolumns = nincolumns - 1
+ nincolumns = nincolumns + 1
+ }
+ }
+ }
+
+ # Verify interactive user input.
+ maglim = clgetr ("maglim")
+ mterms = max (1, min (MAX_MTERMS, clgeti ("nparams")))
+ call ph_agetp (Memd[params])
+ interactive = btoi (clgetb ("interactive"))
+ verify = btoi (clgetb ("verify"))
+
+ # Open a symbol table to hold a list of image charactersitics.
+
+ imtable = stopen ("imtable", 2 * LEN_IMTABLE, LEN_IMTABLE, 10 *
+ LEN_IMTABLE)
+
+ # Read in the data. Extract each unique image name and accompanying
+ # airmass and add it to the symbol table. For each star in each image
+ # extract the x and y centers, and the list of aperture radii,
+ # magnitudes, and magnitude errors.
+
+ imid = NULL
+ id = NULL
+ x = NULL
+ y = NULL
+ nap = NULL
+ rap = NULL
+ mag = NULL
+ merr = NULL
+ sortimid = NO
+
+ npts = 0
+ while (clgfil (photfiles, Memc[fname], SZ_FNAME) != EOF) {
+ incat = open (Memc[fname], READ_ONLY, TEXT_FILE)
+ npts = ph_amkimtable (imtable, incat, Memi[incolumns], naperts,
+ imid, id, x, y, nap, rap, mag, merr, npts, sortimid, maglim)
+ call close (incat)
+ }
+
+ call realloc (imid, npts, TY_INT)
+ call realloc (id, npts, TY_INT)
+ call realloc (x, npts, TY_REAL)
+ call realloc (y, npts, TY_REAL)
+ call realloc (nap, npts, TY_INT)
+ call realloc (rap, naperts * npts, TY_REAL)
+ call realloc (mag, naperts * npts, TY_REAL)
+ call realloc (merr, naperts * npts, TY_REAL)
+
+ # For each image referenced in the airmass file extract
+ # the image name, and the airmass if defined. Enter the new value of
+ # airmass in the symbol table and compute the effective
+ # exposure time required to correct the instrumental magnitudes to
+ # the new exposure time.
+
+ if (obs != NULL) {
+ if (obs == STDIN)
+ call ph_eaobsimtable (imtable, verify)
+ else
+ call ph_aobsimtable (imtable, obs, Memi[obscolumns])
+ }
+
+ # Sort the data by image id and object id if required.
+
+ if (sortimid == YES)
+ call ph_asort (imtable, Memi[imid], Memi[id], Memr[x], Memr[y],
+ Memi[nap], Memr[rap], Memr[mag], Memr[merr], naperts, npts)
+
+ # Free the image id sorting index arrays.
+
+ if (imid != NULL)
+ call mfree (imid, TY_INT)
+
+ # Compute the curves of growth.
+
+ if (interactive == YES) {
+ gd = gopen (Memc[graphics], NEW_FILE, STDGRAPH)
+ call ph_aigrow (gd, apcat, magfd, logfd, mgd, imtable, Memi[id],
+ Memr[x], Memr[y], Memi[nap], Memr[rap], Memr[mag], Memr[merr],
+ naperts, Memd[params], mterms, smallap, largeap)
+ call gclose (gd)
+ } else
+ call ph_agrow (apcat, magfd, logfd, mgd, imtable, Memi[id], Memr[x],
+ Memr[y], Memi[nap], Memr[rap], Memr[mag], Memr[merr], naperts,
+ Memd[params], mterms, smallap, largeap)
+
+ # Free the data arrays.
+
+ if (id != NULL)
+ call mfree (id, TY_INT)
+ if (x != NULL)
+ call mfree (x, TY_REAL)
+ if (y != NULL)
+ call mfree (y, TY_REAL)
+ if (nap != NULL)
+ call mfree (nap, TY_INT)
+ if (rap != NULL)
+ call mfree (rap, TY_REAL)
+ if (mag != NULL)
+ call mfree (mag, TY_REAL)
+ if (merr != NULL)
+ call mfree (merr, TY_REAL)
+
+ # Close the symbol table.
+ call stclose (imtable)
+
+ # Close the files and file lists.
+ call close (apcat)
+ if (magfd != NULL)
+ call close (magfd)
+ if (logfd != NULL)
+ call close (logfd)
+ if (mgd != NULL)
+ call gclose (mgd)
+ if (plotfd != NULL)
+ call close (plotfd)
+ if (obs != NULL)
+ call close (obs)
+ call clpcls (photfiles)
+
+ call sfree (sp)
+end
+
+
+# PH_ASORT -- Sort the data.
+
+procedure ph_asort (imtable, imid, id, x, y, nap, rap, mag, merr, naperts, npts)
+
+pointer imtable # pointer to the symbol table
+int imid[ARB] # array of image ids
+int id[ARB] # array of object ids
+real x[ARB] # array of x coordinates
+real y[ARB] # array of y coordinates
+int nap[ARB] # array of aperture numbers
+real rap[naperts,ARB] # the aperture radii list
+real mag[naperts,ARB] # array of magnitudes
+real merr[naperts,ARB] # array of magnitude errors
+int naperts # the number of apertures
+int npts # the number of points
+
+int nimages, i, nptr
+pointer sp, sym, symbol
+int stnsymbols()
+pointer sthead(), stnext()
+
+begin
+ nimages = stnsymbols (imtable, 0)
+ if (nimages <= 0)
+ return
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (sym, nimages, TY_INT)
+
+ # Read in the symbol list in the last in first out sense.
+
+ symbol = sthead (imtable)
+ do i = 1, nimages {
+ Memi[sym+i-1] = symbol
+ symbol = stnext (imtable, symbol)
+ }
+
+ # Do the image/object id sort if necessary. This is a real sort
+ # where the actual contents of the arrays are rearcolumnd.
+ # After the image/object id sort recompute the offsets specifying the
+ # location of the image data in the symbol table. The first
+ # pass through the symbol table to picks up the information for the
+ # images that have only one entry. The second pass picks up
+ # information for images that have more than one entry.
+
+ call ph_5r3isort (imid, id, nap, x, y, rap, mag, merr, naperts, npts)
+ nptr = npts + 1
+ do i = 1, nimages {
+ symbol = Memi[sym+i-1]
+ if (IMT_NENTRIES(symbol) <= 0)
+ next
+ nptr = nptr - IMT_NENTRIES(symbol)
+ IMT_OFFSET(symbol) = nptr
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_ANXTIMAGE -- Find the first line in the input catalog containing the next
+# image name, given the current image name. Return the new image nam and line.
+
+int procedure ph_anxtimage (fd, columns, image, line, lbufsize)
+
+int fd # file descriptor of the input text file
+int columns[ARB] # the list of input columns
+char image[ARB] # the name of the current image
+pointer line # pointer to the output line
+int lbufsize # current maximum line buffer size
+
+int i, op, colno
+long stat
+pointer sp, str
+bool streq()
+int getline(), nscan()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ if (line == NULL || lbufsize <= 0) {
+ lbufsize = lbufsize + SZ_LINE
+ call malloc (line, lbufsize, TY_CHAR)
+ }
+
+ colno = columns[CAT_IMAGE]
+ Memc[str] = EOS
+ repeat {
+
+ op = 1
+ repeat {
+ stat = getline (fd, Memc[line+op-1])
+ if (stat == EOF)
+ break
+ op = op + stat
+ if (op > lbufsize) {
+ lbufsize = lbufsize + SZ_LINE
+ call realloc (line, lbufsize, TY_CHAR)
+ }
+ } until (Memc[line+op-2] == '\n')
+ if (stat == EOF)
+ break
+ else
+ stat = op - 1
+
+ call sscan (Memc[line])
+ do i = 1, colno
+ call gargwrd (Memc[str], SZ_FNAME)
+ if (nscan() != colno)
+ next
+
+ } until (! streq (image, Memc[str]))
+ call strcpy (Memc[str], image, SZ_FNAME)
+
+ call sfree (sp)
+
+ return (stat)
+end
+
+
+# PH_AGETIMAGE -- Read the next line in the input catalog and return the image
+# name and the line.
+
+int procedure ph_agetimage (fd, columns, image, line, lbufsize)
+
+int fd # file descriptor of the input text file
+int columns[ARB] # the list of input columns
+char image[ARB] # the name of the current image
+pointer line # pointer to the output line
+int lbufsize # size of the output line
+
+int op, i, colno
+int stat
+int getline(), nscan()
+
+begin
+ if (line == NULL || lbufsize <= 0) {
+ lbufsize = lbufsize + SZ_LINE
+ call malloc (line, lbufsize, TY_CHAR)
+ }
+
+ colno = columns[CAT_IMAGE]
+ repeat {
+
+ op = 1
+ repeat {
+ stat = getline (fd, Memc[line+op-1])
+ if (stat == EOF)
+ break
+ op = op + stat
+ if (op > lbufsize) {
+ lbufsize = lbufsize + SZ_LINE
+ call realloc (line, lbufsize, TY_CHAR)
+ }
+ } until (Memc[line+op-2] == '\n')
+ if (stat == EOF)
+ break
+ else
+ stat = op - 1
+
+ call sscan (Memc[line])
+ do i = 1, colno
+ call gargwrd (image, SZ_FNAME)
+ if (nscan() != colno)
+ next
+
+ break
+ }
+
+ return (stat)
+end
+
+
+# PH_AIMDATA -- Decode the airmass from a a line of the input catalog.
+
+procedure ph_aimdata (line, columns, filterid, sz_filterid, itime, airmass,
+ otime)
+
+char line[ARB] # input line to be scanned
+int columns[ARB] # the list of input columns
+char filterid[ARB] # the filter id
+int sz_filterid # the maximum size of the filter id
+real itime # the integration time
+real airmass # the airmass of the observation
+real otime # the time of observation
+
+int i, fcol, icol, acol, ocol, maxcol
+pointer sp, str
+int nscan()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ fcol = columns[CAT_IFILTER]
+ icol = columns[CAT_ITIME]
+ acol = columns[CAT_XAIRMASS]
+ ocol = columns[CAT_OTIME]
+ maxcol = max (fcol, icol, acol, ocol)
+
+ airmass = INDEFR
+
+ call sscan (line)
+ do i = 1, maxcol {
+ if (i == fcol) {
+ call gargwrd (filterid, sz_filterid)
+ if (nscan() != fcol)
+ call strcpy ("INDEF", filterid, sz_filterid)
+ } else if (i == icol) {
+ call gargr (itime)
+ if (nscan() != icol)
+ itime = INDEFR
+ } else if (i == acol) {
+ call gargr (airmass)
+ if (nscan() != acol)
+ airmass = INDEFR
+ } else if (i == ocol) {
+ call gargr (otime)
+ if (nscan() != ocol)
+ otime = INDEFR
+ } else {
+ call gargwrd (Memc[str], SZ_LINE)
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_AOBSDATA -- Decode the filterid, exposure time, and airmass from a
+# line of the airmass file.
+
+procedure ph_aobsdata (line, columns, filterid, sz_filterid, itime, airmass,
+ otime)
+
+char line[ARB] # input line to be scanned
+int columns[ARB] # the list of input columns
+char filterid[ARB] # the filter id
+int sz_filterid # maximum size if filter id string
+real itime # the exposure time
+real airmass # the airmass of the observation
+real otime # the time of observation
+
+int i, fcol, icol, acol, ocol, maxcol
+pointer sp, str
+int nscan()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ fcol = columns[OBS_IFILTER]
+ icol = columns[OBS_ITIME]
+ acol = columns[OBS_XAIRMASS]
+ ocol = columns[OBS_OTIME]
+ maxcol = max (fcol, icol, acol, ocol)
+
+ call strcpy ("INDEF", filterid, sz_filterid)
+ itime = INDEFR
+ airmass = INDEFR
+
+ call sscan (line)
+ do i = 1, maxcol {
+ if (i == fcol) {
+ call gargwrd (filterid, sz_filterid)
+ if (nscan() != fcol)
+ call strcpy ("INDEF", filterid, sz_filterid)
+ } else if (i == icol) {
+ call gargr (itime)
+ if (nscan() != icol)
+ itime = INDEFR
+ } else if (i == acol) {
+ call gargr (airmass)
+ if (nscan() != acol)
+ airmass = INDEFR
+ } else if (i == ocol) {
+ call gargr (otime)
+ if (nscan() != ocol)
+ otime = INDEFR
+ } else {
+ call gargwrd (Memc[str], SZ_LINE)
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_ASTARDATA -- Decode the image name, x and y coordinates, magnitude
+# and magnitude error from the input catalog.
+
+int procedure ph_astardata (line, columns, x, y, nap, rap, mag, merr, naperts,
+ magerr)
+
+char line[ARB] # input line to be scanned
+int columns[ARB] # the list of input columns
+real x, y # the output x and y coordinates
+int nap # the number of apertures
+real rap[ARB] # the output aperture radii
+real mag[ARB] # the output magnitude array
+real merr[ARB] # the output magnitude error array
+int naperts # the number of apertures
+real magerr # the maximum magnitude error
+
+int i, xcol, ycol, rcol1, rcol2, mcol1, mcol2, ecol1, ecol2, maxcol, stat
+pointer sp, str
+int nscan()
+real rval
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ xcol= columns[CAT_XCENTER]
+ ycol= columns[CAT_YCENTER]
+ rcol1 = columns[CAT_RAPERT]
+ rcol2 = columns[CAT_RAPERT] + naperts - 1
+ mcol1 = columns[CAT_MAG]
+ mcol2 = columns[CAT_MAG] + naperts - 1
+ ecol1 = columns[CAT_MERR]
+ ecol2 = columns[CAT_MERR] + naperts - 1
+ maxcol = max (xcol, ycol, rcol1, rcol2, mcol1, mcol2, ecol1, ecol2)
+
+ x = INDEFR
+ y = INDEFR
+ nap = 0
+ call amovkr (INDEFR, rap, naperts)
+ call amovkr (INDEFR, mag, naperts)
+ call amovkr (INDEFR, merr, naperts)
+ stat = OK
+
+ call sscan (line)
+ do i = 1, maxcol {
+
+ if (i == xcol) {
+ call gargr (rval)
+ if (nscan() != xcol)
+ stat = ERR
+ else
+ x = rval
+ } else if (i == ycol) {
+ call gargr (rval)
+ if (nscan() != ycol)
+ stat = ERR
+ else
+ y = rval
+ } else if (i >= rcol1 && i <= rcol2) {
+ call gargr (rval)
+ if (nscan() != i)
+ stat = ERR
+ else
+ rap[i-rcol1+1] = rval
+ } else if (i >= mcol1 && i <= mcol2) {
+ call gargr (rval)
+ if (nscan() != i)
+ stat = ERR
+ #else if (IS_INDEFR(rval))
+ #stat = ERR
+ else {
+ mag[i-mcol1+1] = rval
+ nap = nap + 1
+ }
+ } else if (i >= ecol1 && i <= ecol2) {
+ call gargr (rval)
+ if (nscan() != i)
+ stat = ERR
+ #else if (IS_INDEFR(rval))
+ #stat = ERR
+ #else if (rval > magerr)
+ #stat = ERR
+ else
+ #merr[i-ecol1+1] = sqrt (1.0e-6 + rval ** 2)
+ merr[i-ecol1+1] = rval
+ } else {
+ call gargwrd (Memc[str], SZ_LINE)
+ if (nscan() != i)
+ stat = ERR
+ }
+
+ if (stat == ERR)
+ break
+ nap = nap + 1
+ }
+
+ call sfree (sp)
+
+ # Compute the magnitude differences.
+ if (stat == ERR) {
+ return (ERR)
+ } else if (nap > 1) {
+ nap = 0
+ do i = 1, naperts {
+ if (IS_INDEFR(mag[i]) || IS_INDEFR(merr[i]) || merr[i] >
+ magerr)
+ break
+ nap = nap + 1
+ }
+ #if (nap <= 1)
+ if (nap <= 0)
+ return (ERR)
+ if (nap > 1) {
+ do i = nap, 2, -1 {
+ mag[i] = mag[i] - mag[i-1]
+ merr[i] = sqrt (1.0e-6 + merr[i] ** 2)
+ }
+ }
+ return (OK)
+ } else
+ return (ERR)
+end
+
+
+# PH_AGRANGE -- Get the next column from a list of columns.
+
+int procedure ph_agrange (list, ip, label, maxch)
+
+char list[ARB] # list of labels
+int ip # pointer in to the list of labels
+char label[ARB] # the output label
+int maxch # maximum length of a column name
+
+int op, token
+int ctotok(), strlen()
+
+begin
+ # Decode the column labels.
+ op = 1
+ while (list[ip] != EOS) {
+
+ token = ctotok (list, ip, label[op], maxch)
+ if (label[op] == EOS)
+ next
+ if ((token == TOK_UNKNOWN) || (token == TOK_CHARCON))
+ break
+ if ((token == TOK_PUNCTUATION) && (label[op] == ',')) {
+ if (op == 1)
+ next
+ else
+ break
+ }
+
+ op = op + strlen (label[op])
+ if (IS_WHITE(list[ip]))
+ break
+ }
+
+ label[op] = EOS
+ if ((list[ip] == EOS) && (op == 1))
+ return (EOF)
+ else
+ return (op - 1)
+end
diff --git a/noao/digiphot/photcal/mkobsfile/t_mkphotcors.x b/noao/digiphot/photcal/mkobsfile/t_mkphotcors.x
new file mode 100644
index 00000000..c3e22646
--- /dev/null
+++ b/noao/digiphot/photcal/mkobsfile/t_mkphotcors.x
@@ -0,0 +1,273 @@
+include "../lib/obsfile.h"
+
+# T_MKPHOTCORS - Query the user for the image sets, observing parameters,
+# positional shifts and aperture corrections required by the preprocessor
+# task MKOBSFILE. Input to OBSQUERY is the names of the output image set,
+# observing parameters, shifts and aperture corrections files, and a list
+# of filter ids.
+
+procedure t_mkphotcors ()
+
+pointer infilters # pointer to the input list of filter ids
+pointer imsets # name of the output image set file
+pointer obsparams # pointer to the output obsparams file
+pointer shifts # pointer to the output shifts file
+pointer apercors # pointer to the output aperture corrections file
+pointer obscolumnstr # pointer to format of obsparams
+int verify # verify interactive user input
+int verbose # print status, warning and error messages
+
+int nfilters, csp, cp, ncolumns, nimages
+int insets, outsets, inobs, outobs, insh, outsh, inap, outap
+pointer sp, outfilters, imtable, obscolname, obscolumns
+bool clgetb()
+int btoi(), open(), ph_filters(), ph_esetimtable(), ph_setimtable()
+int ctoi(), access(), ph_getlabels()
+pointer stopen()
+
+begin
+ # Allocate working memory.
+ call smark (sp)
+ call salloc (imsets, SZ_FNAME, TY_CHAR)
+ call salloc (infilters, SZ_LINE, TY_CHAR)
+ call salloc (outfilters, SZ_LINE, TY_CHAR)
+ call salloc (obsparams, SZ_FNAME, TY_CHAR)
+ call salloc (shifts, SZ_FNAME, TY_CHAR)
+ call salloc (apercors, SZ_FNAME, TY_CHAR)
+ call salloc (obscolumnstr, SZ_LINE, TY_CHAR)
+ call salloc (obscolname, SZ_FNAME, TY_CHAR)
+ call salloc (obscolumns, OBS_NFIELDS, TY_INT)
+
+ # Get the parameters.
+ call clgstr ("imsets", Memc[imsets], SZ_FNAME)
+ call clgstr ("idfilters", Memc[infilters], SZ_LINE)
+ call clgstr ("obsparams", Memc[obsparams], SZ_FNAME)
+ call clgstr ("shifts", Memc[shifts], SZ_FNAME)
+ call clgstr ("apercors", Memc[apercors], SZ_FNAME)
+ call clgstr ("obscolumns", Memc[obscolumnstr], SZ_LINE)
+ verify = btoi (clgetb ("verify"))
+ verbose = btoi (clgetb ("verbose"))
+
+ # Open the idfilters string.
+ nfilters = ph_filters (Memc[infilters], Memc[outfilters], SZ_LINE)
+
+ # Open the input and output image sets file.
+ if (Memc[imsets] == EOS) {
+ outsets = NULL
+ insets = open ("STDIN", READ_ONLY, TEXT_FILE)
+ } else if (access (Memc[imsets], READ_ONLY, TEXT_FILE) == YES) {
+ outsets = NULL
+ insets = open (Memc[imsets], READ_ONLY, TEXT_FILE)
+ } else {
+ outsets = open (Memc[imsets], NEW_FILE, TEXT_FILE)
+ insets = open ("STDIN", READ_ONLY, TEXT_FILE)
+ }
+
+ # Open the input and output observing parameters file.
+ if (Memc[obsparams] == EOS) {
+ outobs = NULL
+ inobs = NULL
+ } else if (access (Memc[obsparams], READ_ONLY, TEXT_FILE) == YES) {
+ outobs = NULL
+ inobs = open (Memc[obsparams], READ_ONLY, TEXT_FILE)
+ call amovki (0, Memi[obscolumns], OBS_NFIELDS)
+ csp = 1
+ ncolumns = 0
+ while (ph_getlabels (Memc[obscolumnstr], csp, Memc[obscolname],
+ SZ_FNAME) != EOF) {
+ cp = 1
+ if (ctoi (Memc[obscolname], cp, Memi[obscolumns+ncolumns]) <= 0)
+ Memi[obscolumns+ncolumns] = 0
+ ncolumns = ncolumns + 1
+ }
+ } else {
+ outobs = open (Memc[obsparams], NEW_FILE, TEXT_FILE)
+ inobs = open ("STDIN", READ_ONLY, TEXT_FILE)
+ }
+
+ # Open the input and output shifts file.
+ if (Memc[shifts] == EOS) {
+ outsh = NULL
+ insh = NULL
+ } else if (access (Memc[shifts], READ_ONLY, TEXT_FILE) == YES) {
+ outsh = NULL
+ insh = open (Memc[shifts], READ_ONLY, TEXT_FILE)
+ } else {
+ outsh = open (Memc[shifts], NEW_FILE, TEXT_FILE)
+ insh = open ("STDIN", READ_ONLY, TEXT_FILE)
+ }
+
+ # Open the aperture corrections file.
+ if (Memc[apercors] == EOS) {
+ outap = NULL
+ inap = NULL
+ } else if (access (Memc[apercors], READ_ONLY, TEXT_FILE) == YES) {
+ outap = NULL
+ inap = open (Memc[apercors], READ_ONLY, TEXT_FILE)
+ } else {
+ outap = open (Memc[apercors], NEW_FILE, TEXT_FILE)
+ inap = open ("STDIN", READ_ONLY, TEXT_FILE)
+ }
+
+ # Open a symbol table to hold a list of image charactersitics.
+
+ imtable = stopen ("imtable", 2 * LEN_IMTABLE, LEN_IMTABLE, 10 *
+ LEN_IMTABLE)
+
+ # Read in the image set file and store each unique image name in
+ # the symbol table. Initialize the records fields.
+
+ if (insets == STDIN)
+ nimages = ph_esetimtable (imtable, nfilters, verify)
+ else
+ nimages = ph_setimtable (imtable, insets, nfilters, verbose)
+
+ # For each image referenced in the observing parameters file extract
+ # the image name, the filter id if defined, the exposure time if
+ # defined and the airmass if defined. Enter the new values of filter
+ # id and airmass in the symbol table and compute the effective
+ # exposure time required to correct the instrumental magnitudes to
+ # the new exposure time.
+
+ if (inobs == STDIN)
+ call ph_eobsimtable (imtable, nimages, verify)
+ else if (inobs != NULL)
+ call ph_obsimtable (imtable, inobs, Memi[obscolumns], verbose)
+
+ # Read in the x and y shifts for the image. Images for which no
+ # shift is defined are assigned an x-y shift of 0.0.
+
+ if (insh == STDIN)
+ call ph_eshimtable (imtable, nimages, verify)
+ else if (insh != NULL)
+ call ph_shimtable (imtable, insh, verbose)
+
+ # Read in the aperture corrections. Images for which no aperture
+ # correction is defined are assigned an aperture correction of 0.0.
+
+ if (inap == STDIN)
+ call ph_eapimtable (imtable, nimages, verify)
+ else if (inap != NULL)
+ call ph_apimtable (imtable, inap, verbose)
+
+ # Write the results to the various output files.
+ if (nimages > 0)
+ call ph_wimtable (imtable, outsets, outobs, outsh, outap, nimages)
+
+ # Close the symbol table.
+ call stclose (imtable)
+
+ # Close the input files.
+ if (insets != NULL)
+ call close (insets)
+ if (inobs != NULL)
+ call close (inobs)
+ if (insh != NULL)
+ call close (insh)
+ if (inap != NULL)
+ call close (inap)
+
+ # Close the output files.
+ if (outsets != NULL) {
+ call close (outsets)
+ if (nimages <= 0)
+ call delete (Memc[imsets])
+ }
+ if (outobs != NULL) {
+ call close (outobs)
+ if (nimages <= 0)
+ call delete (Memc[obsparams])
+ }
+ if (outsh != NULL) {
+ call close (outsh)
+ if (nimages <= 0)
+ call delete (Memc[shifts])
+ }
+ if (outap != NULL) {
+ call close (outap)
+ if (nimages <= 0)
+ call delete (Memc[apercors])
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_WIMTABLE -- Write the contents of the symbol table to the output image
+# set file, the output observing parameters file, the output shifts file,
+# and the output aperture corrections file. The only assumption here is
+# that all images in a given image set are adjacent to each other in the
+# symbol table, an assumption that is always true.
+
+procedure ph_wimtable (imtable, outsets, outobs, outsh, outap, nimages)
+
+pointer imtable # pointer to the the input symbol table
+int outsets # the output image set file descriptor
+int outobs # the output observing parameters file descriptor
+int outsh # the output positional shifts file descriptor
+int outap # the output aperture corrections file descriptor
+int nimages # number of images in the symbol table
+
+int i, osetno, setno
+pointer sp, sym, symbol
+pointer sthead(), stnext()
+
+begin
+ call smark (sp)
+ call salloc (sym, nimages, TY_POINTER)
+
+ # Reorder the list of symbols.
+ symbol = sthead (imtable)
+ do i = nimages, 1, -1 {
+ Memi[sym+i-1] = symbol
+ symbol = stnext (imtable, symbol)
+ }
+
+ # Write the output files.
+ osetno = 0
+ do i = 1, nimages {
+
+ symbol = Memi[sym+i-1]
+ setno = IMT_IMSETNO(symbol)
+
+ if (outsets != NULL) {
+ if (setno != osetno) {
+ if (setno == 1)
+ call fprintf (outsets, "%s :")
+ else
+ call fprintf (outsets, "\n%s :")
+ call pargstr (IMT_LABEL(symbol))
+ }
+ call fprintf (outsets, " %s")
+ call pargstr (IMT_IMNAME(symbol))
+ if (i == nimages)
+ call fprintf (outsets, "\n")
+ }
+
+ if (outobs != NULL) {
+ call fprintf (outobs, "%s %s %g %g %0.1h\n")
+ call pargstr (IMT_IMNAME(symbol))
+ call pargstr (IMT_IFILTER(symbol))
+ call pargr (IMT_ITIME(symbol))
+ call pargr (IMT_XAIRMASS(symbol))
+ call pargr (IMT_OTIME(symbol))
+ }
+
+ if (outsh != NULL) {
+ call fprintf (outsh, "%s %g %g\n")
+ call pargstr (IMT_IMNAME(symbol))
+ call pargr (IMT_XSHIFT(symbol))
+ call pargr (IMT_YSHIFT(symbol))
+ }
+
+ if (outap != NULL) {
+ call fprintf (outap, "%s %g\n")
+ call pargstr (IMT_IMNAME(symbol))
+ call pargr (IMT_APERCOR(symbol))
+ }
+
+ osetno = setno
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/photcal/mkobsfile/t_obsfile.x b/noao/digiphot/photcal/mkobsfile/t_obsfile.x
new file mode 100644
index 00000000..6c997cea
--- /dev/null
+++ b/noao/digiphot/photcal/mkobsfile/t_obsfile.x
@@ -0,0 +1,1131 @@
+include <fset.h>
+include <ctotok.h>
+include <ctype.h>
+include "../lib/obsfile.h"
+
+# T_OBSFILE -- Make an observations catalog using the data extracted
+# from the APPHOT/DAOPHOT catalogs by TXDUMP/TDUMP or supplied in a simple
+# text file by the user, the observing parameters file, the shifts and
+# aperture corrections file and the image sets file. OBSFILE expects to
+# see the following 8 fields in the input data file: image name, xcenter,
+# ycenter, exposure time, filter id, airmass, magnitude and magnitude error
+# and uses a simple string containing a list of column numbers to determine
+# which data is in which column. The observing parameters file is decoded
+# in the same way.
+
+procedure t_obsfile ()
+
+int photfiles # pointer to the list of photometry files
+pointer columnstr # pointer to the list of input columns
+pointer infilters # pointer to the input list of filter ids
+int normtime # normalize to an exposure time of 1 time unit
+int allfilters # only output objects with data in all filters
+real tolerance # tolerance in pixels for position matching
+int verify # verify interactive user input
+int verbose # print status, warning and errors messages
+
+int incat, sets, sh, ap, obs, outcat, fmt, wrap
+int csp, cp, nincolumns, nfilters, nimages, npts, sortimid
+pointer sp, outfilters, fname, tfname, column, incolumns, obscolumns, imtable
+pointer objid, x, y, mag, merr, imid, id
+real minmagerr
+
+bool clgetb()
+int clpopnu(), clgfil(), open(), clplen(), ph_filters(), ph_getlabels()
+int ctoi(), ph_setimtable(), ph_esetimtable(), ph_mkimtable(), btoi()
+int access()
+pointer stopen()
+real clgetr()
+
+begin
+ # Allocate working memory.
+ call smark (sp)
+
+ call salloc (infilters, SZ_LINE, TY_CHAR)
+ call salloc (outfilters, SZ_LINE, TY_CHAR)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (tfname, SZ_FNAME, TY_CHAR)
+
+ call salloc (columnstr, SZ_LINE, TY_CHAR)
+ call salloc (column, SZ_FNAME, TY_CHAR)
+ call salloc (incolumns, CAT_NFIELDS, TY_INT)
+ call salloc (obscolumns, OBS_NFIELDS, TY_INT)
+
+ # Get the input file list.
+ photfiles = clpopnu ("photfiles")
+ if (clplen (photfiles) <= 0)
+ call error (0, "The input file list is empty")
+
+ # Decode the input columns list. There must be at least CAT_NFIELDS
+ # column numbers in the incolumns list. The number 0 can be used as
+ # a place holder for missing columns.
+
+ call clgstr ("incolumns", Memc[columnstr], SZ_LINE)
+ csp = 1
+ nincolumns = 0
+ while (ph_getlabels (Memc[columnstr], csp, Memc[column], SZ_FNAME) !=
+ EOF) {
+ cp = 1
+ if (ctoi (Memc[column], cp, Memi[incolumns+nincolumns]) <= 0)
+ Memi[incolumns+nincolumns] = 0
+ nincolumns = nincolumns + 1
+ }
+ if (nincolumns < CAT_NFIELDS)
+ call error (0,
+ "There are too few columns defined in the incolumns string")
+
+ # Open the idfilters string.
+ call clgstr ("idfilters", Memc[infilters], SZ_LINE)
+ nfilters = ph_filters (Memc[infilters], Memc[outfilters], SZ_LINE)
+
+ # Open the image sets file.
+ call clgstr ("imsets", Memc[fname], SZ_FNAME)
+ sets = open (Memc[fname], READ_ONLY, TEXT_FILE)
+
+ # Open the output catalog file.
+ call clgstr ("observations", Memc[fname], SZ_FNAME)
+ outcat = open (Memc[fname], NEW_FILE, TEXT_FILE)
+ call sprintf (Memc[tfname], SZ_FNAME, "f%s.dat")
+ call pargstr (Memc[fname])
+ if (access (Memc[tfname], 0, 0) == YES)
+ call delete (Memc[tfname])
+ fmt = open (Memc[tfname], NEW_FILE, TEXT_FILE)
+ wrap = btoi (clgetb ("wrap"))
+
+ # Get the minimum magnitude error.
+ minmagerr = clgetr ("minmagerr")
+
+ # Normalize the exposure times?
+ normtime = btoi (clgetb ("normtime"))
+
+ # Get the position matching parameters.
+ tolerance = clgetr ("tolerance")
+ allfilters = btoi (clgetb ("allfilters"))
+
+ # Verify interactive user input.
+ verify = btoi (clgetb ("verify"))
+ verbose = btoi (clgetb ("verbose"))
+
+ # Open the shifts file.
+ call clgstr ("shifts", Memc[fname], SZ_FNAME)
+ if (Memc[fname] == EOS)
+ sh = NULL
+ else
+ sh = open (Memc[fname], READ_ONLY, TEXT_FILE)
+
+ # Open the aperture corrections file.
+ call clgstr ("apercors", Memc[fname], SZ_FNAME)
+ if (Memc[fname] == EOS)
+ ap = NULL
+ else
+ ap = open (Memc[fname], READ_ONLY, TEXT_FILE)
+
+ # Open the observing parameters file and decode the column list.
+
+ call clgstr ("obsparams", Memc[fname], SZ_FNAME)
+ if (Memc[fname] == EOS)
+ obs = NULL
+ else {
+ obs = open (Memc[fname], READ_ONLY, TEXT_FILE)
+ call amovki (0, Memi[obscolumns], OBS_NFIELDS)
+ if (obs != STDIN) {
+ call clgstr ("obscolumns", Memc[columnstr], SZ_LINE)
+ csp = 1
+ nincolumns = 1
+ Memi[obscolumns] = 1
+ while (ph_getlabels (Memc[columnstr], csp, Memc[column],
+ SZ_FNAME) != EOF && (nincolumns < OBS_NFIELDS)) {
+ cp = 1
+ if (ctoi (Memc[column], cp,
+ Memi[obscolumns+nincolumns]) <= 0)
+ Memi[obscolumns+nincolumns] = 0
+ else if (Memi[obscolumns+nincolumns] == 1)
+ nincolumns = nincolumns - 1
+ nincolumns = nincolumns + 1
+ }
+ }
+ }
+
+ # Open a symbol table to hold a list of image charactersitics.
+
+ imtable = stopen ("imtable", 2 * LEN_IMTABLE, LEN_IMTABLE, 10 *
+ LEN_IMTABLE)
+
+ # Read in the image set file and store each unique image name in
+ # the symbol table. Initialize the records fields.
+
+ if (sets == NULL)
+ nimages = 0
+ else if (sets == STDIN)
+ nimages = ph_esetimtable (imtable, nfilters, verify)
+ else
+ nimages = ph_setimtable (imtable, sets, nfilters, verbose)
+
+ # For each image referenced in the observing parameters file extract
+ # the image name, the filter id if defined, the exposure time if
+ # defined and the airmass if defined. Enter the new values of filter
+ # id and airmass in the symbol table and compute the effective
+ # exposure time required to correct the instrumental magnitudes to
+ # the new exposure time.
+
+ if (obs != NULL) {
+ if (obs == STDIN)
+ call ph_eobsimtable (imtable, nimages, verify)
+ else {
+ if (sets == STDIN && verbose == YES) {
+ call fstats (obs, F_FILENAME, Memc[fname], SZ_FNAME)
+ call eprintf ("Warning: Filter ids in %s ")
+ call pargstr (Memc[fname])
+ call eprintf ("will replace those listed in idfilters\n")
+ }
+ call ph_obsimtable (imtable, obs, Memi[obscolumns], verbose)
+ }
+ }
+
+ # Read in the x and y shifts for the image. Images for which no
+ # shift is defined are assigned an x-y shift of 0.0.
+
+ if (sh != NULL) {
+ if (sh == STDIN)
+ call ph_eshimtable (imtable, nimages, verify)
+ else
+ call ph_shimtable (imtable, sh, verbose)
+ }
+
+ # Read in the aperture corrections. Images for which no aperture
+ # correction is defined are assigned an aperture correction of 0.0.
+
+ if (ap != NULL) {
+ if (ap == STDIN)
+ call ph_eapimtable (imtable, nimages, verify)
+ else
+ call ph_apimtable (imtable, ap, verbose)
+ }
+
+ # Read in the data. Extract each unique image name and match it
+ # with the corresponding image name in the symbol table. Skip data
+ # for images which are not in the symbol table. For each unique image
+ # name which does match a symbol table image name, extract the exposure
+ # time, filter id, and airmass and enter them in the symbol table.
+ # Read the x and y and magnitude and magnitude error data into
+ # separate data arrays.
+
+ objid = NULL
+ x = NULL
+ y = NULL
+ mag = NULL
+ merr = NULL
+ imid = NULL
+ id = NULL
+ sortimid = NO
+
+ npts = 0
+ while (clgfil (photfiles, Memc[fname], SZ_FNAME) != EOF) {
+ incat = open (Memc[fname], READ_ONLY, TEXT_FILE)
+ npts = ph_mkimtable (imtable, incat, Memi[incolumns], objid, x,
+ y, mag, merr, imid, id, npts, normtime, sortimid, verbose)
+ call close (incat)
+ }
+
+ if (objid != NULL)
+ call realloc (objid, npts * (DEF_LENLABEL+1), TY_CHAR)
+ call realloc (x, npts, TY_REAL)
+ call realloc (y, npts, TY_REAL)
+ call realloc (mag, npts, TY_REAL)
+ call realloc (merr, npts, TY_REAL)
+ call realloc (imid, npts, TY_INT)
+ call realloc (id, npts, TY_INT)
+
+ # Sort the data by image id and object id if position matching is
+ # turned off or by image id and y coordinate if position matching is
+ # turned on.
+
+ if (objid == NULL)
+ call ph_sort (imtable, nimages, "", Memr[x], Memr[y], Memr[mag],
+ Memr[merr], Memi[imid], Memi[id], npts, sortimid, tolerance)
+ else
+ call ph_sort (imtable, nimages, Memc[objid], Memr[x], Memr[y],
+ Memr[mag], Memr[merr], Memi[imid], Memi[id], npts, sortimid,
+ tolerance)
+ # Free the image id sorting index arrays.
+
+ if (imid != NULL)
+ call mfree (imid, TY_INT)
+
+ # Apply the exposure time corrections, x-y shifts, and the aperture
+ # corrections.
+
+ call ph_correct (imtable, Memr[x], Memr[y], Memr[mag], Memr[merr],
+ minmagerr)
+
+ if (verbose == YES) {
+ call fstats (outcat, F_FILENAME, Memc[fname], SZ_FNAME)
+ call printf ("\nObservations file: %s\n")
+ call pargstr (Memc[fname])
+ }
+
+ # Match by order in the catalog if tolerance is less than or equal to
+ # zero or by x-y position if tolerance is greater than zero and output
+ # the data.
+
+ if (objid == NULL)
+ call ph_match (imtable, nimages, Memc[outfilters], nfilters, outcat,
+ "", Memr[x], Memr[y], Memr[mag], Memr[merr], Memi[id], npts,
+ tolerance, allfilters, wrap, verbose)
+ else
+ call ph_match (imtable, nimages, Memc[outfilters], nfilters, outcat,
+ Memc[objid], Memr[x], Memr[y], Memr[mag], Memr[merr],
+ Memi[id], npts, tolerance, allfilters, wrap, verbose)
+
+ if (verbose == YES)
+ call printf ("\n")
+
+ # Write the format file for the output catalog.
+
+ call ph_format (fmt, Memc[outfilters], nfilters)
+
+ # Free the data arrays.
+
+ if (objid != NULL)
+ call mfree (objid, TY_CHAR)
+ if (x != NULL)
+ call mfree (x, TY_REAL)
+ if (y != NULL)
+ call mfree (y, TY_REAL)
+ if (mag != NULL)
+ call mfree (mag, TY_REAL)
+ if (merr != NULL)
+ call mfree (merr, TY_REAL)
+ if (id != NULL)
+ call mfree (id, TY_INT)
+
+ # Close the symbol table.
+ call stclose (imtable)
+
+ # Close the files and file lists.
+ if (sets != NULL)
+ call close (sets)
+ if (sh != NULL)
+ call close (sh)
+ if (ap != NULL)
+ call close (ap)
+ if (obs != NULL)
+ call close (obs)
+ call close (outcat)
+ call close (fmt)
+ call clpcls (photfiles)
+
+ call sfree (sp)
+end
+
+
+# PH_SORT -- Sort the data.
+
+procedure ph_sort (imtable, nimages, objid, x, y, mag, merr, imid, id, npts,
+ sortimid, tolerance)
+
+pointer imtable # pointer to the symbol table
+int nimages # the number of images in the symbol table
+char objid[ARB] # the array of object ids objid[1] = EOS if none
+real x[ARB] # array of x coordinates
+real y[ARB] # array of y coordinates
+real mag[ARB] # array of magnitudes
+real merr[ARB] # array of magnitude errors
+int imid[ARB] # array of image ids
+int id[ARB] # array of object ids
+int npts # the number of points
+int sortimid # sort by image and id
+real tolerance # the tolerance in pixels
+
+int i, nptr
+pointer sp, sym, symbol
+pointer sthead(), stnext()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (sym, nimages, TY_INT)
+
+ # Read in the symbol list in the last in first out sense.
+
+ symbol = sthead (imtable)
+ do i = 1, nimages {
+ Memi[sym+i-1] = symbol
+ symbol = stnext (imtable, symbol)
+ }
+
+ # Do the image/object id sort if necessary. This is a real sort
+ # where the actual contents of the arrays are rearranged.
+ # After the image/object id sort recompute the offsets specifying the
+ # location of the image data in the symbol table. The first
+ # pass through the symbol table to picks up the information for the
+ # images that have only one entry. The second pass picks up
+ # information for images that have more than one entry.
+
+ if (sortimid == YES) {
+ if (objid[1] == EOS)
+ call ph_4r2isort (x, y, mag, merr, imid, id, npts)
+ else
+ call ph_1c4r2isort (objid, x, y, mag, merr, imid, id, npts)
+ nptr = npts + 1
+ do i = 1, nimages {
+ symbol = Memi[sym+i-1]
+ if (IMT_NENTRIES(symbol) <= 0)
+ next
+ nptr = nptr - IMT_NENTRIES(symbol)
+ IMT_OFFSET(symbol) = nptr
+ }
+ }
+
+ # Sort on y if necessary. This is an index sort and does not alter
+ # the position of the data.
+
+ if (tolerance > 0) {
+ do i = 1, nimages {
+ symbol = Memi[sym+i-1]
+ if (IMT_NENTRIES(symbol) <= 0)
+ next
+ nptr = IMT_OFFSET(symbol)
+ call ph_qsort (y[nptr], id[nptr], IMT_NENTRIES(symbol), nptr)
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_CORRECT -- Correct the x, y and mag values using the x-y shifts, aperture
+# corrections, and exposure times.
+
+procedure ph_correct (imtable, x, y, mag, merr, minmagerr)
+
+pointer imtable # pointer to the symbol table
+real x[ARB] # array of x coordinates
+real y[ARB] # array of y coordinates
+real mag[ARB] # array of magnitudes
+real merr[ARB] # array of magnitude errors
+real minmagerr # the minimum magnitude error
+
+int i, nptr, ndata
+pointer sp, imname, symbol, osymbol
+real magshift
+pointer sthead(), stnext(), stfind()
+
+begin
+ # Allocate working space.
+
+ call smark (sp)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+
+ # Loop through the images adding the x, y and magnitude shifts to
+ # the data.
+
+ symbol = sthead (imtable)
+ while (symbol != NULL) {
+
+ # Get the correct symbol.
+ ndata = IMT_NENTRIES(symbol)
+ osymbol = stfind (imtable, IMT_IMNAME(symbol))
+
+ # If data is present make the corrections once for each image.
+
+ if ((ndata > 0) && (osymbol == symbol)) {
+ nptr = IMT_OFFSET(symbol)
+
+ # Correct the positions.
+ call aaddkr (x[nptr], IMT_XSHIFT(symbol), x[nptr], ndata)
+ call aaddkr (y[nptr], IMT_YSHIFT(symbol), y[nptr], ndata)
+
+ # Correct the magnitudes.
+ magshift = 2.5 * log10 (IMT_ITIME(symbol)) + IMT_APERCOR(symbol)
+ do i = nptr, nptr + ndata - 1 {
+ if (IS_INDEFR(mag[i]))
+ next
+ mag[i] = mag[i] + magshift
+ if (IS_INDEFR(merr[i]))
+ next
+ if (merr[i] < minmagerr)
+ merr[i] = minmagerr
+ }
+ }
+
+ # Get the next symbol.
+ symbol = stnext (imtable, symbol)
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_MATCH -- Match up the photometry lists by order in the input catalog
+# or x-y position.
+
+procedure ph_match (imtable, nimages, filters, nfilters, out, objid, x, y,
+ mag, merr, ysort, npts, tolerance, allfilters, wrap, verbose)
+
+pointer imtable # pointer to the image name symbol table
+int nimages # the number of images in the symbol table
+char filters[ARB] # the filters string
+int nfilters # the number of filters
+int out # the output file descriptor
+char objid[ARB] # the object id array
+real x[ARB] # the x input array
+real y[ARB] # the y input array
+real mag[ARB] # the magnitude array
+real merr[ARB] # the magnitude error array
+int ysort[ARB] # the y sort index
+int npts # the number of points
+real tolerance # the x-y matching tolerance in pixels
+int allfilters # match in all filters
+int wrap # format the output file for easy reading
+int verbose # print status, warning and error messages
+
+int i, k, nsets, imptr, filterno, ndata
+pointer sp, imsym, filterid, label, sym, match, osymbol, symbol, index
+bool streq()
+int strdic(), ph_nthlabel()
+pointer sthead(), stnext(), stfind()
+
+begin
+ # Write out the output file column headers.
+ call fprintf (out, "\n")
+ if (wrap == YES) {
+ call fprintf (out,
+"# FIELD%17tFILTER%34tOTIME%40tAIRMASS%49tXCENTER%59tYCENTER%71tMAG%77tMERR\n")
+ } else {
+ do i = 1, nfilters {
+ if (i == 1)
+ call fprintf (out,
+"# FIELD%17tFILTER%34tOTIME%40tAIRMASS%49tXCENTER%59tYCENTER%71tMAG%77tMERR ")
+ else
+ call fprintf (out,
+"%2tFILTER%19tOTIME%25tAIRMASS%34tXCENTER%44tYCENTER%56tMAG%62tMERR ")
+ }
+ call fprintf (out,"\n")
+ }
+ call fprintf (out, "\n")
+
+ # Allocate and or initialize working space.
+ call smark (sp)
+ call salloc (imsym, nimages, TY_INT)
+ call salloc (filterid, SZ_FNAME, TY_CHAR)
+ call salloc (label, SZ_FNAME, TY_CHAR)
+ call salloc (sym, nfilters, TY_INT)
+ if (tolerance > 0.0)
+ call malloc (match, npts, TY_INT)
+ else
+ match = NULL
+ index = NULL
+
+
+ # Read in the symbol table pointers and rearrange them so that the
+ # image name symbols are ordered in the same way as the image set
+ # numbers. Compute the total number of image sets at the same time.
+
+ nsets = 0
+ symbol = sthead (imtable)
+ do i = nimages, 1, -1 {
+ nsets = max (nsets, IMT_IMSETNO(symbol))
+ Memi[imsym+i-1] = symbol
+ symbol = stnext (imtable, symbol)
+ }
+
+ # Loop over the image sets.
+ imptr = 1
+ do i = 1, nsets {
+
+ # Clear the array of symbols and set the label.
+ ndata = 0
+ call amovki (NULL, Memi[sym], nfilters)
+ call strcpy (IMT_LABEL(Memi[imsym+imptr-1]), Memc[label], SZ_FNAME)
+
+ # Loop over the images in the set.
+ repeat {
+
+ # Quit if the image pointer exceeds the number of images.
+ if (imptr > nimages)
+ break
+
+ # Get the next symbol for a given image set.
+ symbol = Memi[imsym+imptr-1]
+ if (IMT_IMSETNO(symbol) != i)
+ break
+
+ # Check for duplicate image names.
+ osymbol = stfind (imtable, IMT_IMNAME(symbol))
+ if (osymbol != symbol) {
+ IMT_OFFSET(symbol) = IMT_OFFSET(osymbol)
+ IMT_NENTRIES(symbol) = IMT_NENTRIES(osymbol)
+ IMT_XAIRMASS(symbol) = IMT_XAIRMASS(osymbol)
+ IMT_OTIME(symbol) = IMT_OTIME(osymbol)
+ call strcpy (IMT_IFILTER(osymbol), IMT_IFILTER(symbol),
+ SZ_FNAME)
+ }
+
+ # Search for the filter id, if one is not found then
+ # use the first unoccupied space.
+
+ filterno = strdic (IMT_IFILTER(symbol), Memc[filterid],
+ SZ_FNAME, filters)
+ if (streq (IMT_IFILTER(symbol), "INDEF")) {
+ do k = 1, nfilters {
+ if (Memi[sym+k-1] != NULL)
+ next
+ if (ph_nthlabel (filters, k, Memc[filterid],
+ SZ_FNAME) != k)
+ Memc[filterid] = EOS
+ filterno = k
+ break
+ }
+ }
+
+ # Load the data pointers.
+ if (filterno <= 0) {
+
+ if (verbose == YES) {
+ call eprintf (
+ "Warning: Image set: %d label: %s image: %s\n")
+ call pargi (i)
+ call pargstr (IMT_LABEL(symbol))
+ call pargstr (IMT_IMNAME(symbol))
+ call eprintf (
+ "\tWarning: Filter %s ")
+ call pargstr (IMT_IFILTER(symbol))
+ call eprintf ("does not belong to filter set %s\n")
+ call pargstr (filters)
+ }
+
+ } else if (Memi[sym+filterno-1] != NULL) {
+
+ if (verbose == YES) {
+ call eprintf (
+ "Warning: Image set: %d label: %s image: %s\n")
+ call pargi (i)
+ call pargstr (IMT_LABEL(symbol))
+ call pargstr (IMT_IMNAME(symbol))
+ call eprintf ("\tData for filter %s is redundant\n")
+ call pargstr (Memc[filterid])
+ }
+
+ } else {
+
+ Memi[sym+filterno-1] = symbol
+ ndata = max (ndata, IMT_NENTRIES(symbol))
+ }
+
+ imptr = imptr + 1
+
+ }
+
+ # Skip matching if there are no points.
+ if (ndata <= 0) {
+ if (verbose == YES) {
+ call eprintf ("Image set: %d Label: %s has no data\n")
+ call pargi (i)
+ call pargstr (Memc[label])
+ }
+ next
+ }
+
+ # Do the matching.
+ if (tolerance <= 0.0) {
+ if (objid[1] == EOS)
+ call ph_join (out, Memc[label], Memi[sym], filters,
+ nfilters, "", x, y, mag, merr, allfilters, wrap,
+ verbose)
+ else
+ call ph_join (out, Memc[label], Memi[sym], filters,
+ nfilters, objid, x, y, mag, merr, allfilters, wrap,
+ verbose)
+ } else {
+ if (index == NULL)
+ call malloc (index, nfilters * ndata, TY_INT)
+ else
+ call realloc (index, nfilters * ndata, TY_INT)
+ if (objid[1] == EOS)
+ call ph_merge (out, Memc[label], Memi[sym], filters,
+ nfilters, "", x, y, mag, merr, ysort, Memi[match],
+ Memi[index], ndata, tolerance, allfilters, wrap,
+ verbose)
+ else
+ call ph_merge (out, Memc[label], Memi[sym], filters,
+ nfilters, objid, x, y, mag, merr, ysort, Memi[match],
+ Memi[index], ndata, tolerance, allfilters, wrap,
+ verbose)
+ }
+ }
+
+ # Free working space.
+ if (match != NULL)
+ call mfree (match, TY_INT)
+ if (index != NULL)
+ call mfree (index, TY_INT)
+ call sfree (sp)
+end
+
+
+# PH_FORMAT -- Write the format file for the output catalog.
+
+procedure ph_format (fd, filters, nfilters)
+
+int fd # file descripter for the format file
+char filters[ARB] # list of filter ids
+int nfilters # number of filters
+
+int i, col
+pointer sp, filterid
+int ph_nthlabel()
+
+begin
+ call smark (sp)
+ call salloc (filterid, SZ_FNAME, TY_CHAR)
+
+ call fprintf (fd, "# Declare the observations file variables\n\n")
+ call fprintf (fd, "observations\n\n")
+
+ col = FIRST_COLUMN
+ do i = 1, nfilters {
+ if (ph_nthlabel (filters, i, Memc[filterid], SZ_FNAME) != i)
+ Memc[filterid] = EOS
+ call fprintf (fd,
+ "T%s%15t%d%30t# time of observation in filter %s\n")
+ call pargstr (Memc[filterid])
+ call pargi (col)
+ call pargstr (Memc[filterid])
+ col = col + 1
+ call fprintf (fd, "X%s%15t%d%30t# airmass in filter %s\n")
+ call pargstr (Memc[filterid])
+ call pargi (col)
+ call pargstr (Memc[filterid])
+ col = col + 1
+ call fprintf (fd, "x%s%15t%d%30t# x coordinate in filter %s\n")
+ call pargstr (Memc[filterid])
+ call pargi (col)
+ call pargstr (Memc[filterid])
+ col = col + 1
+ call fprintf (fd, "y%s%15t%d%30t# y coordinate in filter %s\n")
+ call pargstr (Memc[filterid])
+ call pargi (col)
+ call pargstr (Memc[filterid])
+ col = col + 1
+ call fprintf (fd,
+ "m%s%15t%d%30t# instrumental magnitude in filter %s\n")
+ call pargstr (Memc[filterid])
+ call pargi (col)
+ call pargstr (Memc[filterid])
+ col = col + 1
+ call fprintf (fd,
+ "error(m%s)%15t%d%30t# magnitude error in filter %s\n")
+ call pargstr (Memc[filterid])
+ call pargi (col)
+ call pargstr (Memc[filterid])
+ call fprintf (fd, "\n")
+ col = col + DELTA_COLUMN
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_NXTIMAGE -- Find the first line in the input catalog containing the next
+# image name, given the current image name. Return the new image name and line.
+
+int procedure ph_nxtimage (fd, columns, image, line, lbufsize)
+
+int fd # file descriptor of the input text file
+int columns[ARB] # the list of input columns
+char image[ARB] # the name of the current image
+pointer line # pointer to the output line
+int lbufsize # the line buffer size
+
+int i, op, colno
+long stat
+pointer sp, str
+bool streq()
+int getline(), nscan()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ if (line == NULL || lbufsize <= 0) {
+ lbufsize = lbufsize + SZ_LINE
+ call malloc (line, lbufsize, TY_CHAR)
+ }
+
+ colno = columns[CAT_IMAGE]
+ Memc[str] = EOS
+ repeat {
+
+ op = 1
+ repeat {
+ stat = getline (fd, Memc[line+op-1])
+ if (stat == EOF)
+ break
+ op = op + stat
+ if (op > lbufsize) {
+ lbufsize = lbufsize + SZ_LINE
+ call realloc (line, lbufsize, TY_CHAR)
+ }
+ } until (Memc[line+op-2] == '\n')
+ if (stat == EOF)
+ break
+ else
+ stat = op - 1
+
+ call sscan (Memc[line])
+ do i = 1, colno
+ call gargwrd (Memc[str], SZ_FNAME)
+ if (nscan() != colno)
+ next
+
+ } until (! streq (image, Memc[str]))
+ call strcpy (Memc[str], image, SZ_FNAME)
+
+ call sfree (sp)
+
+ return (stat)
+end
+
+
+# PH_GETIMAGE -- Read the next line in the input catalog and return the image
+# name and the line.
+
+int procedure ph_getimage (fd, columns, image, line, lbufsize)
+
+int fd # file descriptor of the input text file
+int columns[ARB] # the list of input columns
+char image[ARB] # the name of the current image
+pointer line # pointer to the output line
+int lbufsize # the size of the output buffer
+
+int op, i, colno
+int stat
+int getline(), nscan()
+
+begin
+ if (line == NULL || lbufsize <= 0) {
+ lbufsize = lbufsize + SZ_LINE
+ call malloc (line, lbufsize, TY_CHAR)
+ }
+
+ colno = columns[CAT_IMAGE]
+ repeat {
+
+ op = 1
+ repeat {
+ stat = getline (fd, Memc[line+op-1])
+ if (stat == EOF)
+ break
+ op = op + stat
+ if (op > lbufsize) {
+ lbufsize = lbufsize + SZ_LINE
+ call realloc (line, lbufsize, TY_CHAR)
+ }
+ } until (Memc[line+op-2] == '\n')
+ if (stat == EOF)
+ break
+ else
+ stat = op - 1
+
+ call sscan (Memc[line])
+ do i = 1, colno
+ call gargwrd (image, SZ_FNAME)
+ if (nscan() != colno)
+ next
+
+ break
+ }
+
+ return (stat)
+end
+
+
+# PH_IMDATA -- Decode the filter id, integration time and airmass from
+# a line of the input catalog.
+
+procedure ph_imdata (line, columns, filterid, sz_filterid, itime, airmass,
+ otime)
+
+char line[ARB] # input line to be scanned
+int columns[ARB] # the list of input columns
+char filterid[ARB] # the name of the filter
+int sz_filterid # maximum length of the filter id
+real itime # the exposure time of the observation
+real airmass # the airmass of the observation
+real otime # the time of observations
+
+int i, fcol, icol, acol, ocol, maxcol
+pointer sp, str
+int nscan()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ fcol = columns[CAT_IFILTER]
+ icol = columns[CAT_ITIME]
+ acol = columns[CAT_XAIRMASS]
+ ocol = columns[CAT_OTIME]
+ maxcol = max (fcol, icol, acol, ocol)
+
+ call strcpy ("INDEF", filterid, sz_filterid)
+ itime = INDEFR
+ airmass = INDEFR
+ otime = INDEFR
+
+ call sscan (line)
+ do i = 1, maxcol {
+ if ( i == fcol) {
+ call gargwrd (filterid, sz_filterid)
+ if (nscan() != fcol)
+ call strcpy ("INDEF", filterid, sz_filterid)
+ } else if (i == icol) {
+ call gargr (itime)
+ if (nscan() != icol)
+ itime = INDEFR
+ } else if (i == acol) {
+ call gargr (airmass)
+ if (nscan() != acol)
+ airmass = INDEFR
+ } else if (i == ocol) {
+ call gargr (otime)
+ if (nscan() != ocol)
+ otime = INDEFR
+ } else {
+ call gargwrd (Memc[str], SZ_LINE)
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_OBSDATA -- Decode the filter id, integration time and airmass from
+# a line of the observing parameters file.
+
+procedure ph_obsdata (line, columns, filterid, sz_filterid, itime, airmass,
+ otime)
+
+char line[ARB] # input line to be scanned
+int columns[ARB] # the list of input columns
+char filterid[ARB] # the name of the filter
+int sz_filterid # maximum length of the filter id
+real itime # the exposure time of the observation
+real airmass # the airmass of the observation
+real otime # the time of observation
+
+int i, fcol, icol, acol, ocol, maxcol
+pointer sp, str
+int nscan()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ fcol = columns[OBS_IFILTER]
+ icol = columns[OBS_ITIME]
+ acol = columns[OBS_XAIRMASS]
+ ocol = columns[OBS_OTIME]
+ maxcol = max (fcol, icol, acol, ocol)
+
+ call strcpy ("INDEF", filterid, sz_filterid)
+ itime = INDEFR
+ airmass = INDEFR
+ otime = INDEFR
+
+ call sscan (line)
+ do i = 1, maxcol {
+ if ( i == fcol) {
+ call gargwrd (filterid, sz_filterid)
+ if (nscan() != fcol)
+ call strcpy ("INDEF", filterid, sz_filterid)
+ } else if (i == icol) {
+ call gargr (itime)
+ if (nscan() != icol)
+ itime = INDEFR
+ } else if (i == acol) {
+ call gargr (airmass)
+ if (nscan() != acol)
+ airmass = INDEFR
+ } else if (i == ocol) {
+ call gargr (otime)
+ if (nscan() != ocol)
+ otime = INDEFR
+ } else {
+ call gargwrd (Memc[str], SZ_LINE)
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# PH_STARDATA -- Decode the image name, x and y coordinates, magnitude
+# and magnitude error from the input catalog.
+
+int procedure ph_stardata (line, columns, objid, x, y, mag, merr)
+
+char line[ARB] # input line to be scanned
+int columns[ARB] # the list of input columns
+char objid[ARB] # the object id
+real x, y # the output x and y coordinates
+real mag, merr # the output magnitude and magnitude error
+
+int i, icol, xcol, ycol, mcol, ecol, maxcol, stat
+pointer sp, str
+int nscan()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ icol = columns[CAT_ID]
+ xcol= columns[CAT_XCENTER]
+ ycol= columns[CAT_YCENTER]
+ mcol = columns[CAT_MAG]
+ ecol = columns[CAT_MERR]
+ maxcol = max (icol, xcol, ycol, mcol, ecol)
+
+ objid[1] = EOS
+ x = INDEFR
+ y = INDEFR
+ mag = INDEFR
+ merr = INDEFR
+ stat = OK
+
+ call sscan (line)
+ do i = 1, maxcol {
+
+ if (i == icol) {
+ call gargwrd (objid, DEF_LENLABEL)
+ if (nscan() != icol)
+ stat = ERR
+ } else if (i == xcol) {
+ call gargr (x)
+ if (nscan() != xcol)
+ stat = ERR
+ } else if (i == ycol) {
+ call gargr (y)
+ if (nscan() != ycol)
+ stat = ERR
+ } else if (i == mcol) {
+ call gargr (mag)
+ if (nscan() != mcol)
+ stat = ERR
+ } else if (i == ecol) {
+ call gargr (merr)
+ if (nscan() != ecol)
+ stat = ERR
+ } else {
+ call gargwrd (Memc[str], SZ_LINE)
+ if (nscan() != i)
+ stat = ERR
+ }
+ }
+
+ call sfree (sp)
+
+ return (stat)
+end
+
+
+# PH_FILTERS -- Reformat the filter string so that it is a suitable string
+# dictionary for the STRDIC routine.
+
+int procedure ph_filters (infilters, outfilters, max_lenfilters)
+
+char infilters[ARB] # input list of filters
+char outfilters[ARB] # output list of filters
+int max_lenfilters # maximum length of the filter string
+
+int ip, nfilters
+pointer sp, filter
+int ph_getlabels()
+
+begin
+ call smark (sp)
+ call salloc (filter, max_lenfilters, TY_CHAR)
+
+ ip = 1
+ nfilters = 0
+ outfilters[1] = EOS
+ while (ph_getlabels (infilters, ip, Memc[filter], max_lenfilters) !=
+ EOF) {
+ call strcat (",", outfilters, max_lenfilters)
+ call strcat (Memc[filter], outfilters, max_lenfilters)
+ nfilters = nfilters + 1
+ }
+
+ call sfree (sp)
+
+ return (nfilters)
+end
+
+
+# PH_NTHLABEL -- Get the nth label out of a list of labels.
+
+int procedure ph_nthlabel (list, item, label, maxch)
+
+char list[ARB] # input list
+int item # item to be extracted
+char label[ARB] # extracted label
+int maxch # maximum length of the extracted label
+
+int ip, nitems
+int ph_getlabels()
+
+begin
+ nitems = 0
+
+ ip = 1
+ while (ph_getlabels (list, ip, label, maxch) != EOF) {
+ nitems = nitems + 1
+ if (nitems == item)
+ break
+ }
+
+ return (nitems)
+end
+
+
+# PH_GETLABELS -- Get the next label from a list of labels.
+
+int procedure ph_getlabels (list, ip, label, maxch)
+
+char list[ARB] # list of labels
+int ip # pointer in to the list of labels
+char label[ARB] # the output label
+int maxch # maximum length of a column name
+
+int op, token
+int ctotok(), strlen()
+
+begin
+ # Decode the column labels.
+ op = 1
+ while (list[ip] != EOS) {
+
+ token = ctotok (list, ip, label[op], maxch)
+ if (label[op] == EOS)
+ next
+ if ((token == TOK_UNKNOWN) || (token == TOK_CHARCON))
+ break
+ if ((token == TOK_PUNCTUATION) && (label[op] == ',')) {
+ if (op == 1)
+ next
+ else
+ break
+ }
+
+ op = op + strlen (label[op])
+ if (IS_WHITE(list[ip]))
+ break
+ }
+
+ label[op] = EOS
+ if ((list[ip] == EOS) && (op == 1))
+ return (EOF)
+ else
+ return (op - 1)
+end
diff --git a/noao/digiphot/photcal/mkphotcors.par b/noao/digiphot/photcal/mkphotcors.par
new file mode 100644
index 00000000..3bf18a2e
--- /dev/null
+++ b/noao/digiphot/photcal/mkphotcors.par
@@ -0,0 +1,10 @@
+# Parameter file for MKPHOTCORS
+
+imsets,f,a,"",,,The image set file
+idfilters,s,a,"",,,The list of filter ids
+obsparams,f,a,"",,,The input observing parameters files
+shifts,f,a,"",,,The x and y coordinate shifts file
+apercors,f,a,"",,,The aperture corrections file
+obscolumns,s,h,"2 3 4 5",,,The format of obsparams
+verify,b,h,no,,,Verify interactive user input ?
+verbose,b,h,yes,,,Print status warning and error messages
diff --git a/noao/digiphot/photcal/mkpkg b/noao/digiphot/photcal/mkpkg
new file mode 100644
index 00000000..0f47b692
--- /dev/null
+++ b/noao/digiphot/photcal/mkpkg
@@ -0,0 +1,38 @@
+# Make the PHOTCAL package
+
+$call relink
+$exit
+
+update:
+ $call relink
+ $call install
+ ;
+
+relink:
+ $set LIBS = "-lxtools -lnlfit"
+ $update libpkg.a
+ $omake x_photcal.x
+ $link x_photcal.o libpkg.a $(LIBS) -o xx_photcal.e
+ ;
+
+linkonly:
+ $set LIBS = "-lxtools -lnlfit"
+ $link x_photcal.o libpkg.a $(LIBS) -o xx_photcal.e
+ $call install
+ ;
+
+install:
+ $move xx_photcal.e noaobin$x_photcal.e
+ ;
+
+libpkg.a:
+ @evaluate
+ @fitparams
+ @io
+ @mctable
+ @mkcatalog
+ @mkconfig
+ @mkimsets
+ @mkobsfile
+ @parser
+ ;
diff --git a/noao/digiphot/photcal/obsfile.par b/noao/digiphot/photcal/obsfile.par
new file mode 100644
index 00000000..4c64ffc4
--- /dev/null
+++ b/noao/digiphot/photcal/obsfile.par
@@ -0,0 +1,18 @@
+# Parameter file for OBSFILE
+
+photfiles,f,a,,,,The list of input text files
+incolumns,s,a,"",,,The format of the input files
+idfilters,s,a,"",,,The list of filter ids
+imsets,f,a,"",,,The image set file
+observations,f,a,"",,,The output observations file
+wrap,b,h,yes,,,Format the observation file for easy reading ?
+obsparams,f,h,"",,,The input observing parameters files
+obscolumns,s,h,"2 3 4 5",,The format of obsparams
+minmagerr,r,h,0.001,0.0,,The minimum magnitude error
+shifts,f,h,"",,,The x and y coordinate shifts file
+apercors,f,h,"",,,The aperture corrections file
+normtime,b,h,no,,,Normalize the exposure times ?
+tolerance,r,h,5.0,,,The position matching tolerance in pixels
+allfilters,b,h,yes,,,Output objects measured in all filters only ?
+verify,b,h,no,,,Verify interactive user input ?
+verbose,b,h,yes,,,Print status warning and error messages ?
diff --git a/noao/digiphot/photcal/parser/README b/noao/digiphot/photcal/parser/README
new file mode 100644
index 00000000..511483ea
--- /dev/null
+++ b/noao/digiphot/photcal/parser/README
@@ -0,0 +1,2 @@
+This subdirectory contains the parser code and the main routine for the
+CHKCONFIG task.
diff --git a/noao/digiphot/photcal/parser/TODO b/noao/digiphot/photcal/parser/TODO
new file mode 100644
index 00000000..33227eb0
--- /dev/null
+++ b/noao/digiphot/photcal/parser/TODO
@@ -0,0 +1,4 @@
+1. Generalize the pr_eval procedures to any number of recursions, with a limit
+ to avoid infinite loops.
+
+2. Allow any number of plot equations.
diff --git a/noao/digiphot/photcal/parser/lexer.com b/noao/digiphot/photcal/parser/lexer.com
new file mode 100644
index 00000000..76255b55
--- /dev/null
+++ b/noao/digiphot/photcal/parser/lexer.com
@@ -0,0 +1,13 @@
+# Lexer common. This is necessary since the parser, generated by xyacc,
+# does not allow any access to the lexer to initialize it, or to get
+# variable values.
+
+# Variables to initialize lexer
+int nlines # line counter
+int pos # character position in line
+char line[SZ_LINE] # last line from file
+
+# Variables returned by lexer
+char id[SZ_LINE] # last identifier from lexer
+
+common /lexcom/ nlines, pos, line, id
diff --git a/noao/digiphot/photcal/parser/mkpkg b/noao/digiphot/photcal/parser/mkpkg
new file mode 100644
index 00000000..0580f0e0
--- /dev/null
+++ b/noao/digiphot/photcal/parser/mkpkg
@@ -0,0 +1,43 @@
+# The MKPKG file for the PARSER subdirectory.
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ $ifnewer (preval.gx, preval.x)
+ $generic -k -o preval.x preval.gx
+ $endif
+
+ $ifnewer (parser.y, parser.x)
+ $ifeq (HOSTID, unix)
+ $echo "parser.x is out of date; rebuilding with XYACC:"
+ !xyacc -d parser.y
+ $move ytab.x parser.x
+ $move ytab.h ../lib/prtoken.h
+ $else
+ $echo "parser.x is out of date; rebuild with XYACC"
+ $endif
+ $endif
+
+ parser.x "../lib/lexer.h" "../lib/parser.h" "../lib/prdefs.h"\
+ <ctype.h> <lexnum.h>
+ pralloc.x "../lib/parser.h" "../lib/prstruct.h" "parser.com"
+ prcat.x
+ prcode.x "../lib/lexer.h" "../lib/parser.h" "../lib/preval.h"\
+ "../lib/prtoken.h" "prcode.com"
+ prconv.x "../lib/parser.h"
+ prerror.x "../lib/parser.h" "../lib/prdefs.h" "lexer.com"
+ preval.x "../lib/parser.h" "../lib/preval.h"
+ prexit.x "../lib/parser.h" "../lib/prdefs.h" <mach.h>
+ prget.x "../lib/parser.h" "../lib/prstruct.h" "parser.com"
+ prlexer.x "../lib/lexer.h" "../lib/prtoken.h" "lexer.com"\
+ <ctype.h> <lexnum.h>
+ prmap.x "../lib/parser.h" "../lib/prdefs.h"
+ prparse.x "../lib/parser.h" "../lib/prdefs.h" "lexer.com"
+ prput.x "../lib/parser.h" "../lib/prstruct.h" "parser.com"
+ prtable.x "../lib/parser.h" "../lib/prdefs.h" <mach.h>
+ prvtran.x
+ t_chkconfig.x "../lib/parser.h"
+ ;
diff --git a/noao/digiphot/photcal/parser/parser.com b/noao/digiphot/photcal/parser/parser.com
new file mode 100644
index 00000000..db47e0d8
--- /dev/null
+++ b/noao/digiphot/photcal/parser/parser.com
@@ -0,0 +1,49 @@
+# Parser common
+
+# Symbol tables
+pointer symtable # parser symbol table
+
+# Sequential tables
+pointer obstable # observational variable table
+pointer cattable # catalog variable table
+pointer partable # fitting and constant parameter table
+pointer settable # set equation table
+pointer exttable # extinction equation table
+pointer trntable # transformation equation table
+pointer trcattable # temporary reference eq. catalog var. table
+pointer trobstable # temporary ref. eq. observational var. table
+pointer tfcattable # temporary fit eq. catalog var. table
+pointer tfobstable # temporary fit eq. observational var. table
+pointer tpartable # temporary parameter table
+
+# Counters
+int nerrors # number of semantic errors
+int nwarnings # number of warnings
+int nobsvars # number of observational input variables
+int ncatvars # number of catalog input variables
+int nfitpars # number of fitting parameters
+int ntotpars # number of fitting and constant parameters
+int nseteqs # number of set equations
+int nexteqs # number of extinction equations
+int ntrneqs # number of transformation equations
+
+# Column limits
+int mincol # minumum input column
+int minobscol # minumum observational column
+int maxobscol # maximum observational column
+int mincatcol # minumum catalog column
+int maxcatcol # maximum catalog column
+
+# Flags
+int flageqsect # equation section
+int flagerrors # print error messages (YES/NO)
+
+common /parcom/ symtable,
+ obstable, cattable, partable,
+ settable, exttable, trntable,
+ trcattable, trobstable, tfcattable, tfobstable, tpartable,
+ nerrors, nwarnings,
+ nobsvars, ncatvars, nfitpars, ntotpars,
+ nseteqs, nexteqs, ntrneqs,
+ mincol, minobscol, maxobscol, mincatcol, maxcatcol,
+ flageqsect, flagerrors
diff --git a/noao/digiphot/photcal/parser/parser.x b/noao/digiphot/photcal/parser/parser.x
new file mode 100644
index 00000000..47d8ce5b
--- /dev/null
+++ b/noao/digiphot/photcal/parser/parser.x
@@ -0,0 +1,849 @@
+
+# line 2 "parser.y"
+
+include <ctype.h>
+include <lexnum.h>
+include "../lib/lexer.h"
+include "../lib/parser.h"
+include "../lib/prdefs.h"
+
+# Parser stack and structure lengths
+define YYMAXDEPTH 128
+define YYOPLEN LEN_LEX
+
+# Redefine the name of the parser
+define yyparse parse
+
+define OBSSECT 257
+define CATSECT 258
+define EXTSECT 259
+define TRNSECT 260
+define FITID 261
+define CONSTID 262
+define DELTAID 263
+define ERRORID 264
+define WEIGHTID 265
+define MINID 266
+define MAXID 267
+define DERIVID 268
+define PLOTID 269
+define SETID 270
+define F_ABS 271
+define F_ACOS 272
+define F_ASIN 273
+define F_ATAN 274
+define F_COS 275
+define F_EXP 276
+define F_LOG 277
+define F_LOG10 278
+define F_SIN 279
+define F_SQRT 280
+define F_TAN 281
+define IDENTIFIER 282
+define INUMBER 283
+define RNUMBER 284
+define PLUS 285
+define MINUS 286
+define STAR 287
+define SLASH 288
+define EXPON 289
+define COLON 290
+define SEMICOLON 291
+define COMMA 292
+define EQUAL 293
+define LPAR 294
+define RPAR 295
+define EOFILE 296
+define UPLUS 297
+define UMINUS 298
+define yyclearin yychar = -1
+define yyerrok yyerrflag = 0
+define YYMOVE call amovi (Memi[$1], Memi[$2], YYOPLEN)
+define YYERRCODE 256
+
+define YYNPROD 104
+define YYLAST 337
+# line 1 "/iraf/iraf/lib/yaccpar.x"
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+# Parser for yacc output, translated to the IRAF SPP language. The contents
+# of this file form the bulk of the source of the parser produced by Yacc.
+# Yacc recognizes several macros in the yaccpar input source and replaces
+# them as follows:
+# A user suppled "global" definitions and declarations
+# B parser tables
+# C user supplied actions (reductions)
+# The remainder of the yaccpar code is not changed.
+
+define yystack_ 10 # statement labels for gotos
+define yynewstate_ 20
+define yydefault_ 30
+define yyerrlab_ 40
+define yyabort_ 50
+
+define YYFLAG (-1000) # defs used in user actions
+define YYERROR goto yyerrlab_
+define YYACCEPT return (OK)
+define YYABORT return (ERR)
+
+
+# YYPARSE -- Parse the input stream, returning OK if the source is
+# syntactically acceptable (i.e., if compilation is successful),
+# otherwise ERR. The parameters YYMAXDEPTH and YYOPLEN must be
+# supplied by the caller in the %{ ... %} section of the Yacc source.
+# The token value stack is a dynamically allocated array of operand
+# structures, with the length and makeup of the operand structure being
+# application dependent.
+
+int procedure yyparse (fd, yydebug, yylex)
+
+int fd # stream to be parsed
+bool yydebug # print debugging information?
+int yylex() # user-supplied lexical input function
+extern yylex()
+
+short yys[YYMAXDEPTH] # parser stack -- stacks tokens
+pointer yyv # pointer to token value stack
+pointer yyval # value returned by action
+pointer yylval # value of token
+int yyps # token stack pointer
+pointer yypv # value stack pointer
+int yychar # current input token number
+int yyerrflag # error recovery flag
+int yynerrs # number of errors
+
+short yyj, yym # internal variables
+pointer yysp, yypvt
+short yystate, yyn
+int yyxi, i
+errchk salloc, yylex
+
+short yyexca[6]
+data (yyexca(i),i= 1, 6) / -1, 1, 0, -1, -2, 0/
+short yyact[337]
+data (yyact(i),i= 1, 8) / 131, 132, 133, 134, 135, 136, 137, 138/
+data (yyact(i),i= 9, 16) / 139, 140, 141, 130, 142, 143, 125, 126/
+data (yyact(i),i= 17, 24) / 152, 153, 154, 155, 156, 40, 161, 128/
+data (yyact(i),i= 25, 32) / 183, 112, 180, 152, 153, 154, 155, 156/
+data (yyact(i),i= 33, 40) / 60, 61, 62, 58, 59, 175, 111, 52/
+data (yyact(i),i= 41, 48) / 53, 57, 108, 86, 85, 84, 83, 159/
+data (yyact(i),i= 49, 56) / 73, 72, 70, 69, 39, 51, 38, 34/
+data (yyact(i),i= 57, 64) / 33, 24, 25, 18, 19, 198, 42, 196/
+data (yyact(i),i= 65, 72) / 35, 176, 152, 153, 154, 155, 156, 148/
+data (yyact(i),i= 73, 80) / 147, 145, 107, 23, 123, 17, 99, 97/
+data (yyact(i),i= 81, 88) / 95, 91, 98, 96, 21, 29, 15, 68/
+data (yyact(i),i= 89, 96) / 94, 154, 155, 156, 28, 60, 61, 62/
+data (yyact(i),i= 97,104) / 58, 59, 156, 32, 52, 53, 57, 116/
+data (yyact(i),i=105,112) / 117, 142, 143, 24, 25, 18, 19, 144/
+data (yyact(i),i=113,120) / 82, 79, 51, 76, 93, 92, 90, 89/
+data (yyact(i),i=121,128) / 71, 66, 65, 64, 63, 23, 194, 17/
+data (yyact(i),i=129,136) / 190, 27, 12, 3, 129, 4, 7, 106/
+data (yyact(i),i=137,144) / 5, 104, 8, 193, 10, 124, 13, 189/
+data (yyact(i),i=145,152) / 184, 114, 74, 80, 41, 20, 14, 115/
+data (yyact(i),i=153,160) / 77, 31, 127, 105, 109, 81, 78, 75/
+data (yyact(i),i=161,168) / 56, 55, 54, 166, 164, 162, 181, 30/
+data (yyact(i),i=169,176) / 150, 87, 50, 49, 36, 48, 47, 46/
+data (yyact(i),i=177,184) / 45, 37, 44, 43, 22, 9, 16, 26/
+data (yyact(i),i=185,192) / 11, 6, 2, 1, 0, 0, 0, 0/
+data (yyact(i),i=193,200) / 67, 0, 0, 0, 0, 0, 0, 0/
+data (yyact(i),i=201,208) / 0, 0, 0, 0, 88, 0, 0, 0/
+data (yyact(i),i=209,216) / 0, 0, 0, 0, 0, 0, 0, 0/
+data (yyact(i),i=217,224) / 0, 0, 0, 0, 0, 0, 0, 0/
+data (yyact(i),i=225,232) / 0, 0, 0, 110, 0, 0, 0, 118/
+data (yyact(i),i=233,240) / 0, 118, 0, 118, 0, 100, 101, 102/
+data (yyact(i),i=241,248) / 103, 113, 0, 120, 0, 122, 121, 146/
+data (yyact(i),i=249,256) / 149, 119, 0, 0, 0, 0, 0, 0/
+data (yyact(i),i=257,264) / 0, 0, 0, 151, 0, 0, 0, 0/
+data (yyact(i),i=265,272) / 0, 0, 0, 157, 158, 0, 160, 0/
+data (yyact(i),i=273,280) / 0, 0, 0, 0, 0, 0, 0, 0/
+data (yyact(i),i=281,288) / 0, 163, 0, 165, 167, 0, 0, 0/
+data (yyact(i),i=289,296) / 168, 0, 0, 0, 0, 0, 169, 170/
+data (yyact(i),i=297,304) / 171, 172, 173, 0, 177, 174, 178, 0/
+data (yyact(i),i=305,312) / 179, 0, 0, 0, 0, 0, 0, 0/
+data (yyact(i),i=313,320) / 182, 0, 185, 185, 0, 0, 0, 187/
+data (yyact(i),i=321,328) / 191, 188, 191, 0, 186, 195, 0, 0/
+data (yyact(i),i=329,336) / 195, 0, 192, 0, 197, 0, 199, 0/
+data (yyact(i),i=337,337) / 200/
+short yypact[201]
+data (yypact(i),i= 1, 8) /-125,-1000,-123,-1000,-1000,-1000,-129,-205/
+data (yypact(i),i= 9, 16) /-1000,-207,-1000,-131,-199,-1000,-206,-1000/
+data (yypact(i),i= 17, 24) /-155,-184,-238,-239,-227,-1000,-157,-184/
+data (yypact(i),i= 25, 32) /-240,-242,-275,-229,-1000,-1000,-1000,-1000/
+data (yypact(i),i= 33, 40) /-1000,-158,-159,-1000,-1000,-1000,-160,-161/
+data (yypact(i),i= 41, 48) /-1000,-1000,-1000,-168,-1000,-1000,-1000,-1000/
+data (yypact(i),i= 49, 56) /-1000,-1000,-1000,-203,-243,-244,-1000,-1000/
+data (yypact(i),i= 57, 64) /-1000,-162,-245,-246,-167,-169,-170,-249/
+data (yypact(i),i= 65, 72) /-250,-251,-252,-1000,-1000,-163,-164,-212/
+data (yypact(i),i= 73, 80) /-165,-166,-1000,-204,-213,-1000,-209,-214/
+data (yypact(i),i= 81, 88) /-1000,-210,-215,-184,-184,-184,-184,-1000/
+data (yypact(i),i= 89, 96) /-1000,-218,-253,-1000,-257,-270,-167,-182/
+data (yypact(i),i= 97,104) /-169,-182,-170,-182,-1000,-1000,-1000,-1000/
+data (yypact(i),i=105,112) /-217,-271,-1000,-171,-220,-1000,-1000,-221/
+data (yypact(i),i=113,120) /-222,-1000,-1000,-178,-1000,-1000,-1000,-1000/
+data (yypact(i),i=121,128) /-1000,-1000,-1000,-1000,-219,-271,-271,-247/
+data (yypact(i),i=129,136) /-271,-1000,-1000,-1000,-1000,-1000,-1000,-1000/
+data (yypact(i),i=137,144) /-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000/
+data (yypact(i),i=145,152) /-273,-1000,-1000,-1000,-1000,-1000,-1000,-1000/
+data (yypact(i),i=153,160) /-271,-271,-271,-271,-271,-1000,-1000,-271/
+data (yypact(i),i=161,168) /-258,-228,-1000,-1000,-1000,-1000,-1000,-1000/
+data (yypact(i),i=169,176) /-1000,-198,-198,-191,-191,-1000,-269,-1000/
+data (yypact(i),i=177,184) /-1000,-268,-1000,-1000,-1000,-1000,-1000,-1000/
+data (yypact(i),i=185,192) /-138,-1000,-138,-1000,-1000,-141,-230,-1000/
+data (yypact(i),i=193,200) /-141,-1000,-232,-1000,-1000,-1000,-1000,-1000/
+data (yypact(i),i=201,201) /-1000/
+short yypgo[48]
+data (yypgo(i),i= 1, 8) / 0, 187, 186, 185, 184, 183, 150, 135/
+data (yypgo(i),i= 9, 16) / 182, 153, 181, 149, 180, 148, 179, 178/
+data (yypgo(i),i= 17, 24) / 176, 175, 174, 173, 171, 170, 169, 137/
+data (yypgo(i),i= 25, 32) / 168, 166, 165, 164, 144, 143, 139, 163/
+data (yypgo(i),i= 33, 40) / 162, 161, 160, 146, 159, 145, 152, 158/
+data (yypgo(i),i= 41, 48) / 147, 157, 156, 155, 141, 154, 132, 151/
+short yyr1[104]
+data (yyr1(i),i= 1, 8) / 0, 1, 1, 3, 3, 3, 3, 3/
+data (yyr1(i),i= 9, 16) / 6, 6, 8, 8, 8, 2, 2, 2/
+data (yyr1(i),i= 17, 24) / 2, 2, 10, 11, 11, 12, 12, 12/
+data (yyr1(i),i= 25, 32) / 9, 4, 4, 4, 5, 5, 5, 13/
+data (yyr1(i),i= 33, 40) / 13, 14, 14, 14, 14, 14, 14, 14/
+data (yyr1(i),i= 41, 48) / 15, 22, 24, 16, 25, 17, 26, 20/
+data (yyr1(i),i= 49, 56) / 27, 21, 31, 28, 29, 29, 30, 30/
+data (yyr1(i),i= 57, 64) / 18, 18, 18, 32, 35, 35, 36, 33/
+data (yyr1(i),i= 65, 72) / 38, 38, 39, 34, 40, 40, 41, 19/
+data (yyr1(i),i= 73, 80) / 42, 23, 43, 44, 44, 44, 44, 44/
+data (yyr1(i),i= 81, 88) / 44, 44, 44, 44, 44, 44, 45, 45/
+data (yyr1(i),i= 89, 96) / 45, 45, 45, 45, 45, 45, 45, 45/
+data (yyr1(i),i= 97,104) / 45, 37, 47, 47, 47, 46, 46, 7/
+short yyr2[104]
+data (yyr2(i),i= 1, 8) / 0, 5, 1, 2, 3, 2, 1, 1/
+data (yyr2(i),i= 9, 16) / 1, 2, 2, 5, 5, 3, 4, 3/
+data (yyr2(i),i= 17, 24) / 2, 1, 1, 1, 2, 2, 5, 5/
+data (yyr2(i),i= 25, 32) / 1, 2, 1, 1, 2, 2, 1, 1/
+data (yyr2(i),i= 33, 40) / 2, 1, 1, 1, 1, 1, 1, 1/
+data (yyr2(i),i= 41, 48) / 7, 1, 1, 9, 1, 9, 1, 10/
+data (yyr2(i),i= 49, 56) / 1, 10, 1, 1, 3, 1, 3, 1/
+data (yyr2(i),i= 57, 64) / 1, 1, 1, 2, 1, 3, 3, 2/
+data (yyr2(i),i= 65, 72) / 1, 3, 3, 2, 1, 3, 3, 5/
+data (yyr2(i),i= 73, 80) / 1, 2, 1, 3, 3, 3, 3, 3/
+data (yyr2(i),i= 81, 88) / 2, 2, 4, 3, 1, 1, 1, 1/
+data (yyr2(i),i= 89, 96) / 1, 1, 1, 1, 1, 1, 1, 1/
+data (yyr2(i),i= 97,104) / 1, 2, 1, 1, 1, 1, 1, 0/
+short yychk[201]
+data (yychk(i),i= 1, 8) /-1000, -1, -2, 256, 258, -7, -3, 257/
+data (yychk(i),i= 9, 16) / -7, -10, -7, -4, 259, -7, -6, 291/
+data (yychk(i),i= 17, 24) / -8, 282, 264, 265, -11, 291, -12, 282/
+data (yychk(i),i= 25, 32) / 264, 265, -5, 260, 291, 291, -6, -9/
+data (yychk(i),i= 33, 40) / 283, 294, 294, 291, -11, -9, 294, 294/
+data (yychk(i),i= 41, 48) / 296, -13, 291, -14, -15, -16, -17, -18/
+data (yychk(i),i= 49, 56) / -19, -20, -21, 282, 268, 269, -32, -33/
+data (yychk(i),i= 57, 64) / -34, 270, 264, 265, 261, 262, 263, 282/
+data (yychk(i),i= 65, 72) / 282, 282, 282, -13, 290, 294, 294, 282/
+data (yychk(i),i= 73, 80) / 294, 294, -35, -36, 282, -38, -39, 282/
+data (yychk(i),i= 81, 88) / -40, -41, 282, 295, 295, 295, 295, -22/
+data (yychk(i),i= 89, 96) / -7, 282, 282, 293, 282, 282, 292, 293/
+data (yychk(i),i= 97,104) / 292, 293, 292, 293, -9, -9, -9, -9/
+data (yychk(i),i=105,112) / -23, -43, -7, 292, 295, -42, -7, 295/
+data (yychk(i),i=113,120) / 295, -35, -37, -47, 285, 286, -7, -38/
+data (yychk(i),i=121,128) / -37, -40, -37, 293, -44, 285, 286, -45/
+data (yychk(i),i=129,136) / 294, -46, 282, 271, 272, 273, 274, 275/
+data (yychk(i),i=137,144) / 276, 277, 278, 279, 280, 281, 283, 284/
+data (yychk(i),i=145,152) / 282, 293, -23, 293, 293, -46, -24, -7/
+data (yychk(i),i=153,160) / 285, 286, 287, 288, 289, -44, -44, 294/
+data (yychk(i),i=161,168) / -44, 295, -26, -7, -27, -7, -31, -7/
+data (yychk(i),i=169,176) / -23, -44, -44, -44, -44, -44, -44, 295/
+data (yychk(i),i=177,184) / 293, -23, -23, -23, 295, -25, -7, 292/
+data (yychk(i),i=185,192) / -28, -7, -28, -23, -23, -29, 266, -7/
+data (yychk(i),i=193,200) / -29, -30, 267, -7, 293, -30, 293, -23/
+data (yychk(i),i=201,201) / -23/
+short yydef[201]
+data (yydef(i),i= 1, 8) / 103, -2, 103, 2, 103, 17, 103, 6/
+data (yydef(i),i= 9, 16) / 7, 16, 18, 0, 26, 27, 3, 5/
+data (yydef(i),i= 17, 24) / 8, 0, 0, 0, 13, 15, 19, 0/
+data (yydef(i),i= 25, 32) / 0, 0, 0, 30, 25, 4, 9, 10/
+data (yydef(i),i= 33, 40) / 24, 0, 0, 14, 20, 21, 0, 0/
+data (yydef(i),i= 41, 48) / 1, 28, 29, 31, 33, 34, 35, 36/
+data (yydef(i),i= 49, 56) / 37, 38, 39, 0, 0, 0, 56, 57/
+data (yydef(i),i= 57, 64) / 58, 0, 0, 0, 0, 0, 0, 0/
+data (yydef(i),i= 65, 72) / 0, 0, 0, 32, 103, 0, 0, 0/
+data (yydef(i),i= 73, 80) / 0, 0, 59, 60, 0, 63, 64, 0/
+data (yydef(i),i= 81, 88) / 67, 68, 0, 0, 0, 0, 0, 103/
+data (yydef(i),i= 89, 96) / 41, 0, 0, 103, 0, 0, 0, 103/
+data (yydef(i),i= 97,104) / 0, 103, 0, 103, 11, 12, 22, 23/
+data (yydef(i),i=105,112) / 0, 0, 74, 0, 0, 103, 72, 0/
+data (yydef(i),i=113,120) / 0, 61, 62, 0, 98, 99, 100, 65/
+data (yydef(i),i=121,128) / 66, 69, 70, 103, 73, 0, 0, 0/
+data (yydef(i),i=129,136) / 0, 84, 85, 86, 87, 88, 89, 90/
+data (yydef(i),i=137,144) / 91, 92, 93, 94, 95, 96, 101, 102/
+data (yydef(i),i=145,152) / 0, 103, 71, 103, 103, 97, 103, 42/
+data (yydef(i),i=153,160) / 0, 0, 0, 0, 0, 80, 81, 0/
+data (yydef(i),i=161,168) / 0, 0, 103, 46, 103, 48, 103, 50/
+data (yydef(i),i=169,176) / 40, 75, 76, 77, 78, 79, 0, 83/
+data (yydef(i),i=177,184) / 103, 0, 103, 103, 82, 103, 44, 103/
+data (yydef(i),i=185,192) / 103, 51, 103, 43, 45, 103, 0, 53/
+data (yydef(i),i=193,200) / 103, 47, 0, 55, 103, 49, 103, 52/
+data (yydef(i),i=201,201) / 54/
+
+begin
+ call smark (yysp)
+ call salloc (yyv, (YYMAXDEPTH+2) * YYOPLEN, TY_STRUCT)
+
+ # Initialization. The first element of the dynamically allocated
+ # token value stack (yyv) is used for yyval, the second for yylval,
+ # and the actual stack starts with the third element.
+
+ yystate = 0
+ yychar = -1
+ yynerrs = 0
+ yyerrflag = 0
+ yyps = 0
+ yyval = yyv
+ yylval = yyv + YYOPLEN
+ yypv = yylval
+
+yystack_
+ # SHIFT -- Put a state and value onto the stack. The token and
+ # value stacks are logically the same stack, implemented as two
+ # separate arrays.
+
+ if (yydebug) {
+ call printf ("state %d, char 0%o\n")
+ call pargs (yystate)
+ call pargi (yychar)
+ }
+ yyps = yyps + 1
+ yypv = yypv + YYOPLEN
+ if (yyps > YYMAXDEPTH) {
+ call sfree (yysp)
+ call eprintf ("yacc stack overflow\n")
+ return (ERR)
+ }
+ yys[yyps] = yystate
+ YYMOVE (yyval, yypv)
+
+yynewstate_
+ # Process the new state.
+ yyn = yypact[yystate+1]
+
+ if (yyn <= YYFLAG)
+ goto yydefault_ # simple state
+
+ # The variable "yychar" is the lookahead token.
+ if (yychar < 0) {
+ yychar = yylex (fd, yylval)
+ if (yychar < 0)
+ yychar = 0
+ }
+ yyn = yyn + yychar
+ if (yyn < 0 || yyn >= YYLAST)
+ goto yydefault_
+
+ yyn = yyact[yyn+1]
+ if (yychk[yyn+1] == yychar) { # valid shift
+ yychar = -1
+ YYMOVE (yylval, yyval)
+ yystate = yyn
+ if (yyerrflag > 0)
+ yyerrflag = yyerrflag - 1
+ goto yystack_
+ }
+
+yydefault_
+ # Default state action.
+
+ yyn = yydef[yystate+1]
+ if (yyn == -2) {
+ if (yychar < 0) {
+ yychar = yylex (fd, yylval)
+ if (yychar < 0)
+ yychar = 0
+ }
+
+ # Look through exception table.
+ yyxi = 1
+ while ((yyexca[yyxi] != (-1)) || (yyexca[yyxi+1] != yystate))
+ yyxi = yyxi + 2
+ for (yyxi=yyxi+2; yyexca[yyxi] >= 0; yyxi=yyxi+2) {
+ if (yyexca[yyxi] == yychar)
+ break
+ }
+
+ yyn = yyexca[yyxi+1]
+ if (yyn < 0) {
+ call sfree (yysp)
+ return (OK) # ACCEPT -- all done
+ }
+ }
+
+
+ # SYNTAX ERROR -- resume parsing if possible.
+
+ if (yyn == 0) {
+ switch (yyerrflag) {
+ case 0, 1, 2:
+ if (yyerrflag == 0) { # brand new error
+ call eprintf ("syntax error\n")
+yyerrlab_
+ yynerrs = yynerrs + 1
+ # fall through...
+ }
+
+ # case 1:
+ # case 2: incompletely recovered error ... try again
+ yyerrflag = 3
+
+ # Find a state where "error" is a legal shift action.
+ while (yyps >= 1) {
+ yyn = yypact[yys[yyps]+1] + YYERRCODE
+ if ((yyn >= 0) && (yyn < YYLAST) &&
+ (yychk[yyact[yyn+1]+1] == YYERRCODE)) {
+ # Simulate a shift of "error".
+ yystate = yyact[yyn+1]
+ goto yystack_
+ }
+ yyn = yypact[yys[yyps]+1]
+
+ # The current yyps has no shift on "error", pop stack.
+ if (yydebug) {
+ call printf ("error recovery pops state %d, ")
+ call pargs (yys[yyps])
+ call printf ("uncovers %d\n")
+ call pargs (yys[yyps-1])
+ }
+ yyps = yyps - 1
+ yypv = yypv - YYOPLEN
+ }
+
+ # ABORT -- There is no state on the stack with an error shift.
+yyabort_
+ call sfree (yysp)
+ return (ERR)
+
+
+ case 3: # No shift yet; clobber input char.
+
+ if (yydebug) {
+ call printf ("error recovery discards char %d\n")
+ call pargi (yychar)
+ }
+
+ if (yychar == 0)
+ goto yyabort_ # don't discard EOF, quit
+ yychar = -1
+ goto yynewstate_ # try again in the same state
+ }
+ }
+
+
+ # REDUCE -- Reduction by production yyn.
+
+ if (yydebug) {
+ call printf ("reduce %d\n")
+ call pargs (yyn)
+ }
+ yyps = yyps - yyr2[yyn+1]
+ yypvt = yypv
+ yypv = yypv - yyr2[yyn+1] * YYOPLEN
+ YYMOVE (yypv + YYOPLEN, yyval)
+ yym = yyn
+
+ # Consult goto table to find next state.
+ yyn = yyr1[yyn+1]
+ yyj = yypgo[yyn+1] + yys[yyps] + 1
+ if (yyj >= YYLAST)
+ yystate = yyact[yypgo[yyn+1]+1]
+ else {
+ yystate = yyact[yyj+1]
+ if (yychk[yystate+1] != -yyn)
+ yystate = yyact[yypgo[yyn+1]+1]
+ }
+
+ # Perform action associated with the grammar rule, if any.
+ switch (yym) {
+
+case 1:
+# line 41 "parser.y"
+{
+ return (OK)
+ }
+case 2:
+# line 44 "parser.y"
+{
+ return (ERR)
+ }
+case 5:
+# line 55 "parser.y"
+{
+ call pr_error ("The observation section is empty",
+ PERR_WARNING)
+ }
+case 6:
+# line 59 "parser.y"
+{
+ call pr_error ("The observation section is empty",
+ PERR_WARNING)
+ }
+case 7:
+# line 63 "parser.y"
+{
+ call pr_error ("The observation section is undefined",
+ PERR_WARNING)
+ }
+case 10:
+# line 71 "parser.y"
+{
+ call pr_obscol (LEX_ID (yypvt-YYOPLEN), LEX_ID (yypvt))
+ }
+case 11:
+# line 74 "parser.y"
+{
+ call pr_errcol (LEX_ID (yypvt-2*YYOPLEN), LEX_ID (yypvt))
+ }
+case 12:
+# line 77 "parser.y"
+{
+ call pr_wtscol (LEX_ID (yypvt-2*YYOPLEN), LEX_ID (yypvt))
+ }
+case 15:
+# line 88 "parser.y"
+{
+ call pr_error ("The catalog section is empty",
+ PERR_WARNING)
+ }
+case 16:
+# line 92 "parser.y"
+{
+ call pr_error ("The catalog section is empty",
+ PERR_WARNING)
+ }
+case 18:
+# line 99 "parser.y"
+{
+ call pr_puti (MINCOL, 2)
+ }
+case 21:
+# line 105 "parser.y"
+{
+ call pr_catcol (LEX_ID (yypvt-YYOPLEN), LEX_ID (yypvt))
+ }
+case 22:
+# line 108 "parser.y"
+{
+ call pr_errcol (LEX_ID (yypvt-2*YYOPLEN), LEX_ID (yypvt))
+ }
+case 23:
+# line 111 "parser.y"
+{
+ call pr_wtscol (LEX_ID (yypvt-2*YYOPLEN), LEX_ID (yypvt))
+ }
+case 24:
+# line 117 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 29:
+# line 134 "parser.y"
+{
+ call pr_error ("The transformation section is empty",
+ PERR_WARNING)
+ }
+case 30:
+# line 138 "parser.y"
+{
+ call pr_error ("The transformation section is empty",
+ PERR_WARNING)
+ }
+case 40:
+# line 154 "parser.y"
+{
+ call pr_treq (LEX_ID (yypvt-6*YYOPLEN),
+ LEX_ID (yypvt-3*YYOPLEN), LEX_ID (yypvt),
+ LEX_CODE (yypvt-3*YYOPLEN), LEX_CLEN (yypvt-3*YYOPLEN),
+ LEX_CODE (yypvt), LEX_CLEN (yypvt))
+ }
+case 41:
+# line 162 "parser.y"
+{
+ call pr_section (PRS_TRNREF)
+ }
+case 42:
+# line 167 "parser.y"
+{
+ call pr_section (PRS_TRNFIT)
+ }
+case 43:
+# line 175 "parser.y"
+{
+ call pr_trder (LEX_ID (yypvt-6*YYOPLEN), LEX_ID (yypvt-4*YYOPLEN),
+ LEX_ID (yypvt), LEX_CODE (yypvt), LEX_CLEN (yypvt))
+ }
+case 44:
+# line 181 "parser.y"
+{
+ call pr_section (PRS_TRNDER)
+ }
+case 45:
+# line 189 "parser.y"
+{
+ call pr_trplot (LEX_ID (yypvt-6*YYOPLEN),
+ LEX_ID (yypvt-2*YYOPLEN), LEX_ID (yypvt),
+ LEX_CODE (yypvt-2*YYOPLEN), LEX_CLEN (yypvt-2*YYOPLEN),
+ LEX_CODE (yypvt), LEX_CLEN (yypvt))
+ }
+case 46:
+# line 197 "parser.y"
+{
+ call pr_section (PRS_TRNPLOT)
+ }
+case 47:
+# line 207 "parser.y"
+{
+ call pr_erreq (LEX_ID (yypvt-7*YYOPLEN), LEX_ID (yypvt-3*YYOPLEN),
+ LEX_ID (yypvt-YYOPLEN), LEX_ID (yypvt),
+ LEX_CODE (yypvt-3*YYOPLEN), LEX_CLEN (yypvt-3*YYOPLEN),
+ LEX_CODE (yypvt-YYOPLEN), LEX_CLEN (yypvt-YYOPLEN),
+ LEX_CODE (yypvt), LEX_CLEN (yypvt))
+ }
+case 48:
+# line 216 "parser.y"
+{
+ call pr_section (PRS_ERREQ)
+ }
+case 49:
+# line 226 "parser.y"
+{
+ call pr_wtseq (LEX_ID (yypvt-7*YYOPLEN), LEX_ID (yypvt-3*YYOPLEN),
+ LEX_ID (yypvt-YYOPLEN), LEX_ID (yypvt),
+ LEX_CODE (yypvt-3*YYOPLEN), LEX_CLEN (yypvt-3*YYOPLEN),
+ LEX_CODE (yypvt-YYOPLEN), LEX_CLEN (yypvt-YYOPLEN),
+ LEX_CODE (yypvt), LEX_CLEN (yypvt))
+ }
+case 50:
+# line 235 "parser.y"
+{
+ call pr_section (PRS_WTSEQ)
+ }
+case 51:
+# line 243 "parser.y"
+{
+ call pr_section (PRS_LMTEQ)
+ }
+case 52:
+# line 248 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 53:
+# line 251 "parser.y"
+{
+ call strcpy ("", LEX_ID (yyval), LEN_ID)
+ LEX_CLEN (yyval) = 0
+ }
+case 54:
+# line 257 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 55:
+# line 260 "parser.y"
+{
+ call strcpy ("", LEX_ID (yyval), LEN_ID)
+ LEX_CLEN (yyval) = 0
+ }
+case 62:
+# line 279 "parser.y"
+{
+ call pr_fitpar (LEX_ID (yypvt-2*YYOPLEN), LEX_ID (yypvt))
+ }
+case 66:
+# line 288 "parser.y"
+{
+ call pr_const (LEX_ID (yypvt-2*YYOPLEN), LEX_ID (yypvt))
+ }
+case 70:
+# line 297 "parser.y"
+{
+ call pr_delta (LEX_ID (yypvt-2*YYOPLEN), LEX_ID (yypvt))
+ }
+case 71:
+# line 305 "parser.y"
+{
+ call pr_seteq (LEX_ID (yypvt-3*YYOPLEN), LEX_ID (yypvt),
+ LEX_CODE (yypvt), LEX_CLEN (yypvt))
+ }
+case 72:
+# line 311 "parser.y"
+{
+ call pr_section (PRS_SETEQ)
+ }
+case 73:
+# line 331 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ call pr_cend (yyval)
+ }
+case 74:
+# line 337 "parser.y"
+{
+ call pr_cinit ()
+ }
+case 75:
+# line 342 "parser.y"
+{
+ call pr_cat3 (LEX_ID (yypvt-2*YYOPLEN), LEX_ID (yypvt-YYOPLEN), LEX_ID (yypvt),
+ LEX_ID (yyval), LEN_ID)
+ call pr_cgen (PLUS, "", INDEFR)
+ }
+case 76:
+# line 347 "parser.y"
+{
+ call pr_cat3 (LEX_ID (yypvt-2*YYOPLEN), LEX_ID (yypvt-YYOPLEN), LEX_ID (yypvt),
+ LEX_ID (yyval), LEN_ID)
+ call pr_cgen (MINUS, "", INDEFR)
+ }
+case 77:
+# line 352 "parser.y"
+{
+ call pr_cat3 (LEX_ID (yypvt-2*YYOPLEN), LEX_ID (yypvt-YYOPLEN), LEX_ID (yypvt),
+ LEX_ID (yyval), LEN_ID)
+ call pr_cgen (STAR, "", INDEFR)
+ }
+case 78:
+# line 357 "parser.y"
+{
+ call pr_cat3 (LEX_ID (yypvt-2*YYOPLEN), LEX_ID (yypvt-YYOPLEN), LEX_ID (yypvt),
+ LEX_ID (yyval), LEN_ID)
+ call pr_cgen (SLASH, "", INDEFR)
+ }
+case 79:
+# line 362 "parser.y"
+{
+ call pr_cat3 (LEX_ID (yypvt-2*YYOPLEN), LEX_ID (yypvt-YYOPLEN), LEX_ID (yypvt),
+ LEX_ID (yyval), LEN_ID)
+ call pr_cgen (EXPON, "", INDEFR)
+ }
+case 80:
+# line 367 "parser.y"
+{
+ call pr_cat2 (LEX_ID (yypvt-YYOPLEN), LEX_ID (yypvt), LEX_ID (yyval), LEN_ID)
+ call pr_cgen (UPLUS, "", INDEFR)
+ }
+case 81:
+# line 371 "parser.y"
+{
+ call pr_cat2 (LEX_ID (yypvt-YYOPLEN), LEX_ID (yypvt), LEX_ID (yyval), LEN_ID)
+ call pr_cgen (UMINUS, "", INDEFR)
+ }
+case 82:
+# line 375 "parser.y"
+{
+ call pr_cat4 (LEX_ID (yypvt-3*YYOPLEN), LEX_ID (yypvt-2*YYOPLEN), LEX_ID (yypvt-YYOPLEN),
+ LEX_ID (yypvt), LEX_ID (yyval), LEN_ID)
+ call pr_cgen (LEX_TOK (yypvt-3*YYOPLEN), "", INDEFR)
+ }
+case 83:
+# line 380 "parser.y"
+{
+ call pr_cat3 (LEX_ID (yypvt-2*YYOPLEN), LEX_ID (yypvt-YYOPLEN), LEX_ID (yypvt),
+ LEX_ID (yyval), LEN_ID)
+ }
+case 84:
+# line 384 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ call pr_cgen (RNUMBER, "", LEX_VAL (yypvt))
+ }
+case 85:
+# line 388 "parser.y"
+{
+ call pr_chkid (LEX_ID (yypvt))
+ YYMOVE (yypvt, yyval)
+ call pr_cgen (IDENTIFIER, LEX_ID (yypvt), INDEFR)
+ }
+case 86:
+# line 395 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 87:
+# line 398 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 88:
+# line 401 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 89:
+# line 404 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 90:
+# line 407 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 91:
+# line 410 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 92:
+# line 413 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 93:
+# line 416 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 94:
+# line 419 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 95:
+# line 422 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 96:
+# line 425 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 97:
+# line 431 "parser.y"
+{
+ call pr_cat2 (LEX_ID (yypvt-YYOPLEN), LEX_ID (yypvt),
+ LEX_ID (yyval), LEN_ID)
+ LEX_VAL (yyval) = LEX_VAL (yypvt)
+ }
+case 98:
+# line 438 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 99:
+# line 441 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 100:
+# line 444 "parser.y"
+{
+ call strcpy ("", LEX_ID (yyval), LEN_ID)
+ }
+case 101:
+# line 449 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 102:
+# line 452 "parser.y"
+{
+ YYMOVE (yypvt, yyval)
+ } }
+
+ goto yystack_ # stack new state and value
+end
diff --git a/noao/digiphot/photcal/parser/parser.y b/noao/digiphot/photcal/parser/parser.y
new file mode 100644
index 00000000..aaee60e0
--- /dev/null
+++ b/noao/digiphot/photcal/parser/parser.y
@@ -0,0 +1,461 @@
+%{
+
+include <ctype.h>
+include <lexnum.h>
+include "../lib/lexer.h"
+include "../lib/parser.h"
+include "../lib/prdefs.h"
+
+# Parser stack and structure lengths
+define YYMAXDEPTH 128
+define YYOPLEN LEN_LEX
+
+# Redefine the name of the parser
+define yyparse parse
+
+%}
+
+
+%token OBSSECT CATSECT EXTSECT TRNSECT
+%token FITID CONSTID DELTAID
+%token ERRORID WEIGHTID MINID MAXID
+%token DERIVID PLOTID SETID
+%token F_ABS F_ACOS F_ASIN F_ATAN F_COS F_EXP
+%token F_LOG F_LOG10 F_SIN F_SQRT F_TAN
+%token IDENTIFIER INUMBER RNUMBER
+%token PLUS MINUS STAR SLASH EXPON
+%token COLON SEMICOLON COMMA EQUAL LPAR RPAR
+%token EOFILE
+
+%left PLUS MINUS
+%left STAR SLASH
+%left EXPON
+%right UPLUS UMINUS
+
+
+%%
+
+
+# Configuration file.
+
+config : catalog observation extinction transform EOFILE {
+ return (OK)
+ }
+ | error {
+ return (ERR)
+ }
+ ;
+
+
+# Observation variable section. Set equations are not allowed here to avoid
+# a precedence problem in the parser.
+
+observation : OBSSECT obscols
+ | OBSSECT obscols SEMICOLON
+ | OBSSECT SEMICOLON {
+ call pr_error ("The observation section is empty",
+ PERR_WARNING)
+ }
+ | OBSSECT {
+ call pr_error ("The observation section is empty",
+ PERR_WARNING)
+ }
+ | empty {
+ call pr_error ("The observation section is undefined",
+ PERR_WARNING)
+ }
+ ;
+
+obscols : obscol | obscol obscols
+
+obscol : IDENTIFIER column {
+ call pr_obscol (LEX_ID ($1), LEX_ID ($2))
+ }
+ | ERRORID LPAR IDENTIFIER RPAR column {
+ call pr_errcol (LEX_ID ($3), LEX_ID ($5))
+ }
+ | WEIGHTID LPAR IDENTIFIER RPAR column {
+ call pr_wtscol (LEX_ID ($3), LEX_ID ($5))
+ }
+ ;
+
+
+# Catalog variable section. Set equations are not allowed here to avoid
+# a precedence problem in the parser.
+
+catalog : CATSECT catminset catcols
+ | CATSECT catminset catcols SEMICOLON
+ | CATSECT catminset SEMICOLON {
+ call pr_error ("The catalog section is empty",
+ PERR_WARNING)
+ }
+ | CATSECT catminset {
+ call pr_error ("The catalog section is empty",
+ PERR_WARNING)
+ }
+ |empty
+ ;
+
+catminset : empty {
+ call pr_puti (MINCOL, 2)
+ }
+
+catcols : catcol | catcol catcols ;
+
+catcol : IDENTIFIER column {
+ call pr_catcol (LEX_ID ($1), LEX_ID ($2))
+ }
+ | ERRORID LPAR IDENTIFIER RPAR column {
+ call pr_errcol (LEX_ID ($3), LEX_ID ($5))
+ }
+ | WEIGHTID LPAR IDENTIFIER RPAR column {
+ call pr_wtscol (LEX_ID ($3), LEX_ID ($5))
+ }
+ ;
+
+
+column : INUMBER {
+ YYMOVE ($1, $$)
+ }
+ ;
+
+
+# Extinction correction section (NOT YET IMPLEMENTED).
+
+extinction : EXTSECT SEMICOLON
+ | EXTSECT
+ | empty
+ ;
+
+
+# Transformation section.
+
+transform : TRNSECT trneqlist
+ | TRNSECT SEMICOLON {
+ call pr_error ("The transformation section is empty",
+ PERR_WARNING)
+ }
+ | TRNSECT {
+ call pr_error ("The transformation section is empty",
+ PERR_WARNING)
+ }
+ ;
+
+trneqlist : trneq | trneq trneqlist ;
+
+trneq : trntrans | trnderiv | trnplot
+ |fitconstdelta
+ | seteq | erroreq | weighteq
+ ;
+
+
+# Transformation equation
+
+trntrans : IDENTIFIER COLON trnrefset stmt EQUAL trnfitset stmt {
+ call pr_treq (LEX_ID ($1),
+ LEX_ID ($4), LEX_ID ($7),
+ LEX_CODE ($4), LEX_CLEN ($4),
+ LEX_CODE ($7), LEX_CLEN ($7))
+ }
+ ;
+
+trnrefset : empty {
+ call pr_section (PRS_TRNREF)
+ }
+ ;
+
+trnfitset : empty {
+ call pr_section (PRS_TRNFIT)
+ }
+ ;
+
+# Transformation derivative equation.
+
+trnderiv : DERIVID LPAR IDENTIFIER COMMA IDENTIFIER RPAR EQUAL
+ trnderset stmt {
+ call pr_trder (LEX_ID ($3), LEX_ID ($5),
+ LEX_ID ($9), LEX_CODE ($9), LEX_CLEN ($9))
+ }
+ ;
+
+trnderset : empty {
+ call pr_section (PRS_TRNDER)
+ }
+ ;
+
+# Transformation plot equation.
+
+trnplot : PLOTID LPAR IDENTIFIER RPAR EQUAL
+ trnplotset stmt COMMA stmt {
+ call pr_trplot (LEX_ID ($3),
+ LEX_ID ($7), LEX_ID ($9),
+ LEX_CODE ($7), LEX_CLEN ($7),
+ LEX_CODE ($9), LEX_CLEN ($9))
+ }
+ ;
+
+trnplotset : empty {
+ call pr_section (PRS_TRNPLOT)
+ }
+ ;
+
+
+# Error equation. This equation is optionally followed by two
+# expressions for the minimum and maximum values allowed.
+
+erroreq : ERRORID LPAR IDENTIFIER RPAR EQUAL erroreqset stmt
+ limitset limitmin limitmax {
+ call pr_erreq (LEX_ID ($3), LEX_ID ($7),
+ LEX_ID ($9), LEX_ID ($10),
+ LEX_CODE ($7), LEX_CLEN ($7),
+ LEX_CODE ($9), LEX_CLEN ($9),
+ LEX_CODE ($10), LEX_CLEN ($10))
+ }
+ ;
+
+erroreqset : empty {
+ call pr_section (PRS_ERREQ)
+ }
+ ;
+
+
+# Weight equation. This equation is optionally followed by two
+# expressions for the minimum and maximum values allowed.
+
+weighteq : WEIGHTID LPAR IDENTIFIER RPAR EQUAL weighteqset stmt
+ limitset limitmin limitmax {
+ call pr_wtseq (LEX_ID ($3), LEX_ID ($7),
+ LEX_ID ($9), LEX_ID ($10),
+ LEX_CODE ($7), LEX_CLEN ($7),
+ LEX_CODE ($9), LEX_CLEN ($9),
+ LEX_CODE ($10), LEX_CLEN ($10))
+ }
+ ;
+
+weighteqset : empty {
+ call pr_section (PRS_WTSEQ)
+ }
+ ;
+
+
+# Limit equations for errors and weights.
+
+limitset : empty {
+ call pr_section (PRS_LMTEQ)
+ }
+ ;
+
+limitmin : MINID EQUAL stmt {
+ YYMOVE ($3, $$)
+ }
+ | empty {
+ call strcpy ("", LEX_ID ($$), LEN_ID)
+ LEX_CLEN ($$) = 0
+ }
+ ;
+
+limitmax : MAXID EQUAL stmt {
+ YYMOVE ($3, $$)
+ }
+ | empty {
+ call strcpy ("", LEX_ID ($$), LEN_ID)
+ LEX_CLEN ($$) = 0
+ }
+ ;
+
+
+
+# Fitting parameter, constant parameter, and parameter deltas definition.
+# Although deltas are always positive, the parser allows for negative
+# values to avoid a syntax error that would stop the parsing. Check for
+# this is left to the symbol table handler procedures.
+
+fitconstdelta : fit | const | delta ;
+
+fit : FITID fitinitlist ;
+
+fitinitlist : fitinit | fitinit COMMA fitinitlist ;
+
+fitinit : IDENTIFIER EQUAL signedconst {
+ call pr_fitpar (LEX_ID ($1), LEX_ID ($3))
+ }
+ ;
+
+const : CONSTID constinitlist ;
+
+constinitlist : constinit | constinit COMMA constinitlist ;
+
+constinit : IDENTIFIER EQUAL signedconst {
+ call pr_const (LEX_ID ($1), LEX_ID ($3))
+ }
+ ;
+
+delta : DELTAID deltainitlist ;
+
+deltainitlist : deltainit | deltainit COMMA deltainitlist ;
+
+deltainit : IDENTIFIER EQUAL signedconst {
+ call pr_delta (LEX_ID ($1), LEX_ID ($3))
+ }
+ ;
+
+
+# Set equations.
+
+seteq : SETID IDENTIFIER EQUAL seteqset stmt {
+ call pr_seteq (LEX_ID ($2), LEX_ID ($5),
+ LEX_CODE ($5), LEX_CLEN ($5))
+ }
+ ;
+
+seteqset : empty {
+ call pr_section (PRS_SETEQ)
+ }
+ ;
+
+
+
+# Statement list (not used for the moment, but it probably will)
+#
+#stmtlist : stmt {
+# YYMOVE ($1, $$)
+# }
+# | stmt COMMA stmtlist {
+# call pr_cat3 (LEX_ID ($1), LEX_ID ($2), LEX_ID ($3),
+# LEX_ID ($$), LEN_ID)
+# }
+# ;
+
+# Statement (expression).
+
+stmt : exprinit expr {
+ YYMOVE ($2, $$)
+ call pr_cend ($$)
+ }
+ ;
+
+exprinit : empty {
+ call pr_cinit ()
+ }
+ ;
+
+expr : expr PLUS expr {
+ call pr_cat3 (LEX_ID ($1), LEX_ID ($2), LEX_ID ($3),
+ LEX_ID ($$), LEN_ID)
+ call pr_cgen (PLUS, "", INDEFR)
+ }
+ | expr MINUS expr {
+ call pr_cat3 (LEX_ID ($1), LEX_ID ($2), LEX_ID ($3),
+ LEX_ID ($$), LEN_ID)
+ call pr_cgen (MINUS, "", INDEFR)
+ }
+ | expr STAR expr {
+ call pr_cat3 (LEX_ID ($1), LEX_ID ($2), LEX_ID ($3),
+ LEX_ID ($$), LEN_ID)
+ call pr_cgen (STAR, "", INDEFR)
+ }
+ | expr SLASH expr {
+ call pr_cat3 (LEX_ID ($1), LEX_ID ($2), LEX_ID ($3),
+ LEX_ID ($$), LEN_ID)
+ call pr_cgen (SLASH, "", INDEFR)
+ }
+ | expr EXPON expr {
+ call pr_cat3 (LEX_ID ($1), LEX_ID ($2), LEX_ID ($3),
+ LEX_ID ($$), LEN_ID)
+ call pr_cgen (EXPON, "", INDEFR)
+ }
+ | PLUS expr %prec UMINUS {
+ call pr_cat2 (LEX_ID ($1), LEX_ID ($2), LEX_ID ($$), LEN_ID)
+ call pr_cgen (UPLUS, "", INDEFR)
+ }
+ | MINUS expr %prec UMINUS {
+ call pr_cat2 (LEX_ID ($1), LEX_ID ($2), LEX_ID ($$), LEN_ID)
+ call pr_cgen (UMINUS, "", INDEFR)
+ }
+ | funct LPAR expr RPAR {
+ call pr_cat4 (LEX_ID ($1), LEX_ID ($2), LEX_ID ($3),
+ LEX_ID ($4), LEX_ID ($$), LEN_ID)
+ call pr_cgen (LEX_TOK ($1), "", INDEFR)
+ }
+ | LPAR expr RPAR {
+ call pr_cat3 (LEX_ID ($1), LEX_ID ($2), LEX_ID ($3),
+ LEX_ID ($$), LEN_ID)
+ }
+ | constant {
+ YYMOVE ($1, $$)
+ call pr_cgen (RNUMBER, "", LEX_VAL ($1))
+ }
+ | IDENTIFIER {
+ call pr_chkid (LEX_ID ($1))
+ YYMOVE ($1, $$)
+ call pr_cgen (IDENTIFIER, LEX_ID ($1), INDEFR)
+ }
+ ;
+
+funct : F_ABS {
+ YYMOVE ($1, $$)
+ }
+ | F_ACOS {
+ YYMOVE ($1, $$)
+ }
+ | F_ASIN {
+ YYMOVE ($1, $$)
+ }
+ | F_ATAN {
+ YYMOVE ($1, $$)
+ }
+ | F_COS {
+ YYMOVE ($1, $$)
+ }
+ | F_EXP {
+ YYMOVE ($1, $$)
+ }
+ | F_LOG {
+ YYMOVE ($1, $$)
+ }
+ | F_LOG10 {
+ YYMOVE ($1, $$)
+ }
+ | F_SIN {
+ YYMOVE ($1, $$)
+ }
+ | F_SQRT {
+ YYMOVE ($1, $$)
+ }
+ | F_TAN {
+ YYMOVE ($1, $$)
+ }
+ ;
+
+
+signedconst : sign constant {
+ call pr_cat2 (LEX_ID ($1), LEX_ID ($2),
+ LEX_ID ($$), LEN_ID)
+ LEX_VAL ($$) = LEX_VAL ($2)
+ }
+ ;
+
+sign : PLUS %prec UMINUS {
+ YYMOVE ($1, $$)
+ }
+ | MINUS %prec UMINUS {
+ YYMOVE ($1, $$)
+ }
+ | empty {
+ call strcpy ("", LEX_ID ($$), LEN_ID)
+ }
+ ;
+
+constant : INUMBER {
+ YYMOVE ($1, $$)
+ }
+ | RNUMBER {
+ YYMOVE ($1, $$)
+ }
+ ;
+
+
+empty : ;
+
+
+%%
diff --git a/noao/digiphot/photcal/parser/pralloc.x b/noao/digiphot/photcal/parser/pralloc.x
new file mode 100644
index 00000000..2147298e
--- /dev/null
+++ b/noao/digiphot/photcal/parser/pralloc.x
@@ -0,0 +1,304 @@
+.help pralloc
+Parser Memory Allocation.
+
+Entry points:
+
+ pr_alloc () Allocate parser tables.
+
+ pr_inalloc (ptr) Allocate input variable substructure.
+ pr_ftalloc (ptr) Allocate fitting parameter substructure.
+ pr_stalloc (ptr) Allocate set equation substructure.
+ pr_tralloc (ptr, npars) Allocate transf. equation substructure.
+
+ pr_free () Free parser tables.
+.endhelp
+
+include "../lib/parser.h"
+include "../lib/prstruct.h"
+
+# Number of expected symbols in the symbol table. The table is reallocated
+# automatically by the SYMTAB procedures if this value is not enough.
+
+define LEN_SYMTABLE 100
+
+
+# PR_ALLOC -- Allocate space for symbol table and sequential tables
+
+procedure pr_alloc ()
+
+pointer stopen()
+
+include "parser.com"
+
+begin
+ # Open symbol table
+ symtable = stopen ("parser", 2 * LEN_SYMTABLE, LEN_SYMTABLE,
+ LEN_SYMTABLE * SZ_LINE)
+
+ # Allocate space for other tables
+ call mct_alloc (obstable, 10, 1, TY_INT)
+ call mct_alloc (cattable, 10, 1, TY_INT)
+ call mct_alloc (partable, 30, 1, TY_INT)
+ call mct_alloc (exttable, 10, 1, TY_INT)
+ call mct_alloc (trntable, 10, 1, TY_INT)
+ call mct_alloc (settable, 10, 1, TY_INT)
+ call mct_alloc (trcattable, 20, 2, TY_INT)
+ call mct_alloc (trobstable, 20, 2, TY_INT)
+ call mct_alloc (tfcattable, 20, 2, TY_INT)
+ call mct_alloc (tfobstable, 20, 2, TY_INT)
+ call mct_alloc (tpartable, 20, 1, TY_INT)
+end
+
+
+# PR_INALLOC -- Allocate space for input variable substructure.
+
+procedure pr_inalloc (ptr)
+
+pointer ptr # substructure pointer (output)
+
+begin
+ # Allocate space
+ call malloc (ptr, LEN_PINP, TY_STRUCT)
+
+ # Initialize substructure
+ PINP_COL (ptr) = INDEFI
+ PINP_ERRCOL (ptr) = INDEFI
+ PINP_WTSCOL (ptr) = INDEFI
+ PINP_SPARE (ptr) = NO
+end
+
+
+# PR_FTALLOC -- Allocate space for fitting parameter substructure.
+
+procedure pr_ftalloc (ptr)
+
+pointer ptr # substructure pointer (output)
+
+begin
+ # Allocate space
+ call malloc (ptr, LEN_PFIT, TY_STRUCT)
+
+ # Initialize substructure
+ PFIT_VALUE (ptr) = INDEFR
+ PFIT_DELTA (ptr) = INDEFR
+end
+
+
+# PR_STALLOC -- Allocate and initialize a set equation substructure.
+# Initialization may not be necessary for all fields in the substructure,
+# but it's safer to do it anyway.
+
+procedure pr_stalloc (ptr)
+
+pointer ptr # substructure pointer (output)
+
+begin
+ # Allocate space
+ call malloc (ptr, LEN_PSEQ, TY_STRUCT)
+
+ # Initialize string offsets
+ PSEQ_EQ (ptr) = INDEFI
+ PSEQ_ERROR (ptr) = INDEFI
+ PSEQ_ERRMIN (ptr) = INDEFI
+ PSEQ_ERRMAX (ptr) = INDEFI
+ PSEQ_WEIGHT (ptr) = INDEFI
+ PSEQ_WTSMIN (ptr) = INDEFI
+ PSEQ_WTSMAX (ptr) = INDEFI
+
+ # Initialize code pointers
+ PSEQ_RPNEQ (ptr) = NULL
+ PSEQ_RPNERROR (ptr) = NULL
+ PSEQ_RPNERRMIN (ptr) = NULL
+ PSEQ_RPNERRMAX (ptr) = NULL
+ PSEQ_RPNWEIGHT (ptr) = NULL
+ PSEQ_RPNWTSMIN (ptr) = NULL
+ PSEQ_RPNWTSMAX (ptr) = NULL
+end
+
+
+# PR_TRALLOC -- Allocate space and initialize a transformation equation
+# substructure. Initialization may not be necessary for all fields in the
+# substructure, but it's safer to do it anyway.
+
+procedure pr_tralloc (ptr, nrcat, nrobs, nfcat, nfobs, npars)
+
+pointer ptr # substructure pointer (output)
+int nrcat # number of catalog variables in reference eq.
+int nrobs # number of observation variables in reference eq.
+int nfcat # number of catalog variables in fit eq.
+int nfobs # number of observation variables in fit eq.
+int npars # number of parameters
+
+int nvars, nrvars, nfvars
+
+begin
+ # Total number of variables
+ nrvars = nrcat + nrobs
+ nfvars = nfcat + nfobs
+ nvars = nrvars + nfvars
+
+ # Allocate space
+ call malloc (ptr, LEN_PTEQ (nvars, npars), TY_STRUCT)
+
+ # Initialize counters
+ PTEQ_NRCAT (ptr) = nrcat
+ PTEQ_NROBS (ptr) = nrobs
+ PTEQ_NRVAR (ptr) = nrvars
+ PTEQ_NFCAT (ptr) = nfcat
+ PTEQ_NFOBS (ptr) = nfobs
+ PTEQ_NFVAR (ptr) = nfvars
+ PTEQ_NVAR (ptr) = nvars
+ PTEQ_NPAR (ptr) = npars
+ PTEQ_NFPAR (ptr) = INDEFI
+
+ # Initialize variable offsets and counters
+ call amovki (INDEFI, PTEQ_AREFVAR (ptr), nrvars)
+ call amovki (INDEFI, PTEQ_AFITVAR (ptr), nfvars)
+ call aclri (PTEQ_AREFCNT (ptr), nrvars)
+ call aclri (PTEQ_AFITCNT (ptr), nfvars)
+
+ # Initialize parameter offsets, values, and list
+ call amovki (INDEFI, PTEQ_APAR (ptr), npars)
+ call amovkr (INDEFR, PTEQ_APARVAL (ptr), npars)
+ call aclri (PTEQ_APLIST (ptr), npars)
+
+ # Initialize string offsets
+ PTEQ_FIT (ptr) = INDEFI
+ PTEQ_REF (ptr) = INDEFI
+ PTEQ_ERROR (ptr) = INDEFI
+ PTEQ_ERRMIN (ptr) = INDEFI
+ PTEQ_ERRMAX (ptr) = INDEFI
+ PTEQ_WEIGHT (ptr) = INDEFI
+ PTEQ_WTSMIN (ptr) = INDEFI
+ PTEQ_WTSMAX (ptr) = INDEFI
+ PTEQ_XPLOT (ptr) = INDEFI
+ PTEQ_YPLOT (ptr) = INDEFI
+ call amovki (INDEFI, PTEQ_ADER (ptr), npars)
+
+ # Initialize code pointers
+ PTEQ_RPNFIT (ptr) = NULL
+ PTEQ_RPNREF (ptr) = NULL
+ PTEQ_RPNERROR (ptr) = NULL
+ PTEQ_RPNERRMIN (ptr) = NULL
+ PTEQ_RPNERRMAX (ptr) = NULL
+ PTEQ_RPNWEIGHT (ptr) = NULL
+ PTEQ_RPNWTSMIN (ptr) = NULL
+ PTEQ_RPNWTSMAX (ptr) = NULL
+ PTEQ_RPNXPLOT (ptr) = NULL
+ PTEQ_RPNYPLOT (ptr) = NULL
+ call amovki (NULL, PTEQ_ARPNDER (ptr), npars)
+end
+
+
+# PR_FREE - Free parser symbol table and sequential tables.
+
+procedure pr_free ()
+
+int n
+pointer sym, ptr
+
+include "parser.com"
+
+pointer sthead(), stnext()
+
+begin
+ # Traverse the symbol table looking for symbol
+ # substructures before closing it.
+ sym = sthead (symtable)
+ while (sym != NULL) {
+
+ # Get pointer to the equation substructure,
+ # and free it only if not NULL
+ ptr = PSYM_SUB (sym)
+ if (ptr != NULL) {
+
+ # Free additonal buffers associated with the substructure
+ switch (PSYM_TYPE (sym)) {
+ case PTY_CATVAR, PTY_OBSVAR:
+ # do nothing
+
+ case PTY_FITPAR, PTY_CONST:
+ # do nothing
+
+ case PTY_TRNEQ:
+
+ # Free transformation equation codes
+ if (PTEQ_RPNFIT (ptr) != NULL)
+ call mfree (PTEQ_RPNFIT (ptr), TY_STRUCT)
+ if (PTEQ_RPNREF (ptr) != NULL)
+ call mfree (PTEQ_RPNREF (ptr), TY_STRUCT)
+
+ # Free error equation codes
+ if (PTEQ_RPNERROR (ptr) != NULL)
+ call mfree (PTEQ_RPNERROR (ptr), TY_STRUCT)
+ if (PTEQ_RPNERRMIN (ptr) != NULL)
+ call mfree (PTEQ_RPNERRMIN (ptr), TY_STRUCT)
+ if (PTEQ_RPNERRMAX (ptr) != NULL)
+ call mfree (PTEQ_RPNERRMAX (ptr), TY_STRUCT)
+
+ # Free weight equation codes
+ if (PTEQ_RPNWEIGHT (ptr) != NULL)
+ call mfree (PTEQ_RPNWEIGHT (ptr), TY_STRUCT)
+ if (PTEQ_RPNWTSMIN (ptr) != NULL)
+ call mfree (PTEQ_RPNWTSMIN (ptr), TY_STRUCT)
+ if (PTEQ_RPNWTSMAX (ptr) != NULL)
+ call mfree (PTEQ_RPNWTSMAX (ptr), TY_STRUCT)
+
+ # Free plot equation codes
+ if (PTEQ_RPNXPLOT (ptr) != NULL)
+ call mfree (PTEQ_RPNXPLOT (ptr), TY_STRUCT)
+ if (PTEQ_RPNYPLOT (ptr) != NULL)
+ call mfree (PTEQ_RPNYPLOT (ptr), TY_STRUCT)
+ do n = 1, PTEQ_NPAR (ptr)
+ call mfree (PTEQ_RPNDER (ptr, n), TY_STRUCT)
+
+ case PTY_SETEQ:
+
+ # Free set equation code
+ if (PSEQ_RPNEQ (ptr) != NULL)
+ call mfree (PSEQ_RPNEQ (ptr), TY_STRUCT)
+
+ # Free error equation codes
+ if (PSEQ_RPNERROR (ptr) != NULL)
+ call mfree (PSEQ_RPNERROR (ptr), TY_STRUCT)
+ if (PSEQ_RPNERRMIN (ptr) != NULL)
+ call mfree (PSEQ_RPNERRMIN (ptr), TY_STRUCT)
+ if (PSEQ_RPNERRMAX (ptr) != NULL)
+ call mfree (PSEQ_RPNERRMAX (ptr), TY_STRUCT)
+
+ # Free weight equation codes
+ if (PSEQ_RPNWEIGHT (ptr) != NULL)
+ call mfree (PSEQ_RPNWEIGHT (ptr), TY_STRUCT)
+ if (PSEQ_RPNWTSMIN (ptr) != NULL)
+ call mfree (PSEQ_RPNWTSMIN (ptr), TY_STRUCT)
+ if (PSEQ_RPNWTSMAX (ptr) != NULL)
+ call mfree (PSEQ_RPNWTSMAX (ptr), TY_STRUCT)
+
+ default:
+ call error (0, "pr_free: unknown equation symbol type")
+ }
+
+ # Free equation substructure
+ call mfree (ptr, TY_STRUCT)
+ }
+
+ # Advance to next symbol
+ sym = stnext (symtable, sym)
+ }
+
+ # Close symbol table
+ call stclose (symtable)
+
+ # Close other tables
+ call mct_free (obstable)
+ call mct_free (cattable)
+ call mct_free (partable)
+ call mct_free (exttable)
+ call mct_free (trntable)
+ call mct_free (settable)
+ call mct_free (trcattable)
+ call mct_free (trobstable)
+ call mct_free (tfcattable)
+ call mct_free (tfobstable)
+ call mct_free (tpartable)
+end
diff --git a/noao/digiphot/photcal/parser/prcat.x b/noao/digiphot/photcal/parser/prcat.x
new file mode 100644
index 00000000..d8317f73
--- /dev/null
+++ b/noao/digiphot/photcal/parser/prcat.x
@@ -0,0 +1,43 @@
+# PR_CAT2 - Concatenate two strings
+
+procedure pr_cat2 (str1, str2, outstr, maxch)
+
+char str1[ARB], str2[ARB] # input strings
+char outstr[ARB] # output string
+int maxch # max output chars
+
+begin
+ call strcpy (str1, outstr, maxch)
+ call strcat (str2, outstr, maxch)
+end
+
+
+# PR_CAT3 - Concatenate three strings
+
+procedure pr_cat3 (str1, str2, str3, outstr, maxch)
+
+char str1[ARB], str2[ARB], str3[ARB] # input strings
+char outstr[ARB] # output string
+int maxch # max output chars
+
+begin
+ call strcpy (str1, outstr, maxch)
+ call strcat (str2, outstr, maxch)
+ call strcat (str3, outstr, maxch)
+end
+
+
+# PR_CAT4 - Concatenate four strings
+
+procedure pr_cat4 (str1, str2, str3, str4, outstr, maxch)
+
+char str1[ARB], str2[ARB], str3[ARB], str4[ARB] # input strings
+char outstr[ARB] # output string
+int maxch # max output chars
+
+begin
+ call strcpy (str1, outstr, maxch)
+ call strcat (str2, outstr, maxch)
+ call strcat (str3, outstr, maxch)
+ call strcat (str4, outstr, maxch)
+end
diff --git a/noao/digiphot/photcal/parser/prcode.com b/noao/digiphot/photcal/parser/prcode.com
new file mode 100644
index 00000000..5b928b02
--- /dev/null
+++ b/noao/digiphot/photcal/parser/prcode.com
@@ -0,0 +1,8 @@
+# Evaluator common. This common handles the code counter and the code
+# buffer used by the code generator routines during an expression
+# code generation.
+
+int cp # next free instruction
+pointer code # RPN code buffer
+
+common /prcodecom/ cp, code
diff --git a/noao/digiphot/photcal/parser/prcode.x b/noao/digiphot/photcal/parser/prcode.x
new file mode 100644
index 00000000..dfdb95fb
--- /dev/null
+++ b/noao/digiphot/photcal/parser/prcode.x
@@ -0,0 +1,273 @@
+.help prcode
+Parser code generator
+
+The parser generates code for all the equations in the symbol table in
+Reverse Polish Notation (RPN). Under this notation, operands are pushed
+into a stack, until an operation comes up. The operation takes as many stack
+places (from the stack top) it needs as arguments, and places the result
+in the top of the stack. The final result will be always in the top of
+the stack.
+.sp
+In the current implemantation, arguments can be either constants, catalog
+variables, observational variables, parameters, and equations (extinction
+and transformation). The latter argument is a recursive call to other equation.
+Operations can take only one or two stack places as arguments.
+.sp
+The instructions generated by the parser can be of one or two words.
+The first word is always an integer, and identifies the operation to be
+performed. If the operation is a "push" of a quantity into the stack,
+the second word must contain the value (real) or index (integer) of
+the quantity. The real value is used for constants, and index is used
+for variables and parameters.
+.sp
+The RPN instructions are stored into memory as a dinamically allocated
+buffer of structure type (TY_STRUCT), since it may contain integer and
+real numbers.
+.sp
+The procedures provided here are called by the parser, to generate code
+for each expression (formula) found. The following entry points are
+defined:
+
+.nf
+ pr_calloc () Allocate space for temp. code buffer
+ pr_cfree () Deallocate code buffer
+ pr_cinit () Begin code generation
+ pr_cend (ptr) End code generation
+ pr_cgen (token, id, value) Generate code for parser token
+pointer pr_cput (code, len) Create and copy code buffer
+.endhelp
+
+include "../lib/lexer.h"
+include "../lib/parser.h"
+include "../lib/prtoken.h"
+include "../lib/preval.h"
+
+
+# PR_CALLOC - Allocate code buffer
+
+procedure pr_calloc ()
+
+include "prcode.com"
+
+begin
+ # Allocate code buffer
+ call malloc (code, LEN_CODE, TY_STRUCT)
+end
+
+
+# PR_CFREE - Free code buffer
+
+procedure pr_cfree ()
+
+include "prcode.com"
+
+begin
+ # Free buffer in common
+ call mfree (code, TY_STRUCT)
+end
+
+
+# PR_CINIT - Start code generation
+
+procedure pr_cinit ()
+
+include "prcode.com"
+
+begin
+ # Set next free instruction be the first
+ cp = 1
+end
+
+
+# PR_CEND - Finish code generation
+
+procedure pr_cend (ptr)
+
+pointer ptr # lexer symbol pointer
+
+include "prcode.com"
+
+begin
+ # Put the end-of-code marker in
+ # the next instruction
+ Memi[code + cp - 1] = PEV_EOC
+
+ # Set code length
+ LEX_CLEN (ptr) = cp
+
+ # Copy the code buffer into the lexer symbol
+ call amovi (Memi[code], Memi[LEX_CODE (ptr)], cp)
+
+ # Reset code counter to the first
+ # instruction
+ cp = 1
+end
+
+
+# PR_CGEN - Generate RPN code.
+
+procedure pr_cgen (token, id, value)
+
+int token # lexer token
+char id[ARB] # lexer identifier
+real value # lexer value
+
+char aux[SZ_LINE]
+int offset, sym, type
+
+include "prcode.com"
+
+int pr_geti(), pr_gsymi()
+pointer pr_getsym()
+
+begin
+ # Generate code for the current instruction according
+ # with token value returned by the lexer
+ switch (token) {
+
+ case IDENTIFIER:
+
+ # Find the identifier in the symbol table, and store
+ # the appropiate instruction code, and number, according
+ # with the symbol type. If the identifier is not found in
+ # the symbol table no code is generated, and no error
+ # action is taken. The latter is to avoid stopping the
+ # parser and allow some error recovery.
+ # Also compute an offset to add later to the symbol number.
+ # In catalog variables an offset is necessary because the
+ # expression evaluator has only ONE table with variable
+ # values, with catalog variables at the end.
+ sym = pr_getsym (id)
+ if (!IS_INDEFI (sym)) {
+
+ # Get symbol type and take action acordingly
+ type = pr_gsymi (sym, PSYMTYPE)
+ switch (type) {
+ case PTY_OBSVAR:
+ Memi[code + cp - 1] = PEV_OBSVAR
+ offset = 0
+ case PTY_CATVAR:
+ Memi[code + cp - 1] = PEV_CATVAR
+ offset = pr_geti (NOBSVARS)
+ case PTY_FITPAR, PTY_CONST:
+ Memi[code + cp - 1] = PEV_PARAM
+ offset = 0
+ case PTY_SETEQ:
+ Memi[code + cp - 1] = PEV_SETEQ
+ offset = 0
+ case PTY_EXTEQ:
+ Memi[code + cp - 1] = PEV_EXTEQ
+ offset = 0
+ case PTY_TRNEQ:
+ Memi[code + cp - 1] = PEV_TRNEQ
+ offset = 0
+ default:
+ call sprintf (aux, SZ_LINE,
+ "pr_cgen: Illegal symbol type (%d)")
+ call pargi (type)
+ call error (0, aux)
+ }
+
+ # Store symbol number, plus the offset, in next instruction
+ cp = cp + 1
+ Memi[code + cp - 1] = pr_gsymi (sym, PSYMNUM) + offset
+
+ }
+
+ case INUMBER, RNUMBER:
+
+ # Store number instruction code and the number
+ # value in the next instruction
+ Memi[code + cp - 1] = PEV_NUMBER
+ cp = cp + 1
+ Memr[code + cp - 1] = value
+
+ case UPLUS:
+ Memi[code + cp - 1] = PEV_UPLUS
+
+ case UMINUS:
+ Memi[code + cp - 1] = PEV_UMINUS
+
+ case PLUS:
+ Memi[code + cp - 1] = PEV_PLUS
+
+ case MINUS:
+ Memi[code + cp - 1] = PEV_MINUS
+
+ case STAR:
+ Memi[code + cp - 1] = PEV_STAR
+
+ case SLASH:
+ Memi[code + cp - 1] = PEV_SLASH
+
+ case EXPON:
+ Memi[code + cp - 1] = PEV_EXPON
+
+ case F_ABS:
+ Memi[code + cp - 1] = PEV_ABS
+
+ case F_ACOS:
+ Memi[code + cp - 1] = PEV_ACOS
+
+ case F_ASIN:
+ Memi[code + cp - 1] = PEV_ASIN
+
+ case F_ATAN:
+ Memi[code + cp - 1] = PEV_ATAN
+
+ case F_COS:
+ Memi[code + cp - 1] = PEV_COS
+
+ case F_EXP:
+ Memi[code + cp - 1] = PEV_EXP
+
+ case F_LOG:
+ Memi[code + cp - 1] = PEV_LOG
+
+ case F_LOG10:
+ Memi[code + cp - 1] = PEV_LOG10
+
+ case F_SIN:
+ Memi[code + cp - 1] = PEV_SIN
+
+ case F_SQRT:
+ Memi[code + cp - 1] = PEV_SQRT
+
+ case F_TAN:
+ Memi[code + cp - 1] = PEV_TAN
+
+ default:
+ call error (0, "pr_cgen: Illegal instruction")
+ }
+
+ # Count codes, and check boundaries. Reserve at
+ # least three places: two for the next instruction,
+ # and one for the end-of-code marker
+ cp = cp + 1
+ if (cp > LEN_CODE - 2)
+ call error (0, "pr_cgen: Too much code")
+end
+
+
+# PR_CPUT - Allocate space for a code buffer, copy given code bufer into
+# it, and return pointer to it
+
+pointer procedure pr_cput (code, len)
+
+pointer code # code buffer
+int len # code length
+
+pointer aux
+
+begin
+ # Check pointer
+ if (code == NULL)
+ call error (0, "pr_cput: Null code pointer")
+
+ # Allocate memory for code and copy code buffer into it
+ call malloc (aux, len, TY_STRUCT)
+ call amovi (Memi[code], Memi[aux], len)
+
+ # Return new buffer pointer
+ return (aux)
+end
diff --git a/noao/digiphot/photcal/parser/prconv.x b/noao/digiphot/photcal/parser/prconv.x
new file mode 100644
index 00000000..358165a6
--- /dev/null
+++ b/noao/digiphot/photcal/parser/prconv.x
@@ -0,0 +1,72 @@
+.help prconv
+Parser symbol conversion
+
+These procedures convert SYMTAB pointers into symbol offsets and viceversa,
+and string offsets into character pointers (when applicable).
+These procedures are called by the prget and prput procedures in order to
+perform the appropiate type conversions.
+
+.nf
+Entry points:
+
+int = pr_offset (sym) Convert SYMTAB pointer into symbol offset
+pointer = pr_pointer (offset) Convert symbol offset into SYMTAB pointer
+pointer = pr_charp (offset) Convert string offset into character pointer
+.fi
+.endhelp
+
+include "../lib/parser.h"
+
+
+# PR_OFFSET - Convert SYMTAB pointer into an offset
+
+int procedure pr_offset (sym)
+
+pointer sym # symbol pointer
+
+pointer strefstab()
+pointer pr_getp()
+
+begin
+ # Check pointer
+ if (sym == NULL)
+ return (INDEFI)
+ else
+ return (sym - strefstab (pr_getp (SYMTABLE), 0))
+end
+
+
+# PR_POINTER - Convert an offset into a SYMTAB pointer
+
+pointer procedure pr_pointer (offset)
+
+int offset # symbol offset
+
+pointer strefstab()
+pointer pr_getp()
+
+begin
+ # Check offset
+ if (IS_INDEFI (offset))
+ return (NULL)
+ else
+ return (strefstab (pr_getp (SYMTABLE), offset))
+end
+
+
+# PR_CHARP - Convert string offset into character pointer
+
+pointer procedure pr_charp (offset)
+
+int offset # string offset
+
+pointer strefsbuf()
+pointer pr_getp()
+
+begin
+ # Check offset
+ if (IS_INDEFI (offset))
+ return (NULL)
+ else
+ return (strefsbuf (pr_getp (SYMTABLE), offset))
+end
diff --git a/noao/digiphot/photcal/parser/prerror.x b/noao/digiphot/photcal/parser/prerror.x
new file mode 100644
index 00000000..8821810e
--- /dev/null
+++ b/noao/digiphot/photcal/parser/prerror.x
@@ -0,0 +1,57 @@
+include "../lib/parser.h"
+include "../lib/prdefs.h"
+
+
+# PR_ERROR - Issue an error message to the standard output, and take an
+# error action acording to the severity code. Error messages can be disabled
+# if the error flag is set to NO.
+
+procedure pr_error (msg, severity)
+
+char msg[ARB] # error message
+int severity # severity code
+
+include "lexer.com"
+
+#bool clgetb()
+int pr_geti()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_error (msg=%s) (sev=%d)\n")
+ #call pargstr (msg)
+ #call pargi (severity)
+ #}
+
+ # Test whether to process errors, or not
+ if (pr_geti (FLAGERRORS) == NO)
+ return
+
+ # Branch on error severity code
+ switch (severity) {
+ case PERR_WARNING:
+ call pr_inci (NWARNINGS, 1)
+ call printf ("** Warning near line %d: %s%s\n")
+ call pargi (nlines)
+ call pargstr (line)
+ call pargstr (msg)
+ case PERR_SYNTAX:
+ call pr_inci (NERRORS, 1)
+ call printf ("** Error near line %d: %s%s at '%s'\n")
+ call pargi (nlines)
+ call pargstr (line)
+ call pargstr (msg)
+ call pargstr (id)
+ case PERR_SEMANTIC:
+ call pr_inci (NERRORS, 1)
+ call printf ("** Error near line %d: %s%s\n")
+ call pargi (nlines)
+ call pargstr (line)
+ call pargstr (msg)
+ case PERR_POSTPROC:
+ call pr_inci (NERRORS, 1)
+ call printf ("** Error: %s\n")
+ call pargstr (msg)
+ }
+end
diff --git a/noao/digiphot/photcal/parser/preval.gx b/noao/digiphot/photcal/parser/preval.gx
new file mode 100644
index 00000000..24eb5e41
--- /dev/null
+++ b/noao/digiphot/photcal/parser/preval.gx
@@ -0,0 +1,319 @@
+include "../lib/parser.h"
+include "../lib/preval.h"
+
+# Evaluation stack depth
+define STACK_DEPTH 50
+
+
+# PR_EVAL - Evaluate an RPN code expression generated by the parser. This
+# procedure checks for consistency in the input, although the code generated
+# by the parser should be correct, and for stack underflow and overflow.
+# The underflow can only happen under wrong generated code, but overflow
+# can happen in complex expressions. This is not a syntactic, but related
+# with the number of parenthesis used in the original source code expression.
+# Illegal operations, such as division by zero, return and undefined value.
+
+real procedure pr_eval (code, vdata, pdata)
+
+pointer code # RPN code buffer
+real vdata[ARB] # variables
+real pdata[ARB] # parameters
+
+real pr_evs ()
+
+begin
+ return (pr_evs (code, vdata, pdata))
+end
+
+
+# PR_EV[SILRDX] - These procedures are called in chain, one for each indirect
+# call to an equation expression (recursion). In this way it is possible to
+# have up to six levels of indirection. Altough it works well, this is a patch,
+# and should be replaced with a more elegant procedure that keeps a stack of
+# indirect calls.
+
+$for (silrdx)
+real procedure pr_ev$t (code, vdata, pdata)
+
+pointer code # RPN code buffer
+real vdata[ARB] # variables
+real pdata[ARB] # parameters
+
+char str[SZ_LINE]
+int ip # instruction pointer
+int sp # stack pointer
+int ins # current instruction
+int sym # equation symbol
+real stack[STACK_DEPTH] # evaluation stack
+real dummy
+pointer caux, paux
+
+$if (datatype == s)
+real pr_evi ()
+$endif
+$if (datatype == i)
+real pr_evl ()
+$endif
+$if (datatype == l)
+real pr_evr ()
+$endif
+$if (datatype == r)
+real pr_evd ()
+$endif
+$if (datatype == d)
+real pr_evx ()
+$endif
+pointer pr_gsym(), pr_gsymp()
+
+begin
+ # Set the instruction pointer (offset from the
+ # beginning) to the first instruction in the buffer
+ ip = 0
+
+ # Get first instruction from the code buffer
+ ins = Memi[code + ip]
+
+ # Reset execution stack pointer
+ sp = 0
+
+ # Returned value when recursion overflows
+ dummy = INDEFR
+
+ # Loop reading instructions from the code buffer
+ # until the end-of-code instruction is found
+ while (ins != PEV_EOC) {
+
+ # Branch on the instruction type
+ switch (ins) {
+
+ case PEV_NUMBER:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = Memr[code + ip]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_CATVAR:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = vdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_OBSVAR:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = vdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_PARAM:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = pdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_SETEQ:
+ ip = ip + 1
+ sp = sp + 1
+
+ sym = pr_gsym (Memi[code + ip], PTY_SETEQ)
+ caux = pr_gsymp (sym, PSEQRPNEQ)
+
+ $if (datatype == s)
+ stack[sp] = pr_evi (caux, vdata, pdata)
+ $endif
+ $if (datatype == i)
+ stack[sp] = pr_evl (caux, vdata, pdata)
+ $endif
+ $if (datatype == l)
+ stack[sp] = pr_evr (caux, vdata, pdata)
+ $endif
+ $if (datatype == r)
+ stack[sp] = pr_evd (caux, vdata, pdata)
+ $endif
+ $if (datatype == d)
+ stack[sp] = pr_evx (caux, vdata, pdata)
+ $endif
+ $if (datatype == x)
+ stack[sp] = dummy
+ $endif
+
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_EXTEQ:
+ # not yet implemented
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = INDEFR
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_TRNEQ:
+ ip = ip + 1
+ sp = sp + 1
+
+ sym = pr_gsym (Memi[code + ip], PTY_TRNEQ)
+ caux = pr_gsymp (sym, PTEQRPNFIT)
+ paux = pr_gsymp (sym, PTEQSPARVAL)
+
+ $if (datatype == s)
+ stack[sp] = pr_evi (caux, vdata, Memr[paux])
+ $endif
+ $if (datatype == i)
+ stack[sp] = pr_evl (caux, vdata, Memr[paux])
+ $endif
+ $if (datatype == l)
+ stack[sp] = pr_evr (caux, vdata, Memr[paux])
+ $endif
+ $if (datatype == r)
+ stack[sp] = pr_evd (caux, vdata, Memr[paux])
+ $endif
+ $if (datatype == d)
+ stack[sp] = pr_evx (caux, vdata, Memr[paux])
+ $endif
+ $if (datatype == x)
+ stack[sp] = dummy
+ $endif
+
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_UPLUS:
+ # do nothing
+
+ case PEV_UMINUS:
+ stack[sp] = - stack[sp]
+
+ case PEV_PLUS:
+ stack[sp - 1] = stack[sp - 1] + stack[sp]
+ sp = sp - 1
+
+ case PEV_MINUS:
+ stack[sp - 1] = stack[sp - 1] - stack[sp]
+ sp = sp - 1
+
+ case PEV_STAR:
+ stack[sp - 1] = stack[sp - 1] * stack[sp]
+ sp = sp - 1
+
+ case PEV_SLASH:
+ if (stack[sp] != 0) {
+ stack[sp - 1] = stack[sp - 1] / stack[sp]
+ sp = sp - 1
+ } else {
+ stack[sp - 1] = INDEFR
+ sp = sp - 1
+ break
+ }
+
+ case PEV_EXPON:
+ if (stack[sp - 1] != 0)
+ stack[sp - 1] = stack[sp - 1] ** stack[sp]
+ else
+ stack[sp - 1] = 0.0
+ sp = sp - 1
+
+ case PEV_ABS:
+ stack[sp] = abs (stack[sp])
+
+ case PEV_ACOS:
+ if (abs (stack[sp]) <= 1.0)
+ stack[sp] = acos (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_ASIN:
+ if (abs (stack[sp]) <= 1.0)
+ stack[sp] = asin (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_ATAN:
+ stack[sp] = atan (stack[sp])
+
+ case PEV_COS:
+ stack[sp] = cos (stack[sp])
+
+ case PEV_EXP:
+ stack[sp] = exp (stack[sp])
+
+ case PEV_LOG:
+ if (stack[sp] > 0.0)
+ stack[sp] = log (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_LOG10:
+ if (stack[sp] > 0.0)
+ stack[sp] = log10 (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_SIN:
+ stack[sp] = sin (stack[sp])
+
+ case PEV_SQRT:
+ if (stack[sp] >= 0.0)
+ stack[sp] = sqrt (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_TAN:
+ stack[sp] = tan (stack[sp])
+
+ default: # (just in case)
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation code error (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Check for stack overflow. This is the
+ # only check really needed.
+ if (sp >= STACK_DEPTH) {
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation stack overflow (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Check for stack underflow (just in case)
+ if (sp < 1) {
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation stack underflow (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Get next instruction
+ ip = ip + 1
+ ins = Memi[code + ip]
+ }
+
+ # Return expression value
+ return (stack[sp])
+end
+
+$endfor
diff --git a/noao/digiphot/photcal/parser/preval.x b/noao/digiphot/photcal/parser/preval.x
new file mode 100644
index 00000000..28cb9c25
--- /dev/null
+++ b/noao/digiphot/photcal/parser/preval.x
@@ -0,0 +1,1448 @@
+include "../lib/parser.h"
+include "../lib/preval.h"
+
+# Evaluation stack depth
+define STACK_DEPTH 50
+
+
+# PR_EVAL - Evaluate an RPN code expression generated by the parser. This
+# procedure checks for consistency in the input, although the code generated
+# by the parser should be correct, and for stack underflow and overflow.
+# The underflow can only happen under wrong generated code, but overflow
+# can happen in complex expressions. This is not a syntactic, but related
+# with the number of parenthesis used in the original source code expression.
+# Illegal operations, such as division by zero, return and undefined value.
+
+real procedure pr_eval (code, vdata, pdata)
+
+pointer code # RPN code buffer
+real vdata[ARB] # variables
+real pdata[ARB] # parameters
+
+real pr_evs ()
+
+begin
+ return (pr_evs (code, vdata, pdata))
+end
+
+
+# PR_EV[SILRDX] - These procedures are called in chain, one for each indirect
+# call to an equation expression (recursion). In this way it is possible to
+# have up to six levels of indirection. Altough it works well, this is a patch,
+# and should be replaced with a more elegant procedure that keeps a stack of
+# indirect calls.
+
+
+real procedure pr_evs (code, vdata, pdata)
+
+pointer code # RPN code buffer
+real vdata[ARB] # variables
+real pdata[ARB] # parameters
+
+char str[SZ_LINE]
+int ip # instruction pointer
+int sp # stack pointer
+int ins # current instruction
+int sym # equation symbol
+real stack[STACK_DEPTH] # evaluation stack
+real dummy
+pointer caux, paux
+
+real pr_evi ()
+pointer pr_gsym(), pr_gsymp()
+
+begin
+ # Set the instruction pointer (offset from the
+ # beginning) to the first instruction in the buffer
+ ip = 0
+
+ # Get first instruction from the code buffer
+ ins = Memi[code + ip]
+
+ # Reset execution stack pointer
+ sp = 0
+
+ # Returned value when recursion overflows
+ dummy = INDEFR
+
+ # Loop reading instructions from the code buffer
+ # until the end-of-code instruction is found
+ while (ins != PEV_EOC) {
+
+ # Branch on the instruction type
+ switch (ins) {
+
+ case PEV_NUMBER:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = Memr[code + ip]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_CATVAR:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = vdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_OBSVAR:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = vdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_PARAM:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = pdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_SETEQ:
+ ip = ip + 1
+ sp = sp + 1
+
+ sym = pr_gsym (Memi[code + ip], PTY_SETEQ)
+ caux = pr_gsymp (sym, PSEQRPNEQ)
+
+ stack[sp] = pr_evi (caux, vdata, pdata)
+
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_EXTEQ:
+ # not yet implemented
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = INDEFR
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_TRNEQ:
+ ip = ip + 1
+ sp = sp + 1
+
+ sym = pr_gsym (Memi[code + ip], PTY_TRNEQ)
+ caux = pr_gsymp (sym, PTEQRPNFIT)
+ paux = pr_gsymp (sym, PTEQSPARVAL)
+
+ stack[sp] = pr_evi (caux, vdata, Memr[paux])
+
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_UPLUS:
+ # do nothing
+
+ case PEV_UMINUS:
+ stack[sp] = - stack[sp]
+
+ case PEV_PLUS:
+ stack[sp - 1] = stack[sp - 1] + stack[sp]
+ sp = sp - 1
+
+ case PEV_MINUS:
+ stack[sp - 1] = stack[sp - 1] - stack[sp]
+ sp = sp - 1
+
+ case PEV_STAR:
+ stack[sp - 1] = stack[sp - 1] * stack[sp]
+ sp = sp - 1
+
+ case PEV_SLASH:
+ if (stack[sp] != 0) {
+ stack[sp - 1] = stack[sp - 1] / stack[sp]
+ sp = sp - 1
+ } else {
+ stack[sp - 1] = INDEFR
+ sp = sp - 1
+ break
+ }
+
+ case PEV_EXPON:
+ if (stack[sp - 1] != 0)
+ stack[sp - 1] = stack[sp - 1] ** stack[sp]
+ else
+ stack[sp - 1] = 0.0
+ sp = sp - 1
+
+ case PEV_ABS:
+ stack[sp] = abs (stack[sp])
+
+ case PEV_ACOS:
+ if (abs (stack[sp]) <= 1.0)
+ stack[sp] = acos (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_ASIN:
+ if (abs (stack[sp]) <= 1.0)
+ stack[sp] = asin (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_ATAN:
+ stack[sp] = atan (stack[sp])
+
+ case PEV_COS:
+ stack[sp] = cos (stack[sp])
+
+ case PEV_EXP:
+ stack[sp] = exp (stack[sp])
+
+ case PEV_LOG:
+ if (stack[sp] > 0.0)
+ stack[sp] = log (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_LOG10:
+ if (stack[sp] > 0.0)
+ stack[sp] = log10 (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_SIN:
+ stack[sp] = sin (stack[sp])
+
+ case PEV_SQRT:
+ if (stack[sp] >= 0.0)
+ stack[sp] = sqrt (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_TAN:
+ stack[sp] = tan (stack[sp])
+
+ default: # (just in case)
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation code error (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Check for stack overflow. This is the
+ # only check really needed.
+ if (sp >= STACK_DEPTH) {
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation stack overflow (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Check for stack underflow (just in case)
+ if (sp < 1) {
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation stack underflow (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Get next instruction
+ ip = ip + 1
+ ins = Memi[code + ip]
+ }
+
+ # Return expression value
+ return (stack[sp])
+end
+
+
+real procedure pr_evi (code, vdata, pdata)
+
+pointer code # RPN code buffer
+real vdata[ARB] # variables
+real pdata[ARB] # parameters
+
+char str[SZ_LINE]
+int ip # instruction pointer
+int sp # stack pointer
+int ins # current instruction
+int sym # equation symbol
+real stack[STACK_DEPTH] # evaluation stack
+real dummy
+pointer caux, paux
+
+real pr_evl ()
+pointer pr_gsym(), pr_gsymp()
+
+begin
+ # Set the instruction pointer (offset from the
+ # beginning) to the first instruction in the buffer
+ ip = 0
+
+ # Get first instruction from the code buffer
+ ins = Memi[code + ip]
+
+ # Reset execution stack pointer
+ sp = 0
+
+ # Returned value when recursion overflows
+ dummy = INDEFR
+
+ # Loop reading instructions from the code buffer
+ # until the end-of-code instruction is found
+ while (ins != PEV_EOC) {
+
+ # Branch on the instruction type
+ switch (ins) {
+
+ case PEV_NUMBER:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = Memr[code + ip]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_CATVAR:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = vdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_OBSVAR:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = vdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_PARAM:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = pdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_SETEQ:
+ ip = ip + 1
+ sp = sp + 1
+
+ sym = pr_gsym (Memi[code + ip], PTY_SETEQ)
+ caux = pr_gsymp (sym, PSEQRPNEQ)
+
+ stack[sp] = pr_evl (caux, vdata, pdata)
+
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_EXTEQ:
+ # not yet implemented
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = INDEFR
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_TRNEQ:
+ ip = ip + 1
+ sp = sp + 1
+
+ sym = pr_gsym (Memi[code + ip], PTY_TRNEQ)
+ caux = pr_gsymp (sym, PTEQRPNFIT)
+ paux = pr_gsymp (sym, PTEQSPARVAL)
+
+ stack[sp] = pr_evl (caux, vdata, Memr[paux])
+
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_UPLUS:
+ # do nothing
+
+ case PEV_UMINUS:
+ stack[sp] = - stack[sp]
+
+ case PEV_PLUS:
+ stack[sp - 1] = stack[sp - 1] + stack[sp]
+ sp = sp - 1
+
+ case PEV_MINUS:
+ stack[sp - 1] = stack[sp - 1] - stack[sp]
+ sp = sp - 1
+
+ case PEV_STAR:
+ stack[sp - 1] = stack[sp - 1] * stack[sp]
+ sp = sp - 1
+
+ case PEV_SLASH:
+ if (stack[sp] != 0) {
+ stack[sp - 1] = stack[sp - 1] / stack[sp]
+ sp = sp - 1
+ } else {
+ stack[sp - 1] = INDEFR
+ sp = sp - 1
+ break
+ }
+
+ case PEV_EXPON:
+ if (stack[sp - 1] != 0)
+ stack[sp - 1] = stack[sp - 1] ** stack[sp]
+ else
+ stack[sp - 1] = 0.0
+ sp = sp - 1
+
+ case PEV_ABS:
+ stack[sp] = abs (stack[sp])
+
+ case PEV_ACOS:
+ if (abs (stack[sp]) <= 1.0)
+ stack[sp] = acos (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_ASIN:
+ if (abs (stack[sp]) <= 1.0)
+ stack[sp] = asin (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_ATAN:
+ stack[sp] = atan (stack[sp])
+
+ case PEV_COS:
+ stack[sp] = cos (stack[sp])
+
+ case PEV_EXP:
+ stack[sp] = exp (stack[sp])
+
+ case PEV_LOG:
+ if (stack[sp] > 0.0)
+ stack[sp] = log (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_LOG10:
+ if (stack[sp] > 0.0)
+ stack[sp] = log10 (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_SIN:
+ stack[sp] = sin (stack[sp])
+
+ case PEV_SQRT:
+ if (stack[sp] >= 0.0)
+ stack[sp] = sqrt (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_TAN:
+ stack[sp] = tan (stack[sp])
+
+ default: # (just in case)
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation code error (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Check for stack overflow. This is the
+ # only check really needed.
+ if (sp >= STACK_DEPTH) {
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation stack overflow (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Check for stack underflow (just in case)
+ if (sp < 1) {
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation stack underflow (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Get next instruction
+ ip = ip + 1
+ ins = Memi[code + ip]
+ }
+
+ # Return expression value
+ return (stack[sp])
+end
+
+
+real procedure pr_evl (code, vdata, pdata)
+
+pointer code # RPN code buffer
+real vdata[ARB] # variables
+real pdata[ARB] # parameters
+
+char str[SZ_LINE]
+int ip # instruction pointer
+int sp # stack pointer
+int ins # current instruction
+int sym # equation symbol
+real stack[STACK_DEPTH] # evaluation stack
+real dummy
+pointer caux, paux
+
+real pr_evr ()
+pointer pr_gsym(), pr_gsymp()
+
+begin
+ # Set the instruction pointer (offset from the
+ # beginning) to the first instruction in the buffer
+ ip = 0
+
+ # Get first instruction from the code buffer
+ ins = Memi[code + ip]
+
+ # Reset execution stack pointer
+ sp = 0
+
+ # Returned value when recursion overflows
+ dummy = INDEFR
+
+ # Loop reading instructions from the code buffer
+ # until the end-of-code instruction is found
+ while (ins != PEV_EOC) {
+
+ # Branch on the instruction type
+ switch (ins) {
+
+ case PEV_NUMBER:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = Memr[code + ip]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_CATVAR:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = vdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_OBSVAR:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = vdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_PARAM:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = pdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_SETEQ:
+ ip = ip + 1
+ sp = sp + 1
+
+ sym = pr_gsym (Memi[code + ip], PTY_SETEQ)
+ caux = pr_gsymp (sym, PSEQRPNEQ)
+
+ stack[sp] = pr_evr (caux, vdata, pdata)
+
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_EXTEQ:
+ # not yet implemented
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = INDEFR
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_TRNEQ:
+ ip = ip + 1
+ sp = sp + 1
+
+ sym = pr_gsym (Memi[code + ip], PTY_TRNEQ)
+ caux = pr_gsymp (sym, PTEQRPNFIT)
+ paux = pr_gsymp (sym, PTEQSPARVAL)
+
+ stack[sp] = pr_evr (caux, vdata, Memr[paux])
+
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_UPLUS:
+ # do nothing
+
+ case PEV_UMINUS:
+ stack[sp] = - stack[sp]
+
+ case PEV_PLUS:
+ stack[sp - 1] = stack[sp - 1] + stack[sp]
+ sp = sp - 1
+
+ case PEV_MINUS:
+ stack[sp - 1] = stack[sp - 1] - stack[sp]
+ sp = sp - 1
+
+ case PEV_STAR:
+ stack[sp - 1] = stack[sp - 1] * stack[sp]
+ sp = sp - 1
+
+ case PEV_SLASH:
+ if (stack[sp] != 0) {
+ stack[sp - 1] = stack[sp - 1] / stack[sp]
+ sp = sp - 1
+ } else {
+ stack[sp - 1] = INDEFR
+ sp = sp - 1
+ break
+ }
+
+ case PEV_EXPON:
+ if (stack[sp - 1] != 0)
+ stack[sp - 1] = stack[sp - 1] ** stack[sp]
+ else
+ stack[sp - 1] = 0.0
+ sp = sp - 1
+
+ case PEV_ABS:
+ stack[sp] = abs (stack[sp])
+
+ case PEV_ACOS:
+ if (abs (stack[sp]) <= 1.0)
+ stack[sp] = acos (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_ASIN:
+ if (abs (stack[sp]) <= 1.0)
+ stack[sp] = asin (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_ATAN:
+ stack[sp] = atan (stack[sp])
+
+ case PEV_COS:
+ stack[sp] = cos (stack[sp])
+
+ case PEV_EXP:
+ stack[sp] = exp (stack[sp])
+
+ case PEV_LOG:
+ if (stack[sp] > 0.0)
+ stack[sp] = log (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_LOG10:
+ if (stack[sp] > 0.0)
+ stack[sp] = log10 (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_SIN:
+ stack[sp] = sin (stack[sp])
+
+ case PEV_SQRT:
+ if (stack[sp] >= 0.0)
+ stack[sp] = sqrt (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_TAN:
+ stack[sp] = tan (stack[sp])
+
+ default: # (just in case)
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation code error (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Check for stack overflow. This is the
+ # only check really needed.
+ if (sp >= STACK_DEPTH) {
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation stack overflow (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Check for stack underflow (just in case)
+ if (sp < 1) {
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation stack underflow (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Get next instruction
+ ip = ip + 1
+ ins = Memi[code + ip]
+ }
+
+ # Return expression value
+ return (stack[sp])
+end
+
+
+real procedure pr_evr (code, vdata, pdata)
+
+pointer code # RPN code buffer
+real vdata[ARB] # variables
+real pdata[ARB] # parameters
+
+char str[SZ_LINE]
+int ip # instruction pointer
+int sp # stack pointer
+int ins # current instruction
+int sym # equation symbol
+real stack[STACK_DEPTH] # evaluation stack
+real dummy
+pointer caux, paux
+
+real pr_evd ()
+pointer pr_gsym(), pr_gsymp()
+
+begin
+ # Set the instruction pointer (offset from the
+ # beginning) to the first instruction in the buffer
+ ip = 0
+
+ # Get first instruction from the code buffer
+ ins = Memi[code + ip]
+
+ # Reset execution stack pointer
+ sp = 0
+
+ # Returned value when recursion overflows
+ dummy = INDEFR
+
+ # Loop reading instructions from the code buffer
+ # until the end-of-code instruction is found
+ while (ins != PEV_EOC) {
+
+ # Branch on the instruction type
+ switch (ins) {
+
+ case PEV_NUMBER:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = Memr[code + ip]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_CATVAR:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = vdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_OBSVAR:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = vdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_PARAM:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = pdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_SETEQ:
+ ip = ip + 1
+ sp = sp + 1
+
+ sym = pr_gsym (Memi[code + ip], PTY_SETEQ)
+ caux = pr_gsymp (sym, PSEQRPNEQ)
+
+ stack[sp] = pr_evd (caux, vdata, pdata)
+
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_EXTEQ:
+ # not yet implemented
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = INDEFR
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_TRNEQ:
+ ip = ip + 1
+ sp = sp + 1
+
+ sym = pr_gsym (Memi[code + ip], PTY_TRNEQ)
+ caux = pr_gsymp (sym, PTEQRPNFIT)
+ paux = pr_gsymp (sym, PTEQSPARVAL)
+
+ stack[sp] = pr_evd (caux, vdata, Memr[paux])
+
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_UPLUS:
+ # do nothing
+
+ case PEV_UMINUS:
+ stack[sp] = - stack[sp]
+
+ case PEV_PLUS:
+ stack[sp - 1] = stack[sp - 1] + stack[sp]
+ sp = sp - 1
+
+ case PEV_MINUS:
+ stack[sp - 1] = stack[sp - 1] - stack[sp]
+ sp = sp - 1
+
+ case PEV_STAR:
+ stack[sp - 1] = stack[sp - 1] * stack[sp]
+ sp = sp - 1
+
+ case PEV_SLASH:
+ if (stack[sp] != 0) {
+ stack[sp - 1] = stack[sp - 1] / stack[sp]
+ sp = sp - 1
+ } else {
+ stack[sp - 1] = INDEFR
+ sp = sp - 1
+ break
+ }
+
+ case PEV_EXPON:
+ if (stack[sp - 1] != 0)
+ stack[sp - 1] = stack[sp - 1] ** stack[sp]
+ else
+ stack[sp - 1] = 0.0
+ sp = sp - 1
+
+ case PEV_ABS:
+ stack[sp] = abs (stack[sp])
+
+ case PEV_ACOS:
+ if (abs (stack[sp]) <= 1.0)
+ stack[sp] = acos (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_ASIN:
+ if (abs (stack[sp]) <= 1.0)
+ stack[sp] = asin (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_ATAN:
+ stack[sp] = atan (stack[sp])
+
+ case PEV_COS:
+ stack[sp] = cos (stack[sp])
+
+ case PEV_EXP:
+ stack[sp] = exp (stack[sp])
+
+ case PEV_LOG:
+ if (stack[sp] > 0.0)
+ stack[sp] = log (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_LOG10:
+ if (stack[sp] > 0.0)
+ stack[sp] = log10 (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_SIN:
+ stack[sp] = sin (stack[sp])
+
+ case PEV_SQRT:
+ if (stack[sp] >= 0.0)
+ stack[sp] = sqrt (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_TAN:
+ stack[sp] = tan (stack[sp])
+
+ default: # (just in case)
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation code error (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Check for stack overflow. This is the
+ # only check really needed.
+ if (sp >= STACK_DEPTH) {
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation stack overflow (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Check for stack underflow (just in case)
+ if (sp < 1) {
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation stack underflow (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Get next instruction
+ ip = ip + 1
+ ins = Memi[code + ip]
+ }
+
+ # Return expression value
+ return (stack[sp])
+end
+
+
+real procedure pr_evd (code, vdata, pdata)
+
+pointer code # RPN code buffer
+real vdata[ARB] # variables
+real pdata[ARB] # parameters
+
+char str[SZ_LINE]
+int ip # instruction pointer
+int sp # stack pointer
+int ins # current instruction
+int sym # equation symbol
+real stack[STACK_DEPTH] # evaluation stack
+real dummy
+pointer caux, paux
+
+real pr_evx ()
+pointer pr_gsym(), pr_gsymp()
+
+begin
+ # Set the instruction pointer (offset from the
+ # beginning) to the first instruction in the buffer
+ ip = 0
+
+ # Get first instruction from the code buffer
+ ins = Memi[code + ip]
+
+ # Reset execution stack pointer
+ sp = 0
+
+ # Returned value when recursion overflows
+ dummy = INDEFR
+
+ # Loop reading instructions from the code buffer
+ # until the end-of-code instruction is found
+ while (ins != PEV_EOC) {
+
+ # Branch on the instruction type
+ switch (ins) {
+
+ case PEV_NUMBER:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = Memr[code + ip]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_CATVAR:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = vdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_OBSVAR:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = vdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_PARAM:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = pdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_SETEQ:
+ ip = ip + 1
+ sp = sp + 1
+
+ sym = pr_gsym (Memi[code + ip], PTY_SETEQ)
+ caux = pr_gsymp (sym, PSEQRPNEQ)
+
+ stack[sp] = pr_evx (caux, vdata, pdata)
+
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_EXTEQ:
+ # not yet implemented
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = INDEFR
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_TRNEQ:
+ ip = ip + 1
+ sp = sp + 1
+
+ sym = pr_gsym (Memi[code + ip], PTY_TRNEQ)
+ caux = pr_gsymp (sym, PTEQRPNFIT)
+ paux = pr_gsymp (sym, PTEQSPARVAL)
+
+ stack[sp] = pr_evx (caux, vdata, Memr[paux])
+
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_UPLUS:
+ # do nothing
+
+ case PEV_UMINUS:
+ stack[sp] = - stack[sp]
+
+ case PEV_PLUS:
+ stack[sp - 1] = stack[sp - 1] + stack[sp]
+ sp = sp - 1
+
+ case PEV_MINUS:
+ stack[sp - 1] = stack[sp - 1] - stack[sp]
+ sp = sp - 1
+
+ case PEV_STAR:
+ stack[sp - 1] = stack[sp - 1] * stack[sp]
+ sp = sp - 1
+
+ case PEV_SLASH:
+ if (stack[sp] != 0) {
+ stack[sp - 1] = stack[sp - 1] / stack[sp]
+ sp = sp - 1
+ } else {
+ stack[sp - 1] = INDEFR
+ sp = sp - 1
+ break
+ }
+
+ case PEV_EXPON:
+ if (stack[sp - 1] != 0)
+ stack[sp - 1] = stack[sp - 1] ** stack[sp]
+ else
+ stack[sp - 1] = 0.0
+ sp = sp - 1
+
+ case PEV_ABS:
+ stack[sp] = abs (stack[sp])
+
+ case PEV_ACOS:
+ if (abs (stack[sp]) <= 1.0)
+ stack[sp] = acos (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_ASIN:
+ if (abs (stack[sp]) <= 1.0)
+ stack[sp] = asin (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_ATAN:
+ stack[sp] = atan (stack[sp])
+
+ case PEV_COS:
+ stack[sp] = cos (stack[sp])
+
+ case PEV_EXP:
+ stack[sp] = exp (stack[sp])
+
+ case PEV_LOG:
+ if (stack[sp] > 0.0)
+ stack[sp] = log (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_LOG10:
+ if (stack[sp] > 0.0)
+ stack[sp] = log10 (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_SIN:
+ stack[sp] = sin (stack[sp])
+
+ case PEV_SQRT:
+ if (stack[sp] >= 0.0)
+ stack[sp] = sqrt (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_TAN:
+ stack[sp] = tan (stack[sp])
+
+ default: # (just in case)
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation code error (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Check for stack overflow. This is the
+ # only check really needed.
+ if (sp >= STACK_DEPTH) {
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation stack overflow (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Check for stack underflow (just in case)
+ if (sp < 1) {
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation stack underflow (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Get next instruction
+ ip = ip + 1
+ ins = Memi[code + ip]
+ }
+
+ # Return expression value
+ return (stack[sp])
+end
+
+
+real procedure pr_evx (code, vdata, pdata)
+
+pointer code # RPN code buffer
+real vdata[ARB] # variables
+real pdata[ARB] # parameters
+
+char str[SZ_LINE]
+int ip # instruction pointer
+int sp # stack pointer
+int ins # current instruction
+int sym # equation symbol
+real stack[STACK_DEPTH] # evaluation stack
+real dummy
+pointer caux, paux
+
+pointer pr_gsym(), pr_gsymp()
+
+begin
+ # Set the instruction pointer (offset from the
+ # beginning) to the first instruction in the buffer
+ ip = 0
+
+ # Get first instruction from the code buffer
+ ins = Memi[code + ip]
+
+ # Reset execution stack pointer
+ sp = 0
+
+ # Returned value when recursion overflows
+ dummy = INDEFR
+
+ # Loop reading instructions from the code buffer
+ # until the end-of-code instruction is found
+ while (ins != PEV_EOC) {
+
+ # Branch on the instruction type
+ switch (ins) {
+
+ case PEV_NUMBER:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = Memr[code + ip]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_CATVAR:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = vdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_OBSVAR:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = vdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_PARAM:
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = pdata[Memi[code + ip]]
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_SETEQ:
+ ip = ip + 1
+ sp = sp + 1
+
+ sym = pr_gsym (Memi[code + ip], PTY_SETEQ)
+ caux = pr_gsymp (sym, PSEQRPNEQ)
+
+ stack[sp] = dummy
+
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_EXTEQ:
+ # not yet implemented
+ ip = ip + 1
+ sp = sp + 1
+ stack[sp] = INDEFR
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_TRNEQ:
+ ip = ip + 1
+ sp = sp + 1
+
+ sym = pr_gsym (Memi[code + ip], PTY_TRNEQ)
+ caux = pr_gsymp (sym, PTEQRPNFIT)
+ paux = pr_gsymp (sym, PTEQSPARVAL)
+
+ stack[sp] = dummy
+
+ if (IS_INDEFR (stack[sp]))
+ break
+
+ case PEV_UPLUS:
+ # do nothing
+
+ case PEV_UMINUS:
+ stack[sp] = - stack[sp]
+
+ case PEV_PLUS:
+ stack[sp - 1] = stack[sp - 1] + stack[sp]
+ sp = sp - 1
+
+ case PEV_MINUS:
+ stack[sp - 1] = stack[sp - 1] - stack[sp]
+ sp = sp - 1
+
+ case PEV_STAR:
+ stack[sp - 1] = stack[sp - 1] * stack[sp]
+ sp = sp - 1
+
+ case PEV_SLASH:
+ if (stack[sp] != 0) {
+ stack[sp - 1] = stack[sp - 1] / stack[sp]
+ sp = sp - 1
+ } else {
+ stack[sp - 1] = INDEFR
+ sp = sp - 1
+ break
+ }
+
+ case PEV_EXPON:
+ if (stack[sp - 1] != 0)
+ stack[sp - 1] = stack[sp - 1] ** stack[sp]
+ else
+ stack[sp - 1] = 0.0
+ sp = sp - 1
+
+ case PEV_ABS:
+ stack[sp] = abs (stack[sp])
+
+ case PEV_ACOS:
+ if (abs (stack[sp]) <= 1.0)
+ stack[sp] = acos (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_ASIN:
+ if (abs (stack[sp]) <= 1.0)
+ stack[sp] = asin (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_ATAN:
+ stack[sp] = atan (stack[sp])
+
+ case PEV_COS:
+ stack[sp] = cos (stack[sp])
+
+ case PEV_EXP:
+ stack[sp] = exp (stack[sp])
+
+ case PEV_LOG:
+ if (stack[sp] > 0.0)
+ stack[sp] = log (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_LOG10:
+ if (stack[sp] > 0.0)
+ stack[sp] = log10 (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_SIN:
+ stack[sp] = sin (stack[sp])
+
+ case PEV_SQRT:
+ if (stack[sp] >= 0.0)
+ stack[sp] = sqrt (stack[sp])
+ else {
+ stack[sp] = INDEFR
+ break
+ }
+
+ case PEV_TAN:
+ stack[sp] = tan (stack[sp])
+
+ default: # (just in case)
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation code error (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Check for stack overflow. This is the
+ # only check really needed.
+ if (sp >= STACK_DEPTH) {
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation stack overflow (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Check for stack underflow (just in case)
+ if (sp < 1) {
+ call sprintf (str, SZ_LINE,
+ "pr_eval: Evaluation stack underflow (code=%d ip=%d ins=%d sp=%d)")
+ call pargi (code)
+ call pargi (ip)
+ call pargi (ins)
+ call pargi (sp)
+ call error (0, str)
+ }
+
+ # Get next instruction
+ ip = ip + 1
+ ins = Memi[code + ip]
+ }
+
+ # Return expression value
+ return (stack[sp])
+end
diff --git a/noao/digiphot/photcal/parser/prexit.x b/noao/digiphot/photcal/parser/prexit.x
new file mode 100644
index 00000000..eec1d53d
--- /dev/null
+++ b/noao/digiphot/photcal/parser/prexit.x
@@ -0,0 +1,324 @@
+.help prexit
+Parser Exit Handling.
+
+After the compilation has finished without errors, the parser runs the
+pr_exit() routine in order to make sure that there are no inconsistencies in
+the parser symbol table, and to perform all steps that can be done only
+with the full symbol table. This procedure performs the following actions:
+
+- Builds the list of sequential tables for each type of variable, parameter,
+and equation in the symbol table. These tables are used later to access
+each type sequentially.
+
+- Sets the minimum and maximum values for observational and catalog variables.
+
+- Checks that there are no duplications in either the observational or catalog
+input columns.
+
+- Checks that all the derivatives for transformation equations are defined.
+
+If an error or inconsistency is detected an error message is issued.
+
+Entry point:
+
+ pr_exit() Exit procedure
+.endhelp
+
+include <mach.h>
+include "../lib/parser.h"
+include "../lib/prdefs.h"
+
+
+# PR_EXIT - Parser exit procedure.
+
+procedure pr_exit ()
+
+bool derflag, dltflag
+int i1, i2, incol, errcol, wtscol, mincol, maxcol, par, type
+int npar, sym
+pointer sp, aux, symtab, der
+#real delta
+
+#bool clgetb()
+int mct_nrows(), mct_geti(), pr_geti(), pr_gsymi(), pr_gpari()
+pointer sthead(), stnext(), pr_xgetname(), pr_offset, pr_getp(), pr_gderp()
+real pr_gsymr()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode"))
+ #call eprintf ("pr_exit.in\n")
+
+ # Allocate working space
+ call smark (sp)
+ call salloc (aux, SZ_LINE, TY_CHAR)
+
+ # Initialize minimum and maximum column values.
+ # Check for empty sections to initialize with the
+ # right value.
+
+ if (pr_geti (NOBSVARS) > 0) {
+ call pr_puti (MINOBSCOL, MAX_INT)
+ call pr_puti (MAXOBSCOL, -MAX_INT)
+ } else {
+ call pr_puti (MINOBSCOL, INDEFI)
+ call pr_puti (MAXOBSCOL, INDEFI)
+ }
+ if (pr_geti (NCATVARS) > 0) {
+ call pr_puti (MINCATCOL, MAX_INT)
+ call pr_puti (MAXCATCOL, -MAX_INT)
+ } else {
+ call pr_puti (MINCATCOL, INDEFI)
+ call pr_puti (MAXCATCOL, INDEFI)
+ }
+
+ # Build sequential tables from the parser symbol table,
+ # and compute minimum and maximum column numbers.
+
+ symtab = sthead (pr_getp (SYMTABLE))
+ while (symtab != NULL) {
+
+ # Convert SYMTAB pointer into symbol offset.
+ sym = pr_offset (symtab)
+
+ # Get symbol type.
+ type = pr_gsymi (sym, PSYMTYPE)
+
+ # Check symbol type consistency, and enter each symbol in a
+ # sequential table acording with its type
+
+ switch (type) {
+ case PTY_OBSVAR:
+ call mct_sputi (pr_getp (OBSTABLE), sym)
+ incol = pr_gsymi (sym, PINPCOL)
+ mincol = incol
+ maxcol = incol
+ errcol = pr_gsymi (sym, PINPERRCOL)
+ if (! IS_INDEFI(errcol)) {
+ mincol = min (mincol, errcol)
+ maxcol = max (maxcol, errcol)
+ }
+ wtscol = pr_gsymi (sym, PINPWTSCOL)
+ if (! IS_INDEFI(wtscol)) {
+ mincol = min (mincol, wtscol)
+ maxcol = max (maxcol, wtscol)
+ }
+ if (mincol < pr_geti (MINOBSCOL))
+ call pr_puti (MINOBSCOL, mincol)
+ if (maxcol > pr_geti (MAXOBSCOL))
+ call pr_puti (MAXOBSCOL, maxcol)
+ case PTY_CATVAR:
+ call mct_sputi (pr_getp (CATTABLE), sym)
+ incol = pr_gsymi (sym, PINPCOL)
+ mincol = incol
+ maxcol = incol
+ errcol = pr_gsymi (sym, PINPERRCOL)
+ if (! IS_INDEFI(errcol)) {
+ mincol = min (mincol, errcol)
+ maxcol = max (maxcol, errcol)
+ }
+ wtscol = pr_gsymi (sym, PINPWTSCOL)
+ if (! IS_INDEFI(wtscol)) {
+ mincol = min (mincol, wtscol)
+ maxcol = max (maxcol, wtscol)
+ }
+ if (mincol < pr_geti (MINCATCOL))
+ call pr_puti (MINCATCOL, mincol)
+ if (maxcol > pr_geti (MAXCATCOL))
+ call pr_puti (MAXCATCOL, maxcol)
+ case PTY_FITPAR, PTY_CONST:
+ call mct_sputi (pr_getp (PARTABLE), sym)
+ case PTY_SETEQ:
+ call mct_sputi (pr_getp (SETTABLE), sym)
+ case PTY_EXTEQ:
+ call mct_sputi (pr_getp (EXTTABLE), sym)
+ case PTY_TRNEQ:
+ call mct_sputi (pr_getp (TRNTABLE), sym)
+ default:
+ call sprintf (Memc[aux], SZ_LINE,
+ "pr_exit: unknown symbol type [%d] for [%d] [%s]")
+ call pargi (type)
+ call pargi (sym)
+ call pargstr (Memc[pr_xgetname (sym)])
+ call error (0, Memc[aux])
+ }
+
+ # Advance to next SYMTAB symbol.
+ symtab = stnext (pr_getp (SYMTABLE), symtab)
+ }
+
+ # Check for input, error, and weight column duplications.
+ call pr_excol (pr_getp (CATTABLE))
+ call pr_excol (pr_getp (OBSTABLE))
+
+ # Check transfomation equation deltas and derivatives.
+ do i1 = 1, mct_nrows (pr_getp (TRNTABLE)) {
+
+ # Get equation symbol.
+ sym = mct_geti (pr_getp (TRNTABLE), i1, 1)
+
+ # Get number of parameters.
+ npar = pr_gsymi (sym, PTEQNPAR)
+
+ # Check if there are deltas and derivatives defined for the
+ # current equation. The code has been modified so that there
+ # will always be a defined PFITDELTA.
+
+ derflag = false
+ dltflag = false
+ do i2 = 1, npar {
+ der = pr_gderp (sym, i2, PTEQRPNDER)
+ if (der != NULL)
+ derflag = true
+ par = pr_gpari (sym, i2, PTEQPAR)
+ if (IS_INDEFI (par))
+ next
+ if (IS_INDEFR (pr_gsymr (par, PFITDELTA))) {
+ call pr_psymr (par, PFITDELTA, DEF_PFITDELTA)
+ } else if (der != NULL) {
+ call sprintf (Memc[aux], SZ_LINE,
+ "Parameter delta and derivative defined for [%s] in equation [%s]")
+ call pargstr (Memc[pr_xgetname (par)])
+ call pargstr (Memc[pr_xgetname (sym)])
+ call pr_error (Memc[aux], PERR_WARNING)
+ }
+ dltflag = true
+ }
+
+ # Continue with next equation if no deltas or derivatives are
+ # defined. This error check should now never be tripped since the
+ # code has been modified so that dltflag is always true.
+
+ if (! (derflag || dltflag) && (npar > 0)) {
+ call sprintf (Memc[aux], SZ_LINE,
+ "No parameter deltas or derivatives defined for equation [%s]")
+ call pargstr (Memc[pr_xgetname (sym)])
+ call pr_error (Memc[aux], PERR_POSTPROC)
+ next
+ }
+
+ # Loop over all fitting parameters of the equation.
+ # Comment out this code since there are now reasonable defaults
+ # and eventually delete.
+
+ #do i2 = 1, npar {
+
+ # Get parameter offset, parameter delta, and derivative
+ # code pointer. Skip parameters that are not used in
+ # the equation.
+
+ #par = pr_gpari (sym, i2, PTEQPAR)
+ #if (IS_INDEFI (par))
+ #next
+ #delta = pr_gsymr (par, PFITDELTA)
+ #der = pr_gderp (sym, i2, PTEQRPNDER)
+
+ # Check for exclusion between deltas and derivatives,
+ # missing derivative equations, and missing deltas.
+
+ #if (!IS_INDEFR (delta) && der != NULL) {
+ #call sprintf (Memc[aux], SZ_LINE,
+ #"Parameter delta and derivative defined for [%s] in equation [%s]")
+ #call pargstr (Memc[pr_xgetname (par)])
+ #call pargstr (Memc[pr_xgetname (sym)])
+ #call pr_error (Memc[aux], PERR_POSTPROC)
+ #} else if (der == NULL && derflag) {
+ #call sprintf (Memc[aux], SZ_LINE,
+ #"Missing derivative for parameter [%s] in equation [%s]")
+ #call pargstr (Memc[pr_xgetname (par)])
+ #call pargstr (Memc[pr_xgetname (sym)])
+ #call pr_error (Memc[aux], PERR_POSTPROC)
+ #} else if (IS_INDEFR (delta) && dltflag) {
+ #call sprintf (Memc[aux], SZ_LINE,
+ #"Missing delta for parameter [%s] in equation [%s]")
+ #call pargstr (Memc[pr_xgetname (par)])
+ #call pargstr (Memc[pr_xgetname (sym)])
+ #call pr_error (Memc[aux], PERR_POSTPROC)
+ #}
+ #}
+ }
+
+ # Debug ?
+ #if (clgetb ("debug.parcode"))
+ #call eprintf ("pr_exit.out\n")
+
+ call sfree (sp)
+end
+
+
+# PR_EXCOL -- Check for input variable column duplications.
+
+procedure pr_excol (table)
+
+pointer table # table pointer
+
+int i1, i2, sym1, sym2, col1, col2, errcol1, errcol2, wtscol1, wtscol2
+pointer sp, aux
+int mct_nrows(), mct_geti(), pr_gsymi()
+pointer pr_xgetname()
+
+begin
+ call smark (sp)
+ call salloc (aux, SZ_LINE, TY_CHAR)
+
+ do i1 = 1, mct_nrows (table) - 1 {
+
+ # Get first symbol columns.
+ sym1 = mct_geti (table, i1, 1)
+ col1 = pr_gsymi (sym1, PINPCOL)
+ errcol1 = pr_gsymi (sym1, PINPERRCOL)
+ wtscol1 = pr_gsymi (sym1, PINPWTSCOL)
+
+ # Skip spare variable.
+ if (pr_gsymi (sym1, PINPSPARE) == YES)
+ next
+
+ # Check the first symbol against itself.
+ if ((!IS_INDEFI (errcol1) && (col1 == errcol1)) ||
+ (!IS_INDEFI (wtscol1) && (col1 == wtscol1)) ||
+ (!IS_INDEFI (errcol1) && !IS_INDEFI (wtscol1) &&
+ (errcol1 == wtscol1))) {
+ call sprintf (Memc[aux], SZ_LINE,
+ "Duplicate column for input variable [%s]")
+ call pargstr (Memc[pr_xgetname (sym1)])
+ call pr_error (Memc[aux], PERR_WARNING)
+ }
+
+ # Compare the first symbol against all others in the table.
+ do i2 = i1 + 1, mct_nrows (table) {
+
+ # Get second symbol columns.
+ sym2 = mct_geti (table, i2, 1)
+ col2 = pr_gsymi (sym2, PINPCOL)
+ errcol2 = pr_gsymi (sym2, PINPERRCOL)
+ wtscol2 = pr_gsymi (sym2, PINPWTSCOL)
+
+ # Skip spare variable.
+ if (pr_gsymi (sym2, PINPSPARE) == YES)
+ next
+
+ # Check first symbol against the second symbol.
+ if ((col1 == col2) ||
+ #(!IS_INDEFI (errcol2) && (col1 == errcol2)) ||
+ #(!IS_INDEFI (wtscol2) && (col1 == wtscol2)) ||
+ #(!IS_INDEFI (errcol1) && (col2 == errcol1)) ||
+ #(!IS_INDEFI (wtscol1) && (col2 == wtscol1)) ||
+ (!IS_INDEFI (errcol1) && !IS_INDEFI (errcol2) &&
+ (errcol1 == errcol2)) ||
+ (!IS_INDEFI (wtscol1) && !IS_INDEFI (wtscol2) &&
+ (wtscol1 == wtscol2)) ||
+ (!IS_INDEFI (errcol1) && !IS_INDEFI (wtscol2) &&
+ (errcol1 == wtscol2)) ||
+ (!IS_INDEFI (errcol2) && !IS_INDEFI (wtscol1) &&
+ (errcol2 == wtscol1))) {
+ call sprintf (Memc[aux], SZ_LINE,
+ "Duplicate column for input variables [%s] and [%s]")
+ call pargstr (Memc[pr_xgetname (sym1)])
+ call pargstr (Memc[pr_xgetname (sym2)])
+ call pr_error (Memc[aux], PERR_WARNING)
+ }
+ }
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/photcal/parser/prget.x b/noao/digiphot/photcal/parser/prget.x
new file mode 100644
index 00000000..aa30d2e7
--- /dev/null
+++ b/noao/digiphot/photcal/parser/prget.x
@@ -0,0 +1,928 @@
+.help prget
+Low Level Parser Retrieval
+
+These procedures retrieve parameters (attributes) from the parser, symbols,
+symbol variables, symbol derivatives, and symbol fitting parameters, stored
+in the parser common, and the parser symbol table.
+.sp
+These should be the ONLY procedures that access the parser common and symbol
+table directly, by using the macro definitions in prtable.h.
+All other procedures should try to use these procedures as the entry point to
+access any common or symbol table parameter.
+
+.nf
+Entry points:
+
+ int = pr_getsym (name) Get symbol from name
+
+ pointer = pr_xgetname (offset) Get charp. from symbol pointer
+
+ int = pr_gsym (number, type) Get symbol from number and type
+
+ value = pr_get[ip] (param) Get general integer parameter
+
+ value = pr_gsym[cirp] (offset, param) Get symbol parameter
+
+ value = pr_gvar[i] (offset, nv, param) Get variable parameter
+ value = pr_gpar[ir] (offset, np, param) Get fitting param. parameter
+ value = pr_gder[cp] (offset, nd, param) Get derivative parameter
+
+.fi
+.endhelp
+
+include "../lib/parser.h"
+include "../lib/prstruct.h"
+
+
+# PR_GETSYM -- Get symbol offset from symbol name.
+
+int procedure pr_getsym (name)
+
+char name[ARB] # symbol name
+
+include "parser.com"
+
+int pr_offset()
+pointer stfind()
+
+begin
+ # Return symbol pointer
+ return (pr_offset (stfind (symtable, name)))
+end
+
+
+# PR_XGETNAME -- Get symbol character pointer from symbol offset. The 'X'
+# is necessary to remove a system library symbol collision.
+
+pointer procedure pr_xgetname (offset)
+
+pointer offset # symbol offset
+
+pointer sym
+
+include "parser.com"
+
+pointer stname()
+pointer pr_pointer()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym != NULL)
+ return (stname (symtable, sym))
+ else
+ return (NULL)
+end
+
+
+# PR_GSYM -- Get symbol by number, and type.
+
+int procedure pr_gsym (number, type)
+
+int number # quantity number
+int type # type
+
+int aux
+
+include "parser.com"
+
+int mct_nrows()
+int mct_geti()
+
+begin
+ # Brach on parameter type
+ switch (type) {
+ case PTY_OBSVAR:
+ aux = mct_nrows (obstable) - number + 1
+ return (mct_geti (obstable, aux, 1))
+
+ case PTY_CATVAR:
+ aux = mct_nrows (cattable) - number + 1
+ return (mct_geti (cattable, aux, 1))
+
+ case PTY_FITPAR, PTY_CONST:
+ aux = mct_nrows (partable) - number + 1
+ return (mct_geti (partable, aux, 1))
+
+ case PTY_SETEQ:
+ aux = mct_nrows (settable) - number + 1
+ return (mct_geti (settable, aux, 1))
+
+ case PTY_EXTEQ:
+ aux = mct_nrows (exttable) - number + 1
+ return (mct_geti (exttable, aux, 1))
+
+ case PTY_TRNEQ:
+ aux = mct_nrows (trntable) - number + 1
+ return (mct_geti (trntable, aux, 1))
+
+ default:
+ call error (type, "pr_gsym: Unknown parameter")
+ }
+end
+
+
+# PR_GETI -- Get parser integer parameter.
+
+int procedure pr_geti (param)
+
+int param # parameter
+
+include "parser.com"
+
+begin
+ # Brach on parameter type
+ switch (param) {
+ case NERRORS:
+ return (nerrors)
+
+ case NWARNINGS:
+ return (nwarnings)
+
+ case NOBSVARS:
+ return (nobsvars)
+
+ case NCATVARS:
+ return (ncatvars)
+
+ case NFITPARS:
+ return (nfitpars)
+
+ case NTOTPARS:
+ return (ntotpars)
+
+ case NSETEQS:
+ return (nseteqs)
+
+ case NEXTEQS:
+ return (nexteqs)
+
+ case NTRNEQS:
+ return (ntrneqs)
+
+ case MINCOL:
+ return (mincol)
+
+ case MINOBSCOL:
+ return (minobscol)
+
+ case MAXOBSCOL:
+ return (maxobscol)
+
+ case MINCATCOL:
+ return (mincatcol)
+
+ case MAXCATCOL:
+ return (maxcatcol)
+
+ case FLAGEQSECT:
+ return (flageqsect)
+
+ case FLAGERRORS:
+ return (flagerrors)
+
+ default:
+ call error (param, "pr_geti: Unknown parameter")
+ }
+end
+
+
+# PR_GETP -- Get parser pointer parameter.
+
+pointer procedure pr_getp (param)
+
+int param # parameter
+
+include "parser.com"
+
+begin
+ # Brach on parameter type
+ switch (param) {
+ case SYMTABLE:
+ return (symtable)
+
+ case OBSTABLE:
+ return (obstable)
+
+ case CATTABLE:
+ return (cattable)
+
+ case PARTABLE:
+ return (partable)
+
+ case SETTABLE:
+ return (settable)
+
+ case EXTTABLE:
+ return (exttable)
+
+ case TRNTABLE:
+ return (trntable)
+
+ case TRCATTABLE:
+ return (trcattable)
+
+ case TROBSTABLE:
+ return (trobstable)
+
+ case TFCATTABLE:
+ return (tfcattable)
+
+ case TFOBSTABLE:
+ return (tfobstable)
+
+ case TPARTABLE:
+ return (tpartable)
+
+ default:
+ call error (param, "pr_getp: Unknown parameter")
+ }
+end
+
+
+# PR_GSYMC -- Get symbol character pointer parameter.
+
+pointer procedure pr_gsymc (offset, param)
+
+int offset # symbol offset
+int param # parameter
+
+pointer sym
+
+pointer pr_pointer(), pr_charp()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_gsymc: Null symbol pointer")
+
+ # Brach on parameter type
+ switch (param) {
+ case PSEQEQ:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PSEQ_EQ (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PSEQEQ)")
+
+ case PSEQERROR:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PSEQ_ERROR (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PSEQERROR)")
+
+ case PSEQERRMIN:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PSEQ_ERRMIN (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PSEQERRMIN)")
+
+ case PSEQERRMAX:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PSEQ_ERRMAX (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PSEQERRMAX)")
+
+ case PSEQWEIGHT:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PSEQ_WEIGHT (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PSEQWEIGHT)")
+
+ case PSEQWTSMIN:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PSEQ_WTSMIN (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PSEQWTSMIN)")
+
+ case PSEQWTSMAX:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PSEQ_WTSMAX (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PSEQWTSMAX)")
+
+ case PTEQFIT:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PTEQ_FIT (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PTEQFIT)")
+
+ case PTEQREF:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PTEQ_REF (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PTEQREF)")
+
+ case PTEQERROR:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PTEQ_ERROR (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PTEQERROR)")
+
+ case PTEQERRMIN:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PTEQ_ERRMIN (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PTEQERRMIN)")
+
+ case PTEQERRMAX:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PTEQ_ERRMAX (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PTEQERRMAX)")
+
+ case PTEQWEIGHT:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PTEQ_WEIGHT (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PTEQWEIGHT)")
+
+ case PTEQWTSMIN:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PTEQ_WTSMIN (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PTEQWTSMIN)")
+
+ case PTEQWTSMAX:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PTEQ_WTSMAX (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PTEQWTSMAX)")
+
+ case PTEQXPLOT:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PTEQ_XPLOT (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PTEQXPLOT)")
+
+ case PTEQYPLOT:
+ if (PSYM_SUB (sym) != NULL)
+ return (pr_charp (PTEQ_YPLOT (PSYM_SUB (sym))))
+ else
+ call error (0, "pr_gsymc: Null equation pointer (PTEQYPLOT)")
+
+ default:
+ call error (param, "pr_gsymc: Unknown parameter")
+ }
+end
+
+
+# PR_GSYMI -- Get symbol integer parameter.
+
+int procedure pr_gsymi (offset, param)
+
+int offset # symbol offset
+int param # parameter
+
+pointer sym
+
+pointer pr_pointer()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_gsymi: Null symbol offset")
+
+ # Brach on parameter type
+ switch (param) {
+ case PSYMTYPE:
+ return (PSYM_TYPE (sym))
+
+ case PSYMNUM:
+ return (PSYM_NUM (sym))
+
+ case PINPCOL:
+ if (PSYM_SUB (sym) != NULL)
+ return (PINP_COL (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymi: Null equation pointer (PINPCOL)")
+
+ case PINPERRCOL:
+ if (PSYM_SUB (sym) != NULL)
+ return (PINP_ERRCOL (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymi: Null equation pointer (PINPERRCOL)")
+
+ case PINPWTSCOL:
+ if (PSYM_SUB (sym) != NULL)
+ return (PINP_WTSCOL (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymi: Null equation pointer (PINPWTSCOL)")
+
+ case PINPSPARE:
+ if (PSYM_SUB (sym) != NULL)
+ return (PINP_SPARE (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymi: Null equation pointer (PINPSPARE)")
+
+ case PTEQNRCAT:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_NRCAT (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymi: Null equation pointer (PTEQNRCAT)")
+
+ case PTEQNROBS:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_NROBS (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymi: Null equation pointer (PTEQNROBS)")
+
+ case PTEQNRVAR:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_NRVAR (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymi: Null equation pointer (PTEQNRVAR)")
+
+ case PTEQNFCAT:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_NFCAT (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymi: Null equation pointer (PTEQNFCAT)")
+
+ case PTEQNFOBS:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_NFOBS (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymi: Null equation pointer (PTEQNFOBS)")
+
+ case PTEQNFVAR:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_NFVAR (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymi: Null equation pointer (PTEQNFVAR)")
+
+ case PTEQNVAR:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_NVAR (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymi: Null equation pointer (PTEQNVAR)")
+
+ case PTEQNPAR:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_NPAR (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymi: Null equation pointer (PTEQNPAR)")
+
+ case PTEQNFPAR:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_NFPAR (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymi: Null equation pointer (PTEQNFPAR)")
+
+ default:
+ call error (param, "pr_gsymi: Unknown parameter")
+ }
+end
+
+
+# PR_GSYMR -- Get symbol real parameter.
+
+real procedure pr_gsymr (offset, param)
+
+pointer offset # symbol offset
+int param # parameter
+
+pointer sym
+
+pointer pr_pointer()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_gsymr: Null symbol pointer")
+
+ # Brach on parameter type
+ switch (param) {
+ case PFITVALUE:
+ if (PSYM_SUB (sym) != NULL)
+ return (PFIT_VALUE (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymr: Null equation pointer (PFITVALUE)")
+
+ case PFITDELTA:
+ if (PSYM_SUB (sym) != NULL)
+ return (PFIT_DELTA (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymr: Null equation pointer (PFITDELTA)")
+
+ default:
+ call error (param, "pr_gsymr: Unknown parameter")
+ }
+end
+
+
+# PR_GSYMP -- Get symbol pointer parameter.
+
+pointer procedure pr_gsymp (offset, param)
+
+int offset # symbol offset
+int param # parameter
+
+pointer sym
+
+pointer pr_pointer()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_gsymp: Null symbol pointer")
+
+ # Brach on parameter type
+ switch (param) {
+ case PSYMSUB:
+ return (PSYM_SUB (sym))
+
+ case PSEQRPNEQ:
+ if (PSYM_SUB (sym) != NULL)
+ return (PSEQ_RPNEQ (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymp: Null equation pointer (PSEQRPNEQ)")
+
+ case PSEQRPNERROR:
+ if (PSYM_SUB (sym) != NULL)
+ return (PSEQ_RPNERROR (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymp: Null equation pointer (PSEQRPNERROR)")
+
+ case PSEQRPNERRMIN:
+ if (PSYM_SUB (sym) != NULL)
+ return (PSEQ_RPNERRMIN (PSYM_SUB (sym)))
+ else
+ call error (0,
+ "pr_gsymp: Null equation pointer (PSEQRPNERRMIN)")
+
+ case PSEQRPNERRMAX:
+ if (PSYM_SUB (sym) != NULL)
+ return (PSEQ_RPNERRMAX (PSYM_SUB (sym)))
+ else
+ call error (0,
+ "pr_gsymp: Null equation pointer (PSEQRPNERRMAX)")
+
+ case PSEQRPNWEIGHT:
+ if (PSYM_SUB (sym) != NULL)
+ return (PSEQ_RPNWEIGHT (PSYM_SUB (sym)))
+ else
+ call error (0,
+ "pr_gsymp: Null equation pointer (PSEQRPNWEIGHT)")
+
+ case PSEQRPNWTSMIN:
+ if (PSYM_SUB (sym) != NULL)
+ return (PSEQ_RPNWTSMIN (PSYM_SUB (sym)))
+ else
+ call error (0,
+ "pr_gsymp: Null equation pointer (PSEQRPNWTSMIN)")
+
+ case PSEQRPNWTSMAX:
+ if (PSYM_SUB (sym) != NULL)
+ return (PSEQ_RPNWTSMAX (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymp: Null equation pointer (PSEQRPNWTSMAX")
+
+ case PTEQRPNFIT:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_RPNFIT (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymp: Null equation pointer (PTEQRPNFIT)")
+
+ case PTEQRPNREF:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_RPNREF (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymp: Null equation pointer (PTEQRPNREF)")
+
+ case PTEQRPNERROR:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_RPNERROR (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymp: Null equation pointer (PTEQRPNERROR)")
+
+ case PTEQRPNERRMIN:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_RPNERRMIN (PSYM_SUB (sym)))
+ else
+ call error (0,
+ "pr_gsymp: Null equation pointer (PTEQRPNERRMIN)")
+
+ case PTEQRPNERRMAX:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_RPNERRMAX (PSYM_SUB (sym)))
+ else
+ call error (0,
+ "pr_gsymp: Null equation pointer (PTEQRPNERRMAX)")
+
+ case PTEQRPNWEIGHT:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_RPNWEIGHT (PSYM_SUB (sym)))
+ else
+ call error (0,
+ "pr_gsymp: Null equation pointer (PTEQRPNWEIGHT)")
+
+ case PTEQRPNWTSMIN:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_RPNWTSMIN (PSYM_SUB (sym)))
+ else
+ call error (0,
+ "pr_gsymp: Null equation pointer (PTEQRPNWTSMIN)")
+
+ case PTEQRPNWTSMAX:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_RPNWTSMAX (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymp: Null equation pointer (PTEQRPNWTSMAX")
+
+ case PTEQRPNXPLOT:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_RPNXPLOT (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymp: Null equation pointer (PTEQRPNXPLOT)")
+
+ case PTEQRPNYPLOT:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_RPNYPLOT (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymp: Null equation pointer (PTEQRPNYPLOT)")
+
+ case PTEQSREFVAR:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_SREFVAR (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymp: Null equation pointer (PTEQSREFVAR)")
+
+ case PTEQSREFCNT:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_SREFCNT (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymp: Null equation pointer (PTEQSREFCNT)")
+
+ case PTEQSFITVAR:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_SFITVAR (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymp: Null equation pointer (PTEQSFITVAR)")
+
+ case PTEQSFITCNT:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_SFITCNT (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymp: Null equation pointer (PTEQSFITCNT)")
+
+ case PTEQSPAR:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_SPAR (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymp: Null equation pointer (PTEQSPAR)")
+
+ case PTEQSPARVAL:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_SPARVAL (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymp: Null equation pointer (PTEQSPARVAL)")
+
+ case PTEQSPLIST:
+ if (PSYM_SUB (sym) != NULL)
+ return (PTEQ_SPLIST (PSYM_SUB (sym)))
+ else
+ call error (0, "pr_gsymp: Null equation pointer (PTEQSPLIST)")
+
+ default:
+ call error (param, "pr_gsymp: Unknown parameter")
+ }
+end
+
+
+# PR_GVARI -- Get variable integer parameter.
+
+int procedure pr_gvari (offset, nv, param)
+
+int offset # variable offset
+int nv # variable number
+int param # parameter
+
+pointer sym
+
+pointer pr_pointer()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_gvari: Null symbol pointer")
+
+ # Branch on parameter
+ switch (param) {
+ case PTEQREFVAR:
+ if (PSYM_SUB (sym) != NULL) {
+ if (nv >= 1 || nv <= PTEQ_NVAR (PSYM_SUB (sym)))
+ return (PTEQ_REFVAR (PSYM_SUB (sym), nv))
+ else
+ call error (0,
+ "pr_gvari: Not a valid parameter number (PTEQREFVAR)")
+ } else
+ call error (0, "pr_gvari: Null equation pointer (PTEQREFVAR)")
+
+ case PTEQREFCNT:
+ if (PSYM_SUB (sym) != NULL) {
+ if (nv >= 1 || nv <= PTEQ_NVAR (PSYM_SUB (sym)))
+ return (PTEQ_REFCNT (PSYM_SUB (sym), nv))
+ else
+ call error (0,
+ "pr_gvari: Not a valid parameter number (PTEQREFCNT)")
+ } else
+ call error (0, "pr_gvari: Null equation pointer (PTEQREFCNT)")
+
+ case PTEQFITVAR:
+ if (PSYM_SUB (sym) != NULL) {
+ if (nv >= 1 || nv <= PTEQ_NVAR (PSYM_SUB (sym)))
+ return (PTEQ_FITVAR (PSYM_SUB (sym), nv))
+ else
+ call error (0,
+ "pr_gvari: Not a valid parameter number (PTEQFITVAR)")
+ } else
+ call error (0, "pr_gvari: Null equation pointer (PTEQFITVAR)")
+
+ case PTEQFITCNT:
+ if (PSYM_SUB (sym) != NULL) {
+ if (nv >= 1 || nv <= PTEQ_NVAR (PSYM_SUB (sym)))
+ return (PTEQ_FITCNT (PSYM_SUB (sym), nv))
+ else
+ call error (0,
+ "pr_gvari: Not a valid parameter number (PTEQFITCNT)")
+ } else
+ call error (0, "pr_gvari: Null equation pointer (PTEQFITCNT)")
+
+ default:
+ call error (param, "pr_gvari: Unknown parameter")
+ }
+end
+
+
+# PR_GPARI -- Get fitting parameter integer parameter.
+
+int procedure pr_gpari (offset, np, param)
+
+int offset # symbol offset
+int np # parameter number
+int param # parameter
+
+pointer sym
+
+pointer pr_pointer()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_gpari: Null symbol pointer")
+
+ # Brach on parameter
+ switch (param) {
+ case PTEQPAR:
+ if (PSYM_SUB (sym) != NULL) {
+ if (np >= 1 || np <= PTEQ_NPAR (PSYM_SUB (sym)))
+ return (PTEQ_PAR (PSYM_SUB (sym), np))
+ else
+ call error (0, "pr_gpari: Not a valid parameter number (PTEQPAR)")
+ } else
+ call error (0, "pr_gpari: Null equation pointer (PTEQPAR)")
+
+ case PTEQPLIST:
+ if (PSYM_SUB (sym) != NULL) {
+ if (np >= 1 || np <= PTEQ_NPAR (PSYM_SUB (sym)))
+ return (PTEQ_PLIST (PSYM_SUB (sym), np))
+ else
+ call error (0, "pr_gpari: Not a valid parameter number (PTEQPLIST)")
+ } else
+ call error (0, "pr_gpari: Null equation pointer (PTEQPLIST)")
+
+ default:
+ call error (param, "pr_gpari: Unknown parameter")
+ }
+end
+
+
+# PR_GPARR -- Get fitting parameter real parameter.
+
+real procedure pr_gparr (offset, np, param)
+
+int offset # symbol offset
+int np # parameter number
+int param # parameter
+
+pointer sym
+
+pointer pr_pointer()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_gparr: Null symbol pointer")
+
+ # Brach on parameter
+ switch (param) {
+ case PTEQPARVAL:
+ if (PSYM_SUB (sym) != NULL) {
+ if (np >= 1 || np <= PTEQ_NPAR (PSYM_SUB (sym)))
+ return (PTEQ_PARVAL (PSYM_SUB (sym), np))
+ else
+ call error (0, "pr_gparr: Not a valid parameter number (PTEQPARVAL)")
+ } else
+ call error (0, "pr_gparr: Null equation pointer (PTEQPARVAL)")
+
+ default:
+ call error (param, "pr_gparr: Unknown parameter")
+ }
+end
+
+
+# PR_GDERC -- Get derivative character pointer parameter.
+
+pointer procedure pr_gderc (offset, nd, param)
+
+pointer offset # symbol offset
+int nd # derivative number
+int param # parameter
+
+pointer sym
+
+pointer pr_pointer(), pr_charp()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_gderc: Null symbol pointer")
+
+ # Branch on parameter
+ switch (param) {
+ case PTEQDER:
+ if (PSYM_SUB (sym) != NULL) {
+ if (nd >= 1 || nd <= PTEQ_NPAR (PSYM_SUB (sym)))
+ return (pr_charp (PTEQ_DER (PSYM_SUB (sym), nd)))
+ else
+ call error (0, "pr_gderc: Not a valid derivative number (PTEQDER)")
+ } else
+ call error (0, "pr_gderc: Null equation pointer (PTEQDER)")
+
+ default:
+ call error (param, "pr_gderc: Unknown parameter")
+ }
+end
+
+
+# PR_GDERP -- Get derivative pointer parameter.
+
+pointer procedure pr_gderp (offset, nd, param)
+
+int offset # symbol offset
+int nd # derivative number
+int param # parameter
+
+pointer sym
+
+pointer pr_pointer()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_gderp: Null symbol pointer")
+
+ # Branch on parameter
+ switch (param) {
+ case PTEQRPNDER:
+ if (PSYM_SUB (sym) != NULL) {
+ if (nd >= 1 || nd <= PTEQ_NPAR (PSYM_SUB (sym)))
+ return (PTEQ_RPNDER (PSYM_SUB (sym), nd))
+ else
+ call error (0, "pr_gderp: Not a valid derivative number (PTEQRPNDER)")
+ } else
+ call error (0, "pr_gderp: Null equation pointer (PTEQRPNDER)")
+
+ default:
+ call error (param, "pr_gderp: Unknown parameter")
+ }
+end
diff --git a/noao/digiphot/photcal/parser/prlexer.x b/noao/digiphot/photcal/parser/prlexer.x
new file mode 100644
index 00000000..35e6a4c7
--- /dev/null
+++ b/noao/digiphot/photcal/parser/prlexer.x
@@ -0,0 +1,337 @@
+include <ctype.h>
+include <lexnum.h>
+include "../lib/lexer.h"
+include "../lib/prtoken.h"
+
+
+# PR_LEXER - Lexical analizer for the parser of the configuration file.
+
+int procedure pr_lexer (fd, yylval)
+
+int fd # input file descriptor
+pointer yylval # YYLVAL token pointer
+
+char key[SZ_LINE]
+int tok # next token
+int ip, n
+
+include "lexer.com"
+
+bool strne()
+int ctor()
+int strdic(), strlen()
+int lexnum()
+int getline()
+
+begin
+ # Stay scanning the input file until a valid or
+ # error token is found
+ repeat {
+
+ # Skip whitespaces and blank lines
+ while (line[pos] == '\n' || IS_WHITE (line[pos])) {
+
+ # If next character is a newline count
+ # lines, and read a new line from file
+ if (line[pos] == '\n') {
+ nlines = nlines + 1
+ pos = 1
+ if (getline (fd, line) == EOF) {
+ call strcpy ("EOF", LEX_ID (yylval), SZ_LINE)
+ return (EOFILE)
+ }
+ } else
+ pos = pos + 1
+ }
+
+ # Test first valid character
+ if (IS_ALPHA (line[pos])) { # identifier or keyword
+
+ # Read identifier
+ for (ip=1; IS_ALNUM (line[pos]); ip=ip+1) {
+ id[ip] = line[pos]
+ pos = pos + 1
+ }
+ id[ip] = EOS
+
+ # Check for keyword. Abreviations of keywords are allowed
+ # to up to a certain number of characters, but the
+ # identifier returned by the lexer should contain the full
+ # keyword name.
+
+ n = strdic (id, key, SZ_LINE, KEYWORDS)
+ if (n > 0 && strlen (id) >= ABBREVIATE) {
+ call strcpy (key, id, SZ_LINE)
+ switch (n) {
+ case K_CATALOG:
+ tok = CATSECT
+ break
+ case K_OBSERVATION:
+ tok = OBSSECT
+ break
+ case K_EXTINCTION:
+ tok = EXTSECT
+ break
+ case K_TRANSFORMATION:
+ tok = TRNSECT
+ break
+ case K_FIT:
+ tok = FITID
+ break
+ case K_CONSTANT:
+ tok = CONSTID
+ break
+ case K_DELTA:
+ tok = DELTAID
+ break
+ case K_ERROR:
+ tok = ERRORID
+ break
+ case K_WEIGHT:
+ tok = WEIGHTID
+ break
+ case K_MIN:
+ tok = MINID
+ break
+ case K_MAX:
+ tok = MAXID
+ break
+ case K_SET:
+ tok = SETID
+ break
+ case K_DERIVATIVE:
+ tok = DERIVID
+ break
+ case K_PLOT:
+ tok = PLOTID
+ break
+ default:
+ call error (0, "pr_lexxer: Unknown keyword token")
+ }
+ }
+
+ # Check for function. Anything abbreviated,
+ # or not matching is and identifier.
+
+ n = strdic (id, key, SZ_LINE, FUNCTIONS)
+ if (n == 0) {
+ tok = IDENTIFIER
+ break
+ } else if (strne (id, key)) {
+ tok = IDENTIFIER
+ break
+ }
+ switch (n) {
+ case K_ABS: # absolute value
+ tok = F_ABS
+ break
+ case K_ACOS: # arc cosine
+ tok = F_ACOS
+ break
+ case K_ASIN: # arc sine
+ tok = F_ASIN
+ break
+ case K_ATAN: # arc tangent
+ tok = F_ATAN
+ break
+ case K_COS: # cosine
+ tok = F_COS
+ break
+ case K_EXP: # exponential
+ tok = F_EXP
+ break
+ case K_LOG: # natural logarithm
+ tok = F_LOG
+ break
+ case K_LOG10: # decimal logarithm
+ tok = F_LOG10
+ break
+ case K_SIN: # sine
+ tok = F_SIN
+ break
+ case K_SQRT: # square root
+ tok = F_SQRT
+ break
+ case K_TAN: # tangent
+ tok = F_TAN
+ break
+ default:
+ call error (0, "pr_lexer: Unknown identifier")
+ }
+
+ } else if (IS_DIGIT (line[pos]) || line[pos] == '.') { # number
+
+ # Process number
+ switch (lexnum (line, pos, n)) {
+ case LEX_DECIMAL:
+ tok = INUMBER
+ case LEX_REAL:
+ tok = RNUMBER
+ default:
+ tok = ERR
+ }
+
+ # Copy whatever was processed
+ # to the identifier
+ do ip = 1, n
+ id[ip] = line[pos + ip - 1]
+ id[n + 1] = EOS
+
+ # Advance to next token and
+ # break the loop
+ pos = pos + n
+ break
+
+ } else if (line[pos] == '(') { # left parenthesis
+
+ # Copy input character to identifier, set
+ # token, and advance to next character before
+ # breaking the loop
+ call strcpy ("(", id, SZ_LINE)
+ tok = LPAR
+ pos = pos + 1
+ break
+
+ } else if (line[pos] == ')') { # right parenthesis
+
+ # Copy input character to identifier, set
+ # token, and advance to next character before
+ # breaking the loop
+ call strcpy (")", id, SZ_LINE)
+ tok = RPAR
+ pos = pos + 1
+ break
+
+ } else if (line[pos] == '+') { # plus
+
+ # Copy input character to identifier, set
+ # token, and advance to next character before
+ # breaking the loop
+ call strcpy ("+", id, SZ_LINE)
+ tok = PLUS
+ pos = pos + 1
+ break
+
+ } else if (line[pos] == '-') { # minus
+
+ # Copy input character to identifier, set
+ # token, and advance to next character before
+ # breaking the loop
+ call strcpy ("-", id, SZ_LINE)
+ tok = MINUS
+ pos = pos + 1
+ break
+
+ } else if (line[pos] == '*') { # star and double star
+
+ # Advance to next character to see if
+ # it's another star
+ pos = pos + 1
+ if (line[pos] == '*') {
+
+ # Copy input character to identifier, set
+ # token, and advance to next character before
+ # breaking the loop
+ call strcpy ("**", id, SZ_LINE)
+ tok = EXPON
+ pos = pos + 1
+ break
+
+ } else {
+
+ # Copy input characters to identifier, set
+ # token, and break the loop
+ call strcpy ("*", id, SZ_LINE)
+ tok = STAR
+ break
+ }
+
+ } else if (line[pos] == '/') { # slash
+
+ # Copy input character to identifier, set
+ # token, and advance to next character before
+ # breaking the loop
+ call strcpy ("/", id, SZ_LINE)
+ tok = SLASH
+ pos = pos + 1
+ break
+
+ } else if (line[pos] == '=') { # equal
+
+ # Copy input character to identifier, set
+ # token, and advance to next character before
+ # breaking the loop
+ call strcpy ("=", id, SZ_LINE)
+ tok = EQUAL
+ pos = pos + 1
+ break
+
+ } else if (line[pos] == ',') { # comma
+
+ # Copy input character to identifier, set
+ # token, and advance to next character before
+ # breaking the loop
+ call strcpy (",", id, SZ_LINE)
+ tok = COMMA
+ pos = pos + 1
+ break
+
+ } else if (line[pos] == ':') { # colon
+
+ # Copy input character to identifier, set
+ # token, and advance to next character before
+ # breaking the loop
+ call strcpy (":", id, SZ_LINE)
+ tok = COLON
+ pos = pos + 1
+ break
+
+ } else if (line[pos] == ';') { # semicolon
+
+ # Copy input character to identifier, set
+ # token, and advance to next character before
+ # breaking the loop
+ call strcpy (";", id, SZ_LINE)
+ tok = SEMICOLON
+ pos = pos + 1
+ break
+
+ } else if (line[pos] == '#') { # comment
+
+ # Skip current line
+ pos = strlen (line)
+
+ } else { # none of the above
+
+ # All characters not included in the previous
+ # categories are treated as errors
+ id[1] = line[pos]
+ id[2] = EOS
+ tok = ERR
+
+ # Advance to next character before
+ # breaking the loop
+ pos = pos + 1
+ break
+ }
+
+ } # repeat
+
+ # Update yylval structure
+ LEX_TOK (yylval) = tok
+ call strcpy (id, LEX_ID (yylval), SZ_LINE)
+ if (tok == INUMBER || tok == RNUMBER) {
+ ip = 1
+ n = ctor (LEX_ID (yylval), ip, LEX_VAL (yylval))
+ } else
+ LEX_VAL (yylval) = INDEFR
+
+ # Debug
+ #call eprintf ("(tok=%d) (id=%s) (rval=%g)\n")
+ #call pargi (LEX_TOK (yylval))
+ #call pargstr (LEX_ID (yylval))
+ #call pargi (LEX_VAL (yylval))
+
+ # Return token value
+ return (tok)
+end
diff --git a/noao/digiphot/photcal/parser/prmap.x b/noao/digiphot/photcal/parser/prmap.x
new file mode 100644
index 00000000..587769e4
--- /dev/null
+++ b/noao/digiphot/photcal/parser/prmap.x
@@ -0,0 +1,200 @@
+.help prmap
+Column/variable mapping.
+
+These procedures map input column numbers, specified in the configuration
+file, with variable numbers that are used to index information in memory
+tables. Variable numbers are assigned internally by the parser.
+.sp
+The main goal of these routines is to provide a fast way of converting from
+column number to a variable number, if any, since this kind of operation is
+performed by the i/o routines for eavery column in all lines in each input
+file.
+.sp
+First the calling program should map columns with variables in the catalog
+or observation section of the configuration file, by using either pr_obsmap()
+or pr_catmap(). Once the mapping is built the corresponding variable number
+for a given column can be obtained with pr_findmap(). All memory allocated
+by these procedures is free by calling pr_unmap().
+.nf
+
+Main entry points:
+
+ pr_obsmap (table, nobs) Build observational variables map
+ pr_catmap (table, ncat) Build catalog variables map
+int pr_findmap (table, col, nums, max_nums) Find var numbers for given column
+int pr_findmap1 (table, col) Find first var number for given column
+ pr_unmap (table) Free space of mapped variables
+
+Low level entry points:
+
+ pr_inmap (table, nvars, type) Map observational/catalog var.
+.endhelp
+
+include "../lib/parser.h"
+include "../lib/prdefs.h"
+
+# Table structure
+define LEN_TABLE 5 # fixed section length
+define TABLE_MIN Memi[$1+0] # minimum column number
+define TABLE_MAX Memi[$1+1] # maximum column number
+define TABLE_NVARS Memi[$1+2] # number of variables
+define TABLE_PCOLS Memi[$1+3] # pointer to column indices
+define TABLE_PNCOLS Memi[$1+4] # pointer to column indices count
+
+
+# PR_OBSTAB -- Map program observational input variables.
+
+procedure pr_obsmap (table, nobs)
+
+pointer table # table pointer (output)
+int nobs # number of observational variables (output)
+
+begin
+ # Tabulate the observational variables.
+ call pr_inmap (table, nobs, PTY_OBSVAR)
+end
+
+
+# PR_CATTAB -- Map catalog star input variables.
+
+procedure pr_catmap (table, ncat)
+
+pointer table # table pointer (output)
+int ncat # number of catalog variables (output)
+
+begin
+ # Tabulate the catalog variables.
+ call pr_inmap (table, ncat, PTY_CATVAR)
+end
+
+
+# PR_INMAP -- Map input variables from the sequential variable table, and
+# build a table with this mapping. A pointer to the map table is returned,
+# for future use by pr_findmap().
+
+procedure pr_inmap (table, nvars, type)
+
+pointer table # table pointer (output)
+int nvars # number of variables (output)
+int type # symbol type
+
+int i, mincol, maxcol, sym, col
+pointer pcols, pncols, colptr
+int pr_geti(), pr_gsym(), pr_gsymi()
+
+begin
+ # Get the sequential table pointer for the symbol type, and the
+ # maximum and minimum number of columns
+ if (type == PTY_OBSVAR) {
+ nvars = pr_geti (NOBSVARS)
+ mincol = pr_geti (MINOBSCOL)
+ maxcol = pr_geti (MAXOBSCOL)
+ } else if (type == PTY_CATVAR) {
+ nvars = pr_geti (NCATVARS)
+ mincol = pr_geti (MINCATCOL)
+ maxcol = pr_geti (MAXCATCOL)
+ } else
+ call error (0, "pr_inmap: Illegal symbol type")
+
+ # Allocate the basic table structure.
+ call malloc (table, LEN_TABLE, TY_STRUCT)
+ TABLE_MIN (table) = mincol
+ TABLE_MAX (table) = maxcol
+ TABLE_NVARS (table) = nvars
+
+ # Initialize.
+ call malloc (pcols, maxcol * nvars, TY_INT)
+ call amovki (INDEFI, Memi[pcols], maxcol * nvars)
+ call calloc (pncols, maxcol, TY_INT)
+
+ # Traverse symbols and store variable number at the corresponding
+ # table location indexed by column number. There may be more than
+ # one symbol per column number.
+
+ do i = 1, nvars {
+ sym = pr_gsym (i, type)
+ col = pr_gsymi (sym, PINPCOL)
+ colptr = pcols + (col - 1) * nvars + Memi[pncols+col-1]
+ Memi[colptr] = pr_gsymi (sym, PSYMNUM)
+ Memi[pncols+col-1] = Memi[pncols+col-1] + 1
+ }
+
+ TABLE_PCOLS(table) = pcols
+ TABLE_PNCOLS(table) = pncols
+end
+
+
+# PR_FINDMAP -- Find the list of symbol numbers for a given input column.
+
+int procedure pr_findmap (table, col, indices, max_nindices)
+
+pointer table # table pointer
+int col # input column
+int indices[ARB] # output array of indices
+int max_nindices # maximum permitted number of indices
+
+int nvars, nindices
+pointer colptr
+
+begin
+ # Check pointer.
+ if (table == NULL)
+ call error (0, "pr_findmap: Null table pointer")
+
+ # Check the table size.
+ nvars = TABLE_NVARS(table)
+ if (max_nindices < nvars)
+ call error (0, "pr_findmap: The output index array is too short")
+
+ # Look for variable number.
+ if (col < TABLE_MIN (table) || col > TABLE_MAX (table)) {
+ nindices = 0
+ call amovki (INDEFI, indices, nvars)
+ } else {
+ nindices = Memi[TABLE_PNCOLS(table)+col-1]
+ colptr = TABLE_PCOLS(table) + (col - 1) * nvars
+ call amovi (Memi[colptr], indices, nindices)
+ }
+
+ return (nindices)
+end
+
+
+# PR_FINDMAP1 -- Find the symbol number for a given input column.
+
+int procedure pr_findmap1 (table, col)
+
+pointer table # table pointer
+int col # input column
+
+begin
+ # Check pointer.
+ if (table == NULL)
+ call error (0, "pr_findmap: Null table pointer")
+
+ # Look for variable number.
+ if (col < TABLE_MIN (table) || col > TABLE_MAX (table))
+ return (INDEFI)
+ else
+ return (Memi[TABLE_PCOLS(table)+(col-1)*TABLE_NVARS(table)])
+end
+
+
+# PR_UNMAP -- Free space of mapped variables.
+
+procedure pr_unmap (table)
+
+pointer table # table pointer
+
+begin
+ # Check pointer.
+ if (table == NULL)
+ call error (0, "pr_unmap: Null table pointer")
+
+ # Free pointer table.
+ call mfree (TABLE_PCOLS(table), TY_INT)
+ call mfree (TABLE_PNCOLS(table), TY_INT)
+
+ # Free table structure.
+ call mfree (table, TY_INT)
+end
diff --git a/noao/digiphot/photcal/parser/prparse.x b/noao/digiphot/photcal/parser/prparse.x
new file mode 100644
index 00000000..a829ce85
--- /dev/null
+++ b/noao/digiphot/photcal/parser/prparse.x
@@ -0,0 +1,102 @@
+include "../lib/parser.h"
+include "../lib/prdefs.h"
+
+
+# PR_PARSE - Parser driver routine for the parser generated by xyacc. This
+# procedure opens the configuration file, and call the parser generated by
+# xyacc. It returns ERR if errors are found in the configuration file, and
+# OK for no errors. All tables allocated by this procedure MUST be freed
+# by the calling program if there are no errors. Otherwise they are freed
+# before exiting the procedure.
+
+int procedure pr_parse (fname)
+
+char fname[ARB] # solution file name
+
+int fd # input file descriptor
+
+include "lexer.com"
+
+extern pr_lexer()
+int open(), parse(), pr_geti()
+#pointer pr_getp()
+
+begin
+ # Open the input file.
+ if (fname[1] == EOS)
+ call error (0, "ERROR: The configuration file is undefined")
+ else
+ fd = open (fname, READ_ONLY, TEXT_FILE)
+
+ # Initialize the lexer common variables.
+ nlines = 0
+ pos = 1
+ call strcpy ("\n", line, SZ_LINE)
+ call strcpy ("", id, SZ_LINE)
+
+ # Allocate space for parser symbol tables, and code generation table.
+ call pr_alloc ()
+ call pr_calloc ()
+
+ # Initialize the counters.
+ call pr_puti (NERRORS, 0)
+ call pr_puti (NWARNINGS, 0)
+ call pr_puti (NOBSVARS, 0)
+ call pr_puti (NCATVARS, 0)
+ call pr_puti (NFITPARS, 0)
+ call pr_puti (NTOTPARS, 0)
+ call pr_puti (NSETEQS, 0)
+ call pr_puti (NEXTEQS, 0)
+ call pr_puti (NTRNEQS, 0)
+
+ # Initialize the flags.
+ call pr_puti (FLAGERRORS, YES)
+
+ # Initialize the minimum and maximum column values.
+ call pr_puti (MINCOL, 1)
+ call pr_puti (MINOBSCOL, INDEFI)
+ call pr_puti (MINCATCOL, INDEFI)
+ call pr_puti (MAXOBSCOL, INDEFI)
+ call pr_puti (MAXCATCOL, INDEFI)
+
+ # Parse the input stream. Syntax errors are flaged by an ERR parse()
+ # value. Semantic errors are not detected by the parser, but instead
+ # by the symbol table procedures. The latter, do not raise an error
+ # condition, but they send error messages to the standard output if
+ # the FLAGERR flag is set to YES.
+
+ if (parse (fd, false, pr_lexer) == ERR)
+ call pr_error ("Cannot continue parsing", PERR_SYNTAX)
+
+ # Debug ?
+ #call dg_prvdump ("From pr_parse before pr_exit")
+ #call dg_prtdump ("From pr_parse before pr_exit", pr_getp (SYMTABLE))
+
+ # Check consistency of the symbol table only if there
+ # are no errors during the parse. This check may give
+ # some errors undetected during the previous parse.
+
+ if (pr_geti (NERRORS) == 0)
+ call pr_exit ()
+
+ # Free code buffer and and close the input file.
+ call pr_cfree ()
+ call close (fd)
+
+ # Debug ?
+ #call dg_prvdump ("From pr_parse")
+ #call dg_prtdump ("From pr_parse", pr_getp (SYMTABLE))
+
+ # Return value. If there are errors free all the tables
+ # allocated before. Otherwise, keep all tables for later
+ # use. They MUST be freed by the calling program.
+
+ # Return the appropriate error code.
+ if (pr_geti (NERRORS) == 0) {
+ call pr_puti (FLAGERRORS, NO)
+ return (OK)
+ } else {
+ call pr_free ()
+ return (ERR)
+ }
+end
diff --git a/noao/digiphot/photcal/parser/prput.x b/noao/digiphot/photcal/parser/prput.x
new file mode 100644
index 00000000..db0afdd6
--- /dev/null
+++ b/noao/digiphot/photcal/parser/prput.x
@@ -0,0 +1,1020 @@
+.help prput
+Low Level Parser Storage
+
+These procedures store parameters (attributes) to the parser, symbols,
+symbol variables, symbol derivatives, and symbol fitting parameters, in
+the parser common, and the parser symbol table.
+.sp
+These should be the ONLY procedures that access the parser common and
+symbol table directly, by using the macro definitions in prtable.h.
+All other procedures should try to use these procedures as the entry
+point to access any common or symbol table parameter.
+
+.nf
+Entry points:
+
+ int = pr_putsym (name) Put symbol into table
+
+ pr_psym (number, type, value) Put symbol pointer by number,
+ and type
+
+ pr_put[ip] (param, value) Put general parameter
+
+ pr_inc[i] (param, value) Increment general parameter
+ pr_dec[i] (param, value) Decrement general parameter
+
+ pr_psym[cirp] (offset, param, value) Put symbol parameter
+
+ pr_pvar[i] (offset, nv, param, value) Put variable parameter
+ pr_ppar[ir] (offset, np, param, value) Put fitting parameter parameter
+ pr_pder[cp] (offset, nd, param, value) Put derivative parameter
+.fi
+.endhelp
+
+include "../lib/parser.h"
+include "../lib/prstruct.h"
+
+
+# PR_PUTSYM -- Put initialized symbol in the symbol table. Does not check
+# for prevoius existence of the identifier in the table.
+
+int procedure pr_putsym (name)
+
+char name[ARB] # identifier name
+
+int offset
+pointer sym
+
+include "parser.com"
+
+int pr_offset()
+pointer stenter()
+
+begin
+ # Enter symbol into table
+ sym = stenter (symtable, name, LEN_PSYM)
+
+ # Get symbol offset
+ offset = pr_offset (sym)
+
+ # Initialize numbers to INDEF and pointers to NULL
+ call pr_psymi (offset, PSYMTYPE, INDEFI)
+ call pr_psymi (offset, PSYMNUM, INDEFI)
+ call pr_psymp (offset, PSYMSUB, NULL)
+
+ # Return symbol offset
+ return (offset)
+end
+
+
+# PR_PSYM -- Put symbol pointer by number, and type.
+
+procedure pr_psym (number, type, value)
+
+int number # number
+int type # type
+pointer value # value
+
+int aux
+
+include "parser.com"
+
+int mct_nrows()
+
+begin
+ # Branch on parameter type
+ switch (type) {
+ case PTY_OBSVAR:
+ aux = mct_nrows (obstable) - number + 1
+ call mct_putp (obstable, aux, 1, value)
+
+ case PTY_CATVAR:
+ aux = mct_nrows (cattable) - number + 1
+ call mct_putp (cattable, aux, 1, value)
+
+ case PTY_FITPAR, PTY_CONST:
+ aux = mct_nrows (partable) - number + 1
+ #call mct_getp (partable, aux, 1, value)
+ call mct_putp (partable, aux, 1, value)
+
+ case PTY_SETEQ:
+ aux = mct_nrows (settable) - number + 1
+ call mct_putp (settable, aux, 1, value)
+
+ case PTY_EXTEQ:
+ aux = mct_nrows (exttable) - number + 1
+ call mct_putp (exttable, aux, 1, value)
+
+ case PTY_TRNEQ:
+ aux = mct_nrows (trntable) - number + 1
+ call mct_putp (trntable, aux, 1, value)
+
+ default:
+ call error (type, "pr_psym: Unknown parameter")
+ }
+end
+
+
+# PR_PUTI -- Put parser integer parameter.
+
+procedure pr_puti (param, value)
+
+int param # parameter
+int value # value
+
+include "parser.com"
+
+begin
+ # Brach on parameter type
+ switch (param) {
+ case NERRORS:
+ nerrors = value
+
+ case NWARNINGS:
+ nwarnings = value
+
+ case NOBSVARS:
+ nobsvars = value
+
+ case NCATVARS:
+ ncatvars = value
+
+ case NFITPARS:
+ nfitpars = value
+
+ case NTOTPARS:
+ ntotpars = value
+
+ case NSETEQS:
+ nseteqs = value
+
+ case NEXTEQS:
+ nexteqs = value
+
+ case NTRNEQS:
+ ntrneqs = value
+
+ case MINCOL:
+ mincol = value
+
+ case MINOBSCOL:
+ minobscol = value
+
+ case MAXOBSCOL:
+ maxobscol = value
+
+ case MINCATCOL:
+ mincatcol = value
+
+ case MAXCATCOL:
+ maxcatcol = value
+
+ case FLAGEQSECT:
+ flageqsect = value
+
+ case FLAGERRORS:
+ flagerrors = value
+
+ default:
+ call error (param, "pr_puti: Unknown parameter")
+ }
+end
+
+
+# PR_INCI -- Increment parser integer parameter.
+
+procedure pr_inci (param, value)
+
+int param # parameter
+int value # value
+
+include "parser.com"
+
+begin
+ # Brach on parameter type
+ switch (param) {
+ case NERRORS:
+ nerrors = nerrors + value
+
+ case NWARNINGS:
+ nwarnings = nwarnings + value
+
+ case NOBSVARS:
+ nobsvars = nobsvars + value
+
+ case NCATVARS:
+ ncatvars = ncatvars + value
+
+ case NFITPARS:
+ nfitpars = nfitpars + value
+
+ case NTOTPARS:
+ ntotpars = ntotpars + value
+
+ case NSETEQS:
+ nseteqs = nseteqs + value
+
+ case NEXTEQS:
+ nexteqs = nexteqs + value
+
+ case NTRNEQS:
+ ntrneqs = ntrneqs + value
+
+ case MINOBSCOL:
+ minobscol = minobscol + value
+
+ case MAXOBSCOL:
+ maxobscol = maxobscol + value
+
+ case MINCATCOL:
+ mincatcol = mincatcol + value
+
+ case MAXCATCOL:
+ maxcatcol = maxcatcol + value
+
+ default:
+ call error (param, "pr_inci: Unknown parameter")
+ }
+end
+
+
+# PR_DECI -- Decrement parser integer parameter.
+
+procedure pr_deci (param, value)
+
+int param # parameter
+int value # value
+
+include "parser.com"
+
+begin
+ # Brach on parameter type
+ switch (param) {
+ case NERRORS:
+ nerrors = nerrors - value
+
+ case NWARNINGS:
+ nwarnings = nwarnings - value
+
+ case NOBSVARS:
+ nobsvars = nobsvars - value
+
+ case NCATVARS:
+ ncatvars = ncatvars - value
+
+ case NFITPARS:
+ nfitpars = nfitpars - value
+
+ case NTOTPARS:
+ ntotpars = ntotpars - value
+
+ case NSETEQS:
+ nseteqs = nseteqs - value
+
+ case NEXTEQS:
+ nexteqs = nexteqs - value
+
+ case NTRNEQS:
+ ntrneqs = ntrneqs - value
+
+ case MINOBSCOL:
+ minobscol = minobscol - value
+
+ case MAXOBSCOL:
+ maxobscol = maxobscol - value
+
+ case MINCATCOL:
+ mincatcol = mincatcol - value
+
+ case MAXCATCOL:
+ maxcatcol = maxcatcol - value
+
+ default:
+ call error (param, "pr_deci: Unknown parameter")
+ }
+end
+
+
+# PR_PUTP -- Put parser pointer parameter.
+
+procedure pr_putp (param, value)
+
+int param # parameter
+pointer value # value
+
+include "parser.com"
+
+begin
+ # Brach on parameter type
+ switch (param) {
+ case SYMTABLE:
+ symtable = value
+
+ case OBSTABLE:
+ obstable = value
+
+ case CATTABLE:
+ cattable = value
+
+ case PARTABLE:
+ partable = value
+
+ case SETTABLE:
+ settable = value
+
+ case EXTTABLE:
+ exttable = value
+
+ case TRNTABLE:
+ trntable = value
+
+ case TRCATTABLE:
+ trcattable = value
+
+ case TROBSTABLE:
+ trobstable = value
+
+ case TFCATTABLE:
+ tfcattable = value
+
+ case TFOBSTABLE:
+ tfobstable = value
+
+ case TPARTABLE:
+ tpartable = value
+
+ default:
+ call error (param, "pr_putp: Unknown parameter")
+ }
+end
+
+
+# PR_PSYMC -- Put a symbol character string attribute.
+
+procedure pr_psymc (offset, param, value)
+
+int offset # symbol offset
+int param # parameter
+char value[ARB] # value
+
+pointer sym
+
+include "parser.com"
+
+int stpstr()
+pointer pr_pointer()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_psymc: Null symbol pointer")
+
+ # Brach on parameter type
+ switch (param) {
+ case PSEQEQ:
+ if (PSYM_SUB (sym) != NULL)
+ PSEQ_EQ (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PSEQEQ)")
+
+ case PSEQERROR:
+ if (PSYM_SUB (sym) != NULL)
+ PSEQ_ERROR (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PSEQERROR)")
+
+ case PSEQERRMIN:
+ if (PSYM_SUB (sym) != NULL)
+ PSEQ_ERRMIN (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PSEQERRMIN)")
+
+ case PSEQERRMAX:
+ if (PSYM_SUB (sym) != NULL)
+ PSEQ_ERRMAX (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PSEQERRMAX)")
+
+ case PSEQWEIGHT:
+ if (PSYM_SUB (sym) != NULL)
+ PSEQ_WEIGHT (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PSEQWEIGHT)")
+
+ case PSEQWTSMIN:
+ if (PSYM_SUB (sym) != NULL)
+ PSEQ_WTSMIN (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PSEQWTSMIN)")
+
+ case PSEQWTSMAX:
+ if (PSYM_SUB (sym) != NULL)
+ PSEQ_WTSMAX (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PSEQWTSMAX)")
+
+ case PTEQFIT:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_FIT (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PTEQFIT)")
+
+ case PTEQREF:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_REF (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PTEQREF)")
+
+ case PTEQERROR:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_ERROR (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PTEQERROR)")
+
+ case PTEQERRMIN:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_ERRMIN (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PTEQERRMIN)")
+
+ case PTEQERRMAX:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_ERRMAX (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PTEQERRMAX)")
+
+ case PTEQWEIGHT:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_WEIGHT (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PTEQWEIGHT)")
+
+ case PTEQWTSMIN:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_WTSMIN (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PTEQWTSMIN)")
+
+ case PTEQWTSMAX:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_WTSMAX (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PTEQWTSMAX)")
+
+ case PTEQXPLOT:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_XPLOT (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PTEQXPLOT)")
+
+ case PTEQYPLOT:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_YPLOT (PSYM_SUB (sym)) = stpstr (symtable, value, 0)
+ else
+ call error (0, "pr_psymc: Null equation pointer (PTEQYPLOT)")
+
+ default:
+ call error (param, "pr_psymc: Unknown parameter type")
+ }
+end
+
+
+# PR_PSYMI -- Put symbol integer parameter.
+
+procedure pr_psymi (offset, param, value)
+
+int offset # symbol offset
+int param # parameter
+int value # value
+
+pointer sym
+
+pointer pr_pointer()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_psymi: Null symbol pointer")
+
+ # Brach on parameter type
+ switch (param) {
+ case PSYMTYPE:
+ PSYM_TYPE (sym) = value
+
+ case PSYMNUM:
+ PSYM_NUM (sym) = value
+
+ case PINPCOL:
+ if (PSYM_SUB (sym) != NULL)
+ PINP_COL (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymi: Null equation pointer (PINPCOL)")
+
+ case PINPERRCOL:
+ if (PSYM_SUB (sym) != NULL)
+ PINP_ERRCOL (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymi: Null equation pointer (PINPERRCOL)")
+
+ case PINPWTSCOL:
+ if (PSYM_SUB (sym) != NULL)
+ PINP_WTSCOL (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymi: Null equation pointer (PINPWTSCOL)")
+
+ case PINPSPARE:
+ if (PSYM_SUB (sym) != NULL)
+ PINP_SPARE (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymi: Null equation pointer (PINPSPARE)")
+
+ case PTEQNRCAT:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_NRCAT (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymi: Null equation pointer (PTEQNRCAT)")
+
+ case PTEQNROBS:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_NROBS (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymi: Null equation pointer (PTEQNROBS)")
+
+ case PTEQNRVAR:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_NRVAR (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymi: Null equation pointer (PTEQNRVAR)")
+
+ case PTEQNFCAT:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_NFCAT (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymi: Null equation pointer (PTEQNFCAT)")
+
+ case PTEQNFOBS:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_NFOBS (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymi: Null equation pointer (PTEQNFOBS)")
+
+ case PTEQNFVAR:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_NFVAR (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymi: Null equation pointer (PTEQNFVAR)")
+
+ case PTEQNVAR:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_NVAR (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymi: Null equation pointer (PTEQNVAR)")
+
+ case PTEQNPAR:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_NPAR (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymi: Null equation pointer (PTEQNPAR)")
+
+ case PTEQNFPAR:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_NFPAR (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymi: Null equation pointer (PTEQNFPAR)")
+
+ default:
+ call error (param, "pr_psymi: Unknown parameter")
+ }
+end
+
+
+# PR_PSYMR -- Put symbol real parameter.
+
+procedure pr_psymr (offset, param, value)
+
+int offset # symbol offset
+int param # parameter
+real value # value
+
+pointer sym
+
+pointer pr_pointer()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_psymr: Null symbol pointer")
+
+ # Brach on parameter type
+ switch (param) {
+ case PFITVALUE:
+ if (PSYM_SUB (sym) != NULL)
+ PFIT_VALUE (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymr: Null equation pointer (PFITVALUE)")
+
+ case PFITDELTA:
+ if (PSYM_SUB (sym) != NULL)
+ PFIT_DELTA (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymr: Null equation pointer (PFITDELTA)")
+
+ default:
+ call error (param, "pr_psymr: Unknown parameter")
+ }
+end
+
+
+# PR_PSYMP -- Put symbol pointer parameter.
+
+procedure pr_psymp (offset, param, value)
+
+int offset # symbol offset
+int param # parameter
+pointer value # value
+
+pointer sym
+
+pointer pr_pointer()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_psymp: Null symbol pointer")
+
+ # Brach on parameter type
+ switch (param) {
+ case PSYMSUB:
+ PSYM_SUB (sym) = value
+
+ case PSEQRPNEQ:
+ if (PSYM_SUB (sym) != NULL)
+ PSEQ_RPNEQ (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymp: Null equation pointer (PSEQRPNEQ)")
+
+ case PSEQRPNERROR:
+ if (PSYM_SUB (sym) != NULL)
+ PSEQ_RPNERROR (PSYM_SUB (sym)) = value
+ else
+ call error (0,
+ "pr_psymp: Null equation pointer (PSEQRPNERROR)")
+
+ case PSEQRPNERRMIN:
+ if (PSYM_SUB (sym) != NULL)
+ PSEQ_RPNERRMIN (PSYM_SUB (sym)) = value
+ else
+ call error (0,
+ "pr_psymp: Null equation pointer (PSEQRPNERRMIN)")
+
+ case PSEQRPNERRMAX:
+ if (PSYM_SUB (sym) != NULL)
+ PSEQ_RPNERRMAX (PSYM_SUB (sym)) = value
+ else
+ call error (0,
+ "pr_psymp: Null equation pointer (PSEQRPNERRMAX)")
+
+ case PSEQRPNWEIGHT:
+ if (PSYM_SUB (sym) != NULL)
+ PSEQ_RPNWEIGHT (PSYM_SUB (sym)) = value
+ else
+ call error (0,
+ "pr_psymp: Null equation pointer (PSEQRPNWEIGHT")
+
+ case PSEQRPNWTSMIN:
+ if (PSYM_SUB (sym) != NULL)
+ PSEQ_RPNWTSMIN (PSYM_SUB (sym)) = value
+ else
+ call error (0,
+ "pr_psymp: Null equation pointer (PSEQRPNWTSMIN)")
+
+ case PSEQRPNWTSMAX:
+ if (PSYM_SUB (sym) != NULL)
+ PSEQ_RPNWTSMAX (PSYM_SUB (sym)) = value
+ else
+ call error (0,
+ "pr_psymp: Null equation pointer (PSEQRPNWTSMAX)")
+
+ case PTEQRPNFIT:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_RPNFIT (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymp: Null equation pointer (PTEQRPNFIT)")
+
+ case PTEQRPNREF:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_RPNREF (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymp: Null equation pointer (PTEQRPNREF)")
+
+ case PTEQRPNERROR:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_RPNERROR (PSYM_SUB (sym)) = value
+ else
+ call error (0, "pr_psymp: Null equation pointer (PTEQRPNERROR)")
+
+ case PTEQRPNERRMIN:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_RPNERRMIN (PSYM_SUB (sym)) = value
+ else
+ call error (0,
+ "pr_psymp: Null equation pointer (PTEQRPNERRMIN)")
+
+ case PTEQRPNERRMAX:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_RPNERRMAX (PSYM_SUB (sym)) = value
+ else
+ call error (0,
+ "pr_psymp: Null equation pointer (PTEQRPNERRMAX)")
+
+ case PTEQRPNWEIGHT:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_RPNWEIGHT (PSYM_SUB (sym)) = value
+ else
+ call error (0,
+ "pr_psymp: Null equation pointer (PTEQRPNWEIGHT")
+
+ case PTEQRPNWTSMIN:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_RPNWTSMIN (PSYM_SUB (sym)) = value
+ else
+ call error (0,
+ "pr_psymp: Null equation pointer (PTEQRPNWTSMIN)")
+
+ case PTEQRPNWTSMAX:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_RPNWTSMAX (PSYM_SUB (sym)) = value
+ else
+ call error (0,
+ "pr_psymp: Null equation pointer (PTEQRPNWTSMAX")
+
+ case PTEQRPNXPLOT:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_RPNXPLOT (PSYM_SUB (sym)) = value
+ else
+ call error (0,
+ "pr_psymp: Null equation pointer (PTEQRPNXPLOT)")
+
+ case PTEQRPNYPLOT:
+ if (PSYM_SUB (sym) != NULL)
+ PTEQ_RPNYPLOT (PSYM_SUB (sym)) = value
+ else
+ call error (0,
+ "pr_psymp: Null equation pointer (PTEQRPNYPLOT)")
+
+ default:
+ call error (param, "pr_psymp: Unknown parameter")
+ }
+end
+
+
+# PR_PVARI -- Put variable integer parameter.
+
+procedure pr_pvari (offset, nv, param, value)
+
+int offset # symbol offset
+int nv # variable number
+int param # parameter
+int value # value
+
+pointer sym
+
+pointer pr_pointer()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_pvari: Null symbol pointer")
+
+ # Branch on parameter
+ switch (param) {
+ case PTEQREFVAR:
+ if (PSYM_SUB (sym) != NULL) {
+ if (nv >= 1 || nv <= PTEQ_NVAR (PSYM_SUB (sym)))
+ PTEQ_REFVAR (PSYM_SUB (sym), nv) = value
+ else
+ call error (0,
+ "pr_pvari: Not a valid variable number (PTEQREFVAR)")
+ } else
+ call error (0, "pr_pvari: Null equation pointer (PTEQREFVAR)")
+
+ case PTEQREFCNT:
+ if (PSYM_SUB (sym) != NULL) {
+ if (nv >= 1 || nv <= PTEQ_NVAR (PSYM_SUB (sym)))
+ PTEQ_REFCNT (PSYM_SUB (sym), nv) = value
+ else
+ call error (0,
+ "pr_pvari: Not a valid variable number (PTEQREFCNT)")
+ } else
+ call error (0, "pr_pvari: Null equation pointer (PTEQREFCNT)")
+
+ case PTEQFITVAR:
+ if (PSYM_SUB (sym) != NULL) {
+ if (nv >= 1 || nv <= PTEQ_NVAR (PSYM_SUB (sym)))
+ PTEQ_FITVAR (PSYM_SUB (sym), nv) = value
+ else
+ call error (0,
+ "pr_pvari: Not a valid variable number (PTEQFITVAR)")
+ } else
+ call error (0, "pr_pvari: Null equation pointer (PTEQFITVAR)")
+
+ case PTEQFITCNT:
+ if (PSYM_SUB (sym) != NULL) {
+ if (nv >= 1 || nv <= PTEQ_NVAR (PSYM_SUB (sym)))
+ PTEQ_FITCNT (PSYM_SUB (sym), nv) = value
+ else
+ call error (0,
+ "pr_pvari: Not a valid variable number (PTEQFITCNT)")
+ } else
+ call error (0, "pr_pvari: Null equation pointer (PTEQFITCNT)")
+
+ default:
+ call error (param, "pr_pvari: Unknown parameter")
+ }
+end
+
+
+# PR_PPARI -- Put fitting parameter integer parameter.
+
+procedure pr_ppari (offset, np, param, value)
+
+int offset # symbol offset
+int np # parameter number
+int param # parameter
+int value # value
+
+pointer sym
+
+pointer pr_pointer()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_ppari: Null symbol pointer")
+
+ # Branch on parameter
+ switch (param) {
+ case PTEQPAR:
+ if (PSYM_SUB (sym) != NULL) {
+ if (np >= 1 || np <= PTEQ_NVAR (PSYM_SUB (sym)))
+ PTEQ_PAR (PSYM_SUB (sym), np) = value
+ else
+ call error (0,
+ "pr_ppari: Not a valid variable number (PTEQPAR)")
+ } else
+ call error (0, "pr_ppari: Null equation pointer (PTEQPAR)")
+
+ case PTEQPLIST:
+ if (PSYM_SUB (sym) != NULL) {
+ if (np >= 1 || np <= PTEQ_NVAR (PSYM_SUB (sym)))
+ PTEQ_PLIST (PSYM_SUB (sym), np) = value
+ else
+ call error (0,
+ "pr_ppari: Not a valid variable number (PTEQPLIST)")
+ } else
+ call error (0, "pr_ppari: Null equation pointer (PTEQPLIST)")
+
+ default:
+ call error (param, "pr_ppari: Unknown parameter")
+ }
+end
+
+
+# PR_PPARR -- Put fitting parameter real parameter.
+
+procedure pr_pparr (offset, np, param, value)
+
+int offset # symbol offset
+int np # parameter number
+int param # parameter
+real value # value
+
+pointer sym
+
+pointer pr_pointer()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_pparr: Null symbol pointer")
+
+ # Branch on parameter
+ switch (param) {
+ case PTEQPARVAL:
+ if (PSYM_SUB (sym) != NULL) {
+ if (np >= 1 || np <= PTEQ_NVAR (PSYM_SUB (sym)))
+ PTEQ_PARVAL (PSYM_SUB (sym), np) = value
+ else
+ call error (0,
+ "pr_pparr: Not a valid variable number (PTEQPARVAL)")
+ } else
+ call error (0, "pr_pparr: Null equation pointer (PTEQPARVAL)")
+
+ default:
+ call error (param, "pr_pparr: Unknown parameter")
+ }
+end
+
+
+# PR_PDERC -- Put derivative character string parameter.
+
+procedure pr_pderc (offset, nd, param, value)
+
+int offset # symbol offset
+int nd # derivative number
+int param # parameter
+char value[ARB] # value
+
+pointer sym
+
+include "parser.com"
+
+int stpstr()
+pointer pr_pointer
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_pderc: Null symbol pointer")
+
+ # Branch on parameter
+ switch (param) {
+ case PTEQDER:
+ if (PSYM_SUB (sym) != NULL) {
+ if (nd >= 1 || nd <= PTEQ_NVAR (PSYM_SUB (sym)))
+ PTEQ_DER (PSYM_SUB (sym), nd) = stpstr (symtable, value, 0)
+ else
+ call error (0,
+ "pr_pderc: Not a valid variable number (PTEQDER)")
+ } else
+ call error (param, "pr_pderc: Null equation pointer (PTEQDER)")
+
+ default:
+ call error (param, "pr_pderc: Unknown parameter")
+ }
+end
+
+
+# PR_PDERP -- Put derivative pointer parameter.
+
+procedure pr_pderp (offset, nd, param, value)
+
+int offset # symbol offset
+int nd # derivative number
+int param # parameter
+pointer value # value
+
+pointer sym
+
+include "parser.com"
+
+pointer pr_pointer()
+
+begin
+ # Get symbol pointer
+ sym = pr_pointer (offset)
+
+ # Check symbol pointer
+ if (sym == NULL)
+ call error (0, "pr_pderp: Null symbol pointer")
+
+ # Branch on parameter
+ switch (param) {
+ case PTEQRPNDER:
+ if (PSYM_SUB (sym) != NULL) {
+ if (nd >= 1 || nd <= PTEQ_NVAR (PSYM_SUB (sym)))
+ PTEQ_RPNDER (PSYM_SUB (sym), nd) = value
+ else
+ call error (0,
+ "pr_pderp: Not a valid derivative number (PTEQRPNDER)")
+ } else
+ call error (0, "pr_pderp: Null equation pointer (PTEQRPNDER)")
+
+ default:
+ call error (param, "pr_pderp: Unknown parameter")
+ }
+end
diff --git a/noao/digiphot/photcal/parser/prtable.x b/noao/digiphot/photcal/parser/prtable.x
new file mode 100644
index 00000000..1b6c746f
--- /dev/null
+++ b/noao/digiphot/photcal/parser/prtable.x
@@ -0,0 +1,1371 @@
+.help prtable
+Parser Symbol Table Handling.
+
+.nf
+Entry points:
+
+ pr_obscol (variable, col) Enter observational var. column
+ pr_catcol (variable, col) Enter catalog var. column
+ pr_errcol (variable, col) Enter error column
+ pr_wtscol (variable, col) Enter weight column
+
+ pr_fitpar (name, value) Enter fitting parameter value
+ pr_const (name, value) Enter constant parameter value
+ pr_delta (name, value) Enter delta for parameter value
+
+ pr_seteq (name, eq, rpn, lenrpn) Enter set equation
+
+ pr_treq (name, refeq, trneq, Enter transformation equation
+ rpnref, lenref,
+ rpntrn, lentrn)
+ pr_trder (name, param, equation, Enter trans. deriv.
+ rpneq, leneq)
+ pr_trplot (name, xploteq, yploteq, Enter trans. plot equations
+ rpnxplot, lenxplot,
+ rpnyplot, lenyplot)
+
+ pr_erreq (name, erreq, mineq, maxeq, Enter error equation
+ rpnerr, lenerr, rpnmin,
+ lenmin, rpnmax, lenmax)
+ pr_wtseq (name, wghteq, mineq, maxeq, Enter weight equation
+ rpnwght, lenwght, rpnmin,
+ lenmin, rpnmax, lenmax)
+
+ pr_section (section) Enter equation section
+
+ pr_chkid (name) Check identifier type
+
+Low level entry points:
+
+ pr_incol (type, variable, col, spare) Enter input column
+ pr_param (type, name, value) Enter parameter value
+ pr_trvar (sym, nrcat, nrobs, nfcat, nfobs) Update variables in eq.
+ pr_trpar (sym, npar) Update parameters in eq.
+ pr_trpnum (syme, symp) Get parameter number
+.endhelp
+
+include <mach.h>
+include "../lib/parser.h"
+include "../lib/prdefs.h"
+
+
+# PR_OBSCOL -- Enter an observational variable name and its column in the
+# input file into the symbol table.
+
+procedure pr_obscol (variable, col)
+
+char variable[ARB] # variable name
+char col[ARB] # column
+
+#bool clgetb()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_obscol (%s) (%s)\n")
+ #call pargstr (variable)
+ #call pargstr (col)
+ #}
+
+ # Enter observational variable
+ call pr_incol (PTY_OBSVAR, variable, col, NO)
+end
+
+
+# PR_CATCOL -- Enter the name of a catalog variable for a catalog
+# star, and its column in the input file into the symbol table.
+
+procedure pr_catcol (variable, col)
+
+char variable[ARB] # variable name
+char col[ARB] # column
+
+#bool clgetb()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_catcol (%s) (%s)\n")
+ #call pargstr (variable)
+ #call pargstr (col)
+ #}
+
+ # Enter catalog variable
+ call pr_incol (PTY_CATVAR, variable, col, NO)
+end
+
+
+# PR_INCOL -- Enter an observational or catalog variable name, and its
+# column in the input file into the symbol table.
+
+procedure pr_incol (type, variable, col, spare)
+
+int type # column type (observation or catalog)
+char variable[ARB] # variable name
+char col[ARB] # column
+int spare # spare column (YES/NO) ?
+
+char aux[SZ_LINE]
+int sym, ip, colnum
+pointer ptr
+#bool clgetb()
+int ctoi(), pr_geti(), pr_getsym(), pr_putsym()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_incol (%d) (%s) (%s)\n")
+ #call pargi (type)
+ #call pargstr (variable)
+ #call pargstr (col)
+ #}
+
+ # Enter variable into the symbol table if it's not already there.
+ if (IS_INDEFI (pr_getsym (variable))) {
+
+ # Get column value, and check if it's in range.
+ ip = 1
+ if (ctoi (col, ip, colnum) <= 0)
+ colnum = 0
+ if (colnum < pr_geti (MINCOL)) {
+ call sprintf (aux, SZ_LINE,
+ "Column out of range or reserved for matching name [%s]")
+ call pargstr (variable)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ # Enter and initialize variable name in the table.
+ sym = pr_putsym (variable)
+
+ # Enter type.
+ call pr_psymi (sym, PSYMTYPE, type)
+
+ # Allocate space for the symbol substructure,
+ # and store it into the symbol structure.
+ call pr_inalloc (ptr)
+ call pr_psymp (sym, PSYMSUB, ptr)
+
+ # Enter column number and spare flag.
+ call pr_psymi (sym, PINPCOL, colnum)
+ call pr_psymi (sym, PINPSPARE, spare)
+
+ # Count variables, and enter variable number.
+ if (type == PTY_OBSVAR) {
+ call pr_inci (NOBSVARS, 1)
+ call pr_psymi (sym, PSYMNUM, pr_geti (NOBSVARS))
+ } else {
+ call pr_inci (NCATVARS, 1)
+ call pr_psymi (sym, PSYMNUM, pr_geti (NCATVARS))
+ }
+
+ } else {
+ call sprintf (aux, SZ_LINE,
+ "Input variable [%s] declared more than once")
+ call pargstr (variable)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+end
+
+
+# PR_ERRCOL -- Enter an observational or catalog variable error column in
+# the input file into the symbol table.
+
+procedure pr_errcol (variable, col)
+
+char variable[ARB] # variable name
+char col[ARB] # column
+
+char aux[SZ_LINE]
+int sym, ip, colnum
+#bool clgetb()
+int ctoi(), pr_geti(), pr_getsym(), pr_gsymi()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_errcol (%s) (%s)\n")
+ #call pargstr (variable)
+ #call pargstr (col)
+ #}
+
+ # Enter error into table if the variable is already there.
+ sym = pr_getsym (variable)
+ if (!IS_INDEFI (sym)) {
+
+ # Get column value, and check if it's in range.
+ ip = 1
+ if (ctoi (col, ip, colnum) <= 0)
+ colnum = 0
+ if (colnum < pr_geti (MINCOL)) {
+ call sprintf (aux, SZ_LINE,
+ "Error column out of range or reserved for matching name [%s]")
+ call pargstr (variable)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ # Enter column value
+ call pr_psymi (sym, PINPERRCOL, colnum)
+
+ # Enter spare value.
+ call sprintf (aux, SZ_LINE, "@E_%s")
+ call pargstr (variable)
+ call pr_incol (pr_gsymi (sym, PSYMTYPE), aux, col, YES)
+
+ } else {
+ call sprintf (aux, SZ_LINE,
+ "Attempt to define error column for undefined variable [%s]")
+ call pargstr (variable)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+end
+
+
+# PR_WTSCOL -- Enter an observational or catalog variable weight column in
+# the input file into the symbol table.
+
+procedure pr_wtscol (variable, col)
+
+char variable[ARB] # variable name
+char col[ARB] # column
+
+char aux[SZ_LINE]
+int sym, ip, colnum
+#bool clgetb()
+int ctoi(), pr_geti(), pr_getsym(), pr_gsymi()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_wtscol (%s) (%s)\n")
+ #call pargstr (variable)
+ #call pargstr (col)
+ #}
+
+ # Enter error into table if the variable is already there.
+ sym = pr_getsym (variable)
+ if (!IS_INDEFI (sym)) {
+
+ # Get column value, and check if it's in range.
+ ip = 1
+ if (ctoi (col, ip, colnum) <= 0)
+ colnum = 0
+ if (colnum < pr_geti (MINCOL)) {
+ call sprintf (aux, SZ_LINE,
+ "Weight column out of range or reserved for matching name [%s]")
+ call pargstr (variable)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ # Enter column value.
+ call pr_psymi (sym, PINPWTSCOL, colnum)
+
+ # Enter spare value.
+ call sprintf (aux, SZ_LINE, "@W_%s")
+ call pargstr (variable)
+ call pr_incol (pr_gsymi (sym, PSYMTYPE), aux, col, YES)
+
+ } else {
+ call sprintf (aux, SZ_LINE,
+ "Attempt to define weight column for undefined variable [%s]")
+ call pargstr (variable)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+end
+
+
+# PR_FITPAR -- Enter a variable name and its value as a fitting parameter
+# into the symbol table, if it's not already there.
+
+procedure pr_fitpar (name, value)
+
+char name[ARB] # parameter name
+char value[ARB] # parameter value
+
+#bool clgetb()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_fitpar (%s) (%s)\n")
+ #call pargstr (name)
+ #call pargstr (value)
+ #}
+
+ # Enter fitting parameter.
+ call pr_param (PTY_FITPAR, name, value)
+end
+
+
+# PR_CONST -- Enter a variable name and its value as a constant parameter
+# into the symbol table, if it's not already there.
+
+procedure pr_const (name, value)
+
+char name[ARB] # constant name
+char value[ARB] # parameter value
+
+#bool clgetb()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_const (%s) (%s)\n")
+ #call pargstr (name)
+ #call pargstr (value)
+ #}
+
+ # Enter constant parameter.
+ call pr_param (PTY_CONST, name, value)
+end
+
+
+# PR_PARAM -- Enter a variable name and its value as either a constant
+# or fitting parameter into the symbol table, if it's not already there.
+
+procedure pr_param (type, name, value)
+
+int type # parameter type
+char name[ARB] # parameter name
+char value[ARB] # parameter value
+
+char aux[SZ_LINE]
+int sym, ip, n, symtype
+pointer ptr
+real rval
+
+#bool clgetb()
+int ctor(), pr_geti(), pr_gsymi(), pr_getsym(), pr_putsym()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_param (%d) (%s) (%s)\n")
+ #call pargi (type)
+ #call pargstr (name)
+ #call pargstr (value)
+ #}
+
+ # Get parameter value, and check it.
+ ip = 1
+ n = ctor (value, ip, rval)
+ if (n == 0 || IS_INDEFR (rval)) {
+ call sprintf (aux, SZ_LINE,
+ "Constant or fitting parameter value undefined for [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ # Get symbol and symbol type.
+ sym = pr_getsym (name)
+ if (!IS_INDEFI (sym))
+ symtype = pr_gsymi (sym, PSYMTYPE)
+ else
+ symtype = INDEFI
+
+ # Enter name into the symbol table if it's not
+ # already there. Otherwise redefine it if possible.
+ # Do not enter or redefine with undefined values.
+ if (IS_INDEFI (sym)) {
+
+ # Enter name into symbol table.
+ sym = pr_putsym (name)
+
+ # Enter type
+ call pr_psymi (sym, PSYMTYPE, type)
+
+ # Allocate space for the symbol substructure,
+ # and store it into the symbol structure.
+ call pr_ftalloc (ptr)
+ call pr_psymp (sym, PSYMSUB, ptr)
+
+ # Count total number of parameters, and number
+ # of fitting parameters.
+ call pr_inci (NTOTPARS, 1)
+ if (type == PTY_FITPAR)
+ call pr_inci (NFITPARS, 1)
+
+ # Enter number, and value.
+ call pr_psymi (sym, PSYMNUM, pr_geti (NTOTPARS))
+ call pr_psymr (sym, PFITVALUE, rval)
+
+ } else if (symtype == PTY_FITPAR || symtype == PTY_CONST) {
+
+ # Update fitting parameter counter.
+ if (symtype == PTY_FITPAR && type == PTY_CONST)
+ call pr_deci (NFITPARS, 1)
+ else if (symtype == PTY_CONST && type == PTY_FITPAR)
+ call pr_inci (NFITPARS, 1)
+
+ # Redefine type and value, but not number.
+ call pr_psymi (sym, PSYMTYPE, type)
+ call pr_psymr (sym, PFITVALUE, rval)
+
+ # Issue warning message.
+ call sprintf (aux, SZ_LINE,
+ "Constant or fitting parameter [%s] redefined")
+ call pargstr (name)
+ call pr_error (aux, PERR_WARNING)
+
+ } else {
+ call sprintf (aux, SZ_LINE,
+ "Constant or fitting parameter [%s] declared more than once")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+end
+
+
+# PR_DELTA -- Enter a variable name and its value as the delta of a fitting
+# or constant parameter. Check for negative or zero delta values.
+
+procedure pr_delta (name, value)
+
+char name[ARB] # parameter name
+char value[ARB] # delta value
+
+char aux[SZ_LINE]
+int sym, ip, n, symtype
+real rval
+#bool clgetb()
+int ctor(), pr_getsym(), pr_gsymi()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_delta (%s) (%s)\n")
+ #call pargstr (name)
+ #call pargstr (value)
+ #}
+
+ # Get symbol and symbol type
+ sym = pr_getsym (name)
+ if (!IS_INDEFI (sym)) {
+
+ # Get delta value, and check it.
+ ip = 1
+ n = ctor (value, ip, rval)
+ if (n == 0 || IS_INDEFR (rval)) {
+ call sprintf (aux, SZ_LINE,
+ "Delta value undefined for parameter [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ } else if (rval <= 0) {
+ call sprintf (aux, SZ_LINE,
+ "Delta value for parameter [%s] must be positive")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ # Enter delta if the type is consistent.
+ symtype = pr_gsymi (sym, PSYMTYPE)
+ if (symtype == PTY_FITPAR || symtype == PTY_CONST) {
+ call pr_psymr (sym, PFITDELTA, rval)
+ } else {
+ call sprintf (aux, SZ_LINE,
+ "Attempt to define a delta for a non-parameter [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ } else {
+ call sprintf (aux, SZ_LINE,
+ "Attempt to define delta for undefined parameter [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+end
+
+
+# PR_SETEQ -- Enter the set equation the symbol table, if it's not already
+# there.
+
+procedure pr_seteq (name, eq, rpn, lenrpn)
+
+char name[ARB] # equation name
+char eq[ARB] # equation
+pointer rpn # equation code
+int lenrpn # code length
+
+char aux[SZ_LINE]
+int sym
+pointer ptr
+
+#bool clgetb()
+int pr_geti(), pr_getsym(), pr_putsym()
+pointer pr_cput()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_seteq (%s) (eq=%s) (rpn=%d,%d)\n")
+ #call pargstr (name)
+ #call pargstr (eq)
+ #call pargi (rpn)
+ #call pargi (lenrpn)
+ #}
+
+ # Enter ser equation into the symbol table if it's not
+ # already there.
+ if (IS_INDEFI (pr_getsym (name))) {
+
+ # Enter equation into symbol table.
+ sym = pr_putsym (name)
+
+ # Count equations.
+ call pr_inci (NSETEQS, 1)
+
+ # Enter equation type, and number.
+ call pr_psymi (sym, PSYMTYPE, PTY_SETEQ)
+ call pr_psymi (sym, PSYMNUM, pr_geti (NSETEQS))
+
+ # Allocate space for an equation substructure,
+ # and store it into the symbol structure.
+ call pr_stalloc (ptr)
+ call pr_psymp (sym, PSYMSUB, ptr)
+
+ # Enter equation string offset, and code.
+ call pr_psymc (sym, PSEQEQ, eq)
+ call pr_psymp (sym, PSEQRPNEQ, pr_cput (rpn, lenrpn))
+
+ # Enter null strings for error, and weight equations
+ # because they might not be defined afterwards, and because
+ # they can't be initialized at allocation time.
+ call pr_psymc (sym, PSEQERROR, "")
+ call pr_psymc (sym, PSEQERRMIN, "")
+ call pr_psymc (sym, PSEQERRMAX, "")
+ call pr_psymc (sym, PSEQWEIGHT, "")
+ call pr_psymc (sym, PSEQWTSMIN, "")
+ call pr_psymc (sym, PSEQWTSMAX, "")
+
+ } else {
+ call sprintf (aux, SZ_LINE,
+ "Set equation declared more than once [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+end
+
+
+# PR_TREQ -- Enter the transformation equation along with its reference
+# equation, and its plotting equations into the symbol table.
+
+procedure pr_treq (name, refeq, trneq, rpnref, lenref, rpntrn, lentrn)
+
+char name[ARB] # equation name
+char refeq[ARB] # reference equation
+char trneq[ARB] # transformation equation
+pointer rpnref # reference equation code
+int lenref # code length
+pointer rpntrn # transformation equation code
+int lentrn # code length
+
+char aux[SZ_LINE]
+int i, nrcat, nrobs, nfcat, nfobs, npar, sym
+pointer ptr
+#bool clgetb()
+int mct_nrows(), pr_geti(), pr_getsym(), pr_putsym()
+pointer pr_getp(), pr_cput()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_treq (%s) (ref=%s) (eq=%s)\n")
+ #call pargstr (name)
+ #call pargstr (refeq)
+ #call pargstr (trneq)
+ #call eprintf (
+ #"pr_treq (ref=%d,%d) (eq=%d,%d)\n")
+ #call pargi (rpnref)
+ #call pargi (lenref)
+ #call pargi (rpntrn)
+ #call pargi (lentrn)
+ #}
+
+ # Enter transformation equation into the symbol table
+ # if it's not already there.
+ if (IS_INDEFI (pr_getsym (name))) {
+
+ # Enter equation into symbol table. The symbol
+ # attributes are initialized to default values.
+ sym = pr_putsym (name)
+
+ # Count equations.
+ call pr_inci (NTRNEQS, 1)
+
+ # Enter equation type, and number.
+ call pr_psymi (sym, PSYMTYPE, PTY_TRNEQ)
+ call pr_psymi (sym, PSYMNUM, pr_geti (NTRNEQS))
+
+ # Get number of catalog and observational variables,
+ # and number of parameters for the current equation.
+ # All of them were stored in the temporary table during
+ # the parse of the expression.
+ nrcat = mct_nrows (pr_getp (TRCATTABLE))
+ nrobs = mct_nrows (pr_getp (TROBSTABLE))
+ nfcat = mct_nrows (pr_getp (TFCATTABLE))
+ nfobs = mct_nrows (pr_getp (TFOBSTABLE))
+ npar = mct_nrows (pr_getp (TPARTABLE))
+
+ # Allocate space for an equation substructure,
+ # and store it into the symbol structure.
+ call pr_tralloc (ptr, nrcat, nrobs, nfcat, nfobs, npar)
+ call pr_psymp (sym, PSYMSUB, ptr)
+
+ # Update variable counters in the equation substructure.
+ call pr_trvar (sym, nrcat, nrobs, nfcat, nfobs)
+
+ # Update fitting parameter data in the equation substructure.
+ call pr_trpar (sym, npar)
+
+ # Enter equation string offsets.
+ call pr_psymc (sym, PTEQFIT, trneq)
+ call pr_psymc (sym, PTEQREF, refeq)
+
+ # Enter null strings for error, weight, plot equations, and
+ # derivative equations, because they might not be defined
+ # afterwards, and because they can't be initialized at
+ # allocation time.
+ call pr_psymc (sym, PTEQERROR, "")
+ call pr_psymc (sym, PTEQERRMIN, "")
+ call pr_psymc (sym, PTEQERRMAX, "")
+ call pr_psymc (sym, PTEQWEIGHT, "")
+ call pr_psymc (sym, PTEQWTSMIN, "")
+ call pr_psymc (sym, PTEQWTSMAX, "")
+ call pr_psymc (sym, PTEQXPLOT, "")
+ call pr_psymc (sym, PTEQYPLOT, "")
+ do i = 1, npar
+ call pr_pderc (sym, i, PTEQDER, "")
+
+ # Enter equation codes.
+ call pr_psymp (sym, PTEQRPNFIT, pr_cput (rpntrn, lentrn))
+ call pr_psymp (sym, PTEQRPNREF, pr_cput (rpnref, lenref))
+
+ # Clear temporary tables.
+ call mct_reset (pr_getp (TROBSTABLE))
+ call mct_reset (pr_getp (TRCATTABLE))
+ call mct_reset (pr_getp (TFOBSTABLE))
+ call mct_reset (pr_getp (TFCATTABLE))
+ call mct_reset (pr_getp (TPARTABLE))
+
+ } else {
+ call sprintf (aux, SZ_LINE,
+ "Transformation equation [%s] declared more than once")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+end
+
+
+# PR_TRPAR -- Update fitting parameters in the equation substructure.
+# Fitting and constant parameters for the current equation were stored
+# in the temporary table when the equation was parsed.
+# Count fitting (active) parameters, and update the parameter
+# values, and fitting parameter list.
+
+procedure pr_trpar (sym, npar)
+
+int sym # equation symbol
+int npar # number of parameters
+
+int nfpar # number of fitting parameters
+int symp # parameter symbol
+int i
+
+#bool clgetb()
+int pr_gsymi(), pr_gpari()
+pointer pr_getp(), pr_gsymp(), mct_getbuf()
+real pr_gsymr()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_trpar (sym=%d) (npar=%d)\n")
+ #call pargi (sym)
+ #call pargi (npar)
+ #}
+
+ # Move parameter offsets from temporary table to
+ # equation substructure, if there are any.
+ if (npar > 0) {
+ call amovi (Memi[mct_getbuf (pr_getp (TPARTABLE))],
+ Memi[pr_gsymp (sym, PTEQSPAR)], npar)
+ }
+
+ # Clear the fitting parameter list.
+ call aclri (Memi[pr_gsymp (sym, PTEQSPLIST)], npar)
+
+ # Reset number of fitting parameters, and iterate
+ # for all the parameters in the equation.
+ nfpar = 0
+ do i = 1, npar {
+
+ # Get parameter symbol and process it.
+ symp = pr_gpari (sym, i, PTEQPAR)
+ if (!IS_INDEFI (symp)) {
+
+ # Enter value.
+ call pr_pparr (sym, i, PTEQPARVAL, pr_gsymr (symp, PFITVALUE))
+
+ # Enter fitting parameter number to the list.
+ if (pr_gsymi (symp, PSYMTYPE) == PTY_FITPAR) {
+ nfpar = nfpar + 1
+ call pr_ppari (sym, nfpar, PTEQPLIST, i)
+ }
+
+ } else
+ call error (0, "pr_trpar: Undefined parameter symbol")
+ }
+
+ # Enter number of fitting (active) parameters.
+ call pr_psymi (sym, PTEQNFPAR, nfpar)
+end
+
+
+# PR_TRVAR -- Update variable symbols and counters in the equation
+# substructure. Variable symbols and counters for the reference and
+# fit equations were stored in the temporary tables when the equation
+# was parsed. The offsets and counters come from two different sequential
+# tables, but are stored in one place in the equation substructure.
+
+procedure pr_trvar (sym, nrcat, nrobs, nfcat, nfobs)
+
+int sym # equation symbol
+int nrcat, nrobs # reference eq. counters
+int nfcat, nfobs # fit eq. counters
+
+int i
+pointer table
+
+#bool clgetb()
+int mct_geti()
+pointer pr_getp()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf (
+ #"pr_trvar (sym=%d) (nrc=%d) (nro=%d) (nfc=%d) (nfo=%d)\n")
+ #call pargi (sym)
+ #call pargi (nrcat)
+ #call pargi (nrobs)
+ #call pargi (nfcat)
+ #call pargi (nfobs)
+ #}
+
+ # Update reference equation symbols and counters.
+ table = pr_getp (TRCATTABLE)
+ do i = 1, nrcat {
+ call pr_pvari (sym, i, PTEQREFVAR, mct_geti (table, i, 1))
+ call pr_pvari (sym, i, PTEQREFCNT, mct_geti (table, i, 2))
+ }
+ table = pr_getp (TROBSTABLE)
+ do i = nrcat + 1, nrcat + nrobs {
+ call pr_pvari (sym, i, PTEQREFVAR, mct_geti (table, i - nrcat, 1))
+ call pr_pvari (sym, i, PTEQREFCNT, mct_geti (table, i - nrcat, 2))
+ }
+
+ # Update fit equation symbols and counters
+ table = pr_getp (TFCATTABLE)
+ do i = 1, nfcat {
+ call pr_pvari (sym, i, PTEQFITVAR, mct_geti (table, i, 1))
+ call pr_pvari (sym, i, PTEQFITCNT, mct_geti (table, i, 2))
+ }
+ table = pr_getp (TFOBSTABLE)
+ do i = nfcat + 1, nfcat + nfobs {
+ call pr_pvari (sym, i, PTEQFITVAR, mct_geti (table, i - nfcat, 1))
+ call pr_pvari (sym, i, PTEQFITCNT, mct_geti (table, i - nfcat, 2))
+ }
+end
+
+
+# PR_TRDER -- Enter the derivative of a given equation with respect to
+# a fitting parameter or constant into the symbol table.
+
+procedure pr_trder (name, param, equation, rpneq, leneq)
+
+char name[ARB] # equation name
+char param[ARB] # parameter name
+char equation[ARB] # derivative equation
+pointer rpneq # derivative code
+int leneq # code length
+
+char aux[SZ_LINE]
+int np
+int type
+int syme, symp
+
+#bool clgetb()
+int pr_gsymi()
+int pr_trpnum()
+int pr_getsym()
+pointer pr_cput()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_trder (%s) (%s) (%s) (%d,%d)\n")
+ #call pargstr (name)
+ #call pargstr (param)
+ #call pargstr (equation)
+ #call pargi (rpneq)
+ #call pargi (leneq)
+ #}
+
+ # Get parameter symbol from the table if it's already
+ # there. Otherwise issue an error message.
+ symp = pr_getsym (param)
+ if (!IS_INDEFI (symp)) {
+ type = pr_gsymi (symp, PSYMTYPE)
+ if (type != PTY_FITPAR && type != PTY_CONST) {
+ call sprintf (aux, SZ_LINE,
+ "Derivative with respect of non-parameter [%s]")
+ call pargstr (param)
+ call pr_error (aux, PERR_SEMANTIC)
+ return
+ }
+ } else {
+ call sprintf (aux, SZ_LINE,
+ "Derivative with respect of undefined parameter [%s]")
+ call pargstr (param)
+ call pr_error (aux, PERR_SEMANTIC)
+ return
+ }
+
+ # Enter the derivative into the symbol table if the equation
+ # is already there, and if the fitting parameter belongs to
+ # the equation.
+ syme = pr_getsym (name)
+ if (!IS_INDEFI (syme)) {
+ if (pr_gsymi (syme, PSYMTYPE) == PTY_TRNEQ) {
+
+ # Get parameter number for the equation. An undefined
+ # value means that it doesn't belong to it.
+ np = pr_trpnum (syme, symp)
+
+ # If the parameter was found enter the derivative
+ # equation, and code in the substructure under the
+ # parameter number
+ if (!IS_INDEFI (np)) {
+ call pr_pderc (syme, np, PTEQDER, equation)
+ call pr_pderp (syme, np, PTEQRPNDER, pr_cput (rpneq, leneq))
+ } else {
+ call sprintf (aux, SZ_LINE,
+ "Derivative with respect to unappropiate parameter [%s]")
+ call pargstr (param)
+ call pr_error (aux, PERR_WARNING)
+ }
+
+ } else {
+ call sprintf (aux, SZ_LINE,
+ "Derivative of non-transformation equation [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ } else {
+ call sprintf (aux, SZ_LINE, "Derivative of undefined equation [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+end
+
+
+# PR_TRPLOT -- Enter plot equations of a given transformation equation
+# into the symbol table.
+
+procedure pr_trplot (name, xploteq, yploteq, rpnxplot, lenxplot,
+ rpnyplot, lenyplot)
+
+char name[ARB] # equation name
+char xploteq[ARB] # x plot equation
+char yploteq[ARB] # y plot equation
+pointer rpnxplot # x plot equation code
+int lenxplot # x plot code length
+pointer rpnyplot # y plot equation code
+int lenyplot # y plot code length
+
+char aux[SZ_LINE]
+int sym
+#bool clgetb()
+int pr_gsymi(), pr_getsym()
+pointer pr_cput()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_trplot (%s) (%s) (%s)\n")
+ #call pargstr (name)
+ #call pargstr (xploteq)
+ #call pargstr (yploteq)
+ #call eprintf (
+ #"pr_trplot (xplot=%d,%d) (yplot=%d,%d)\n")
+ #call pargi (rpnxplot)
+ #call pargi (lenxplot)
+ #call pargi (rpnyplot)
+ #call pargi (lenyplot)
+ #}
+
+ # Enter the plot equations into the symbol table if the
+ # equation is already there.
+ sym = pr_getsym (name)
+ if (!IS_INDEFI (sym)) {
+ if (pr_gsymi (sym, PSYMTYPE) == PTY_TRNEQ) {
+
+ # Enter equation string offsets
+ call pr_psymc (sym, PTEQXPLOT, xploteq)
+ call pr_psymc (sym, PTEQYPLOT, yploteq)
+
+ # Enter equation codes
+ call pr_psymp (sym, PTEQRPNXPLOT, pr_cput (rpnxplot, lenxplot))
+ call pr_psymp (sym, PTEQRPNYPLOT, pr_cput (rpnyplot, lenyplot))
+
+ } else {
+ call sprintf (aux, SZ_LINE,
+ "Plot of non-transformation equation [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ } else {
+ call sprintf (aux, SZ_LINE, "Plot of undefined equation [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+end
+
+
+# PR_TRPNUM -- Get parameter number for the equation.
+
+int procedure pr_trpnum (syme, symp)
+
+int syme # equation symbol
+int symp # symbol symbol
+
+int i, np
+#bool clgetb()
+int pr_gsymi(), pr_gpari()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_trpnum (%d) (%d)\n")
+ #call pargi (syme)
+ #call pargi (symp)
+ #}
+
+ # Initialize to undefined.
+ np = INDEFI
+
+ # Search for the parameter into the equation substructure.
+ do i = 1, pr_gsymi (syme, PTEQNPAR) {
+ if (symp == pr_gpari (syme, i, PTEQPAR)) {
+ np = i
+ break
+ }
+ }
+
+ # Return parameter number.
+ return (np)
+end
+
+
+# PR_ERREQ -- Enter the error equation of a given transformation or
+# set equation into the symbol table.
+
+procedure pr_erreq (name, erreq, mineq, maxeq, rpnerr, lenerr, rpnmin,
+ lenmin, rpnmax, lenmax)
+
+char name[ARB] # equation name
+char erreq[ARB] # error equation
+char mineq[ARB] # min equation
+char maxeq[ARB] # max equation
+pointer rpnerr # error code
+int lenerr # error code length
+pointer rpnmin # min code
+int lenmin # min code length
+pointer rpnmax # max code
+int lenmax # max code length
+
+char aux[SZ_LINE]
+int sym, type
+#bool clgetb()
+int pr_gsymi(), pr_getsym()
+pointer pr_cput()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_erreq (%s) (%s) (%s) (%s)\n")
+ #call pargstr (name)
+ #call pargstr (erreq)
+ #call pargstr (mineq)
+ #call pargstr (maxeq)
+ #call eprintf (
+ #"pr_erreq (err=%d,%d) (min=%d,%d) (max=%d,%d)\n")
+ #call pargi (rpnerr)
+ #call pargi (lenerr)
+ #call pargi (rpnmin)
+ #call pargi (lenmin)
+ #call pargi (rpnmax)
+ #call pargi (lenmax)
+ #}
+
+ # Enter the error, maximum, and minimum equations into the
+ # symbol table if the equation is already there.
+ sym = pr_getsym (name)
+ if (!IS_INDEFI (sym)) {
+ type = pr_gsymi (sym, PSYMTYPE)
+ if (type == PTY_SETEQ) {
+
+ # Enter equation string offsets
+ call pr_psymc (sym, PSEQERROR, erreq)
+ call pr_psymc (sym, PSEQERRMIN, mineq)
+ call pr_psymc (sym, PSEQERRMAX, maxeq)
+
+ # Enter equation codes
+ call pr_psymp (sym, PSEQRPNERROR, pr_cput (rpnerr, lenerr))
+ if (lenmin > 0)
+ call pr_psymp (sym, PSEQRPNERRMIN, pr_cput (rpnmin, lenmin))
+ if (lenmax > 0)
+ call pr_psymp (sym, PSEQRPNERRMAX, pr_cput (rpnmax, lenmax))
+
+ } else if (type == PTY_TRNEQ) {
+
+ # Enter equation string offsets
+ call pr_psymc (sym, PTEQERROR, erreq)
+ call pr_psymc (sym, PTEQERRMIN, mineq)
+ call pr_psymc (sym, PTEQERRMAX, maxeq)
+
+ # Enter equation codes
+ call pr_psymp (sym, PTEQRPNERROR, pr_cput (rpnerr, lenerr))
+ if (lenmin > 0)
+ call pr_psymp (sym, PTEQRPNERRMIN, pr_cput (rpnmin, lenmin))
+ if (lenmax > 0)
+ call pr_psymp (sym, PTEQRPNERRMAX, pr_cput (rpnmax, lenmax))
+
+ } else {
+ call sprintf (aux, SZ_LINE,
+ "Error of non transformation or set equation [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ } else {
+ call sprintf (aux, SZ_LINE, "Error of undefined equation [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+end
+
+
+# PR_WTSEQ -- Enter the weight equation of a given transformation or set
+# equation into the symbol table.
+
+procedure pr_wtseq (name, wghteq, mineq, maxeq, rpnwght, lenwght, rpnmin,
+ lenmin, rpnmax, lenmax)
+
+char name[ARB] # equation name
+char wghteq[ARB] # weight equation
+char mineq[ARB] # min equation
+char maxeq[ARB] # max equation
+pointer rpnwght # weight code
+int lenwght # weight code length
+pointer rpnmin # min code
+int lenmin # min code length
+pointer rpnmax # max code
+int lenmax # max code length
+
+char aux[SZ_LINE]
+int sym, type
+#bool clgetb()
+int pr_gsymi(), pr_getsym()
+pointer pr_cput()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_wtseq (%s) (%s) (%s) (%s)\n")
+ #call pargstr (name)
+ #call pargstr (wghteq)
+ #call pargstr (mineq)
+ #call pargstr (maxeq)
+ #call eprintf (
+ #"pr_wtseq (wght=%d,%d) (min=%d,%d) (max=%d,%d)\n")
+ #call pargi (rpnwght)
+ #call pargi (lenwght)
+ #call pargi (rpnmin)
+ #call pargi (lenmin)
+ #call pargi (rpnmax)
+ #call pargi (lenmax)
+ #}
+
+ # Enter the weight, maximum, and minimum equations into the
+ # symbol table if the equation is already there.
+ sym = pr_getsym (name)
+ if (!IS_INDEFI (sym)) {
+ type = pr_gsymi (sym, PSYMTYPE)
+ if (type == PTY_SETEQ) {
+
+ # Enter equation string offsets
+ call pr_psymc (sym, PSEQWEIGHT, wghteq)
+ call pr_psymc (sym, PSEQWTSMIN, mineq)
+ call pr_psymc (sym, PSEQWTSMAX, maxeq)
+
+ # Enter equation codes
+ call pr_psymp (sym, PSEQRPNWEIGHT, pr_cput (rpnwght, lenwght))
+ if (lenmin > 0)
+ call pr_psymp (sym, PSEQRPNWTSMIN, pr_cput (rpnmin, lenmin))
+ if (lenmax > 0)
+ call pr_psymp (sym, PSEQRPNWTSMAX, pr_cput (rpnmax, lenmax))
+
+ } else if (type == PTY_TRNEQ) {
+
+ # Enter equation string offsets
+ call pr_psymc (sym, PTEQWEIGHT, wghteq)
+ call pr_psymc (sym, PTEQWTSMIN, mineq)
+ call pr_psymc (sym, PTEQWTSMAX, maxeq)
+
+ # Enter equation codes
+ call pr_psymp (sym, PTEQRPNWEIGHT, pr_cput (rpnwght, lenwght))
+ if (lenmin > 0)
+ call pr_psymp (sym, PTEQRPNWTSMIN, pr_cput (rpnmin, lenmin))
+ if (lenmax > 0)
+ call pr_psymp (sym, PTEQRPNWTSMAX, pr_cput (rpnmax, lenmax))
+
+ } else {
+ call sprintf (aux, SZ_LINE,
+ "Weight of non transformation or set equation [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ } else {
+ call sprintf (aux, SZ_LINE, "Weight of undefined equation [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+end
+
+
+# PR_SECTION -- Set the equation section.
+
+procedure pr_section (section)
+
+int section # equation section
+
+#bool clgetb()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_section (%d)\n")
+ #call pargi (section)
+ #}
+
+ # Set the type flag.
+ call pr_puti (FLAGEQSECT, section)
+end
+
+
+# PR_CHKID -- Check the identifier according to the equation section.
+
+procedure pr_chkid (name)
+
+char name[ARB] # identifier name
+
+bool found
+char aux[SZ_LINE]
+int row, nrows, type, sym
+pointer table
+
+#bool clgetb()
+int mct_nrows(), mct_geti()
+int pr_geti(), pr_gsymi()
+int pr_getsym()
+pointer pr_getp()
+
+begin
+ # Debug ?
+ #if (clgetb ("debug.parcode")) {
+ #call eprintf ("pr_chkid (%s)\n")
+ #call pargstr (name)
+ #}
+
+ # Check if identfier is in the table.
+ sym = pr_getsym (name)
+ if (!IS_INDEFI (sym)) {
+
+ # Get symbol type.
+ type = pr_gsymi (sym, PSYMTYPE)
+
+ # Check equation section.
+ switch (pr_geti (FLAGEQSECT)) {
+ case PRS_SETEQ:
+ if (type != PTY_OBSVAR && type != PTY_CATVAR &&
+ type != PTY_SETEQ) {
+ call sprintf (aux, SZ_LINE,
+ "Illegal identifier in set equation [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ case PRS_TRNREF:
+ if (type != PTY_OBSVAR && type != PTY_CATVAR &&
+ type != PTY_SETEQ && type != PTY_TRNEQ) {
+ call sprintf (aux, SZ_LINE,
+ "Illegal identifier in reference equation [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ # Enter observational or catalog variable into the
+ # corresponding sequential table, if it was not
+ # already there. Otherwise increment variable counter.
+ if (type == PTY_OBSVAR || type == PTY_CATVAR) {
+
+ # Select temporary table
+ switch (type) {
+ case PTY_OBSVAR:
+ table = pr_getp (TROBSTABLE)
+ case PTY_CATVAR:
+ table = pr_getp (TRCATTABLE)
+ }
+
+ # Search for symbol in the sequential table
+ found = false
+ nrows = mct_nrows (table)
+ do row = 1, nrows {
+ if (sym == mct_geti (table, row, 1)) {
+ found = true
+ break
+ }
+ }
+
+ # Increment counter if the variable was found.
+ # Otherwise enter symbol and initialize counter
+ # to one.
+ if (found) {
+ call mct_puti (table, row, 2,
+ mct_geti (table, row, 2) + 1)
+ } else {
+ call mct_puti (table, nrows + 1, 1, sym)
+ call mct_puti (table, nrows + 1, 2, 1)
+ }
+ }
+
+ case PRS_TRNFIT:
+ if (type != PTY_OBSVAR && type != PTY_CATVAR &&
+ type != PTY_FITPAR && type != PTY_CONST &&
+ type != PTY_SETEQ) {
+ call sprintf (aux, SZ_LINE,
+ "Illegal identifier in fit equation [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ # Enter observational variable, catalog variable,
+ # fitting parameter, or constant parameter into the
+ # corresponding sequential table, if it was not already
+ # there. Otherwise, for variables, increment counter.
+ # For fitting parameters, also update the symbol number
+ # relative to the current equation.
+ if (type == PTY_OBSVAR || type == PTY_CATVAR ||
+ type == PTY_FITPAR || type == PTY_CONST) {
+
+ # Select temporary table
+ switch (type) {
+ case PTY_OBSVAR:
+ table = pr_getp (TFOBSTABLE)
+ case PTY_CATVAR:
+ table = pr_getp (TFCATTABLE)
+ case PTY_FITPAR, PTY_CONST:
+ table = pr_getp (TPARTABLE)
+ }
+
+ # Search for symbol in the sequential table
+ found = false
+ nrows = mct_nrows (table)
+ do row = 1, nrows {
+ if (sym == mct_geti (table, row, 1)) {
+ found = true
+ break
+ }
+ }
+
+ # Enter symbol into the sequential table if it was
+ # not found. For variables initialize counter, and
+ # for parameters update the symbol number.
+ # Otherwise, increment the variable counter.
+ if (found) {
+ if (type == PTY_CATVAR || type == PTY_OBSVAR)
+ call mct_puti (table, row, 2,
+ mct_geti (table, row, 2) + 1)
+ } else {
+ call mct_puti (table, nrows + 1, 1, sym)
+ if (type == PTY_CATVAR || type == PTY_OBSVAR)
+ call mct_puti (table, nrows + 1, 2, 1)
+ else if (type == PTY_FITPAR || type == PTY_CONST)
+ call pr_psymi (sym, PSYMNUM, nrows + 1)
+ }
+ }
+
+ case PRS_TRNDER:
+ if (type != PTY_OBSVAR && type != PTY_CATVAR &&
+ type != PTY_FITPAR && type != PTY_CONST &&
+ type != PTY_SETEQ && type != PTY_TRNEQ) {
+ call sprintf (aux, SZ_LINE,
+ "Illegal identifier in derivative equation [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ case PRS_TRNPLOT:
+ if (type != PTY_OBSVAR && type != PTY_CATVAR &&
+ type != PTY_FITPAR && type != PTY_CONST &&
+ type != PTY_SETEQ && type != PTY_TRNEQ) {
+ call sprintf (aux, SZ_LINE,
+ "Illegal identifier in plot equation [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ case PRS_ERREQ:
+ if (type != PTY_OBSVAR && type != PTY_CATVAR &&
+ type != PTY_FITPAR && type != PTY_CONST &&
+ type != PTY_SETEQ) {
+ call sprintf (aux, SZ_LINE,
+ "Illegal identifier in error equation [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ case PRS_WTSEQ:
+ if (type != PTY_OBSVAR && type != PTY_CATVAR &&
+ type != PTY_FITPAR && type != PTY_CONST &&
+ type != PTY_SETEQ) {
+ call sprintf (aux, SZ_LINE,
+ "Illegal identifier in weight equation [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ case PRS_LMTEQ:
+ if (type != PTY_OBSVAR && type != PTY_CATVAR &&
+ type != PTY_FITPAR && type != PTY_CONST &&
+ type != PTY_SETEQ) {
+ call sprintf (aux, SZ_LINE,
+ "Illegal identifier in min or max equation [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+
+ default: call error (0, "pr_chkid: Unknown section type")
+ }
+
+ } else {
+ call sprintf (aux, SZ_LINE,
+ "Undefined identifier in expression [%s]")
+ call pargstr (name)
+ call pr_error (aux, PERR_SEMANTIC)
+ }
+end
diff --git a/noao/digiphot/photcal/parser/prvtran.x b/noao/digiphot/photcal/parser/prvtran.x
new file mode 100644
index 00000000..6119ce05
--- /dev/null
+++ b/noao/digiphot/photcal/parser/prvtran.x
@@ -0,0 +1,25 @@
+# PR_VTRAN -- Translate the internal parser symbol for an error or weight
+# column definition into a compact user readable definition. This code is
+# intended primarily for interfacing to the inlfit or other package with
+# the goal of making more pleasing variable names.
+
+procedure pr_vtran (invname, outvname, maxch)
+
+char invname[ARB] # the input variable name
+char outvname[ARB] # the output variable name
+int maxch # maximum number of characters
+
+int first, last
+int gstrmatch()
+
+begin
+ if (gstrmatch (invname, "@E_", first, last) != 0) {
+ call sprintf (outvname, maxch, "er(%s)")
+ call pargstr (invname[last+1])
+ } else if (gstrmatch (invname, "@W_", first, last) != 0) {
+ call sprintf (outvname, maxch, "wt(%s)")
+ call pargstr (invname[last+1])
+ } else {
+ call strcpy (invname, outvname, maxch)
+ }
+end
diff --git a/noao/digiphot/photcal/parser/t_chkconfig.x b/noao/digiphot/photcal/parser/t_chkconfig.x
new file mode 100644
index 00000000..0b75c4e9
--- /dev/null
+++ b/noao/digiphot/photcal/parser/t_chkconfig.x
@@ -0,0 +1,228 @@
+include "../lib/parser.h"
+
+
+# T_CHKCONFIG - Check the configuration file for syntax and semantic errors,
+# and print information on the standard output about all the entities declared
+# in it.
+
+procedure t_chkconfig ()
+
+char input[SZ_FNAME] # input file name
+bool verbose # verbose output
+
+bool done
+int i, j, n, sym
+
+bool clgetb()
+int pr_parse(), pr_gsym(), pr_geti(), pr_gsymi(), pr_gpari()
+real pr_gsymr()
+pointer pr_xgetname(), pr_gsymc(), pr_gderc(), pr_gderp()
+
+begin
+ # Get the task parameters.
+ call clgstr ("config", input, SZ_FNAME)
+ verbose = clgetb ("verbose")
+
+ # Print the beginning of compilation message.
+ call printf ("\n\n** Beginning of compilation **\n\n")
+
+ # Parse the input file.
+ done = (pr_parse (input) == OK)
+
+ # Print the end of compilation message.
+ call printf ("\n** End of compilation **\n\n")
+
+ # Print verbose output.
+ if (done && verbose) {
+
+ # Print the catalog variables.
+ n = pr_geti (NCATVARS)
+ if (n > 0) {
+
+ # Print section title
+ call printf (
+ "\nCATALOG VARIABLES, COLUMNS, AND ERROR COLUMNS:\n\n")
+
+ # Loop over all variables
+ do i = 1, n {
+ sym = pr_gsym (i, PTY_CATVAR)
+ if (pr_gsymi (sym, PINPSPARE) == YES)
+ next
+ call printf ("%2d %s\t%d\t%d\n")
+ call pargi (pr_gsymi (sym, PSYMNUM))
+ call pargstr (Memc[pr_xgetname (sym)])
+ call pargi (pr_gsymi (sym, PINPCOL))
+ call pargi (pr_gsymi (sym, PINPERRCOL))
+ }
+ }
+
+ # Print input obervation variables.
+ n = pr_geti (NOBSVARS)
+ if (n > 0) {
+
+ # Print section title
+ call printf (
+ "\nOBSERVATIONAL VARIABLES, COLUMNS, AND ERROR COLUMNS:\n\n")
+
+ # Loop over all variables
+ do i = 1, n {
+ sym = pr_gsym (i, PTY_OBSVAR)
+ if (pr_gsymi (sym, PINPSPARE) == YES)
+ next
+ call printf ("%2d %s\t%d\t%d\n")
+ call pargi (pr_gsymi (sym, PSYMNUM))
+ call pargstr (Memc[pr_xgetname (sym)])
+ call pargi (pr_gsymi (sym, PINPCOL))
+ call pargi (pr_gsymi (sym, PINPERRCOL))
+ }
+ }
+
+ # Print the fitting and constant parameters.
+ n = pr_geti (NTOTPARS)
+ if (n > 0) {
+
+ # Print section title
+ call printf (
+ "\nFIT AND CONSTANT PARAMETER VALUES:\n\n")
+
+ # Loop over all fitting parameters
+ do i = 1, n {
+ sym = pr_gsym (i, PTY_FITPAR)
+ call printf ("%2d %s\t%g\t%s\n")
+ call pargi (i)
+ call pargstr (Memc[pr_xgetname (sym)])
+ call pargr (pr_gsymr (sym, PFITVALUE))
+ if (pr_gsymi (sym, PSYMTYPE) == PTY_CONST)
+ call pargstr ("(constant)")
+ else
+ call pargstr ("")
+ }
+ }
+
+ # Print the set equations.
+ n = pr_geti (NSETEQS)
+ if (n > 0) {
+
+ # Print title
+ call printf (
+ "\nAUXILIARY (SET) EQUATIONS:\n\n")
+
+ # Loop over all equations
+ do i = 1, n {
+
+ # Print the equation.
+ sym = pr_gsym (i, PTY_SETEQ)
+ call printf ("%2d %s = %s\n")
+ call pargi (pr_gsymi (sym, PSYMNUM))
+ call pargstr (Memc[pr_xgetname (sym)])
+ call pargstr (Memc[pr_gsymc (sym, PSEQEQ)])
+
+ # Print the error equation.
+ call printf (" error = %s, min = %s, max = %s\n")
+ call pargstr (Memc[pr_gsymc (sym, PSEQERROR)])
+ call pargstr (Memc[pr_gsymc (sym, PSEQERRMIN)])
+ call pargstr (Memc[pr_gsymc (sym, PSEQERRMAX)])
+
+# # Print the weight equation.
+# call printf (" weight = %s, min = %s, max = %s\n")
+# call pargstr (Memc[pr_gsymc (sym, PSEQWEIGHT)])
+# call pargstr (Memc[pr_gsymc (sym, PSEQWTSMIN)])
+# call pargstr (Memc[pr_gsymc (sym, PSEQWTSMAX)])
+
+ call printf ("\n")
+ }
+ }
+
+ # Print the transformation equations.
+ n = pr_geti (NTRNEQS)
+ if (n > 0) {
+
+ # Print section title
+ call printf (
+ "\nTRANSFORMATION EQUATIONS:\n\n")
+
+ # Loop over all equations
+ do i = 1, n {
+
+ # Print the equation.
+ sym = pr_gsym (i, PTY_TRNEQ)
+ call printf ("%2d %s: %s = %s\n")
+ call pargi (pr_gsymi (sym, PSYMNUM))
+ call pargstr (Memc[pr_xgetname (sym)])
+ call pargstr (Memc[pr_gsymc (sym, PTEQREF)])
+ call pargstr (Memc[pr_gsymc (sym, PTEQFIT)])
+
+ # Print the derivative equations.
+ do j = 1, pr_gsymi (sym, PTEQNPAR) {
+ if (pr_gderp (sym, j, PTEQRPNDER) != NULL) {
+ call printf (" derivative (%s, %s) = %s\n")
+ call pargstr (Memc[pr_xgetname (sym)])
+ call pargstr (Memc[pr_xgetname (pr_gpari (sym,
+ j, PTEQPAR))])
+ call pargstr (Memc[pr_gderc (sym, j, PTEQDER)])
+ } else {
+ call printf (" delta(%s, %s) = %s\n")
+ call pargstr (Memc[pr_xgetname (sym)])
+ call pargstr (Memc[pr_xgetname (pr_gpari (sym,
+ j, PTEQPAR))])
+ call pargr (pr_gsymr(pr_gpari (sym, j, PTEQPAR),
+ PFITDELTA))
+ }
+ }
+
+ # Print the error equation.
+ call printf (" error = %s, min = %s, max = %s\n")
+ call pargstr (Memc[pr_gsymc (sym, PTEQERROR)])
+ call pargstr (Memc[pr_gsymc (sym, PTEQERRMIN)])
+ call pargstr (Memc[pr_gsymc (sym, PTEQERRMAX)])
+
+ # Print the weight equation.
+ call printf (" weight = %s, min = %s, max = %s\n")
+ call pargstr (Memc[pr_gsymc (sym, PTEQWEIGHT)])
+ call pargstr (Memc[pr_gsymc (sym, PTEQWTSMIN)])
+ call pargstr (Memc[pr_gsymc (sym, PTEQWTSMAX)])
+
+ # Print the plot defaults.
+ call printf (" plot x = %s, y = %s\n")
+ call pargstr (Memc[pr_gsymc (sym, PTEQXPLOT)])
+ call pargstr (Memc[pr_gsymc (sym, PTEQYPLOT)])
+
+ call printf ("\n")
+ }
+ call printf ("\n")
+ }
+ }
+
+ # Print the counter values.
+ call printf ("Catalog input variables = %d\n")
+ call pargi (pr_geti (NCATVARS))
+ call printf ("First catalog column = %d\n")
+ call pargi (pr_geti (MINCATCOL))
+ call printf ("Last catalog column = %d\n\n")
+ call pargi (pr_geti (MAXCATCOL))
+ call printf ("Observational input variables = %d\n")
+ call pargi (pr_geti (NOBSVARS))
+ call printf ("First observational column = %d\n")
+ call pargi (pr_geti (MINOBSCOL))
+ call printf ("Last observational column = %d\n\n")
+ call pargi (pr_geti (MAXOBSCOL))
+ call printf ("Fitting parameters = %d\n")
+ call pargi (pr_geti (NFITPARS))
+ call printf ("Constant parameters = %d\n\n")
+ call pargi (pr_geti (NTOTPARS) - pr_geti (NFITPARS))
+# call printf ("Extinction equations = %d\n")
+# call pargi (pr_geti (NEXTEQS))
+ call printf ("Auxiliary (set) equations = %d\n")
+ call pargi (pr_geti (NSETEQS))
+ call printf ("Transformation equations = %d\n\n")
+ call pargi (pr_geti (NTRNEQS))
+ call printf ("Warnings = %d\n")
+ call pargi (pr_geti (NWARNINGS))
+ call printf ("Errors = %d\n")
+ call pargi (pr_geti (NERRORS))
+ call flush (STDOUT)
+
+ # Free the tables.
+ if (done)
+ call pr_free ()
+end
diff --git a/noao/digiphot/photcal/parser/y.tab.h b/noao/digiphot/photcal/parser/y.tab.h
new file mode 100644
index 00000000..8b3119a8
--- /dev/null
+++ b/noao/digiphot/photcal/parser/y.tab.h
@@ -0,0 +1,42 @@
+define OBSSECT 257
+define CATSECT 258
+define EXTSECT 259
+define TRNSECT 260
+define FITID 261
+define CONSTID 262
+define DELTAID 263
+define ERRORID 264
+define WEIGHTID 265
+define MINID 266
+define MAXID 267
+define DERIVID 268
+define PLOTID 269
+define SETID 270
+define F_ABS 271
+define F_ACOS 272
+define F_ASIN 273
+define F_ATAN 274
+define F_COS 275
+define F_EXP 276
+define F_LOG 277
+define F_LOG10 278
+define F_SIN 279
+define F_SQRT 280
+define F_TAN 281
+define IDENTIFIER 282
+define INUMBER 283
+define RNUMBER 284
+define PLUS 285
+define MINUS 286
+define STAR 287
+define SLASH 288
+define EXPON 289
+define COLON 290
+define SEMICOLON 291
+define COMMA 292
+define EQUAL 293
+define LPAR 294
+define RPAR 295
+define EOFILE 296
+define UPLUS 297
+define UMINUS 298
diff --git a/noao/digiphot/photcal/photcal.cl b/noao/digiphot/photcal/photcal.cl
new file mode 100644
index 00000000..7923b53e
--- /dev/null
+++ b/noao/digiphot/photcal/photcal.cl
@@ -0,0 +1,55 @@
+# Package script task for the PHOTCAL package.
+#{ PHOTCAL package definition
+
+
+# Load other packages
+
+images # some of the preprocessors require hselect
+lists # the mkimsets script requires the unique task
+proto # some of the preprocessors require fields
+
+# Define photcal package
+
+package photcal
+
+# PHOTCAL tasks
+
+task apfile,
+ catalog,
+ config,
+ chkconfig,
+ evalfit,
+ fitparams,
+ imgroup,
+ invertfit,
+ obsfile,
+ mkphotcors = "photcal$x_photcal.e"
+
+# PHOTCAL scripts
+
+task mkapfile = "photcal$mkapfile.cl"
+task mkcatalog = "photcal$mkcatalog.cl"
+task mkconfig = "photcal$mkconfig.cl"
+task mkimsets = "photcal$mkimsets.cl"
+task mknobsfile = "photcal$mknobsfile.cl"
+task mkobsfile = "photcal$mkobsfile.cl"
+
+# PTOOLS tasks
+
+task istable,
+ tbcrename,
+ tbkeycol,
+ txdump = "ptools$x_ptools.e"
+
+# PTOOLS scripts which depend on PTOOLS and TTOOLS tasks
+
+task pdump = "ptools$pdump.cl"
+
+# TTOOLS tasks linked into the photcal package
+
+task tbdump = "ptools$tbdump.cl"
+
+hidetask catalog, config, imgroup
+hidetask istable, tbcrename, tbkeycol, txdump, tbdump, pdump
+
+clbye()
diff --git a/noao/digiphot/photcal/photcal.hd b/noao/digiphot/photcal/photcal.hd
new file mode 100644
index 00000000..21cff756
--- /dev/null
+++ b/noao/digiphot/photcal/photcal.hd
@@ -0,0 +1,28 @@
+# Help directory for the PHOTCAL package.
+
+$doc = "./doc/"
+
+$evaluate = "photcal$evaluate/"
+$fitparams = "photcal$fitparams/"
+$mkobsfile = "photcal$mkobsfile/"
+$mkconfig = "photcal$mkconfig/"
+$mkimsets = "photcal$mkimsets/"
+$parser = "photcal$parser/"
+
+apfile hlp = doc$apfile.hlp, src = mkobsfile$t_apfile.x
+chkconfig hlp = doc$chkconfig.hlp, src = parser$t_chkconfig.x
+config hlp = doc$config.hlp
+evalfit hlp = doc$evalfit.hlp, src = evaluate$t_evalfit.x
+fitparams hlp = doc$fitparams.hlp, src = fitparams$t_fitparams.x
+invertfit hlp = doc$invertfit.hlp, src = evaluate$t_invertfit.x
+mkapfile hlp = doc$mkapfile.hlp, src = photcal$mkapfile.cl
+mkconfig hlp = doc$mkconfig.hlp, src = mkconfig$t_config.x
+mkimsets hlp = doc$mkimsets.hlp, src = mkimsets$t_mkimsets.x
+mknobsfile hlp = doc$mknobsfile.hlp, src = photcal$mknobsfile.cl
+mkobsfile hlp = doc$mkobsfile.hlp, src = photcal$mkobsfile.cl
+mkcatalog hlp = doc$mkcatalog.hlp, src = photcal$mkcatalog.cl
+mkphotcors hlp = doc$mkphotcors.hlp, src = mkobsfile$t_mkphotcors.x
+obsfile hlp = doc$obsfile.hlp, src = mkobsfile$t_obsfile.x
+pcintro hlp = doc$pcintro.hlp
+inlfit hlp = doc$inlfit.hlp
+revisions sys=Revisions
diff --git a/noao/digiphot/photcal/photcal.men b/noao/digiphot/photcal/photcal.men
new file mode 100644
index 00000000..2628c830
--- /dev/null
+++ b/noao/digiphot/photcal/photcal.men
@@ -0,0 +1,16 @@
+ mkapfile - Prepare aperture corrections file from apphot/daophot output
+ mkcatalog - Type in a standard star catalog or observations file
+ mkimsets - Prepare an image set file for input to (mk)(n)obsfile
+ mk(n)obsfile - Prepare an observations file from apphot/daophot output
+ mkphotcors - Prepare the photometric corrections files
+ apfile - Prepare an aperture corrections file from a text file
+ obsfile - Prepare an observations file from a text file
+
+ mkconfig - Prepare a configuration file
+ chkconfig - Check the configuration file for grammar and syntax errors
+ fitparams - Compute the parameters of the transformation equations
+ evalfit - Compute the standard indices by evaluating the fit
+ invertfit - Compute the standard indices by inverting the fit
+
+ help config - Print description of the configuration file format
+ help pcintro - Print a short introduction to the photcal package
diff --git a/noao/digiphot/photcal/photcal.par b/noao/digiphot/photcal/photcal.par
new file mode 100644
index 00000000..b31c590f
--- /dev/null
+++ b/noao/digiphot/photcal/photcal.par
@@ -0,0 +1,5 @@
+# PHOTCAL package parameter file.
+
+catdir,s,h,"photcal$catalogs/",,,Directory containing standard star catalogs
+version,s,h,"Aug91"
+mode,s,h,ql
diff --git a/noao/digiphot/photcal/x_photcal.x b/noao/digiphot/photcal/x_photcal.x
new file mode 100644
index 00000000..15fd48f6
--- /dev/null
+++ b/noao/digiphot/photcal/x_photcal.x
@@ -0,0 +1,10 @@
+task apfile = t_apfile,
+ catalog = t_catalog,
+ config = t_config,
+ chkconfig = t_chkconfig,
+ fitparams = t_fitparams,
+ imgroup = t_imgroup,
+ invertfit = t_invertfit,
+ evalfit = t_evalfit,
+ obsfile = t_obsfile,
+ mkphotcors = t_mkphotcors