aboutsummaryrefslogtreecommitdiff
path: root/noao/digiphot
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
downloadiraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'noao/digiphot')
-rw-r--r--noao/digiphot/apphot/README35
-rw-r--r--noao/digiphot/apphot/Revisions1582
-rw-r--r--noao/digiphot/apphot/aplib/apairmass.x36
-rw-r--r--noao/digiphot/apphot/aplib/apapcolon.x353
-rw-r--r--noao/digiphot/apphot/aplib/aparrays.x52
-rw-r--r--noao/digiphot/apphot/aplib/apfilter.x41
-rw-r--r--noao/digiphot/apphot/aplib/apfree.x25
-rw-r--r--noao/digiphot/apphot/aplib/apgaperts.x214
-rw-r--r--noao/digiphot/apphot/aplib/apgqverify.x68
-rw-r--r--noao/digiphot/apphot/aplib/apgsvw.x162
-rw-r--r--noao/digiphot/apphot/aplib/apgtverify.x19
-rw-r--r--noao/digiphot/apphot/aplib/apimbuf.x17
-rw-r--r--noao/digiphot/apphot/aplib/apimkeys.x72
-rw-r--r--noao/digiphot/apphot/aplib/apinit.x106
-rw-r--r--noao/digiphot/apphot/aplib/apinpars1.x104
-rw-r--r--noao/digiphot/apphot/aplib/apinpars2.x207
-rw-r--r--noao/digiphot/apphot/aplib/apitime.x36
-rw-r--r--noao/digiphot/apphot/aplib/apmark1.x270
-rw-r--r--noao/digiphot/apphot/aplib/apmark2.x46
-rw-r--r--noao/digiphot/apphot/aplib/apnew.x46
-rw-r--r--noao/digiphot/apphot/aplib/apnscolon.x165
-rw-r--r--noao/digiphot/apphot/aplib/apnshow.x118
-rw-r--r--noao/digiphot/apphot/aplib/apotime.x52
-rw-r--r--noao/digiphot/apphot/aplib/apoutpars1.x99
-rw-r--r--noao/digiphot/apphot/aplib/apoutpars2.x146
-rw-r--r--noao/digiphot/apphot/aplib/appadu.x37
-rw-r--r--noao/digiphot/apphot/aplib/apqrad.x119
-rw-r--r--noao/digiphot/apphot/aplib/aprcursor1.x584
-rw-r--r--noao/digiphot/apphot/aplib/aprcursor2.x144
-rw-r--r--noao/digiphot/apphot/aplib/aprdnoise.x36
-rw-r--r--noao/digiphot/apphot/aplib/apset.x72
-rw-r--r--noao/digiphot/apphot/aplib/apset1.x330
-rw-r--r--noao/digiphot/apphot/aplib/apset2.x227
-rw-r--r--noao/digiphot/apphot/aplib/apshowplot.x83
-rw-r--r--noao/digiphot/apphot/aplib/apstat.x77
-rw-r--r--noao/digiphot/apphot/aplib/apstat1.x316
-rw-r--r--noao/digiphot/apphot/aplib/apstat2.x215
-rw-r--r--noao/digiphot/apphot/aplib/apverify1.x582
-rw-r--r--noao/digiphot/apphot/aplib/apverify2.x188
-rw-r--r--noao/digiphot/apphot/aplib/apwcs.x117
-rw-r--r--noao/digiphot/apphot/aplib/apwparam1.x415
-rw-r--r--noao/digiphot/apphot/aplib/apwparam2.x104
-rw-r--r--noao/digiphot/apphot/aplib/apwres1.x437
-rw-r--r--noao/digiphot/apphot/aplib/apwres2.x347
-rw-r--r--noao/digiphot/apphot/aplib/apwres3.x132
-rw-r--r--noao/digiphot/apphot/aplib/apwres4.x238
-rw-r--r--noao/digiphot/apphot/aplib/mkpkg102
-rw-r--r--noao/digiphot/apphot/apphot.cl58
-rw-r--r--noao/digiphot/apphot/apphot.hd34
-rw-r--r--noao/digiphot/apphot/apphot.men26
-rw-r--r--noao/digiphot/apphot/apphot.par11
-rw-r--r--noao/digiphot/apphot/aptest.cl220
-rw-r--r--noao/digiphot/apphot/aputil/apbsmooth.x33
-rw-r--r--noao/digiphot/apphot/aputil/apclip.x23
-rw-r--r--noao/digiphot/apphot/aputil/apdate.x29
-rw-r--r--noao/digiphot/apphot/aputil/apdiverr.x7
-rw-r--r--noao/digiphot/apphot/aputil/apfnames.x280
-rw-r--r--noao/digiphot/apphot/aputil/apgscur.x88
-rw-r--r--noao/digiphot/apphot/aputil/apgtools.x141
-rw-r--r--noao/digiphot/apphot/aputil/aplucy.x47
-rw-r--r--noao/digiphot/apphot/aputil/apmapr.x21
-rw-r--r--noao/digiphot/apphot/aputil/apmeds.x154
-rw-r--r--noao/digiphot/apphot/aputil/apmoments.x138
-rw-r--r--noao/digiphot/apphot/aputil/apnlfuncs.x375
-rw-r--r--noao/digiphot/apphot/aputil/appcache.x83
-rw-r--r--noao/digiphot/apphot/aputil/aprmwhite.x22
-rw-r--r--noao/digiphot/apphot/aputil/aptopt.x232
-rw-r--r--noao/digiphot/apphot/aputil/apvectors.x515
-rw-r--r--noao/digiphot/apphot/aputil/mkpkg25
-rw-r--r--noao/digiphot/apphot/center.par21
-rw-r--r--noao/digiphot/apphot/center/apbcenter.x96
-rw-r--r--noao/digiphot/apphot/center/apcconfirm.x75
-rw-r--r--noao/digiphot/apphot/center/apcencolon.x329
-rw-r--r--noao/digiphot/apphot/center/apcenter.x357
-rw-r--r--noao/digiphot/apphot/center/apcerrors.x32
-rw-r--r--noao/digiphot/apphot/center/apcfree.x46
-rw-r--r--noao/digiphot/apphot/center/apcinit.x94
-rw-r--r--noao/digiphot/apphot/center/apclean.x152
-rw-r--r--noao/digiphot/apphot/center/apcplot.x304
-rw-r--r--noao/digiphot/apphot/center/apcpshow.x66
-rw-r--r--noao/digiphot/apphot/center/apcradsetup.x99
-rw-r--r--noao/digiphot/apphot/center/apcshow.x19
-rw-r--r--noao/digiphot/apphot/center/apcsnratio.x92
-rw-r--r--noao/digiphot/apphot/center/apctr1d.x113
-rw-r--r--noao/digiphot/apphot/center/apctrbuf.x115
-rw-r--r--noao/digiphot/apphot/center/apfitcen.x291
-rw-r--r--noao/digiphot/apphot/center/apgcpars.x27
-rw-r--r--noao/digiphot/apphot/center/apgctr1d.x105
-rw-r--r--noao/digiphot/apphot/center/apictr.x48
-rw-r--r--noao/digiphot/apphot/center/aplgctr1d.x87
-rw-r--r--noao/digiphot/apphot/center/apmctr1d.x88
-rw-r--r--noao/digiphot/apphot/center/appcenter.x84
-rw-r--r--noao/digiphot/apphot/center/appcpars.x21
-rw-r--r--noao/digiphot/apphot/center/aprefitcen.x193
-rw-r--r--noao/digiphot/apphot/center/center.key78
-rw-r--r--noao/digiphot/apphot/center/icenter.key12
-rw-r--r--noao/digiphot/apphot/center/mkpkg54
-rw-r--r--noao/digiphot/apphot/center/t_center.x306
-rw-r--r--noao/digiphot/apphot/centerpars.par14
-rw-r--r--noao/digiphot/apphot/daofind.par21
-rw-r--r--noao/digiphot/apphot/daofind/apbfdfind.x139
-rw-r--r--noao/digiphot/apphot/daofind/apconvolve.x320
-rw-r--r--noao/digiphot/apphot/daofind/apegkernel.x132
-rw-r--r--noao/digiphot/apphot/daofind/apfdcolon.x282
-rw-r--r--noao/digiphot/apphot/daofind/apfdconfirm.x22
-rw-r--r--noao/digiphot/apphot/daofind/apfdfind.x213
-rw-r--r--noao/digiphot/apphot/daofind/apfdfree.x34
-rw-r--r--noao/digiphot/apphot/daofind/apfdgpars.x20
-rw-r--r--noao/digiphot/apphot/daofind/apfdinit.x59
-rw-r--r--noao/digiphot/apphot/daofind/apfdpars.x16
-rw-r--r--noao/digiphot/apphot/daofind/apfdradsetup.x82
-rw-r--r--noao/digiphot/apphot/daofind/apfdshow.x72
-rw-r--r--noao/digiphot/apphot/daofind/apfdstars.x151
-rw-r--r--noao/digiphot/apphot/daofind/apfind.x626
-rw-r--r--noao/digiphot/apphot/daofind/apimset.x17
-rw-r--r--noao/digiphot/apphot/daofind/daofind.key66
-rw-r--r--noao/digiphot/apphot/daofind/idaofind.key8
-rw-r--r--noao/digiphot/apphot/daofind/mkpkg37
-rw-r--r--noao/digiphot/apphot/daofind/t_daofind.x419
-rw-r--r--noao/digiphot/apphot/datapars.par25
-rw-r--r--noao/digiphot/apphot/doc/apsums.apps19
-rw-r--r--noao/digiphot/apphot/doc/apsums.noao17
-rw-r--r--noao/digiphot/apphot/doc/aptest.hlp68
-rw-r--r--noao/digiphot/apphot/doc/center.hlp638
-rw-r--r--noao/digiphot/apphot/doc/centerpars.hlp206
-rw-r--r--noao/digiphot/apphot/doc/daofind.hlp579
-rw-r--r--noao/digiphot/apphot/doc/daofind.noao21
-rw-r--r--noao/digiphot/apphot/doc/datapars.hlp290
-rw-r--r--noao/digiphot/apphot/doc/findpars.hlp134
-rw-r--r--noao/digiphot/apphot/doc/fitpsf.hlp680
-rw-r--r--noao/digiphot/apphot/doc/fitsky.hlp632
-rw-r--r--noao/digiphot/apphot/doc/fitskypars.hlp219
-rw-r--r--noao/digiphot/apphot/doc/pexamine.hlp836
-rw-r--r--noao/digiphot/apphot/doc/phot.hlp767
-rw-r--r--noao/digiphot/apphot/doc/photpars.hlp102
-rw-r--r--noao/digiphot/apphot/doc/polymark.hlp430
-rw-r--r--noao/digiphot/apphot/doc/polypars.hlp69
-rw-r--r--noao/digiphot/apphot/doc/polyphot.hlp791
-rw-r--r--noao/digiphot/apphot/doc/qphot.hlp647
-rw-r--r--noao/digiphot/apphot/doc/radprof.hlp813
-rw-r--r--noao/digiphot/apphot/doc/specs/Ap.doc1071
-rw-r--r--noao/digiphot/apphot/doc/specs/Ap.spc1032
-rw-r--r--noao/digiphot/apphot/doc/specs/apphot.db366
-rw-r--r--noao/digiphot/apphot/doc/specs/apphot.spc1296
-rw-r--r--noao/digiphot/apphot/doc/specs/apphot.spc.lw1296
-rw-r--r--noao/digiphot/apphot/doc/specs/apphot.spc.toc111
-rw-r--r--noao/digiphot/apphot/doc/ucache.hlp15
-rw-r--r--noao/digiphot/apphot/doc/userdocs/apuser.ms1881
-rw-r--r--noao/digiphot/apphot/doc/wphot.hlp780
-rw-r--r--noao/digiphot/apphot/findpars.par12
-rw-r--r--noao/digiphot/apphot/fitpsf.par24
-rw-r--r--noao/digiphot/apphot/fitpsf/apbfitpsf.x95
-rw-r--r--noao/digiphot/apphot/fitpsf/apfbuf.x88
-rw-r--r--noao/digiphot/apphot/fitpsf/apfitpsf.x344
-rw-r--r--noao/digiphot/apphot/fitpsf/apgpfpars.x40
-rw-r--r--noao/digiphot/apphot/fitpsf/appfconfirm.x58
-rw-r--r--noao/digiphot/apphot/fitpsf/appferrors.x26
-rw-r--r--noao/digiphot/apphot/fitpsf/appfradsetup.x86
-rw-r--r--noao/digiphot/apphot/fitpsf/apppfpars.x34
-rw-r--r--noao/digiphot/apphot/fitpsf/apppsf.x123
-rw-r--r--noao/digiphot/apphot/fitpsf/appsfshow.x59
-rw-r--r--noao/digiphot/apphot/fitpsf/apsfcolon.x238
-rw-r--r--noao/digiphot/apphot/fitpsf/apsfelgauss.x185
-rw-r--r--noao/digiphot/apphot/fitpsf/apsffit.x136
-rw-r--r--noao/digiphot/apphot/fitpsf/apsffree.x52
-rw-r--r--noao/digiphot/apphot/fitpsf/apsfinit.x94
-rw-r--r--noao/digiphot/apphot/fitpsf/apsfmoments.x106
-rw-r--r--noao/digiphot/apphot/fitpsf/apsfradgauss.x183
-rw-r--r--noao/digiphot/apphot/fitpsf/apsfrefit.x113
-rw-r--r--noao/digiphot/apphot/fitpsf/fitpsf.key73
-rw-r--r--noao/digiphot/apphot/fitpsf/ifitpsf.key10
-rw-r--r--noao/digiphot/apphot/fitpsf/mkpkg44
-rw-r--r--noao/digiphot/apphot/fitpsf/t_fitpsf.x288
-rw-r--r--noao/digiphot/apphot/fitsky.par21
-rw-r--r--noao/digiphot/apphot/fitsky/apavsky.x107
-rw-r--r--noao/digiphot/apphot/fitsky/apbsky.x98
-rw-r--r--noao/digiphot/apphot/fitsky/apcentroid.x244
-rw-r--r--noao/digiphot/apphot/fitsky/apcrosscor.x288
-rw-r--r--noao/digiphot/apphot/fitsky/apfitsky.x452
-rw-r--r--noao/digiphot/apphot/fitsky/apgauss.x296
-rw-r--r--noao/digiphot/apphot/fitsky/apgrowhist.x136
-rw-r--r--noao/digiphot/apphot/fitsky/apgspars.x26
-rw-r--r--noao/digiphot/apphot/fitsky/aphgmsub.x51
-rw-r--r--noao/digiphot/apphot/fitsky/aphistplot.x233
-rw-r--r--noao/digiphot/apphot/fitsky/aplgsky.x216
-rw-r--r--noao/digiphot/apphot/fitsky/apmean.x120
-rw-r--r--noao/digiphot/apphot/fitsky/apmedian.x184
-rw-r--r--noao/digiphot/apphot/fitsky/apmode.x185
-rw-r--r--noao/digiphot/apphot/fitsky/appsky.x103
-rw-r--r--noao/digiphot/apphot/fitsky/appspars.x22
-rw-r--r--noao/digiphot/apphot/fitsky/apradplot.x91
-rw-r--r--noao/digiphot/apphot/fitsky/apreadsky.x40
-rw-r--r--noao/digiphot/apphot/fitsky/aprefitsky.x371
-rw-r--r--noao/digiphot/apphot/fitsky/aprgrow.x64
-rw-r--r--noao/digiphot/apphot/fitsky/apsconfirm.x74
-rw-r--r--noao/digiphot/apphot/fitsky/apserrors.x42
-rw-r--r--noao/digiphot/apphot/fitsky/apsfree.x48
-rw-r--r--noao/digiphot/apphot/fitsky/apsinit.x116
-rw-r--r--noao/digiphot/apphot/fitsky/apsky.x346
-rw-r--r--noao/digiphot/apphot/fitsky/apskybuf.x254
-rw-r--r--noao/digiphot/apphot/fitsky/apskycolon.x367
-rw-r--r--noao/digiphot/apphot/fitsky/apsplot.x244
-rw-r--r--noao/digiphot/apphot/fitsky/apsradsetup.x97
-rw-r--r--noao/digiphot/apphot/fitsky/apsshow.x99
-rw-r--r--noao/digiphot/apphot/fitsky/fitsky.key81
-rw-r--r--noao/digiphot/apphot/fitsky/ifitsky.key11
-rw-r--r--noao/digiphot/apphot/fitsky/mkpkg59
-rw-r--r--noao/digiphot/apphot/fitsky/t_fitsky.x303
-rw-r--r--noao/digiphot/apphot/fitskypars.par17
-rw-r--r--noao/digiphot/apphot/lib/apphot.h110
-rw-r--r--noao/digiphot/apphot/lib/apphotdef.h80
-rw-r--r--noao/digiphot/apphot/lib/center.h102
-rw-r--r--noao/digiphot/apphot/lib/centerdef.h60
-rw-r--r--noao/digiphot/apphot/lib/display.h21
-rw-r--r--noao/digiphot/apphot/lib/displaydef.h23
-rw-r--r--noao/digiphot/apphot/lib/find.h75
-rw-r--r--noao/digiphot/apphot/lib/finddef.h26
-rw-r--r--noao/digiphot/apphot/lib/fitpsf.h72
-rw-r--r--noao/digiphot/apphot/lib/fitpsfdef.h43
-rw-r--r--noao/digiphot/apphot/lib/fitsky.h128
-rw-r--r--noao/digiphot/apphot/lib/fitskydef.h65
-rw-r--r--noao/digiphot/apphot/lib/noise.h54
-rw-r--r--noao/digiphot/apphot/lib/noisedef.h21
-rw-r--r--noao/digiphot/apphot/lib/phot.h86
-rw-r--r--noao/digiphot/apphot/lib/photdef.h43
-rw-r--r--noao/digiphot/apphot/lib/polyphot.h63
-rw-r--r--noao/digiphot/apphot/lib/polyphotdef.h37
-rw-r--r--noao/digiphot/apphot/lib/radprof.h66
-rw-r--r--noao/digiphot/apphot/lib/radprofdef.h38
-rw-r--r--noao/digiphot/apphot/mkpkg39
-rw-r--r--noao/digiphot/apphot/pexamine.par20
-rw-r--r--noao/digiphot/apphot/phot.par24
-rw-r--r--noao/digiphot/apphot/phot/apbphot.x115
-rw-r--r--noao/digiphot/apphot/phot/apcomags.x118
-rw-r--r--noao/digiphot/apphot/phot/apgppars.x35
-rw-r--r--noao/digiphot/apphot/phot/apgqppars.x75
-rw-r--r--noao/digiphot/apphot/phot/apmag.x118
-rw-r--r--noao/digiphot/apphot/phot/apmagbuf.x89
-rw-r--r--noao/digiphot/apphot/phot/apmeasure.x116
-rw-r--r--noao/digiphot/apphot/phot/appconfirm.x98
-rw-r--r--noao/digiphot/apphot/phot/apperrors.x48
-rw-r--r--noao/digiphot/apphot/phot/appfree.x66
-rw-r--r--noao/digiphot/apphot/phot/apphot.x511
-rw-r--r--noao/digiphot/apphot/phot/apphotcolon.x209
-rw-r--r--noao/digiphot/apphot/phot/appinit.x100
-rw-r--r--noao/digiphot/apphot/phot/appmag.x120
-rw-r--r--noao/digiphot/apphot/phot/apppars.x26
-rw-r--r--noao/digiphot/apphot/phot/appplot.x273
-rw-r--r--noao/digiphot/apphot/phot/appshow.x83
-rw-r--r--noao/digiphot/apphot/phot/apqcolon.x331
-rw-r--r--noao/digiphot/apphot/phot/apqphot.x494
-rw-r--r--noao/digiphot/apphot/phot/apqppars.x42
-rw-r--r--noao/digiphot/apphot/phot/apqradsetup.x105
-rw-r--r--noao/digiphot/apphot/phot/apqshow.x86
-rw-r--r--noao/digiphot/apphot/phot/apradsetup.x126
-rw-r--r--noao/digiphot/apphot/phot/apremag.x77
-rw-r--r--noao/digiphot/apphot/phot/iphot.key18
-rw-r--r--noao/digiphot/apphot/phot/iqphot.key8
-rw-r--r--noao/digiphot/apphot/phot/mkpkg81
-rw-r--r--noao/digiphot/apphot/phot/phot.key109
-rw-r--r--noao/digiphot/apphot/phot/qphot.key48
-rw-r--r--noao/digiphot/apphot/phot/t_phot.x341
-rw-r--r--noao/digiphot/apphot/phot/t_qphot.x293
-rw-r--r--noao/digiphot/apphot/photpars.par7
-rw-r--r--noao/digiphot/apphot/polymark.par13
-rw-r--r--noao/digiphot/apphot/polypars.par4
-rw-r--r--noao/digiphot/apphot/polyphot.par22
-rw-r--r--noao/digiphot/apphot/polyphot/apgypars.x29
-rw-r--r--noao/digiphot/apphot/polyphot/apmkpylist.x279
-rw-r--r--noao/digiphot/apphot/polyphot/appyerrors.x35
-rw-r--r--noao/digiphot/apphot/polyphot/apybphot.x94
-rw-r--r--noao/digiphot/apphot/polyphot/apycenter.x59
-rw-r--r--noao/digiphot/apphot/polyphot/apycolon.x226
-rw-r--r--noao/digiphot/apphot/polyphot/apyconfirm.x99
-rw-r--r--noao/digiphot/apphot/polyphot/apycoords.x43
-rw-r--r--noao/digiphot/apphot/polyphot/apydraw.x55
-rw-r--r--noao/digiphot/apphot/polyphot/apyfit.x578
-rw-r--r--noao/digiphot/apphot/polyphot/apyfree.x41
-rw-r--r--noao/digiphot/apphot/polyphot/apyget.x306
-rw-r--r--noao/digiphot/apphot/polyphot/apyinit.x64
-rw-r--r--noao/digiphot/apphot/polyphot/apymkfree.x23
-rw-r--r--noao/digiphot/apphot/polyphot/apymkinit.x31
-rw-r--r--noao/digiphot/apphot/polyphot/apynextobj.x190
-rw-r--r--noao/digiphot/apphot/polyphot/apypars.x20
-rw-r--r--noao/digiphot/apphot/polyphot/apyphot.x577
-rw-r--r--noao/digiphot/apphot/polyphot/apyprint.x94
-rw-r--r--noao/digiphot/apphot/polyphot/apyradsetup.x135
-rw-r--r--noao/digiphot/apphot/polyphot/apyshift.x41
-rw-r--r--noao/digiphot/apphot/polyphot/apywrite.x92
-rw-r--r--noao/digiphot/apphot/polyphot/ipolyphot.key16
-rw-r--r--noao/digiphot/apphot/polyphot/mkpkg60
-rw-r--r--noao/digiphot/apphot/polyphot/polymark.key16
-rw-r--r--noao/digiphot/apphot/polyphot/polyphot.key110
-rw-r--r--noao/digiphot/apphot/polyphot/polyshow.x65
-rw-r--r--noao/digiphot/apphot/polyphot/t_polymark.x240
-rw-r--r--noao/digiphot/apphot/polyphot/t_polyphot.x329
-rw-r--r--noao/digiphot/apphot/qphot.par27
-rw-r--r--noao/digiphot/apphot/radprof.par28
-rw-r--r--noao/digiphot/apphot/radprof/apbradprof.x107
-rw-r--r--noao/digiphot/apphot/radprof/apfrprof.x417
-rw-r--r--noao/digiphot/apphot/radprof/apgrpars.x46
-rw-r--r--noao/digiphot/apphot/radprof/approfsetup.x123
-rw-r--r--noao/digiphot/apphot/radprof/apprprof.x109
-rw-r--r--noao/digiphot/apphot/radprof/apradprof.x500
-rw-r--r--noao/digiphot/apphot/radprof/aprconfirm.x118
-rw-r--r--noao/digiphot/apphot/radprof/aprferrors.x40
-rw-r--r--noao/digiphot/apphot/radprof/aprmmeasure.x96
-rw-r--r--noao/digiphot/apphot/radprof/aprpars.x37
-rw-r--r--noao/digiphot/apphot/radprof/aprpbuf.x82
-rw-r--r--noao/digiphot/apphot/radprof/aprpcolon.x241
-rw-r--r--noao/digiphot/apphot/radprof/aprpfree.x60
-rw-r--r--noao/digiphot/apphot/radprof/aprpindef.x69
-rw-r--r--noao/digiphot/apphot/radprof/aprpinit.x77
-rw-r--r--noao/digiphot/apphot/radprof/aprpplot.x307
-rw-r--r--noao/digiphot/apphot/radprof/iradprof.key20
-rw-r--r--noao/digiphot/apphot/radprof/mkpkg58
-rw-r--r--noao/digiphot/apphot/radprof/radprof.key116
-rw-r--r--noao/digiphot/apphot/radprof/rprofshow.x75
-rw-r--r--noao/digiphot/apphot/radprof/t_radprof.x306
-rw-r--r--noao/digiphot/apphot/temp8
-rw-r--r--noao/digiphot/apphot/test/README5
-rw-r--r--noao/digiphot/apphot/test/coords.dat10
-rw-r--r--noao/digiphot/apphot/test/fits1.fitsbin0 -> 14400 bytes
-rw-r--r--noao/digiphot/apphot/test/fits2.fitsbin0 -> 14400 bytes
-rw-r--r--noao/digiphot/apphot/test/fits3.fitsbin0 -> 14400 bytes
-rw-r--r--noao/digiphot/apphot/test/fits4.fitsbin0 -> 14400 bytes
-rw-r--r--noao/digiphot/apphot/test/fits5.fitsbin0 -> 14400 bytes
-rw-r--r--noao/digiphot/apphot/test/polygons.dat6
-rw-r--r--noao/digiphot/apphot/wphot.par24
-rw-r--r--noao/digiphot/apphot/wphot/apbwphot.x108
-rw-r--r--noao/digiphot/apphot/wphot/apgmeasure.x190
-rw-r--r--noao/digiphot/apphot/wphot/apgwppars.x35
-rw-r--r--noao/digiphot/apphot/wphot/aptmeasure.x192
-rw-r--r--noao/digiphot/apphot/wphot/apwconfirm.x110
-rw-r--r--noao/digiphot/apphot/wphot/apwmag.x157
-rw-r--r--noao/digiphot/apphot/wphot/apwpars.x27
-rw-r--r--noao/digiphot/apphot/wphot/apwpcolon.x157
-rw-r--r--noao/digiphot/apphot/wphot/apwphot.x509
-rw-r--r--noao/digiphot/apphot/wphot/apwremag.x76
-rw-r--r--noao/digiphot/apphot/wphot/mkpkg38
-rw-r--r--noao/digiphot/apphot/wphot/t_wphot.x339
-rw-r--r--noao/digiphot/apphot/wphot/wphot.key109
-rw-r--r--noao/digiphot/apphot/x_apphot.x12
-rw-r--r--noao/digiphot/daophot/README32
-rw-r--r--noao/digiphot/daophot/Revisions918
-rw-r--r--noao/digiphot/daophot/addstar.par23
-rw-r--r--noao/digiphot/daophot/addstar/dpadconfirm.x14
-rw-r--r--noao/digiphot/daophot/addstar/dpaddrd.x89
-rw-r--r--noao/digiphot/daophot/addstar/dpartstar.x303
-rw-r--r--noao/digiphot/daophot/addstar/dpnaddstar.x265
-rw-r--r--noao/digiphot/daophot/addstar/mkpkg17
-rw-r--r--noao/digiphot/daophot/addstar/t_addstar.x331
-rw-r--r--noao/digiphot/daophot/allstar.par19
-rw-r--r--noao/digiphot/daophot/allstar/dpabuf.x495
-rw-r--r--noao/digiphot/daophot/allstar/dpaconfirm.x37
-rw-r--r--noao/digiphot/daophot/allstar/dpalinit.x665
-rw-r--r--noao/digiphot/daophot/allstar/dpalmemstar.x182
-rw-r--r--noao/digiphot/daophot/allstar/dpalphot.x1438
-rw-r--r--noao/digiphot/daophot/allstar/dpalwrite.x556
-rw-r--r--noao/digiphot/daophot/allstar/dpastar.x327
-rw-r--r--noao/digiphot/daophot/allstar/dpcache.x244
-rw-r--r--noao/digiphot/daophot/allstar/dpglim.x17
-rw-r--r--noao/digiphot/daophot/allstar/dprectify.x74
-rw-r--r--noao/digiphot/daophot/allstar/dpregroup.x219
-rw-r--r--noao/digiphot/daophot/allstar/mkpkg32
-rw-r--r--noao/digiphot/daophot/allstar/t_allstar.x355
-rw-r--r--noao/digiphot/daophot/centerpars.par12
-rw-r--r--noao/digiphot/daophot/daoedit.par9
-rw-r--r--noao/digiphot/daophot/daoedit/daoedit.h123
-rw-r--r--noao/digiphot/daophot/daoedit/daoedit.key26
-rw-r--r--noao/digiphot/daophot/daoedit/dpecolon.x441
-rw-r--r--noao/digiphot/daophot/daoedit/dpeconfirm.x433
-rw-r--r--noao/digiphot/daophot/daoedit/dpemark.x734
-rw-r--r--noao/digiphot/daophot/daoedit/dpeomark.x68
-rw-r--r--noao/digiphot/daophot/daoedit/dperplot.x172
-rw-r--r--noao/digiphot/daophot/daoedit/dperprofile.x590
-rw-r--r--noao/digiphot/daophot/daoedit/idaoedit.key22
-rw-r--r--noao/digiphot/daophot/daoedit/mkpkg16
-rw-r--r--noao/digiphot/daophot/daoedit/t_daoedit.x317
-rw-r--r--noao/digiphot/daophot/daofind.par21
-rw-r--r--noao/digiphot/daophot/daolib/bicubic.x47
-rw-r--r--noao/digiphot/daophot/daolib/daoran.x43
-rw-r--r--noao/digiphot/daophot/daolib/dpairmass.x42
-rw-r--r--noao/digiphot/daophot/daolib/dpapheader.x56
-rw-r--r--noao/digiphot/daophot/daolib/dpdate.x28
-rw-r--r--noao/digiphot/daophot/daolib/dpfilter.x41
-rw-r--r--noao/digiphot/daophot/daolib/dpfree.x71
-rw-r--r--noao/digiphot/daophot/daolib/dpgetapert.x530
-rw-r--r--noao/digiphot/daophot/daolib/dpgppars.x227
-rw-r--r--noao/digiphot/daophot/daolib/dpgsubrast.x32
-rw-r--r--noao/digiphot/daophot/daolib/dpgsvw.x162
-rw-r--r--noao/digiphot/daophot/daolib/dpimkeys.x71
-rw-r--r--noao/digiphot/daophot/daolib/dpinit.x225
-rw-r--r--noao/digiphot/daophot/daolib/dpnames.x415
-rw-r--r--noao/digiphot/daophot/daolib/dpotime.x51
-rw-r--r--noao/digiphot/daophot/daolib/dppadu.x36
-rw-r--r--noao/digiphot/daophot/daolib/dppcache.x83
-rw-r--r--noao/digiphot/daophot/daolib/dpppars.x94
-rw-r--r--noao/digiphot/daophot/daolib/dprdnoise.x36
-rw-r--r--noao/digiphot/daophot/daolib/dpreadpsf.x138
-rw-r--r--noao/digiphot/daophot/daolib/dprmwhite.x22
-rw-r--r--noao/digiphot/daophot/daolib/dpset.x181
-rw-r--r--noao/digiphot/daophot/daolib/dpstat.x180
-rw-r--r--noao/digiphot/daophot/daolib/dpverify.x563
-rw-r--r--noao/digiphot/daophot/daolib/dpwcs.x234
-rw-r--r--noao/digiphot/daophot/daolib/dpwparam.x98
-rw-r--r--noao/digiphot/daophot/daolib/erf.x81
-rw-r--r--noao/digiphot/daophot/daolib/invers.f112
-rw-r--r--noao/digiphot/daophot/daolib/invers2.x72
-rw-r--r--noao/digiphot/daophot/daolib/mkpkg48
-rw-r--r--noao/digiphot/daophot/daolib/mvmul.x48
-rw-r--r--noao/digiphot/daophot/daolib/pctile.f91
-rw-r--r--noao/digiphot/daophot/daolib/profile.x506
-rw-r--r--noao/digiphot/daophot/daolib/quick.f202
-rw-r--r--noao/digiphot/daophot/daolib/ran3.x63
-rw-r--r--noao/digiphot/daophot/daolib/usepsf.x81
-rw-r--r--noao/digiphot/daophot/daopars.par25
-rw-r--r--noao/digiphot/daophot/daophot.cl77
-rw-r--r--noao/digiphot/daophot/daophot.hd42
-rw-r--r--noao/digiphot/daophot/daophot.men31
-rw-r--r--noao/digiphot/daophot/daophot.par13
-rw-r--r--noao/digiphot/daophot/daotest.cl308
-rw-r--r--noao/digiphot/daophot/datapars.par25
-rw-r--r--noao/digiphot/daophot/doc/addstar.hlp365
-rw-r--r--noao/digiphot/daophot/doc/allstar.hlp519
-rw-r--r--noao/digiphot/daophot/doc/centerpars.hlp207
-rw-r--r--noao/digiphot/daophot/doc/daoedit.hlp164
-rw-r--r--noao/digiphot/daophot/doc/daofind.hlp601
-rw-r--r--noao/digiphot/daophot/doc/daopars.hlp331
-rw-r--r--noao/digiphot/daophot/doc/daotest.hlp89
-rw-r--r--noao/digiphot/daophot/doc/datapars.hlp289
-rw-r--r--noao/digiphot/daophot/doc/findpars.hlp135
-rw-r--r--noao/digiphot/daophot/doc/fitskypars.hlp212
-rw-r--r--noao/digiphot/daophot/doc/group.hlp304
-rw-r--r--noao/digiphot/daophot/doc/grpselect.hlp73
-rw-r--r--noao/digiphot/daophot/doc/nstar.hlp501
-rw-r--r--noao/digiphot/daophot/doc/peak.hlp439
-rw-r--r--noao/digiphot/daophot/doc/pexamine.hlp780
-rw-r--r--noao/digiphot/daophot/doc/pfmerge.hlp65
-rw-r--r--noao/digiphot/daophot/doc/phot.hlp831
-rw-r--r--noao/digiphot/daophot/doc/photpars.hlp100
-rw-r--r--noao/digiphot/daophot/doc/psf.hlp752
-rw-r--r--noao/digiphot/daophot/doc/pstselect.hlp418
-rw-r--r--noao/digiphot/daophot/doc/seepsf.hlp101
-rw-r--r--noao/digiphot/daophot/doc/setimpars.hlp165
-rw-r--r--noao/digiphot/daophot/doc/specs/daophot.spc1047
-rw-r--r--noao/digiphot/daophot/doc/specs/daoutils.spc700
-rw-r--r--noao/digiphot/daophot/doc/substar.hlp323
-rw-r--r--noao/digiphot/daophot/doc/userdocs/daophot.usr.tex2005
-rw-r--r--noao/digiphot/daophot/doc/userdocs/daoref.ms6290
-rw-r--r--noao/digiphot/daophot/findpars.par12
-rw-r--r--noao/digiphot/daophot/fitskypars.par17
-rw-r--r--noao/digiphot/daophot/group.par16
-rw-r--r--noao/digiphot/daophot/group/dpgconfirm.x24
-rw-r--r--noao/digiphot/daophot/group/dpmkgroup.x484
-rw-r--r--noao/digiphot/daophot/group/dpsmpsf.x199
-rw-r--r--noao/digiphot/daophot/group/dpwrtgroup.x448
-rw-r--r--noao/digiphot/daophot/group/mkpkg18
-rw-r--r--noao/digiphot/daophot/group/t_group.x246
-rw-r--r--noao/digiphot/daophot/grpselect.par8
-rw-r--r--noao/digiphot/daophot/lib/allstardef.h116
-rw-r--r--noao/digiphot/daophot/lib/apseldef.h57
-rw-r--r--noao/digiphot/daophot/lib/daophotdef.h257
-rw-r--r--noao/digiphot/daophot/lib/nstardef.h63
-rw-r--r--noao/digiphot/daophot/lib/peakdef.h55
-rw-r--r--noao/digiphot/daophot/lib/psfdef.h111
-rw-r--r--noao/digiphot/daophot/lib/warning.dat14
-rw-r--r--noao/digiphot/daophot/mkpkg44
-rw-r--r--noao/digiphot/daophot/nstar.par17
-rw-r--r--noao/digiphot/daophot/nstar/dpggroup.x386
-rw-r--r--noao/digiphot/daophot/nstar/dpmemnstar.x158
-rw-r--r--noao/digiphot/daophot/nstar/dpnconfirm.x34
-rw-r--r--noao/digiphot/daophot/nstar/dpnstar.x355
-rw-r--r--noao/digiphot/daophot/nstar/dpnstarfit.x1383
-rw-r--r--noao/digiphot/daophot/nstar/dpntwrite.x600
-rw-r--r--noao/digiphot/daophot/nstar/mkpkg24
-rw-r--r--noao/digiphot/daophot/nstar/t_nstar.x308
-rw-r--r--noao/digiphot/daophot/peak.par17
-rw-r--r--noao/digiphot/daophot/peak/dpmempk.x72
-rw-r--r--noao/digiphot/daophot/peak/dppeakphot.x277
-rw-r--r--noao/digiphot/daophot/peak/dppkconfirm.x25
-rw-r--r--noao/digiphot/daophot/peak/dppkfit.x411
-rw-r--r--noao/digiphot/daophot/peak/dppkwrite.x365
-rw-r--r--noao/digiphot/daophot/peak/dprrphot.x98
-rw-r--r--noao/digiphot/daophot/peak/mkpkg22
-rw-r--r--noao/digiphot/daophot/peak/t_peak.x299
-rw-r--r--noao/digiphot/daophot/pexamine.par20
-rw-r--r--noao/digiphot/daophot/pfmerge.par6
-rw-r--r--noao/digiphot/daophot/phot.par24
-rw-r--r--noao/digiphot/daophot/photpars.par7
-rw-r--r--noao/digiphot/daophot/psf.par27
-rw-r--r--noao/digiphot/daophot/psf/README2
-rw-r--r--noao/digiphot/daophot/psf/dpaddstar.x188
-rw-r--r--noao/digiphot/daophot/psf/dpcontpsf.x449
-rw-r--r--noao/digiphot/daophot/psf/dpdelstar.x112
-rw-r--r--noao/digiphot/daophot/psf/dpfitpsf.x1693
-rw-r--r--noao/digiphot/daophot/psf/dpispstars.x329
-rw-r--r--noao/digiphot/daophot/psf/dplocstar.x109
-rw-r--r--noao/digiphot/daophot/psf/dpmempsf.x217
-rw-r--r--noao/digiphot/daophot/psf/dpmkpsf.x361
-rw-r--r--noao/digiphot/daophot/psf/dppcolon.x271
-rw-r--r--noao/digiphot/daophot/psf/dppconfirm.x26
-rw-r--r--noao/digiphot/daophot/psf/dpplotpsf.x49
-rw-r--r--noao/digiphot/daophot/psf/dppset.x81
-rw-r--r--noao/digiphot/daophot/psf/dppsfutil.x381
-rw-r--r--noao/digiphot/daophot/psf/dppstat.x80
-rw-r--r--noao/digiphot/daophot/psf/dppsubrast.x172
-rw-r--r--noao/digiphot/daophot/psf/dpptconfirm.x21
-rw-r--r--noao/digiphot/daophot/psf/dppwrtgrp.x642
-rw-r--r--noao/digiphot/daophot/psf/dppwselmer.x220
-rw-r--r--noao/digiphot/daophot/psf/dpqverify.x68
-rw-r--r--noao/digiphot/daophot/psf/dpradpsf.x75
-rw-r--r--noao/digiphot/daophot/psf/dprmpsf.x156
-rw-r--r--noao/digiphot/daophot/psf/dprstars.x156
-rw-r--r--noao/digiphot/daophot/psf/dpshowpsf.x287
-rw-r--r--noao/digiphot/daophot/psf/dpspstars.x194
-rw-r--r--noao/digiphot/daophot/psf/dpsubpsf.x183
-rw-r--r--noao/digiphot/daophot/psf/dpsurfpsf.x437
-rw-r--r--noao/digiphot/daophot/psf/dpwritepsf.x270
-rw-r--r--noao/digiphot/daophot/psf/mkpkg70
-rw-r--r--noao/digiphot/daophot/psf/mkpsf.key40
-rw-r--r--noao/digiphot/daophot/psf/mkpsflist.key15
-rw-r--r--noao/digiphot/daophot/psf/showpsf.key24
-rw-r--r--noao/digiphot/daophot/psf/t_psf.x509
-rw-r--r--noao/digiphot/daophot/psf/t_pstselect.x329
-rw-r--r--noao/digiphot/daophot/pstselect.par23
-rw-r--r--noao/digiphot/daophot/seepsf.par9
-rw-r--r--noao/digiphot/daophot/seepsf/dpmkimage.x110
-rw-r--r--noao/digiphot/daophot/seepsf/mkpkg11
-rw-r--r--noao/digiphot/daophot/seepsf/t_seepsf.x91
-rw-r--r--noao/digiphot/daophot/select/dpgwselect.x141
-rw-r--r--noao/digiphot/daophot/select/dppfmerge.x81
-rw-r--r--noao/digiphot/daophot/select/dpsgroup.x95
-rw-r--r--noao/digiphot/daophot/select/mkpkg15
-rw-r--r--noao/digiphot/daophot/select/t_grpselect.x105
-rw-r--r--noao/digiphot/daophot/select/t_pfmerge.x110
-rw-r--r--noao/digiphot/daophot/setimpars.cl276
-rw-r--r--noao/digiphot/daophot/substar.par17
-rw-r--r--noao/digiphot/daophot/substar/dpgimbufr.x137
-rw-r--r--noao/digiphot/daophot/substar/dprestars.x116
-rw-r--r--noao/digiphot/daophot/substar/dpsconfirm.x18
-rw-r--r--noao/digiphot/daophot/substar/dpsubstar.x200
-rw-r--r--noao/digiphot/daophot/substar/mkpkg17
-rw-r--r--noao/digiphot/daophot/substar/t_substar.x286
-rw-r--r--noao/digiphot/daophot/test/cmds.dat4
-rw-r--r--noao/digiphot/daophot/test/fits3.fitsbin0 -> 14400 bytes
-rw-r--r--noao/digiphot/daophot/x_daophot.x14
-rw-r--r--noao/digiphot/digiphot.cl15
-rw-r--r--noao/digiphot/digiphot.hd30
-rw-r--r--noao/digiphot/digiphot.men4
-rw-r--r--noao/digiphot/digiphot.par4
-rw-r--r--noao/digiphot/lib/mkpkg11
-rw-r--r--noao/digiphot/lib/ptkeysdef.h77
-rw-r--r--noao/digiphot/lib/pttables/Revisions10
-rw-r--r--noao/digiphot/lib/pttables/mkpkg19
-rw-r--r--noao/digiphot/lib/pttables/ptchoose.x164
-rw-r--r--noao/digiphot/lib/pttables/ptfmkrec.x102
-rw-r--r--noao/digiphot/lib/pttables/ptgetop.x112
-rw-r--r--noao/digiphot/lib/pttables/ptgnfn.x239
-rw-r--r--noao/digiphot/lib/pttables/pthdrs.x235
-rw-r--r--noao/digiphot/lib/pttables/ptkeywords.x615
-rw-r--r--noao/digiphot/lib/pttables/ptkid.x26
-rw-r--r--noao/digiphot/lib/pttables/ptkstat.x137
-rw-r--r--noao/digiphot/lib/pttables/ptmkrec.x86
-rw-r--r--noao/digiphot/lib/pttables/ptranges.x38
-rw-r--r--noao/digiphot/mkpkg14
-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
-rw-r--r--noao/digiphot/ptools/README23
-rw-r--r--noao/digiphot/ptools/Revisions395
-rw-r--r--noao/digiphot/ptools/cntrplot.par21
-rw-r--r--noao/digiphot/ptools/doc/istable.hlp64
-rw-r--r--noao/digiphot/ptools/doc/pcalc.hlp86
-rw-r--r--noao/digiphot/ptools/doc/pconcat.hlp50
-rw-r--r--noao/digiphot/ptools/doc/pconvert.hlp153
-rw-r--r--noao/digiphot/ptools/doc/pdump.hlp178
-rw-r--r--noao/digiphot/ptools/doc/pexamine.hlp835
-rw-r--r--noao/digiphot/ptools/doc/prenumber.hlp59
-rw-r--r--noao/digiphot/ptools/doc/pselect.hlp130
-rw-r--r--noao/digiphot/ptools/doc/psort.hlp64
-rw-r--r--noao/digiphot/ptools/doc/pttest.hlp78
-rw-r--r--noao/digiphot/ptools/doc/tbcalc.hlp79
-rw-r--r--noao/digiphot/ptools/doc/tbconcat.hlp49
-rw-r--r--noao/digiphot/ptools/doc/tbcrename.hlp50
-rw-r--r--noao/digiphot/ptools/doc/tbdump.hlp193
-rw-r--r--noao/digiphot/ptools/doc/tbkeycol.hlp50
-rw-r--r--noao/digiphot/ptools/doc/tbrenumber.hlp54
-rw-r--r--noao/digiphot/ptools/doc/tbselect.hlp107
-rw-r--r--noao/digiphot/ptools/doc/tbsort.hlp78
-rw-r--r--noao/digiphot/ptools/doc/txcalc.hlp80
-rw-r--r--noao/digiphot/ptools/doc/txconcat.hlp45
-rw-r--r--noao/digiphot/ptools/doc/txdump.hlp167
-rw-r--r--noao/digiphot/ptools/doc/txrenumber.hlp59
-rw-r--r--noao/digiphot/ptools/doc/txselect.hlp121
-rw-r--r--noao/digiphot/ptools/doc/txsort.hlp61
-rw-r--r--noao/digiphot/ptools/histplot.par20
-rw-r--r--noao/digiphot/ptools/istable.par7
-rw-r--r--noao/digiphot/ptools/lib/strip.ptoolsx0
-rw-r--r--noao/digiphot/ptools/lib/warning.dat12
-rw-r--r--noao/digiphot/ptools/mkpkg38
-rw-r--r--noao/digiphot/ptools/pcalc.cl50
-rw-r--r--noao/digiphot/ptools/pconcat.cl56
-rw-r--r--noao/digiphot/ptools/pconvert.par8
-rw-r--r--noao/digiphot/ptools/pconvert/mkpkg14
-rw-r--r--noao/digiphot/ptools/pconvert/ptconvert.x236
-rw-r--r--noao/digiphot/ptools/pconvert/ptdeftable.x375
-rw-r--r--noao/digiphot/ptools/pconvert/ptstrwrd.x51
-rw-r--r--noao/digiphot/ptools/pconvert/t_pconvert.x53
-rw-r--r--noao/digiphot/ptools/pdump.cl83
-rw-r--r--noao/digiphot/ptools/pexamine.par20
-rw-r--r--noao/digiphot/ptools/pexamine/mkpkg21
-rw-r--r--noao/digiphot/ptools/pexamine/pexamine.h115
-rw-r--r--noao/digiphot/ptools/pexamine/pexamine.key146
-rw-r--r--noao/digiphot/ptools/pexamine/ptahgmr.x44
-rw-r--r--noao/digiphot/ptools/pexamine/ptalimr.x35
-rw-r--r--noao/digiphot/ptools/pexamine/ptcolon.x668
-rw-r--r--noao/digiphot/ptools/pexamine/ptdelete.x335
-rw-r--r--noao/digiphot/ptools/pexamine/ptgetphot.x432
-rw-r--r--noao/digiphot/ptools/pexamine/ptimplot.x940
-rw-r--r--noao/digiphot/ptools/pexamine/ptplot.x1462
-rw-r--r--noao/digiphot/ptools/pexamine/ptrddata.x125
-rw-r--r--noao/digiphot/ptools/pexamine/ptsetup.x360
-rw-r--r--noao/digiphot/ptools/pexamine/ptwtfile.x143
-rw-r--r--noao/digiphot/ptools/pexamine/t_pexamine.x188
-rw-r--r--noao/digiphot/ptools/prenumber.cl50
-rw-r--r--noao/digiphot/ptools/pselect.cl77
-rw-r--r--noao/digiphot/ptools/psort.cl42
-rw-r--r--noao/digiphot/ptools/ptools.cl50
-rw-r--r--noao/digiphot/ptools/ptools.hd34
-rw-r--r--noao/digiphot/ptools/ptools.men24
-rw-r--r--noao/digiphot/ptools/ptools.par3
-rw-r--r--noao/digiphot/ptools/pttest.cl550
-rw-r--r--noao/digiphot/ptools/ptutils/mkpkg12
-rw-r--r--noao/digiphot/ptools/ptutils/t_istable.x71
-rw-r--r--noao/digiphot/ptools/ptutils/t_tbcrename.x73
-rw-r--r--noao/digiphot/ptools/ptutils/t_tbkeycol.x140
-rw-r--r--noao/digiphot/ptools/radplot.par22
-rw-r--r--noao/digiphot/ptools/surfplot.par10
-rw-r--r--noao/digiphot/ptools/tbcalc.cl37
-rw-r--r--noao/digiphot/ptools/tbconcat.cl113
-rw-r--r--noao/digiphot/ptools/tbcrename.par6
-rw-r--r--noao/digiphot/ptools/tbdump.cl44
-rw-r--r--noao/digiphot/ptools/tbkeycol.par5
-rw-r--r--noao/digiphot/ptools/tbrenumber.cl36
-rw-r--r--noao/digiphot/ptools/tbselect.cl20
-rw-r--r--noao/digiphot/ptools/tbsort.cl21
-rw-r--r--noao/digiphot/ptools/test/gcommands.dat3
-rw-r--r--noao/digiphot/ptools/test/icommands.dat1
-rw-r--r--noao/digiphot/ptools/test/test1.dat133
-rw-r--r--noao/digiphot/ptools/test/test2.dat315
-rw-r--r--noao/digiphot/ptools/txcalc.par6
-rw-r--r--noao/digiphot/ptools/txconcat.par6
-rw-r--r--noao/digiphot/ptools/txdump.par8
-rw-r--r--noao/digiphot/ptools/txrenumber.par6
-rw-r--r--noao/digiphot/ptools/txselect.par6
-rw-r--r--noao/digiphot/ptools/txsort.par6
-rw-r--r--noao/digiphot/ptools/txtools/mkpkg23
-rw-r--r--noao/digiphot/ptools/txtools/ptqsort.x215
-rw-r--r--noao/digiphot/ptools/txtools/ptrenumb.x221
-rw-r--r--noao/digiphot/ptools/txtools/ptsortnum.x446
-rw-r--r--noao/digiphot/ptools/txtools/ptxcalc.x255
-rw-r--r--noao/digiphot/ptools/txtools/ptxdump.x421
-rw-r--r--noao/digiphot/ptools/txtools/ptxselect.x160
-rw-r--r--noao/digiphot/ptools/txtools/t_txcalc.x65
-rw-r--r--noao/digiphot/ptools/txtools/t_txconcat.x128
-rw-r--r--noao/digiphot/ptools/txtools/t_txdump.x45
-rw-r--r--noao/digiphot/ptools/txtools/t_txrenumber.x65
-rw-r--r--noao/digiphot/ptools/txtools/t_txselect.x64
-rw-r--r--noao/digiphot/ptools/txtools/t_txsort.x65
-rw-r--r--noao/digiphot/ptools/x_ptools.x11
-rw-r--r--noao/digiphot/ptools/xyplot.par20
869 files changed, 166003 insertions, 0 deletions
diff --git a/noao/digiphot/apphot/README b/noao/digiphot/apphot/README
new file mode 100644
index 00000000..8324e8d7
--- /dev/null
+++ b/noao/digiphot/apphot/README
@@ -0,0 +1,35 @@
+ The Aperture Photometry Package
+ ----------------------------------
+
+The apphot package contains routines which perform aperture
+photometry in circular and polygonal apertures using fractional pixel
+techniques. No point spread function fitting techniques are employed.
+The photometry routines are most suitable for use on uncrowded
+or moderately crowded fields.
+
+The apphot directory structure is listed below. The package organization
+is by task, for example the center subdirectory contains routines
+specific to the center task or by function, for example the nlfit
+directory contains the non-linear least squares fitting routines.
+The wphot task shares alot of code with the phot task. Similarly
+the polymark task shares some code with the polyphot task.
+The .h files are all in lib as many of them are shared by several tasks.
+
+ |-aplib---------apphot routines used by several tasks
+ |-aputil--------miscellaneous useful routines
+ |-center--------routines specific to centering, the center task
+ |-daofind-------routines specific to the daofind task
+ |-doc-----------apphot documentation
+|-apphot-----|-fitpsf--------routines specific to the fitpsf task
+ |-fitsky--------routines specific to sky fitting, the fitsky task
+ |-lib-----------apphot definitions or .h files
+ |-phot----------routines specific to the qphot/phot tasks
+ |-polyphot------routines specific to the polyphot/polymark tasks
+ |-radprof-------routines specific to the radprof task
+ |-wphot---------routines specific to the wphot task
+ |-test----------directory of test data
+
+
+Lindsey Davis
+NOAO IRAF GROUP
+November 1991
diff --git a/noao/digiphot/apphot/Revisions b/noao/digiphot/apphot/Revisions
new file mode 100644
index 00000000..99578517
--- /dev/null
+++ b/noao/digiphot/apphot/Revisions
@@ -0,0 +1,1582 @@
+.HELP revisions Jun88 noao.digiphot.apphot
+.nf
+
+
+apphot/wphot/apwmag.x
+ Minor typo where procedure closed with a ']' (8/19/09, MJF)
+
+apphot/wphot/t_wphot.x
+ A call to apstats() was being passed 'cl' instead of 'ap' (8/19/09, MJF)
+
+apphot/phot/apqradsetup.x
+apphot/phot/apradsetup.x
+apphot/wphot/apbwphot.x
+ The ap_wmag() was incorrectly being used as apwmag() (8/17/09, MJF)
+
+apphot/aputil/apvectors.x
+ Modified so the calculation is done in floating point (8/15/09, MJF)
+
+apphot/daofind/apfdcolon.x
+ A call to apsets() was mistakenly using a closed 'cl' pointer instead
+ of the 'ap' apphot struct pointer (8/15/09, MJF)
+
+apphot/radprof/apfrprof.x
+ The cvrject() subroutine was called w/ an extra argument (7/12/09, MJF)
+
+apphot/aputil/apnlfuncs.x
+ 1. Comments now say whether a parameter is a variance or a sigma.
+ 2. Check for zero variance or sigma were improved. The default value
+ is a sigma of 6 or a variance of 36.
+ 3. CGAUSS1D was setting the wrong variable (z instead of r2) when
+ a zero variance is found.
+ (3/18/09, Valdes: reported by Jason Quinn)
+
+aplib/apwparam1.x
+ The CLEAN parameter was being printed with UN_CSCALEUNIT units instead
+ of UN_CSWITCH (7/8/08, MJF)
+
+aplib/apwparam1.x
+ The format string had 'yyy' instead of 'yyyy'.
+ (5/27/08, Valdes)
+
+apphot/fitpsf/apsffit.x
+apphot/phot/apmag.x
+apphot/phot/apremag.x
+apphot/wphot/apwmag.x
+apphot/wphot/apwremag.x
+ Fixed some procedure calls being closed with a ']' instead of a ')'
+ (2/17/08, MJF)
+
+=======
+V2.12.3
+=======
+
+apphot/aputil/apnlfuncs.x
+ Catch error when the input sigma is zero. (5/2/05, Valdes)
+
+=======
+V2.12.2
+=======
+
+apphot/aputil/aptopt.x
+ Catch error when the input sigma is zero. (2/24/03, Valdes)
+
+apphot/center/t_center.x
+apphot/fitpsf/t_fitpsf.x
+apphot/fitsky/t_fitsky.x
+apphot/phot/t_phot.x
+apphot/phot/t_qphot.x
+apphot/polyphot/t_polyphot.x
+apphot/radprof/t_radprof.x
+apphot/wphot/t_wphot.x
+ The handling of the "default" parameter value for coordinate lists
+ failed when the input list had more than one image. The way this
+ was done relied on a string not being modified but it was being
+ modified in a call to apfroot. (9/30/02, Valdes)
+
+=======
+V2.12.1
+=======
+
+apphot/center/apcenter.x
+apphot/fitpsf/apfitpsf.x
+apphot/fitsky/apsky.x
+apphot/phot/apphot.x
+apphot/polyphot/apyhot.x
+apphot/radprof/apradprof.x
+apphot/wphot/apwphot.x
+ Fixed problems with the 'v' that can occur if the same star is measured
+ with different parameters without an intervening cursor move.
+
+ Davis, June 20, 2002
+
+apphot/fitsky/mkpkg
+ declaration. Added a missing <imhdr.h> file dependency to the apsky.x
+ declaration.
+
+ Davis, December 13, 2001
+
+apphot/daofind/mkpkg
+ Removed an unnecessary ../lib/display.h file dependency from the apbfdfind
+ declaration. Added a missing ../lib/display.h file dependency to the
+ apfdcolon.x declaration.
+
+ Davis, December 13, 2001
+
+apphot/aputil/appcache.x
+ Added a call setting IM_BUFFRAC to 0 to the memory caching code in the
+ apphot package tasks in order to force the imio buffer to be the size of
+ the input image.
+
+ Davis, December 10, 2001
+
+apphot/center/apcenter.x
+ Fixed a boolean / integer conversion problem in the interactive variable.
+ This bug should not be present in released code.
+
+ Davis, September 19, 2001
+
+apphot/polyphot/apymkinit.x
+ The call to ap_defsetup was missing the fwhmpsf argument. Since
+ this is never used in the code this bug may not cause a problem.
+
+ Davis, September 19, 2001
+
+apphot/aplib/apwres2.x
+ The pargr routine was being called with a double precision constant
+ 0.0d0 argument.
+
+ Davis, September 19, 2001
+
+apphot/fitsky/apcentroid.x
+ Fixed a real/double type mismatch in a call to alimr.
+
+ Davis, September 19, 2001
+
+apphot/
+ Modified all the apphot tasks to accept input coordinates in logical, tv,
+ physical, or world coordinates and to write the output coordinates in
+ logical, tv, or physical coordinates. One consequence of this is that
+ the apphot tasks will now work correctly off image sections in interactive
+ mode. Another is that users can work on image sections while preserving
+ the coordinate system of the entire image.
+
+ Davis, May 30, 2000
+
+apphot/
+ Modified all the apphot tasks to strip the directory information from
+ the input image and coordinate file names written to the output files,
+ to the terminal, and to the plot headers. The colon commands will still
+ read and write full image and coordinate file path names. This change
+ improves the likelyhood that the full root image name will be written
+ to the output. This root image name is used by the photometric calibration
+ code to construct images sets.
+
+ Davis, April 19, 2000
+
+apphot/*/mkpkg
+ Added some missing file dependencies and deleted some unecessary ones
+ from the mkpkg files.
+
+ Davis, September 20, 1999
+
+apphot/polyphot/apyfit.x
+apphot/polyphot/appyerrors.x
+apphot/aplib/apwres2.x
+ Improved the error reports for polyphot in the case where the effective
+ aperture is 0, which may occur if the polygon is off the image or due
+ to fractional pixel effects.
+
+ Davis, August 10, 1999
+
+apphot/polyphot/apyget.x
+apphot/polyphot/apmkpylist.x
+apphot/polyphot/ayphot.x
+apphot/polyphot/apyradsetup.x
+ Modified the polygon drawing code (the g keystroke command) to flush
+ the graphics buffer after every polygon segement is drawn instead
+ of after the polygon is complete.
+
+ Davis, July 9, 1999
+
+apphot/aputil/apotime.x
+ Modified the code which reads the time of observation value from the image
+ header to extract the time field from the date-obs keyword if it is
+ present.
+
+ Davis, May 11, 1999
+
+apphot/aputil/apdate.x
+ Modified the date and time photometry file keyword encoding tasks to
+ write the date and time in the proper fits format and in units of GMT.
+ Note that GMT is deactivated in digiphotx because the necessary routine
+ is not yet in the system.
+
+ Davis, May 11, 1999
+
+apphot/aputil/apfnames.x
+ Modified the default input and output file nameing routines to handle
+ input images with kernel sections and cluster indices more gracefully.
+
+ Davis, January 17, 1999
+
+apphot/aplib/apwparam1.x
+apphot/aputil/apdate.x
+ Modified the apphot output file writing routines to write the "DATE"
+ keyword in the new FITS standard format, eg. yyyy-mm-dd instead of
+ mm-dd-yy.
+
+ Davis, December 29, 1998
+
+apphot/daofind/t_daofind.x
+ Modified the default output file naming code to support names of the
+ form "directory/default" as well as "default" in interactive mode
+ as well as non-interactive mode.
+
+ Davis, February 13, 1998
+
+apphot/daofind/apfind.x
+ Modified the centering routines to protect against a rare floating
+ divide by 0 condition.
+
+ Davis, June 24, 1997
+
+apphot/aptest.cl
+ Modified the rfits calling sequence so that the test script will
+ run correctly with the new version of rfits.
+
+ Davis, May 29, 1997
+
+apphot/daofind/apfind.x
+ Modified the routine that computes the new roundness parameter to check
+ for <= 0.0 quantities in the denominator of the new roundness statistic.
+ Zero valued quantities can in rare cases cause a divide by zero or
+ floating operand error.
+
+ Davis, July 21, 1996
+
+apphot/lib/polyphotdef.h
+apphot/aplib/apset1.x
+apphot/aplib/apset2.x
+apphot/aplib/apset.x
+apphot/aplib/apstat1.x
+apphot/aplib/apstat2.x
+apphot/aplib/apstat.x
+apphot/aplib/apwres2.x
+apphot/aplib/aparrays.x
+apphot/aplib/aprcursor1.x
+apphot/aplib/mkpkg
+apphot/phot/apmag.x
+apphot/phot/apremag.x
+apphot/phot/appinit.x
+apphot/phot/appfree.x
+apphot/phot/appplot.x
+apphot/phot/apmeasure.x
+apphot/phot/apcomags.x
+apphot/phot/mkpkg
+apphot/wphot/apwmag.x
+apphot/wphot/apwremag.x
+apphot/wphot/apgmeasure.x
+apphot/wphot/aptmeasure.x
+apphot/wphot/mkpkg
+apphot/radprof/apfrprof.x
+apphot/radprof/aprpindex.x
+apphot/radprof/aprpplot.x
+apphot/radprof/aprmmeasure.x
+apphot/polyphot/apyfit.x
+apphot/polyphot/mkpkg
+ Modified the aperture sum routines to work in double precision where
+ appropriate. This avoids rounding errors that become visible when
+ working on synthetic data or data with neglible sky noise.
+
+ Davis, July 18, 1996
+
+apphot/doc/qphot.hlp
+ Fixed some typos / omissions in the qphot help page.
+
+ Davis, April 11, 1996
+
+apphot/apphot.cl
+apphot/apphot.men
+ Replaced the txdump task with the more general pdump task and added the
+ pcalc, pconvert, prenumber, pselect, and psort tasks to the apphot
+ package.
+
+ Davis, March 15, 1996
+
+apphot/aplib/apwres1.x
+apphot/daofind/apfind.x
+ Fixed a serious bug in the daofind centering code which resulted
+ in incorrect fractional pixel corrections being computed. This error
+ can most easily be detected by plotting the histogram of the fractional
+ pixel corrections for an image with a large number of detected objects.
+ The histogram will be modulated with "peaks" around the .33 and .66
+ fractional pixel values.
+
+ This bug is also present in the standalone version of daophot ii. User
+ should obtain a new version of daophot ii from Peter Stetson.
+
+ Added a new roundness statistic to daofind. This statistic is sensitive
+ to objects which are elongated in directions other than x and y.
+
+ Davis, March 15, 1996
+
+apphot/center/apcenter.x
+apphot/fitpsf/apfitpsf.x
+apphot/fitsky/apsky.x
+apphot/phot/apphot.x
+apphot/phot/apqphot.x
+apphot/polyphot/apyphot.x
+apphot/radprof/apradprof.x
+apphot/wphot/apwphot.x
+ The new m keystroke command was doing exactly the same thing as the n
+ keystroke command due to a confusion of the key and colonkey variables.
+
+ Davis, Feb 12, 1996
+
+apphot/doc/centerpars.hlp
+apphot/center/mkpkg
+apphot/center/apfitcen.x
+apphot/center/aprefitcen.x
+apphot/center/apcplot.x
+apphot/aputil/apgtools.x
+ Modified the centering algorithm code to recognize 3 separate cases:
+ 1) cthreshold = 0.0 invokes the default thresholding technique for
+ each algorithm, 2) cthreshold = +val sets the threshold to some
+ value above (below) the local data minimum (maximum), 3) cthreshold=INDEF
+ or undefined turns off all thresholding. This change does not
+ change the default behavior of the code.
+
+ Changed the definition of local data minimum from the minimum pixel
+ in the centering box to the minimum median value for each row in the
+ centering box. This gives a value much closer to the background values
+ and protects against very low valued pixels in the centering box defining
+ the thresholding level.
+
+ Davis, Sept 29, 1995
+
+apphot/fitsky/apskybuf.x
+ Changed the misleading error return code from AP_SKY_OUTOFBOUNDS to
+ AP_NSKY_TOO_SMALL in the case when all the sky are out of the good
+ data range.
+
+ Davis, June 22, 1995
+
+apphot/daofind/apfind.x
+ Added a check to avoid a divide by zero error in the code which computes
+ the x and y positions of the detected objects. The divide by zero error
+ can occur when the datamin value is too high for the image and there
+ are not enough points to accurately compute the new x and y position.
+
+ Davis, June 19, 1995
+
+apphot/aplib/mkpkg
+apphot/aplib/apwres1.x
+apphot/aplib/apwres2.x
+apphot/aplib/apwres3.x
+apphot/aplib/apwres4.x
+apphot/doc/phot.hlp
+apphot/doc/polyphot.hlp
+apphot/doc/qphot.hlp
+apphot/doc/radprof.hlp
+apphot/doc/wphot.hlp
+ Added a FLUX column to the output of the PHOT, POLYPHOT, QPHOT, RADPROF,
+ and WPHOT tasks and updated the appropriate help pages.
+
+ Davis, Nov 14, 1994
+
+apphot/daofind/apfdstars.x
+apphot/daofind/apbfdfind.x
+ Added a missing check for an INDEF value of sigma that could cause
+ a floating point overflow in daofind when run from the APPHOT package
+ with the default parameters.
+
+ Davis, Oct 20, 1994
+
+apphot/aplib/apwres2.x
+ Added a check to make sure that the OTIME and IFILTER fields do not
+ overflow the 23 character space allotted for them in the output file.
+
+ Davis, Oct 12, 1994
+
+apphot/center/t_center.x
+apphot/daofind/t_daofind.x
+apphot/fitpsf/t_fitpsf.x
+apphot/fitsky/t_fitsky.x
+apphot/phot/t_phot.x
+apphot/phot/t_qphot.x
+apphot/polyphot/t_polymark.x
+apphot/polyphot/t_polyphot.x
+apphot/radprof/t_radprof.x
+apphot/wphot/t_wphot.x
+ Fixed a bug in the default input and output file naming code which was
+ causing the directory specifications to be stripped from the names.
+
+ Davis, Oct 4, 1994
+
+apphot/phot/apphot.x
+apphot/phot/apqphot.x
+apphot/wphot/apwphot.x
+apphot/polyphot/apyphot.x
+apphot/radprof/apradprof.x
+apphot/phot/phot.key
+apphot/phot/qphot.key
+apphot/wphot/wphot.key
+apphot/polyphot/polyphot.key
+apphot/radprof/radprof.key
+apphot/doc/phot.hlp
+apphot/doc/qphot.hlp
+apphot/doc/wphot.hlp
+apphot/doc/polyphot.hlp
+apphot/doc/radprof.hlp
+ Added a new keystroke command 'a' to the phot, qphot, wphot, polyphot
+ and radprof commands. The a keystroke command compute a sky value
+ by averaging several sky values sampled in different regions of the
+ image. Basically it is a loop over the the t keystroke command.
+ The sky value in each region is computed using the current algorithm
+ and geometry and the individual sky, sky sigma and sky skew values
+ are averaged to produce a final sky, sigma and skew, whereas the
+ number of sky pixels and number of rejected sky pixels are summed.
+ The a keystroke command is intended for use with the p and o keystroke
+ commands to produce an offset sky measurement capability.
+
+ Davis, Feb 10, 1994
+
+apphot/fitpsf/apsffit.x
+apphot/fitpsf/apsfrefit.x
+apphot/aplib/apwres4.x
+ 1. Modified the fitpsf task fitting routines so that the parameter and
+ parameter error arrays are initialized to INDEF (instead of being left
+ with the values from the previous fit), in the case that the
+ fitting box is entirely off the image or that that there are too few
+ pixels in the fitting box to fit the model psf.
+ 2. Modified the output formatting routines to print the errors in
+ the fitted rsigma (function=radgauss), xsigma and ysigma (function=
+ elgauss), and rgyrat and ellip (function=moments) to three decimal
+ places instead of two.
+
+ Davis, Jan 17, 1994
+
+apphot/center/t_center.x
+apphot/fitpsf/t_fitpsf.x
+apphot/fitsky/t_fitsky.x
+apphot/phot/t_phot.x
+apphot/polyphot/t_polyphot.x
+apphot/phot/t_qphot.x
+apphot/phot/t_radprof.x
+apphot/wphot/t_wphot.x
+ If the number of input images was greater than one, the number of output
+ files exactly equal to one, and the input coordinate file for the image
+ did not contain any decodable coordinates the coordinate file rather
+ than the empty output file is deleted. This was ocurring because the
+ output file was not being correctly stored each time through the image
+ loop and empty output files are deleted by the apphot tasks.
+
+ Davis, Dec 31, 1993
+
+apphot/fitsky/aprefitsky.x
+ The SCALE parameter in the call to ap_crossor was incorrectly
+ dereferenced as AP_SCALE(sky) instead of AP_SCALE(ap).
+
+ Davis, Sep 13, 1993
+
+apphot/aplib/apinpars2.x
+ The shiclip parameter, default = 0.0, was incorrectly being set to the
+ value of the sloclip parameter at startup time.
+
+ Davis, Sep 9, 1993
+
+apphot/center/aprefitcen.x
+ The CMAXITER parameter was incorrectly referenced in the call to
+ the ap_lgctr1d routine inside the routine aprefitcenter.
+ This centering routine is not often used, and the bug is trigggered
+ only if an object is recentered using different algorithm parameters
+ but the same image data, something only likely to occur in interactive
+ mode.
+
+ Davis, Sep 6, 1993
+
+apphot/center/apcencolon.x
+ The arugument cmdstr in the routine apcentercolon was declared as
+ "char cmdstr" instead of "char cmdstr[ARB]. This has not caused any
+ errors in the code but is poor style.
+
+ Davis, Sep 6, 1993
+
+apphot/phot/apgqppars.x
+apphot/doc/qphot.hlp
+apphot/fitskypars.par
+apphot/doc/fitskypars.hlp
+ Changed the default sky fitting algorithm for the qphot and phot tasks from
+ "mode" to "centroid" with histogram smoothing, to minimize problems
+ with data taken at low light levels which have poorly sampled
+ histograms.
+
+ Davis, Aug 14, 1993
+
+apphot$
+ The sky fitting routines were revised. Two new parameters, ploclip and
+ phiclip, which define the percentage of pixels to clip on the low
+ and high sides of the sky pixel distribution were added to fitskypars. The
+ fitskypars parameter skreject was split into two parameters
+ sloreject and shireject which define the low and high side rejection
+ parameters respectively. For the mean, median, and mode algorithms
+ the first rejection cut is now made below sky - min (smax - sky, sky - smin,
+ sloreject * skysigma) and above sky + min (smax - sky, sky - smin,
+ shireject * skysigma) where sky is the first estimate of the mean, median,
+ and median of the sky pixels respectively, instead of below and above the
+ skreject rejection limits alone. The median is computed using
+ the average of 5% of the pixels around the median instead of 10 pixels.
+ All the histogram dependent algorithms: histplot, centroid, gauss,
+ crosscor, ofilt now use the median of the sky pixels as the center
+ of the histogram, and define the extent of the
+ histogram in a manner similar to that used for the first cut in
+ the mean, median, and mode algorithms. The sigma parameter is
+ no longer used to define the extent and binsize of the sky histogram.
+ Instead the computed sky sigma is used.
+
+ Added m and n keys to the apphot tasks. These keys operate in the same
+ way as the :m and :n keys which have no arguments.
+
+ Added the o key to the apphot tasks. This behaves in the same way
+ as the p key but outputs the results to the output results file.
+
+ Davis, Feb 24, 1993
+
+apphot/aputil/apgflags.x
+ Removed this routine which was not being used and referenced gio.h from
+ the apphot library.
+
+ Davis, Feb 11, 1993
+
+apphot/daofind
+
+ Added the findpars pset to the daofind task and removed the parameter
+ threshold from datapars to findpars. All the detection algorithm
+ parameters moved to findpars.
+
+ Changed the name of the output convolved image to starmap. Added
+ an option to output the best fit sky image skymap.
+
+ Davis, Sept 17, 1992
+
+apphot$
+ Modified all tasks (daofind, center, fitpsf, fitsky, phot, polymark,
+ polyphot, qphot, radprof, and wphot) that were designed to draw marks
+ on the image display to use the imd kernel. All graphics
+ drawing commands are done with portable gio calls. A temporary routine
+ which uses the imd interface to fetch the display device viewport and
+ window is called each time a new image is mapped. A warning message
+ is issued if the image is not loaded in the display and the default
+ full frame viewport is used. All display drawing is done to the
+ current frame, even if the current frame is not the frame containing
+ the image. The imd kernel does not support the gflush command so
+ a gframe command is used instead. This can create a messy metacode
+ file but is a reasonable approximation for interactive use.
+
+ Davis, Sep 2, 1992
+
+apphot$phot/apphotcolon.x
+apphot$phot/apqcolon.x
+apphot$radprof/aprpcolon.x
+apphot$wphot/apwpcolon.x
+apphot$wphot/aptmeasure.x
+apphot$wphot/apgmeasure.x
+apphot$aplib/apverify1.x
+apphot$daofind/apfcolon.x
+apphot$fitpsf/apppsf.x
+apphot$fitpsf/apsfcolon.x
+apphot$polyphot/apycolon.x
+ Added some missing sfree statements.
+
+ Davis, Sep 2, 1992
+
+apphot$fitsky/aplgsky,x
+ The test "if (ier != AP_OK)" was being made instead of the proper test
+ "if (iter < 0)". The local variable ier was never defined or used which
+ tripped a bug in the DEC fortran compiler.
+
+ Davis, August 3, 1992
+
+apphot$datapars.par
+apphot$centerpars.par
+apphot$doc/datapars.hlp
+apphot$doc/centerpars.hlp
+apphot$lib/noisedef.h
+apphot$lib/noise.h
+apphot$lib/centerdef.h
+apphot$lib/center.h
+apphot$center/apcinit.x
+apphot$center/apcencolon.x
+apphot$center/apcshow.x
+apphot$center/apcconfirm.x
+apphot$center/apcplot.x
+apphot$center/apfitcen.x
+apphot$center/refitcen.x
+apphot$aplib/apinit.x
+apphot$aplib/apnscolon.x
+apphot$aplib/apnshow.x
+apphot$aplib/apinpars.x
+apphot$aplib/apoutpars.x
+apphot$aplib/aprcursor1.x
+apphot$aplib/apverify1.x
+apphot$aplib/apset2.x
+apphot$aplib/apstat2.x
+apphot$aplib/apwparam1.x
+ Changed the units of the cthreshold parameter to sigma and moved it
+ to the centerpars parameter set.
+
+ Davis, July 7, 1992
+
+apphot$center/t_center.x
+apphot$fitpsf/t_fitpsf.x
+apphot$fitsky/t_fitsky.x
+apphot$phot/t_phot.x
+apphot$phot/t_qphot.x
+apphot$polyphot/t_polyphot.x
+apphot$radprof/t_radprof.x
+apphot$wphot/t_wphot.x
+ 1. The apphot tasks center, fitspf, fitsky, phot, qphot, polyphot,
+ radprof, anbd wphot were not closing the coordinate files correctly
+ in the case that coords="default" was the length of the coordinate
+ list was being incorrectly set to 1.
+
+ Davis, June 24, 1992
+
+apphot$aplib/apapcolon.x
+ 1. The interactive :image <imname> command was not updating the time of
+ observation correctly since the obstime keyword was not being read.
+
+ Davis, June 23, 1992
+
+apphot$polyphot/apyfit.x
+ 1. Improved the precision of the polyphot fractional pixel algorithm.
+
+ Davis, April 1, 1992
+
+apphot$polyphot/apyfit.x
+ 1. The intersection points of an image line and a polygon could
+ be incorrectly translated into a list of ranges if the polygon was
+ concave and contained a side collinear with the image line.
+
+ Davis, February 25, 1991
+
+apphot$daofind/apfdstars.x
+ 1. Removed an extraneous "include <fset.h> statement from daofind.
+
+ Davis, November 20, 1991
+
+ *** Ran spplint on the apphot code
+
+apphot$daofind/apfshow.x
+apphot$aplib/apnshow.x
+apphot$aplib/apqshow.x
+apphot$aplib/apwparam1.x
+ 1. Fixed several places in the code where the boolean function itob
+ was declared an integer.
+
+apphot$aplib/apoutpars.x
+ 1. Removed an extra maxch argument from all the clppset calls.
+
+apphot$fitpsf/apppfpars.x
+apphot$phot/apqppars.x
+ 1. Removed an extra argument from the clpstr call.
+
+apphot$aplib/aprcursor2.x
+ 1. The call to ap_rparam in ap_cpapert was being made with the integer
+ argument PSFAPERT instead of the string argument KY_PSFAPERT.
+
+apphot$fitsky/apskycolon.x
+ 1. The calls to ap_apcolon and ap_nscolon were being made with a type
+ real junk variable instead of a type in junk variable. This was harmless.
+
+apphot$fitsky/apspshow.x
+ 1. Changed a pargi call to a pargb call.
+
+ Davis, Oct 7, 1991
+
+apphot$test/aptest.cl
+ 1. Made some minor formatting changes to the aptest CL script.
+
+ Davis, Aug 23, 1991
+
+apphot$aplib/apfrprof.x
+ 1. Radprof was incorrectly normalizing the integral of the total intensity,
+ by failing to multiply by the step size.
+
+ Davis, Aug 23, 1991
+
+apphot$aplib/apwres2.x
+apphot$radprof/apprprof.x
+ 1. Changed the unit on output for the radial profile and fwhm from "pixels"
+ to "scale".
+
+ Davis, Aug 23, 1991
+
+apphot$aplib/apwres1.x
+ 1. Changed the unit for RAPERT on output from "pixels" to "scale".
+
+ Davis, Aug 23, 1991
+
+apphot$
+ 1. Support for picking up the time of observation, for example UT, was
+ added to all the apphot routines.
+
+ 2. Apphot will now print out INDEF for all object which have bad data
+ inside the photometry apertures.
+
+ 3. Whitespace is stripped from the filter id and the iraf version
+ definition before either of these quantities is written to the photometry
+ files.
+
+ 4. The output file header parameters are now 23 characters long instead
+ of 15.
+
+ 5. The numerical values of the error codes have been changed for book-
+ keeping purposes.
+
+ Davis, August 1, 1991
+
+apphot$apselect/
+ 1. Added the replacement task for apselect, txdump, to the package.
+
+ 2. Added the pexamine task to the package.
+
+ 3. Removed the apselect subdirectory.
+
+ Davis, July 29, 1991
+
+apphot$qphot/
+apphot$polymark/
+apphot$nlfit/
+
+ 1. Moved all the routines in the qphot subdirectory into the phot
+ subdirectory and deleted the qphot subdirectory.
+
+ 2. Moved all the routines in the polymark subdirectory into the polyphot
+ subdirectory and deleted the polymark subdirectory.
+
+ 3. Removed the old nlfit library from the apphot package and replaced it
+ with the new version which has been installed in the math package.
+ The affected algorithms are the gauss centering algorithm, the gauss
+ sky fitting algorithm, and the fitpsf task radial and elliptical gaussian
+ function fitting algorithms.
+
+ 4. The errors computed by the gauss centering routine are smaller in the
+ new version than the old version as the old code was dividing by sqrt
+ (nfree) instead of sqrt (npts).
+
+ Davis, July 28, 1991
+
+apphot$fitpsf/apsffit.x
+apphot$fitpsf/apsfrefit.x
+apphot$fitpsf/apsfradgauss.x
+apphot$fitpsf/apsfelgauss.x
+ 1. The errors computed by the fitpsf radial and elliptical gaussian
+ fitting routines are smaller in the new version than the old version
+ as the old code was dividing by sqrt (nfree) instead of sqrt (npts).
+
+ 2. The error output for rsigma in the fitpsf radial gaussian fitting
+ routine and for xsigma/ysigma in the elliptical gaussian fitting routines
+ in the old code was actually the error in rsigma ** 2 or xsigma ** 2
+ and ysigma ** 2 respectively. These errors were too small.
+
+ Davis, July 28, 1991
+
+apphot$center/apfitcen.x
+apphot$center/aprefitcen.x
+apphot$center/apgctr1d.x
+apphot$center/aplgctr1d.x
+apphot$aputil/aptopt.x
+apphot$aputil/apqzero.x
+ 1. Modified all the centering routines so that the fitted centers are
+ contrained to stay in the fitting box after each iteration. The gauss
+ algorithm in particular could runaway when fitting objects near the
+ edge of the frame or very weak objects.
+
+ 2. Fixed a bug in the optimal filter algorithm wherein the
+ normalization procedure could fail if there wa no star in the
+ centering box.
+
+ Davis, May 30, 1991
+
+apphot$center/apcconfirm.x
+apphot$fitsky/apsconfirm.x
+apphot$phot/appconfirm.x
+apphot$wphot/apwconfirm.x
+apphot$polyphot/apyconfirm.x
+apphot$radprof/aprconfirm.x
+apphot$fitpsf/appsfconfirm.x
+ 1. Modified all the apphot task verify routines to verify datamin and
+ datamax.
+
+ Davis, Mar 29, 1991
+
+apphot$nlfit/nliter.x
+apphot$nlfit/nlacpts.x
+ 1. Modified nlfit routines to get rid of the wtflag argument in those
+ routines where it was not actually used.
+
+ Davis, Nov 20, 1990
+
+apphot$aputil/apwlimr.x
+apphot$fitpsf/apsfradgauss.x
+apphot$fitpsf/apsfelgauss.x
+apphot$fitpsf/apsffit.x
+apphot$fitpsf/apsfrefit.x
+ 1. Modified the fitpsf task so the the radial gaussian and elliptical
+ gaussian fitting routines use the maximum (emission objects) or
+ minimum (absorption objects) pixel position as the first guess for
+ a good position instead of the center position.
+
+ Davis, Nov 16/1990
+
+apphot$daofind/apbfdfind.x
+apphot$daofind/apconvolve.x
+apphot$daofind/apfdstars.x
+ 1. Fixed a bug in the batch mode execution of DAOFIND wherein
+ DAOFIND quit with an "cannot write pixel file error" when run on
+ a previously existing convolved image. This bug was introduced by the
+ Mar 12 1990 bugfix.
+
+ Davis, Nov 8, 1990
+
+apphot$polyphot/t_polyphot.x
+apphot$lib/polyphot.h
+ 1. Changed the default size of MAX_NVERTICES from 100 to 900 to satisfy
+ some surface photometry people. Removed a redundant MAX_NVERTICES
+ declaration in t_polyphot.x
+
+ Davis, Aug 24, 1990
+
+apphot$phot/apmagbuf.x
+ 1. Phot was refusing to fit stars whose apertures were < 1.0 pixels from
+ the edge of the image because the out-of-bounds criterion was too
+ conservative. I modified the code to remove this problem.
+
+ Davis, Aug 6, 1990
+
+apphot$daofind/apbfdfind.x
+apphot$daofind/apfdstars.x
+apphot$daofind/apfind.x
+ 1. Changed the daofind program to automatically include the relative
+ error in the detection threshold.
+
+Davis, July 17, 1990
+
+apphot$fitsky/apskybuf.x
+ 1. In a few cases due to fractional pixel effects the skyfitting
+ routines were not preallocating sufficient space to hold the sky
+ pixels resulting in a memory corruption error.
+
+ Davis, June 27, 1990
+
+apphot$aplib/apfrprof.x,mkpkg
+ 1. Modified radprof so that it would integrate 2*PI*r*I instead of
+ just I itself.
+
+ Davis, June 18, 1990
+
+apphot$aplib/apfdres.x
+ 1. Renamed the round and sharp parameters to roundness and sharp to
+ remove and ambiguity in the naming convention.
+
+ Davis, May 24, 1990
+
+apphot$daofind/apconvolve.x
+ 1. Added an imflush after the last write in apconolve which cured
+ a "pixel file is truncated error". This error showed up when
+ daofind was run on an image that was 641 by 1025 but not on
+ one that was 640 by 1024. Apparently this problem has been there
+ all along but only occurs very rarely.
+
+ Davis, Mar 29, 1980
+
+apphot$aptest.cl
+apphot$aptest.par
+ 1. Added the aptest task to the apphot package.
+
+ Davis, Mar 19, 1990
+
+apphot$aplib/
+ 1. Fixed two bugs in the output formating code. Long file names could
+ overflow the fixed format space allotted and destroy the syntax of the
+ file making it impossible for apselect to decode it. Second the COORDS
+ parameter was mistakenly typed as integer instead of string.
+ Davis, Mar 14, 1990
+
+apphot$daofind/
+ 1. Fixed a bug which was causing daofind to fail to compute the convolved
+ image when the input and output images were in hhh format. The hhh format
+ was failing the test [if (IM_PIXFILE(im) == EOS)] as the pixel
+ file names are set at different places in the oif and stf kernel.
+ The test was dangerous and redundant, and has been removed.
+
+ Davis, Mar 12, 1990
+
+apphot$qphot/mkpkg
+ 1. Removed a duplicate entry for apqcolon.x from the mkpkg file.
+
+ Davis, Feb 20, 1990
+
+apphot$center/apcsnratio.x
+ 1. Recoded this routine slightly to avoid an optimizer bug in
+ the 386i version.
+
+ Davis, Feb 13, 1990
+
+apphot$center/apcinit.x
+apphot$fitsky/apsinit.x,apsplot.x
+apphot$phot/appplot.x
+ 1. The sky fitting algorithm string was not being correctly set if
+ salgorithm was "gauss" or "median" resulting in garbage in the output
+ file header. The correct algorithm was being used.
+
+ 2. A floating point error would occur if salgorithm = "constant",
+ sigma = "INDEFR" and radial profile plotting was enabled. The problem
+ occurred because the plot was trying to draw the 3 * sigma of the
+ sky line by adding the sky value and the sky sigma which is INDEFR.
+
+ 3. Disabled plotting the centering pixel buffer in the case where
+ "calgorithm" was none and the sky pixel buffer when salgorithm is
+ "none".
+
+ Davis, Feb 7, 1990
+
+apphot$fitpsf/apfitpsf.x
+apphot$fitpsf/aprefitpsf.x
+ Fixed a bug in the weighting scheme for fitpsf in which the gain was
+ not scaling the image intensities correctly. I also added a check
+ for 0 valued weights.
+
+ Davis, Jan29, 1990
+
+apphot$
+ Added a setup menu mode to all the apphot tasks. When the user types
+ i they enter the setup menu instead of a pre-defined set of commands.
+ The default setup is still available as the v key, but each parameter
+ can now be set individually as well.
+
+ The documentation has been brought up-to-date.
+
+ Davis, Jan 29, 1990
+
+apphot$phot/t_phot.x
+
+ Added calls to ap_airmass and ap_filter to the phot task as the filter
+ and airmass were not updating correctly.
+
+ Davis, Jan 16, 1990
+
+apphot$
+ Four new parameters airmass, xairmass, filter, ifilter were added to
+ the datapars task to permit users to pick up the filter and airmass
+ quantities form the image headers for later transmission to calibration
+ programs.
+
+ Davis, Nov 28, 1989
+
+apphot$radprof.par
+ The default value of the verbose parameter in radprof was yes
+ instead of no as it should have been.
+
+ Davis, Nov 28, 1989
+
+apphot$
+ Added a new algorithm "mean" to the sky fitting options.
+
+ Davis, Nov 17, 1989
+
+apphot$
+ Added an update parameter to all the apphot tasks. If verify is yes
+ and the task is run in non-interactive mode update will update
+ the critical parameters into the psets.
+
+ Davis, Nov 16, 1989
+
+apphot$radprof/t_radprof.x
+ Removed a defunct define MAX_NAPERTS 15 statement from the
+ radprof task. It now uses the definition in phot.h like all
+ the other tasks.
+
+ Davis, Nov 9, 1989
+
+apphot$daofind/
+ Changed daofind so that a new .coo file is output everytime daofind
+ is run in interactive mode.
+
+ Davis, Oct 30, 1989
+
+apphot$fitsky/apmode.x
+ Made some subtle mods to the mode fitting algorithm. In particular
+ only the first cut is made around the median the remainder are around
+ the mode.
+
+ Davis, October 11, 1989
+
+apphot$
+ 1. apphot$center, fitsky, phot, wphot, polyphot, fitpsf and radprof tasks
+ Activated the datamin and datamax parameters. Pixels outside
+ this range are rejected from sky fitting algorithms and from the
+ non-linear least squares fits in fitpsf and radprof. If a bad pixel
+ is in the centering aperture or in a photometry aperture a magnitude
+ is still computed but a warning message is issued.
+
+ The only task where these parameters are not currently implemented
+ is daofind, pending algorithm review.
+
+ 2. apphot$polyphot/apyphot.x
+ Added a keystroke option to fit polygons that are not shifted to the
+ current cursor position.
+
+ 3. apphot$fitsky/aprefitsky.x
+ Fixed an error in the stellar position reported on the plot in the
+ radplot option for sky fitting. The last cursor position was not
+ being reported.
+
+ 4. apphot$fitsky/apmode.x
+ Changed the cut to one around the mode. Things look ok.
+
+ Davis, October 10, 1989
+
+apphot$apselect/apkeywords.x
+ 1. Fixed a bug in the apselect task. Apselect was not picking up changes
+ int the keywords (#K) values correctly. The pointer in the ky_addval
+ procedure was being incorrectly computed and the new value was being
+ put in the wrong place.
+
+ Davis, Sept 15, 1989
+
+apphot$
+ 1. I removed the query for fwhmpsf from phot.
+
+ 2. I fixed a serious problem in daofind when interactive = yes and
+ the task was rerun on the same convolved image but using a new
+ threshold. There was also a problem with the naming of the
+ temporary image.
+
+ Davis, Aug 22, 1989
+
+apphot$aplib/aprcursor.x
+apphot$aplib/apradpsf.x
+
+ 1. The prompt for the psf fitting box parameter box has been changed from
+ "centering radius" to "fitting box half width".
+ The prompt for the centering box parameter cbox has been changed from
+ "centering radius" to "centering box half width".
+
+ 2. The code to quickly center the radial profile before fitting has
+ been added to the interactive setup routine. Somehow the fitpsf
+ task was overlooked when this update was made originally.
+
+ Davis, Aug 1, 1989
+
+apphot$aprcursor.x
+ The procedure ap_caper() inside apphot$aplib/aprcursor.x was define as
+ a type real procedure but called as a subroutine. I removed the type
+ real declaration.
+
+ Davis, July 31, 1989
+
+Version 2.8 export
+
+*************************************************************************
+
+apphot$
+ 1. The inverse of the scale was being incorrectly printed out by
+ the :show command.
+
+ 2. Fwhmpsf is in scale units not pixels as listed in datapars.
+
+ 3. Exposure, ccdread and gain were not being updated correctly
+ in interactive mode.
+
+ Davis, June 20, 1989
+
+apphot$
+ 1. A new parameter scale has been added to datapars and integrated into
+ the apphot tasks. All the radial profile plots will now display
+ units of scale and of pixels. The .hlp. .key and : commands
+ have all be changed appropritately. Testing is complete.
+
+ 2. Some minor changes have been made to the quick look output formats.
+
+ 3. A verbose and verify switch have been added to all the appropriate
+ tasks.
+
+ 4. Daofind has been modifed so that the convolved image is automatically
+ up to date if any of the convolution kernel parameters have been
+ modified.
+
+ Davis, May 27, 1989
+
+apphot$
+ 1. Add the verify switch to radprof and wphot.
+
+ 2. Began separation of the scale and fwhmpsf parameter.
+ Scale was added to the apphot structure.
+
+ Davis, May 17, 1989
+
+apphot$
+ 1. Fixed an error in the definition of the skyfile format in phot.hlp
+ and wphot.hlp. The are seven columns not five with the x and y position
+ in columns 1 and 2.
+
+ 2. Added the verify switch to the center, fitsky, fitpsf and polyphot tasks.
+
+ Davis, Mar 20, 1989
+
+apphot$
+ 1. Modified the prompts in datapars.par, centerpars.par, fitskypars.par
+ and photpars.par.
+
+ 2. Added a confirm switch to the phot task.
+
+ Davis, Mar 15, 1989
+
+apphot$
+ 1. Changed the interactive setup routine in daofind so that the radial
+ profile is centered before the interactive setup menu is entered.
+
+ 2. A confirm switch has been added to the daofind task so that in batch
+ mode (the default) the user can check/confirm/modify the critical
+ task parameters. A similar 'v' for verify key has been added to
+ the list of interactive menu setup commands.
+
+ Davis, Mar 14, 1989
+
+apphot$
+ 1. Edited the daofind parameter file to make the prompts more illuminating.
+
+ 2. Changed all the daofind subdirectory procedure names beginning with
+ ap to ap_. This continues the apphot cleanup begun in January.
+
+ 3. Fixed a bug in the interactive daofind code. If no convolution image
+ was opened daofind was trying to delete a nonexistent image at
+ task termination.
+
+ Davis, Mar 13, 1989
+
+apphot$apselect/
+ I changed all the apselect subdirectory procedure names to begin with
+ ap_. This continues the cleanup begun in January. Moved the apkeysdef.h
+ file into the aplib subdirectory with all the other .h files.
+
+ 1. Davis, Mar 3, 1989
+
+apphot$
+ I changed all the .keys and .skeys file extensions to .key extensions.
+ This removes a problem with installations which do a strip operation.
+
+ Davis, Feb 3, 1989
+
+apphot$apyfit.x
+ I fixed a potential problem in polyphot. If a user specified a concave
+ polygon and the image line intersected the polygon exactly on a vertex
+ polyphot might not be able to tell whether a line segment was inside
+ or outside the polygon, causing a error in the total flux computation.
+ The affected routine was ap_yclip in apyfit.x
+
+ 1. Davis, Jan 30, 1989
+
+apphot$
+ All the tasks doing interactive setup using a radial profile now
+ center the profile before plotting. This facilitates marking the full
+ width half maximum of the psf on the plot.
+
+ Davis, Jan 23, 1989
+
+apphot
+ 1. Davis, Jan 21, 1989
+ Began cleanup of file and procedure names. All file names now begin with
+ ap. All procedure names begin with ap. Eventually I will clean up
+ the ap to ap_ convention. The subdirectories polyphot and polymark
+ have been completely overhauled. Note caution about updates is in order.
+
+apphot
+ 1. Davis, Nov 11, 1988
+ Removed a call to imparse in apimroot.x and a call to iki_parse in
+ apoutname.x. The calls were changed to imgimage.
+
+apphot
+ 1. Davis, Nov 3, 1988
+ Daofind was outputing an incorrect magnitude estimate due to an indexing
+ problem. The correct stellar position was being output.
+
+apphot
+ 1. Davis, Oct 27, 1988
+ The :aperts coomand in qphot.keys, phot.keys and wphot.keys was changed
+ to the correct :apertures command. The corresponding help pages were
+ also modified.
+
+apphot
+ 1. Davis, Oct 4, 1988
+ The statement z = z + p[4] was out of order in the routine cdgauss1d
+ in cgauss1d.x. The evaluation of the derivative with respect to sigma
+ was in error. This bug would not be noticed in the apphot code as
+ sigma was being held constant whenever this routine was called.
+
+apphot
+ 1. Davis, Sept 12, 1988
+ The APPHOT package was installed in the apphot subdirectory of the
+ digiphot package.
+
+apphot
+ 1. Davis, Aug 15, 1988
+ If the i key (interactive setup option) was used after the first object
+ record was written to the database file then the changed parameters
+ were not being updated in the database file. The : commands were
+ being updated correctly. This problem has been fixed in all the
+ interactive tasks.
+
+apphot
+ 1. Davis, Aug 18, 1988
+ Apselect will now accept a list of text files as input.
+
+apphot
+ 1. Davis, Aug 16, 1988
+ The apphot tasks now save the apertures string as well as the list
+ of apertures. The phot, qphot and wphot phot tasks will noe accept
+ a ranges syntax of the form ap1:apn:apstep. This syntax can be
+ mixed with the former syntax. In addition it is know possible to read
+ the apertures from a text file.
+
+apphot
+ 1. Davis, Aug 11, 1988
+ Fixed a bug in the angle computation for the elliptical Gaussian fitting
+ routine in fitpsf. Positive angles from 0 to 90 were correct, the
+ rest were being forced to be positive.
+
+ 2. It is now possible to change the image, coordinate file and output
+ file name from apphot interactive mode.
+
+apphot
+ 1. Changed the maximum number of apertures from 15 to 100.
+ 2. Changed apwparam to allocate astring of SZ_LINE long.
+
+ Davis, Aug 4, 1988
+
+apphot
+ 1. Fixed a bug in polyget.x. The program was hanging in batch mode when
+ one tried to read a polygons file created by the imtool cursor readback
+ facility. I removed an incorrectly placed next statement.
+
+ Davis, Jul 29, 1988
+
+apphot
+ 1. Added id strings to all the parameter files which request
+ algorithm names etc.
+
+ Davis, Jun 1, 1988
+
+apphot
+ 1. I fixed a potentially serious problem in the way daofind handles
+ out of bounds regions. Daofind was accessing an out of bounds array
+ which accasionally would fail with divide by zeros NaNs etc.
+ The positions of stars near the edge of the image could be affected.
+
+ Davis, Apr29, 1988
+
+apphot$
+ 1. Added a new parameter threshold and changed old parameter threshold
+ to cthreshold.
+
+ 2. Daofind now reads the datapars file. It can now work on both emission
+ and absorption features.
+
+ 3. Cleaned up the output and integrated with rest of apphot.
+
+ Davis, Apr22, 1988
+
+apphot$
+ 1. Removed redundant MISC string definitions.
+
+ 2. Added the DATAMIN and DATAMAX parameters required by daophot. This
+ required changes to the apphot structure, the get and put pars routines
+ and the set and stat calls.
+
+ Davis, Apr12, 1988
+
+apphot$
+ 1. Added correct error code handling for the case where cbox <= 0.0
+ or dannulus = 0.0. The correct action but incorrect error code was
+ being returned.
+
+ 2. Fixed the same bug in the code for fitpsf.
+
+ Davis, Apr4, 1988
+
+apphot$
+ 1. Fixed a bug in decoding the apertures string. If a nonsensical
+ apertures string was given then the apertures could be decoded into
+ some strange number.
+
+ Davis, Apr4, 1988
+
+apphot$apselect.x
+ 1. I fixed a bug in the apselect task which occurred when the user
+ requested all the output fields with the * command and the output
+ records contained array valued fields. The select buffer
+ was being allocated space equal to the number of unique keys, not
+ space for the total number of elements causing memory overflow
+ problems.
+
+ Davis, Apr1, 1988
+
+apphot$
+ 1. Added a needed gdeactivate command to i setup key menus when they
+ terminate prematurely. Otherwise the terminal is left in graphics
+ mode.
+
+ 2. A bug in the batch mode of running apphot tasks occurred if a single
+ output file was specified and there were no stars in the first file.
+ The header could be written several times and cause and error in apselect.
+
+ Davis, Mar31, 1988
+
+apphot$fitpsf/
+ 1. I changed the initial guess for the sigma to be the fwhmpsf instead
+ of a small fraction of the fitting box as before. This affects both the
+ radial Gaussian and the elliptical Gaussian.
+
+ Davis, Mar15,1988
+
+apphot$
+ 1. Floating divide by 0 errors were occurring in daofind when the threshold
+ was set to zero. These were arising in two different places. The
+ magnitude estimate is based on a ratio with respect to threshold
+ and the sharpness computation can blow up when the peak pixel is zero.
+
+ 2. I have added a warning message to aptime.x, appadu.x and aprdnoise.x
+ so that they will print an error message if the header parameter
+ keyword cannot be found in the image header.
+
+ Davis, Mar8,1988
+
+apphot$
+ The graphics and image device opens have been moved outside of the
+ image loop in interactive mode.
+
+ Davis, Feb23,1988
+
+apphot$
+ 1. All the next now print out a short help page at startup time if they
+ are run in interactive mode.
+
+ 2. I changed the task termination sequence. q from inside the cursor
+ loop calls up a verification sequence, return goes back into the cursor
+ loop, n exits the cursor loop and asks for the next image, q quits the
+ task and w quits the task and writes to the pset parameter files.
+
+ 3. I have added the bell character to the end of all warning messages.
+ More specific error messages were added to tell people that they are
+ at the end of a coordinate lists etc.
+
+ Davis, Feb18,1988
+
+apphot$
+ I switched the exposure and itime parameters from the photpars and
+ polypars psets to the datapars pset where they more properly belong.
+
+ Davis, Feb9, 1988
+
+apphot$
+ If salgorithm = constant then the algorithm which computes the magnitude
+ errors will try to use the value of the sigma parameter to estimate the
+ random noise inside the aperture. If sigma is INDEFR it will use only the
+ poisson statistics of the star.
+
+ Davis, Feb 6, 1988
+
+apphot$
+ Moved the pfeature parameter from centerpars and placed it in datapars
+ where it logically belongs.
+
+ Corrected a radprof error in which the extracted pixel array was being
+ call out of bounds even when it wasn't.
+
+ Polyphot was centering on the cursor position even when no polygon
+ had been defined.
+
+ Davis, Feb 5, 1988
+
+apphot$radprof/,apphot$apselect/
+ Fixed a minor bug in apselect. If string parameters were exactly equal
+ to their formatted lengths then a single extra character would get
+ printed at the end of each selected field. This happened for example
+ when the photometry parameter was out of bounds.
+
+ In the radprof task the sky subtracted sums were being printed out
+ instead of the total sums. The mangnitudes were being computed
+ correctly.
+
+ Davis, Feb 2, 1988
+
+apphot$apselect/
+ Made extensive changes to the keyword and units string maintenance
+ facilities, mostly to make the package easier to maintain.
+
+ Changed the pfeature keyword to emission which makes more sense.
+
+ Davis, Jan 25, 1988
+
+apphot$t_apselect.x
+ Corrected a bug in the apselect program in which the package would
+ crash if the fields string was set to NULL. I included a check for
+ the null string in the t_apselect.x procedure.
+
+ Davis, Jan 20, 1988
+
+apphot$
+ I made the task lintran part of the apphot package. This allows the
+ user to manipulate the coordinate lists.
+
+ Davis, Jan 20, 1988
+
+apphot$polyphot/pyprint
+ I corrected an error in the format string for the polyphot magnitude
+ error which was shifting the number over 2 columns.
+
+ Davis, Jan 9, 1988
+
+apphot$daofind/apfind.x
+ A bug in the way daofind computed the convolution kernel for very
+ small kernels was discovered and corrected. The kernel is supposed to
+ be defined for all pixels < 2.0 pixels from the center. For small
+ kernels these elements were being left at zero. IN most cases this
+ causes no problems except for the fact that the sharpness parameter
+ was lower than seen from daofind and that the nomalization for the
+ magnitudes is different. Workarounds are to increase nsigma from the
+ default of 1.5.
+
+ Davis, Jan 6, 1988
+
+apphot$polyphot/polyfit.x
+ The itime normalization was not working correctly in the polyphot
+ task. The time was being picked up correctly but the zero-point
+ correction was not being made to the magnitude.
+
+ Davis, Dec 31, 1987
+
+apphot$polyphot/pybphot.x
+ Davis, Dec 30, 1987
+ I fixed a bug in the polyphot batch mode processing routine. An
+ "illegal file descriptor" error was occurring when polyphot was run
+ in batch mode with a null coordinate file list and a polygons list.
+
+apphot$
+ I continued the clean up of apphot output files. Some of these
+ bugs could cause problems for potential users of apselect.
+ Changed the units string for CERROR, SERROR, PERROR and RERROR to
+ "cerrors", "serrors", "rerrors" and "perrors" from "cerror",
+ "serror", "perror" and "rerror" respectively to make things consistent
+ with the other tasks.
+
+ I changed to polyphot units string for ZMAGNITUDE and EXPOSURE to
+ "zeropoint" and "keyword" respectively for consistency with the phot
+ bug.
+
+ Fixed a bug in the polyphot output file where a # was missing in front
+ of the line beginning with XCENTER.
+
+ Fixed a bug in the output of fitpsf with function = radgauss where
+ the SIGMA keyword was used for two different quantities and only the
+ first one was being output.
+
+ I changed the order of the output table headers from for example
+ #N#N#N #U#U#U and #F#F#F to #N#U#F #N#U#F and #N#U#F. I rechecked
+ apselect on all this.
+
+ Davis, Dec 22, 1987
+
+apphot$
+ I added a comment about the definition of box in the fitpsf parameter
+ file.
+
+ Changed the output format of the center task slightly. The units for
+ HOST are now "computer". Similarly the units string for GAIN and
+ CCDREAD are now "keyword" and "keyword". These changes will affect
+ all tasks in the apphot package which use the datapars parameter set.
+
+ Changed the units string for SALGORITHM to "algorithm". I also corrected
+ an error in the COORDS keyword by changing it from CCORDS to COORDS.
+ I added an s to the ERROR units string, changing it from error to
+ errors.
+
+ I corrected a bug in the output file for the wphot task. The record
+ names, units and formats were not being written to the output file.
+ The problem was that the task name in the batch program had not
+ been changed from ophot to wphot. See also that the task statement
+ was incorrect.
+
+ Davis, Dec 21, 1987
+
+apphot$
+ I changed the default mode for the binary version of the plotfile from
+ NEW_FILE to append. This avoids annoying cannot open plotfile
+ information when phot is run many times. The user must be aware
+ however that very long plot files can be generated. The affected
+ tasks are center, fitsky, phot, wphot, and radprof.
+
+ Davis, Dec 21, 1987
+
+apphot$apselect/apselect.x
+ I installed the new apselect in apphot. In the process I fixed the last
+ memory allocation bug which only showed up in the output of the radprof
+ program where the records were unusually long.
+
+ Davis, Dec 21, 1987
+
+apphot$radprof/apprprof.x
+ I fixed some minor bugs in the output format of radprof which were
+ causing apselect errors. First the records PRADIUS, INTENSITY, INTENSITY
+ should read PRADIUS, INTENSITY and TINTENSITY. The total intensity
+ record was never being read. I added a trailing slash at the end of the
+ magnitude record to indicate that the record continued on to include
+ the radial profile. If the radial profile was long > 20 records a
+ segmentation violation would occur as the program was not reallocating
+ extra memory correctly.
+
+ Davis, Dec 21, 1987
+
+apphot$radprof/aprpinit.x
+ Radprof was not reading multiple appertures from the photpars parameter
+ file correctly. The problem was that the napert and weight arguments
+ were reversed in the call to ap_photsetup making napert always equal
+ to 1.
+
+ Davis, Dec 15, 1987
+
+apphot$apselect/
+ Array subscripts in the apselect task were not being handled correctly
+ on the sun machines. The problem was in the call to the stridx routine.
+ A character constant was being placed in the first argument which is
+ interpreted as an integer. This wa ok on Vax machines with their reverse
+ byte order but did not work on the Suns. I set up some character
+ constants and taht removed the problem.
+
+ Arrays and array elements were not always being handled correctly by the
+ expression parser. In fact arrays are curently illegal in expression.
+ The program will now abort with a more informative error message if
+ it detects an array in an expression. Array elements are permitted
+ however.
+
+ I added some missing mfree statements which were causing random
+ segmentation violation errors from time to time.
+
+ Finally I made some changes for the sake of efficiency. For example
+ I call the routine apchoose only once instead of once for each record
+ in the output file.
+
+ Davis, Dec 15, 1987
+
+apphot$apphot.hd
+ Changed the name of the wphot help page from ophot.hlp to wphot.hlp
+ and the same of the source code file from t_ophot.x to t_wphot.x.
+ Ophot was the historical name of this package.
+
+ Corrected an error in the installation guide instructions on installing
+ the help database. The help apphot command was not functioning
+ correctly. The problem was a missing apphot defintion infront of the
+ .men, .sys etc commands.
+
+ Davis, Dec 15, 1987
+
+apphot$apimroot.x
+ Fixed a bug in the output file name generating code. If output = default
+ and the image name specification included an image section then apphot
+ tasks would try to create an output file name of the form .extension.
+ version. The left square brackett made the image name appear like a
+ directory to fio. I included code to strip the image section off the
+ image name before constructing the output file name. The image
+ section information is however preserved in the output file.
+
+ Davis, Dec 10, 1987
+
+---------------------------------------------------------------------------
+
+ October 27, 1987 Alpha Test Version Released
+
+--------------------------------------------------------------------------
+.endhelp
diff --git a/noao/digiphot/apphot/aplib/apairmass.x b/noao/digiphot/apphot/aplib/apairmass.x
new file mode 100644
index 00000000..3dcb9cdf
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apairmass.x
@@ -0,0 +1,36 @@
+include <imhdr.h>
+include "../lib/apphot.h"
+
+# AP_AIRMASS - Procedure to determine the image airmass.
+
+procedure ap_airmass (im, ap)
+
+pointer im # pointer to IRAF image
+pointer ap # pointer to apphot structure
+
+pointer sp, key
+real xair
+real imgetr(), apstatr()
+
+begin
+ call smark (sp)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ call apstats (ap, AIRMASS, Memc[key], SZ_FNAME)
+ if (Memc[key] == EOS)
+ xair = apstatr (ap, XAIRMASS)
+ else {
+ iferr {
+ xair = imgetr (im, Memc[key])
+ } then {
+ xair = apstatr (ap, XAIRMASS)
+ call eprintf ("Warning: Image %s Keyword: %s not found\n")
+ call pargstr (IM_HDRFILE(im))
+ call pargstr (Memc[key])
+ }
+ }
+ if (IS_INDEFR(xair) || xair <= 0.0)
+ call apsetr (ap, XAIRMASS, INDEFR)
+ else
+ call apsetr (ap, XAIRMASS, xair)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aplib/apapcolon.x b/noao/digiphot/apphot/aplib/apapcolon.x
new file mode 100644
index 00000000..1a906345
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apapcolon.x
@@ -0,0 +1,353 @@
+include <error.h>
+include "../lib/apphot.h"
+
+# AP_APCOLON -- Process colon commands for setting the top level apphot package
+# parameters.
+
+procedure ap_apcolon (ap, im, cl, out, stid, ltid, cmdstr, newimage,
+ newcenterbuf, newcenter, newskybuf, newsky, newbuf, newfit)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the iraf image
+int cl # coordinate file descriptor
+int out # output file descriptor
+int stid # output file sequence number
+int ltid # coordinate file sequence number
+char cmdstr[ARB] # command string
+int newimage # new image ?
+int newcenterbuf, newcenter # new centering parameters ?
+int newskybuf, newsky # new sky fitting parameters ?
+int newbuf, newfit # new photometry parameters ?
+
+bool bval
+int ncmd, ip
+pointer sp, cmd, str
+real rval
+
+bool streq(), itob()
+int strdic(), nscan(), btoi(), apstati(), ctowrd(), open()
+pointer immap()
+real apstatr()
+errchk immmap, open
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Get the command.
+ ip = 1
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, APCMDS)
+ switch (ncmd) {
+
+ case APCMD_FWHMPSF:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_FWHMPSF)
+ call pargr (apstatr (ap, FWHMPSF))
+ call pargstr (UN_ASCALEUNIT)
+ } else {
+ call apsetr (ap, FWHMPSF, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_FWHMPSF, rval, UN_ASCALEUNIT,
+ "full width half max of psf")
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ }
+
+ case APCMD_SCALE:
+ call gargr (rval)
+ if (nscan () == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_SCALE)
+ call pargr (1.0 / apstatr (ap, SCALE))
+ call pargstr (UN_AUNITS)
+ } else if (rval > 0.0) {
+ call apsetr (ap, SCALE, (1.0 / rval))
+ if (stid > 1)
+ call ap_rparam (out, KY_SCALE, (1.0 / rval), UN_AUNITS,
+ "scale in units / pixel")
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ }
+
+ case APCMD_EMISSION:
+ call gargb (bval)
+ if (nscan() == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (KY_POSITIVE)
+ call pargb (itob (apstati (ap, POSITIVE)))
+ } else {
+ call apseti (ap, POSITIVE, btoi (bval))
+ if (stid > 1)
+ call ap_bparam (out, KY_POSITIVE, bval, UN_ASWITCH,
+ "emission feature")
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ }
+
+ case APCMD_FILTER:
+ call gargstr (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, FILTER, Memc[str], SZ_LINE)
+ call printf ("%s = %s\n")
+ call pargstr (KY_FILTER)
+ call pargstr (Memc[str])
+ } else {
+ if (ctowrd (Memc[cmd], ip, Memc[str], SZ_LINE) <= 0)
+ Memc[str] = EOS
+ call apsets (ap, FILTER, Memc[str])
+ if (im != NULL)
+ call ap_filter (im, ap)
+ if (stid > 1)
+ call ap_sparam (out, KY_FILTER, Memc[str], UN_AKEYWORD,
+ "filter keyword")
+ }
+
+ case APCMD_FILTERID:
+ call gargstr (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, FILTERID, Memc[str], SZ_LINE)
+ call printf ("%s = %s\n")
+ call pargstr (KY_FILTERID)
+ call pargstr (Memc[str])
+ } else {
+ if (ctowrd (Memc[cmd], ip, Memc[str], SZ_LINE) <= 0)
+ Memc[str] = EOS
+ call apsets (ap, FILTERID, Memc[str])
+ }
+
+ case APCMD_OBSTIME:
+ call gargstr (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, OBSTIME, Memc[str], SZ_LINE)
+ call printf ("%s = %s\n")
+ call pargstr (KY_OBSTIME)
+ call pargstr (Memc[str])
+ } else {
+ if (ctowrd (Memc[cmd], ip, Memc[str], SZ_LINE) <= 0)
+ Memc[str] = EOS
+ call apsets (ap, OBSTIME, Memc[str])
+ if (im != NULL)
+ call ap_otime (im, ap)
+ if (stid > 1)
+ call ap_sparam (out, KY_OBSTIME, Memc[str], UN_AKEYWORD,
+ "obstime keyword")
+ }
+
+ case APCMD_OTIME:
+ call gargstr (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, OTIME, Memc[str], SZ_LINE)
+ call printf ("%s = %s %s\n")
+ call pargstr (KY_OTIME)
+ call pargstr (Memc[str])
+ call pargstr (UN_ATIMEUNIT)
+ } else {
+ if (ctowrd (Memc[cmd], ip, Memc[str], SZ_LINE) <= 0)
+ Memc[str] = EOS
+ call apsets (ap, OTIME, Memc[str])
+ }
+
+ case APCMD_AIRMASS:
+ call gargstr (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, AIRMASS, Memc[str], SZ_LINE)
+ call printf ("%s = %s\n")
+ call pargstr (KY_AIRMASS)
+ call pargstr (Memc[str])
+ } else {
+ if (ctowrd (Memc[cmd], ip, Memc[str], SZ_LINE) <= 0)
+ Memc[str] = EOS
+ call apsets (ap, AIRMASS, Memc[str])
+ if (im != NULL)
+ call ap_airmass (im, ap)
+ if (stid > 1)
+ call ap_sparam (out, KY_AIRMASS, Memc[str], UN_AKEYWORD,
+ "airmass keyword")
+ }
+
+ case APCMD_XAIRMASS:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_XAIRMASS)
+ call pargr (apstatr (ap, XAIRMASS))
+ call pargstr (UN_ANUMBER)
+ } else {
+ call apsetr (ap, XAIRMASS, rval)
+ #if (stid > 1)
+ #call ap_rparam (out, KY_XAIRMASS, rval, UN_ANUMBER,
+ #"airmass")
+ }
+
+ case APCMD_EXPOSURE:
+ call gargstr (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, EXPOSURE, Memc[str], SZ_LINE)
+ call printf ("%s = %s\n")
+ call pargstr (KY_EXPOSURE)
+ call pargstr (Memc[str])
+ } else {
+ if (ctowrd (Memc[cmd], ip, Memc[str], SZ_LINE) <= 0)
+ Memc[str] = EOS
+ call apsets (ap, EXPOSURE, Memc[str])
+ if (im != NULL)
+ call ap_itime (im, ap)
+ if (stid > 1)
+ call ap_sparam (out, KY_EXPOSURE, Memc[str], UN_AKEYWORD,
+ "exposure time keyword")
+ newfit = YES
+ }
+
+ case APCMD_ITIME:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_ITIME)
+ call pargr (apstatr (ap, ITIME))
+ call pargstr (UN_ATIMEUNIT)
+ } else {
+ call apsetr (ap, ITIME, rval)
+ #if (stid > 1)
+ #call ap_rparam (out, KY_ITIME, rval, UN_ATIMEUNIT,
+ #"exposure time")
+ newfit = YES
+ }
+
+ case APCMD_DATAMIN:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_DATAMIN)
+ call pargr (apstatr (ap, DATAMIN))
+ call pargstr (UN_ACOUNTS)
+ } else {
+ call apsetr (ap, DATAMIN, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_DATAMIN, rval, UN_ACOUNTS,
+ "minimim good data value")
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ }
+
+ case APCMD_DATAMAX:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_DATAMAX)
+ call pargr (apstatr (ap, DATAMAX))
+ call pargstr (UN_ACOUNTS)
+ } else {
+ call apsetr (ap, DATAMAX, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_DATAMAX, rval, UN_ACOUNTS,
+ "maximum good data value")
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ }
+
+ case APCMD_IMAGE:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ call apstats (ap, IMNAME, Memc[str], SZ_FNAME)
+ if (Memc[cmd] == EOS || streq (memc[cmd], Memc[str])) {
+ call printf ("%s: %s\n")
+ call pargstr (KY_IMNAME)
+ call pargstr (Memc[str])
+ } else {
+ if (im != NULL) {
+ call imunmap (im)
+ im = NULL
+ }
+ iferr {
+ im = immap (Memc[cmd], READ_ONLY, 0)
+ } then {
+ call erract (EA_WARN)
+ im = immap (Memc[str], READ_ONLY, 0)
+ } else {
+ call apimkeys (ap, im, Memc[cmd])
+ newimage = YES
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ }
+ }
+
+ case APCMD_COORDS:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ call apstats (ap, CLNAME, Memc[str], SZ_FNAME)
+ if (Memc[cmd] == EOS || streq (Memc[cmd], Memc[str])) {
+ call printf ("%s: %s\n")
+ call pargstr (KY_CLNAME)
+ call pargstr (Memc[str])
+ } else {
+ if (cl != NULL) {
+ call close( cl)
+ cl = NULL
+ }
+ iferr {
+ cl = open (Memc[cmd], READ_ONLY, TEXT_FILE)
+ } then {
+ cl = NULL
+ call erract (EA_WARN)
+ call apsets (ap, CLNAME, "")
+ call apsets (ap, CLROOT, "")
+ call printf ("Coordinate file is undefined.\n")
+ } else {
+ call apsets (ap, CLNAME, Memc[cmd])
+ call apfroot (Memc[cmd], Memc[str], SZ_FNAME)
+ call apsets (ap, CLROOT, Memc[str])
+ ltid = 0
+ }
+ }
+
+ case APCMD_OUTPUT:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ call apstats (ap, OUTNAME, Memc[str], SZ_FNAME)
+ if (Memc[cmd] == EOS || streq (Memc[cmd], Memc[str])) {
+ call printf ("%s: %s\n")
+ call pargstr (KY_OUTNAME)
+ call pargstr (Memc[str])
+ } else {
+ if (out != NULL) {
+ call close (out)
+ out = NULL
+ if (stid <= 1)
+ call delete (Memc[str])
+ }
+ iferr {
+ out = open (Memc[cmd], NEW_FILE, TEXT_FILE)
+ } then {
+ call erract (EA_WARN)
+ call printf ("Reopening output file: %s\n")
+ call pargstr (Memc[str])
+ if (Memc[str] != EOS)
+ out = open (Memc[str], APPEND, TEXT_FILE)
+ else
+ out = NULL
+ } else {
+ call apsets (ap, OUTNAME, Memc[cmd])
+ stid = 1
+ }
+ }
+ default:
+ call printf ("Unknown or ambiguous colon command\7\n")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aplib/aparrays.x b/noao/digiphot/apphot/aplib/aparrays.x
new file mode 100644
index 00000000..563608fd
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/aparrays.x
@@ -0,0 +1,52 @@
+include "../lib/apphotdef.h"
+include "../lib/photdef.h"
+include "../lib/phot.h"
+
+# AP_ARRAYR -- Procedure to move apphot parameters stored as real arrays
+# into a user allocated array.
+
+procedure ap_arrayr (ap, param, array)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+real array[ARB] # array
+
+pointer phot
+
+begin
+ phot = AP_PPHOT(ap)
+ switch (param) {
+ case APERTS:
+ call amovr (Memr[AP_APERTS(phot)], array, AP_NAPERTS(phot))
+ case MAGS:
+ call amovr (Memr[AP_MAGS(phot)], array, AP_NAPERTS(phot))
+ case MAGERRS:
+ call amovr (Memr[AP_MAGERRS(phot)], array, AP_NAPERTS(phot))
+ default:
+ call error (0, "AP_ARRAYR: Unknown apphot real array")
+ }
+end
+
+
+# AP_ARRAYD -- Procedure to move apphot parameters stored as double arrays
+# into a user allocated array.
+
+procedure ap_arrayd (ap, param, array)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+double array[ARB] # array
+
+pointer phot
+
+begin
+ phot = AP_PPHOT(ap)
+ switch (param) {
+ case AREAS:
+ call amovd (Memd[AP_AREA(phot)], array, AP_NAPERTS(phot))
+ case SUMS:
+ call amovd (Memd[AP_SUMS(phot)], array, AP_NAPERTS(phot))
+ default:
+ call error (0, "AP_ARRAYD: Unknown apphot double array")
+ }
+end
diff --git a/noao/digiphot/apphot/aplib/apfilter.x b/noao/digiphot/apphot/aplib/apfilter.x
new file mode 100644
index 00000000..b9bfcc9d
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apfilter.x
@@ -0,0 +1,41 @@
+include <imhdr.h>
+include "../lib/apphot.h"
+
+# AP_FILTER -- Procedure to set the image airmass.
+
+procedure ap_filter (im, ap)
+
+pointer im # pointer to IRAF image
+pointer ap # pointer to apphot structure
+
+pointer sp, key, filt
+
+begin
+ call smark (sp)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ call salloc (filt, SZ_FNAME, TY_CHAR)
+
+ call apstats (ap, FILTER, Memc[key], SZ_FNAME)
+ Memc[filt] = EOS
+ if (Memc[key] == EOS)
+ call apstats (ap, FILTERID, Memc[filt], SZ_FNAME)
+ else {
+ iferr {
+ call imgstr (im, Memc[key], Memc[filt], SZ_FNAME)
+ } then {
+ call apstats (ap, FILTERID, Memc[filt], SZ_FNAME)
+ call eprintf ("Warning: Image %s Keyword: %s not found\n")
+ call pargstr (IM_HDRFILE(im))
+ call pargstr (Memc[key])
+ }
+ }
+
+ if (Memc[filt] == EOS) {
+ call apsets (ap, FILTERID, "INDEF")
+ } else {
+ call ap_rmwhite (Memc[filt], Memc[filt], SZ_FNAME)
+ call apsets (ap, FILTERID, Memc[filt])
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aplib/apfree.x b/noao/digiphot/apphot/aplib/apfree.x
new file mode 100644
index 00000000..30c6c396
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apfree.x
@@ -0,0 +1,25 @@
+include "../lib/apphotdef.h"
+
+# AP_NOISECLS -- Procedure to close up the noise structure and arrays.
+
+procedure ap_noisecls (ap)
+
+pointer ap # pointer to apphot structure
+
+begin
+ if (AP_NOISE(ap) == NULL)
+ return
+ call mfree (AP_NOISE(ap), TY_STRUCT)
+end
+
+
+# AP_DISPCLS -- Procedure to close up the dislay structure and arrays.
+
+procedure ap_dispcls (ap)
+
+pointer ap # pointer to the apphot structure
+
+begin
+ if (AP_PDISPLAY(ap) != NULL)
+ call mfree (AP_PDISPLAY(ap), TY_STRUCT)
+end
diff --git a/noao/digiphot/apphot/aplib/apgaperts.x b/noao/digiphot/apphot/aplib/apgaperts.x
new file mode 100644
index 00000000..05558cc1
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apgaperts.x
@@ -0,0 +1,214 @@
+include <lexnum.h>
+include <ctype.h>
+
+# AP_GETAPERTS -- Procedure to extract real aperture values from a string
+
+int procedure ap_getaperts (str, aperts, max_naperts)
+
+char str[ARB] # string
+real aperts[ARB] # number of apertures
+int max_naperts # maximum number of apertures
+
+int fd, naperts
+int open(), ap_rdaperts(), ap_decaperts()
+errchk open(), close()
+
+begin
+ naperts = 0
+
+ iferr {
+ fd = open (str, READ_ONLY, TEXT_FILE)
+ naperts = ap_rdaperts (fd, aperts, max_naperts)
+ call close (fd)
+ } then {
+ naperts = ap_decaperts (str, aperts, max_naperts)
+ }
+
+ return (naperts)
+end
+
+
+# AP_RDAPERTS -- Procedure to read out the apertures listed one per line
+# from a file.
+
+int procedure ap_rdaperts (fd, aperts, max_naperts)
+
+int fd # aperture list file descriptor
+real aperts[ARB] # list of apertures
+int max_naperts # maximum number of apertures
+
+int naperts
+pointer sp, line
+int getline(), ap_decaperts()
+
+begin
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+
+ naperts = 0
+ while (getline (fd, Memc[line]) != EOF && naperts < max_naperts) {
+ naperts = naperts + ap_decaperts (Memc[line], aperts[1+naperts],
+ max_naperts - naperts)
+ }
+
+ call sfree (sp)
+
+ return (naperts)
+end
+
+
+# AP_DECAPERTS -- Procedure to decode the aperture string.
+
+int procedure ap_decaperts (str, aperts, max_naperts)
+
+char str[ARB] # aperture string
+real aperts[ARB] # aperture array
+int max_naperts # maximum number of apertures
+
+char outstr[SZ_LINE]
+int naperts, ip, op, ndecode, nap
+real apstart, apend, apstep
+bool fp_equalr()
+int gctor()
+
+begin
+ naperts = 0
+
+ for (ip = 1; str[ip] != EOS && naperts < max_naperts;) {
+
+ apstart = 0.0
+ apend = 0.0
+ apstep = 0.0
+ ndecode = 0
+
+ # Skip past white space and commas.
+ while (IS_WHITE(str[ip]))
+ ip = ip + 1
+ if (str[ip] == ',')
+ ip = ip + 1
+
+ # Get the number.
+ op = 1
+ while (IS_DIGIT(str[ip]) || str[ip] == '.') {
+ outstr[op] = str[ip]
+ ip = ip + 1
+ op = op + 1
+ }
+ outstr[op] = EOS
+
+ # Decode the starting aperture.
+ op = 1
+ if (gctor (outstr, op, apstart) > 0) {
+ apend = apstart
+ ndecode = 1
+ } else
+ apstart = 0.0
+
+ # Skip past white space and commas.
+ while (IS_WHITE(str[ip]))
+ ip = ip + 1
+ if (str[ip] == ',')
+ ip = ip + 1
+
+ # Get the ending aperture
+ if (str[ip] == ':') {
+ ip = ip + 1
+
+ # Get the ending aperture.
+ op = 1
+ while (IS_DIGIT(str[ip]) || str[ip] == '.') {
+ outstr[op] = str[ip]
+ ip = ip + 1
+ op = op + 1
+ }
+ outstr[op] = EOS
+
+ # Decode the ending aperture.
+ op = 1
+ if (gctor (outstr, op, apend) > 0) {
+ ndecode = 2
+ apstep = apend - apstart
+ }
+ }
+
+ # Skip past white space and commas.
+ while (IS_WHITE(str[ip]))
+ ip = ip + 1
+ if (str[ip] == ',')
+ ip = ip + 1
+
+ # Get the step size.
+ if (str[ip] == ':') {
+ ip = ip + 1
+
+ # Get the step size.
+ op = 1
+ while (IS_DIGIT(str[ip]) || str[ip] == '.') {
+ outstr[op] = str[ip]
+ ip = ip + 1
+ op = op + 1
+ }
+ outstr[op] = EOS
+
+ # Decode the step size.
+ op = 1
+ if (gctor (outstr, op, apstep) > 0) {
+ if (fp_equalr (apstep, 0.0))
+ apstep = apend - apstart
+ else
+ ndecode = (apend - apstart) / apstep + 1
+ if (ndecode < 0) {
+ ndecode = -ndecode
+ apstep = - apstep
+ }
+ }
+ }
+
+ # Negative apertures are not permitted.
+ if (apstart <= 0.0 || apend <= 0.0)
+ break
+
+ # Fill in the apertures.
+ if (ndecode == 0) {
+ ;
+ } else if (ndecode == 1) {
+ naperts = naperts + 1
+ aperts[naperts] = apstart
+ } else if (ndecode == 2) {
+ naperts = naperts + 1
+ aperts[naperts] = apstart
+ if (naperts >= max_naperts)
+ break
+ naperts = naperts + 1
+ aperts[naperts] = apend
+ } else {
+ for (nap = 1; nap <= ndecode && naperts < max_naperts;
+ nap = nap + 1) {
+ naperts = naperts + 1
+ aperts[naperts] = apstart + (nap - 1) * apstep
+ }
+ }
+ }
+
+ return (naperts)
+end
+
+
+# GCTOR -- Procedure to convert a character variable to a real number.
+# This routine is just an interface routine to the IRAF procedure gctod.
+
+int procedure gctor (str, ip, rval)
+
+char str[ARB] # string to be converted
+int ip # pointer to the string
+real rval # real value
+
+double dval
+int nchars
+int gctod()
+
+begin
+ nchars = gctod (str, ip, dval)
+ rval = dval
+ return (nchars)
+end
diff --git a/noao/digiphot/apphot/aplib/apgqverify.x b/noao/digiphot/apphot/aplib/apgqverify.x
new file mode 100644
index 00000000..b7114e37
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apgqverify.x
@@ -0,0 +1,68 @@
+include <ttyset.h>
+include <fset.h>
+
+define QUERY "[Hit return to continue, n next image, q quit, w quit and save parameters]"
+
+# APGQVERIFY -- Print a message in the status line asking the user if they
+# really want to quit, returning YES if they really want to quit, NO otherwise.
+
+int procedure apgqverify (task, ap, ch)
+
+char task[ARB] # name of the apphot task
+pointer ap # pointer to apphot structure
+int ch # character keystroke command
+
+pointer tty
+int getci(), strmatch()
+pointer ttyodes()
+
+begin
+ tty = ttyodes ("terminal")
+ call ttyclearln (STDOUT, tty)
+ call ttyso (STDOUT, tty, YES)
+
+ call printf (QUERY)
+ call flush (STDOUT)
+ call fseti (STDIN, F_RAW, YES)
+ if (getci (STDIN, ch) == EOF)
+ ;
+ call fseti (STDIN, F_RAW, NO)
+ call ttyso (STDOUT, tty, NO)
+ call ttyclearln (STDOUT, tty)
+ call printf ("\n")
+ call flush (STDOUT)
+
+ call ttycdes (tty)
+
+ if (ch == 'q') {
+ return (YES)
+ } else if (ch == 'w') {
+ if (strmatch ("^center", task) > 0) {
+ call ap_pcpars (ap)
+ } else if (strmatch ("^fitsky", task) > 0) {
+ call ap_pspars (ap)
+ } else if (strmatch ("^phot", task) > 0) {
+ call ap_ppars (ap)
+ } else if (strmatch ("^wphot", task) > 0) {
+ call ap_wpars (ap)
+ } else if (strmatch ("^qphot", task) > 0) {
+ call ap_qppars (ap)
+ } else if (strmatch ("^polyphot", task) > 0) {
+ call ap_pypars (ap)
+ } else if (strmatch ("^radprof", task) > 0) {
+ call ap_rpars (ap)
+ } else if (strmatch ("^fitpsf", task) > 0) {
+ call ap_ppfpars (ap)
+ } else if (strmatch ("^daofind", task) > 0) {
+ call ap_fdpars (ap)
+ } else if (strmatch ("^polymark", task) > 0) {
+ ;
+ }
+ return (YES)
+ } else if (ch == 'n') {
+ return (YES)
+ } else {
+ return (NO)
+ }
+
+end
diff --git a/noao/digiphot/apphot/aplib/apgsvw.x b/noao/digiphot/apphot/aplib/apgsvw.x
new file mode 100644
index 00000000..00f35e90
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apgsvw.x
@@ -0,0 +1,162 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imio.h>
+include <imhdr.h>
+include <math.h>
+
+# AP_GSWV -- Set the data window and viewport for the image display.
+
+procedure ap_gswv (id, image, im, max_nframes)
+
+pointer id # pointer to the image display graphics stream
+char image # the input image name
+pointer im # pointer to the input image
+int max_nframes # the maximum number of display frames
+
+real vx1, vx2, vy1, vy2
+
+begin
+ if (id == NULL)
+ return
+ call ap_gsview (image, im, max_nframes, vx1, vx2, vy1, vy2)
+ call gsview (id, vx1, vx2, vy1, vy2)
+ call gswind (id, 1.0, real (IM_LEN(im,1)), 1.0, real (IM_LEN(im,2)))
+end
+
+
+# AP_GSVIEW -- Map the viewport and window of the image display.
+
+procedure ap_gsview (image, im, max_nframes, vx1, vx2, vy1, vy2)
+
+char image # the input image name
+pointer im # pointer to the input image
+int max_nframes # the maximum number of display frames
+real vx1, vx2, vy1, vy2 # the output viewport
+
+int i, frame, wcs_status, dim1, dim2, step1, step2
+pointer sp, rimname, frimage, frimname, frim, iw
+real x1, x2, y1, y2, fx1, fx2, fy1, fy2, junkx, junky
+bool streq()
+pointer imd_mapframe(), iw_open()
+
+begin
+ # Allocate some memory.
+ call smark (sp)
+ call salloc (rimname, SZ_FNAME, TY_CHAR)
+ call salloc (frimage, SZ_FNAME, TY_CHAR)
+ call salloc (frimname, SZ_FNAME, TY_CHAR)
+
+ # Get the root image name.
+ call imgimage (image, Memc[rimname], SZ_FNAME)
+
+ # Loop through the defined image frames searching for the one
+ # which has the image loaded.
+
+ frame = 0
+ do i = 1, max_nframes {
+ frim = imd_mapframe (i, READ_ONLY, NO)
+ iw = iw_open (frim, i, Memc[frimage], SZ_FNAME, wcs_status)
+ call imgimage (Memc[frimage], Memc[frimname], SZ_FNAME)
+ if (streq (Memc[rimname], Memc[frimname])) {
+ frame = i
+ break
+ } else {
+ call iw_close (iw)
+ call imunmap (frim)
+ }
+ }
+
+ # Default to current frame if the image has not been displayes?
+ if (frame == 0) {
+ call eprintf ("Warning: image %s is not loaded in the display\n")
+ call pargstr (Memc[rimname])
+ vx1 = 0.0
+ vx2 = 1.0
+ vy1 = 0.0
+ vy2 = 1.0
+ call sfree (sp)
+ return
+ }
+
+ # Find the beginning and end points of the requested image section.
+ # We already know at this point that the input logical image is
+ # 2-dimensional. However this 2-dimensional section may be part of
+ # n-dimensional image.
+
+ # X dimension.
+ dim1 = IM_VMAP(im,1)
+ step1 = IM_VSTEP(im,dim1)
+ if (step1 >= 0) {
+ x1 = IM_VOFF(im,dim1) + 1
+ x2 = x1 + IM_LEN(im,1) - 1
+ } else {
+ x1 = IM_VOFF(im,dim1) - 1
+ x2 = x1 - IM_LEN(im,1) + 1
+ }
+
+ # Y dimension.
+ dim2 = IM_VMAP(im,2)
+ step2 = IM_VSTEP(im,dim2)
+ if (step2 >= 0) {
+ y1 = IM_VOFF(im,dim2) + 1
+ y2 = y1 + IM_LEN(im,2) - 1
+ } else {
+ y1 = IM_VOFF(im,dim2) - 1
+ y2 = y1 - IM_LEN(im,2) + 1
+ }
+
+ # Get the frame buffer coordinates corresponding to the lower left
+ # and upper right corners of the image section.
+
+ call iw_im2fb (iw, x1, y1, fx1, fy1)
+ call iw_im2fb (iw, x2, y2, fx2, fy2)
+ if (fx1 > fx2) {
+ junkx = fx1
+ fx1 = fx2
+ fx2 = junkx
+ }
+ if (fy1 > fy2) {
+ junky = fy1
+ fy1 = fy2
+ fy2 = junky
+ }
+
+ # Check that some portion of the input image is in the display.
+ # If not select the default viewport and window coordinates.
+ if (fx1 > IM_LEN(frim,1) || fx2 < 1.0 || fy1 > IM_LEN(frim,2) ||
+ fy2 < 1.0) {
+ vx1 = 0.0
+ vx2 = 1.0
+ vy1 = 0.0
+ vy2 = 1.0
+ call iw_close (iw)
+ call imunmap (frim)
+ call sfree (sp)
+ return
+ }
+
+ # Compute a new viewport and window for X.
+ if (fx1 >= 1.0)
+ vx1 = max (0.0, min (1.0, (fx1 - 0.5) / IM_LEN(frim,1)))
+ else
+ vx1 = 0.0
+ if (fx2 <= IM_LEN(frim,1))
+ vx2 = max (0.0, min (1.0, (fx2 + 0.5) / IM_LEN(frim,1)))
+ else
+ vx2 = 1.0
+
+ # Compute a new viewport and window for Y.
+ if (fy1 >= 1.0)
+ vy1 = max (0.0, min (1.0, (fy1 - 0.5) / IM_LEN(frim,2)))
+ else
+ vy1 = 0.0
+ if (fy2 <= IM_LEN(frim,2))
+ vy2 = max (0.0, min (1.0, (fy2 + 0.5) / IM_LEN(frim,2)))
+ else
+ vy2 = 1.0
+
+ # Clean up.
+ call iw_close (iw)
+ call imunmap (frim)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aplib/apgtverify.x b/noao/digiphot/apphot/aplib/apgtverify.x
new file mode 100644
index 00000000..a2d8bed8
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apgtverify.x
@@ -0,0 +1,19 @@
+# APGTVERIFY -- Print a message in the status line asking the user if they
+# really want to quit, returning YES if they really want to quit, NO otherwise.
+
+int procedure apgtverify (ch)
+
+int ch # character keystroke command
+
+begin
+ if (ch == 'q') {
+ return (YES)
+ } else if (ch == 'w') {
+ return (YES)
+ } else if (ch == 'n') {
+ return (NO)
+ } else {
+ return (NO)
+ }
+
+end
diff --git a/noao/digiphot/apphot/aplib/apimbuf.x b/noao/digiphot/apphot/aplib/apimbuf.x
new file mode 100644
index 00000000..d600a15d
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apimbuf.x
@@ -0,0 +1,17 @@
+include "../lib/apphotdef.h"
+
+# AP_IMBUF -- Set the parameters for the image buffer.
+
+procedure ap_imbuf (ap, hwidth, sequential)
+
+pointer ap # pointer to the apphot structure
+int hwidth # halfwidth of the line buffer
+int sequential # optimize for sequntial i/o
+
+begin
+ AP_SEQUENTIAL(ap) = sequential
+ AP_HWIDTH(ap) = hwidth
+ if (AP_IMBUF(ap) != NULL)
+ call mfree (AP_IMBUF(ap), TY_REAL)
+ AP_IMBUF(ap) = NULL
+end
diff --git a/noao/digiphot/apphot/aplib/apimkeys.x b/noao/digiphot/apphot/aplib/apimkeys.x
new file mode 100644
index 00000000..74105404
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apimkeys.x
@@ -0,0 +1,72 @@
+include "../lib/apphot.h"
+
+# APIMKEYS - Set the image name and keyword parameters after an image
+# is mapped.
+
+procedure apimkeys (ap, im, imname)
+
+pointer ap # pointer to the apphot structure
+pointer im # the image descriptor
+char imname[ARB] # the input image name
+
+pointer sp, imroot, mw, ct
+int apstati()
+pointer mw_openim(), mw_sctran()
+errchk mw_openim(), mw_sctran()
+
+begin
+ call smark (sp)
+ call salloc (imroot, SZ_FNAME, TY_CHAR)
+
+ # Set the image and root names.
+ call apsets (ap, IMNAME, imname)
+ call apimroot (imname, Memc[imroot], SZ_FNAME)
+ call apsets (ap, IMROOT, Memc[imroot])
+
+ # Set the wcs descriptors.
+ mw = apstati (ap, MW)
+ if (mw != NULL)
+ call mw_close (mw)
+ iferr {
+ mw = mw_openim (im)
+ } then {
+ call apseti (ap, MW, NULL)
+ call apseti (ap, CTIN, NULL)
+ call apseti (ap, CTOUT, NULL)
+ } else {
+ call apseti (ap, MW, mw)
+ switch (apstati (ap, WCSIN)) {
+ case WCS_WORLD:
+ iferr (ct = mw_sctran (mw, "world", "logical", 03B))
+ ct = NULL
+ case WCS_PHYSICAL:
+ iferr (ct = mw_sctran (mw, "physical", "logical", 03B))
+ ct = NULL
+ case WCS_TV, WCS_LOGICAL:
+ ct = NULL
+ default:
+ ct = NULL
+ }
+ call apseti (ap, CTIN, ct)
+ switch (apstati (ap, WCSOUT)) {
+ case WCS_PHYSICAL:
+ iferr (ct = mw_sctran (mw, "logical", "physical", 03B))
+ ct = NULL
+ case WCS_TV, WCS_LOGICAL:
+ ct = NULL
+ default:
+ ct = NULL
+ }
+ call apseti (ap, CTOUT, ct)
+ }
+
+ # Set the keywords.
+ call ap_rdnoise (im, ap)
+ call ap_padu (im, ap)
+ call ap_itime (im, ap)
+ call ap_airmass (im, ap)
+ call ap_filter (im, ap)
+ call ap_otime (im, ap)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aplib/apinit.x b/noao/digiphot/apphot/aplib/apinit.x
new file mode 100644
index 00000000..19e87eee
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apinit.x
@@ -0,0 +1,106 @@
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/noisedef.h"
+include "../lib/noise.h"
+include "../lib/displaydef.h"
+
+# AP_DEFSETUP -- Initialize the global apphot package parameters to their
+# default values.
+
+procedure ap_defsetup (ap, fwhmpsf)
+
+pointer ap # pointer to the apphot package
+real fwhmpsf # the FWHM of the stellar images
+
+begin
+ # Initalize the file names.
+ AP_IMNAME(ap) = EOS
+ AP_IMROOT(ap) = EOS
+ AP_CLNAME(ap) = EOS
+ AP_CLROOT(ap) = EOS
+ AP_OUTNAME(ap) = EOS
+ AP_PLOTFILE(ap) = EOS
+ AP_OUTNAME(ap) = EOS
+
+ AP_WCSIN(ap) = WCS_LOGICAL
+ AP_WCSOUT(ap) = WCS_LOGICAL
+ AP_MW(ap) = NULL
+ AP_CTIN(ap) = NULL
+ AP_CTOUT(ap) = NULL
+
+ # Initialize the cursor positions.
+ AP_CWX(ap) = INDEFR
+ AP_CWY(ap) = INDEFR
+ AP_WX(ap) = INDEFR
+ AP_WY(ap) = INDEFR
+
+ # Set up the data characteristics.
+ AP_SCALE(ap) = DEF_SCALE
+ AP_FWHMPSF(ap) = fwhmpsf
+ AP_POSITIVE(ap) = DEF_POSITIVE
+ AP_DATAMIN(ap) = DEF_DATAMIN
+ AP_DATAMAX(ap) = DEF_DATAMAX
+
+ # Set up the image header keywords.
+ AP_EXPOSURE(ap) = EOS
+ AP_ITIME(ap) = DEF_ITIME
+ AP_FILTER(ap) = EOS
+ call strcpy (DEF_FILTERID, AP_FILTERID(ap), SZ_FNAME)
+ AP_AIRMASS(ap) = EOS
+ AP_XAIRMASS(ap) = DEF_XAIRMASS
+ AP_OBSTIME(ap) = EOS
+ call strcpy (DEF_OTIME, AP_OTIME(ap), SZ_FNAME)
+
+ # Set buffer parameters.
+ AP_SEQUENTIAL(ap) = NULL
+ AP_IMBUF(ap) = NULL
+ AP_HWIDTH(ap) = 0
+end
+
+
+# AP_NOISESETUP -- Procedure to intialize noise model parameters.
+
+procedure ap_noisesetup (ap, noise)
+
+pointer ap # pointer to apphot structure
+int noise # noise model
+
+pointer nse
+
+begin
+ call malloc (AP_NOISE(ap), LEN_APNOISE, TY_STRUCT)
+ nse = AP_NOISE(ap)
+ AP_NOISEFUNCTION(nse) = noise
+ switch (noise) {
+ case AP_NCONSTANT:
+ call strcpy ("constant", AP_NSTRING(nse), SZ_FNAME)
+ case AP_NPOISSON:
+ call strcpy ("poisson", AP_NSTRING(nse), SZ_FNAME)
+ default:
+ call strcpy ("poisson", AP_NSTRING(nse), SZ_FNAME)
+ }
+ AP_READNOISE(nse) = DEF_READNOISE
+ AP_SKYSIGMA(nse) = DEF_SKYSIGMA
+ AP_EPADU(nse) = DEF_EPADU
+ AP_GAIN(nse) = EOS
+ AP_CCDREAD(nse) = EOS
+end
+
+
+# AP_DISPSETUP -- Procedure to setup the display parameters.
+
+procedure ap_dispsetup (ap)
+
+pointer ap # pointer to apphot structure
+
+pointer dsp
+
+begin
+ call malloc (AP_PDISPLAY(ap), LEN_DISPLAYSTRUCT, TY_STRUCT)
+ dsp = AP_PDISPLAY(ap)
+ AP_MKSKY(dsp) = DEF_MKSKY
+ AP_MKCENTER(dsp) = DEF_MKCENTER
+ AP_MKAPERT(dsp) = DEF_MKAPERT
+ AP_RADPLOTS(dsp) = DEF_RADPLOTS
+ AP_MKDETECTIONS(dsp) = DEF_MKDETECTIONS
+end
diff --git a/noao/digiphot/apphot/aplib/apinpars1.x b/noao/digiphot/apphot/aplib/apinpars1.x
new file mode 100644
index 00000000..cc332004
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apinpars1.x
@@ -0,0 +1,104 @@
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/noise.h"
+include "../lib/find.h"
+
+# AP_GDAPARS-- Read in the data dependent parameters from the datapars file.
+
+procedure ap_gdapars (ap)
+
+pointer ap # pointer to the apphot structure
+
+int noise
+pointer sp, str, np
+bool clgpsetb()
+int strdic(), btoi()
+pointer clopset()
+real clgpsetr()
+
+begin
+ # Allocate workin space.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Open the pset parameter file.
+ np = clopset ("datapars")
+
+ # Get the data dependent parameters.
+ call apsetr (ap, FWHMPSF, clgpsetr (np, "fwhmpsf"))
+ call apsetr (ap, SCALE, 1.0 / clgpsetr (np, "scale"))
+ call apseti (ap, POSITIVE, btoi (clgpsetb (np, "emission")))
+ call apsetr (ap, DATAMIN, clgpsetr (np, "datamin"))
+ call apsetr (ap, DATAMAX, clgpsetr (np, "datamax"))
+ call apsetr (ap, SKYSIGMA, clgpsetr (np, "sigma"))
+
+ # Get the noise function parameters.
+ call clgpset (np, "noise", Memc[str], SZ_LINE)
+ noise = strdic (Memc[str], Memc[str], SZ_LINE, NFUNCS)
+ call apsets (ap, NSTRING, Memc[str])
+ call apseti (ap, NOISEFUNCTION, noise)
+ call clgpset (np, "gain", Memc[str], SZ_LINE)
+ call apsets (ap, GAIN, Memc[str])
+ call apsetr (ap, EPADU, clgpsetr (np, "epadu"))
+ call clgpset (np, "ccdread", Memc[str], SZ_LINE)
+ call apsets (ap, CCDREAD, Memc[str])
+ call apsetr (ap, READNOISE, clgpsetr (np, "readnoise"))
+
+ # Get the image header parameters.
+ call clgpset (np, "exposure", Memc[str], SZ_LINE)
+ call apsets (ap, EXPOSURE, Memc[str])
+ call apsetr (ap, ITIME, clgpsetr (np, "itime"))
+ call clgpset (np, "airmass", Memc[str], SZ_LINE)
+ call apsets (ap, AIRMASS, Memc[str])
+ call apsetr (ap, XAIRMASS, clgpsetr (np, "xairmass"))
+ call clgpset (np, "filter", Memc[str], SZ_LINE)
+ call apsets (ap, FILTER, Memc[str])
+ call clgpset (np, "ifilter", Memc[str], SZ_LINE)
+ call apsets (ap, FILTERID, Memc[str])
+ call clgpset (np, "obstime", Memc[str], SZ_LINE)
+ call apsets (ap, OBSTIME, Memc[str])
+ call clgpset (np, "otime", Memc[str], SZ_LINE)
+ call apsets (ap, OTIME, Memc[str])
+
+ # Close the parameter set files.
+ call clcpset (np)
+
+ call sfree (sp)
+end
+
+
+# AP_GFIPARS -- Read in the object finding parametes from the findpars
+# parameter file.
+
+procedure ap_gfipars (ap)
+
+pointer ap # pointer to the apphot structure
+
+pointer pp
+bool clgpsetb()
+int btoi()
+pointer clopset()
+real clgpsetr()
+
+begin
+ # Open the pset parameter file.
+ pp = clopset ("findpars")
+
+ # Get the kernel statistics.
+ call apsetr (ap, NSIGMA, clgpsetr (pp, "nsigma"))
+ call apsetr (ap, RATIO, clgpsetr (pp, "ratio"))
+ call apsetr (ap, THETA, clgpsetr (pp, "theta"))
+
+ # Get the image detection characteristics.
+ call apsetr (ap, THRESHOLD, clgpsetr (pp, "threshold"))
+ call apsetr (ap, SHARPLO, clgpsetr (pp, "sharplo"))
+ call apsetr (ap, SHARPHI, clgpsetr (pp, "sharphi"))
+ call apsetr (ap, ROUNDLO, clgpsetr (pp, "roundlo"))
+ call apsetr (ap, ROUNDHI, clgpsetr (pp, "roundhi"))
+
+ # Set the marking parameter.
+ call apseti (ap, MKDETECTIONS, btoi (clgpsetb (pp, "mkdetections")))
+
+ # Close the parameter set file.
+ call clcpset (pp)
+end
diff --git a/noao/digiphot/apphot/aplib/apinpars2.x b/noao/digiphot/apphot/aplib/apinpars2.x
new file mode 100644
index 00000000..ff9cf3eb
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apinpars2.x
@@ -0,0 +1,207 @@
+include "../lib/display.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+include "../lib/polyphot.h"
+
+# AP_GCEPARS -- Read in the centering algorithm parameters from the
+# centerpars parameter file.
+
+procedure ap_gcepars (ap)
+
+pointer ap # pointer to the apphot structure
+
+int function
+pointer sp, str, pp
+bool clgpsetb()
+int strdic(), btoi(), clgpseti()
+pointer clopset()
+real clgpsetr()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Open the pset parameter file.
+ pp = clopset ("centerpars")
+
+ # Get the centering parameters.
+ call clgpset (pp, "calgorithm", Memc[str], SZ_LINE)
+ function = strdic (Memc[str], Memc[str], SZ_LINE, CFUNCS)
+ call apsets (ap, CSTRING, Memc[str])
+ call apseti (ap, CENTERFUNCTION, function)
+ call apsetr (ap, CAPERT, clgpsetr (pp, "cbox") / 2.0)
+ call apsetr (ap, CTHRESHOLD, clgpsetr (pp, "cthreshold"))
+ call apsetr (ap, MINSNRATIO, clgpsetr (pp, "minsnratio"))
+ call apseti (ap, CMAXITER, clgpseti (pp, "cmaxiter"))
+ call apsetr (ap, MAXSHIFT, clgpsetr (pp, "maxshift"))
+ call apseti (ap, CLEAN, btoi (clgpsetb (pp, "clean")))
+ call apsetr (ap, RCLEAN, clgpsetr (pp, "rclean"))
+ call apsetr (ap, RCLIP, clgpsetr (pp, "rclip"))
+ call apsetr (ap, SIGMACLEAN, clgpsetr (pp, "kclean"))
+
+ call apseti (ap, MKCENTER, btoi (clgpsetb (pp, "mkcenter")))
+
+
+ # Close the parameter set file.
+ call clcpset (pp)
+
+ call sfree (sp)
+end
+
+
+# AP_GSAPARS -- Read in the sky fitting parameters from the fitskypars
+# parameter file.
+
+procedure ap_gsapars (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+int function
+pointer sp, str, pp
+bool clgpsetb()
+int strdic(), clgpseti(), btoi()
+pointer clopset()
+real clgpsetr()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Open the pset parameter file.
+ pp = clopset ("fitskypars")
+
+ # Get the sky fitting algorithm parameters.
+ call clgpset (pp, "salgorithm", Memc[str], SZ_LINE)
+ function = strdic (Memc[str], Memc[str], SZ_LINE, SFUNCS)
+ call apsets (ap, SSTRING, Memc[str])
+ call apseti (ap, SKYFUNCTION, function)
+ call apsetr (ap, SKY_BACKGROUND, clgpsetr (pp, "skyvalue"))
+ call apsetr (ap, ANNULUS, clgpsetr (pp, "annulus"))
+ call apsetr (ap, DANNULUS, clgpsetr (pp, "dannulus"))
+ call apsetr (ap, K1, clgpsetr (pp, "khist"))
+ call apsetr (ap, BINSIZE, clgpsetr (pp, "binsize"))
+ call apseti (ap, SMOOTH, btoi (clgpsetb (pp, "smooth")))
+ call apseti (ap, SMAXITER, clgpseti (pp, "smaxiter"))
+ call apsetr (ap, SLOCLIP, clgpsetr (pp, "sloclip"))
+ call apsetr (ap, SHICLIP, clgpsetr (pp, "shiclip"))
+ call apseti (ap, SNREJECT, clgpseti (pp, "snreject"))
+ call apsetr (ap, SLOREJECT, clgpsetr (pp, "sloreject"))
+ call apsetr (ap, SHIREJECT, clgpsetr (pp, "shireject"))
+ call apsetr (ap, RGROW, clgpsetr (pp, "rgrow"))
+
+ # Get the marking parameter.
+ call apseti (ap, MKSKY, btoi (clgpsetb (pp, "mksky")))
+
+ # Close the parameter set file.
+ call clcpset (pp)
+
+ call sfree (sp)
+end
+
+
+# AP_GPHPARS -- Get the photometry algorithm parameters from the photometry
+# file.
+
+procedure ap_gphars (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+pointer sp, str, pp
+bool clgpsetb()
+int btoi()
+pointer clopset()
+real clgpsetr()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Open the pset parameter file.
+ pp = clopset ("photpars")
+
+ # Get the photometry parameters.
+ call clgpset (pp, "apertures", Memc[str], SZ_LINE)
+ call apsets (ap, APERTS, Memc[str])
+ call apsetr (ap, ZMAG, clgpsetr (pp, "zmag"))
+ call apseti (ap, MKAPERT, btoi (clgpsetb (pp, "mkapert")))
+ call apsets (ap, PWSTRING, "constant")
+ call apseti (ap, PWEIGHTS, AP_PWCONSTANT)
+
+ # Close the parameter set file.
+ call clcpset (pp)
+
+ call sfree (sp)
+end
+
+
+# AP_GPOPARS -- Get the polygonal aperture photometry parameters.
+
+procedure ap_gpopars (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+pointer sp, str, pp
+bool clgpsetb()
+int btoi()
+pointer clopset()
+real clgpsetr()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Open the pset parameter file.
+ pp = clopset ("polypars")
+
+ # Get the parameters.
+ call apsetr (ap, PYZMAG, clgpsetr (pp, "zmag"))
+ call apseti (ap, MKPOLYGON, btoi (clgpsetb (pp, "mkpolygon")))
+
+ # Close the parameter set file.
+ call clcpset (pp)
+
+ call sfree (sp)
+end
+
+
+# AP_GWHPARS -- Get the photometry algorithm parameters from the photometry
+# file.
+
+procedure ap_gwhars (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+int weight
+pointer sp, str, pp
+bool clgpsetb()
+int btoi(), strdic()
+pointer clopset()
+real clgpsetr()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Open the pset parameter file.
+ pp = clopset ("photpars")
+
+ # Get the photometry parameters.
+ call clgpset (pp, "apertures", Memc[str], SZ_LINE)
+ call apsets (ap, APERTS, Memc[str])
+ call apsetr (ap, ZMAG, clgpsetr (pp, "zmag"))
+ call apseti (ap, MKAPERT, btoi (clgpsetb (pp, "mkapert")))
+ call apsets (ap, PWSTRING, "constant")
+ call apseti (ap, PWEIGHTS, AP_PWCONSTANT)
+
+ # Get the major parameters.
+ call clgpset (pp, "weighting", Memc[str], SZ_LINE)
+ weight = strdic (Memc[str], Memc[str], SZ_LINE, PWFUNCS)
+ call apsets (ap, PWSTRING, Memc[str])
+ call apseti (ap, PWEIGHTS, weight)
+
+ # Close the parameter set file.
+ call clcpset (pp)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aplib/apitime.x b/noao/digiphot/apphot/aplib/apitime.x
new file mode 100644
index 00000000..c01dfc9e
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apitime.x
@@ -0,0 +1,36 @@
+include <imhdr.h>
+include "../lib/apphot.h"
+
+# AP_ITIME - Procedure to set the image exposure time .
+
+procedure ap_itime (im, ap)
+
+pointer im # pointer to IRAF image
+pointer ap # pointer to apphot structure
+
+pointer sp, key
+real itime
+real imgetr(), apstatr()
+
+begin
+ call smark (sp)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ call apstats (ap, EXPOSURE, Memc[key], SZ_FNAME)
+ if (Memc[key] == EOS)
+ itime = apstatr (ap, ITIME)
+ else {
+ iferr {
+ itime = imgetr (im, Memc[key])
+ } then {
+ itime = apstatr (ap, ITIME)
+ call eprintf ("Warning: Image %s Keyword: %s not found\n")
+ call pargstr (IM_HDRFILE(im))
+ call pargstr (Memc[key])
+ }
+ }
+ if (IS_INDEFR(itime) || itime <= 0.0)
+ call apsetr (ap, ITIME, 1.0)
+ else
+ call apsetr (ap, ITIME, itime)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aplib/apmark1.x b/noao/digiphot/apphot/aplib/apmark1.x
new file mode 100644
index 00000000..1982a679
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apmark1.x
@@ -0,0 +1,270 @@
+include <gset.h>
+include "../lib/apphot.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+include "../lib/polyphot.h"
+include "../lib/radprof.h"
+
+# APMARK -- Procedure to mark center, fitsky and phot parameters on the display.
+
+procedure apmark (ap, id, mkcenter, mksky, mkapert)
+
+pointer ap # apphot pointer
+pointer id # pointer to image display stream
+int mkcenter # mark the computed center
+int mksky # mark the sky annulus
+int mkapert # mark the aperture(s)
+
+int i, marktype
+pointer sp, temp
+real inner_sky, outer_sky, apert
+int apstati(), gstati()
+real apstatr()
+errchk greactivate, gdeactivate, gamove, gadraw, gmark
+
+begin
+ if (id == NULL)
+ return
+ if (mkcenter == NO && mksky == NO && mkapert == NO)
+ return
+ iferr {
+ call greactivate (id, 0)
+ } then {
+ return
+ }
+
+ marktype = gstati (id, G_PMLTYPE)
+
+ # Mark the center and shift on the display.
+ if (mkcenter == YES) {
+ iferr {
+ call gseti (id, G_PMLTYPE, GL_SOLID)
+ call gamove (id, (apstatr (ap, XCENTER) - apstatr (ap, XSHIFT)),
+ (apstatr (ap, YCENTER) - apstatr (ap, YSHIFT)))
+ call gadraw (id, apstatr (ap, XCENTER), apstatr (ap, YCENTER))
+ call gmark (id, apstatr (ap, XCENTER), apstatr (ap, YCENTER),
+ GM_PLUS, -2.0, -2.0)
+ } then
+ ;
+ }
+
+ # Draw the sky annuli on the display.
+ if (mksky == YES) {
+ iferr {
+ call gseti (id, G_PMLTYPE, GL_DASHED)
+ call gmark (id, apstatr (ap, SXCUR), apstatr (ap, SYCUR),
+ GM_PLUS, -2.0, -2.0)
+ inner_sky = 2.0 * apstatr (ap, SCALE) * apstatr (ap, ANNULUS)
+ call gmark (id, apstatr (ap, SXCUR), apstatr (ap, SYCUR),
+ GM_CIRCLE, -inner_sky, -inner_sky)
+ outer_sky = 2.0 * apstatr (ap, SCALE) * (apstatr (ap,
+ ANNULUS) + apstatr (ap, DANNULUS))
+ call gmark (id, apstatr (ap, SXCUR), apstatr (ap, SYCUR),
+ GM_CIRCLE, -outer_sky, -outer_sky)
+ } then
+ ;
+ }
+
+ # Draw the apertures on the display.
+ if (mkapert == YES) {
+ iferr {
+ call smark (sp)
+ call salloc (temp, apstati (ap, NAPERTS), TY_REAL)
+ call ap_arrayr (ap, APERTS, Memr[temp])
+ call gseti (id, G_PMLTYPE, GL_DASHED)
+ call gmark (id, apstatr (ap, PXCUR), apstatr (ap, PYCUR),
+ GM_PLUS, -2.0, -2.0)
+ do i = 1, apstati (ap, NAPERTS) {
+ apert = 2.0 * apstatr (ap, SCALE) * Memr[temp+i-1]
+ call gmark (id, apstatr (ap, PXCUR), apstatr (ap, PYCUR),
+ GM_CIRCLE, -apert, -apert)
+ }
+ call sfree (sp)
+ } then
+ call sfree (sp)
+ }
+
+ # Restore the mark type.
+ call gseti (id, G_PMLTYPE, marktype)
+
+ iferr {
+ call gdeactivate (id, 0)
+ } then
+ return
+end
+
+# APPYMARK -- Procedure to mark center, fitsky and polyphot parameters on the
+# display.
+
+procedure appymark (ap, id, x, y, nver, mkcenter, mksky, mkpolygon)
+
+pointer ap # apphot pointer
+pointer id # pointer to image display stream
+real x[ARB] # coordinates of x vertices
+real y[ARB] # coordinates of y vertices
+int nver # number of vertices
+int mkcenter # mark the computed center
+int mksky # mark the sky annulus
+int mkpolygon # mark the aperture(s)
+
+int marktype, linetype
+real inner_sky, outer_sky
+int gstati()
+real apstatr()
+errchk greactivate, gdeactivate, gamove, gadraw, gmark, gline
+
+begin
+ if (id == NULL)
+ return
+ if (mkcenter == NO && mksky == NO && mkpolygon == NO)
+ return
+ iferr {
+ call greactivate (id, 0)
+ } then
+ return
+
+ marktype = gstati (id, G_PMLTYPE)
+ linetype = gstati (id, G_PLTYPE)
+
+ if (mkcenter == YES) {
+ iferr {
+ call gseti (id, G_PMLTYPE, GL_SOLID)
+ call gamove (id, (apstatr (ap, XCENTER) - apstatr (ap, XSHIFT)),
+ (apstatr (ap, YCENTER) - apstatr (ap, YSHIFT)))
+ call gadraw (id, apstatr (ap, XCENTER), apstatr (ap, YCENTER))
+ call gmark (id, apstatr (ap, XCENTER), apstatr (ap, YCENTER),
+ GM_PLUS, -2.0, -2.0)
+ } then
+ ;
+ }
+
+ if (mksky == YES) {
+ iferr {
+ call gseti (id, G_PMLTYPE, GL_DASHED)
+ call gmark (id, apstatr (ap, SXCUR), apstatr (ap, SYCUR),
+ GM_PLUS, -2.0, -2.0)
+ inner_sky = 2.0 * apstatr (ap, SCALE) * apstatr (ap, ANNULUS)
+ call gmark (id, apstatr (ap, SXCUR), apstatr (ap, SYCUR),
+ GM_CIRCLE, -inner_sky, -inner_sky)
+ outer_sky = 2.0 * apstatr (ap, SCALE) * (apstatr (ap,
+ ANNULUS) + apstatr (ap, DANNULUS))
+ call gmark (id, apstatr (ap, SXCUR), apstatr (ap, SYCUR),
+ GM_CIRCLE, -outer_sky, -outer_sky)
+ } then
+ ;
+ }
+
+ if (mkpolygon == YES) {
+ iferr {
+ call gseti (id, G_PLTYPE, GL_DASHED)
+ call gmark (id, apstatr (ap, PYCX), apstatr (ap, PYCY),
+ GM_PLUS, -2.0, -2.0)
+ call gpline (id, x, y, nver)
+ } then
+ ;
+ }
+
+ call gseti (id, G_PMLTYPE, marktype)
+ call gseti (id, G_PLTYPE, linetype)
+
+ iferr (call gdeactivate (id, 0))
+ return
+end
+
+
+# APRMARK -- Procedure to mark center, fitsky and radprof parameters on the
+# display.
+
+procedure aprmark (ap, id, mkcenter, mksky, mkapert)
+
+pointer ap # apphot pointer
+pointer id # pointer to image display stream
+int mkcenter # mark the computed center
+int mksky # mark the sky annulus
+int mkapert # mark the aperture(s)
+
+int i, marktype
+pointer sp, temp
+real inner_sky, outer_sky, apert, radius, xc, yc
+int apstati(), gstati()
+real apstatr()
+errchk greactivate, gdeactivate, gamove, gadraw, gmark
+
+begin
+ if (id == NULL)
+ return
+ if (mkcenter == NO && mksky == NO && mkapert == NO)
+ return
+
+ iferr {
+ call greactivate (id, 0)
+ } then
+ return
+
+ marktype = gstati (id, G_PMLTYPE)
+
+ # Mark the center and shift on the display.
+ if (mkcenter == YES) {
+ iferr {
+ call gseti (id, G_PMLTYPE, GL_SOLID)
+ call gamove (id, (apstatr (ap, XCENTER) - apstatr (ap, XSHIFT)),
+ (apstatr (ap, YCENTER) - apstatr (ap, YSHIFT)))
+ call gadraw (id, apstatr (ap, XCENTER), apstatr (ap, YCENTER))
+ call gmark (id, apstatr (ap, XCENTER), apstatr (ap, YCENTER),
+ GM_PLUS, -2.0, -2.0)
+ call gflush (id)
+ } then
+ ;
+ }
+
+ # Draw the sky annuli on the display.
+ if (mksky == YES) {
+ iferr {
+ call gseti (id, G_PMLTYPE, GL_DASHED)
+ call gmark (id, apstatr (ap, SXCUR), apstatr (ap, SYCUR),
+ GM_PLUS, -2.0, -2.0)
+ inner_sky = 2.0 * apstatr (ap, SCALE) * apstatr (ap, ANNULUS)
+ call gmark (id, apstatr (ap, SXCUR), apstatr (ap, SYCUR),
+ GM_CIRCLE, -inner_sky, -inner_sky)
+ outer_sky = 2.0 * apstatr (ap, SCALE) * (apstatr (ap,
+ ANNULUS) + apstatr (ap, DANNULUS))
+ call gmark (id, apstatr (ap, SXCUR), apstatr (ap, SYCUR),
+ GM_CIRCLE, -outer_sky, -outer_sky)
+ call gflush (id)
+ } then
+ ;
+ }
+
+ # Draw the apertures on the display.
+ if (mkapert == YES) {
+ iferr {
+ call smark (sp)
+ call salloc (temp, apstati (ap, NAPERTS), TY_REAL)
+ call gseti (id, G_PMLTYPE, GL_DASHED)
+ call gmark (id, apstatr (ap, XCENTER), apstatr (ap, YCENTER),
+ GM_PLUS, -2.0, -2.0)
+ call ap_arrayr (ap, APERTS, Memr[temp])
+ do i = 1, apstati (ap, NAPERTS) {
+ apert = 2.0 * apstatr (ap, SCALE) * Memr[temp+i-1]
+ call gmark (id, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), GM_CIRCLE, -apert, -apert)
+ }
+ xc = apstatr (ap, XCENTER)
+ yc = apstatr (ap, YCENTER)
+ radius = apstatr (ap, SCALE) * apstatr (ap, RPRADIUS)
+ call gamove (id, xc - radius, yc - radius)
+ call gadraw (id, xc + radius, yc - radius)
+ call gadraw (id, xc + radius, yc + radius)
+ call gadraw (id, xc - radius, yc + radius)
+ call gadraw (id, xc - radius, yc - radius)
+ call sfree (sp)
+ } then
+ call sfree (sp)
+ }
+
+ call gseti (id, G_PMLTYPE, marktype)
+
+ iferr (call gdeactivate (id, 0))
+ return
+end
diff --git a/noao/digiphot/apphot/aplib/apmark2.x b/noao/digiphot/apphot/aplib/apmark2.x
new file mode 100644
index 00000000..96896e56
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apmark2.x
@@ -0,0 +1,46 @@
+include <gset.h>
+include "../lib/apphot.h"
+include "../lib/fitpsf.h"
+
+
+# AP_PFMARK -- Procedure to mark the psf fitting box on the display.
+
+procedure appfmark (ap, id, mkbox)
+
+pointer ap # pointer to the apphot procedure
+pointer id # pointer to the display stream
+int mkbox # mark the psf fitting box
+
+int marktype
+real radius, xc, yc
+int gstati()
+real apstatr()
+errchk greactivate, gdeactivate, gamove, gadraw
+
+begin
+ if (id == NULL)
+ return
+ if (mkbox == NO)
+ return
+
+ iferr (call greactivate (id, 0))
+ return
+
+ marktype = gstati (id,G_PMLTYPE)
+ iferr {
+ call gseti (id, G_PMLTYPE, GL_DASHED)
+ xc = apstatr (ap, PFXCUR)
+ yc = apstatr (ap, PFYCUR)
+ radius = apstatr (ap, SCALE) * apstatr (ap, PSFAPERT)
+ call gamove (id, xc - radius, yc - radius)
+ call gadraw (id, xc + radius, yc - radius)
+ call gadraw (id, xc + radius, yc + radius)
+ call gadraw (id, xc - radius, yc + radius)
+ call gadraw (id, xc - radius, yc - radius)
+ } then
+ ;
+ call gseti (id, G_PMLTYPE, marktype)
+
+ iferr (call gdeactivate (id, 0))
+ return
+end
diff --git a/noao/digiphot/apphot/aplib/apnew.x b/noao/digiphot/apphot/aplib/apnew.x
new file mode 100644
index 00000000..b5da6fc1
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apnew.x
@@ -0,0 +1,46 @@
+include "../lib/apphot.h"
+
+# APNEW -- Procedure to determine whether the current star is the same as
+# the previous star and/or whether the current star belongs to the coordinate
+# list or not.
+
+int procedure apnew (ap, wx, wy, xlist, ylist, newlist)
+
+pointer ap # pointer to the apphot structure
+real wx # x cursor coordinate
+real wy # y cursor coordinate
+real xlist # x list coordinate
+real ylist # y list coordinate
+int newlist # integer new list
+
+bool fp_equalr()
+int newobject
+real deltaxy
+real apstatr()
+
+begin
+ deltaxy = apstatr (ap, FWHMPSF) * apstatr (ap, SCALE)
+
+ if (newlist == NO) {
+ if (! fp_equalr (wx, apstatr (ap, WX)) || ! fp_equalr (wy,
+ apstatr (ap, WY)))
+ newobject = YES
+ else
+ newobject = NO
+ } else if ((abs (xlist - wx) <= deltaxy) &&
+ (abs (ylist - wy) <= deltaxy)) {
+ wx = xlist
+ wy = ylist
+ newobject = NO
+ } else if (fp_equalr (wx, apstatr (ap, WX)) && fp_equalr (wy,
+ apstatr (ap, WY))) {
+ wx = xlist
+ wy = ylist
+ newobject = NO
+ } else {
+ newlist = NO
+ newobject = YES
+ }
+
+ return (newobject)
+end
diff --git a/noao/digiphot/apphot/aplib/apnscolon.x b/noao/digiphot/apphot/aplib/apnscolon.x
new file mode 100644
index 00000000..34bc43fc
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apnscolon.x
@@ -0,0 +1,165 @@
+include <error.h>
+include "../lib/noise.h"
+
+# AP_NSCOLON -- Procedure to process colon commands for setting
+# noise fitting parameters.
+
+procedure ap_nscolon (ap, im, out, stid, cmdstr, newcenterbuf,
+ newcenter, newskybuf, newsky, newbuf, newfit)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the iraf image
+int out # output file descriptor
+int stid # output file sequence number
+char cmdstr[ARB] # command string
+int newcenterbuf, newcenter # new centering parameters ?
+int newskybuf, newsky # new sky fitting parameters ?
+int newbuf, newfit # new photometry parameters ?
+
+int ncmd, stat, ip
+pointer sp, cmd, str
+real rval
+int strdic(), nscan(), ctowrd()
+real apstatr()
+errchk immmap
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Get the command.
+ ip = 1
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, NCMDS)
+ switch (ncmd) {
+
+ case NCMD_NOISE:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, NSTRING, Memc[str], SZ_FNAME)
+ call printf ("%s = %s %s\n")
+ call pargstr (KY_NSTRING)
+ call pargstr (Memc[str])
+ call pargstr (UN_NMODEL)
+ } else {
+ stat = strdic (Memc[cmd], Memc[cmd], SZ_LINE, NFUNCS)
+ if (stat > 0) {
+ call apseti (ap, NOISEFUNCTION, stat)
+ call apsets (ap, NSTRING, Memc[cmd])
+ if (stid > 1)
+ call ap_sparam (out, KY_NSTRING, Memc[cmd], UN_NMODEL,
+ "noise model")
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ }
+ }
+
+ case NCMD_SIGMA:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_SKYSIGMA)
+ call pargr (apstatr (ap, SKYSIGMA))
+ call pargstr (UN_NCOUNTS)
+ } else {
+ call apsetr (ap, SKYSIGMA, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_SKYSIGMA, rval, UN_NCOUNTS,
+ "standard deviation of 1 pixel")
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ }
+
+ case NCMD_EPADU:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_EPADU)
+ call pargr (apstatr (ap, EPADU))
+ call pargstr (UN_NEPADU)
+ } else {
+ call apsetr (ap, EPADU, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_EPADU, rval, UN_NEPADU,
+ "photons per adu")
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ }
+
+ case NCMD_GAIN:
+ call gargstr (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, GAIN, Memc[str], SZ_LINE)
+ call printf ("%s = %s\n")
+ call pargstr (KY_GAIN)
+ call pargstr (Memc[str])
+ } else {
+ if (ctowrd (Memc[cmd], ip, Memc[str], SZ_LINE) <= 0)
+ Memc[str] = EOS
+ call apsets (ap, GAIN, Memc[str])
+ if (im != NULL)
+ call ap_padu (im, ap)
+ if (stid > 1)
+ call ap_sparam (out, KY_GAIN, Memc[str], UN_NKEYWORD,
+ "gain keyword")
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ }
+
+ case NCMD_CCDREAD:
+ call gargstr (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, CCDREAD, Memc[str], SZ_LINE)
+ call printf ("%s = %s\n")
+ call pargstr (KY_CCDREAD)
+ call pargstr (Memc[str])
+ } else {
+ if (ctowrd (Memc[cmd], ip, Memc[str], SZ_LINE) <= 0)
+ Memc[str] = EOS
+ call apsets (ap, CCDREAD, Memc[str])
+ if (im != NULL)
+ call ap_rdnoise (im, ap)
+ if (stid > 1)
+ call ap_sparam (out, KY_CCDREAD, Memc[str], UN_NKEYWORD,
+ "read noise keyword")
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ }
+
+ case NCMD_READNOISE:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_READNOISE)
+ call pargr (apstatr (ap, READNOISE))
+ call pargstr (UN_NELECTRONS)
+ } else {
+ call apsetr (ap, READNOISE, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_READNOISE, rval, UN_NELECTRONS,
+ "readout noise")
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ }
+
+
+ default:
+ call printf ("Unknown or ambiguous colon command\7\n")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aplib/apnshow.x b/noao/digiphot/apphot/aplib/apnshow.x
new file mode 100644
index 00000000..a0a173a0
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apnshow.x
@@ -0,0 +1,118 @@
+include "../lib/apphot.h"
+include "../lib/noise.h"
+
+# AP_NSHOW -- Procedure to display the current data parameters.
+
+procedure ap_nshow (ap)
+
+pointer ap # pointer to the apphot structure
+
+pointer sp, str1, str2
+bool itob()
+int apstati()
+real apstatr()
+
+begin
+ call smark (sp)
+ call salloc (str1, SZ_LINE, TY_CHAR)
+ call salloc (str2, SZ_LINE, TY_CHAR)
+
+ # Set the object charactersitics.
+ call printf ("\nData Characteristics\n")
+ call apstats (ap, IMNAME, Memc[str1], SZ_FNAME)
+ call printf (" %s: %s (%.2f, %.2f) %s: %g\n")
+ call pargstr (KY_IMNAME)
+ call pargstr (Memc[str1])
+ call pargr (apstatr (ap, CWX))
+ call pargr (apstatr (ap, CWY))
+ call pargstr (KY_SCALE)
+ call pargr (1.0 / apstatr (ap, SCALE))
+
+ call apstats (ap, OUTNAME, Memc[str1], SZ_FNAME)
+ call printf (" %s: %s")
+ call pargstr (KY_OUTNAME)
+ call pargstr (Memc[str1])
+
+ call apstats (ap, CLNAME, Memc[str1], SZ_FNAME)
+ call printf (" %s: %s\n")
+ call pargstr (KY_CLNAME)
+ call pargstr (Memc[str1])
+
+ call printf (" %s = %g %s %s = %b\n")
+ call pargstr (KY_FWHMPSF)
+ call pargr (apstatr (ap, FWHMPSF))
+ call pargstr (UN_ASCALEUNIT)
+ call pargstr (KY_POSITIVE)
+ call pargb (itob (apstati (ap, POSITIVE)))
+
+ call printf (" %s = %g %s %s = %g %s\n")
+ call pargstr (KY_DATAMIN)
+ call pargr (apstatr (ap, DATAMIN))
+ call pargstr (UN_ACOUNTS)
+ call pargstr (KY_DATAMAX)
+ call pargr (apstatr (ap, DATAMAX))
+ call pargstr (UN_ACOUNTS)
+
+ call apstats (ap, EXPOSURE, Memc[str1], SZ_FNAME)
+ call printf (" %s = %s %s = %g %s\n")
+ call pargstr (KY_EXPOSURE)
+ call pargstr (Memc[str1])
+ call pargstr (KY_ITIME)
+ call pargr (apstatr (ap, ITIME))
+ call pargstr (UN_ATIMEUNIT)
+
+ # Set the filter ID.
+ call apstats (ap, FILTER, Memc[str1], SZ_FNAME)
+ call apstats (ap, FILTERID, Memc[str2], SZ_FNAME)
+ call printf (" %s = %s %s = %s\n")
+ call pargstr (KY_FILTER)
+ call pargstr (Memc[str1])
+ call pargstr (KY_FILTERID)
+ call pargstr (Memc[str2])
+
+ # Set the airmass.
+ call apstats (ap, AIRMASS, Memc[str1], SZ_FNAME)
+ call printf (" %s = %s %s = %g\n")
+ call pargstr (KY_AIRMASS)
+ call pargstr (Memc[str1])
+ call pargstr (KY_XAIRMASS)
+ call pargr (apstatr (ap, XAIRMASS))
+
+ # Set the time of observation.
+ call apstats (ap, OBSTIME, Memc[str1], SZ_FNAME)
+ call apstats (ap, OTIME, Memc[str2], SZ_FNAME)
+ call printf (" %s = %s %s = %s\n")
+ call pargstr (KY_OBSTIME)
+ call pargstr (Memc[str1])
+ call pargstr (KY_OTIME)
+ call pargstr (Memc[str2])
+
+ # Set the noise model.
+ call printf ("\nNoise Model\n")
+ call apstats (ap, NSTRING, Memc[str1], SZ_FNAME)
+ call printf (" %s = %s %s %s = %g %s\n")
+ call pargstr (KY_NSTRING)
+ call pargstr (Memc[str1])
+ call pargstr (UN_NMODEL)
+ call pargstr (KY_SKYSIGMA)
+ call pargr (apstatr (ap, SKYSIGMA))
+ call pargstr (UN_NCOUNTS)
+
+ call apstats (ap, GAIN, Memc[str1], SZ_LINE)
+ call printf (" %s = %s %s = %g %s\n")
+ call pargstr (KY_GAIN)
+ call pargstr (Memc[str1])
+ call pargstr (KY_EPADU)
+ call pargr (apstatr (ap, EPADU))
+ call pargstr (UN_NEPADU)
+
+ call apstats (ap, CCDREAD, Memc[str1], SZ_LINE)
+ call printf (" %s = %s %s = %g %s\n")
+ call pargstr (KY_CCDREAD)
+ call pargstr (Memc[str1])
+ call pargstr (KY_READNOISE)
+ call pargr (apstatr (ap, READNOISE))
+ call pargstr (UN_NELECTRONS)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aplib/apotime.x b/noao/digiphot/apphot/aplib/apotime.x
new file mode 100644
index 00000000..2da01e3e
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apotime.x
@@ -0,0 +1,52 @@
+include <imhdr.h>
+include "../lib/apphot.h"
+
+# AP_OTIME -- Fetch the time or epoch of the observation from the image
+# header.
+
+procedure ap_otime (im, ap)
+
+pointer im # pointer to IRAF image
+pointer ap # pointer to apphot structure
+
+char timechar
+int index
+pointer sp, key, otime
+bool streq()
+int strldx()
+
+begin
+ call smark (sp)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ call salloc (otime, SZ_FNAME, TY_CHAR)
+
+ call apstats (ap, OBSTIME, Memc[key], SZ_FNAME)
+ Memc[otime] = EOS
+ if (Memc[key] == EOS)
+ call apstats (ap, OTIME, Memc[otime], SZ_FNAME)
+ else {
+ iferr {
+ call imgstr (im, Memc[key], Memc[otime], SZ_FNAME)
+ } then {
+ call apstats (ap, OTIME, Memc[otime], SZ_FNAME)
+ call eprintf ("Warning: Image %s Keyword: %s not found\n")
+ call pargstr (IM_HDRFILE(im))
+ call pargstr (Memc[key])
+ }
+ }
+ if (Memc[otime] == EOS) {
+ call apsets (ap, OTIME, "INDEF")
+ } else if (streq ("DATE-OBS", Memc[key]) || streq ("date-obs",
+ Memc[key])) {
+ timechar = 'T'
+ index = strldx (timechar, Memc[otime])
+ if (index > 0)
+ call apsets (ap, OTIME, Memc[otime+index])
+ else
+ call apsets (ap, OTIME, "INDEF")
+ } else {
+ call apsets (ap, OTIME, Memc[otime])
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aplib/apoutpars1.x b/noao/digiphot/apphot/aplib/apoutpars1.x
new file mode 100644
index 00000000..c4894bbb
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apoutpars1.x
@@ -0,0 +1,99 @@
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/display.h"
+include "../lib/find.h"
+
+
+# AP_DAPARS -- Procedure to write out the current DATAPARS parameters
+# to the current DATAPARS parameter file.
+
+procedure ap_dapars (ap)
+
+pointer ap # pointer to apphot structure
+
+pointer sp, str, np
+bool itob()
+int apstati()
+pointer clopset()
+real apstatr()
+
+begin
+ # Open the parameter sets.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ np = clopset ("datapars")
+
+ # Set the noise model.
+ call apstats (ap, NSTRING, Memc[str], SZ_FNAME)
+ call clppset (np, "noise", Memc[str])
+
+ # Get the rest of the data dependent parameters.
+ call clppsetr (np, "fwhmpsf", apstatr (ap, FWHMPSF))
+ call clppsetr (np, "scale", 1.0 / apstatr (ap, SCALE))
+ call clppsetb (np, "emission", itob (apstati (ap, POSITIVE)))
+ call clppsetr (np, "datamin", apstatr (ap, DATAMIN))
+ call clppsetr (np, "datamax", apstatr (ap, DATAMAX))
+
+ call clppsetr (np, "sigma", apstatr (ap, SKYSIGMA))
+ call apstats (ap, GAIN, Memc[str], SZ_LINE)
+ call clppset (np, "gain", Memc[str])
+ call clppsetr (np, "epadu", apstatr (ap, EPADU))
+ call apstats (ap, CCDREAD, Memc[str], SZ_LINE)
+ call clppset (np, "ccdread", Memc[str])
+ call clppsetr (np, "readnoise", apstatr (ap, READNOISE))
+
+ call apstats (ap, EXPOSURE, Memc[str], SZ_LINE)
+ call clppset (np, "exposure", Memc[str])
+ call clppsetr (np, "itime", apstatr (ap, ITIME))
+
+ call apstats (ap, AIRMASS, Memc[str], SZ_LINE)
+ call clppset (np, "airmass", Memc[str])
+ call clppsetr (np, "xairmass", apstatr (ap, XAIRMASS))
+
+ call apstats (ap, FILTER, Memc[str], SZ_LINE)
+ call clppset (np, "filter", Memc[str])
+ call apstats (ap, FILTERID, Memc[str], SZ_LINE)
+ call clppset (np, "ifilter", Memc[str])
+
+ call apstats (ap, OBSTIME, Memc[str], SZ_LINE)
+ call clppset (np, "obstime", Memc[str])
+ call apstats (ap, OTIME, Memc[str], SZ_LINE)
+ call clppset (np, "otime", Memc[str])
+
+ # Close the pset files.
+ call clcpset (np)
+ call sfree (sp)
+end
+
+
+# AP_FIPARS -- Procedure to write out the current FINDPARS parameters
+# to the current FINDPARS parameter file.
+
+procedure ap_fipars (ap)
+
+pointer ap # pointer to apphot structure
+
+pointer pp
+bool itob()
+int apstati()
+pointer clopset()
+real apstatr()
+
+begin
+ pp = clopset ("findpars")
+
+ call clppsetr (pp, "nsigma", apstatr (ap, NSIGMA) )
+ call clppsetr (pp, "ratio", apstatr (ap, RATIO))
+ call clppsetr (pp, "theta", apstatr (ap, THETA))
+
+ call clppsetr (pp, "threshold", apstatr (ap, THRESHOLD))
+ call clppsetr (pp, "sharplo", apstatr (ap, SHARPLO))
+ call clppsetr (pp, "sharphi", apstatr (ap, SHARPHI))
+ call clppsetr (pp, "roundlo", apstatr (ap, ROUNDLO))
+ call clppsetr (pp, "roundhi", apstatr (ap, ROUNDHI))
+
+ call clppsetb (pp, "mkdetections", itob (apstati (ap, MKDETECTIONS)))
+
+ call clcpset (pp)
+end
diff --git a/noao/digiphot/apphot/aplib/apoutpars2.x b/noao/digiphot/apphot/aplib/apoutpars2.x
new file mode 100644
index 00000000..79b929c4
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apoutpars2.x
@@ -0,0 +1,146 @@
+include "../lib/display.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+include "../lib/polyphot.h"
+
+
+# AP_CEPARS -- Procedure to write out the current CENTERPARS parameters
+# to the current CENTERPARS parameter file.
+
+procedure ap_cepars (ap)
+
+pointer ap # pointer to apphot structure
+
+pointer sp, str, cp
+bool itob()
+int apstati()
+pointer clopset()
+real apstatr()
+
+begin
+ # Open the parameter set.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ cp = clopset ("centerpars")
+
+ # Write the centering parameters.
+ call apstats (ap, CSTRING, Memc[str], SZ_FNAME)
+ call clppset (cp, "calgorithm", Memc[str])
+ call clppsetr (cp, "cbox", 2.0 * apstatr (ap, CAPERT))
+ call clppsetr (cp, "cthreshold", apstatr (ap, CTHRESHOLD))
+ call clppsetr (cp, "minsnratio", apstatr (ap, MINSNRATIO))
+ call clppseti (cp, "cmaxiter", apstati (ap, CMAXITER))
+ call clppsetr (cp, "maxshift", apstatr (ap, MAXSHIFT))
+ call clppsetb (cp, "clean", itob (apstati (ap, CLEAN)))
+ call clppsetr (cp, "rclean", apstatr (ap, RCLEAN))
+ call clppsetr (cp, "rclip", apstatr (ap, RCLIP))
+ call clppsetr (cp, "kclean", apstatr (ap, SIGMACLEAN))
+ call clppsetb (cp, "mkcenter", itob (apstati (ap, MKCENTER)))
+
+ # Close the pset file.
+ call clcpset (cp)
+ call sfree (sp)
+end
+
+
+# AP_SAPARS -- Procedure to write out the current FITSKYPARS parameters
+# to the FITSKYPARS file.
+
+procedure ap_sapars (ap)
+
+pointer ap # pointer to apphot structure
+
+pointer mp, str, sp
+bool itob()
+int apstati()
+pointer clopset()
+real apstatr()
+
+begin
+ # Open the parameter sets.
+ call smark (mp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ sp = clopset ("fitskypars")
+
+ # Set the sky fitting parameters.
+ call apstats (ap, SSTRING, Memc[str], SZ_FNAME)
+ call clppset (sp, "salgorithm", Memc[str])
+ call clppsetr (sp, "annulus", apstatr (ap, ANNULUS))
+ call clppsetr (sp, "dannulus", apstatr (ap, DANNULUS))
+ call clppsetr (sp, "skyvalue", apstatr (ap, SKY_BACKGROUND))
+ call clppsetr (sp, "khist", apstatr (ap, K1))
+ call clppsetr (sp, "binsize", apstatr (ap, BINSIZE))
+ call clppsetb (sp, "smooth", itob (apstati (ap, SMOOTH)))
+ call clppsetr (sp, "sloclip", apstatr (ap, SLOCLIP))
+ call clppsetr (sp, "shiclip", apstatr (ap, SHICLIP))
+ call clppseti (sp, "smaxiter", apstati (ap, SMAXITER))
+ call clppseti (sp, "snreject", apstati (ap, SNREJECT))
+ call clppsetr (sp, "sloreject", apstatr (ap, SLOREJECT))
+ call clppsetr (sp, "shireject", apstatr (ap, SHIREJECT))
+ call clppsetr (sp, "rgrow", apstatr (ap, RGROW))
+ call clppsetb (sp, "mksky", itob (apstati (ap, MKSKY)))
+
+ # Close up the pset files.
+ call clcpset (sp)
+ call sfree (mp)
+end
+
+
+# AP_PHPARS -- Procedure to write out the PHOTPARS parameters to the
+# PHOTPARS task.
+
+procedure ap_phpars (ap)
+
+pointer ap # pointer to apphot structure
+
+pointer mp, str, pp
+bool itob()
+int apstati()
+pointer clopset()
+real apstatr()
+
+begin
+ # Open the parameter set.
+ call smark (mp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ pp = clopset ("photpars")
+
+ # Set the photometry parameters.
+ call apstats (ap, APERTS, Memc[str], SZ_LINE)
+ call clppset (pp, "apertures", Memc[str])
+ call clppsetr (pp, "zmag", apstatr (ap, ZMAG))
+ call apstats (ap, PWSTRING, Memc[str], SZ_FNAME)
+ call clppset (pp, "weighting", Memc[str])
+ call clppsetb (pp, "mkapert", itob (apstati (ap, MKAPERT)))
+
+ # Close the pset file.
+ call clcpset (pp)
+ call sfree (mp)
+end
+
+
+# AP_POPARS -- Procedure to write the current POLYPARS parameters to the
+# current POLYPARS parameter file.
+
+procedure ap_popars (ap)
+
+pointer ap # pointer to apphot structure
+
+pointer pp
+bool itob()
+int apstati()
+pointer clopset()
+real apstatr()
+
+begin
+ # Open the psets.
+ pp = clopset ("polypars")
+
+ # Set the photometry parameters.
+ call clppsetr (pp, "zmag", apstatr (ap, PYZMAG))
+ call clppsetb (pp, "mkpolygon", itob (apstati (ap, MKPOLYGON)))
+
+ # Close the pset files.
+ call clcpset (pp)
+end
diff --git a/noao/digiphot/apphot/aplib/appadu.x b/noao/digiphot/apphot/aplib/appadu.x
new file mode 100644
index 00000000..121decaf
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/appadu.x
@@ -0,0 +1,37 @@
+include <imhdr.h>
+include "../lib/noise.h"
+
+# AP_PADU -- Procedure to set the gain parameter for the noise model
+# computation.
+
+procedure ap_padu (im, ap)
+
+pointer im # pointer to IRAF image
+pointer ap # pointer to apphot structure
+
+pointer sp, key
+real padu
+real imgetr(), apstatr()
+
+begin
+ call smark (sp)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ call apstats (ap, GAIN, Memc[key], SZ_FNAME)
+ if (Memc[key] == EOS)
+ padu = apstatr (ap, EPADU)
+ else {
+ iferr {
+ padu = imgetr (im, Memc[key])
+ } then {
+ padu = apstatr (ap, EPADU)
+ call eprintf ("Warning: Image %s Keyword %s not found.\n")
+ call pargstr (IM_HDRFILE(im))
+ call pargstr (Memc[key])
+ }
+ }
+ if (IS_INDEFR(padu) || padu <= 0.0)
+ call apsetr (ap, EPADU, 1.0)
+ else
+ call apsetr (ap, EPADU, padu)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aplib/apqrad.x b/noao/digiphot/apphot/aplib/apqrad.x
new file mode 100644
index 00000000..6c035d7f
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apqrad.x
@@ -0,0 +1,119 @@
+include <mach.h>
+include "../lib/apphot.h"
+include "../lib/center.h"
+
+define RADIUS 15.0
+define CRADIUS 5
+
+# AP_QRAD -- Simple radial profile plotter.
+
+procedure ap_qrad (ap, im, wx, wy, gd)
+
+pointer ap # pointer to apphot structure
+pointer im # pointero to the IRAF image
+real wx, wy # cursor coordinates
+pointer gd # pointer to graphics stream
+
+real gwx, gwy, xcenter, ycenter, xc, yc, radius, rmin, rmax, imin, imax
+real u1, u2, v1, v2, x1, x2, y1, y2, xold, yold
+pointer gt, sp, pix, coords, index, r, cmd
+int maxpix, npix, nx, ny, wcs, key, niter
+
+real apstatr()
+pointer ap_gtinit()
+int ap_skypix(), clgcur(), apstati()
+int nscan(), scan()
+
+begin
+ # Check for open graphics stream.
+ if (gd == NULL)
+ return
+ call greactivate (gd, 0)
+ call gclear (gd)
+ call gflush (gd)
+
+ # Get the radius of the extraction region.
+ call printf ("Half width of extraction box (%4.1f) pixels:")
+ call pargr (RADIUS)
+ call flush (STDOUT)
+ if (scan () == EOF)
+ radius = RADIUS
+ else {
+ call gargr (radius)
+ if (nscan () < 1)
+ radius = RADIUS
+ }
+ maxpix = (2 * int (radius) + 1) ** 2
+
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (coords, maxpix, TY_INT)
+ call salloc (index, maxpix, TY_INT)
+ call salloc (pix, maxpix, TY_REAL)
+ call salloc (r, maxpix, TY_REAL)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Fit the center using 3 iterations.
+ xold = wx
+ yold = wy
+ niter = 0
+ repeat {
+ call ap_ictr (im, xold, yold, CRADIUS, apstati (ap,
+ POSITIVE), xcenter, ycenter)
+ niter = niter + 1
+ if (abs (xcenter - xold) <= 1.0 && abs (ycenter - yold) <= 1.0)
+ break
+ xold = xcenter
+ yold = ycenter
+ } until (niter >= 3)
+
+ # Fetch the pixels for the radial profile.
+ npix = ap_skypix (im, xcenter, ycenter, 0.0, radius, Memr[pix],
+ Memi[coords], xc, yc, nx, ny)
+ if (npix <= 0) {
+ call gdeactivate (gd, 0)
+ call sfree (sp)
+ return
+ }
+ call ap_index (Memi[index], npix)
+
+
+ # Store old viewport and window coordinates.
+ call ggview (gd, u1, u2, v1, v2)
+ call ggwind (gd, x1, x2, y1, y2)
+
+ # Initialize the plot and store the viewport and window limits.
+ #call apstats (ap, IMNAME, Memc[cmd], SZ_FNAME)
+ call apstats (ap, IMROOT, Memc[cmd], SZ_FNAME)
+ call ap_ltov (im, xcenter, ycenter, xcenter, ycenter, 1)
+ gt = ap_gtinit (Memc[cmd], xcenter, ycenter)
+
+ # Compute the radius values.
+ call ap_xytor (Memi[coords], Memi[index], Memr[r], npix, xc, yc, nx)
+ call alimr (Memr[r], npix, rmin, rmax)
+ call alimr (Memr[pix], npix, imin, imax)
+
+ # Plot radial profiles.
+ call gclear (gd)
+ call ap_rset (gd, gt, 0.0, rmax, imin, imax, apstatr (ap, SCALE))
+ call ap_plotrad (gd, gt, Memr[r], Memr[pix], npix, "plus")
+
+ # Go into cursor mode.
+ call printf ("Waiting for cursor mode command: [:.help=help,q=quit]")
+ while (clgcur ("gcommands", gwx, gwy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+ if (key == 'q')
+ break
+ call printf (
+ "Waiting for cursor mode command: [:.help=help,q=quit]")
+ }
+
+ # Restore old window and viewport coordinates.
+ call gsview (gd, u1, u2, v1, v2)
+ call gswind (gd, x1, x2, y1, y2)
+
+ # Free plots and working space.
+ call ap_gtfree (gt)
+ call sfree (sp)
+ call gdeactivate (gd, 0)
+end
diff --git a/noao/digiphot/apphot/aplib/aprcursor1.x b/noao/digiphot/apphot/aplib/aprcursor1.x
new file mode 100644
index 00000000..594cbbeb
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/aprcursor1.x
@@ -0,0 +1,584 @@
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+
+
+# AP_CFWHMPSF -- Read the fwhmpsf from the radial profile plot.
+
+real procedure ap_cfwhmpsf (ap, gd, out, stid, rmin, rmax, imin, imax)
+
+pointer ap # pointer to the apphot structure
+pointer gd # pointer to the grapics stream
+int out # output file descriptor
+int stid # sequence number in output file
+real rmin, rmax # x axis limits
+real imin, imax # y axis limits
+
+int wcs, key, stat
+pointer sp, cmd
+real scale, fwhmpsf, xjunk, yjunk
+int clgcur()
+real apstatr(), ap_vfwhmpsf()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ scale = apstatr (ap, SCALE)
+
+ # Mark the FWHM of the PSF on the plot.
+ call printf ("Mark half-width half-maximum of the psf (%g) pixels:")
+ call pargr (apstatr (ap, FWHMPSF) * scale / 2.0)
+ call gscur (gd, apstatr (ap, FWHMPSF) * scale / 2.0, (imin + imax) /
+ 2.0)
+ stat = clgcur ("gcommands", xjunk, yjunk, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || xjunk <= 0.0 || xjunk > rmax)
+ fwhmpsf = apstatr (ap, FWHMPSF)
+ else
+ fwhmpsf = 2.0 * xjunk / scale
+
+ # Verify the results.
+ call apsetr (ap, FWHMPSF, fwhmpsf)
+ fwhmpsf = ap_vfwhmpsf (ap)
+
+ # Save the results.
+ if (out != NULL && stid > 1)
+ call ap_rparam (out, KY_FWHMPSF, fwhmpsf, UN_ASCALEUNIT,
+ "full width half maximum of the psf")
+
+ call sfree (sp)
+
+ return (fwhmpsf)
+end
+
+
+# AP_CDATAMIN -- Read the good data minimum off the radial profile plot.
+
+real procedure ap_cdatamin (ap, gd, out, stid, rmin, rmax, imin, imax)
+
+pointer ap # pointer to the apphot structure
+pointer gd # pointer to the grapics stream
+int out # output file descriptor
+int stid # sequence number in output file
+real rmin, rmax # x axis limits
+real imin, imax # y axis limits
+
+int wcs, key, stat
+pointer sp, cmd
+real datamin, xjunk, yjunk
+int clgcur()
+real apstatr(), ap_vdatamin()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Mark the datamin on the plot.
+ call printf ("Mark the good data minimum (%g) counts:")
+ call pargr (apstatr (ap, DATAMIN))
+ if (IS_INDEFR (apstatr (ap, DATAMIN)))
+ call gscur (gd, (rmin + rmax) / 2.0, imin - 1.0)
+ else
+ call gscur (gd, (rmin + rmax) / 2.0, apstatr (ap, DATAMIN))
+ stat = clgcur ("gcommands", xjunk, yjunk, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || yjunk < imin || yjunk > imax)
+ datamin = apstatr (ap, DATAMIN)
+ else
+ datamin = yjunk
+
+ # Verify the results.
+ call apsetr (ap, DATAMIN, datamin)
+ datamin = ap_vdatamin (ap)
+
+ # Store the results.
+ if (out != NULL && stid > 1)
+ call ap_rparam (out, KY_DATAMIN, datamin, UN_ACOUNTS,
+ "minimum good data value")
+ call sfree (sp)
+
+ return (datamin)
+end
+
+
+# AP_CDATAMAX -- Read the good data maximum off the radial profile plot.
+
+real procedure ap_cdatamax (ap, gd, out, stid, rmin, rmax, imin, imax)
+
+pointer ap # pointer to the apphot structure
+pointer gd # pointer to the grapics stream
+int out # output file descriptor
+int stid # sequence number in output file
+real rmin, rmax # x axis limits
+real imin, imax # y axis limits
+
+int wcs, key, stat
+pointer sp, cmd
+real datamax, xjunk, yjunk
+int clgcur()
+real apstatr(), ap_vdatamax()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Mark the datamax on the plot.
+ call printf ("Mark the good data maximum (%g) counts:")
+ call pargr (apstatr (ap, DATAMAX))
+ if (IS_INDEFR (apstatr (ap, DATAMAX)))
+ call gscur (gd, (rmin + rmax) / 2.0, imax + 1.0)
+ else
+ call gscur (gd, (rmin + rmax) / 2.0, apstatr (ap, DATAMAX))
+ stat = clgcur ("gcommands", xjunk, yjunk, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || yjunk < imin || yjunk > imax)
+ datamax = apstatr (ap, DATAMAX)
+ else
+ datamax = yjunk
+
+ # Verify the result.
+ call apsetr (ap, DATAMAX, datamax)
+ datamax = ap_vdatamax (ap)
+
+ # Store the results.
+ if (out != NULL && stid > 1)
+ call ap_rparam (out, KY_DATAMAX, datamax, UN_ACOUNTS,
+ "maximum good data value")
+ call sfree (sp)
+
+ return (datamax)
+end
+
+
+# AP_CCAPERT -- Read the centering aperture of the radial profile plot.
+
+real procedure ap_ccapert (ap, gd, out, stid, rmin, rmax, imin, imax)
+
+pointer ap # pointer to the apphot structure
+pointer gd # pointer to the grapics stream
+int out # output file descriptor
+int stid # output file sequence number
+real rmin, rmax # x axis limits
+real imin, imax # y axis limits
+
+int wcs, key, stat
+pointer sp, cmd
+real scale, capert, xjunk, yjunk
+int clgcur()
+real apstatr(), ap_vcapert()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ scale = apstatr (ap, SCALE)
+
+ # Mark the centering aperture on the plot.
+ call printf ("Mark centering box half width (%g) pixels:")
+ call pargr (apstatr (ap, CAPERT) * scale)
+ call gscur (gd, apstatr (ap, CAPERT) * scale, (imin + imax) / 2.0)
+ stat = clgcur ("gcommands", xjunk, yjunk, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || xjunk <= 0.0 || xjunk > rmax)
+ capert = apstatr (ap, CAPERT)
+ else
+ capert = xjunk / scale
+
+ # Verify the results.
+ call apsetr (ap, CAPERT, capert)
+ capert = ap_vcapert (ap)
+
+ # Store the results.
+ if (out != NULL && stid > 1)
+ call ap_rparam (out, KY_CAPERT, 2.0 * capert, UN_CSCALEUNIT,
+ "centering box width")
+ call sfree (sp)
+
+ return (capert)
+end
+
+
+# AP_CRCLEAN -- Read the cleaning radius off the radial profile plot.
+
+real procedure ap_crclean (ap, gd, out, stid, rmin, rmax, imin, imax)
+
+pointer ap # pointer to the apphot structure
+pointer gd # pointer to the grapics stream
+int out # output file descriptor
+int stid # sequence number in output file
+real rmin, rmax # x axis limits
+real imin, imax # y axis limits
+
+int wcs, key, stat
+pointer sp, cmd
+real scale, rclean, xjunk, yjunk
+int clgcur()
+real apstatr(), ap_vrclean()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ scale = apstatr (ap, SCALE)
+
+ # Mark the cleaning radius on the plot.
+ call printf (
+ "Mark the centering algorithm cleaning radius (%g) pixels:")
+ call pargr (apstatr (ap, RCLEAN) * scale)
+ call gscur (gd, apstatr (ap, RCLEAN) * scale, (imin + imax) /
+ 2.0)
+ stat = clgcur ("gcommands", xjunk, yjunk, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || xjunk <= 0.0 || xjunk > rmax)
+ rclean = apstatr (ap, RCLEAN)
+ else
+ rclean = xjunk / scale
+
+ # Verify the results.
+ call apsetr (ap, RCLEAN, rclean)
+ rclean = ap_vrclean (ap)
+
+ # Save the results.
+ if (out != NULL && stid > 1)
+ call ap_rparam (out, KY_RCLEAN, rclean, UN_CSCALEUNIT,
+ "cleaning radius")
+ call sfree (sp)
+
+ return (rclean)
+end
+
+
+# AP_CRCLIP -- Read the clipping radius off the radial profile plot.
+
+real procedure ap_crclip (ap, gd, out, stid, rmin, rmax, imin, imax)
+
+pointer ap # pointer to the apphot structure
+pointer gd # pointer to the grapics stream
+int out # output file descriptor
+int stid # sequence number in output file
+real rmin, rmax # x axis limits
+real imin, imax # y axis limits
+
+int wcs, key, stat
+pointer sp, cmd
+real scale, rclip, xjunk, yjunk
+int clgcur()
+real apstatr(), ap_vrclip()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ scale = apstatr (ap, SCALE)
+
+ # Mark clipping radius on the plot.
+ call printf (
+ "Mark the centering algorithm clipping radius (%g) pixels:")
+ call pargr (apstatr (ap, RCLIP) * scale)
+ call gscur (gd, apstatr (ap, RCLIP) * scale, (imin + imax) /
+ 2.0)
+ stat = clgcur ("gcommands", xjunk, yjunk, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || xjunk <= 0.0 || xjunk > rmax)
+ rclip = apstatr (ap, RCLIP)
+ else
+ rclip = xjunk / scale
+
+ # Verify the results.
+ call apsetr (ap, RCLIP, rclip)
+ rclip = ap_vrclip (ap)
+
+ # Save the results.
+ if (out != NULL && stid > 1)
+ call ap_rparam (out, KY_RCLIP, rclip, UN_CSCALEUNIT,
+ "clipping radius")
+ call sfree (sp)
+
+ return (rclip)
+end
+
+
+# AP_CANNULUS -- Read the sky annulus of the radial profile plot.
+
+real procedure ap_cannulus (ap, gd, out, stid, rmin, rmax, imin, imax)
+
+pointer ap # pointer to the apphot structure
+pointer gd # pointer to the grapics stream
+int out # output file descriptor
+int stid # output file sequence number
+real rmin, rmax # x axis limits
+real imin, imax # y axis limits
+
+int wcs, key, stat
+pointer sp, cmd
+real scale, annulus, xjunk, yjunk
+int clgcur()
+real apstatr(), ap_vannulus()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ scale = apstatr (ap, SCALE)
+
+ # Mark the inner sky radius.
+ call printf ("Mark inner sky radius (%g) pixels:")
+ call pargr (apstatr (ap, ANNULUS) * apstatr (ap, SCALE))
+ call gscur (gd, apstatr (ap, ANNULUS) * apstatr (ap, SCALE),
+ (imin + imax) / 2.0)
+ stat = clgcur ("gcommands", xjunk, yjunk, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || xjunk < 0.0 || xjunk > rmax)
+ annulus = apstatr (ap, ANNULUS)
+ else
+ annulus = xjunk / scale
+
+ # Verify the result.
+ call apsetr (ap, ANNULUS, annulus)
+ annulus = ap_vannulus (ap)
+
+ # Save the results.
+ if (out != NULL && stid > 1)
+ call ap_rparam (out, KY_ANNULUS, annulus, UN_SSCALEUNIT,
+ "radius of the inner sky annulus")
+ call sfree (sp)
+
+ return (annulus)
+end
+
+
+# AP_CRGROW -- Read the region growing radius off the radial profile plot.
+
+real procedure ap_crgrow (ap, gd, out, stid, rmin, rmax, imin, imax)
+
+pointer ap # pointer to the apphot structure
+pointer gd # pointer to the grapics stream
+int out # the output file descriptor
+int stid # output file sequence number
+real rmin, rmax # x axis limits
+real imin, imax # y axis limits
+
+int wcs, key, stat
+pointer sp, cmd
+real scale, rgrow, xjunk, yjunk
+int clgcur()
+real apstatr(), ap_vrgrow()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ scale = apstatr (ap, SCALE)
+
+ # Mark the inner sky radius.
+ call printf ("Mark region growing radius (%g) pixels:")
+ call pargr (apstatr (ap, RGROW) * apstatr (ap, SCALE))
+ call gscur (gd, apstatr (ap, RGROW) * apstatr (ap, SCALE),
+ (imin + imax) / 2.0)
+ stat = clgcur ("gcommands", xjunk, yjunk, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || xjunk < 0.0 || xjunk > rmax)
+ rgrow = apstatr (ap, RGROW)
+ else
+ rgrow = xjunk / scale
+
+ # Verify the region growing radius.
+ call apsetr (ap, RGROW, rgrow)
+ rgrow = ap_vrgrow (ap)
+
+ # Save the results.
+ if (out != NULL && stid > 1)
+ call ap_rparam (out, KY_RGROW, rgrow, UN_SSCALEUNIT,
+ "region growing radius")
+ call sfree (sp)
+
+ return (rgrow)
+end
+
+
+# AP_CDANNULUS -- Read the sky annulus width off the radial profile plot.
+
+real procedure ap_cdannulus (ap, gd, out, stid, annulus, rmin, rmax, imin, imax)
+
+pointer ap # pointer to the apphot structure
+pointer gd # pointer to the grapics stream
+int out # output file descriptor
+int stid # output file sequence number
+real rmin, rmax # x axis limits
+real imin, imax # y axis limits
+
+int wcs, key, stat
+pointer sp, cmd
+real scale, annulus, dannulus, xjunk, yjunk
+int clgcur()
+real apstatr(), ap_vdannulus()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ scale = apstatr (ap, SCALE)
+
+ # Mark the outer sky radius.
+ call printf ("Mark outer sky radius (%g) pixels:")
+ call pargr (apstatr (ap, SCALE) * (apstatr (ap, ANNULUS) +
+ apstatr (ap, DANNULUS)))
+ call gscur (gd, apstatr (ap, SCALE) * (apstatr (ap, ANNULUS) +
+ apstatr (ap, DANNULUS)), (imin + imax) / 2.0)
+ stat = clgcur ("gcommands", xjunk, yjunk, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || (xjunk / scale < annulus) || xjunk > rmax)
+ dannulus = apstatr (ap, DANNULUS)
+ else
+ dannulus = (xjunk / scale - annulus)
+
+ # Verify the width of the annulus.
+ call apsetr (ap, DANNULUS, dannulus)
+ dannulus = ap_vdannulus (ap)
+
+ # Save the results.
+ if (out != NULL && stid > 1)
+ call ap_rparam (out, KY_DANNULUS, dannulus, UN_SSCALEUNIT,
+ "width of the sky annulus")
+ call sfree (sp)
+
+ return (dannulus)
+end
+
+
+# AP_CSIGMA -- Read the sky sigma from the radial profile plot.
+
+real procedure ap_csigma (ap, gd, out, stid, rmin, rmax, imin, imax)
+
+pointer ap # pointer to the apphot structure
+pointer gd # pointer to the grapics stream
+int out # output file descriptor
+int stid # sequence number in output file
+real rmin, rmax # x axis limits
+real imin, imax # y axis limits
+
+int wcs, key, stat
+pointer sp, cmd
+real mean, sigma3, xjunk, yjunk
+int clgcur()
+int apstati()
+real apstatr(), ap_vsigma()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Estimate the mean sky.
+ if (apstati (ap, POSITIVE) == YES)
+ mean = imin
+ else
+ mean = imax
+ call printf ("Estimate sky sigma. Mark mean sky level (%g):")
+ call pargr (mean)
+ call gscur (gd, (rmin + rmax) / 2.0, mean)
+ stat = clgcur ("gcommands", xjunk, yjunk, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || yjunk < imin || yjunk > imax)
+ mean = mean
+ else
+ mean = yjunk
+
+ # Estimate the sky sigma.
+ if (IS_INDEFR (apstatr (ap, SKYSIGMA)))
+ sigma3 = INDEFR
+ else
+ sigma3 = 3.0 * apstatr (ap, SKYSIGMA)
+ call printf ("Next mark 3 sigma sky level (%g):")
+ call pargr (sigma3)
+ if (IS_INDEFR(sigma3))
+ call gscur (gd, (rmin + rmax) / 2.0, imin - 1.0)
+ else
+ call gscur (gd, (rmin + rmax) / 2.0, mean + sigma3)
+ stat = clgcur ("gcommands", xjunk, yjunk, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || yjunk < imin || yjunk > imax) {
+ sigma3 = apstatr (ap, SKYSIGMA)
+ if (! IS_INDEFR (sigma3))
+ sigma3 = 3.0 * sigma3
+ } else
+ sigma3 = abs (yjunk - mean)
+
+ # Verify the results.
+ if (IS_INDEFR(sigma3))
+ call apsetr (ap, SKYSIGMA, INDEFR)
+ else
+ call apsetr (ap, SKYSIGMA, sigma3 / 3.0)
+ sigma3 = ap_vsigma (ap)
+
+ # Save the results.
+ if (out != NULL && stid > 1)
+ call ap_rparam (out, KY_SKYSIGMA, sigma3, UN_NCOUNTS,
+ "standard deviation of 1 sky pixel")
+
+ call sfree (sp)
+
+ if (IS_INDEFR(sigma3))
+ return (sigma3)
+ else
+ return (sigma3 / 3.0)
+end
+
+
+# AP_CAPER -- Read the apertures off the radial profile plot.
+
+procedure ap_caper (ap, gd, out, stid, outstr, rmin, rmax, imin, imax)
+
+pointer ap # pointer to the apphot structure
+pointer gd # pointer to the grapics stream
+int out # output file descriptor
+int stid # output file number sequence
+char outstr[ARB] # output apertures
+real rmin, rmax # x axis limits
+real imin, imax # y axis limits
+
+int i, wcs, key, naperts
+pointer sp, cmd, tstr, aperts
+real scale, xjunk, yjunk
+int clgcur()
+int apstati(), strlen()
+real apstatr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (tstr, SZ_LINE, TY_CHAR)
+ scale = apstatr (ap, SCALE)
+
+ # Get the apertures.
+ naperts = apstati (ap, NAPERTS)
+ call salloc (aperts, naperts, TY_REAL)
+ call ap_arrayr (ap, APERTS, Memr[aperts])
+
+ # Encode the old aperture string.
+ outstr[1] = EOS
+ do i = 1, naperts - 1 {
+ call sprintf (outstr[1+strlen(outstr)], SZ_FNAME,"%.2f,")
+ call pargr (Memr[aperts+i-1] * scale)
+ }
+ call sprintf (outstr[1+strlen(outstr)], SZ_FNAME,"%.2f")
+ call pargr (Memr[aperts+naperts-1] * scale)
+
+ # Type prompt string.
+ call printf ("Mark apertures (%s) pixels [q=quit]:")
+ call pargstr (outstr)
+ call gscur (gd, Memr[aperts] * scale, (imin + imax) / 2.0)
+
+ # Mark the apertures.
+ outstr[1] = EOS
+ Memc[tstr] = EOS
+ while (clgcur ("gcommands", xjunk, yjunk, wcs, key, Memc[cmd],
+ SZ_LINE) != EOF) {
+ if (key == 'q')
+ break
+ if (xjunk <= 0.0 || xjunk > rmax)
+ next
+ call sprintf (outstr[1+strlen(outstr)], SZ_FNAME,"%.2f,")
+ call pargr (xjunk / scale)
+ call sprintf (Memc[tstr+strlen(Memc[tstr])], SZ_FNAME,"%.2f,")
+ call pargr (xjunk)
+ call printf ("Mark apertures (%s) pixels [q=quit]:")
+ call pargstr (Memc[tstr])
+ }
+ outstr[strlen(outstr)] = EOS
+
+ # Verify the results.
+ call apsets (ap, APERTS, outstr)
+ call ap_vaperts (ap, outstr, SZ_LINE)
+
+ # Save the results.
+ if (out != NULL && stid > 1)
+ call ap_sparam (out, KY_APERTS, outstr, UN_PSCALEUNIT,
+ "list of aperture radii")
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aplib/aprcursor2.x b/noao/digiphot/apphot/aplib/aprcursor2.x
new file mode 100644
index 00000000..e24049b5
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/aprcursor2.x
@@ -0,0 +1,144 @@
+include "../lib/apphot.h"
+include "../lib/radprof.h"
+include "../lib/fitpsf.h"
+
+# AP_CRPROF -- Read the radial profile size off the radial profile plot.
+
+real procedure ap_crprof (ap, gd, out, stid, rmin, rmax, imin, imax)
+
+pointer ap # pointer to the apphot structure
+pointer gd # pointer to the grapics stream
+int out # output file descriptor
+int stid # output file sequence number
+real rmin, rmax # x axis limits
+real imin, imax # y axis limits
+
+int wcs, key, stat
+pointer sp, cmd
+real scale, radius, xjunk, yjunk
+int clgcur()
+real apstatr(), ap_vrpradius()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ scale = apstatr (ap, SCALE)
+
+ # Estimate the minimum (maximum) data level.
+ # Mark maximum radius of the radial profile.
+ call printf ("Mark maximum radius for profile (%g) pixels:")
+ call pargr (apstatr (ap, RPRADIUS) * scale)
+ call gscur (gd, apstatr (ap, RPRADIUS) * scale, (imin + imax) / 2.0)
+ stat = clgcur ("gcommands", xjunk, yjunk, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || xjunk < 0.0 || xjunk > rmax)
+ radius = apstatr (ap, RPRADIUS)
+ else
+ radius = xjunk / scale
+
+ # Verify the results.
+ call apsetr (ap, RPRADIUS, radius)
+ radius = ap_vrpradius (ap)
+
+ # Store the results.
+ if (out != NULL && stid > 1)
+ call ap_rparam (out, KY_RPRADIUS, radius, UN_RSCALEUNIT,
+ "fitting radius")
+
+ call sfree (sp)
+
+ return (radius)
+end
+
+
+# AP_CRPSTEP -- Read the radial profile size off the radial profile plot.
+
+real procedure ap_crpstep (ap, gd, out, stid, rmin, rmax, imin, imax)
+
+pointer ap # pointer to the apphot structure
+pointer gd # pointer to the grapics stream
+int out # output file descriptor
+int stid # output file sequence number
+real rmin, rmax # x axis limits
+real imin, imax # y axis limits
+
+int wcs, key, stat
+pointer sp, cmd
+real scale, step, xjunk, yjunk
+int clgcur()
+real apstatr(), ap_vstep()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ scale = apstatr (ap, SCALE)
+
+ # Mark the radial profile step size.
+ call printf ("Mark step size (%g) pixels:")
+ call pargr (apstatr (ap, RPSTEP) * scale)
+ call gscur (gd, apstatr (ap, RPSTEP) * scale, (imin + imax) / 2.0)
+ stat = clgcur ("gcommands", xjunk, yjunk, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || xjunk < 0.0 || xjunk > rmax)
+ step = apstatr (ap, RPSTEP)
+ else
+ step = xjunk / scale
+
+ # Verify the results.
+ call apsetr (ap, RPSTEP, step)
+ step = ap_vstep (ap)
+
+ # Store the results.
+ if (out != NULL && stid > 1)
+ call ap_rparam (out, KY_RPSTEP, step, UN_RSCALEUNIT,
+ "step size in pixels")
+
+ call sfree (sp)
+
+ return (step)
+end
+
+
+# AP_CPAPERT -- Read the fitting radius on the radial profile plot.
+
+real procedure ap_cpapert (ap, gd, out, stid, rmin, rmax, imin, imax)
+
+pointer ap # pointer to the apphot structure
+pointer gd # pointer to the grapics stream
+int out # output file descriptor
+int stid # output file sequence number
+real rmin, rmax # x axis limits
+real imin, imax # y axis limits
+
+int wcs, key, stat
+pointer sp, cmd
+real scale, psfapert, xjunk, yjunk
+int clgcur()
+real apstatr(), ap_vpsfapert()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ scale = apstatr (ap, SCALE)
+
+ # Mark the fitting radius on the plot.
+ call printf ("Mark fitting box half width (%g) pixels:")
+ call pargr (apstatr (ap, PSFAPERT) * scale)
+ call gscur (gd, apstatr (ap, PSFAPERT) * scale, (imin + imax) / 2.0)
+ stat = clgcur ("gcommands", xjunk, yjunk, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || xjunk <= 0.0 || xjunk > rmax)
+ psfapert = apstatr (ap, PSFAPERT)
+ else
+ psfapert = xjunk / scale
+
+ # Verify the results.
+ call apsetr (ap, PSFAPERT, psfapert)
+ psfapert = ap_vpsfapert (ap)
+
+ # Store the results.
+ if (out != NULL && stid > 1)
+ call ap_rparam (out, KY_PSFAPERT, 2.0 * psfapert, UN_PSFSCALEUNIT,
+ "width of the fitting box")
+
+ call sfree (sp)
+
+ return (psfapert)
+end
diff --git a/noao/digiphot/apphot/aplib/aprdnoise.x b/noao/digiphot/apphot/aplib/aprdnoise.x
new file mode 100644
index 00000000..e4fbda2c
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/aprdnoise.x
@@ -0,0 +1,36 @@
+include <imhdr.h>
+include "../lib/noise.h"
+
+# AP_RDNOISE - Procedure to set the image read noise parameter.
+
+procedure ap_rdnoise (im, ap)
+
+pointer im # pointer to IRAF image
+pointer ap # pointer to apphot structure
+
+pointer sp, key
+real rdnoise
+real imgetr(), apstatr()
+
+begin
+ call smark (sp)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ call apstats (ap, CCDREAD, Memc[key], SZ_FNAME)
+ if (Memc[key] == EOS)
+ rdnoise = apstatr (ap, READNOISE)
+ else {
+ iferr {
+ rdnoise = imgetr (im, Memc[key])
+ } then {
+ rdnoise = apstatr (ap, READNOISE)
+ call eprintf ("Warning: Image %s Keyword %s not found.\n")
+ call pargstr (IM_HDRFILE(im))
+ call pargstr (Memc[key])
+ }
+ }
+ if (IS_INDEFR(rdnoise) || rdnoise <= 0.0)
+ call apsetr (ap, READNOISE, 0.0)
+ else
+ call apsetr (ap, READNOISE, rdnoise)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aplib/apset.x b/noao/digiphot/apphot/aplib/apset.x
new file mode 100644
index 00000000..2248f561
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apset.x
@@ -0,0 +1,72 @@
+define MAXERR1 500
+define MAXERR2 1000
+
+
+# APSETS -- Procedure to set an apphot string parameter.
+
+procedure apsets (ap, param, str)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+char str[ARB] # string parameter
+
+begin
+ if (param <= MAXERR1)
+ call ap1sets (ap, param, str)
+ else if (param <= MAXERR2)
+ call ap2sets (ap, param, str)
+end
+
+
+# APSETI -- Procedure to set an integer apphot parameter.
+
+procedure apseti (ap, param, ival)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+int ival # integer value
+
+begin
+ if (param <= MAXERR1)
+ call ap1seti (ap, param, ival)
+ else if (param <= MAXERR2)
+ call ap2seti (ap, param, ival)
+ else
+ call error (0, "Unknown APPHOT integer parameter")
+end
+
+
+# APSETR -- Procedure to set a real apphot parameter.
+
+procedure apsetr (ap, param, rval)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+real rval # real value
+
+begin
+ if (param <= MAXERR1)
+ call ap1setr (ap, param, rval)
+ else if (param <= MAXERR2)
+ call ap2setr (ap, param, rval)
+ else
+ call error (0, "Unknown APPHOT real parameter")
+end
+
+
+# APSETD -- Procedure to set a double apphot parameter.
+
+procedure apsetd (ap, param, dval)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+double dval # double value
+
+begin
+ if (param <= MAXERR1)
+ call ap1setd (ap, param, dval)
+ else if (param <= MAXERR2)
+ call ap2setd (ap, param, dval)
+ else
+ call error (0, "Unknown APPHOT double parameter")
+end
diff --git a/noao/digiphot/apphot/aplib/apset1.x b/noao/digiphot/apphot/aplib/apset1.x
new file mode 100644
index 00000000..6c4d6f1b
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apset1.x
@@ -0,0 +1,330 @@
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/centerdef.h"
+include "../lib/center.h"
+include "../lib/fitskydef.h"
+include "../lib/fitsky.h"
+include "../lib/photdef.h"
+include "../lib/phot.h"
+include "../lib/fitpsfdef.h"
+include "../lib/fitpsf.h"
+
+# AP1SETS -- Procedure to set an apphot string parameter.
+
+procedure ap1sets (ap, param, str)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+char str[ARB] # string parameter
+
+int naperts
+pointer ctr, sky, phot, psf
+real aperts[MAX_NAPERTS]
+int ap_getaperts()
+
+begin
+ ctr = AP_PCENTER(ap)
+ sky = AP_PSKY(ap)
+ phot = AP_PPHOT(ap)
+ psf = AP_PPSF(ap)
+
+ switch (param) {
+ case IMNAME:
+ call strcpy (str, AP_IMNAME(ap), SZ_FNAME)
+ case IMROOT:
+ call strcpy (str, AP_IMROOT(ap), SZ_FNAME)
+ case CLNAME:
+ call strcpy (str, AP_CLNAME(ap), SZ_FNAME)
+ case CLROOT:
+ call strcpy (str, AP_CLROOT(ap), SZ_FNAME)
+ case PLOTFILE:
+ call strcpy (str, AP_PLOTFILE(ap), SZ_FNAME)
+ case OUTNAME:
+ call strcpy (str, AP_OUTNAME(ap), SZ_FNAME)
+ case EXPOSURE:
+ call strcpy (str, AP_EXPOSURE(ap), SZ_FNAME)
+ case AIRMASS:
+ call strcpy (str, AP_AIRMASS(ap), SZ_FNAME)
+ case FILTER:
+ call strcpy (str, AP_FILTER(ap), SZ_FNAME)
+ case FILTERID:
+ call strcpy (str, AP_FILTERID(ap), SZ_FNAME)
+ case OBSTIME:
+ call strcpy (str, AP_OBSTIME(ap), SZ_FNAME)
+ case OTIME:
+ call strcpy (str, AP_OTIME(ap), SZ_FNAME)
+
+ case CSTRING:
+ call strcpy (str, AP_CSTRING(ctr), SZ_FNAME)
+
+ case SSTRING:
+ call strcpy (str, AP_SSTRING(sky), SZ_FNAME)
+
+ case APSTRING:
+ call strcpy (str, AP_APSTRING(phot), SZ_FNAME)
+ case APERTS:
+ naperts = ap_getaperts (str, aperts, MAX_NAPERTS)
+ if (naperts > 0) {
+ call strcpy (str, AP_APSTRING(phot), SZ_LINE)
+ AP_NAPERTS(phot) = naperts
+ call realloc (AP_APERTS(phot), AP_NAPERTS(phot), TY_REAL)
+ call realloc (AP_AREA(phot), AP_NAPERTS(phot), TY_DOUBLE)
+ call realloc (AP_SUMS(phot), AP_NAPERTS(phot), TY_DOUBLE)
+ call realloc (AP_MAGS(phot), AP_NAPERTS(phot), TY_REAL)
+ call realloc (AP_MAGERRS(phot), AP_NAPERTS(phot), TY_REAL)
+ call amovr (aperts, Memr[AP_APERTS(phot)], AP_NAPERTS(phot))
+ call asrtr (Memr[AP_APERTS(phot)], Memr[AP_APERTS(phot)],
+ AP_NAPERTS(phot))
+ }
+ case PWSTRING:
+ call strcpy (str, AP_PWSTRING(phot), SZ_FNAME)
+
+ case PSFSTRING:
+ call strcpy (str, AP_PSFSTRING(psf), SZ_FNAME)
+
+ default:
+ call error (0, "APSETS: Unknown apphot string parameter")
+ }
+end
+
+
+# AP1SETI -- Procedure to set an integer apphot parameter.
+
+procedure ap1seti (ap, param, ival)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+int ival # integer value
+
+pointer cen, sky, phot, psf
+
+begin
+ cen = AP_PCENTER(ap)
+ sky = AP_PSKY(ap)
+ phot = AP_PPHOT(ap)
+ psf = AP_PPSF(ap)
+
+ switch (param) {
+ case POSITIVE:
+ AP_POSITIVE(ap) = ival
+ case WCSIN:
+ AP_WCSIN(ap) = ival
+ case WCSOUT:
+ AP_WCSOUT(ap) = ival
+ case MW:
+ AP_MW(ap) = ival
+ case CTIN:
+ AP_CTIN(ap) = ival
+ case CTOUT:
+ AP_CTOUT(ap) = ival
+
+ case CENTERFUNCTION:
+ AP_CENTERFUNCTION(cen) = ival
+ case CLEAN:
+ AP_CLEAN(cen) = ival
+ case CMAXITER:
+ AP_CMAXITER(cen) = ival
+
+ case SKYFUNCTION:
+ AP_SKYFUNCTION(sky) = ival
+ case SMAXITER:
+ AP_SMAXITER(sky) = ival
+ case SNREJECT:
+ AP_SNREJECT(sky) = ival
+ case SMOOTH:
+ AP_SMOOTH(sky) = ival
+ case NSKY:
+ AP_NSKY(sky) = ival
+ case NSKY_REJECT:
+ AP_NSKY_REJECT(sky) = ival
+
+ case PWEIGHTS:
+ AP_PWEIGHTS(phot) = ival
+
+ case PSFUNCTION:
+ AP_PSFUNCTION(psf) = ival
+ case NPARS:
+ AP_PSFNPARS(psf) = ival
+ case MAXNPARS:
+ AP_MAXNPARS(psf) = ival
+ case PMAXITER:
+ AP_PMAXITER(psf) = ival
+ case PNREJECT:
+ AP_PNREJECT(psf) = ival
+
+ default:
+ call error (0, "APSETI: Unknown apphot integer parameter")
+ }
+end
+
+
+# AP1SETR -- Procedure to set a real apphot parameter.
+
+procedure ap1setr (ap, param, rval)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+real rval # real value
+
+pointer cen, sky, phot, psf
+
+begin
+ cen = AP_PCENTER(ap)
+ sky = AP_PSKY(ap)
+ phot = AP_PPHOT(ap)
+ psf = AP_PPSF(ap)
+
+ switch (param) {
+
+ case FWHMPSF:
+ AP_FWHMPSF(ap) = rval
+ case SCALE:
+ AP_SCALE(ap) = rval
+ case WX:
+ AP_WX(ap) = rval
+ case WY:
+ AP_WY(ap) = rval
+ case ITIME:
+ AP_ITIME(ap) = rval
+ case CWX:
+ AP_CWX(ap) = rval
+ case CWY:
+ AP_CWY(ap) = rval
+ case DATAMIN:
+ AP_DATAMIN(ap) = rval
+ case DATAMAX:
+ AP_DATAMAX(ap) = rval
+ case XAIRMASS:
+ AP_XAIRMASS(ap) = rval
+
+ case CDATALIMIT:
+ AP_CDATALIMIT(cen) = rval
+ case XSHIFT:
+ AP_XSHIFT(cen) = rval
+ case YSHIFT:
+ AP_YSHIFT(cen) = rval
+ case OXSHIFT:
+ AP_OXSHIFT(cen) = rval
+ case OYSHIFT:
+ AP_OYSHIFT(cen) = rval
+ case CXCUR:
+ AP_CXCUR(cen) = rval
+ case CYCUR:
+ AP_CYCUR(cen) = rval
+ case CAPERT:
+ AP_CAPERT(cen) = rval
+ case CTHRESHOLD:
+ AP_CTHRESHOLD(cen) = rval
+ case MAXSHIFT:
+ AP_MAXSHIFT(cen) = rval
+ case MINSNRATIO:
+ AP_MINSNRATIO(cen) = rval
+ case RCLEAN:
+ AP_RCLEAN(cen) = rval
+ case RCLIP:
+ AP_RCLIP(cen) = rval
+ case SIGMACLEAN:
+ AP_SIGMACLEAN(cen) = rval
+ case OXINIT:
+ AP_OXINIT(cen) = rval
+ case OYINIT:
+ AP_OYINIT(cen) = rval
+ case XCENTER:
+ AP_XCENTER(cen) = rval
+ case YCENTER:
+ AP_YCENTER(cen) = rval
+ case OXCENTER:
+ AP_OXCENTER(cen) = rval
+ case OYCENTER:
+ AP_OYCENTER(cen) = rval
+ case XERR:
+ AP_XERR(cen) = rval
+ case YERR:
+ AP_YERR(cen) = rval
+
+ case ANNULUS:
+ AP_ANNULUS(sky) = rval
+ case DANNULUS:
+ AP_DANNULUS(sky) = rval
+ case SXCUR:
+ AP_SXCUR(sky) = rval
+ case SYCUR:
+ AP_SYCUR(sky) = rval
+ case OSXCUR:
+ AP_OSXCUR(sky) = rval
+ case OSYCUR:
+ AP_OSYCUR(sky) = rval
+ case K1:
+ AP_K1(sky) = rval
+ case SLOREJECT:
+ AP_SLOREJECT(sky) = rval
+ case SHIREJECT:
+ AP_SHIREJECT(sky) = rval
+ case SLOCLIP:
+ AP_SLOCLIP(sky) = rval
+ case SHICLIP:
+ AP_SHICLIP(sky) = rval
+ case BINSIZE:
+ AP_BINSIZE(sky) = rval
+ case RGROW:
+ AP_RGROW(sky) = rval
+ case SKY_BACKGROUND:
+ AP_SKYBACKGROUND(sky) = rval
+ case SKY_MODE:
+ AP_SKY_MODE(sky) = rval
+ case SKY_SIGMA:
+ AP_SKY_SIG(sky) = rval
+ case SKY_SKEW:
+ AP_SKY_SKEW(sky) = rval
+
+ case PXCUR:
+ AP_PXCUR(phot) = rval
+ case PYCUR:
+ AP_PYCUR(phot) = rval
+ case OPXCUR:
+ AP_OPXCUR(phot) = rval
+ case OPYCUR:
+ AP_OPYCUR(phot) = rval
+ case ZMAG:
+ AP_ZMAG(phot) = rval
+
+ case PK2:
+ AP_PK2(psf) = rval
+ case PSFAPERT:
+ AP_PSFAPERT(psf) = rval
+ case PFXCUR:
+ AP_PFXCUR(psf) = rval
+ case PFYCUR:
+ AP_PFYCUR(psf) = rval
+ case OPFXCUR:
+ AP_OPFXCUR(psf) = rval
+ case OPFYCUR:
+ AP_OPFYCUR(psf) = rval
+
+ default:
+ call error (0, "APSETR: Unknown apphot real parameter")
+ }
+end
+
+
+# AP1SETD -- Procedure to set a double apphot parameter.
+
+procedure ap1setd (ap, param, dval)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+double dval # double value
+
+pointer cen, sky, phot, psf
+
+begin
+ cen = AP_PCENTER(ap)
+ sky = AP_PSKY(ap)
+ phot = AP_PPHOT(ap)
+ psf = AP_PPSF(ap)
+
+ switch (param) {
+ default:
+ call error (0, "APSETD: Unknown apphot double parameter")
+ }
+end
diff --git a/noao/digiphot/apphot/aplib/apset2.x b/noao/digiphot/apphot/aplib/apset2.x
new file mode 100644
index 00000000..85200daf
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apset2.x
@@ -0,0 +1,227 @@
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/displaydef.h"
+include "../lib/display.h"
+include "../lib/noisedef.h"
+include "../lib/noise.h"
+include "../lib/polyphotdef.h"
+include "../lib/polyphot.h"
+include "../lib/radprofdef.h"
+include "../lib/radprof.h"
+include "../lib/finddef.h"
+include "../lib/find.h"
+
+# AP2SETS -- Procedure to set an apphot string parameter.
+
+procedure ap2sets (ap, param, str)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+char str[ARB] # string parameter
+
+pointer nse, ply
+
+begin
+ nse = AP_NOISE(ap)
+ ply = AP_POLY(ap)
+
+ switch (param) {
+ case PYNAME:
+ call strcpy (str, AP_PYNAME(ply), SZ_FNAME)
+ case PYROOT:
+ call strcpy (str, AP_PYROOT(ply), SZ_FNAME)
+ case GAIN:
+ call strcpy (str, AP_GAIN(nse), SZ_FNAME)
+ case NSTRING:
+ call strcpy (str, AP_NSTRING(nse), SZ_FNAME)
+ case CCDREAD:
+ call strcpy (str, AP_CCDREAD(nse), SZ_FNAME)
+ default:
+ call error (0, "APSETS: Unknown apphot string parameter")
+ }
+end
+
+
+# AP2SETI -- Procedure to set an integer apphot parameter.
+
+procedure ap2seti (ap, param, ival)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+int ival # integer value
+
+pointer dsp, nse, ply, rprof
+
+begin
+ nse = AP_NOISE(ap)
+ dsp = AP_PDISPLAY(ap)
+ ply = AP_POLY(ap)
+ rprof = AP_RPROF(ap)
+
+ switch (param) {
+ case RPORDER:
+ AP_RPORDER(rprof) = ival
+ case RPNREJECT:
+ AP_RPNREJECT(rprof) = ival
+ case PYNVER:
+ AP_PYNVER(ply) = ival
+ case PYBADPIX:
+ AP_PYBADPIX(ply) = ival
+ case MKSKY:
+ AP_MKSKY(dsp) = ival
+ case MKCENTER:
+ AP_MKCENTER(dsp) = ival
+ case MKAPERT:
+ AP_MKAPERT(dsp) = ival
+ case MKPOLYGON:
+ AP_MKPOLYGON(dsp) = ival
+ case MKDETECTIONS:
+ AP_MKDETECTIONS(dsp) = ival
+ case NOISEFUNCTION:
+ AP_NOISEFUNCTION(nse) = ival
+ case MKPSFBOX:
+ AP_MKPSFBOX(dsp) = ival
+ case RADPLOTS:
+ AP_RADPLOTS(dsp) = ival
+ case RPNPTS:
+ AP_RPNPTS(rprof) = ival
+ case RPNDATA:
+ AP_RPNDATA(rprof) = ival
+ case RPNDATAREJ:
+ AP_RPNDATAREJ(rprof) = ival
+ default:
+ call error (0, "APSETI: Unknown apphot integer parameter")
+ }
+end
+
+
+# AP2SETR -- Procedure to set a real apphot parameter.
+
+procedure ap2setr (ap, param, rval)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+real rval # real value
+
+pointer nse, ply, rprof, fnd
+
+begin
+ nse = AP_NOISE(ap)
+ ply = AP_POLY(ap)
+ rprof = AP_RPROF(ap)
+ fnd = AP_PFIND(ap)
+
+ switch (param) {
+ case RPFWHM:
+ AP_RPFWHM(rprof) = rval
+ case INORM:
+ AP_INORM(rprof) = rval
+ case TNORM:
+ AP_TINORM(rprof) = rval
+ case DNORM:
+ AP_DNORM(rprof) = rval
+ case RPXCUR:
+ AP_RPXCUR(rprof) = rval
+ case RPYCUR:
+ AP_RPYCUR(rprof) = rval
+ case ORPXCUR:
+ AP_ORPXCUR(rprof) = rval
+ case ORPYCUR:
+ AP_ORPYCUR(rprof) = rval
+ case RPRADIUS:
+ AP_RPRADIUS(rprof) = rval
+ AP_RPNPTS(rprof) = int (AP_RPRADIUS(rprof) / AP_RPSTEP(rprof)) + 1
+ call realloc (AP_RPDIST(rprof), AP_RPNPTS(rprof), TY_REAL)
+ call realloc (AP_INTENSITY(rprof), AP_RPNPTS(rprof), TY_REAL)
+ call realloc (AP_DINTENSITY(rprof), AP_RPNPTS(rprof), TY_REAL)
+ call realloc (AP_TINTENSITY(rprof), AP_RPNPTS(rprof), TY_REAL)
+ case RPSTEP:
+ AP_RPSTEP(rprof) = rval
+ AP_RPNPTS(rprof) = int (AP_RPRADIUS(rprof) / AP_RPSTEP(rprof)) + 1
+ call realloc (AP_RPDIST(rprof), AP_RPNPTS(rprof), TY_REAL)
+ call realloc (AP_INTENSITY(rprof), AP_RPNPTS(rprof), TY_REAL)
+ call realloc (AP_DINTENSITY(rprof), AP_RPNPTS(rprof), TY_REAL)
+ call realloc (AP_TINTENSITY(rprof), AP_RPNPTS(rprof), TY_REAL)
+ case RPKSIGMA:
+ AP_RPKSIGMA(rprof) = rval
+ case PYZMAG:
+ AP_PYZMAG(ply) = rval
+ case PYMAG:
+ AP_PYMAG(ply) = rval
+ case PYMAGERR:
+ AP_PYMAGERR(ply) = rval
+ case PYX:
+ AP_PYX(ply) = rval
+ case PYY:
+ AP_PYY(ply) = rval
+ case PYMINRAD:
+ AP_PYMINRAD(ply) = rval
+ case PYCX:
+ AP_PYCX(ply) = rval
+ case PYCY:
+ AP_PYCY(ply) = rval
+ case OPYCX:
+ AP_OPYCX(ply) = rval
+ case OPYCY:
+ AP_OPYCY(ply) = rval
+ case PYXMEAN:
+ AP_PYXMEAN(ply) = rval
+ case PYYMEAN:
+ AP_PYYMEAN(ply) = rval
+ case OPYXMEAN:
+ AP_OPYXMEAN(ply) = rval
+ case OPYYMEAN:
+ AP_OPYYMEAN(ply) = rval
+ case SKYSIGMA:
+ AP_SKYSIGMA(nse) = rval
+ case EPADU:
+ AP_EPADU(nse) = rval
+ case READNOISE:
+ AP_READNOISE(nse) = rval
+ case THRESHOLD:
+ AP_THRESHOLD(fnd) = rval
+ case RATIO:
+ AP_RATIO(fnd) = rval
+ case THETA:
+ AP_THETA(fnd) = rval
+ case NSIGMA:
+ AP_NSIGMA(fnd) = rval
+ case SHARPLO:
+ AP_SHARPLO(fnd) = rval
+ case SHARPHI:
+ AP_SHARPHI(fnd) = rval
+ case ROUNDLO:
+ AP_ROUNDLO(fnd) = rval
+ case ROUNDHI:
+ AP_ROUNDHI(fnd) = rval
+ default:
+ call error (0, "APSETR: Unknown apphot real parameter")
+ }
+end
+
+
+# AP2SETD -- Procedure to set a double apphot parameter.
+
+procedure ap2setd (ap, param, dval)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+double dval # double value
+
+pointer nse, ply, rprof, fnd
+
+begin
+ nse = AP_NOISE(ap)
+ ply = AP_POLY(ap)
+ rprof = AP_RPROF(ap)
+ fnd = AP_PFIND(ap)
+
+ switch (param) {
+ case PYNPIX:
+ AP_PYNPIX(ply) = dval
+ case PYFLUX:
+ AP_PYFLUX(ply) = dval
+ default:
+ call error (0, "APSETD: Unknown apphot double parameter")
+ }
+end
diff --git a/noao/digiphot/apphot/aplib/apshowplot.x b/noao/digiphot/apphot/aplib/apshowplot.x
new file mode 100644
index 00000000..ed188d52
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apshowplot.x
@@ -0,0 +1,83 @@
+include "../lib/apphot.h"
+
+define RADIUS 15.0
+define CRADIUS 5
+
+# AP_SHOWPLOT -- Plot a radial profile of a star.
+
+int procedure ap_showplot (ap, im, wx, wy, gd, xcenter, ycenter, rmin,
+ rmax, imin, imax)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the image
+real wx, wy # the cursor coordinates
+pointer gd # pointer to the graphics stream
+real xcenter, ycenter # the centered coordinates
+real rmin, rmax # minimum and maximum radius
+real imin, imax # minimum and maximum intensity
+
+real radius, xc, yc, xold, yold
+pointer sp, r, skypix, coords, index, str, gt
+int niter, lenbuf, nx, ny, nsky
+
+real apstatr()
+pointer ap_gtinit()
+int ap_gvrad(), apstati(), ap_skypix()
+
+begin
+ call gclear (gd)
+ call gflush (gd)
+
+ # Set the pixel extraction parameters.
+ lenbuf = ap_gvrad (RADIUS, radius)
+
+ # Initialize.
+ call smark (sp)
+ call salloc (r, lenbuf, TY_REAL)
+ call salloc (skypix, lenbuf, TY_REAL)
+ call salloc (coords, lenbuf, TY_INT)
+ call salloc (index, lenbuf, TY_INT)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Center the star.
+ niter = 0
+ xold = wx
+ yold = wy
+ repeat {
+ call ap_ictr (im, xold, yold, CRADIUS, apstati (ap, POSITIVE),
+ xcenter, ycenter)
+ niter = niter + 1
+ if (abs (xcenter - xold) <= 1.0 && abs (ycenter - yold) <= 1.0)
+ break
+ xold = xcenter
+ yold = ycenter
+ } until (niter >= 3)
+
+ # Fetch the pixels.
+ nsky = ap_skypix (im, xcenter, ycenter, 0.0, radius, Memr[skypix],
+ Memi[coords], xc, yc, nx, ny)
+ if (nsky <= 0) {
+ call sfree (sp)
+ return (ERR)
+ }
+ call ap_index (Memi[index], nsky)
+
+ # Compute the radius and intensity values.
+ call ap_xytor (Memi[coords], Memi[index], Memr[r], nsky, xc, yc, nx)
+ call alimr (Memr[r], nsky, rmin, rmax)
+ call alimr (Memr[skypix], nsky, imin, imax)
+
+ # Plot the radial profiles.
+ #call apstats (ap, IMNAME, Memc[str], SZ_FNAME)
+ call apstats (ap, IMROOT, Memc[str], SZ_FNAME)
+ call ap_ltov (im, xcenter, ycenter, xc, yc, 1)
+ gt = ap_gtinit (Memc[str], xc, yc)
+ call ap_rset (gd, gt, 0.0, rmax, imin, imax, apstatr (ap, SCALE))
+ call ap_plotrad (gd, gt, Memr[r], Memr[skypix], nsky, "plus")
+
+ # Cleanup.
+ call ap_gtfree (gt)
+ call sfree (sp)
+
+ return (OK)
+end
diff --git a/noao/digiphot/apphot/aplib/apstat.x b/noao/digiphot/apphot/aplib/apstat.x
new file mode 100644
index 00000000..9ddc98ca
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apstat.x
@@ -0,0 +1,77 @@
+define MAXERR1 500
+define MAXERR2 1000
+
+# APSTATS -- Procedure to fetch an apphot string parameter.
+
+procedure apstats (ap, param, str, maxch)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+char str[ARB] # string
+int maxch # maximum number of characters
+
+begin
+ if (param <= MAXERR1)
+ call ap1stats (ap, param, str, maxch)
+ else if (param <= MAXERR2)
+ call ap2stats (ap, param, str, maxch)
+ else
+ call error (0, "APSTATS: Unknown apphot string parameter")
+end
+
+
+# APSTATI -- Procedure to set an integer apphot parameter.
+
+int procedure apstati (ap, param)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+
+int ap1stati(), ap2stati()
+
+begin
+ if (param <= MAXERR1)
+ return (ap1stati (ap, param))
+ else if (param <= MAXERR2)
+ return (ap2stati (ap, param))
+ else
+ call error (0, "APSTATI: Unknown apphot integer parameter")
+end
+
+
+# APSTATR -- Procedure to set a real apphot parameter.
+
+real procedure apstatr (ap, param)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+
+real ap1statr(), ap2statr()
+
+begin
+ if (param <= MAXERR1)
+ return (ap1statr (ap, param))
+ else if (param <= MAXERR2)
+ return (ap2statr (ap, param))
+ else
+ call error (0, "APSTATR: Unknown apphot real parameter")
+end
+
+
+# APSTATD -- Procedure to set a double apphot parameter.
+
+double procedure apstatd (ap, param)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+
+double ap1statd(), ap2statd()
+
+begin
+ if (param <= MAXERR1)
+ return (ap1statd (ap, param))
+ else if (param <= MAXERR2)
+ return (ap2statd (ap, param))
+ else
+ call error (0, "APSTATD: Unknown apphot double parameter")
+end
diff --git a/noao/digiphot/apphot/aplib/apstat1.x b/noao/digiphot/apphot/aplib/apstat1.x
new file mode 100644
index 00000000..0df220ae
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apstat1.x
@@ -0,0 +1,316 @@
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/centerdef.h"
+include "../lib/center.h"
+include "../lib/fitskydef.h"
+include "../lib/fitsky.h"
+include "../lib/photdef.h"
+include "../lib/phot.h"
+include "../lib/fitpsfdef.h"
+include "../lib/fitpsf.h"
+
+# AP1STATS -- Procedure to fetch an apphot string parameter.
+
+procedure ap1stats (ap, param, str, maxch)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+char str[ARB] # string
+int maxch # maximum number of characters
+
+pointer cen, sky, phot, psf
+
+begin
+ cen = AP_PCENTER(ap)
+ sky = AP_PSKY(ap)
+ phot = AP_PPHOT(ap)
+ psf = AP_PPSF(ap)
+
+ switch (param) {
+ case IMNAME:
+ call strcpy (AP_IMNAME(ap), str, maxch)
+ case IMROOT:
+ call strcpy (AP_IMROOT(ap), str, maxch)
+ case CLNAME:
+ call strcpy (AP_CLNAME(ap), str, maxch)
+ case CLROOT:
+ call strcpy (AP_CLROOT(ap), str, maxch)
+ case PLOTFILE:
+ call strcpy (AP_PLOTFILE(ap), str, maxch)
+ case OUTNAME:
+ call strcpy (AP_OUTNAME(ap), str, maxch)
+ case EXPOSURE:
+ call strcpy (AP_EXPOSURE(ap), str, maxch)
+ case AIRMASS:
+ call strcpy (AP_AIRMASS(ap), str, maxch)
+ case FILTER:
+ call strcpy (AP_FILTER(ap), str, maxch)
+ case FILTERID:
+ call strcpy (AP_FILTERID(ap), str, maxch)
+ case OBSTIME:
+ call strcpy (AP_OBSTIME(ap), str, maxch)
+ case OTIME:
+ call strcpy (AP_OTIME(ap), str, maxch)
+
+ case CSTRING:
+ call strcpy (AP_CSTRING(cen), str, maxch)
+
+ case SSTRING:
+ call strcpy (AP_SSTRING(sky), str, maxch)
+
+ case APSTRING:
+ call strcpy (AP_APSTRING(phot), str, maxch)
+ case APERTS:
+ call strcpy (AP_APSTRING(phot), str, maxch)
+ case PWSTRING:
+ call strcpy (AP_PWSTRING(phot), str, maxch)
+
+ case PSFSTRING:
+ call strcpy (AP_PSFSTRING(psf), str, maxch)
+
+ default:
+ call error (0, "APSTATS: Unknown apphot string parameter")
+ }
+end
+
+
+# AP1STATI -- Procedure to set an integer apphot parameter.
+
+int procedure ap1stati (ap, param)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+
+pointer cen, sky, phot, psf
+
+begin
+ cen = AP_PCENTER(ap)
+ sky = AP_PSKY(ap)
+ phot = AP_PPHOT(ap)
+ psf = AP_PPSF(ap)
+
+ switch (param) {
+ case POSITIVE:
+ return (AP_POSITIVE(ap))
+ case WCSIN:
+ return (AP_WCSIN(ap))
+ case WCSOUT:
+ return (AP_WCSOUT(ap))
+ case MW:
+ return (AP_MW(ap))
+ case CTIN:
+ return (AP_CTIN(ap))
+ case CTOUT:
+ return (AP_CTOUT(ap))
+
+ case CENTERFUNCTION:
+ return (AP_CENTERFUNCTION(cen))
+ case CLEAN:
+ return (AP_CLEAN(cen))
+ case CMAXITER:
+ return (AP_CMAXITER(cen))
+
+ case SKYFUNCTION:
+ return (AP_SKYFUNCTION(sky))
+ case SMAXITER:
+ return (AP_SMAXITER(sky))
+ case SNREJECT:
+ return (AP_SNREJECT(sky))
+ case SMOOTH:
+ return (AP_SMOOTH(sky))
+ case NSKY:
+ return (AP_NSKY(sky))
+ case NSKY_REJECT:
+ return (AP_NSKY_REJECT(sky))
+
+ case NAPERTS:
+ return (AP_NAPERTS(phot))
+ case PWEIGHTS:
+ return (AP_PWEIGHTS(phot))
+
+ case MAXNPARS:
+ return (AP_MAXNPARS(psf))
+ case NPARS:
+ return (AP_PSFNPARS(psf))
+ case PMAXITER:
+ return (AP_PMAXITER(psf))
+ case PSFUNCTION:
+ return (AP_PSFUNCTION(psf))
+ case PNREJECT:
+ return (AP_PNREJECT(psf))
+
+ default:
+ call error (0, "APSTATI: Unknown apphot integer parameter")
+ }
+end
+
+
+# AP1STATR -- Procedure to set a real apphot parameter.
+
+real procedure ap1statr (ap, param)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+
+pointer cen, sky, phot, psf
+
+begin
+ cen = AP_PCENTER(ap)
+ sky = AP_PSKY(ap)
+ phot = AP_PPHOT(ap)
+ psf = AP_PPSF(ap)
+
+ switch (param) {
+
+ case FWHMPSF:
+ return (AP_FWHMPSF(ap))
+ case SCALE:
+ return (AP_SCALE(ap))
+ case WX:
+ return (AP_WX(ap))
+ case WY:
+ return (AP_WY(ap))
+ case ITIME:
+ return (AP_ITIME(ap))
+ case CWX:
+ return (AP_CWX(ap))
+ case CWY:
+ return (AP_CWY(ap))
+ case DATAMIN:
+ return (AP_DATAMIN(ap))
+ case DATAMAX:
+ return (AP_DATAMAX(ap))
+ case XAIRMASS:
+ return (AP_XAIRMASS(ap))
+
+ case CDATALIMIT:
+ return (AP_CDATALIMIT(cen))
+ case XSHIFT:
+ return (AP_XSHIFT(cen))
+ case YSHIFT:
+ return (AP_YSHIFT(cen))
+ case OXSHIFT:
+ return (AP_OXSHIFT(cen))
+ case OYSHIFT:
+ return (AP_OYSHIFT(cen))
+ case CXCUR:
+ return (AP_CXCUR(cen))
+ case CYCUR:
+ return (AP_CYCUR(cen))
+ case CAPERT:
+ return (AP_CAPERT(cen))
+ case CTHRESHOLD:
+ return (AP_CTHRESHOLD(cen))
+ case MAXSHIFT:
+ return (AP_MAXSHIFT(cen))
+ case MINSNRATIO:
+ return (AP_MINSNRATIO(cen))
+ case RCLEAN:
+ return (AP_RCLEAN(cen))
+ case RCLIP:
+ return (AP_RCLIP(cen))
+ case SIGMACLEAN:
+ return (AP_SIGMACLEAN(cen))
+
+ case OXINIT:
+ return (AP_OXINIT(cen))
+ case OYINIT:
+ return (AP_OYINIT(cen))
+ case XCENTER:
+ return (AP_XCENTER(cen))
+ case YCENTER:
+ return (AP_YCENTER(cen))
+ case OXCENTER:
+ return (AP_OXCENTER(cen))
+ case OYCENTER:
+ return (AP_OYCENTER(cen))
+ case XERR:
+ return (AP_XERR(cen))
+ case YERR:
+ return (AP_YERR(cen))
+
+ case SXCUR:
+ return (AP_SXCUR(sky))
+ case SYCUR:
+ return (AP_SYCUR(sky))
+ case OSXCUR:
+ return (AP_OSXCUR(sky))
+ case OSYCUR:
+ return (AP_OSYCUR(sky))
+ case ANNULUS:
+ return (AP_ANNULUS(sky))
+ case DANNULUS:
+ return (AP_DANNULUS(sky))
+ case K1:
+ return (AP_K1(sky))
+ case SLOREJECT:
+ return (AP_SLOREJECT(sky))
+ case SHIREJECT:
+ return (AP_SHIREJECT(sky))
+ case SLOCLIP:
+ return (AP_SLOCLIP(sky))
+ case SHICLIP:
+ return (AP_SHICLIP(sky))
+ case BINSIZE:
+ return (AP_BINSIZE(sky))
+ case RGROW:
+ return (AP_RGROW(sky))
+ case SKY_BACKGROUND:
+ return (AP_SKYBACKGROUND(sky))
+ case SKY_MODE:
+ return (AP_SKY_MODE(sky))
+ case SKY_SIGMA:
+ return (AP_SKY_SIG(sky))
+ case SKY_SKEW:
+ return (AP_SKY_SKEW(sky))
+
+ case PXCUR:
+ return (AP_PXCUR(phot))
+ case PYCUR:
+ return (AP_PYCUR(phot))
+ case OPXCUR:
+ return (AP_OPXCUR(phot))
+ case OPYCUR:
+ return (AP_OPYCUR(phot))
+ case ZMAG:
+ return (AP_ZMAG(phot))
+
+ case PSFAPERT:
+ return (AP_PSFAPERT(psf))
+ case PK2:
+ return (AP_PK2(psf))
+ case PFXCUR:
+ return (AP_PFXCUR(psf))
+ case PFYCUR:
+ return (AP_PFYCUR(psf))
+ case OPFXCUR:
+ return (AP_OPFXCUR(psf))
+ case OPFYCUR:
+ return (AP_OPFYCUR(psf))
+
+ default:
+ call error (0, "APSTATR: Unknown apphot real parameter")
+ }
+end
+
+
+# AP1STATD -- Procedure to set a double apphot parameter.
+
+double procedure ap1statd (ap, param)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+
+pointer cen, sky, phot, psf
+
+begin
+ cen = AP_PCENTER(ap)
+ sky = AP_PSKY(ap)
+ phot = AP_PPHOT(ap)
+ psf = AP_PPSF(ap)
+
+ switch (param) {
+ default:
+ call error (0, "APSTATD: Unknown apphot double parameter")
+ }
+end
diff --git a/noao/digiphot/apphot/aplib/apstat2.x b/noao/digiphot/apphot/aplib/apstat2.x
new file mode 100644
index 00000000..032b19e5
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apstat2.x
@@ -0,0 +1,215 @@
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/displaydef.h"
+include "../lib/display.h"
+include "../lib/noisedef.h"
+include "../lib/noise.h"
+include "../lib/polyphotdef.h"
+include "../lib/polyphot.h"
+include "../lib/radprofdef.h"
+include "../lib/radprof.h"
+include "../lib/finddef.h"
+include "../lib/find.h"
+
+# AP2STATS -- Procedure to fetch an apphot string parameter.
+
+procedure ap2stats (ap, param, str, maxch)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+char str[ARB] # string
+int maxch # maximum number of characters
+
+pointer nse, ply
+
+begin
+ nse = AP_NOISE(ap)
+ ply = AP_POLY(ap)
+
+ switch (param) {
+ case PYNAME:
+ call strcpy (AP_PYNAME(ply), str, maxch)
+ case PYROOT:
+ call strcpy (AP_PYROOT(ply), str, maxch)
+ case GAIN:
+ call strcpy (AP_GAIN(nse), str, maxch)
+ case NSTRING:
+ call strcpy (AP_NSTRING(nse), str, maxch)
+ case CCDREAD:
+ call strcpy (AP_CCDREAD(nse), str, maxch)
+ default:
+ call error (0, "APSTATS: Unknown apphot string parameter")
+ }
+end
+
+
+# AP2STATI -- Procedure to set an integer apphot parameter.
+
+int procedure ap2stati (ap, param)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+
+pointer dsp, nse, ply, rprof
+
+begin
+ dsp = AP_PDISPLAY(ap)
+ nse = AP_NOISE(ap)
+ ply = AP_POLY(ap)
+ rprof = AP_RPROF(ap)
+
+ switch (param) {
+ case RPORDER:
+ return (AP_RPORDER(rprof))
+ case RPNREJECT:
+ return (AP_RPNREJECT(rprof))
+ case PYNVER:
+ return (AP_PYNVER(ply))
+ case PYBADPIX:
+ return (AP_PYBADPIX(ply))
+ case MKSKY:
+ return (AP_MKSKY(dsp))
+ case MKCENTER:
+ return (AP_MKCENTER(dsp))
+ case MKAPERT:
+ return (AP_MKAPERT(dsp))
+ case MKPOLYGON:
+ return (AP_MKPOLYGON(dsp))
+ case MKDETECTIONS:
+ return (AP_MKDETECTIONS(dsp))
+ case NOISEFUNCTION:
+ return (AP_NOISEFUNCTION(nse))
+ case MKPSFBOX:
+ return (AP_MKPSFBOX(dsp))
+ case RADPLOTS:
+ return (AP_RADPLOTS(dsp))
+ case RPNPTS:
+ return (AP_RPNPTS(rprof))
+ case RPNDATA:
+ return (AP_RPNDATA(rprof))
+ case RPNDATAREJ:
+ return (AP_RPNDATAREJ(rprof))
+ default:
+ call error (0, "APSTATI: Unknown apphot integer parameter")
+ }
+end
+
+
+# AP2STATR -- Procedure to set a real apphot parameter.
+
+real procedure ap2statr (ap, param)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+
+pointer nse, ply, rprof, fnd
+
+begin
+ nse = AP_NOISE(ap)
+ ply = AP_POLY(ap)
+ rprof = AP_RPROF(ap)
+ fnd = AP_PFIND(ap)
+
+ switch (param) {
+ case RPFWHM:
+ return (AP_RPFWHM(rprof))
+ case INORM:
+ return (AP_INORM(rprof))
+ case TNORM:
+ return (AP_TINORM(rprof))
+ case DNORM:
+ return (AP_DNORM(rprof))
+ case RPXCUR:
+ return (AP_RPXCUR(rprof))
+ case RPYCUR:
+ return (AP_RPYCUR(rprof))
+ case ORPXCUR:
+ return (AP_ORPXCUR(rprof))
+ case ORPYCUR:
+ return (AP_ORPYCUR(rprof))
+ case RPRADIUS:
+ return (AP_RPRADIUS(rprof))
+ case RPSTEP:
+ return (AP_RPSTEP(rprof))
+ case RPKSIGMA:
+ return (AP_RPKSIGMA(rprof))
+ case PYZMAG:
+ return (AP_PYZMAG(ply))
+ case PYMAG:
+ return (AP_PYMAG(ply))
+ case PYMAGERR:
+ return (AP_PYMAGERR(ply))
+ case PYX:
+ return (AP_PYX(ply))
+ case PYY:
+ return (AP_PYY(ply))
+ case PYMINRAD:
+ return (AP_PYMINRAD(ply))
+ case PYXMEAN:
+ return (AP_PYXMEAN(ply))
+ case PYYMEAN:
+ return (AP_PYYMEAN(ply))
+ case OPYXMEAN:
+ return (AP_OPYXMEAN(ply))
+ case OPYYMEAN:
+ return (AP_OPYYMEAN(ply))
+ case PYCX:
+ return (AP_PYCX(ply))
+ case PYCY:
+ return (AP_PYCY(ply))
+ case OPYCX:
+ return (AP_OPYCX(ply))
+ case OPYCY:
+ return (AP_OPYCY(ply))
+ case SKYSIGMA:
+ return (AP_SKYSIGMA(nse))
+ case EPADU:
+ return (AP_EPADU(nse))
+ case READNOISE:
+ return (AP_READNOISE(nse))
+ case THRESHOLD:
+ return (AP_THRESHOLD(fnd))
+ case RATIO:
+ return (AP_RATIO(fnd))
+ case THETA:
+ return (AP_THETA(fnd))
+ case NSIGMA:
+ return (AP_NSIGMA(fnd))
+ case SHARPLO:
+ return (AP_SHARPLO(fnd))
+ case SHARPHI:
+ return (AP_SHARPHI(fnd))
+ case ROUNDLO:
+ return (AP_ROUNDLO(fnd))
+ case ROUNDHI:
+ return (AP_ROUNDHI(fnd))
+ default:
+ call error (0, "APSTATR: Unknown apphot real parameter")
+ }
+end
+
+
+# AP2STATD -- Procedure to set a double apphot parameter.
+
+double procedure ap2statd (ap, param)
+
+pointer ap # pointer to apphot structure
+int param # parameter
+
+pointer nse, ply, rprof, fnd
+
+begin
+ nse = AP_NOISE(ap)
+ ply = AP_POLY(ap)
+ rprof = AP_RPROF(ap)
+ fnd = AP_PFIND(ap)
+
+ switch (param) {
+ case PYNPIX:
+ return (AP_PYNPIX(ply))
+ case PYFLUX:
+ return (AP_PYFLUX(ply))
+ default:
+ call error (0, "APSTATD: Unknown apphot double parameter")
+ }
+end
diff --git a/noao/digiphot/apphot/aplib/apverify1.x b/noao/digiphot/apphot/aplib/apverify1.x
new file mode 100644
index 00000000..1ecd04b6
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apverify1.x
@@ -0,0 +1,582 @@
+include <math.h>
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+
+# AP_GVRAD -- Verify or get the radius of the extraction box.
+
+int procedure ap_gvrad (defradius, radius)
+
+real defradius # the default radius
+real radius # the output radius
+
+int lenbuf
+int scan(), nscan()
+
+begin
+ call printf (
+ "Radius of extraction box in pixels (%4.1f) (CR or value): ")
+ call pargr (defradius)
+ call flush (STDOUT)
+
+ if (scan () == EOF)
+ radius = defradius
+ else {
+ call gargr (radius)
+ if (nscan () < 1)
+ radius = defradius
+ }
+ lenbuf = PI * radius * (radius + 1.0)
+
+ return (lenbuf)
+end
+
+
+# AP_VFWHMPSF -- Verify the full width maximum of the psf.
+
+real procedure ap_vfwhmpsf (ap)
+
+pointer ap # pointer to the apphot structure
+
+real scale, fwhmpsf
+int scan(), nscan()
+real apstatr()
+
+begin
+ scale = apstatr (ap, SCALE)
+ call printf ("FWHM of features in scale units (%g) (CR or value): ")
+ call pargr (apstatr (ap, FWHMPSF))
+ call flush (STDOUT)
+
+ # Confirm the fwhmpsf.
+ if (scan() == EOF)
+ fwhmpsf = apstatr (ap, FWHMPSF)
+ else {
+ call gargr (fwhmpsf)
+ if (nscan () != 1)
+ fwhmpsf = apstatr (ap, FWHMPSF)
+ }
+
+ call printf ("\tNew FWHM of features: %g scale units %g pixels\n")
+ call pargr (fwhmpsf)
+ call pargr (scale * fwhmpsf)
+ call apsetr (ap, FWHMPSF, fwhmpsf)
+
+ return (fwhmpsf)
+end
+
+
+# AP_VDATAMIN-- Verify the minimum good data value.
+
+real procedure ap_vdatamin (ap)
+
+pointer ap # pointer to the apphot structure
+
+real datamin
+int scan(), nscan()
+real apstatr()
+
+begin
+ # Confirm the threshold parameter.
+ call printf ("Minimum good data value (%g) (CR or value): ")
+ call pargr (apstatr (ap, DATAMIN))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ datamin = apstatr (ap, DATAMIN)
+ else {
+ call gargr (datamin)
+ if (nscan () != 1)
+ datamin = apstatr (ap, DATAMIN)
+ }
+
+ call printf ("\tNew minimum good data value: %g counts\n")
+ call pargr (datamin)
+ call apsetr (ap, DATAMIN, datamin)
+
+ return (datamin)
+end
+
+
+# AP_VDATAMAX-- Verify the maximum good data value.
+
+real procedure ap_vdatamax (ap)
+
+pointer ap # pointer to the apphot structure
+
+real datamax
+int scan(), nscan()
+real apstatr()
+
+begin
+ # Confirm the threshold parameter.
+ call printf ("Maximum good data value (%g) (CR or value): ")
+ call pargr (apstatr (ap, DATAMAX))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ datamax = apstatr (ap, DATAMAX)
+ else {
+ call gargr (datamax)
+ if (nscan () != 1)
+ datamax = apstatr (ap, DATAMAX)
+ }
+
+ call printf ("\tNew maximum good data value: %g counts\n")
+ call pargr (datamax)
+ call apsetr (ap, DATAMAX, datamax)
+
+ return (datamax)
+end
+
+
+# AP_VSIGMA -- Verify the standard deviation of the sky
+
+real procedure ap_vsigma (ap)
+
+pointer ap # pointer to the apphot structure
+
+real skysigma
+int scan(), nscan()
+real apstatr()
+
+begin
+ # Confirm the sky sigma parameter.
+ call printf (
+ "Standard deviation of background in counts (%g) (CR or value): ")
+ call pargr (apstatr (ap, SKYSIGMA))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ skysigma = apstatr (ap, SKYSIGMA)
+ else {
+ call gargr (skysigma)
+ if (nscan () != 1)
+ skysigma = apstatr (ap, SKYSIGMA)
+ }
+
+ call printf ("\tNew standard deviation of background: %g counts\n")
+ call pargr (skysigma)
+ call apsetr (ap, SKYSIGMA, skysigma)
+
+ return (skysigma)
+end
+
+
+# AP_VCSTRING -- Verify the centering string.
+
+procedure ap_vcstring (ap, str, maxch)
+
+pointer ap # pointer to the apphot strucuture
+char str[ARB] # output string
+int maxch # maximum number of characters
+
+int cfunc
+int scan(), strdic(), nscan()
+
+begin
+ # Print the old centering algorithm.
+ call apstats (ap, CSTRING, str, maxch)
+ call printf ("Centering algorithm (%s) (CR or value): ")
+ call pargstr (str)
+ call flush (STDOUT)
+
+ # Confirm the centering algorithm.
+ if (scan() != EOF) {
+ call gargwrd (str, maxch)
+ cfunc = strdic (str, str, maxch, CFUNCS)
+ if (nscan () == 1 && cfunc > 0) {
+ call apseti (ap, CENTERFUNCTION, cfunc)
+ call apsets (ap, CSTRING, str)
+ }
+ }
+
+ # Print the new result.
+ call apstats (ap, CSTRING, str, maxch)
+ call printf ("\tNew centering algorithm: %s\n")
+ call pargstr (str)
+end
+
+
+# AP_VCAPERT -- Verify the centering aperture.
+
+real procedure ap_vcapert (ap)
+
+pointer ap # pointert to the apphot strucuture
+
+real scale, capert
+int scan(), nscan()
+real apstatr()
+
+begin
+ # Get the apphot scale factor.
+ scale = apstatr (ap, SCALE)
+
+ # Print the old centering value.
+ call printf ("Centering box width in scale units (%g) (CR or value): ")
+ call pargr (2.0 * apstatr (ap, CAPERT))
+ call flush (STDOUT)
+
+ # Get the new centering value.
+ if (scan() == EOF)
+ capert = 2.0 * apstatr (ap, CAPERT)
+ else {
+ call gargr (capert)
+ if (nscan () != 1)
+ capert = 2.0 * apstatr (ap, CAPERT)
+ }
+
+ # Type the new value.
+ call apsetr (ap, CAPERT, capert / 2.0)
+ call printf ("\tNew centering box width: %g scale units %g pixels\n")
+ call pargr (capert)
+ call pargr (scale * capert)
+
+ return (capert / 2.0)
+end
+
+
+# AP_VCTHRESHOLD -- Verify the centering threshold parameter.
+
+real procedure ap_vcthreshold (ap)
+
+pointer ap # pointer to the apphot structure
+
+real skysigma, cthreshold
+int scan(), nscan()
+real apstatr()
+
+begin
+ # Get the sky sigma.
+ skysigma = apstatr (ap, SKYSIGMA)
+
+ # Print the old centering threshold.
+ call printf (
+ "Centering threshold in sigma above data minimum (%g) (CR or value): ")
+ call pargr (apstatr (ap, CTHRESHOLD))
+ call flush (STDOUT)
+
+ # Confirm the centering threshold parameter.
+ if (scan() == EOF)
+ cthreshold = apstatr (ap, CTHRESHOLD)
+ else {
+ call gargr (cthreshold)
+ if (nscan () != 1)
+ cthreshold = apstatr (ap, CTHRESHOLD)
+ }
+
+ # Print the new centering threshold.
+ call apsetr (ap, CTHRESHOLD, cthreshold)
+ call printf ("\tNew centering threshold: %g skysigma %g counts\n")
+ call pargr (cthreshold)
+ if (IS_INDEFR(skysigma))
+ call pargr (INDEFR)
+ else
+ call pargr (cthreshold * skysigma)
+
+ return (cthreshold)
+end
+
+
+# AP_VRCLEAN -- Verify the cleaning radius
+
+real procedure ap_vrclean (ap)
+
+pointer ap # pointer to the apphot structure
+
+real scale, rclean
+int scan(), nscan()
+real apstatr()
+
+begin
+ # Confirm the cleaning radius.
+ scale = apstatr (ap, SCALE)
+ call printf ("Cleaning radius in scale units (%g) (CR or value): ")
+ call pargr (apstatr (ap, RCLEAN))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ rclean = apstatr (ap, RCLEAN)
+ else {
+ call gargr (rclean)
+ if (nscan () != 1)
+ rclean = apstatr (ap, RCLEAN)
+ }
+
+ call apsetr (ap, RCLEAN, rclean)
+ call printf ("\tNew cleaning radius: %g scale units %g pixels\n")
+ call pargr (rclean)
+ call pargr (scale * rclean)
+
+ return (rclean)
+end
+
+
+# AP_VRCLIP -- Verify the clipping radius.
+
+real procedure ap_vrclip (ap)
+
+pointer ap # pointer to the apphot structure
+
+real scale, rclip
+int scan(), nscan()
+real apstatr()
+
+begin
+ # Confirm the clipping radius.
+ scale = apstatr (ap, SCALE)
+ call printf ("Clipping radius in scale units (%g) (CR or value): ")
+ call pargr (apstatr (ap, RCLIP))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ rclip = apstatr (ap, RCLIP)
+ else {
+ call gargr (rclip)
+ if (nscan () != 1)
+ rclip = apstatr (ap, RCLIP)
+ }
+
+ call apsetr (ap, RCLIP, rclip)
+ call printf ("\tNew FWHM clipping radius: %g scale units %g pixels\n")
+ call pargr (rclip)
+ call pargr (scale * rclip)
+
+ return (rclip)
+end
+
+
+# AP_VSSTRING -- Verify the sky fitting algorithm string.
+
+procedure ap_vsstring (ap, str, maxch)
+
+pointer ap # pointer to the apphot structure
+char str[ARB] # output string
+int maxch # maximum number of characteristics
+
+int sfunc
+int scan(), nscan(), strdic()
+
+begin
+ # Print the old salgorithm string.
+ call apstats (ap, SSTRING, str, maxch)
+ call printf ("Sky fitting algorithm (%s) (CR or value): ")
+ call pargstr (str)
+ call flush (STDOUT)
+
+ # Confirm the sky fitting algorithm.
+ if (scan() != EOF) {
+ call gargwrd (str, maxch)
+ sfunc = strdic (str, str, maxch, SFUNCS)
+ if (nscan () == 1 && sfunc > 0) {
+ call apseti (ap, SKYFUNCTION, sfunc)
+ call apsets (ap, SSTRING, str)
+ }
+ }
+
+ # Print the new salgorithm string.
+ call apstats (ap, SSTRING, str, maxch)
+ call printf ("\tSky fitting algorithm: %s\n")
+ call pargstr (str)
+end
+
+
+# AP_VANNULUS -- Verify the inner radius of sky annulus.
+
+real procedure ap_vannulus (ap)
+
+pointer ap # pointer to the apphot structure
+
+real scale, annulus
+int scan(), nscan()
+real apstatr()
+
+begin
+ scale = apstatr (ap, SCALE)
+
+ # Print the old inner sky radius value.
+ call printf (
+ "Inner radius of sky annulus in scale units (%g) (CR or value): ")
+ call pargr (apstatr (ap, ANNULUS))
+ call flush (STDOUT)
+
+ # Verify the new value.
+ if (scan () == EOF)
+ annulus = apstatr (ap, ANNULUS)
+ else {
+ call gargr (annulus)
+ if (nscan () != 1)
+ annulus = apstatr (ap, ANNULUS)
+ }
+
+ # Print the old inner sky radius value.
+ call apsetr (ap, ANNULUS, annulus)
+ call printf (
+ "\tNew inner radius of sky annulus: %g scale units %g pixels\n")
+ call pargr (annulus)
+ call pargr (scale * annulus)
+
+ return (annulus)
+end
+
+
+# AP_VDANNULUS -- Verify the width of the sky annulus.
+
+real procedure ap_vdannulus (ap)
+
+pointer ap # pointer to the apphot structure
+
+real scale, dannulus
+int scan(), nscan()
+real apstatr()
+
+begin
+ scale = apstatr (ap, SCALE)
+
+ # Print the old sky annulus width.
+ call printf (
+ "Width of the sky annulus in scale units (%g) (CR or value): ")
+ call pargr (apstatr (ap, DANNULUS))
+ call flush (STDOUT)
+
+ # Confirm the width of the sky annulus.
+ if (scan() == EOF)
+ dannulus = apstatr (ap, DANNULUS)
+ else {
+ call gargr (dannulus)
+ if (nscan () != 1)
+ dannulus = apstatr (ap, DANNULUS)
+ }
+
+ # Print the new sky annulus width.
+ call apsetr (ap, DANNULUS, dannulus)
+ call printf (
+ "\tNew width of the sky annulus: %g scale units %g pixels\n")
+ call pargr (dannulus)
+ call pargr (scale * dannulus)
+
+ return (dannulus)
+end
+
+
+# AP_VRGROW -- Verify the region growing radius
+
+real procedure ap_vrgrow (ap)
+
+pointer ap # pointer to the apphot structure
+
+real scale, rgrow
+int scan(), nscan()
+real apstatr()
+
+begin
+ scale = apstatr (ap, SCALE)
+
+ # Print the old region growing radius.
+ call printf (
+ "Region growing radius in scale units (%g) (CR or value): ")
+ call pargr (apstatr (ap, RGROW))
+ call flush (STDOUT)
+
+ # Confirm the region growing radius.
+ if (scan() == EOF)
+ rgrow = apstatr (ap, RGROW)
+ else {
+ call gargr (rgrow)
+ if (nscan () != 1)
+ rgrow = apstatr (ap, RGROW)
+ }
+
+ # Print the region growing radius.
+ call apsetr (ap, RGROW, rgrow)
+ call printf (
+ "\tNew region growing radius: %g scale units %g pixels\n")
+ call pargr (rgrow)
+ call pargr (scale * rgrow)
+
+ return (rgrow)
+end
+
+
+# AP_VAPERTS -- Verify the photometric apertures.
+
+procedure ap_vaperts (ap, str, maxch)
+
+pointer ap # pointer to the apphot structure
+char str[ARB] # output string
+int maxch # maximum number of characters
+
+int i, naperts
+pointer sp, aperts
+real scale
+int scan(), nscan(), ap_getaperts()
+real apstatr()
+
+begin
+ call smark (sp)
+ call salloc (aperts, MAX_NAPERTS, TY_REAL)
+
+ scale = apstatr (ap, SCALE)
+
+ # Print the old aperture string.
+ call apstats (ap, APERTS, str, maxch)
+ call printf (
+ "File/list of aperture radii in scale units (%s) (CR or value): ")
+ call pargstr (str)
+ call flush (STDOUT)
+
+ # Get the new apertures.
+ if (scan() == EOF)
+ call apstats (ap, APERTS, str, maxch)
+ else {
+ call gargwrd (str, maxch)
+ if (nscan () != 1)
+ call apstats (ap, APERTS, str, maxch)
+ }
+
+ # Print the new apertures.
+ naperts = ap_getaperts (str, Memr[aperts], MAX_NAPERTS)
+ do i = 1, naperts {
+ call printf ("\tAperture radius %d: %g scale units %g pixels\n")
+ call pargi (i)
+ call pargr (Memr[aperts+i-1])
+ call pargr (scale * Memr[aperts+i-1])
+ }
+
+ call apsets (ap, APERTS, str)
+ call sfree (sp)
+end
+
+
+# AP_VPWSTRING -- Verify the weighting string.
+
+procedure ap_vpwstring (ap, str, maxch)
+
+pointer ap # pointer to the apphot structure
+char str[ARB] # output string
+int maxch # maximum number of characters
+
+int wfunc
+int scan(), nscan(), strdic()
+
+begin
+ # Print the old string.
+ call apstats (ap, PWSTRING, str, maxch)
+ call printf ("Weighting algorithm (%s) (CR or value): ")
+ call pargstr (str)
+ call flush (STDOUT)
+
+ # Get the new value.
+ if (scan() != EOF) {
+ call gargwrd (str, maxch)
+ wfunc = strdic (str, str, maxch, PWFUNCS)
+ if (nscan () == 1 && wfunc > 0) {
+ call apseti (ap, PWEIGHTS, wfunc)
+ call apsets (ap, PWSTRING, str)
+ }
+ }
+
+ # Print the new value.
+ call apstats (ap, PWSTRING, str, maxch)
+ call printf ("\tNew weighting algorithm: %s\n")
+ call pargstr (str)
+
+ call apsets (ap, PWSTRING, str)
+end
diff --git a/noao/digiphot/apphot/aplib/apverify2.x b/noao/digiphot/apphot/aplib/apverify2.x
new file mode 100644
index 00000000..b5f02f46
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apverify2.x
@@ -0,0 +1,188 @@
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/find.h"
+include "../lib/fitpsf.h"
+include "../lib/radprof.h"
+
+
+# AP_VTHRESHOLD -- Verify the full detection threshold.
+
+real procedure ap_vthreshold (ap)
+
+pointer ap # pointer to the apphot structure
+
+real skysigma, threshold
+int scan(), nscan()
+real apstatr()
+
+begin
+ skysigma = apstatr (ap, SKYSIGMA)
+
+ # Confirm the threshold parameter.
+ call printf (
+ "Detection threshold in sigma (%g) (CR or value): ")
+ call pargr (apstatr (ap, THRESHOLD))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ threshold = apstatr (ap, THRESHOLD)
+ else {
+ call gargr (threshold)
+ if (nscan () != 1)
+ threshold = apstatr (ap, THRESHOLD)
+ }
+
+ call printf ("\tNew detection threshold: %g sigma %g counts\n")
+ call pargr (threshold)
+ call apsetr (ap, THRESHOLD, threshold)
+ if (IS_INDEFR(skysigma))
+ call pargr (INDEFR)
+ else
+ call pargr (threshold * skysigma)
+
+ return (threshold)
+end
+
+# AP_VPFSTRING -- Verify the psf fitting function.
+
+procedure ap_vpfstring (ap, str, maxch)
+
+pointer ap # pointer to the apphot structure
+char str[ARB] # output string
+int maxch # maximum number of characters
+
+int pfunc
+int scan(), nscan(), strdic()
+
+begin
+ # Print the old string value.
+ call apstats (ap, PSFSTRING, str, maxch)
+ call printf ("Fitting function (%s) (CR or value): ")
+ call pargstr (str)
+ call flush (STDOUT)
+
+ # Get the new value.
+ if (scan() != EOF) {
+ call gargwrd (str, maxch)
+ pfunc = strdic (str, str, maxch, PSFFUNCS)
+ if (nscan () == 1 && pfunc > 0) {
+ call apseti (ap, PSFUNCTION, pfunc)
+ call apsets (ap, PSFSTRING, str)
+ }
+ }
+
+ # Print the new value.
+ call apstats (ap, PSFSTRING, str, SZ_LINE)
+ call printf ("\tNew fitting function: %s\n")
+ call pargstr (str)
+end
+
+
+# AP_VPSFAPERT -- Verify the point spread function fitting aperture.
+
+real procedure ap_vpsfapert (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+real scale, psfapert
+int scan(), nscan()
+real apstatr()
+
+begin
+ scale = apstatr (ap, SCALE)
+
+ # Print the old value.
+ call printf ("Fitting box width in scale units (%g) (CR or value): ")
+ call pargr (2.0 * apstatr (ap, PSFAPERT))
+ call flush (STDOUT)
+
+ # Get the new value.
+ if (scan() == EOF)
+ psfapert = 2.0 * apstatr (ap, PSFAPERT)
+ else {
+ call gargr (psfapert)
+ if (nscan () != 1)
+ psfapert = 2.0 * apstatr (ap, PSFAPERT)
+ }
+
+ # Print the new value.
+ call printf ("\tNew fitting box width: %g scale units %g pixels\n")
+ call pargr (psfapert)
+ call pargr (scale * psfapert)
+ call apsetr (ap, PSFAPERT, psfapert / 2.0)
+
+ return (psfapert / 2.0)
+end
+
+
+# AP_VRPRADIUS -- Verify the radial profile fitting radius.
+
+real procedure ap_vrpradius (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+real scale, radius
+int scan(), nscan()
+real apstatr()
+
+begin
+ scale = apstatr (ap, SCALE)
+
+ # Print the old value.
+ call printf ("Fitting radius in scale units (%g) (CR or value): ")
+ call pargr (apstatr (ap, RPRADIUS))
+ call flush (STDOUT)
+
+ # Get the new value.
+ if (scan() == EOF)
+ radius = apstatr (ap, RPRADIUS)
+ else {
+ call gargr (radius)
+ if (nscan () != 1)
+ radius = apstatr (ap, RPRADIUS)
+ }
+
+ # Print the new value.
+ call printf ("\tNew fitting radius: %g scale units %g pixels\n")
+ call pargr (radius)
+ call pargr (scale * radius)
+ call apsetr (ap, RPRADIUS, radius)
+
+ return (radius)
+end
+
+
+# AP_VSTEP -- Verify the profile step size.
+
+real procedure ap_vstep (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+real scale, step
+int scan(), nscan()
+real apstatr()
+
+begin
+ scale = apstatr (ap, SCALE)
+
+ # Print the old value.
+ call printf ("Step size in scale units (%g) (CR or value): ")
+ call pargr (apstatr (ap, RPSTEP))
+ call flush (STDOUT)
+
+ # Get the new value.
+ if (scan() == EOF)
+ step = apstatr (ap, RPSTEP)
+ else {
+ call gargr (step)
+ if (nscan () != 1)
+ step = apstatr (ap, RPSTEP)
+ }
+
+ # Print the new value.
+ call printf ("\tNew step size: %g scale units %g pixels\n")
+ call pargr (step)
+ call pargr (scale * step)
+ call apsetr (ap, RPSTEP, step)
+
+ return (step)
+end
diff --git a/noao/digiphot/apphot/aplib/apwcs.x b/noao/digiphot/apphot/aplib/apwcs.x
new file mode 100644
index 00000000..21ff7831
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apwcs.x
@@ -0,0 +1,117 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imio.h>
+include "../lib/apphot.h"
+
+# AP_ITOL -- Convert coordinates from the input coordinate system to the
+# logical coordinate system.
+
+procedure ap_itol (ap, xin, yin, xout, yout, npts)
+
+pointer ap # the apphot package descriptor
+real xin[ARB] # the input x coordinate
+real yin[ARB] # the input y coordinate
+real xout[ARB] # the output x coordinate
+real yout[ARB] # the output y coordinate
+int npts # the number of coordinates to convert
+
+double xt, yt
+pointer ct
+int i
+int apstati()
+
+begin
+ ct = apstati (ap, CTIN)
+ if (ct == NULL) {
+ call amovr (xin, xout, npts)
+ call amovr (yin, yout, npts)
+ return
+ }
+
+ do i = 1, npts {
+ call mw_c2trand (ct, double (xin[i]), double (yin[i]), xt, yt)
+ xout[i] = xt
+ yout[i] = yt
+ }
+end
+
+
+# AP_LTOO -- Convert coordinates from the logical coordinate system to the
+# output coordinate system.
+
+procedure ap_ltoo (ap, xin, yin, xout, yout, npts)
+
+pointer ap # the apphot package descriptor
+real xin[ARB] # the input x coordinate
+real yin[ARB] # the input y coordinate
+real xout[ARB] # the output x coordinate
+real yout[ARB] # the output y coordinate
+int npts # the number of coordinates to convert
+
+double xt, yt
+pointer ct
+int i
+int apstati()
+
+begin
+ ct = apstati (ap, CTOUT)
+ if (ct == NULL) {
+ call amovr (xin, xout, npts)
+ call amovr (yin, yout, npts)
+ return
+ }
+
+ do i = 1, npts {
+ call mw_c2trand (ct, double (xin[i]), double (yin[i]), xt, yt)
+ xout[i] = xt
+ yout[i] = yt
+ }
+end
+
+
+# AP_LTOV -- Convert coordinate from the logical coordinate system to the
+# output coordinate system.
+
+procedure ap_ltov (im, xin, yin, xout, yout, npts)
+
+pointer im # the input image descriptor
+real xin[ARB] # the input x coordinate
+real yin[ARB] # the input y coordinate
+real xout[ARB] # the output x coordinate
+real yout[ARB] # the output y coordinate
+int npts # the number of coordinates to convert
+
+int i, index1, index2
+
+begin
+ index1 = IM_VMAP(im,1)
+ index2 = IM_VMAP(im,2)
+ do i = 1, npts {
+ xout[i] = xin[i] * IM_VSTEP(im,index1) + IM_VOFF(im,index1)
+ yout[i] = yin[i] * IM_VSTEP(im,index2) + IM_VOFF(im,index2)
+ }
+end
+
+
+# AP_VTOL -- Convert coordinate from the tv coordinate system to the
+# logical coordinate system.
+
+procedure ap_vtol (im, xin, yin, xout, yout, npts)
+
+pointer im # the input image descriptor
+real xin[ARB] # the input x coordinate
+real yin[ARB] # the input y coordinate
+real xout[ARB] # the output x coordinate
+real yout[ARB] # the output y coordinate
+int npts # the number of coordinates to convert
+
+int i, index1, index2
+
+begin
+ index1 = IM_VMAP(im,1)
+ index2 = IM_VMAP(im,2)
+ do i = 1, npts {
+ xout[i] = (xin[i] - IM_VOFF(im,index1)) / IM_VSTEP(im,index1)
+ yout[i] = (yin[i] - IM_VOFF(im,index2)) / IM_VSTEP(im,index2)
+ }
+end
diff --git a/noao/digiphot/apphot/aplib/apwparam1.x b/noao/digiphot/apphot/aplib/apwparam1.x
new file mode 100644
index 00000000..54086aeb
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apwparam1.x
@@ -0,0 +1,415 @@
+include <time.h>
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+
+# AP_PARAM -- Procedure to write the apphot parameters to a text file.
+
+procedure ap_param (ap, out, task)
+
+pointer ap # pointer to the apphot structure
+int out # output file descriptor
+char task[ARB] # task name
+
+int nchars
+pointer sp, outstr, date, time
+bool itob()
+int strmatch(), envfind(), gstrcpy(), apstati()
+real apstatr()
+
+begin
+ if (out == NULL)
+ return
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+ call salloc (date, SZ_DATE, TY_CHAR)
+ call salloc (time, SZ_DATE, TY_CHAR)
+
+ # Write the id.
+
+ nchars = envfind ("version", Memc[outstr], SZ_LINE)
+ if (nchars <= 0)
+ nchars = gstrcpy ("NOAO/IRAF", Memc[outstr], SZ_LINE)
+ call ap_rmwhite (Memc[outstr], Memc[outstr], SZ_LINE)
+ call ap_sparam (out, "IRAF", Memc[outstr], "version",
+ "current version of IRAF")
+
+ nchars = envfind ("userid", Memc[outstr], SZ_LINE)
+ call ap_sparam (out, "USER", Memc[outstr], "name", "user id")
+
+ call gethost (Memc[outstr], SZ_LINE)
+ call ap_sparam (out, "HOST", Memc[outstr], "computer",
+ "IRAF host machine")
+
+ call apdate (Memc[date], Memc[time], SZ_DATE)
+ call ap_sparam (out, "DATE", Memc[date], "yyyy-mm-dd", "date")
+ call ap_sparam (out, "TIME", Memc[time], "hh:mm:ss", "time")
+
+ call ap_sparam (out, "PACKAGE", "apphot", "name",
+ "name of IRAF package")
+ call ap_sparam (out, "TASK", task, "name", "name of apphot task")
+ call fprintf (out, "#\n")
+
+ # Write out the apphot parameters.
+ call ap_rparam (out, KY_SCALE, 1.0 / apstatr (ap, SCALE), UN_AUNITS,
+ "scale in units per pixel")
+ call ap_rparam (out, KY_FWHMPSF, apstatr (ap, FWHMPSF), UN_ASCALEUNIT,
+ "full width half maximum of the psf")
+ call ap_bparam (out, KY_POSITIVE, itob (apstati (ap, POSITIVE)),
+ UN_ASWITCH, "positive feature")
+ call ap_rparam (out, KY_DATAMIN, apstatr (ap, DATAMIN), UN_ACOUNTS,
+ "minimum good data value")
+ call ap_rparam (out, KY_DATAMAX, apstatr (ap, DATAMAX), UN_ACOUNTS,
+ "maximum good data value")
+
+ # Write out the image header keyword parameters.
+ call apstats (ap, EXPOSURE, Memc[outstr], SZ_FNAME)
+ if (Memc[outstr] == EOS)
+ call strcpy ("\"\"", Memc[outstr], SZ_FNAME)
+ call ap_sparam (out, KY_EXPOSURE, Memc[outstr], UN_AKEYWORD,
+ "exposure time keyword")
+ call apstats (ap, AIRMASS, Memc[outstr], SZ_FNAME)
+ if (Memc[outstr] == EOS)
+ call strcpy ("\"\"", Memc[outstr], SZ_FNAME)
+ call ap_sparam (out, KY_AIRMASS, Memc[outstr], UN_AKEYWORD,
+ "airmass keyword")
+ call apstats (ap, FILTER, Memc[outstr], SZ_FNAME)
+ if (Memc[outstr] == EOS)
+ call strcpy ("\"\"", Memc[outstr], SZ_FNAME)
+ call ap_sparam (out, KY_FILTER, Memc[outstr], UN_AKEYWORD,
+ "filter keyword")
+ call apstats (ap, OBSTIME, Memc[outstr], SZ_FNAME)
+ if (Memc[outstr] == EOS)
+ call strcpy ("\"\"", Memc[outstr], SZ_FNAME)
+ call ap_sparam (out, KY_OBSTIME, Memc[outstr], UN_AKEYWORD,
+ "obstime keyword")
+ call fprintf (out, "#\n")
+
+ # Write the noise model parameters.
+ call ap_wnse (ap, out)
+
+ # Write the centering parameters.
+ call ap_wctrs (ap, out)
+
+ # Write sky fitting parameters.
+ call ap_wskys (ap, out)
+
+ # Write the phot parameters.
+ call ap_wwphot (ap, out)
+
+ # Write the polyphot parameters.
+ call ap_wpoly (ap, out)
+
+ # Write the radial profile parameters.
+ call ap_wprofs (ap, out)
+
+ # Write the psf fitting parameters.
+ call ap_wpsf (ap, out)
+
+ # Write the header banner
+ if (strmatch ("^center", task) > 0)
+ call ap_cphdr (ap, out)
+ else if (strmatch ("^fitsky", task) > 0)
+ call ap_sphdr (ap, out)
+ else if (strmatch ("^phot", task) > 0)
+ call ap_maghdr (ap, out)
+ else if (strmatch ("^qphot", task) > 0)
+ call ap_maghdr (ap, out)
+ else if (strmatch ("^wphot", task) > 0)
+ call ap_maghdr (ap, out)
+ else if (strmatch ("^polyphot", task) > 0)
+ call ap_yhdr (ap, out)
+ else if (strmatch ("^fitpsf", task) > 0)
+ call ap_pfhdr (ap, out)
+ else if (strmatch ("^radprof", task) > 0)
+ call ap_rphdr (ap, out)
+ #else if (strmatch ("^daofind", task) > 0)
+ #call ap_fdhdr (ap, out)
+
+ call sfree (sp)
+end
+
+
+# AP_WCTRS -- Procedure to write out the centering parameters.
+
+procedure ap_wctrs (ap, out)
+
+pointer ap # apphot pointer
+int out # output file descriptor
+
+pointer sp, str
+bool itob()
+int apstati()
+real apstatr()
+
+begin
+ if (out == NULL)
+ return
+
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ if (AP_PCENTER(ap) != NULL) {
+ call apstats (ap, CSTRING, Memc[str], SZ_FNAME)
+ call ap_sparam (out, KY_CSTRING, Memc[str], UN_CALGORITHM,
+ "centering algorithm")
+ call ap_rparam (out, KY_CAPERT, 2.0* apstatr (ap, CAPERT),
+ UN_CSCALEUNIT, "centering box width")
+ call ap_rparam (out, KY_CTHRESHOLD, apstatr (ap, CTHRESHOLD),
+ UN_CSIGMA, "threshold for centering")
+ call ap_rparam (out, KY_MINSNRATIO, apstatr (ap, MINSNRATIO),
+ UN_CNUMBER, "minimum signal to noise ratio")
+ call ap_iparam (out, KY_CMAXITER, apstati (ap, CMAXITER),
+ UN_CNUMBER, "maximum number of iterations")
+ call ap_rparam (out, KY_MAXSHIFT, apstatr (ap, MAXSHIFT),
+ UN_CSCALEUNIT, "maximum shift")
+ call ap_bparam (out, KY_CLEAN, itob (apstati (ap, CLEAN)),
+ UN_CSWITCH, "apply clean algorithm before centering")
+ call ap_rparam (out, KY_RCLEAN, apstatr (ap, RCLEAN),
+ UN_CSCALEUNIT, "cleaning radius")
+ call ap_rparam (out, KY_RCLIP, apstatr (ap, RCLIP), UN_CSCALEUNIT,
+ "clipping radius")
+ call ap_rparam (out, KY_SIGMACLEAN, apstatr (ap, SIGMACLEAN),
+ UN_CSIGMA, "k-sigma clean rejection criterion")
+ call fprintf (out, "#\n")
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_WSKYS -- Procedure to write out the sky fitting parameters.
+
+procedure ap_wskys (ap, out)
+
+pointer ap # apphot structure
+int out # output pointer
+
+pointer sp, str
+bool itob()
+int apstati()
+real apstatr()
+
+begin
+ if (out == NULL)
+ return
+
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ if (AP_PSKY(ap) != NULL) {
+ call apstats (ap, SSTRING, Memc[str], SZ_FNAME)
+ call ap_sparam (out, KY_SSTRING, Memc[str], UN_SALGORITHM,
+ " sky fitting algorithm")
+ call ap_rparam (out, KY_ANNULUS, apstatr (ap, ANNULUS),
+ UN_SSCALEUNIT, "inner radius of sky annulus")
+ call ap_rparam (out, KY_DANNULUS, apstatr (ap, DANNULUS),
+ UN_SSCALEUNIT, "width of the sky annulus")
+ call ap_rparam (out, KY_SKY_BACKGROUND, apstatr (ap,
+ SKY_BACKGROUND), UN_SCOUNTS, "user supplied sky value")
+ call ap_rparam (out, KY_K1, apstatr (ap, K1), UN_SSIGMA,
+ "half width of sky histogram")
+ call ap_rparam (out, KY_BINSIZE, apstatr (ap, BINSIZE),
+ UN_SSIGMA, "width of sky histogram bin")
+ call ap_bparam (out, KY_SMOOTH, itob (apstati (ap, SMOOTH)),
+ UN_SSWITCH, "Lucy smooth the histogram")
+ call ap_iparam (out, KY_SMAXITER, apstati (ap, SMAXITER),
+ UN_SNUMBER, "maximum number of iterations")
+ call ap_rparam (out, KY_SLOCLIP, apstatr (ap, SLOCLIP),
+ UN_SPERCENT, "lower clipping limit")
+ call ap_rparam (out, KY_SHICLIP, apstatr (ap, SHICLIP),
+ UN_SPERCENT, "upper clipping limit")
+ call ap_iparam (out, KY_SNREJECT, apstati (ap, SNREJECT),
+ UN_SNUMBER, "maximum number of rejection cycles")
+ call ap_rparam (out, KY_SLOREJECT, apstatr (ap, SLOREJECT),
+ UN_SSIGMA, "lower k-sigma rejection criterion")
+ call ap_rparam (out, KY_SHIREJECT, apstatr (ap, SHIREJECT),
+ UN_SSIGMA, "upper k-sigma rejection criterion")
+ call ap_rparam (out, KY_RGROW, apstatr (ap, RGROW), UN_SSCALEUNIT,
+ "region growing radius")
+ call fprintf (out, "#\n")
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_WNSE -- Porcedure to compute the noise model parameters.
+
+procedure ap_wnse (ap, out)
+
+pointer ap # apphot pointer
+int out # output file descriptor
+
+pointer sp, str
+real apstatr()
+
+begin
+ if (out == NULL)
+ return
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ if (AP_NOISE(ap) != NULL) {
+ call apstats (ap, NSTRING, Memc[str], SZ_FNAME)
+ call ap_sparam (out, KY_NSTRING, Memc[str], UN_NMODEL,
+ "noise model")
+ call ap_rparam (out, KY_SKYSIGMA, apstatr (ap, SKYSIGMA),
+ UN_NCOUNTS, "standard deviation of 1 sky pixel")
+ call apstats (ap, GAIN, Memc[str], SZ_FNAME)
+ if (Memc[str] == EOS)
+ call strcpy ("\"\"", Memc[str], SZ_FNAME)
+ call ap_sparam (out, KY_GAIN, Memc[str], UN_NKEYWORD,
+ "gain keyword")
+ call ap_rparam (out, KY_EPADU, apstatr (ap, EPADU), UN_NEPADU,
+ "electrons per adu")
+ call apstats (ap, CCDREAD, Memc[str], SZ_FNAME)
+ if (Memc[str] == EOS)
+ call strcpy ("\"\"", Memc[str], SZ_FNAME)
+ call ap_sparam (out, KY_CCDREAD, Memc[str], UN_NKEYWORD,
+ "read noise keyword")
+ call ap_rparam (out, KY_READNOISE, apstatr (ap, READNOISE),
+ UN_NELECTRONS, "electrons")
+ call fprintf (out, "#\n")
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_WWPHOT -- Procedure to write out the photometry parameters.
+
+procedure ap_wwphot (ap, out)
+
+pointer ap # apphot structure pointer
+int out # output file descriptor
+
+pointer sp, str
+real apstatr()
+
+begin
+ if (out == NULL)
+ return
+
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ if (AP_PPHOT(ap) != NULL) {
+ call apstats (ap, PWSTRING, Memc[str], SZ_LINE)
+ call ap_sparam (out, KY_PWSTRING, Memc[str], UN_PMODEL,
+ "photometric weighting scheme")
+ call apstats (ap, APERTS, Memc[str], SZ_LINE)
+ call ap_sparam (out, KY_APERTS, Memc[str], UN_PSCALEUNIT,
+ "list of apertures")
+ call ap_rparam (out, KY_ZMAG, apstatr (ap, ZMAG), UN_PZMAG,
+ "zero point of magnitdue scale")
+ call fprintf (out, "#\n")
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_RPARAM -- Procedure to encode a real apphot parameter.
+
+procedure ap_rparam (out, keyword, value, units, comments)
+
+int out # output file descriptor
+char keyword[ARB] # keyword string
+real value # parameter value
+char units[ARB] # units string
+char comments[ARB] # comment string
+
+begin
+ if (out == NULL)
+ return
+
+ call strupr (keyword)
+ call fprintf (out,
+ "#K%4t%-10.10s%14t = %17t%-23.7g%41t%-10.10s%52t%-10s\n")
+ call pargstr (keyword)
+ call pargr (value)
+ call pargstr (units)
+ call pargstr ("%-23.7g")
+ call pargstr (comments)
+end
+
+
+# AP_IPARAM -- Procedure to encode an apphot integer parameter.
+
+procedure ap_iparam (out, keyword, value, units, comments)
+
+int out # output file descriptor
+char keyword[ARB] # keyword string
+int value # parameter value
+char units[ARB] # units string
+char comments[ARB] # comment string
+
+begin
+ if (out == NULL)
+ return
+
+ call strupr (keyword)
+ call fprintf (out,
+ "#K%4t%-10.10s%14t = %17t%-23d%41t%-10.10s%52t%-10s\n")
+ call pargstr (keyword)
+ call pargi (value)
+ call pargstr (units)
+ call pargstr ("%-23d")
+ call pargstr (comments)
+end
+
+
+# AP_BPARAM -- Procedure to encode an apphot boolean parameter.
+
+procedure ap_bparam (out, keyword, value, units, comments)
+
+int out # output file descriptor
+char keyword[ARB] # keyword string
+bool value # parameter value
+char units[ARB] # units string
+char comments[ARB] # comment string
+
+begin
+ if (out == NULL)
+ return
+
+ call strupr (keyword)
+ call fprintf (out,
+ "#K%4t%-10.10s%14t = %17t%-23b%41t%-10.10s%52t%-10s\n")
+ call pargstr (keyword)
+ call pargb (value)
+ call pargstr (units)
+ call pargstr ("%-23b")
+ call pargstr (comments)
+end
+
+
+# AP_SPARAM -- Procedure to encode an apphot string parameter.
+
+procedure ap_sparam (out, keyword, value, units, comments)
+
+int out # output file descriptor
+char keyword[ARB] # keyword string
+char value[ARB] # parameter value
+char units[ARB] # units string
+char comments[ARB] # comment string
+
+begin
+ if (out == NULL)
+ return
+
+ call strupr (keyword)
+ call fprintf (out,
+ "#K%4t%-10.10s%14t = %17t%-23.23s%41t%-10.10s%52t%-10s\n")
+ call pargstr (keyword)
+ call pargstr (value)
+ call pargstr (units)
+ call pargstr ("%-23s")
+ call pargstr (comments)
+end
diff --git a/noao/digiphot/apphot/aplib/apwparam2.x b/noao/digiphot/apphot/aplib/apwparam2.x
new file mode 100644
index 00000000..1c15f26c
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apwparam2.x
@@ -0,0 +1,104 @@
+include "../lib/apphotdef.h"
+include "../lib/polyphot.h"
+include "../lib/fitpsf.h"
+include "../lib/radprof.h"
+
+
+# AP_WPROFS -- Procedure to print out the profile fitting parameters.
+
+procedure ap_wprofs (ap, out)
+
+pointer ap # apphot structure pointer
+int out # output file descriptor
+
+pointer sp, str
+int apstati()
+real apstatr()
+
+begin
+ if (out == NULL)
+ return
+
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ if (AP_RPROF(ap) != NULL) {
+ call ap_rparam (out, KY_RPRADIUS, apstatr (ap, RPRADIUS),
+ UN_RSCALEUNIT, "fitting radius")
+ call ap_rparam (out, KY_RPSTEP, apstatr (ap, RPSTEP),
+ UN_RSCALEUNIT, "step size in radius")
+ call ap_iparam (out, KY_RPORDER, apstati (ap, RPORDER), UN_RNUMBER,
+ "number of splines pieces")
+ call ap_rparam (out, KY_RPKSIGMA, apstatr (ap, RPKSIGMA),
+ UN_RSIGMA, "k-sigma rejection criterion")
+ call ap_iparam (out, KY_RPNREJECT, apstati (ap, RPNREJECT),
+ UN_RNUMBER, "maximum number of rejection cycles")
+ call fprintf (out, "#\n")
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_WPOLY -- Procedure to write out the polyphot parameters.
+
+procedure ap_wpoly (ap, out)
+
+pointer ap # apphot structure pointer
+int out # output file descriptor
+
+pointer sp, str
+real apstatr()
+
+begin
+ if (out == NULL)
+ return
+
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ if (AP_POLY(ap) != NULL) {
+ call ap_sparam (out, "WEIGHTING", "constant", "model", "")
+ call ap_rparam (out, KY_PYZMAG, apstatr (ap, PYZMAG), UN_PYZMAG,
+ "zero point of magnitdue scale")
+ call fprintf (out, "#\n")
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_WPSF -- Procedure to write the psf fitting parameters .
+
+procedure ap_wpsf (ap, out)
+
+pointer ap # apphot strucuture pointer
+int out # output file descriptor
+
+pointer sp, str
+int apstati()
+real apstatr()
+
+begin
+ if (out == NULL)
+ return
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ if (AP_PPSF(ap) != NULL) {
+ call apstats (ap, PSFSTRING, Memc[str], SZ_FNAME)
+ call ap_sparam (out, KY_PSFUNCTION, Memc[str], UN_PSFMODEL,
+ "fitting function")
+ call ap_rparam (out, KY_PSFAPERT, 2.0 * apstatr (ap, PSFAPERT),
+ UN_PSFSCALEUNIT, "width of the fitting box")
+ call ap_iparam (out, KY_PMAXITER, apstati (ap, PMAXITER),
+ UN_PSFSCALEUNIT, "maximum number of iterations")
+ call ap_rparam (out, KY_PK2, apstatr (ap, PK2), UN_PSFSIGMA,
+ "k-sigma rejection limit for the fit")
+ call ap_iparam (out, KY_PNREJECT, apstati (ap, PNREJECT),
+ UN_PSFNUMBER, "maximum number of rejection cycles")
+ call fprintf (out, "#\n")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aplib/apwres1.x b/noao/digiphot/apphot/aplib/apwres1.x
new file mode 100644
index 00000000..3d7b490a
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apwres1.x
@@ -0,0 +1,437 @@
+include "../lib/apphot.h"
+include "../lib/find.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+
+# define the #N, #U, and #F daofind strings
+
+define FD_NSTR "#N%4tXCENTER%14tYCENTER%24tMAG%33tSHARPNESS%45t\
+SROUND%57tGROUND%69tID%80t\\\n"
+define FD_USTR "#U%4tpixels%14tpixels%24t#%33t#%45t#%57t#%69t#%80t\\\n"
+define FD_FSTR "#F%4t%%-13.3f%14t%%-10.3f%24t%%-9.3f%33t%%-12.3f%45t\
+%%-12.3f%57t%%-12.3f%69t%%-6d%80t\\\n"
+define FD_WSTR "%4t%-10.3f%-10.3f%-9.3f%-12.3f%-12.3f%-12.3f%-6d\n"
+
+# AP_WFDPARAM -- Write the daofind parameters to the output file.
+
+procedure ap_wfdparam (out, ap)
+
+int out # the output file descriptor
+pointer ap # pointer to the apphot structure
+
+pointer sp, str
+real apstatr()
+
+begin
+ if (out == NULL)
+ return
+
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Write out the parameters.
+ call ap_param (ap, out, "daofind")
+ #call apstats (ap, IMNAME, Memc[str], SZ_FNAME)
+ call apstats (ap, IMROOT, Memc[str], SZ_FNAME)
+ call ap_sparam (out, KY_IMNAME, Memc[str], "imagename", "image name")
+ call ap_rparam (out, KY_FWHMPSF, apstatr (ap, FWHMPSF), UN_ASCALEUNIT,
+ "fwhm of the psf")
+ call ap_rparam (out, KY_THRESHOLD, apstatr (ap, THRESHOLD),
+ UN_FSIGMA, "detection threshold in sigma")
+ call ap_rparam (out, KY_NSIGMA, apstatr (ap, NSIGMA), UN_FSIGMA,
+ "size of the kernel in fwhmpsf")
+ call ap_rparam (out, KY_RATIO, apstatr (ap, RATIO), UN_FNUMBER,
+ "ratio of ysigma to xsigma")
+ call ap_rparam (out, KY_THETA, apstatr (ap, THETA), UN_FDEGREES,
+ "position angle in degrees")
+ call fprintf (out, "#\n")
+ call ap_rparam (out, KY_SHARPLO, apstatr (ap, SHARPLO), UN_FNUMBER,
+ "lower sharpness bound")
+ call ap_rparam (out, KY_SHARPHI, apstatr (ap, SHARPHI), UN_FNUMBER,
+ "higher sharpness bound")
+ call ap_rparam (out, KY_ROUNDLO, apstatr (ap, ROUNDLO), UN_FNUMBER,
+ "lower roundness bound")
+ call ap_rparam (out, KY_ROUNDHI, apstatr (ap, ROUNDHI), UN_FNUMBER,
+ "higher roundness bound")
+ call fprintf (out, "#\n")
+
+ # Write out the header banner.
+ call ap_fdhdr (ap, out)
+
+ call sfree (sp)
+end
+
+
+# AP_FDHDR -- Write the daofind column banner to the output file.
+
+procedure ap_fdhdr (ap, out)
+
+pointer ap # pointer to the apphot structure (unused)
+int out # output file descriptor
+
+begin
+ if (out == NULL)
+ return
+
+ call fprintf (out, FD_NSTR)
+ call fprintf (out, FD_USTR)
+ call fprintf (out, FD_FSTR)
+ call fprintf (out, "#\n")
+end
+
+
+# APSTDOUT -- Print the daofind results on the standard output.
+
+procedure apstdout (density, ptrs, ncols, nbox, cols, x, y, sharp, round1,
+ round2, nstars, ntotal, threshold)
+
+real density[ncols,nbox] # array of densities
+int ptrs[ARB] # array of line pointers
+int ncols, nbox # dimensions of the data
+int cols[ARB] # array of column numbers
+real x[ARB] # x coordinates
+real y[ARB] # y coordinates
+real sharp[ARB] # sharpness
+real round1[ARB] # first roundness parameter
+real round2[ARB] # second roundness parameter
+int nstars # number of detected stars in the line
+int ntotal # total number of detected objects
+real threshold # threshold for detection
+
+int i, middle
+real den
+
+begin
+ middle = 1 + nbox / 2
+ do i = 1, nstars {
+ call printf (" %7.2f %7.2f %7.3f %6.3f %6.3f %6.3f %4d\n")
+ call pargr (x[i])
+ call pargr (y[i])
+ if (threshold <= 0.0)
+ den = INDEFR
+ else
+ den = -2.5 * log10 (density[cols[i],ptrs[middle]] /
+ threshold)
+ call pargr (den)
+ call pargr (sharp[i])
+ call pargr (round1[i])
+ call pargr (round2[i])
+ call pargi (ntotal + i)
+ }
+end
+
+
+# APDTFOUT -- Write the daofind results to the output file.
+
+procedure apdtfout (fd, density, ptrs, ncols, nbox, cols, x, y, sharp, round1,
+ round2, nstars, ntotal, threshold, stid)
+
+int fd # the output file descriptor
+real density[ncols, nbox] # densities
+int ptrs[ARB] # array of line pointers
+int ncols, nbox # dimensions of the data
+int cols[ARB] # column numbers
+real x[ARB] # xcoords
+real y[ARB] # y coords
+real sharp[ARB] # sharpnesses
+real round1[ARB] # first roundness
+real round2[ARB] # second roundness
+int nstars # number of detected stars in the line
+int ntotal # total number of detected objects
+real threshold # threshold for detection
+int stid # output file sequence number
+
+int i, middle
+real den
+
+begin
+ if (fd == NULL)
+ return
+
+ middle = 1 + nbox / 2
+ do i = 1, nstars {
+ call fprintf (fd, FD_WSTR)
+ call pargr (x[i])
+ call pargr (y[i])
+ if (threshold <= 0.0)
+ den = INDEFR
+ else
+ den = -2.5 * log10 (density[cols[i],ptrs[middle]] /
+ threshold)
+ call pargr (den)
+ call pargr (sharp[i])
+ call pargr (round1[i])
+ call pargr (round2[i])
+ call pargi (stid + ntotal + i - 1)
+ }
+end
+
+
+# define the #N, #U and #K id strings
+
+define ID_NSTR "#N%4tIMAGE%24tXINIT%34tYINIT%44tID%50tCOORDS%73tLID%80t\\\n"
+define ID_USTR "#U%4timagename%24tpixels%34tpixels%44t##%50tfilename%73t\
+##%80t\\\n"
+define ID_FSTR "#F%4t%%-23s%24t%%-10.3f%34t%%-10.3f%44t%%-6d%50t%%-23s%73t\
+%%-6d%80t \n"
+define ID_WSTR "%-23.23s%24t%-10.3f%34t%-10.3f%44t%-6d%50t%-23.23s%73t\
+%-6d%80t%c\n"
+
+# AP_IDHDR -- Print the id column header strings.
+
+procedure ap_idhdr (ap, fd)
+
+pointer ap # apphot descriptor (unused)
+int fd # output file descriptor
+
+begin
+ if (fd == NULL)
+ return
+ call fprintf (fd, ID_NSTR)
+ call fprintf (fd, ID_USTR)
+ call fprintf (fd, ID_FSTR)
+ call fprintf (fd, "#\n")
+end
+
+
+# AP_WID -- Write the id record to a file.
+
+procedure ap_wid (ap, fd, xpos, ypos, id, lid, lastchar)
+
+pointer ap # pointer to apphot structure
+int fd # output file descriptor
+real xpos # x position
+real ypos # y position
+int id # id of the star
+int lid # list number
+int lastchar # last character in record
+
+pointer sp, imname, clname
+
+begin
+ if (fd == NULL)
+ return
+
+ call smark (sp)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+ call salloc (clname, SZ_FNAME, TY_CHAR)
+
+ # Print description of object.
+ call apstats (ap, IMROOT, Memc[imname], SZ_FNAME)
+ call apstats (ap, CLROOT, Memc[clname], SZ_FNAME)
+ if (Memc[clname] == EOS)
+ call strcpy ("nullfile", Memc[clname], SZ_FNAME)
+ call fprintf (fd, ID_WSTR)
+ call pargstr (Memc[imname])
+ call pargr (xpos)
+ call pargr (ypos)
+ call pargi (id)
+ call pargstr (Memc[clname])
+ call pargi (lid)
+ call pargi (lastchar)
+
+ call sfree (sp)
+end
+
+
+# define the #N, #U and #K center strings
+
+define CTR_NSTR "#N%4tXCENTER%15tYCENTER%26tXSHIFT%34tYSHIFT%42tXERR%50t\
+YERR%66tCIER%71tCERROR%80t\\\n"
+define CTR_USTR "#U%4tpixels%15tpixels%26tpixels%34tpixels%42tpixels%50t\
+pixels%66t##%71tcerrors%80t\\\n"
+define CTR_FSTR "#F%4t%%-14.3f%15t%%-11.3f%26t%%-8.3f%34t%%-8.3f%42t\
+%%-8.3f%50t%%-15.3f%66t%%-5d%71t%%-9s%80t \n"
+define CTR_WSTR "%4t%-11.3f%-11.3f%-8.3f%-8.3f%-8.3f%-15.3f%-5d%-9.9s\
+%80t%c\n"
+
+
+# AP_CHDR -- Print the center algorithm column header strings.
+
+procedure ap_chdr (ap, fd)
+
+pointer ap # apphot descriptor (unused)
+int fd # output file descriptor
+
+begin
+ if (fd == NULL)
+ return
+ call fprintf (fd, CTR_NSTR)
+ call fprintf (fd, CTR_USTR)
+ call fprintf (fd, CTR_FSTR)
+ call fprintf (fd, "#\n")
+end
+
+
+# AP_WCRES -- Write out the centering algorithm results to a file.
+
+procedure ap_wcres (ap, fd, ier, lastchar)
+
+pointer ap # pointer to apphot structure
+int fd # output file descriptor
+int ier # error code
+int lastchar # last character written out
+
+pointer sp, str
+real apstatr()
+
+begin
+ if (fd == NULL)
+ return
+
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call ap_cserrors (ier, Memc[str], SZ_LINE)
+
+ # Print the computed centers.
+ call fprintf (fd, CTR_WSTR)
+ call pargr (apstatr (ap, OXCENTER))
+ call pargr (apstatr (ap, OYCENTER))
+ call pargr (apstatr (ap, OXSHIFT))
+ call pargr (apstatr (ap, OYSHIFT))
+ call pargr (apstatr (ap, XERR))
+ call pargr (apstatr (ap, YERR))
+ call pargi (ier)
+ call pargstr (Memc[str])
+ call pargi (lastchar)
+
+ call sfree (sp)
+end
+
+
+# AP_CSERRORS -- Encode the centering task error messages into a string.
+
+procedure ap_cserrors (ier, str, maxch)
+
+int ier # error code
+char str[ARB] # output str
+int maxch # maximum number of characters
+
+begin
+ switch (ier) {
+ case AP_CTR_NOAREA:
+ call strcpy ("OffImage", str, maxch)
+ case AP_CTR_OUTOFBOUNDS:
+ call strcpy ("EdgeImage", str, maxch)
+ case AP_CTR_NTOO_SMALL:
+ call strcpy ("TooFewPts", str, maxch)
+ case AP_CTR_SINGULAR:
+ call strcpy ("Singular", str, maxch)
+ case AP_CTR_NOCONVERGE:
+ call strcpy ("BadFit", str, maxch)
+ case AP_CTR_BADSHIFT:
+ call strcpy ("BigShift", str, maxch)
+ case AP_CTR_LOWSNRATIO:
+ call strcpy ("LowSnr", str, maxch)
+ case AP_CTR_BADDATA:
+ call strcpy ("BadPixels", str, maxch)
+ default:
+ call strcpy ("NoError", str, maxch)
+ }
+end
+
+
+# define the #N, #U and #K fitsky strings
+
+define SKY_NSTR "#N%4tMSKY%19tSTDEV%34tSSKEW%49tNSKY%56tNSREJ%66tSIER\
+%71tSERROR%80t\\\n"
+define SKY_USTR "#U%4tcounts%19tcounts%34tcounts%49tnpix%56tnpix%66t##\
+%71tserrors%80t\\\n"
+define SKY_FSTR "#F%4t%%-18.7g%19t%%-15.7g%34t%%-15.7g%49t%%-7d%56t\
+%%-9d%66t%%-5d%71t%%-9s%80t \n"
+define SKY_WSTR "%4t%-15.7g%-15.7g%-15.7g%-7d%-9d%-5d%-9.9s%80t%c\n"
+
+# AP_SHDR -- Print the sky fitting column header strings.
+
+procedure ap_shdr (ap, fd)
+
+pointer ap # apphot descriptor (unused)
+int fd # output file descriptor
+
+begin
+ if (fd == NULL)
+ return
+
+ call fprintf (fd, SKY_NSTR)
+ call fprintf (fd, SKY_USTR)
+ call fprintf (fd, SKY_FSTR)
+ call fprintf (fd, "#\n")
+end
+
+
+# AP_WSRES -- Write the results of the sky fitting algorithms to the output
+# file.
+
+procedure ap_wsres (ap, fd, ier, lastchar)
+
+pointer ap # pointer to apphot structure
+int fd # output file descriptor
+int ier # error code
+int lastchar # last character
+
+int apstati()
+real apstatr()
+
+pointer sp, str
+
+begin
+ if (fd == NULL)
+ return
+
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call ap_sserrors (ier, Memc[str], SZ_LINE)
+
+ # Print the computed sky value and statistics.
+ call fprintf (fd, SKY_WSTR)
+ call pargr (apstatr (ap, SKY_MODE))
+ call pargr (apstatr (ap, SKY_SIGMA))
+ call pargr (apstatr (ap, SKY_SKEW))
+ call pargi (apstati (ap, NSKY))
+ call pargi (apstati (ap, NSKY_REJECT))
+ call pargi (ier)
+ call pargstr (Memc[str])
+ call pargi (lastchar)
+
+ call sfree (sp)
+end
+
+
+# AP_SSERRORS -- Encode the sky fitting error messages in a string.
+
+procedure ap_sserrors (ier, str, maxch)
+
+int ier # integer error code
+char str[ARB] # the output string
+int maxch # maximum number of characters
+
+begin
+ switch (ier) {
+ case AP_NOSKYAREA:
+ call strcpy ("OffImage", str, maxch)
+ case AP_SKY_OUTOFBOUNDS:
+ call strcpy ("EdgeImage", str, maxch)
+ case AP_NOHISTOGRAM:
+ call strcpy ("NoHist", str, maxch)
+ case AP_FLAT_HIST:
+ call strcpy ("FlatHist", str, maxch)
+ case AP_NSKY_TOO_SMALL:
+ call strcpy ("TooFewPts", str, maxch)
+ case AP_SKY_SINGULAR:
+ call strcpy ("Singular", str, maxch)
+ case AP_SKY_NOCONVERGE:
+ call strcpy ("BadFit", str, maxch)
+ case AP_NOGRAPHICS:
+ call strcpy ("NoGraph", str, maxch)
+ case AP_NOSKYFILE:
+ call strcpy ("NoFile", str, maxch)
+ case AP_EOFSKYFILE:
+ call strcpy ("ShortFile", str, maxch)
+ case AP_BADSKYSCAN:
+ call strcpy ("BadRecord", str, maxch)
+ case AP_BADPARAMS:
+ call strcpy ("BadParams", str, maxch)
+ default:
+ call strcpy ("NoError", str, maxch)
+ }
+end
diff --git a/noao/digiphot/apphot/aplib/apwres2.x b/noao/digiphot/apphot/aplib/apwres2.x
new file mode 100644
index 00000000..1c5d38a5
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apwres2.x
@@ -0,0 +1,347 @@
+include "../lib/apphotdef.h"
+include "../lib/photdef.h"
+
+include "../lib/apphot.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+include "../lib/polyphot.h"
+
+# define the #N, #U and #K phot/wphot strings
+
+define MAG1_NSTR "#N%4tITIME%19tXAIRMASS%34tIFILTER%57tOTIME%80t\\\n"
+define MAG1_USTR "#U%4ttimeunit%19tnumber%34tname%57ttimeunit%80t\\\n"
+define MAG1_FSTR "#F%4t%%-18.7g%19t%%-15.7g%34t%%-23s%57t%%-23s%80t \n"
+define MAG1_WSTR "%4t%-15.7g%-15.7g%-23.23s%-23.23s%80t\\\n"
+
+define MAG2_NSTR "#N%4tRAPERT%13tSUM%27tAREA%38tFLUX%52tMAG%59tMERR%66t\
+PIER%71tPERROR%80t\\\n"
+define MAG2_USTR "#U%4tscale%13tcounts%27tpixels%38tcounts%52tmag%59t\
+mag%66t##%71tperrors%80t\\\n"
+define MAG2_FSTR "#F%4t%%-12.2f%13t%%-14.7g%27t%%-11.7g%38t%%-14.7g%52t\
+%%-7.3f%59t%%-6.3f%66t%%-5d%71t%%-9s%80t \n"
+define MAG2_WSTR "%4t%-9.2f%-14.7g%-11.7g%-14.7g%-7.3f%-6.3f%-5d%-9.9s\
+%79t%2s\n"
+
+
+# AP_MHDR -- Print the phot/wphot/qphot column header strings.
+
+procedure ap_mhdr (ap, fd)
+
+pointer ap # apphot descriptor (unused)
+int fd # output file descriptor
+
+begin
+ if (fd == NULL)
+ return
+
+ call fprintf (fd, MAG1_NSTR)
+ call fprintf (fd, MAG1_USTR)
+ call fprintf (fd, MAG1_FSTR)
+ call fprintf (fd, "#\n")
+
+ call fprintf (fd, MAG2_NSTR)
+ call fprintf (fd, MAG2_USTR)
+ call fprintf (fd, MAG2_FSTR)
+ call fprintf (fd, "#\n")
+end
+
+
+# AP_WMRES -- Write the results of the phot/qphot/wphot tasks to the output
+# file.
+
+procedure ap_wmres (ap, fd, i, pier, endstr)
+
+pointer ap # pointer to apphot structure
+int fd # output text file
+int i # index of variable length field
+int pier # photometric error
+char endstr[ARB] # termination string
+
+int ier
+pointer sp, str, phot
+real sky_val
+real apstatr()
+
+begin
+ # Initialize.
+ if (fd == NULL)
+ return
+
+ phot = AP_PPHOT(ap)
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Write out the exposure time, airmass and filter information.
+ if (i <= 1) {
+ call fprintf (fd, MAG1_WSTR)
+ call pargr (apstatr (ap, ITIME))
+ call pargr (apstatr (ap, XAIRMASS))
+ call apstats (ap, FILTERID, Memc[str], SZ_FNAME)
+ call pargstr (Memc[str])
+ call apstats (ap, OTIME, Memc[str], SZ_FNAME)
+ call pargstr (Memc[str])
+ }
+
+ # Write out the error code.
+ if (IS_INDEFR(Memr[AP_MAGS(phot)+i-1])) {
+ if (pier != AP_APERT_OUTOFBOUNDS)
+ ier = pier
+ else if (i > AP_NMAXAP(phot))
+ ier = AP_APERT_OUTOFBOUNDS
+ else
+ ier = AP_OK
+ } else if (i >= AP_NMINAP(phot)) {
+ ier = AP_APERT_BADDATA
+ } else {
+ ier = AP_OK
+ }
+ call ap_pserrors (ier, Memc[str], SZ_LINE)
+
+ # Write out the photometry results.
+ call fprintf (fd, MAG2_WSTR)
+ if (i == 0) {
+ call pargr (0.0)
+ call pargr (0.0)
+ call pargr (0.0)
+ call pargr (INDEFR)
+ call pargr (INDEFR)
+ call pargi (ier)
+ call pargstr (Memc[str])
+ call pargstr (endstr)
+ } else {
+ call pargr (Memr[AP_APERTS(phot)+i-1])
+ call pargd (Memd[AP_SUMS(phot)+i-1])
+ call pargd (Memd[AP_AREA(phot)+i-1])
+ sky_val = apstatr (ap, SKY_MODE)
+ if (IS_INDEFR(sky_val))
+ call pargr (0.0)
+ else
+ call pargr (real (Memd[AP_SUMS(phot)+i-1] - sky_val *
+ Memd[AP_AREA(phot)+i-1]))
+ call pargr (Memr[AP_MAGS(phot)+i-1])
+ if (Memr[AP_MAGERRS(phot)+i-1] > 99.999)
+ call pargr (INDEFR)
+ else
+ call pargr (Memr[AP_MAGERRS(phot)+i-1])
+ call pargi (ier)
+ call pargstr (Memc[str])
+ call pargstr (endstr)
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_PSERRORS -- Encode the photometric errors string.
+
+procedure ap_pserrors (ier, str, maxch)
+
+int ier # photometry error code
+char str[ARB] # output string
+int maxch # maximum length of string
+
+begin
+ switch (ier) {
+ case AP_APERT_NOAPERT:
+ call strcpy ("OffImage", str, maxch)
+ case AP_APERT_OUTOFBOUNDS:
+ call strcpy ("EdgeImage", str, maxch)
+ case AP_APERT_NOSKYMODE:
+ call strcpy ("NoSky", str, maxch)
+ case AP_APERT_NEGMAG:
+ call strcpy ("NoFlux", str, maxch)
+ case AP_APERT_BADDATA:
+ call strcpy ("BadPixels", str, maxch)
+ default:
+ call strcpy ("NoError", str, maxch)
+ }
+end
+
+
+# define the #N, #U and #K polyphot strings
+
+define PY_NSTR1 "#N%4tITIME%19tXAIRMASS%34tIFILTER%57tOTIME%80t\\\n"
+define PY_USTR1 "#U%4ttimeunit%19tnumber%34tname%57ttimeunit%80t\\\n"
+define PY_FSTR1 "#F%4t%%-18.7g%19t%%-15.7g%34t%%-23s%57t%%-23s%80t \n"
+define PY_WSTR1 "%4t%-15.7g%-15.7g%-23.23s%-23.23s%80t\\\n"
+
+define PY_NSTR2 "#N%4tSUM%19tAREA%34tFLUX%49tMAG%58tMERR%66tPIER%71t\
+PERROR%80t\\\n"
+define PY_USTR2 "#U%4tcounts%19tpixels%34tcounts%49tmag%58tmag%66t##%71t\
+perrors%80t\\\n"
+define PY_FSTR2 "#F%4t%%-18.7g%19t%%-15.7g%34t%%-15.7g%49t%%-9.3f%58t\
+%%-7.3f%66t%%-5d%71t%%-9s%80t \n"
+define PY_WSTR2 "%4t%-15.7g%-15.7g%-15.7g%-9.3f%-7.3f%-5d%-9.9s%80t\\\n"
+
+define PY_NSTR3 "#N%4tPOLYGONS%24tPID%29tOLDXMEAN%38tOLDYMEAN%47t\
+XMEAN%56tYMEAN%65tMINRAD%74tNVER%80t\\\n"
+define PY_USTR3 "#U%4tfilename%24t##%29tpixels%38tpixels%47t\
+pixels%56tpixels%65tpixels%74t##%80t\\\n"
+define PY_FSTR3 "#F%4t%%-23s%24t%%-5d%29t%%-9.2f%38t%%-9.2f%47t\
+%%-9.2f%56t%%-9.2f%65t%%-9.2f%74t%%-5d%80t \n"
+define PY_WSTR3 "%4t%-20.20s%-5d%-9.2f%-9.2f%-9.2f%-9.2f%-9.2f%-5d%80t\\\n"
+
+define PY_NSTR4 "#N%4tXVERTEX%13tYVERTEX%80t\\\n"
+define PY_USTR4 "#U%4tpixels%13tpixels%80t\\\n"
+define PY_FSTR4 "#F%4t%%-12.2f%13t%%-9.2f%80t \n"
+define PY_WSTR4 "%4t%-9.2f%-9.2f%79t%2s\n"
+
+
+# AP_PLHDR -- Print the polyphot column header strings.
+
+procedure ap_plhdr (ap, fd)
+
+pointer ap # apphot descriptor (unused)
+int fd # output file descriptor
+
+begin
+ if (fd == NULL)
+ return
+
+ call fprintf (fd, PY_NSTR1)
+ call fprintf (fd, PY_USTR1)
+ call fprintf (fd, PY_FSTR1)
+ call fprintf (fd, "#\n")
+
+ call fprintf (fd, PY_NSTR2)
+ call fprintf (fd, PY_USTR2)
+ call fprintf (fd, PY_FSTR2)
+ call fprintf (fd, "#\n")
+
+ call fprintf (fd, PY_NSTR3)
+ call fprintf (fd, PY_USTR3)
+ call fprintf (fd, PY_FSTR3)
+ call fprintf (fd, "#\n")
+
+ call fprintf (fd, PY_NSTR4)
+ call fprintf (fd, PY_USTR4)
+ call fprintf (fd, PY_FSTR4)
+ call fprintf (fd, "#\n")
+end
+
+
+# AP_WLRES -- Write the results of the polyphot task to the output file.
+
+procedure ap_wlres (py, fd, xver, yver, nver, pid, pier)
+
+pointer py # pointer to apphot structure
+int fd # output file descriptor
+real xver[ARB] # coords of x vertices
+real yver[ARB] # coords of y vertices
+int nver # number of vertices
+int pid # polygon number
+int pier # photometric error
+
+int i
+pointer sp, str, pyname
+real sky_val
+int apstati()
+double apstatd()
+real apstatr()
+
+begin
+ if (fd == NULL)
+ return
+
+ # Allocate space.
+ call smark (sp)
+ call salloc (pyname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Write out the exposure time, airmass and filter id.
+ call fprintf (fd, PY_WSTR1)
+ call pargr (apstatr (py, ITIME))
+ call pargr (apstatr (py, XAIRMASS))
+ call apstats (py, FILTERID, Memc[str], SZ_FNAME)
+ call pargstr (Memc[str])
+ call apstats (py, OTIME, Memc[str], SZ_FNAME)
+ call pargstr (Memc[str])
+
+ # Write the photometry results.
+ call ap_spyerrors (pier, Memc[str], SZ_LINE)
+ sky_val = apstatr (py, SKY_MODE)
+ call fprintf (fd, PY_WSTR2)
+ call pargd (apstatd (py, PYFLUX))
+ call pargd (apstatd (py, PYNPIX))
+ if (IS_INDEFR(sky_val))
+ call pargr (0.0)
+ else
+ call pargr (real (apstatd (py, PYFLUX) - sky_val *
+ apstatd (py, PYNPIX)))
+ call pargr (apstatr (py, PYMAG))
+ if (apstatr (py, PYMAGERR) > 99.999)
+ call pargr (INDEFR)
+ else
+ call pargr (apstatr (py, PYMAGERR))
+ call pargi (pier)
+ call pargstr (Memc[str])
+
+ # Write the polygon characteristics
+ #call apstats (py, PYNAME, Memc[pyname], SZ_FNAME)
+ call apstats (py, PYROOT, Memc[pyname], SZ_FNAME)
+ call fprintf (fd, PY_WSTR3)
+ if (Memc[pyname] == EOS)
+ call pargstr ("nullfile")
+ else
+ call pargstr (Memc[pyname])
+ call pargi (pid)
+ call pargr (apstatr (py, OPYXMEAN))
+ call pargr (apstatr (py, OPYYMEAN))
+ call pargr (apstatr (py, OPYCX))
+ call pargr (apstatr (py, OPYCY))
+ call pargr (apstatr (py, PYMINRAD))
+ call pargi (apstati (py, PYNVER))
+
+ # Write out the vertices of the polygon.
+ if (nver == 0) {
+ call fprintf (fd, PY_WSTR4)
+ call pargr (INDEFR)
+ call pargr (INDEFR)
+ call pargstr (" ")
+ } else {
+ do i = 1, nver {
+ call fprintf (fd, PY_WSTR4)
+ if (nver == 1) {
+ call pargr (xver[i])
+ call pargr (yver[i])
+ call pargstr (" ")
+ } else if (i == nver) {
+ call pargr (xver[i])
+ call pargr (yver[i])
+ call pargstr ("* ")
+ } else {
+ call pargr (xver[i])
+ call pargr (yver[i])
+ call pargstr ( "*\\")
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_SPYERRORS -- Encode the polygon fitting error in a string.
+
+procedure ap_spyerrors (ier, str, maxch)
+
+int ier # error code
+char str[ARB] # output string
+int maxch # maximum number of characters
+
+begin
+ switch (ier) {
+ case PY_NOPOLYGON:
+ call strcpy ("NoPolygon", str, maxch)
+ case PY_OUTOFBOUNDS:
+ call strcpy ("EdgeImage", str, maxch)
+ case PY_NOPIX:
+ call strcpy ("NoPixels", str, maxch)
+ case PY_NOSKYMODE:
+ call strcpy ("NoSky", str, maxch)
+ case PY_BADDATA:
+ call strcpy ("BadPixels", str, maxch)
+ default:
+ call strcpy ("NoError", str, maxch)
+ }
+end
diff --git a/noao/digiphot/apphot/aplib/apwres3.x b/noao/digiphot/apphot/aplib/apwres3.x
new file mode 100644
index 00000000..757361dc
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apwres3.x
@@ -0,0 +1,132 @@
+include "../lib/apphotdef.h"
+include "../lib/radprofdef.h"
+include "../lib/apphot.h"
+include "../lib/radprof.h"
+
+# define the #N, #U and #K radprof strings
+
+define RP_NSTR1 "#N%4tPFWHM%14tINORM%29tTINORM%66tRIER%71tRERROR%80t\\\n"
+define RP_USTR1 "#U%4tScale%14tcounts%29tcounts%66t##%71trerrors%80t\\\n"
+define RP_FSTR1 "#F%4t%%-13.3f%14t%%-15.7f%29t%%-36.7f%66t%%-5d%71t\
+%%-9s%80t \n"
+define RP_WSTR1 "%4t%-10.3f%-15.7g%-36.7g%-5d%-9.9s%80t\\\n"
+
+define RP_NSTR2 "#N%4tPRADIUS%14tINTENSITY%29tTINTENSITY%80t\\\n"
+define RP_USTR2 "#U%4tscale%14tcounts%29tcounts%80t\\\n"
+define RP_FSTR2 "#F%4t%%-13.3f%14t%%-15.7f%29t%%-15.7f%80t \n"
+define RP_WSTR2 "%4t%-10.3f%-15.7g%-15.7g%79t%2s\n"
+
+
+# AP_RHDR -- Print the radprof column header strings.
+
+procedure ap_rhdr (ap, fd)
+
+pointer ap # apphot descriptor (unused)
+int fd # output file descriptor
+
+begin
+ if (fd == NULL)
+ return
+ call fprintf (fd, RP_NSTR1)
+ call fprintf (fd, RP_USTR1)
+ call fprintf (fd, RP_FSTR1)
+ call fprintf (fd, "#\n")
+ call fprintf (fd, RP_NSTR2)
+ call fprintf (fd, RP_USTR2)
+ call fprintf (fd, RP_FSTR2)
+ call fprintf (fd, "#\n")
+end
+
+
+# AP_WRRES -- Write the results of the radprof task to the output file.
+
+procedure ap_wrres (ap, fd, ier)
+
+pointer ap # pointer to apphot structure
+int fd # output text file descriptor
+int ier # radial profile error
+
+int i, nrpts
+pointer sp, str, rprof
+real apstatr()
+
+begin
+ # Initialize.
+ if (fd == NULL)
+ return
+ rprof = AP_RPROF(ap)
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Print the radprof parameters.
+ call ap_srerrors (ier, Memc[str], SZ_LINE)
+ call fprintf (fd, RP_WSTR1)
+ call pargr (apstatr (ap, RPFWHM) / apstatr (ap, SCALE))
+ call pargr (apstatr (ap, INORM))
+ call pargr (apstatr (ap, TNORM))
+ call pargi (ier)
+ call pargstr (Memc[str])
+
+ # Print the radial profile.
+ nrpts = apstatr (ap, RPRADIUS) / apstatr (ap, RPSTEP) + 1
+ if (nrpts == 0) {
+ call fprintf (fd, RP_WSTR2)
+ call pargr (INDEFR)
+ call pargr (INDEFR)
+ call pargr (INDEFR)
+ call pargstr (" ")
+ } else {
+ do i = 1, nrpts {
+ if (nrpts == 1) {
+ call fprintf (fd, RP_WSTR2)
+ call pargr (Memr[AP_RPDIST(rprof)+i-1] / AP_SCALE(ap))
+ call pargr (Memr[AP_INTENSITY(rprof)+i-1])
+ call pargr (Memr[AP_TINTENSITY(rprof)+i-1])
+ call pargstr (" ")
+ } if (i == nrpts) {
+ call fprintf (fd, RP_WSTR2)
+ call pargr (Memr[AP_RPDIST(rprof)+i-1] / AP_SCALE(ap))
+ call pargr (Memr[AP_INTENSITY(rprof)+i-1])
+ call pargr (Memr[AP_TINTENSITY(rprof)+i-1])
+ call pargstr ("* ")
+ } else {
+ call fprintf (fd, RP_WSTR2)
+ call pargr (Memr[AP_RPDIST(rprof)+i-1] / AP_SCALE(ap))
+ call pargr (Memr[AP_INTENSITY(rprof)+i-1])
+ call pargr (Memr[AP_TINTENSITY(rprof)+i-1])
+ call pargstr ("*\\")
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_SRERRORS -- Encode the radial profile error message in a string.
+
+procedure ap_srerrors (ier, str, maxch)
+
+int ier # error code
+char str[ARB] # encoded error string
+int maxch # maximum number of characters
+
+begin
+ switch (ier) {
+ case AP_RP_NOPROFILE:
+ call sprintf (str, maxch, "%s")
+ call pargstr ("OffImage")
+ case AP_RP_OUTOFBOUNDS:
+ call sprintf (str, maxch, "%s")
+ call pargstr ("EdgeImage")
+ case AP_RP_NPTS_TOO_SMALL:
+ call sprintf (str, maxch, "%s")
+ call pargstr ("TooFewPts")
+ case AP_RP_SINGULAR:
+ call sprintf (str, maxch, "%s")
+ call pargstr ("Singular")
+ default:
+ call sprintf (str, maxch, "%s")
+ call pargstr ("NoError")
+ }
+end
diff --git a/noao/digiphot/apphot/aplib/apwres4.x b/noao/digiphot/apphot/aplib/apwres4.x
new file mode 100644
index 00000000..67276ea1
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/apwres4.x
@@ -0,0 +1,238 @@
+include "../lib/apphotdef.h"
+include "../lib/fitpsfdef.h"
+include "../lib/apphot.h"
+include "../lib/fitpsf.h"
+
+# define the #N, #U and #K fitpsf strings
+
+define PSF_RNSTR1 "#N%4tXCENTER%14tYCENTER%24tRSIGMA%33tAMPLITUDE%48t\
+SKY%80t\\\n"
+define PSF_RUSTR1 "#U%4tpixels%14tpixels%24tpixels%33tcounts%48t\
+counts%80t\\\n"
+define PSF_RFSTR1 "#F%4t%%-13.3f%14t%%-10.3f%24t%%-9.2f%33t%%-15.7g%48t\
+%%-15.7g%80t \n"
+define PSF_RWSTR1 "%4t%-10.3f%14t%-10.3f%24t%-9.2f%33t%-15.7g%48t\
+%-15.7g%80t\\\n"
+
+define PSF_RNSTR2 "#N%4tEXCENTER%14tEYCENTER%24tERSIGMA%33tEAMPLITUDE%48t\
+ESKY%63tIER%68tERROR%80t\\\n"
+define PSF_RUSTR2 "#U%4tpixels%14tpixels%24tpixels%33tcounts%48t\
+counts%63t##%68terrors%80t\\\n"
+define PSF_RFSTR2 "#F%4t%%-13.3f%14t%%-10.3f%24t%%-9.3f%33t%%-15.7g%48t\
+%%-15.7g%63t%%-5d%68t%%-13s%80t \n"
+define PSF_RWSTR2 "%4t%-10.3f%14t%-10.3f%24t%-9.3f%33t%-15.7g%48t\
+%-15.7g%63t%-5d%68t%-13.13s\n"
+
+define PSF_ENSTR1 "#N%4tXCENTER%14tYCENTER%24tXSIGMA%33tYSIGMA%42t\
+ROT%49tAMPLITUDE%64tSKY%80t\\\n"
+define PSF_EUSTR1 "#U%4tpixels%14tpixels%24tpixels%33tpixels%42t\
+deg%49tcounts%64tcounts%80t\\\n"
+define PSF_EFSTR1 "#F%4t%%-13.3f%14t%%-10.3f%24t%%-9.2f%33t%%-9.2f%42t\
+%%-7.2f%49t%%-15.7g%64t%%-15.7g%80t \n"
+define PSF_EWSTR1 "%4t%-10.3f%-10.3f%-9.2f%-9.2f%-7.2f%-15.7g%-15.7g%80t\\\n"
+
+define PSF_ENSTR2 "#N%4tEXCENTER%14tEYCENTER%24tEXSIGMA%33tEYSIGMA%42t\
+EROT%49tEAMPLITDE%64tESKY%80t\\\n"
+define PSF_EUSTR2 "#U%4tpixels%14tpixels%24tpixels%33tpixels%42t\
+deg%49tcounts%64tcounts%80t\\\n"
+define PSF_EFSTR2 "#F%4t%%-13.3f%14t%%-10.3f%24t%%-9.3f%33t%%-9.3f%42t\
+%%-7.2f%49t%%-15.7g%64t%%-15.7g%80t \n"
+define PSF_EWSTR2 "%4t%-10.3f%-10.3f%-9.3f%-9.3f%-7.2f%-15.7g%-15.7g%80t\\\n"
+
+define PSF_ENSTR3 "#N%4tIER%9tERROR%80t\\\n"
+define PSF_EUSTR3 "#U%4t##%9terrors%80t\\\n"
+define PSF_EFSTR3 "#F%4t%%-8d%9t%%-13s%80t \n"
+define PSF_EWSTR3 "%4t%-5d%-13.13s%80t \n"
+
+
+define PSF_MNSTR1 "#N%4tXCENTER%14tYCENTER%24tRGYRAT%33tELLIP%42t\
+ROT%49tAMPLITUDE%64tSKY%80t\\\n"
+define PSF_MUSTR1 "#U%4tpixels%14tpixels%24tpixels%33tratio%42tdeg%49t\
+counts%64tcounts%80t\\\n"
+define PSF_MFSTR1 "#F%4t%%-13.3f%14t%%-10.3f%24t%%-9.2f%33t%%-9.2f%42t\
+%%-7.2f%49t%%-15.7g%64t%%-15.7f%80t \n"
+define PSF_MWSTR1 "%4t%-10.3f%-10.3f%-9.2f%-9.2f%-7.2f%-15.7g%-15.7g%80t\\\n"
+
+define PSF_MNSTR2 "#N%4tEXCENTER%14tEYCENTER%24tERGYRAT%33tEELLIP%42t\
+EROT%49tEAMPLITUDE%64tESKY%80t\\\n"
+define PSF_MUSTR2 "#U%4tpixels%14tpixels%24tpixels%33tratio%42tdeg%49t\
+counts%64tcounts%80t\\\n"
+define PSF_MFSTR2 "#F%4t%%-13.3f%14t%%-10.3f%24t%%-9.3f%33t%%-9.3f%42t\
+%%-7.2f%49t%%-15.7g%64t%%-15.7g%80t \n"
+define PSF_MWSTR2 "%4t%-10.3f%-10.3f%-9.3f%-9.3f%-7.2f%-15.7g%-15.7g%80t\\\n"
+
+define PSF_MNSTR3 "#N%4tIER%9tERROR%80t\\\n"
+define PSF_MUSTR3 "#U%4t##%9terrors%80t\\\n"
+define PSF_MFSTR3 "#F%4t%%-8d%9t%%-13s%80t \n"
+define PSF_MWSTR3 "%4t%-5d%-13.13s%80t \n"
+
+
+# AP_WFRES -- Write the results of the fitpsf task to the output file.
+
+procedure ap_wfres (ap, fd, ier)
+
+pointer ap # pointer to apphot structure
+int fd # output file descriptor
+int ier # comment string
+
+pointer psf
+
+begin
+ # Initialize.
+ if (fd == NULL)
+ return
+ psf = AP_PPSF(ap)
+
+ # Print the parameters.
+ switch (AP_PSFUNCTION(psf)) {
+ case AP_RADGAUSS:
+ call fprintf (fd, PSF_RWSTR1)
+ call pargr (Memr[AP_PPARS(psf)+1])
+ call pargr (Memr[AP_PPARS(psf)+2])
+ call pargr (Memr[AP_PPARS(psf)+3])
+ call pargr (Memr[AP_PPARS(psf)])
+ call pargr (Memr[AP_PPARS(psf)+4])
+ call fprintf (fd, PSF_RWSTR2)
+ call pargr (Memr[AP_PPERRS(psf)+1])
+ call pargr (Memr[AP_PPERRS(psf)+2])
+ call pargr (Memr[AP_PPERRS(psf)+3])
+ call pargr (Memr[AP_PPERRS(psf)])
+ call pargr (Memr[AP_PPERRS(psf)+4])
+ call pargi (ier)
+ case AP_ELLGAUSS:
+ call fprintf (fd, PSF_EWSTR1)
+ call pargr (Memr[AP_PPARS(psf)+1])
+ call pargr (Memr[AP_PPARS(psf)+2])
+ call pargr (Memr[AP_PPARS(psf)+3])
+ call pargr (Memr[AP_PPARS(psf)+4])
+ call pargr (Memr[AP_PPARS(psf)+5])
+ call pargr (Memr[AP_PPARS(psf)])
+ call pargr (Memr[AP_PPARS(psf)+6])
+ call fprintf (fd, PSF_EWSTR2)
+ call pargr (Memr[AP_PPERRS(psf)+1])
+ call pargr (Memr[AP_PPERRS(psf)+2])
+ call pargr (Memr[AP_PPERRS(psf)+3])
+ call pargr (Memr[AP_PPERRS(psf)+4])
+ call pargr (Memr[AP_PPERRS(psf)+5])
+ call pargr (Memr[AP_PPERRS(psf)])
+ call pargr (Memr[AP_PPERRS(psf)+6])
+ call fprintf (fd, PSF_EWSTR3)
+ call pargi (ier)
+ case AP_MOMENTS:
+ call fprintf (fd, PSF_MWSTR1)
+ call pargr (Memr[AP_PPARS(psf)+1])
+ call pargr (Memr[AP_PPARS(psf)+2])
+ call pargr (Memr[AP_PPARS(psf)+3])
+ call pargr (Memr[AP_PPARS(psf)+4])
+ call pargr (Memr[AP_PPARS(psf)+5])
+ call pargr (Memr[AP_PPARS(psf)])
+ call pargr (Memr[AP_PPARS(psf)+6])
+ call fprintf (fd, PSF_MWSTR2)
+ call pargr (Memr[AP_PPERRS(psf)+1])
+ call pargr (Memr[AP_PPERRS(psf)+2])
+ call pargr (Memr[AP_PPERRS(psf)+3])
+ call pargr (Memr[AP_PPERRS(psf)+4])
+ call pargr (Memr[AP_PPERRS(psf)+5])
+ call pargr (Memr[AP_PPERRS(psf)])
+ call pargr (Memr[AP_PPERRS(psf)+6])
+ call fprintf (fd, PSF_MWSTR3)
+ call pargi (ier)
+ default:
+ ;
+ }
+
+ # Print the error message.
+ switch (ier) {
+ case AP_NOPSFAREA:
+ call pargstr ("OffImage")
+ case AP_PSF_OUTOFBOUNDS:
+ call pargstr ("EdgeImage")
+ case AP_NPSF_TOO_SMALL:
+ call pargstr ("TooFewPts")
+ case AP_PSF_SINGULAR:
+ call pargstr ("Singular")
+ case AP_PSF_NOCONVERGE:
+ call pargstr ("BadFit")
+ default:
+ call pargstr ("NoError")
+ }
+end
+
+
+# RADHDR -- Write the column headers for the radial gaussian function.
+
+procedure radhdr (ap, fd)
+
+pointer ap # pointer to apphot structure
+int fd # output file descriptor
+
+begin
+ # Print the keyword names.
+ call ap_idhdr (ap, fd)
+
+ call fprintf (fd, PSF_RNSTR1)
+ call fprintf (fd, PSF_RUSTR1)
+ call fprintf (fd, PSF_RFSTR1)
+ call fprintf (fd, "#\n")
+
+ call fprintf (fd, PSF_RNSTR2)
+ call fprintf (fd, PSF_RUSTR2)
+ call fprintf (fd, PSF_RFSTR2)
+ call fprintf (fd, "#\n")
+end
+
+
+# ELHDR -- Write the column headers for the elliptical gaussian function.
+
+procedure elhdr (ap, fd)
+
+pointer ap # pointer to apphot structure
+int fd # output file descriptor
+
+begin
+ # Print the keywords.
+ call ap_idhdr (ap, fd)
+
+ call fprintf (fd, PSF_ENSTR1)
+ call fprintf (fd, PSF_EUSTR1)
+ call fprintf (fd, PSF_EFSTR1)
+ call fprintf (fd, "#\n")
+
+ call fprintf (fd, PSF_ENSTR2)
+ call fprintf (fd, PSF_EUSTR2)
+ call fprintf (fd, PSF_EFSTR2)
+ call fprintf (fd, "#\n")
+
+ call fprintf (fd, PSF_ENSTR3)
+ call fprintf (fd, PSF_EUSTR3)
+ call fprintf (fd, PSF_EFSTR3)
+ call fprintf (fd, "#\n")
+end
+
+
+# MOMHDR -- Write the column headers for the moments function.
+
+procedure momhdr (ap, fd)
+
+pointer ap # pointer to apphot structure
+int fd # output file descriptor
+
+begin
+ # Print the keywords.
+ call ap_idhdr (ap, fd)
+
+ call fprintf (fd, PSF_MNSTR1)
+ call fprintf (fd, PSF_MUSTR1)
+ call fprintf (fd, PSF_MFSTR1)
+ call fprintf (fd, "#\n")
+
+ call fprintf (fd, PSF_MNSTR2)
+ call fprintf (fd, PSF_MUSTR2)
+ call fprintf (fd, PSF_MFSTR2)
+ call fprintf (fd, "#\n")
+
+ call fprintf (fd, PSF_MNSTR3)
+ call fprintf (fd, PSF_MUSTR3)
+ call fprintf (fd, PSF_MFSTR3)
+ call fprintf (fd, "#\n")
+end
diff --git a/noao/digiphot/apphot/aplib/mkpkg b/noao/digiphot/apphot/aplib/mkpkg
new file mode 100644
index 00000000..a426075f
--- /dev/null
+++ b/noao/digiphot/apphot/aplib/mkpkg
@@ -0,0 +1,102 @@
+# APPHOT Library Tools
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ apairmass.x <imhdr.h> ../lib/apphot.h
+ apapcolon.x <error.h> ../lib/apphot.h
+ aparrays.x ../lib/phot.h ../lib/photdef.h \
+ ../lib/apphotdef.h
+ apfree.x ../lib/apphotdef.h
+ apgaperts.x <lexnum.h> <ctype.h>
+ apgqverify.x <ttyset.h> <fset.h>
+ apgsvw.x <imio.h> <imhdr.h> \
+ <math.h>
+ apgtverify.x
+ apinit.x ../lib/apphotdef.h ../lib/apphot.h \
+ ../lib/noisedef.h ../lib/noise.h \
+ ../lib/displaydef.h
+ apinpars1.x ../lib/apphot.h ../lib/noise.h \
+ ../lib/find.h ../lib/display.h
+ apinpars2.x ../lib/display.h ../lib/center.h \
+ ../lib/fitsky.h ../lib/phot.h \
+ ../lib/polyphot.h
+ apitime.x ../lib/apphot.h <imhdr.h>
+ apfilter.x <imhdr.h> ../lib/apphot.h
+ apimbuf.x ../lib/apphotdef.h
+ apmark1.x <gset.h> ../lib/center.h \
+ ../lib/fitsky.h ../lib/apphot.h \
+ ../lib/phot.h ../lib/polyphot.h \
+ ../lib/radprof.h
+ apmark2.x <gset.h> ../lib/apphot.h \
+ ../lib/fitpsf.h
+ apnew.x ../lib/apphot.h
+ apnscolon.x <error.h> ../lib/noise.h
+ apnshow.x ../lib/apphot.h ../lib/noise.h
+ apotime.x ../lib/apphot.h <imhdr.h>
+ apoutpars1.x ../lib/apphot.h ../lib/noise.h \
+ ../lib/display.h ../lib/find.h
+ apoutpars2.x ../lib/display.h ../lib/center.h \
+ ../lib/fitsky.h ../lib/phot.h \
+ ../lib/polyphot.h
+ apqrad.x ../lib/apphot.h ../lib/center.h \
+ <mach.h>
+ appadu.x ../lib/noise.h <imhdr.h>
+ aprcursor1.x ../lib/apphot.h ../lib/noise.h \
+ ../lib/center.h ../lib/fitsky.h \
+ ../lib/phot.h
+ aprcursor2.x ../lib/apphot.h ../lib/fitpsf.h \
+ ../lib/radprof.h
+ aprdnoise.x ../lib/noise.h <imhdr.h>
+ apset.x
+ apset1.x ../lib/center.h ../lib/centerdef.h \
+ ../lib/fitsky.h ../lib/apphot.h \
+ ../lib/apphotdef.h ../lib/fitskydef.h \
+ ../lib/phot.h ../lib/photdef.h \
+ ../lib/fitpsfdef.h ../lib/fitpsf.h
+ apset2.x ../lib/apphot.h ../lib/apphotdef.h \
+ ../lib/display.h ../lib/polyphot.h \
+ ../lib/radprofdef.h ../lib/radprof.h \
+ ../lib/polyphotdef.h ../lib/noisedef.h \
+ ../lib/noise.h ../lib/finddef.h \
+ ../lib/find.h ../lib/displaydef.h
+ apstat.x
+ apstat1.x ../lib/center.h ../lib/centerdef.h \
+ ../lib/fitsky.h ../lib/apphot.h \
+ ../lib/apphotdef.h ../lib/fitskydef.h \
+ ../lib/phot.h ../lib/photdef.h \
+ ../lib/fitpsfdef.h ../lib/fitpsf.h
+ apstat2.x ../lib/apphot.h ../lib/apphotdef.h \
+ ../lib/display.h ../lib/polyphot.h \
+ ../lib/radprofdef.h ../lib/radprof.h \
+ ../lib/polyphotdef.h ../lib/noisedef.h \
+ ../lib/noise.h ../lib/finddef.h \
+ ../lib/find.h ../lib/displaydef.h
+ apshowplot.x ../lib/apphot.h
+ apverify1.x <math.h> ../lib/apphot.h \
+ ../lib/center.h ../lib/fitsky.h \
+ ../lib/phot.h ../lib/noise.h
+ apverify2.x ../lib/apphot.h ../lib/fitpsf.h \
+ ../lib/noise.h ../lib/find.h \
+ ../lib/radprof.h
+ apwres1.x ../lib/apphot.h ../lib/find.h \
+ ../lib/center.h ../lib/fitsky.h
+ apwres2.x ../lib/apphotdef.h ../lib/photdef.h \
+ ../lib/apphot.h ../lib/fitsky.h \
+ ../lib/phot.h ../lib/polyphot.h
+ apwres3.x ../lib/apphotdef.h ../lib/radprofdef.h \
+ ../lib/apphot.h ../lib/radprof.h
+ apwres4.x ../lib/apphotdef.h ../lib/fitpsfdef.h \
+ ../lib/fitpsf.h ../lib/apphot.h
+ apwparam1.x <time.h> ../lib/apphot.h \
+ ../lib/noise.h ../lib/center.h \
+ ../lib/fitsky.h ../lib/phot.h \
+ ../lib/apphotdef.h
+ apwparam2.x ../lib/apphotdef.h ../lib/polyphot.h \
+ ../lib/radprof.h ../lib/fitpsf.h
+ apimkeys.x ../lib/apphot.h
+ apwcs.x ../lib/apphot.h <imio.h>
+ ;
diff --git a/noao/digiphot/apphot/apphot.cl b/noao/digiphot/apphot/apphot.cl
new file mode 100644
index 00000000..d4b3b94f
--- /dev/null
+++ b/noao/digiphot/apphot/apphot.cl
@@ -0,0 +1,58 @@
+#{ APPHOTX -- Digital aperture photometry package.
+
+dataio # rfits task required by aptest.cl script
+lists # lintran task in the lists package
+
+package apphot
+
+task center,
+ daofind,
+ fitpsf,
+ fitsky,
+ radprof,
+ phot,
+ polymark,
+ polyphot,
+ qphot,
+ wphot = "apphot$x_apphot.e"
+
+task centerpars = "apphot$centerpars.par"
+task datapars = "apphot$datapars.par"
+task findpars = "apphot$findpars.par"
+task fitskypars = "apphot$fitskypars.par"
+task photpars = "apphot$photpars.par"
+task polypars = "apphot$polypars.par"
+
+task aptest = "apphot$aptest.cl"
+
+# PTOOLS tasks
+
+task pexamine = "apphot$x_ptools.e"
+
+task pconvert,
+ istable,
+ txcalc,
+ txdump,
+ txrenumber,
+ txselect,
+ txsort = "ptools$x_ptools.e"
+
+task xyplot = "ptools$xyplot.par"
+task histplot = "ptools$histplot.par"
+task radplot = "ptools$radplot.par"
+task surfplot = "ptools$surfplot.par"
+task cntrplot = "ptools$cntrplot.par"
+
+# PTOOLS scripts which depend on PTOOLS and TTOOLS tasks
+# Note TTOOLS is not loaded
+
+task pcalc = "ptools$pcalc.cl"
+task pdump = "ptools$pdump.cl"
+task prenumber = "ptools$prenumber.cl"
+task pselect = "ptools$pselect.cl"
+task psort = "ptools$psort.cl"
+
+hidetask istable, txcalc, txdump, txrenumber, txselect, txsort
+hidetask xyplot, histplot, radplot, surfplot, cntrplot
+
+clbye()
diff --git a/noao/digiphot/apphot/apphot.hd b/noao/digiphot/apphot/apphot.hd
new file mode 100644
index 00000000..6061b68d
--- /dev/null
+++ b/noao/digiphot/apphot/apphot.hd
@@ -0,0 +1,34 @@
+# Help directory for the APPHOT package
+
+$doc = "./doc/"
+
+$aptest = "apphot$aptest/"
+$center = "apphot$center/"
+$daofind = "apphot$daofind/"
+$fitpsf = "apphot$fitpsf/"
+$fitsky = "apphot$fitsky/"
+$phot = "apphot$phot/"
+$polyphot = "apphot$polyphot/"
+$pexamine = "ptools$pexamine/"
+$radprof = "apphot$radprof/"
+$wphot = "apphot$wphot/"
+
+aptest hlp=doc$aptest.hlp
+center hlp=doc$center.hlp, src=center$t_center.x
+centerpars hlp=doc$centerpars.hlp, src=apphot$centerpars.par
+daofind hlp=doc$daofind.hlp, src=daofind$t_daofind.x
+datapars hlp=doc$datapars.hlp, src=apphot$datapars.par
+findpars hlp=doc$findpars.hlp, src=apphot$findpars.par
+fitpsf hlp=doc$fitpsf.hlp, src=fitpsf$t_fitpsf.x
+fitsky hlp=doc$fitsky.hlp, src=fitsky$t_fitsky.x
+fitskypars hlp=doc$fitskypars.hlp, src=apphot$fitskypars.par
+pexamine hlp=doc$pexamine.hlp, src=pexamine$t_pexamine.x
+phot hlp=doc$phot.hlp, src=phot$t_phot.x
+photpars hlp=doc$photpars.hlp, src=apphot$photpars.par
+polymark hlp=doc$polymark.hlp, src=polyphot$t_polymark.x
+polyphot hlp=doc$polyphot.hlp, src=polyphot$t_polyphot.x
+polypars hlp=doc$polypars.hlp, src=apphot$polypars.par
+qphot hlp=doc$qphot.hlp, src=phot$t_qphot.x
+radprof hlp=doc$radprof.hlp, src=radprof$t_radprof.x
+wphot hlp=doc$wphot.hlp, src=wphot$t_wphot.x
+revisions sys=Revisions
diff --git a/noao/digiphot/apphot/apphot.men b/noao/digiphot/apphot/apphot.men
new file mode 100644
index 00000000..e83c00ff
--- /dev/null
+++ b/noao/digiphot/apphot/apphot.men
@@ -0,0 +1,26 @@
+ aptest - Run basic tests on the apphot package tasks
+ center - Compute accurate centers for a list of objects
+ centerpars - Edit the centering parameters
+ daofind - Find stars in an image using the dao algorithm
+ datapars - Edit the data dependent parameters
+ findpars - Edit the star detection parameters
+ fitpsf - Model the stellar psf with an analytic function
+ fitsky - Compute sky values in a list of annular or circular regions
+ fitskypars - Edit the sky fitting parameters
+ phot - Measure magnitudes for a list of stars
+ photpars - Edit the photometry parameters
+ polymark - Create polygon lists for polyphot
+ polyphot - Measure magnitudes inside a list of polygonal regions
+ polypars - Edit the polyphot parameters
+ qphot - Measure quick magnitudes for a list of stars
+ radprof - Compute the stellar radial profile of a list of stars
+ wphot - Measure magnitudes for a list of stars with weighting
+
+ lintran - Linearly transform a coordinate list
+ pcalc - Do arithmetic operations on a list of apphot databases
+ pconvert - Convert a text database to a tables database
+ pdump - Print selected fields from a list of apphot databases
+ pexamine - Interactively examine and edit an apphot database
+ prenumber - Renumber stars in an apphot database
+ pselect - Select records from an apphot database
+ psort - Sort an apphot database
diff --git a/noao/digiphot/apphot/apphot.par b/noao/digiphot/apphot/apphot.par
new file mode 100644
index 00000000..ba37d156
--- /dev/null
+++ b/noao/digiphot/apphot/apphot.par
@@ -0,0 +1,11 @@
+# APPHOTX package parameter file
+
+version,s,h,"May00"
+wcsin,s,h,logical,"logical|tv|physical|world",,"The input coordinates wcs"
+wcsout,s,h,logical,"logical|tv|physical",,"The output coordinates wcs"
+cache,b,h,no,,,"Cache image in memory ?"
+verify,b,h,yes,,,"Verify critical parameters ?"
+update,b,h,no,,,"Update critial parameters ?"
+verbose,b,h,no,,,"Print verbose output ?"
+graphics,s,h,stdgraph,,,"Default graphics device"
+display,s,h,stdimage,,,"Default display device"
diff --git a/noao/digiphot/apphot/aptest.cl b/noao/digiphot/apphot/aptest.cl
new file mode 100644
index 00000000..58dad449
--- /dev/null
+++ b/noao/digiphot/apphot/aptest.cl
@@ -0,0 +1,220 @@
+# APTEST - Self testing procedure for the APPHOT package.
+
+procedure aptest (imname)
+
+string imname {prompt="Name of the output test image"}
+string aplogfile {"", prompt="Name of the output log file"}
+string applotfile {"", prompt="Name of the output plot file"}
+
+begin
+ # Declare local variables.
+ string im, aplog, applot, apcoords
+
+ # Check that the user truly wants to proceed.
+ s1 = ""
+ print ("")
+ print ("APTEST INITIALIZES THE APPHOT TASK PARAMETERS")
+ print ("TYPE q or Q TO QUIT, ANY OTHER KEY TO PROCEED")
+ if (scan (s1) != EOF) {
+ if (s1 == "q" || s1 == "Q") {
+ print ("TERMINATING THE APTEST TASK")
+ bye
+ }
+ }
+ print ("")
+
+ # Define some local variables.
+ im = imname
+ aplog = aplogfile
+ if (aplog == "") {
+ aplog = im // ".log"
+ }
+ applot = applotfile
+ if (applot == "") {
+ applot = im // ".plot"
+ }
+
+ # Read in the fits file and check for existance of the log and
+ # plot files.
+ if (! access (im // ".imh") && ! access (im // ".hhh")) {
+ rfits ("apphot$test/fits3.fits", "0", im, make_image=yes,
+ long_header=no, short_header=yes, datatype="",blank=0,
+ scale=yes,oldirafname=no,offset=0, >& "dev$null")
+ } else {
+ error (0, "Error: The image already exists on disk")
+ }
+ if (access (aplog)) {
+ error (0, "Error: The log file already exists on disk")
+ }
+ if (access (applot)) {
+ error (0, "Error: The plot file already exists on disk")
+ }
+
+ # Initialize the APPHOT package.
+ print ("INITIALIZE THE APPHOT PACKAGE", >> aplog)
+ print ("", >> aplog)
+ print ("")
+ print ("INITIALIZE THE APPHOT PACKAGE")
+ print ("")
+
+ unlearn ("txdump")
+ unlearn ("center")
+ unlearn ("centerpars")
+ unlearn ("daofind")
+ unlearn ("datapars")
+ unlearn ("findpars")
+ unlearn ("fitpsf")
+ unlearn ("fitsky")
+ unlearn ("fitskypars")
+ unlearn ("phot")
+ unlearn ("photpars")
+ unlearn ("polymark")
+ unlearn ("polyphot")
+ unlearn ("polypars")
+ unlearn ("qphot")
+ unlearn ("radprof")
+ unlearn ("wphot")
+
+ # Test the DAOFIND task.
+
+ print ("TESTING THE DAOFIND TASK", >> aplog)
+ print ("TESTING THE DAOFIND TASK")
+ print ("", >> aplog)
+
+ datapars.fwhmpsf=2.354820
+ datapars.sigma=10.0
+ findpars.threshold=3.0
+
+ apcoords = im // ".coo.1"
+ daofind (im, output=apcoords, interactive-, verify-)
+ concat (apcoords, aplog, append=yes)
+
+ # Test the CENTER task.
+
+ print ("", >> aplog)
+ print ("TESTING THE CENTER TASK", >> aplog)
+ print ("TESTING THE CENTER TASK")
+ print ("", >> aplog)
+
+ center (im, coords=apcoords, interactive-, verify-)
+ concat (im // ".ctr.1", aplog, append=yes)
+ delete (im // ".ctr.1", ver-, >& "dev$null")
+
+ # Test the FITSKY task.
+
+ print ("", >> aplog)
+ print ("TESTING THE FITSKY TASK", >> aplog)
+ print ("TESTING THE FITSKY TASK")
+ print ("", >> aplog)
+
+ fitskypars.annulus=6.0
+ fitskypars.dannulus=7.0
+
+ fitsky (im, coords=apcoords, interactive-, verify-)
+ concat (im // ".sky.1", aplog, append=yes)
+ delete (im // ".sky.1", ver-, >& "dev$null")
+
+ # Test the QPHOT task.
+
+ print ("", >> aplog)
+ print ("TESTING THE QPHOT TASK", >> aplog)
+ print ("TESTING THE QPHOT TASK")
+ print ("", >> aplog)
+
+ qphot (im, 5.0, 6.0, 7.0, "3.0,5.0", coords=apcoords, interactive-)
+ concat (im // ".mag.1", aplog, append=yes)
+ delete (im // ".mag.1", ver-, >& "dev$null")
+
+ # Test the PHOT task.
+
+ print ("", >> aplog)
+ print ("TESTING THE PHOT TASK", >> aplog)
+ print ("TESTING THE PHOT TASK")
+ print ("", >> aplog)
+
+ photpars.apertures="3.0,5.0"
+
+ phot (im, coords=apcoords, interactive-, verify-)
+ concat (im // ".mag.1", aplog, append=yes)
+ delete (im // ".mag.1", ver-, >& "dev$null")
+
+ # Test the WPHOT task.
+
+ print ("", >> aplog)
+ print ("TESTING THE WPHOT TASK", >> aplog)
+ print ("TESTING THE WPHOT TASK")
+ print ("", >> aplog)
+
+ photpars.weighting="gauss"
+
+ wphot (im, coords=apcoords, interactive-, verify-)
+ concat (im // ".omag.1", aplog, append=yes)
+ delete (im // ".omag.1", ver-, >& "dev$null")
+
+ # Test the POLYPHOT task.
+
+ print ("", >> aplog)
+ print ("TESTING THE POLYPHOT TASK", >> aplog)
+ print ("TESTING THE POLYPHOT TASK")
+ print ("", >> aplog)
+ print ("COPY OF THE POLYGONS FILE", >> aplog)
+ print ("", >> aplog)
+ concat ("apphot$test/polygons.dat", aplog, append=yes)
+ print ("", >> aplog)
+
+ polyphot (im, coords=apcoords, polygons="apphot$test/polygons.dat",
+ interactive-, verify-)
+ concat (im // ".ply.1", aplog, append=yes)
+ delete (im // ".ply.1", ver-, >& "dev$null")
+
+ # Test the RADPROF task.
+
+ print ("", >> aplog)
+ print ("TESTING THE RADPROF TASK", >> aplog)
+ print ("TESTING THE RADPROF TASK")
+ print ("", >> aplog)
+
+ radprof (im, 8.0, 0.25, coords=apcoords, output="default",
+ plotfile=applot, order=4, nreject=3, kreject=3.0, interactive-,
+ verify-)
+ concat (im // ".prf.1", aplog, append=yes)
+ delete (im // ".prf.1", ver-, >& "dev$null")
+
+ # Test the FITPSF task.
+
+ print ("", >> aplog)
+ print ("TESTING THE FITPSF TASK", >> aplog)
+ print ("TESTING THE FITPSF TASK")
+ print ("", >> aplog)
+
+ fitpsf (im, 7.0, coords=apcoords, interactive-, verify-)
+ concat (im // ".psf.1", aplog, append=yes)
+ delete (im // ".psf.1", ver-, >& "dev$null")
+
+ print ("", >> aplog)
+ print ("APPHOT PACKAGE TESTS COMPLETED", >> aplog)
+ print ("")
+ print ("APPHOT PACKAGE TESTS COMPLETED")
+ print ("", >> aplog)
+
+ # Clean up.
+ delete (apcoords, ver-, >& "dev$null")
+ unlearn ("txdump")
+ unlearn ("center")
+ unlearn ("centerpars")
+ unlearn ("daofind")
+ unlearn ("datapars")
+ unlearn ("findpars")
+ unlearn ("fitpsf")
+ unlearn ("fitsky")
+ unlearn ("fitskypars")
+ unlearn ("phot")
+ unlearn ("photpars")
+ unlearn ("polymark")
+ unlearn ("polyphot")
+ unlearn ("polypars")
+ unlearn ("qphot")
+ unlearn ("radprof")
+ unlearn ("wphot")
+ bye
+end
diff --git a/noao/digiphot/apphot/aputil/apbsmooth.x b/noao/digiphot/apphot/aputil/apbsmooth.x
new file mode 100644
index 00000000..28c53c00
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/apbsmooth.x
@@ -0,0 +1,33 @@
+# AP_BSMOOTH - Box car smooth a histogram 1, 2 or 3 times.
+
+procedure ap_bsmooth (hgm, shgm, nbins, nker, iter)
+
+real hgm[ARB] # the original histogram
+real shgm[ARB] # the smoothed histogram
+int nbins # length of the histogram
+int nker # half width of box kernel
+int iter # number of iterations
+
+pointer sp, work1, work2
+
+begin
+ # Smooth the histogram
+ switch (iter) {
+ case 1:
+ call ap_sboxr (hgm, shgm, nbins, nker)
+ case 2:
+ call smark (sp)
+ call salloc (work1, nbins, TY_REAL)
+ call ap_sboxr (hgm, Memr[work1], nbins, nker)
+ call ap_sboxr (Memr[work1], shgm, nbins, nker)
+ call sfree (sp)
+ default:
+ call smark (sp)
+ call salloc (work1, nbins, TY_REAL)
+ call salloc (work2, nbins, TY_REAL)
+ call ap_sboxr (hgm, Memr[work1], nbins, nker)
+ call ap_sboxr (Memr[work1], Memr[work2], nbins, nker)
+ call ap_sboxr (Memr[work2], shgm, nbins, nker)
+ call sfree (sp)
+ }
+end
diff --git a/noao/digiphot/apphot/aputil/apclip.x b/noao/digiphot/apphot/aputil/apclip.x
new file mode 100644
index 00000000..62a52c30
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/apclip.x
@@ -0,0 +1,23 @@
+# AP_CLIP -- Clip the ends of a sorted pixel distribution by a certain
+# percent.
+
+int procedure ap_clip (skypix, index, npix, loclip, hiclip, loindex, hiindex)
+
+real skypix[ARB] # the unsorted array of sky pixels
+int index[ARB] # the array of sorted indices
+int npix # the number of sky pixels
+real loclip, hiclip # the clipping factors in percent
+int loindex, hiindex # the clipping indices
+
+begin
+ # Sort the pixels.
+ call apqsort (skypix, index, index, npix)
+
+ # Determine the clipping factors.
+ loindex = nint (0.01 * loclip * npix) + 1
+ hiindex = npix - nint (0.01 * hiclip * npix)
+ if ((hiindex - loindex + 1) <= 0)
+ return (npix)
+ else
+ return (loindex - 1 + npix - hiindex)
+end
diff --git a/noao/digiphot/apphot/aputil/apdate.x b/noao/digiphot/apphot/aputil/apdate.x
new file mode 100644
index 00000000..21faea88
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/apdate.x
@@ -0,0 +1,29 @@
+include <time.h>
+
+# APDATE -- Fetch the date and time strings required for the apphot output
+# files.
+
+procedure apdate (date, time, maxch)
+
+char date[ARB] # the date string
+char time[ARB] # the time string
+int maxch # the maximum number of character in the string
+
+int tm[LEN_TMSTRUCT]
+long ctime
+long clktime()
+#long lsttogmt()
+
+begin
+ ctime = clktime (long(0))
+ #ctime = lsttogmt (ctime)
+ call brktime (ctime, tm)
+ call sprintf (date, maxch, "%04d-%02d-%02d")
+ call pargi (TM_YEAR(tm))
+ call pargi (TM_MONTH(tm))
+ call pargi (TM_MDAY(tm))
+ call sprintf (time, maxch, "%02d:%02d:%02d")
+ call pargi (TM_HOUR(tm))
+ call pargi (TM_MIN(tm))
+ call pargi (TM_SEC(tm))
+end
diff --git a/noao/digiphot/apphot/aputil/apdiverr.x b/noao/digiphot/apphot/aputil/apdiverr.x
new file mode 100644
index 00000000..d3c36444
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/apdiverr.x
@@ -0,0 +1,7 @@
+# AP_DIVERR -- Error condition procedure which returns a value of unity.
+
+real procedure ap_diverr ()
+
+begin
+ return (1.0)
+end
diff --git a/noao/digiphot/apphot/aputil/apfnames.x b/noao/digiphot/apphot/aputil/apfnames.x
new file mode 100644
index 00000000..95e56167
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/apfnames.x
@@ -0,0 +1,280 @@
+
+# APINNAME -- Construct an apphot input file name.
+# If input is null or a directory, a name is constructed from the root
+# of the image name and the extension. The disk is searched to avoid
+# name collisions.
+
+procedure apinname (image, input, ext, name, maxch)
+
+char image[ARB] # image name
+char input[ARB] # input directory or name
+char ext[ARB] # extension
+char name[ARB] # input name
+int maxch # maximum size of name
+
+int ndir, nimdir, clindex, clsize
+pointer sp, root, str
+int fnldir(), strlen()
+
+begin
+ call smark (sp)
+ call salloc (root, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ ndir = fnldir (input, name, maxch)
+ if (strlen (input) == ndir) {
+ call imparse (image, Memc[root], SZ_FNAME, Memc[str], SZ_FNAME,
+ Memc[str], SZ_FNAME, clindex, clsize)
+ nimdir = fnldir (Memc[root], Memc[str], SZ_FNAME)
+ if (clindex >= 0) {
+ call sprintf (name[ndir+1], maxch, "%s%d.%s.*")
+ call pargstr (Memc[root+nimdir])
+ call pargi (clindex)
+ call pargstr (ext)
+ } else {
+ call sprintf (name[ndir+1], maxch, "%s.%s.*")
+ call pargstr (Memc[root+nimdir])
+ call pargstr (ext)
+ }
+ call apiversion (name, name, maxch)
+ } else
+ call strcpy (input, name, maxch)
+
+ call sfree (sp)
+end
+
+
+# APOUTNAME -- Construct an apphot output file name.
+# If output is null or a directory, a name is constructed from the root
+# of the image name and the extension. The disk is searched to avoid
+# name collisions.
+
+procedure apoutname (image, output, ext, name, maxch)
+
+char image[ARB] # image name
+char output[ARB] # output directory or name
+char ext[ARB] # extension
+char name[ARB] # output name
+int maxch # maximum size of name
+
+int ndir, nimdir, clindex, clsize
+pointer sp, root, str
+int fnldir(), strlen()
+
+begin
+ call smark (sp)
+ call salloc (root, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ ndir = fnldir (output, name, maxch)
+ if (strlen (output) == ndir) {
+ call imparse (image, Memc[root], SZ_FNAME, Memc[str], SZ_FNAME,
+ Memc[str], SZ_FNAME, clindex, clsize)
+ nimdir = fnldir (Memc[root], Memc[str], SZ_FNAME)
+ if (clindex >= 0) {
+ call sprintf (name[ndir+1], maxch, "%s%d.%s.*")
+ call pargstr (Memc[root+nimdir])
+ call pargi (clindex)
+ call pargstr (ext)
+ } else {
+ call sprintf (name[ndir+1], maxch, "%s.%s.*")
+ call pargstr (Memc[root+nimdir])
+ call pargstr (ext)
+ }
+ call apoversion (name, name, maxch)
+ } else
+ call strcpy (output, name, maxch)
+
+ call sfree (sp)
+end
+
+
+# APTMPIMAGE -- Generate a temporary image name either by calling a system
+# routine or by appending the image name to a user specified prefix.
+
+int procedure aptmpimage (image, prefix, tmp, name, maxch)
+
+char image[ARB] # image name
+char prefix[ARB] # user supplied prefix
+char tmp[ARB] # user supplied temporary root
+char name[ARB] # output name
+int maxch # max number of chars
+
+int npref, ndir, nimdir, clindex, clsize
+pointer sp, root, str
+int fnldir(), strlen()
+
+begin
+ npref = strlen (prefix)
+ ndir = fnldir (prefix, name, maxch)
+ if (npref == ndir) {
+ call mktemp (tmp, name[ndir+1], maxch)
+ return (NO)
+ } else {
+ call smark (sp)
+ call salloc (root, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+ call strcpy (prefix, name, npref)
+ call imparse (image, Memc[root], SZ_FNAME, Memc[str], SZ_FNAME,
+ Memc[str], SZ_FNAME, clindex, clsize)
+ nimdir = fnldir (Memc[root], Memc[str], SZ_FNAME)
+ if (clindex >= 0) {
+ call sprintf (name[npref+1], maxch, "%s%d")
+ call pargstr (Memc[root+nimdir])
+ call pargi (clindex)
+ } else {
+ call sprintf (name[npref+1], maxch, "%s")
+ call pargstr (Memc[root+nimdir])
+ }
+ call sfree (sp)
+ return (YES)
+ }
+end
+
+
+# APIMROOT -- Fetch the root image name minus the directory specification
+# and the section notation.
+
+procedure apimroot (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
+
+
+
+# APFROOT -- Fetch the file name minus the directory specification,
+
+procedure apfroot (filename, root, maxch)
+
+char filename[ARB] # input file name
+char root[ARB] # output root file name
+int maxch # maximum number of characters
+
+pointer sp, str
+int nchars
+int fnldir()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_PATHNAME, TY_CHAR)
+
+ nchars = fnldir (filename, Memc[str], SZ_PATHNAME)
+ call strcpy (filename[nchars+1], root, maxch)
+
+ call sfree (sp)
+end
+
+
+# APOVERSION -- Compute the next available version number of a given file
+# name template and output the new file name.
+
+procedure apoversion (template, filename, maxch)
+
+char template[ARB] # name template
+char filename[ARB] # output name
+int maxch # maximum number of characters
+
+char period
+int newversion, version, len
+pointer sp, list, name
+int fntgfnb() strldx(), ctoi(), fntopnb()
+
+begin
+ # Allocate temporary space
+ call smark (sp)
+ call salloc (name, maxch, TY_CHAR)
+ period = '.'
+ list = fntopnb (template, NO)
+
+ # Loop over the names in the list searchng for the highest version.
+ newversion = 0
+ while (fntgfnb (list, Memc[name], maxch) != EOF) {
+ len = strldx (period, Memc[name])
+ len = len + 1
+ if (ctoi (Memc[name], len, version) <= 0)
+ next
+ newversion = max (newversion, version)
+ }
+
+ # Make new output file name.
+ len = strldx (period, template)
+ call strcpy (template, filename, len)
+ call sprintf (filename[len+1], maxch, "%d")
+ call pargi (newversion + 1)
+
+ call fntclsb (list)
+ call sfree (sp)
+end
+
+
+# APIVERSION -- Compute the highest available version number of a given file
+# name template and output the file name.
+
+procedure apiversion (template, filename, maxch)
+
+char template[ARB] # name template
+char filename[ARB] # output name
+int maxch # maximum number of characters
+
+char period
+int newversion, version, len
+pointer sp, list, name
+int fntgfnb() strldx(), ctoi(), fntopnb()
+
+begin
+ # Allocate temporary space
+ call smark (sp)
+ call salloc (name, maxch, TY_CHAR)
+ period = '.'
+ list = fntopnb (template, NO)
+
+ # Loop over the names in the list searchng for the highest version.
+ newversion = 0
+ while (fntgfnb (list, Memc[name], maxch) != EOF) {
+ len = strldx (period, Memc[name])
+ len = len + 1
+ if (ctoi (Memc[name], len, version) <= 0)
+ next
+ newversion = max (newversion, version)
+ }
+
+ # Make new output file name.
+ len = strldx (period, template)
+ call strcpy (template, filename, len)
+ call sprintf (filename[len+1], maxch, "%d")
+ call pargi (newversion)
+
+ call fntclsb (list)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aputil/apgscur.x b/noao/digiphot/apphot/aputil/apgscur.x
new file mode 100644
index 00000000..5cc8a6df
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/apgscur.x
@@ -0,0 +1,88 @@
+include <gset.h>
+include <fset.h>
+
+# APGSCUR -- Read the x and y coordinates of an object from a file and move
+# the cursor to those coordinates.
+
+int procedure apgscur (sl, gd, xcur, ycur, prev_num, req_num, num)
+
+int sl # coordinate file descriptor
+pointer gd # pointer to graphics stream
+real xcur, ycur # x cur and y cur
+int prev_num # previous number
+int req_num # requested number
+int num # list number
+
+int stdin, nskip, ncount
+pointer sp, fname
+int fscan(), nscan(), strncmp()
+errchk greactivate, gdeactivate, gscur
+
+begin
+ if (sl == NULL)
+ return (EOF)
+
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+
+ # Find the number of objects to be skipped.
+ call fstats (sl, F_FILENAME, Memc[fname], SZ_FNAME)
+ if (strncmp ("STDIN", Memc[fname], 5) == 0) {
+ stdin = YES
+ nskip = 1
+ } else {
+ stdin = NO
+ if (req_num <= prev_num) {
+ call seek (sl, BOF)
+ nskip = req_num
+ } else
+ nskip = req_num - prev_num
+ }
+
+ # Initialize.
+ ncount = 0
+ num = prev_num
+
+ # Read the coordinates and write the cursor.
+ repeat {
+
+ # Print the prompt if file is STDIN.
+ if (stdin == YES) {
+ call printf ("Type object x and y coordinates: ")
+ call flush (STDOUT)
+ }
+
+ # Fetch the coordinates.
+ if (fscan (sl) != EOF) {
+ call gargr (xcur)
+ call gargr (ycur)
+ if (nscan () == 2) {
+ ncount = ncount + 1
+ num = num + 1
+ }
+ } else
+ ncount = EOF
+
+ # Move the cursor.
+ if (gd != NULL && (ncount == nskip || ncount == EOF)) {
+ iferr {
+ call greactivate (gd, 0)
+ call gscur (gd, xcur, ycur)
+ call gdeactivate (gd, 0)
+ } then
+ ;
+ }
+
+ } until (ncount == EOF || ncount == nskip)
+
+ call sfree (sp)
+
+ if (ncount == EOF) {
+ return (EOF)
+ } else if (nskip == req_num) {
+ num = ncount
+ return (ncount)
+ } else {
+ return (num)
+ }
+end
diff --git a/noao/digiphot/apphot/aputil/apgtools.x b/noao/digiphot/apphot/aputil/apgtools.x
new file mode 100644
index 00000000..e35cb543
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/apgtools.x
@@ -0,0 +1,141 @@
+include <gset.h>
+include <pkg/gtools.h>
+
+# AP_GTINIT -- Initialize the gtools package for the apphot routines.
+
+pointer procedure ap_gtinit (image, wx, wy)
+
+char image[ARB] # the image name
+real wx, wy # center of sky subraster
+
+pointer sp, gt, str
+pointer gt_init()
+
+begin
+ # Allocate working space.
+ gt = gt_init ()
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Set the plot title.
+ call sprintf (Memc[str], SZ_LINE, "Image: %s: %.2f %.2f\n")
+ call pargstr (image)
+ call pargr (wx)
+ call pargr (wy)
+ call gt_sets (gt, GTTITLE, Memc[str])
+
+ call sfree (sp)
+ return (gt)
+end
+
+
+# AP_GTFREE -- Free the gtools package.
+
+procedure ap_gtfree (gt)
+
+pointer gt # pointer to gtools structure
+
+begin
+ call gt_free (gt)
+end
+
+
+# AP_PLOTRAD -- Plot the radial profile of a list of pixels.
+
+procedure ap_plotrad (gd, gt, r, i, npts, polymark)
+
+pointer gd # pointer to graphics stream
+pointer gt # the GTOOLS pointer
+real r[ARB] # the radii array
+real i[ARB] # the intensity array
+int npts # number of points
+char polymark[ARB] # polyline type
+
+begin
+ call gt_sets (gt, GTTYPE, "mark")
+ call gt_sets (gt, GTMARK, polymark)
+ call gt_plot (gd, gt, r, i, npts)
+end
+
+
+# AP_PLOTPTS -- Plot the radial profile of a list of pixels excluding points
+# that are outside the plotting window altogether.
+
+procedure ap_plotpts (gd, gt, r, i, npts, xmin, xmax, ymin, ymax, polymark)
+
+pointer gd # pointer to graphics stream
+pointer gt # the GTOOLS pointer
+real r[ARB] # the radii array
+real i[ARB] # the intensity array
+int npts # number of points
+real xmin, xmax # the x plot limits
+real ymin, ymax # the y plot limits
+char polymark[ARB] # polyline type
+
+int j
+
+begin
+ call gt_sets (gt, GTTYPE, "mark")
+ call gt_sets (gt, GTMARK, polymark)
+ do j = 1, npts {
+ if (r[j] < xmin || r[j] > xmax)
+ next
+ if (i[j] < ymin || i[j] > ymax)
+ next
+ call gt_plot (gd, gt, r[j], i[j], 1)
+
+ }
+end
+
+
+# AP_RSET -- Set up the parameters for the radial profile plot.
+
+procedure ap_rset (gd, gt, xmin, xmax, ymin, ymax, xscale)
+
+pointer gd # pointer to GRAPHICS stream
+pointer gt # pointer to GTOOLS structure
+real xmin, xmax # min and max of x vector
+real ymin, ymax # min and max of y vector
+real xscale # image scale
+
+pointer sp, str, title
+real vx1, vx2, vy1, vy2, aspect
+real gstatr()
+
+begin
+ call smark (sp)
+ call salloc (title, 3 * SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Reset the aspect ratio.
+ aspect = gstatr (gd, G_ASPECT)
+ call gsetr (gd, G_ASPECT, 0.75)
+
+ # Construct the title.
+ call sysid (Memc[title], 3 * SZ_LINE)
+ call strcat ("\n", Memc[title], 3 * SZ_LINE)
+ call gt_gets (gt, GTTITLE, Memc[str], SZ_LINE)
+ call strcat (Memc[str], Memc[title], 3 * SZ_LINE)
+ call strcat ("\n\n", Memc[title], 3 * SZ_LINE)
+
+ # Draw three axes.
+ call gseti (gd, G_XDRAWAXES, 2)
+ call gswind (gd, xmin / xscale, xmax / xscale, ymin, ymax)
+ call glabax (gd, Memc[title], "", "Intensity")
+
+ # Draw the bottom x axis
+ call gseti (gd, G_YDRAWAXES, 0)
+ call gseti (gd, G_XDRAWAXES, 1)
+ call ggview (gd, vx1, vx2, vy1, vy2)
+ call gsview (gd, vx1, vx2, vy1, vy2)
+ call gswind (gd, xmin, xmax, ymin, ymax)
+ call glabax (gd, "",
+ "Radial Distance (lower-pixels, upper-scale units)", "")
+
+ # Reset to standard gio parameters.
+ call gseti (gd, G_YDRAWAXES, 3)
+ call gseti (gd, G_XDRAWAXES, 3)
+ call gsetr (gd, G_ASPECT, aspect)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aputil/aplucy.x b/noao/digiphot/apphot/aputil/aplucy.x
new file mode 100644
index 00000000..f70a39ed
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/aplucy.x
@@ -0,0 +1,47 @@
+# AP_LUCY_SMOOTH - Lucy smooth a histogram with a box shaped function.
+
+procedure ap_lucy_smooth (hgm, shgm, nbins, nker, iter)
+
+real hgm[ARB] # the original histogram
+real shgm[ARB] # smoothed histogram
+int nbins # length of the histogram
+int nker # length of box kernel
+int iter # number of iterations
+
+int i, j, nsmooth
+pointer sp, work1, work2
+real ap_diverr()
+
+begin
+ # Allocate space and clear the work arrays.
+ call smark (sp)
+ call salloc (work1, nbins, TY_REAL)
+ call salloc (work2, nbins, TY_REAL)
+ call aclrr (Memr[work1], nbins)
+ call aclrr (Memr[work2], nbins)
+ call aclrr (shgm, nbins)
+
+ # Compute the smoothing length and initialize output array.
+ nsmooth = nbins - nker + 1
+ #call ap_aboxr (hgm, shgm[1+nker/2], nsmooth, nker)
+ call ap_sboxr (hgm, shgm, nbins, nker)
+
+ # Iterate on the solution.
+ do i = 1, iter {
+ #call ap_aboxr (shgm, Memr[work1+nker/2], nsmooth, nker)
+ call ap_sboxr (shgm, Memr[work1], nbins, nker)
+ #do j = 1 + nker / 2, nsmooth + nker / 2 {
+ do j = 1, nbins {
+ if (Memr[work1+j-1] == 0.0)
+ Memr[work1+j-1] = ap_diverr ()
+ else
+ #Memr[work1+j-1] = hgm[j] / Memr[work1+j-1]
+ Memr[work1+j-1] = shgm[j] / Memr[work1+j-1]
+ }
+ #call ap_aboxr (Memr[work1], Memr[work2+nker/2], nsmooth, nker)
+ call ap_sboxr (Memr[work1], Memr[work2], nbins, nker)
+ call amulr (shgm, Memr[work2], shgm, nbins)
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/aputil/apmapr.x b/noao/digiphot/apphot/aputil/apmapr.x
new file mode 100644
index 00000000..0d4159ab
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/apmapr.x
@@ -0,0 +1,21 @@
+# APMAPR -- Vector linear transformation. Map the range of pixel values
+# a1, a2 from a into the range b1, b2 into b. It is assumed that a1 < a2
+# and b1 < b2.
+
+real procedure apmapr (a, a1, a2, b1, b2)
+
+real a # the value to be mapped
+real a1, a2 # the numbers specifying the input data range
+real b1, b2 # the numbers specifying the output data range
+
+real minout, maxout, aoff, boff
+real scalar
+
+begin
+ scalar = (real (b2) - real (b1)) / (real (a2) - real (a1))
+ minout = min (b1, b2)
+ maxout = max (b1, b2)
+ aoff = a1
+ boff = b1
+ return (max(minout, min(maxout, real((a - aoff) * scalar) + boff)))
+end
diff --git a/noao/digiphot/apphot/aputil/apmeds.x b/noao/digiphot/apphot/aputil/apmeds.x
new file mode 100644
index 00000000..0a206c8a
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/apmeds.x
@@ -0,0 +1,154 @@
+# APSMED -- Compute the averaged median given a sorted array and an averaging
+# half width.
+
+real procedure apsmed (pix, index, npts, medcut)
+
+real pix[ARB] # array of sky pixels
+int index[ARB] # sorted index array
+int npts # number of pixels
+int medcut # averaging half width
+
+int med, j, nmed, medlo, medhi
+real sumed
+
+begin
+ med = (npts + 1) / 2
+ if (mod (med, 2) == 1) {
+ medlo = max (1, med - medcut)
+ medhi = min (npts, med + medcut)
+ } else {
+ medlo = max (1, med - medcut)
+ medhi = min (npts, med + medcut + 1)
+ }
+
+ sumed = 0.0
+ nmed = 0
+ do j = medlo, medhi {
+ sumed = sumed + pix[index[j]]
+ nmed = nmed + 1
+ }
+
+ return (sumed / nmed)
+end
+
+
+# APIMED -- Compute the index of new median value. Weight is an arbitrary
+# weight array which is assumed to be zero if the pixels has been rejected
+# and is positive otherwise.
+
+int procedure apimed (weight, index, lo, hi, nmed)
+
+real weight[ARB] # array of weights
+int index[ARB] # array of sorted indices
+int lo, hi # ranges of weights
+int nmed # number of good sky pixels
+
+int npts, med
+
+begin
+ npts = 0
+ for (med = lo; med <= hi && npts < nmed; med = med + 1) {
+ if (weight[index[med]] > 0.0)
+ npts = npts + 1
+ }
+
+ if (npts == 0)
+ return (0)
+ else
+ return (med)
+end
+
+
+# APWSMED -- Compute the new averaged median given a sorted input array,
+# an averaging half-width, and assuming that there has been pixel rejection.
+
+real procedure apwsmed (pix, index, weight, npix, med, medcut)
+
+real pix[ARB] # pixel values array
+int index[ARB] # sorted indices array
+real weight[ARB] # the weights array
+int npix # number of pixels
+int med # index of median value
+int medcut # of median cut
+
+int j, nmed, maxmed
+real sumed
+
+begin
+ sumed = pix[index[med]]
+ if (mod (med, 2) == 1)
+ maxmed = 2 * medcut + 1
+ else
+ maxmed = 2 * medcut + 2
+
+ nmed = 1
+ for (j = med - 1; j >= 1; j = j - 1) {
+ if (nmed >= medcut + 1)
+ break
+ if (weight[index[j]] > 0.0) {
+ sumed = sumed + pix[index[j]]
+ nmed = nmed + 1
+ }
+ }
+ for (j = med + 1; j <= npix; j = j + 1) {
+ if (nmed >= maxmed)
+ break
+ if (weight[index[j]] > 0.0) {
+ sumed = sumed + pix[index[j]]
+ nmed = nmed + 1
+ }
+ }
+
+ return (sumed / nmed)
+end
+
+
+# APMEDR -- Vector median selection. The selection is carried out in a temporary
+# array, leaving the input vector unmodified. Especially demanding applications
+# may wish to call the asok routine directory to avoid the call to the memory
+# allocator.
+
+real procedure apmedr (a, index, npix)
+
+real a[ARB] # input array of values
+int index[ARB] # sorted index array
+int npix # number of pixels
+
+int i
+pointer sp, aa
+real median
+real asokr() # select the Kth smallest element from A
+
+begin
+ switch (npix) {
+ case 1, 2:
+ return (a[1])
+
+ case 3:
+ if (a[1] < a[2]) {
+ if (a[2] < a[3])
+ return (a[2])
+ else if (a[1] < a[3])
+ return (a[3])
+ else
+ return (a[1])
+ } else {
+ if (a[2] > a[3])
+ return (a[2])
+ else if (a[1] < a[3])
+ return (a[1])
+ else
+ return (a[3])
+ }
+
+ default:
+ call smark (sp)
+ call salloc (aa, npix, TY_REAL)
+ do i = 1, npix
+ Memr[aa+i-1] = a[index[i]]
+ median = asokr (Memr[aa], npix, (npix + 1) / 2)
+ call sfree (sp)
+
+ return (median)
+ }
+end
diff --git a/noao/digiphot/apphot/aputil/apmoments.x b/noao/digiphot/apphot/aputil/apmoments.x
new file mode 100644
index 00000000..5a1bfbd4
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/apmoments.x
@@ -0,0 +1,138 @@
+# APMOMENTS -- Procedure to compute the first three moments of a
+# distribution given the appropriate sums.
+
+procedure apmoments (sumpx, sumsqpx, sumcbpx, npix, sky_zero, mean, sigma, skew)
+
+double sumpx # sum of the pixels
+double sumsqpx # sum of pixels squared
+double sumcbpx # sum of cubes of pixels
+int npix # number of pixels
+real sky_zero # sky zero point for moment analysis
+real mean # mean of pixels
+real sigma # sigma of pixels
+real skew # skew of pixels
+
+double dmean, dsigma, dskew
+
+begin
+ # Recompute the moments.
+ dmean = sumpx / npix
+ dsigma = sumsqpx / npix - dmean ** 2
+ if (dsigma <= 0.0d0) {
+ sigma = 0.0
+ skew = 0.0
+ } else {
+ dskew = sumcbpx / npix - 3.0d0 * dmean * dsigma - dmean ** 3
+ sigma = sqrt (dsigma)
+ if (dskew < 0.0d0)
+ skew = - (abs (dskew) ** (1.0d0 / 3.0d0))
+ else if (dskew > 0.0d0)
+ skew = dskew ** (1.0d0 / 3.0d0)
+ else
+ skew = 0.0
+ }
+ mean = sky_zero + dmean
+end
+
+
+# APFMOMENTS -- Procedure to compute the first three moments of a distribution
+# given the data. The sums are returned as well.
+
+procedure apfmoments (pix, npix, sky_zero, sumpx, sumsqpx, sumcbpx, mean,
+ sigma, skew)
+
+real pix[npix] # array of pixels
+int npix # number of pixels
+real sky_zero # sky zero point for moment analysis
+double sumpx # sum of the pixels
+double sumsqpx # sum of pixels squared
+double sumcbpx # sum of cubes of pixels
+real mean # mean of pixels
+real sigma # sigma of pixels
+real skew # skew of pixels
+
+double dpix, dmean, dsigma, dskew
+int i
+
+begin
+ # Zero and accumulate the sums.
+ sumpx = 0.0d0
+ sumsqpx = 0.0d0
+ sumcbpx = 0.0d0
+ do i = 1, npix {
+ dpix = pix[i] - sky_zero
+ sumpx = sumpx + dpix
+ sumsqpx = sumsqpx + dpix * dpix
+ sumcbpx = sumcbpx + dpix * dpix * dpix
+ }
+
+ # Compute the moments.
+ dmean = sumpx / npix
+ dsigma = sumsqpx / npix - dmean ** 2
+ if (dsigma <= 0.0) {
+ sigma = 0.0
+ skew = 0.0
+ } else {
+ dskew = sumcbpx / npix - 3.0d0 * dmean * dsigma - dmean ** 3
+ sigma = sqrt (dsigma)
+ if (dskew < 0.0d0)
+ skew = - (abs (dskew) ** (1.0d0 / 3.0d0))
+ else if (dskew > 0.0d0)
+ skew = dskew ** (1.0d0 / 3.0d0)
+ else
+ skew = 0.0
+ }
+ mean = sky_zero + dmean
+end
+
+
+# APFIMOMENTS -- Procedure to compute the first three moments of a distribution
+# given the data. The sums are returned as well.
+
+procedure apfimoments (pix, index, npix, sky_zero, sumpx, sumsqpx, sumcbpx,
+ mean, sigma, skew)
+
+real pix[ARB] # array of pixels
+int index[ARB] # the index array
+int npix # number of pixels
+real sky_zero # sky zero point for moment analysis
+double sumpx # sum of the pixels
+double sumsqpx # sum of pixels squared
+double sumcbpx # sum of cubes of pixels
+real mean # mean of pixels
+real sigma # sigma of pixels
+real skew # skew of pixels
+
+double dpix, dmean, dsigma, dskew
+int i
+
+begin
+ # Zero and accumulate the sums.
+ sumpx = 0.0d0
+ sumsqpx = 0.0d0
+ sumcbpx = 0.0d0
+ do i = 1, npix {
+ dpix = pix[index[i]] - sky_zero
+ sumpx = sumpx + dpix
+ sumsqpx = sumsqpx + dpix * dpix
+ sumcbpx = sumcbpx + dpix * dpix * dpix
+ }
+
+ # Compute the moments.
+ dmean = sumpx / npix
+ dsigma = sumsqpx / npix - dmean ** 2
+ if (dsigma <= 0.0d0) {
+ sigma = 0.0
+ skew = 0.0
+ } else {
+ dskew = sumcbpx / npix - 3.0d0 * dmean * dsigma - dmean ** 3
+ sigma = sqrt (dsigma)
+ if (dskew < 0.0d0)
+ skew = - (abs (dskew) ** (1.0d0 / 3.0d0))
+ else if (dskew > 0.0d0)
+ skew = dskew ** (1.0d0 / 3.0d0)
+ else
+ skew = 0.0
+ }
+ mean = dmean + sky_zero
+end
diff --git a/noao/digiphot/apphot/aputil/apnlfuncs.x b/noao/digiphot/apphot/aputil/apnlfuncs.x
new file mode 100644
index 00000000..290b9e90
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/apnlfuncs.x
@@ -0,0 +1,375 @@
+
+include <math.h>
+include <mach.h>
+
+# CGAUSS1D - Compute the value of a 1-D Gaussian function on a constant
+# background.
+
+procedure cgauss1d (x, nvars, p, np, z)
+
+real x[ARB] # variables, x[1] = position coordinate
+int nvars # the number of variables, not used
+real p[ARB] # p[1]=amplitude p[2]=center p[3]=variance p[4]=sky
+int np # number of parameters np = 4
+real z # function return
+
+real r2
+
+begin
+ if (p[3] == 0.)
+ r2 = 36.0
+ else
+ r2 = (x[1] - p[2]) ** 2 / (2. * p[3])
+ if (abs (r2) > 25.0)
+ z = p[4]
+ else
+ z = p[1] * exp (-r2) + p[4]
+end
+
+
+# CDGAUSS1D -- Compute the value a 1-D Gaussian profile on a constant
+# background and its derivatives.
+
+procedure cdgauss1d (x, nvars p, dp, np, z, der)
+
+real x[ARB] # variables, x[1] = position coordinate
+int nvars # the number of variables, not used
+real p[ARB] # p[1]=amplitude, p[2]=center, p[3]=sky p[4]=variance
+real dp[ARB] # parameter derivatives
+int np # number of parameters np=4
+real z # function value
+real der[ARB] # derivatives
+
+real dx, r2
+
+begin
+ dx = x[1] - p[2]
+ if (p[3] == 0.)
+ r2 = 36.0
+ else
+ r2 = dx * dx / (2.0 * p[3])
+ if (abs (r2) > 25.0) {
+ z = p[4]
+ der[1] = 0.0
+ der[2] = 0.0
+ der[3] = 0.0
+ der[4] = 1.0
+ } else {
+ der[1] = exp (-r2)
+ z = p[1] * der[1]
+ der[2] = z * dx / p[3]
+ der[3] = z * r2 / p[3]
+ der[4] = 1.0
+ z = z + p[4]
+ }
+end
+
+
+# GAUSSR -- Compute the value of a 2-D radially symmetric Gaussian profile
+# which is assumed to be sitting on a constant background.
+
+# Parameter Allocation:
+# 1 Amplitude
+# 2 X-center
+# 3 Y-center
+# 4 Variance
+# 5 Sky
+
+procedure gaussr (x, nvars, p, np, z)
+
+real x[ARB] # the input variables
+int nvars # the number of variables
+real p[np] # parameter vector
+int np # number of parameters
+real z # function return
+
+real dx, dy, r2
+
+begin
+ dx = x[1] - p[2]
+ dy = x[2] - p[3]
+ if (p[4] == 0.)
+ r2 = 36.0
+ else
+ r2 = (dx * dx + dy * dy) / (2.0 * p[4])
+ if (abs (r2) > 25.0)
+ z = p[5]
+ else
+ z = p[1] * exp (- r2) + p[5]
+end
+
+
+# DGAUSSR -- Compute the value of a 2-D Gaussian profile and its derivatives
+# which assumed to be sitting on top of a constant background.
+
+procedure dgaussr (x, nvars, p, dp, np, z, der)
+
+real x[ARB] # the input variables
+int nvars # the number of variables
+real p[np] # parameter vector
+real dp[np] # dummy array of parameter increments
+int np # number of parameters
+real z # function return
+real der[np] # derivatives
+
+real dx, dy, r2
+
+begin
+ dx = x[1] - p[2]
+ dy = x[2] - p[3]
+ if (p[4] == 0.)
+ r2 = 36.0
+ else
+ r2 = (dx * dx + dy * dy) / (2.0 * p[4])
+
+ if (abs (r2) > 25.0) {
+ z = p[5]
+ der[1] = 0.0
+ der[2] = 0.0
+ der[3] = 0.0
+ der[4] = 0.0
+ der[5] = 1.0
+ } else {
+ der[1] = exp (-r2)
+ z = p[1] * der[1]
+ der[2] = z * dx / p[4]
+ der[3] = z * dy / p[4]
+ der[4] = z * r2 / p[4]
+ z = z + p[5]
+ der[5] = 1.0
+ }
+end
+
+
+# ELGAUSS -- Compute the value of a 2-D elliptical Gaussian function which
+# is assumed to be sitting on top of a constant background.
+
+# Parameter Allocation:
+# 1 Amplitude
+# 2 X-center
+# 3 Y-center
+# 4 Variance-x
+# 5 Variance-y
+# 6 Theta-rotation
+# 7 Sky
+
+procedure elgauss (x, nvars, p, np, z)
+
+real x[ARB] # input variables, x[1] = x, x[2] = y
+int nvars # number of variables, not used
+real p[np] # parameter vector
+int np # number of parameters
+real z # function return
+
+real dx, dy, crot, srot, xt, yt, r2
+
+begin
+ dx = x[1] - p[2]
+ dy = x[2] - p[3]
+ crot = cos (p[6])
+ srot = sin (p[6])
+ xt = (dx * crot + dy * srot)
+ yt = (-dx * srot + dy * crot)
+ if (p[4] == 0. || p[5] == 0.)
+ r2 = 36.0
+ else
+ r2 = (xt ** 2 / p[4] + yt ** 2 / p[5]) / 2.0
+ if (abs (r2) > 25.0)
+ z = p[7]
+ else
+ z = p[1] * exp (-r2) + p[7]
+end
+
+
+# DELGAUSS -- Compute the value of a 2-D elliptical Gaussian assumed to
+# sitting on top of a constant background and its derivatives.
+
+procedure delgauss (x, nvars, p, dp, np, z, der)
+
+real x[ARB] # input variables, x[1] = x, x[2] = y
+int nvars # number of variables, not used
+real p[np] # parameter vector
+real dp[np] # delta of parameters
+int np # number of parameters
+real z # function value
+real der[np] # function return
+
+real crot, srot, crot2, srot2, sigx2, sigy2, a, b, c
+real dx, dy, dx2, dy2, r2
+
+begin
+ crot = cos (p[6])
+ srot = sin (p[6])
+ crot2 = crot ** 2
+ srot2 = srot ** 2
+ sigx2 = p[4]
+ sigy2 = p[5]
+ if (sigx2 == 0. || sigy2 == 0.)
+ r2 = 36.0
+ else {
+ a = (crot2 / sigx2 + srot2 / sigy2)
+ b = 2.0 * crot * srot * (1.0 / sigx2 - 1.0 /sigy2)
+ c = (srot2 / sigx2 + crot2 / sigy2)
+
+ dx = x[1] - p[2]
+ dy = x[2] - p[3]
+ dx2 = dx ** 2
+ dy2 = dy ** 2
+ r2 = 0.5 * (a * dx2 + b * dx * dy + c * dy2)
+ }
+
+ if (abs (r2) > 25.0) {
+ z = p[7]
+ der[1] = 0.0
+ der[2] = 0.0
+ der[3] = 0.0
+ der[4] = 0.0
+ der[5] = 0.0
+ der[6] = 0.0
+ der[7] = 1.0
+ } else {
+ der[1] = exp (-r2)
+ z = p[1] * der[1]
+ der[2] = z * (2.0 * a * dx + b * dy)
+ der[3] = z * (b * dx + 2.0 * c * dy)
+ der[4] = z * (crot2 * dx2 + 2.0 * crot * srot * dx * dy +
+ srot2 * dy2) / (2.0 * sigx2 * sigx2)
+ der[5] = z * (srot2 * dx2 - 2.0 * crot * srot * dx * dy +
+ crot2 * dy2) / (2.0 * sigy2 * sigy2)
+ der[6] = z * (b * dx2 + 2.0 * (c - a) * dx * dy - b * dy2)
+ z = z + p[7]
+ der[7] = 1.0
+ }
+end
+
+
+
+# GAUSS1D -- Compute the profile of a 1d Gaussian with a background value
+# of zero.
+
+procedure gauss1d (x, nvars, p, np, z)
+
+real x[ARB] # list of variables, x[1] = position coordinate
+int nvars # number of variables
+real p[ARB] # p[1]=amplitude p[2]=center p[3]=sigma
+int np # number of parameters == 3
+real z # function return
+
+real r
+
+begin
+ if (p[3] == 0.)
+ r = 6.0
+ else
+ r = (x[1] - p[2]) / (p[3] * SQRTOF2)
+ if (abs (r) > 5.0)
+ z = 0.0
+ else
+ z = p[1] * exp (- r ** 2)
+end
+
+
+# DGAUSS1D -- Compute the function value and derivatives of a 1-D Gaussian
+# function with a background value of zero.
+
+procedure dgauss1d (x, nvars, p, dp, np, z, der)
+
+real x[ARB] # list of variables, x[1] = position coordinate
+int nvars # number of variables
+real p[ARB] # p[1]=amplitude, p[2]=center, p[3]=sigma
+real dp[ARB] # parameter derivatives
+int np # number of parameters
+real z # function value
+real der[ARB] # derivatives
+
+real r
+
+begin
+ if (p[3] == 0.)
+ r = 6.0
+ else
+ r = (x[1] - p[2]) / (SQRTOF2 * p[3])
+ if (abs (r) > 5.0) {
+ z = 0.0
+ der[1] = 0.0
+ der[2] = 0.0
+ der[3] = 0.0
+ } else {
+ der[1] = exp (- r ** 2)
+ z = der[1] * p[1]
+ der[2] = z * r * SQRTOF2 / p[3]
+ der[3] = der[2] * SQRTOF2 * r
+ }
+end
+
+
+# GAUSSKEW - Compute the value of a 1-D skewed Gaussian profile.
+# The background value is assumed to be zero.
+
+procedure gausskew (x, nvars, p, np, z)
+
+real x[ARB] # list of variables, x[1] = position coordinate
+int nvars # number of variables, not used
+real p[ARB] # p[1]=amplitude p[2]=center p[3]=variance p[4]=skew
+int np # number of parameters == 3
+real z # function return
+
+real dx, r2, r3
+
+begin
+ dx = (x[1] - p[2])
+ if (p[3] == 0.)
+ r2 = 36.0
+ else {
+ r2 = dx ** 2 / (2.0 * p[3])
+ r3 = r2 * dx / sqrt (2.0 * abs (p[3]))
+ }
+ if (abs (r2) > 25.0)
+ z = 0.0
+ else
+ z = (1.0 + p[4] * r3) * p[1] * exp (-r2)
+end
+
+
+# DGAUSSKEW -- Compute the value of a 1-D skewed Gaussian and its derivatives.
+# The background value is assumed to be zero.
+
+procedure dgausskew (x, nvars, p, dp, np, z, der)
+
+real x[ARB] # list of variables, x[1] = position coordinate
+int nvars # number of variables, not used
+real p[ARB] # p[1]=amplitude, p[2]=center, p[3]=variance, p[4]=skew
+real dp[ARB] # parameter derivatives
+int np # number of parameters
+real z # function value
+real der[ARB] # derivatives
+
+real dx, d1, d2, d3, r, r2, r3, rint
+
+begin
+ dx = x[1] - p[2]
+ if (p[3] == 0.)
+ r2 = 36.0
+ else
+ r2 = dx ** 2 / (2.0 * p[3])
+ if (abs (r2) > 25.0) {
+ z = 0.0
+ der[1] = 0.0
+ der[2] = 0.0
+ der[3] = 0.0
+ der[4] = 0.0
+ } else {
+ r = dx / sqrt (2.0 * abs (p[3]))
+ r3 = r2 * r
+ d1 = exp (-r2)
+ z = d1 * p[1]
+ d2 = z * dx / p[3]
+ d3 = z * r2 / p[3]
+ rint = 1.0 + p[4] * r3
+ der[1] = d1 * rint
+ der[2] = d2 * (rint - 1.5 * p[4] * r)
+ der[3] = d3 * (rint - 1.5 * p[4] * r)
+ der[4] = z * r3
+ z = z * rint
+ }
+end
diff --git a/noao/digiphot/apphot/aputil/appcache.x b/noao/digiphot/apphot/aputil/appcache.x
new file mode 100644
index 00000000..d1059583
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/appcache.x
@@ -0,0 +1,83 @@
+include <imhdr.h>
+include <imset.h>
+
+# AP_MEMSTAT -- Figure out if there is enough memory to cache the image
+# pixels. If it is necessary to request more memory and the memory is
+# avalilable return YES otherwise return NO.
+
+int procedure ap_memstat (cache, req_size, old_size)
+
+int cache #I cache memory ?
+int req_size #I the requested working set size in chars
+int old_size #O the original working set size in chars
+
+int cur_size, max_size
+int begmem()
+
+begin
+ # Find the default working set size.
+ cur_size = begmem (0, old_size, max_size)
+
+ # If cacheing is disabled return NO regardless of the working set size.
+ if (cache == NO)
+ return (NO)
+
+ # If the requested working set size is less than the current working
+ # set size return YES.
+ if (req_size <= cur_size)
+ return (YES)
+
+ # Reset the current working set size.
+ cur_size = begmem (req_size, old_size, max_size)
+ if (req_size <= cur_size) {
+ return (YES)
+ } else {
+ return (NO)
+ }
+end
+
+
+# AP_PCACHE -- Cache the image pixels im memory by resetting the default image
+# buffer size. If req_size is INDEF the size of the image is used to determine
+# the size of the image i/o buffers.
+
+procedure ap_pcache (im, req_size, buf_size)
+
+pointer im #I the input image point
+int req_size #I the requested working set size in chars
+int buf_size #O the new image buffer size
+
+int def_size, new_imbufsize
+int sizeof(), imstati()
+
+begin
+ # Find the default buffer size.
+ def_size = imstati (im, IM_BUFSIZE)
+
+ # Return if the image is not 2-dimensional.
+ if (IM_NDIM(im) != 2) {
+ buf_size = def_size
+ return
+ }
+
+ # Compute the new required image i/o buffer size in chars.
+ if (IS_INDEFI(req_size)) {
+ new_imbufsize = IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ } else {
+ new_imbufsize = req_size
+ }
+
+ # If the default image i/o buffer size is already bigger than
+ # the requested size do nothing.
+ if (def_size >= new_imbufsize) {
+ buf_size = def_size
+ return
+ }
+
+ # Reset the image i/o buffer.
+ call imseti (im, IM_BUFSIZE, new_imbufsize)
+ call imseti (im, IM_BUFFRAC, 0)
+ buf_size = new_imbufsize
+ return
+end
diff --git a/noao/digiphot/apphot/aputil/aprmwhite.x b/noao/digiphot/apphot/aputil/aprmwhite.x
new file mode 100644
index 00000000..071ea7ed
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/aprmwhite.x
@@ -0,0 +1,22 @@
+include <ctype.h>
+
+# AP_RMWHITE -- Remove whitespace from a string.
+
+procedure ap_rmwhite (instr, outstr, maxch)
+
+char instr[ARB] # the input string
+char outstr[ARB] # the output string, may be the same as instr
+int maxch # maximum number of characters in outstr
+
+int ip, op
+
+begin
+ op = 1
+ for (ip = 1; (instr[ip] != EOS) && (op <= maxch); ip = ip + 1) {
+ if (IS_WHITE(instr[ip]))
+ next
+ outstr[op] = instr[ip]
+ op = op + 1
+ }
+ outstr[op] = EOS
+end
diff --git a/noao/digiphot/apphot/aputil/aptopt.x b/noao/digiphot/apphot/aputil/aptopt.x
new file mode 100644
index 00000000..0e5bc212
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/aptopt.x
@@ -0,0 +1,232 @@
+include <mach.h>
+include <math.h>
+
+# APTOPT - One-dimensional centering routine using repeated convolutions to
+# locate image center.
+
+define MAX_SEARCH 3 # Max initial search steps
+
+int procedure aptopt (data, npix, center, sigma, tol, maxiter, ortho)
+
+real data[ARB] # initial data
+int npix # number of pixels
+real center # initial guess at center
+real sigma # sigma of Gaussian
+real tol # gap tolerance for sigma
+int maxiter # maximum number of iterations
+int ortho # orthogonalize weighting vector
+
+int i, iter
+pointer sp, wgt
+real newx, x[3], news, s[3], delx
+real adotr(), apqzero()
+
+begin
+ if (sigma <= 0.0)
+ return (-1)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (wgt, npix, TY_REAL)
+
+ # Initialize.
+ x[1] = center
+ call mkt_prof_derv (Memr[wgt], npix, x[1], sigma, ortho)
+ s[1] = adotr (Memr[wgt], data, npix)
+ #if (abs (s[1]) <= EPSILONR) {
+ if (s[1] == 0.0) {
+ center = x[1]
+ call sfree (sp)
+ return (0)
+ } else
+ s[3] = s[1]
+
+ # Search for the correct interval.
+ for (i = 1; (s[3] * s[1] >= 0.0) && (i <= MAX_SEARCH); i = i + 1) {
+ s[3] = s[1]
+ x[3] = x[1]
+ x[1] = x[3] + sign (sigma, s[3])
+ call mkt_prof_derv (Memr[wgt], npix, x[1], sigma, ortho)
+ s[1] = adotr (Memr[wgt], data, npix)
+ #if (abs (s[1]) <= EPSILONR) {
+ if (s[1] == 0.0) {
+ center = x[1]
+ call sfree (sp)
+ return (0)
+ }
+ }
+
+ # Location not bracketed.
+ if (s[3] * s[1] > 0.0) {
+ call sfree (sp)
+ return (-1)
+ }
+
+ # Intialize the quadratic search.
+ delx = x[1] - x[3]
+ x[2] = x[3] - s[3] * delx / (s[1] - s[3])
+ call mkt_prof_derv (Memr[wgt], npix, x[2], sigma, ortho)
+ s[2] = adotr (Memr[wgt], data, npix)
+ #if (abs (s[2]) <= EPSILONR) {
+ if (s[2] == 0.0) {
+ center = x[2]
+ call sfree (sp)
+ return (1)
+ }
+
+ # Search quadratically.
+ for (iter = 2; iter <= maxiter; iter = iter + 1) {
+
+ # Check for completion.
+ #if (abs (s[2]) <= EPSILONR)
+ if (s[2] == 0.0)
+ break
+ if (abs (x[2] - x[1]) <= tol)
+ break
+ if (abs (x[3] - x[2]) <= tol)
+ break
+
+ # Compute new intermediate value.
+ newx = x[1] + apqzero (x, s)
+ call mkt_prof_derv (Memr[wgt], npix, newx, sigma, ortho)
+ news = adotr (Memr[wgt], data, npix)
+
+ if (s[1] * s[2] > 0.0) {
+ s[1] = s[2]
+ x[1] = x[2]
+ s[2] = news
+ x[2] = newx
+ } else {
+ s[3] = s[2]
+ x[3] = x[2]
+ s[2] = news
+ x[2] = newx
+ }
+ }
+
+ # Evaluate the center.
+ center = x[2]
+ call sfree (sp)
+ return (iter)
+end
+
+
+# AP_TPROFDER -- Procedure to estimate the approximating triangle function
+# and its derivatives.
+
+procedure ap_tprofder (data, der, npix, center, sigma, ampl)
+
+real data[ARB] # input data
+real der[ARB] # derivatives
+int npix # number of pixels
+real center # center of input Gaussian function
+real sigma # sigma of input Gaussian function
+real ampl # amplitude
+
+int i
+real x, xabs, width
+
+begin
+ width = sigma * 2.35
+ do i = 1, npix {
+ x = (i - center) / width
+ xabs = abs (x)
+ if (xabs <= 1.0) {
+ data[i] = ampl * (1.0 - xabs)
+ der[i] = x * data[i]
+ } else {
+ data[i] = 0.0
+ der[i] = 0.0
+ }
+ }
+end
+
+
+# MKT_PROF_DERV - Make orthogonal profile derivative vector.
+
+procedure mkt_prof_derv (weight, npix, center, sigma, norm)
+
+real weight[ARB] # input weight
+int npix # number of pixels
+real center # center
+real sigma # center
+int norm # orthogonalise weight
+
+pointer sp, der
+real coef
+real asumr(), adotr()
+
+begin
+ call smark (sp)
+ call salloc (der, npix, TY_REAL)
+
+ # Fetch the weighting function and derivatives.
+ call ap_tprofder (Memr[der], weight, npix, center, sigma, 1.0)
+
+ if (norm == YES) {
+
+ # Make orthogonal to level background.
+ coef = -asumr (weight, npix) / npix
+ call aaddkr (weight, coef, weight, npix)
+ coef = -asumr (Memr[der], npix) / npix
+ call aaddkr (Memr[der], coef, Memr[der], npix)
+
+ # Make orthogonal to profile vector.
+ coef = adotr (Memr[der], Memr[der], npix)
+ if (coef <= 0.0)
+ coef = 1.0
+ else
+ coef = adotr (weight, Memr[der], npix) / coef
+ call amulkr (Memr[der], coef, Memr[der], npix)
+ call asubr (weight, Memr[der], weight, npix)
+
+ # Normalize the final vector.
+ coef = adotr (weight, weight, npix)
+ if (coef <= 0.0)
+ coef = 1.0
+ else
+ coef = sqrt (1.0 / coef)
+ call amulkr (weight, coef, weight, npix)
+ }
+
+ call sfree (sp)
+end
+
+define QTOL .125
+
+# APQZERO - Solve for the root of a quadratic function defined by three
+# points.
+
+real procedure apqzero (x, y)
+
+real x[3]
+real y[3]
+
+real a, b, c, det, dx
+real x2, x3, y2, y3
+
+begin
+ # Compute the determinant.
+ x2 = x[2] - x[1]
+ x3 = x[3] - x[1]
+ y2 = y[2] - y[1]
+ y3 = y[3] - y[1]
+ det = x2 * x3 * (x2 - x3)
+
+ # Compute the shift in x.
+ #if (abs (det) > 100.0 * EPSILONR) {
+ if (abs (det) > 0.0) {
+ a = (x3 * y2 - x2 * y3) / det
+ b = - (x3 * x3 * y2 - x2 * x2 * y3) / det
+ c = a * y[1] / (b * b)
+ if (abs (c) > QTOL)
+ dx = (-b / (2.0 * a)) * (1.0 - sqrt (1.0 - 4.0 * c))
+ else
+ dx = - (y[1] / b) * (1.0 + c)
+ return (dx)
+ #} else if (abs (y3) > EPSILONR)
+ } else if (abs (y3) > 0.0)
+ return (-y[1] * x3 / y3)
+ else
+ return (0.0)
+end
diff --git a/noao/digiphot/apphot/aputil/apvectors.x b/noao/digiphot/apphot/aputil/apvectors.x
new file mode 100644
index 00000000..7c9dbcfd
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/apvectors.x
@@ -0,0 +1,515 @@
+
+# AP_ABOXR -- Vector boxcar smooth. The input vector is convolved with a
+# uniform kernel of length knpix. Boundary extension is assumed to have
+# been performed on the input array before entering the routine.
+
+procedure ap_aboxr (in, out, npix, knpix)
+
+real in[npix+knpix-1] # input array with boundary exntension
+real out[npix] # output array
+int npix # number of pixels
+int knpix # length of the kernel
+
+int i
+real sum
+
+begin
+ sum = 0.0
+ do i = 1, knpix - 1
+ sum = sum + in[i]
+
+ do i = 1, npix {
+ sum = sum + in[i+knpix-1]
+ out[i] = sum / knpix
+ sum = sum - in[i]
+ }
+
+end
+
+
+# AP_SBOXR -- Boxcar smooth for a vector that has not been boundary
+# extended.
+
+procedure ap_sboxr (in, out, npix, nsmooth)
+
+real in[npix] # input array
+real out[npix] # output array
+int npix # number of pixels
+int nsmooth # half width of smoothing box
+
+int i, j, ib, ie, ns
+real sum
+
+begin
+ ns = 2 * nsmooth + 1
+ do i = 1, npix {
+ ib = max (i - nsmooth, 1)
+ ie = min (i + nsmooth, npix)
+ sum = 0.0
+ do j = ib, ie
+ sum = sum + in[j]
+ out[i] = sum / ns
+ }
+end
+
+
+# AP_ALIMR -- Compute the maximum and minimum data values and indices of a
+# 1D array.
+
+procedure ap_alimr (data, npts, mindat, maxdat, imin, imax)
+
+real data[npts] # data array
+int npts # number of points
+real mindat, maxdat # min and max data value
+int imin, imax # indices of min and max data values
+
+int i
+
+begin
+ imin = 1
+ imax = 1
+ mindat = data[1]
+ maxdat = data[1]
+
+ do i = 2, npts {
+ if (data[i] > maxdat) {
+ imax = i
+ maxdat = data[i]
+ }
+ if (data[i] < mindat) {
+ imin = i
+ mindat = data[i]
+ }
+ }
+end
+
+
+# AP_IALIMR -- Compute the maximum and minimum data values of a 1D indexed
+# array
+
+procedure ap_ialimr (data, index, npts, mindat, maxdat)
+
+real data[npts] # data array
+int index[npts] # index array
+int npts # number of points
+real mindat, maxdat # min and max data value
+
+int i
+
+begin
+ mindat = data[index[1]]
+ maxdat = data[index[1]]
+ do i = 2, npts {
+ if (data[index[i]] > maxdat)
+ maxdat = data[index[i]]
+ if (data[index[i]] < mindat)
+ mindat = data[index[i]]
+ }
+end
+
+
+# AP_ASUMR - Compute the sum of an index sorted array
+
+real procedure ap_asumr (data, index, npts)
+
+real data[npts] # data array
+int index[npts] # index array
+int npts # number of points
+
+double sum
+int i
+
+begin
+ sum = 0.0d0
+ do i = 1, npts
+ sum = sum + data[index[i]]
+ return (real (sum))
+end
+
+
+# AP_AMAXEL -- Find the maximum value and its index of a 1D array.
+
+procedure ap_amaxel (a, npts, maxdat, imax)
+
+real a[ARB] # the data array
+int npts # number of points
+real maxdat # maximum value
+int imax # imdex of max value
+
+int i
+
+begin
+ maxdat = a[1]
+ imax = 1
+ do i = 2, npts {
+ if (a[i] > maxdat) {
+ maxdat = a[i]
+ imax = i
+ }
+ }
+end
+
+
+# AHGMR -- Accumulate the histogram of the input vector. The output vector
+# hgm (the histogram) should be cleared prior to the first call. The procedure
+# returns the number of data values it could not include in the histogram.
+
+int procedure aphgmr (data, wgt, npix, hgm, nbins, z1, z2)
+
+real data[ARB] # data vector
+real wgt[ARB] # weights vector
+int npix # number of pixels
+real hgm[ARB] # output histogram
+int nbins # number of bins in histogram
+real z1, z2 # greyscale values of first and last bins
+
+real dz
+int bin, i, nreject
+
+begin
+ if (nbins < 2)
+ return (0)
+
+ nreject = 0
+ dz = real (nbins - 1) / real (z2 - z1)
+ do i = 1, npix {
+ if (data[i] < z1 || data[i] > z2) {
+ nreject = nreject + 1
+ wgt[i] = 0.0
+ next
+ }
+ bin = int ((data[i] - z1) * dz) + 1
+ hgm[bin] = hgm[bin] + 1.0
+ }
+
+ return (nreject)
+end
+
+
+# APHIGMR -- Accumulate the histogram of the input vector. The output vector
+# hgm (the histogram) should be cleared prior to the first call. The procedure
+# returns the number of data values it could not include in the histogram.
+
+int procedure aphigmr (data, wgt, index, npix, hgm, nbins, z1, z2)
+
+real data[ARB] # data vector
+real wgt[ARB] # weights vector
+int index[ARB] # index vector
+int npix # number of pixels
+real hgm[ARB] # output histogram
+int nbins # number of bins in histogram
+real z1, z2 # greyscale values of first and last bins
+
+real dz
+int bin, i, nreject
+
+begin
+ if (nbins < 2)
+ return (0)
+
+ nreject = 0
+ dz = real (nbins - 1) / real (z2 - z1)
+ do i = 1, npix {
+ if (data[index[i]] < z1 || data[index[i]] > z2) {
+ nreject = nreject + 1
+ wgt[index[i]] = 0.0
+ next
+ }
+ bin = int ((data[index[i]] - z1) * dz) + 1
+ hgm[bin] = hgm[bin] + 1.0
+ }
+
+ return (nreject)
+end
+
+
+# AP_IJTOR -- Compute radius values given the center coordinates, the line
+# number in a the subraster and the length of the subraster x axis.
+
+procedure ap_ijtor (r, nr, line, xc, yc)
+
+real r[nr] # array of output r values
+int nr # length of r array
+int line # line number
+real xc, yc # subraster center
+
+int i
+real temp
+
+begin
+ temp = (line - yc ) ** 2
+ do i = 1, nr
+ r[i] = sqrt ((i - xc) ** 2 + temp)
+end
+
+
+# AP_IJTOR2 -- Compute radius values given the center coordinates and the size
+# of the subraster.
+
+procedure ap_ijtor2 (r, nx, ny, xc, yc)
+
+real r[nx,ARB] # array of output r values
+int nx # x dimension of output array
+int ny # Y dimension of output array
+real xc, yc # subraster center
+
+int i, j
+real temp
+
+begin
+ do j = 1, ny {
+ temp = (j - yc) ** 2
+ do i = 1, nx
+ r[i,j] = sqrt ((i - xc) ** 2 + temp)
+ }
+end
+
+
+# AP_2DALIMR -- Compute min and max values of a 2D array along with
+# the indices of the minimum and maximum pixel.
+
+procedure ap_2dalimr (data, nx, ny, mindat, maxdat, imin, jmin, imax, jmax)
+
+real data[nx, ny] # data
+int nx, ny # array dimensions
+real mindat, maxdat # min, max data values
+int imin, jmin # indices of min element
+int imax, jmax # indices of max element
+
+int i, j
+
+begin
+ imin = 1
+ jmin = 1
+ imax = 1
+ jmax = 1
+ mindat = data[1,1]
+ maxdat = data[1,1]
+
+ do j = 2, ny {
+ do i = 1, nx {
+ if (data[i,j] < mindat) {
+ imin = i
+ jmin = j
+ mindat = data[i,j]
+ } else if (data[i,j] > maxdat) {
+ imax = i
+ jmax = j
+ maxdat = data[i,j]
+ }
+ }
+ }
+end
+
+
+define LOGPTR 20 # log2(maxpts) (1e6)
+
+# APQSORT -- Vector Quicksort. In this version the index array is
+# sorted.
+
+procedure apqsort (data, a, b, npix)
+
+real data[ARB] # data array
+int a[ARB], b[ARB] # index array
+int npix # number of pixels
+
+int i, j, lv[LOGPTR], p, uv[LOGPTR], temp
+real pivot
+
+begin
+ # Initialize the indices for an inplace sort.
+ do i = 1, npix
+ a[i] = i
+ call amovi (a, b, npix)
+
+ 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[b[j]]
+
+ while (i < j) {
+ for (i=i+1; data[b[i]] < pivot; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (data[b[j]] <= pivot)
+ break
+ if (i < j) { # out of order pair
+ temp = b[j] # interchange elements
+ b[j] = b[i]
+ b[i] = temp
+ }
+ }
+
+ j = uv[p] # move pivot to position i
+ temp = b[j] # interchange elements
+ b[j] = b[i]
+ b[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
+ }
+ }
+end
+
+
+
+# APRECIPROCAL -- Compute the reciprocal of the absolute value of a vector.
+
+procedure apreciprocal (a, b, npts, value)
+
+real a[ARB] # the input vector
+real b[ARB] # the output vector
+int npts # the number of data points
+real value # the value to be assigned to b[i] if a[i] = 0
+
+int i
+
+begin
+ do i = 1, npts {
+ if (a[i] > 0.0)
+ b[i] = 1.0 / a[i]
+ else if (a[i] < 0.0)
+ b[i] = - 1.0 / a[i]
+ else
+ b[i] = value
+ }
+end
+
+
+# AP_WLIMR -- Set the weights of all data points outside a given minimum and
+# maximum values to zero. Compute the minimum and maximum values and their
+# indices of the remaining data.
+
+procedure ap_wlimr (pix, w, npts, datamin, datamax, dmin, dmax, imin, imax)
+
+real pix[ARB] # input pixel array
+real w[ARB] # weight array
+int npts # number of points
+real datamin # minimum good data point
+real datamax # maximum good data point
+real dmin # output data minimum
+real dmax # output data maximum
+int imin # index of the data minimum
+int imax # index of the data maximum
+
+int i
+real value
+
+begin
+ dmin = datamax
+ dmax = datamin
+ imin = 1
+ imax = 1
+
+ do i = 1, npts {
+ value = pix[i]
+ if ((value < datamin) || (value > datamax)) {
+ w[i] = 0.0
+ next
+ }
+ if (value < dmin) {
+ dmin = value
+ imin = i
+ } else if (value > dmax) {
+ dmax = value
+ imax = i
+ }
+ }
+end
+
+
+# APWSSQR -- Compute the weighted sum of the squares of a vector.
+
+real procedure apwssqr (a, wgt, npts)
+
+real a[ARB] # data array
+real wgt[ARB] # array of weights
+int npts # number of points
+
+int i
+real sum
+
+begin
+ sum = 0.0
+ do i = 1, npts
+ sum = sum + wgt[i] * a[i] * a[i]
+ return (sum)
+end
+
+
+# AP_XYTOR -- Change the single integer coord of the sky pixels to a radial
+# distance value. The integer coordinate is equal to coord = (i - xc + 1) +
+# blklen * (j - yc).
+
+procedure ap_xytor (coords, index, r, nskypix, xc, yc, blklen)
+
+int coords[ARB] # coordinate array
+int index[ARB] # the index array
+real r[ARB] # radial coordinates
+int nskypix # number of sky pixels
+real xc, yc # center of sky subraster
+int blklen # x dimension of sky subraster
+
+int i
+real x, y
+
+begin
+ do i = 1, nskypix {
+ x = real (mod (coords[index[i]], blklen))
+ if (x == 0)
+ x = real (blklen)
+ y = (coords[index[i]] - x) / blklen + 1
+ r[i] = sqrt ((x - xc) ** 2 + (y - yc) ** 2)
+ }
+end
+
+
+# AP_W1SUR -- Linearly combine two vectors where the weight for the first
+# vectors is 1.0 and is k2 for the second vector
+
+procedure ap_w1sur (a, b, c, npts, k2)
+
+real a[ARB] # the first input vector
+real b[ARB] # the second input vector
+real c[ARB] # the output vector
+int npts # number of points
+real k2 # the weigting factor for the second vector
+
+int i
+
+begin
+ do i = 1, npts
+ c[i] = a[i] + k2 * b[i]
+end
+
+
+# AP_INDEX -- Define an index array.
+
+procedure ap_index (index, npix)
+
+int index[ARB] # the index array
+int npix # the number of pixels
+
+int i
+
+begin
+ do i = 1, npix
+ index[i] = i
+end
diff --git a/noao/digiphot/apphot/aputil/mkpkg b/noao/digiphot/apphot/aputil/mkpkg
new file mode 100644
index 00000000..eefeed9d
--- /dev/null
+++ b/noao/digiphot/apphot/aputil/mkpkg
@@ -0,0 +1,25 @@
+# Miscellaneous Routines used by the APPHOT Package
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ apbsmooth.x
+ apclip.x
+ apdate.x <time.h>
+ apdiverr.x
+ apfnames.x
+ apgscur.x <gset.h> <fset.h>
+ apgtools.x <pkg/gtools.h> <gset.h>
+ aplucy.x
+ apnlfuncs.x <mach.h> <math.h>
+ apmapr.x
+ apmeds.x
+ apmoments.x
+ appcache.x <imhdr.h> <imset.h>
+ aprmwhite.x <ctype.h>
+ aptopt.x <math.h> <mach.h>
+ apvectors.x
+ ;
diff --git a/noao/digiphot/apphot/center.par b/noao/digiphot/apphot/center.par
new file mode 100644
index 00000000..3dbe8ad8
--- /dev/null
+++ b/noao/digiphot/apphot/center.par
@@ -0,0 +1,21 @@
+# CENTER
+
+image,f,a,,,,"Input image(s)"
+coords,f,h,"",,,"Input coordinate list(s) (default: image.coo.?)"
+output,f,h,"default",,,"Output center file(s) (default: image.ctr.?)"
+plotfile,s,h,"",,,"Output plot metacode file"
+datapars,pset,h,"",,,"Data dependent parameters"
+centerpars,pset,h,"",,,"Centering parameters"
+interactive,b,h,yes,,,"Interactive mode ?"
+radplots,b,h,no,,,"Plot the radial profiles in interactive mode ?"
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor: [x y wcs] key [cmd]"
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the input image pixels in memory ?"
+verify,b,h,)_.verify,,,"Verify critical parameters in non-interactive mode ?"
+update,b,h,)_.update,,,"Update critical parameters in non-interactive mode ?"
+verbose,b,h,)_.verbose,,,"Print messages in non-interactive mode ?"
+graphics,s,h,)_.graphics,,,"Graphics device"
+display,s,h,)_.display,,,"Display device"
+mode,s,h,'ql'
diff --git a/noao/digiphot/apphot/center/apbcenter.x b/noao/digiphot/apphot/center/apbcenter.x
new file mode 100644
index 00000000..9a607ee3
--- /dev/null
+++ b/noao/digiphot/apphot/center/apbcenter.x
@@ -0,0 +1,96 @@
+include <fset.h>
+include "../lib/apphot.h"
+include "../lib/display.h"
+
+# APBCENTER -- Procedure to determine accurate centers for a list of objects
+# in batch mode using a simple text file list.
+
+procedure apbcenter (ap, im, cl, out, id, ld, mgd, gid, interactive)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the IRAF image
+int cl # the coordinate file descriptor
+int out # output file descriptor
+int id # output file sequence number
+int ld # the coordinate file list number
+pointer mgd # pointer to the metacode file stream
+pointer gid # pointer to the image display stream
+int interactive # mode of use
+
+int stdin, ier, ild
+pointer sp, str
+real wx, wy
+int apfitcenter(), fscan(), nscan(), strncmp(), apstati()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+ call fstats (cl, F_FILENAME, Memc[str], SZ_FNAME)
+
+ # Initialize.
+ ild = ld
+
+ # Print query.
+ if (strncmp ("STDIN", Memc[str], 5) == 0) {
+ stdin = YES
+ call printf ("Type object x and y coordinates (^D or ^Z to end): ")
+ call flush (STDOUT)
+ } else
+ stdin = NO
+
+ # Loop over the coordinate file.
+ while (fscan (cl) != EOF) {
+
+ # Get and store the coordinates.
+ call gargr (wx)
+ call gargr (wy)
+ if (nscan () != 2) {
+ if (stdin == YES) {
+ call printf (
+ "Type object x and y coordinates (^D or ^Z to end): ")
+ call flush (STDOUT)
+ }
+ next
+ }
+
+ # Transform the input coordinates.
+ switch (apstati(ap,WCSIN)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_itol (ap, wx, wy, wx, wy, 1)
+ case WCS_TV:
+ call ap_vtol (im, wx, wy, wx, wy, 1)
+ default:
+ ;
+ }
+
+ call apsetr (ap, CWX, wx)
+ call apsetr (ap, CWY, wy)
+
+ # Fit the center.
+ ier = apfitcenter (ap, im, wx, wy)
+
+ # Print and/or plot the results.
+ if (interactive == YES) {
+ call ap_qcenter (ap, ier)
+ if (gid != NULL)
+ call apmark (ap, gid, apstati (ap, MKCENTER), NO, NO)
+ }
+ call ap_cplot (ap, id, mgd, YES)
+ if (id == 1)
+ call ap_param (ap, out, "center")
+ call ap_pcenter (ap, out, id, ild, ier)
+
+ # Setup for the next object.
+ id = id + 1
+ ild = ild + 1
+ call apsetr (ap, WX, wx)
+ call apsetr (ap, WY, wy)
+ if (stdin == YES) {
+ call printf (
+ "Type object x and y coordinates (^D or ^Z to end): ")
+ call flush (STDOUT)
+ }
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/center/apcconfirm.x b/noao/digiphot/apphot/center/apcconfirm.x
new file mode 100644
index 00000000..6c570bd4
--- /dev/null
+++ b/noao/digiphot/apphot/center/apcconfirm.x
@@ -0,0 +1,75 @@
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+
+# AP_CCONFIRM -- Procedure to confirm the critical center parameters.
+
+procedure ap_cconfirm (ap, out, stid)
+
+pointer ap # pointer to the apphot structure
+int out # output file descriptor
+int stid # output file sequence number
+
+pointer sp, str
+real fwhmpsf, capert, skysigma, datamin, datamax
+int apstati()
+real apstatr(), ap_vfwhmpsf(), ap_vcapert(), ap_vsigma()
+real ap_vdatamin(), ap_vdatamax()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ call printf ("\n")
+
+ # Confirm the centering algorithm.
+ call ap_vcstring (ap, Memc[str], SZ_FNAME)
+
+ if (apstati (ap, CENTERFUNCTION) != AP_NONE) {
+
+ # Confirm the fwhmpsf.
+ if (apstati (ap, CENTERFUNCTION) != AP_CENTROID1D) {
+ fwhmpsf = ap_vfwhmpsf (ap)
+ } else
+ fwhmpsf = apstatr (ap, FWHMPSF)
+
+ # Confirm the centering box.
+ capert = 2.0 * ap_vcapert (ap)
+
+ # Confirm the sky sigma parameter.
+ skysigma = ap_vsigma (ap)
+
+ } else {
+
+ fwhmpsf = apstatr (ap, FWHMPSF)
+ capert = 2.0 * apstatr (ap, CAPERT)
+ skysigma = apstatr (ap, SKYSIGMA)
+
+ }
+
+ # Confirm the sky sigma parameter.
+
+ # Confirm the minimum and maximum good data values.
+ datamin = ap_vdatamin (ap)
+ datamax = ap_vdatamax (ap)
+
+ call printf ("\n")
+
+ # Update the database file.
+ if (out != NULL && stid > 1) {
+ call ap_sparam (out, KY_CSTRING, Memc[str], UN_CALGORITHM,
+ "centering algorithm")
+ call ap_rparam (out, KY_FWHMPSF, fwhmpsf, UN_ASCALEUNIT,
+ "full width half maximum of the psf")
+ call ap_rparam (out, KY_CAPERT, capert, UN_CSCALEUNIT,
+ "centering box width")
+ call ap_rparam (out, KY_SKYSIGMA, skysigma, UN_NCOUNTS,
+ "standard deviation of 1 sky pixel")
+ call ap_rparam (out, KY_DATAMIN, datamin, UN_ACOUNTS,
+ "minimum good data value")
+ call ap_rparam (out, KY_DATAMAX, datamax, UN_ACOUNTS,
+ "maximum good data value")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/center/apcencolon.x b/noao/digiphot/apphot/center/apcencolon.x
new file mode 100644
index 00000000..9f2f40f8
--- /dev/null
+++ b/noao/digiphot/apphot/center/apcencolon.x
@@ -0,0 +1,329 @@
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+
+# APCENTERCOLON -- Process colon commands from the centering task.
+
+procedure apcentercolon (ap, im, cl, out, stid, ltid, cmdstr, newimage,
+ newbuf, newfit)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the iraf image
+int cl # coordinate file descriptor
+int out # output file descriptor
+int stid # output file sequence number
+int ltid # input list sequence number
+char cmdstr[ARB] # command string
+int newimage # new image ?
+int newbuf # new center buffer ?
+int newfit # new center fit ?
+
+int junk
+pointer sp, incmd, outcmd
+int strdic()
+
+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 (cmdstr)
+ call gargwrd (Memc[incmd], SZ_LINE)
+ if (Memc[incmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, CCMDS) != 0)
+ call ap_ccolon (ap, out, stid, cmdstr, newbuf, newfit)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, APCMDS) != 0)
+ call ap_apcolon (ap, im, cl, out, stid, ltid, cmdstr, newimage,
+ newbuf, newfit, junk, junk, junk, junk)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, NCMDS) != 0)
+ call ap_nscolon (ap, im, out, stid, cmdstr, newbuf, newfit,
+ junk, junk, junk, junk)
+ else
+ call ap_cimcolon (ap, cmdstr)
+
+ call sfree (sp)
+end
+
+
+# AP_CCOLON -- Process colon commands affecting the centering parameters.
+
+procedure ap_ccolon (ap, out, stid, cmdstr, newbuf, newfit)
+
+pointer ap # pointer to the apphot structure
+int out # output file descriptor
+int stid # output list id number
+char cmdstr # command string
+int newbuf # new sky buffer
+int newfit # new sky fit
+
+bool bval
+int ival, ncmd, stat
+pointer sp, cmd, str
+real rval
+
+bool itob()
+int nscan(), strdic(), btoi(), apstati()
+real apstatr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Get the command.
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, CCMDS)
+ switch (ncmd) {
+
+ case CCMD_CBOXWIDTH:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_CAPERT)
+ call pargr (2.0 * apstatr (ap, CAPERT))
+ call pargstr (UN_CSCALEUNIT)
+ } else {
+ call apsetr (ap, CAPERT, (rval / 2.0))
+ if (stid > 1)
+ call ap_rparam (out, KY_CAPERT, rval, UN_CSCALEUNIT,
+ "centering subraster width")
+ newbuf = YES
+ newfit = YES
+ }
+
+ case CCMD_CALGORITHM:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, CSTRING, Memc[str], SZ_FNAME)
+ call printf ("%s = %s %s\n")
+ call pargstr (KY_CSTRING)
+ call pargstr (Memc[str])
+ call pargstr (UN_CALGORITHM)
+ } else {
+ stat = strdic (Memc[cmd], Memc[cmd], SZ_LINE, CFUNCS)
+ if (stat > 0) {
+ call apseti (ap, CENTERFUNCTION, stat)
+ call apsets (ap, CSTRING, Memc[cmd])
+ if (stid > 1)
+ call ap_sparam (out, KY_CSTRING, Memc[cmd],
+ UN_CALGORITHM, "centering algorihtm")
+ newbuf = YES
+ newfit = YES
+ }
+ }
+
+ case CCMD_CTHRESHOLD:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_CTHRESHOLD)
+ call pargr (apstatr (ap, CTHRESHOLD))
+ call pargstr (UN_CSIGMA)
+ } else {
+ call apsetr (ap, CTHRESHOLD, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_CTHRESHOLD, rval, UN_CSIGMA,
+ "threshold for centering")
+ newbuf = YES
+ newfit = YES
+ }
+
+ case CCMD_MAXSHIFT:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_MAXSHIFT)
+ call pargr (apstatr (ap, MAXSHIFT))
+ call pargstr (UN_CSCALEUNIT)
+ } else {
+ call apsetr (ap, MAXSHIFT, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_MAXSHIFT, rval, UN_CSCALEUNIT,
+ "maximum shift")
+ newfit = YES
+ }
+
+ case CCMD_MINSNRATIO:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (KY_MINSNRATIO)
+ call pargr (apstatr (ap, MINSNRATIO))
+ } else {
+ call apsetr (ap, MINSNRATIO, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_MINSNRATIO, rval,
+ UN_CNUMBER, "minimum signal-to-noise ratio")
+ newfit = YES
+ }
+
+ case CCMD_CMAXITER:
+ call gargi (ival)
+ if (nscan () == 1) {
+ call printf ("%s = %d\n")
+ call pargstr (KY_CMAXITER)
+ call pargi (apstati (ap, CMAXITER))
+ } else {
+ call apseti (ap, CMAXITER, ival)
+ if (stid > 1)
+ call ap_iparam (out, KY_CMAXITER, ival, UN_CNUMBER,
+ "maximum number of iterations")
+ newfit = YES
+ }
+
+ case CCMD_CLEAN:
+ call gargb (bval)
+ if (nscan () == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (KY_CLEAN)
+ call pargb (itob (apstati (ap, CLEAN)))
+ } else {
+ call apseti (ap, CLEAN, btoi (bval))
+ if (stid > 1)
+ call ap_bparam (out, KY_CLEAN, bval, UN_CSCALEUNIT,
+ "apply clean algorithm before centering")
+ newbuf = YES
+ newfit = YES
+ }
+
+ case CCMD_RCLEAN:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_RCLEAN)
+ call pargr (apstatr (ap, RCLEAN))
+ call pargstr (UN_CSCALEUNIT)
+ } else {
+ call apsetr (ap, RCLEAN, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_RCLEAN, rval, UN_CSCALEUNIT,
+ "cleaning radius")
+ newbuf = YES
+ newfit = YES
+ }
+
+ case CCMD_RCLIP:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_RCLIP)
+ call pargr (apstatr (ap, RCLIP))
+ call pargstr (UN_CSCALEUNIT)
+ } else {
+ call apsetr (ap, RCLIP, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_RCLIP, rval, UN_CSCALEUNIT,
+ "clipping radius")
+ newbuf = YES
+ newfit = YES
+ }
+
+ case CCMD_KCLEAN:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_SIGMACLEAN)
+ call pargr (apstatr (ap, SIGMACLEAN))
+ call pargstr (UN_CSIGMA)
+ } else {
+ call apsetr (ap, SIGMACLEAN, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_SIGMACLEAN, rval,
+ UN_CSIGMA, "k-sigma clean rejection criterion")
+ newbuf = YES
+ newfit = YES
+ }
+
+ case CCMD_MKCENTER:
+ call gargb (bval)
+ if (nscan() == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (KY_MKCENTER)
+ call pargb (itob (apstati (ap, MKCENTER)))
+ } else
+ call apseti (ap, MKCENTER, btoi (bval))
+
+ default:
+ call printf ("Unknown or ambiguous colon command\7\n")
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_CIMCOLON -- Process colon commands for the center task that do
+# not affect the centering parameters
+
+procedure ap_cimcolon (ap, cmdstr)
+
+pointer ap # pointer to the apphot structure
+char cmdstr[ARB] # command string
+
+bool bval
+int ncmd
+pointer sp, cmd
+bool itob()
+int strdic(), nscan(), apstati(), btoi()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Get the command.
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, MISC)
+ switch (ncmd) {
+ case ACMD_SHOW:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, CSHOWARGS)
+ switch (ncmd) {
+ case CCMD_DATA:
+ call printf ("\n")
+ call ap_nshow (ap)
+ call printf ("\n")
+ case CCMD_CENTER:
+ call printf ("\n")
+ call ap_cpshow (ap)
+ call printf ("\n")
+ default:
+ call printf ("\n")
+ call ap_cshow (ap)
+ call printf ("\n")
+ }
+ case ACMD_RADPLOTS:
+ call gargb (bval)
+ if (nscan () == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (KY_RADPLOTS)
+ call pargb (itob (apstati (ap, RADPLOTS)))
+ } else {
+ call apseti (ap, RADPLOTS, btoi (bval))
+ }
+ default:
+ call printf ("Unknown or ambiguous colon command\7\n")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/center/apcenter.x b/noao/digiphot/apphot/center/apcenter.x
new file mode 100644
index 00000000..8e1b4c68
--- /dev/null
+++ b/noao/digiphot/apphot/center/apcenter.x
@@ -0,0 +1,357 @@
+include <ctype.h>
+include <gset.h>
+include <imhdr.h>
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/center.h"
+
+define HELPFILE "apphot$center/center.key"
+
+# APCENTER -- Procedure to determine accurate centers for a list of objects
+# interactively.
+
+int procedure apcenter (ap, im, cl, gd, mgd, id, out, stid, interactive, cache)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the IRAF image
+int cl # coordinate list file descriptor
+pointer gd # pointer to the graphics stream
+pointer mgd # pointer to the plot metacode stream
+pointer id # pointer to the image display stream
+int out # output file descriptor
+int stid # output file sequence number
+int interactive # interactive mode
+int cache # cache the input pixels
+
+real wx, wy, xlist, ylist
+pointer sp, cmd
+int wcs, key, colonkey, newimage, newobject, newcenter, newlist, ier, oid
+int ip, prev_num, req_num, ltid, buf_size, old_size, req_size, memstat
+
+real apstatr()
+int ctoi(), clgcur(), apgscur(), apfitcenter(), aprefitcenter(), apstati()
+int apgqverify(), apgtverify(), apnew(), ap_memstat(), sizeof()
+
+define endswitch_ 99
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Initialize cursor command.
+ key = ' '
+ Memc[cmd] = EOS
+
+ # Initialize fitting parameters.
+ newimage = NO
+ newobject = YES
+ newcenter = YES
+ ier = AP_OK
+
+ # Initialize sequencing.
+ newlist = NO
+ ltid = 0
+
+ # Loop over the cursor commands.
+ while (clgcur ("icommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+
+ # Store the current cursor coordinates.
+ call ap_vtol (im, wx, wy, wx, wy, 1)
+ call apsetr (ap, CWX, wx)
+ call apsetr (ap, CWY, wy)
+
+ # Test to see if the cursor has moved.
+ if (apnew (ap, wx, wy, xlist, ylist, newlist) == YES) {
+ newobject = YES
+ newcenter = YES
+ }
+
+ # Process the colon commands.
+ switch (key) {
+
+ # Quit.
+ case 'q':
+ if (interactive == YES) {
+ if (apgqverify ("center", ap, key) == YES) {
+ call sfree (sp)
+ return (apgtverify (key))
+ }
+ } else {
+ call sfree (sp)
+ return (NO)
+ }
+
+ # Print error messages.
+ case 'e':
+ if (interactive == YES)
+ call ap_cerrors (ap, ier)
+
+ # Get information on keystroke commands.
+ case '?':
+ if ((id != NULL) && (id == gd))
+ call gpagefile (id, HELPFILE, "")
+ else if (interactive == YES)
+ call pagefile (HELPFILE, "[space=cmhelp,q=quit,?=help]")
+
+ # Rewind the coord list.
+ case 'r':
+ if (cl != NULL) {
+ call seek (cl, BOF)
+ ltid = 0
+ } else if (interactive == YES)
+ call printf ("No coordinate list\n")
+
+ # Draw a centered stellar radial profile plot.
+ case 'd':
+ if (interactive == YES) {
+ call ap_qrad (ap, im, wx, wy, gd)
+ newobject = YES
+ newcenter = YES
+ }
+
+ # Interactively set the centering parameters.
+ case 'i':
+ if (interactive == YES) {
+ call ap_cradsetup (ap, im, wx, wy, gd, out, stid)
+ newobject = YES
+ newcenter = YES
+ }
+
+ # Verify critical parameters.
+ case 'v':
+ call ap_cconfirm (ap, out, stid)
+ newobject = YES
+ newcenter = YES
+
+ # Measure the next object.
+ case 'm', 'n':
+
+ # No coordinate file.
+ if (cl == NULL) {
+ if (interactive == YES)
+ call printf ("No coordinate list\n")
+ goto endswitch_
+ }
+
+ # Need to rewind coordinate file.
+ prev_num = ltid
+ req_num = ltid + 1
+ if (apgscur (cl, id, xlist, ylist, prev_num, req_num, ltid) ==
+ EOF) {
+ if (interactive == YES)
+ call printf (
+ "End of coordinate list, use r key to rewind\n")
+ goto endswitch_
+ }
+
+ # Convert coordinates if necessary.
+ switch (apstati (ap, WCSIN)) {
+ case WCS_PHYSICAL, WCS_WORLD:
+ call ap_itol (ap, xlist, ylist, xlist, ylist, 1)
+ case WCS_TV:
+ call ap_vtol (im, xlist, ylist, xlist, ylist, 1)
+ default:
+ ;
+ }
+
+ # Move to next object.
+ newlist = YES
+ if (key == 'm') {
+ newobject = YES
+ newcenter = YES
+ goto endswitch_
+ }
+
+ # Measure next object.
+ ier = apfitcenter (ap, im, xlist, ylist)
+ if (id != NULL) {
+ call apmark (ap, id, apstati (ap, MKCENTER), NO, NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_cplot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qcenter (ap, ier)
+ if (stid == 1)
+ call ap_param (ap, out, "center")
+ call ap_cplot (ap, stid, mgd, YES)
+ call ap_pcenter (ap, out, stid, ltid, ier)
+ stid = stid + 1
+ newobject = NO
+ newcenter = NO
+
+ # Save centering parameters in the pset files.
+ case 'w':
+ call ap_pcpars (ap)
+
+ # Process apphot : commands.
+ case ':':
+ for (ip = 1; IS_WHITE(Memc[cmd+ip-1]); ip = ip + 1)
+ ;
+ colonkey = Memc[cmd+ip-1]
+
+ # Process the apphot :n command.
+ switch (colonkey) {
+ case 'm', 'n':
+
+ # Show/set apphot commands
+ if (Memc[cmd+ip] != EOS && Memc[cmd+ip] != ' ') {
+ call apcentercolon (ap, im, cl, out, stid, ltid,
+ Memc[cmd], newimage, newobject, newcenter)
+ goto endswitch_
+ }
+
+ # No coordinate list.
+ if (cl == NULL) {
+ if (interactive == YES)
+ call printf ("No coordinate list\n")
+ goto endswitch_
+ }
+
+ # Get next object from list.
+ ip = ip + 1
+ prev_num = ltid
+ if (ctoi (Memc[cmd], ip, req_num) <= 0)
+ req_num = ltid + 1
+
+ # Fetch the next object from the list.
+ if (apgscur (cl, id, xlist, ylist, prev_num, req_num,
+ ltid) == EOF) {
+ if (interactive == YES)
+ call printf (
+ "End of coordinate list, use r key to rewind\n")
+ goto endswitch_
+ }
+
+ # Convert the coordinates.
+ switch (apstati (ap, WCSIN)) {
+ case WCS_PHYSICAL, WCS_WORLD:
+ call ap_itol (ap, xlist, ylist, xlist, ylist, 1)
+ case WCS_TV:
+ call ap_vtol (im, xlist, ylist, xlist, ylist, 1)
+ default:
+ ;
+ }
+
+ # Move to the next object.
+ newlist = YES
+ if (colonkey == 'm') {
+ newobject = YES
+ newcenter = YES
+ goto endswitch_
+ }
+
+ # Measure next object.
+ ier = apfitcenter (ap, im, xlist, ylist)
+ if (id != NULL) {
+ call apmark (ap, id, apstati (ap, MKCENTER), NO, NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_cplot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qcenter (ap, ier)
+ if (stid == 1)
+ call ap_param (ap, out, "center")
+ call ap_cplot (ap, stid, mgd, YES)
+ call ap_pcenter (ap, out, stid, ltid, ier)
+ stid = stid + 1
+ newobject = NO
+ newcenter = NO
+
+ # Show/set apphot parameters.
+ default:
+ call apcentercolon (ap, im, cl, out, stid, ltid, Memc[cmd],
+ newimage, newobject, newcenter)
+ }
+
+ if (newimage == YES) {
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[cmd], im, 4)
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+ }
+
+ newimage = NO
+
+ # Fit the center, and save the results.
+ case 'f', ' ':
+
+ # Compute the center.
+ if (newobject == YES)
+ ier = apfitcenter (ap, im, wx, wy)
+ else if (newcenter == YES)
+ ier = aprefitcenter (ap, im, ier)
+ if (id != NULL) {
+ call apmark (ap, id, apstati (ap, MKCENTER), NO, NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_cplot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qcenter (ap, ier)
+ newobject = NO; newcenter = NO
+
+ # Write the results to the output file(s).
+ if (key == ' ') {
+ if (stid == 1)
+ call ap_param (ap, out, "center")
+ if (newlist == YES)
+ call ap_pcenter (ap, out, stid, ltid, ier)
+ else
+ call ap_pcenter (ap, out, stid, 0, ier)
+ call ap_cplot (ap, stid, mgd, YES)
+ stid = stid + 1
+ }
+
+ # Fit centers for the rest of the list.
+ case 'l':
+
+ # No coordinate list.
+ if (cl == NULL) {
+ if (interactive == YES)
+ call printf ("No coordinate list\n")
+ goto endswitch_
+ }
+
+ # Center rest of coordinate list.
+ ltid = ltid + 1
+ oid = stid
+ call apbcenter (ap, im, cl, out, stid, ltid, mgd, id, YES)
+ ltid = ltid + stid - oid + 1
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ # Unknown command.
+ default:
+ call printf ("Unknown or ambiguous keystroke command\n")
+ }
+
+endswitch_
+ # Setup for the next object by setting the default keystroke
+ # command and storing the old cursor coordinates in the
+ # centering structure.
+
+ key = ' '
+ Memc[cmd] = EOS
+ call apsetr (ap, WX, apstatr (ap, CWX))
+ call apsetr (ap, WY, apstatr (ap, CWY))
+
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/center/apcerrors.x b/noao/digiphot/apphot/center/apcerrors.x
new file mode 100644
index 00000000..4f8c32bb
--- /dev/null
+++ b/noao/digiphot/apphot/center/apcerrors.x
@@ -0,0 +1,32 @@
+include "../lib/center.h"
+
+# AP_CERRORS -- Procedure to print the centering task error messages.
+
+procedure ap_cerrrors (ap, ier)
+
+pointer ap # apphot pointer (unused)
+int ier # centering error code
+
+begin
+ switch (ier) {
+ case AP_CTR_NOAREA:
+ call printf ("There are no pixels in the centering box.\n")
+ case AP_CTR_OUTOFBOUNDS:
+ call printf (
+ "The centering region is partially outside the image.\n")
+ case AP_CTR_NTOO_SMALL:
+ call printf ("The centering box has too few points.\n")
+ case AP_CTR_SINGULAR:
+ call printf ("The centering solution is singular.\n")
+ case AP_CTR_NOCONVERGE:
+ call printf ("The centering algorithm does not converge.\n")
+ case AP_CTR_BADSHIFT:
+ call printf ("The center shift is large.\n")
+ case AP_CTR_LOWSNRATIO:
+ call printf ("The signal to noise ratio is low.\n")
+ case AP_CTR_BADDATA:
+ call printf ("Bad data in the centering subraster.\n")
+ default:
+ call printf ("")
+ }
+end
diff --git a/noao/digiphot/apphot/center/apcfree.x b/noao/digiphot/apphot/center/apcfree.x
new file mode 100644
index 00000000..7fb219c7
--- /dev/null
+++ b/noao/digiphot/apphot/center/apcfree.x
@@ -0,0 +1,46 @@
+include "../lib/apphotdef.h"
+include "../lib/centerdef.h"
+
+# APCFREE -- Procedure to free the centering data structure.
+
+procedure apcfree (ap)
+
+pointer ap # pointer to the apphot structure
+
+begin
+ if (ap == NULL)
+ return
+ if (AP_NOISE(ap) != NULL)
+ call ap_noisecls (ap)
+ if (AP_PCENTER(ap) != NULL)
+ call ap_ctrcls (ap)
+ if (AP_PDISPLAY(ap) != NULL)
+ call ap_dispcls (ap)
+ if (AP_IMBUF(ap) != NULL)
+ call mfree (AP_IMBUF(ap), TY_REAL)
+ if (AP_MW(ap) != NULL)
+ call mw_close (AP_MW(ap))
+ call mfree (ap, TY_STRUCT)
+end
+
+
+# AP_CTRCLS -- Procedure to close up the centering structure arrays.
+
+procedure ap_ctrcls (ap)
+
+pointer ap # pointer to apphot structure
+
+pointer ctr
+
+begin
+ ctr = AP_PCENTER(ap)
+ if (ctr == NULL)
+ return
+ if (AP_CTRPIX(ctr) != NULL)
+ call mfree (AP_CTRPIX(ctr), TY_REAL)
+ if (AP_XCTRPIX(ctr) != NULL)
+ call mfree (AP_XCTRPIX(ctr), TY_REAL)
+ if (AP_YCTRPIX(ctr) != NULL)
+ call mfree (AP_YCTRPIX(ctr), TY_REAL)
+ call mfree (AP_PCENTER(ap), TY_STRUCT)
+end
diff --git a/noao/digiphot/apphot/center/apcinit.x b/noao/digiphot/apphot/center/apcinit.x
new file mode 100644
index 00000000..a9f38fd7
--- /dev/null
+++ b/noao/digiphot/apphot/center/apcinit.x
@@ -0,0 +1,94 @@
+include "../lib/apphotdef.h"
+include "../lib/centerdef.h"
+include "../lib/center.h"
+
+# APCINIT - Procedure to initialize the centering structure.
+
+procedure apcinit (ap, function, cbox, fwhmpsf, noise)
+
+pointer ap # pointer to the apphot structure
+int function # centering algorithm
+real cbox # half width of centering box
+real fwhmpsf # FWHM of the PSF
+int noise # noise function
+
+begin
+ # Allocate space.
+ call malloc (ap, LEN_APSTRUCT, TY_STRUCT)
+
+ # Set up the global apphot package parameters.
+ call ap_defsetup (ap, fwhmpsf)
+
+ # Setup the noise structure.
+ call ap_noisesetup (ap, noise)
+
+ # Initialize the centering parameters.
+ call ap_ctrsetup (ap, function, cbox)
+
+ # Display the options.
+ call ap_dispsetup (ap)
+
+ # Unused structures are set to null.
+ AP_PSKY(ap) = NULL
+ AP_PPSF(ap) = NULL
+ AP_PPHOT(ap) = NULL
+ AP_POLY(ap) = NULL
+ AP_RPROF(ap) = NULL
+end
+
+
+# AP_CTRSETUP -- Procedure to setup the centering array parameters.
+
+procedure ap_ctrsetup (ap, function, cbox)
+
+pointer ap # pointer to apphot structure
+int function # centering function
+real cbox # radius of centering aperture
+
+pointer ctr
+
+begin
+ # Allocate space for the centering structure.
+ call malloc (AP_PCENTER(ap), LEN_CENSTRUCT, TY_STRUCT)
+ ctr = AP_PCENTER(ap)
+ AP_CXCUR(ctr) = INDEFR
+ AP_CYCUR(ctr) = INDEFR
+
+ AP_CENTERFUNCTION(ctr) = function
+ switch (function) {
+ case AP_CENTROID1D:
+ call strcpy ("centroid", AP_CSTRING(ctr), SZ_FNAME)
+ case AP_GAUSS1D:
+ call strcpy ("gauss", AP_CSTRING(ctr), SZ_FNAME)
+ case AP_NONE:
+ call strcpy ("none", AP_CSTRING(ctr), SZ_FNAME)
+ case AP_OFILT1D:
+ call strcpy ("ofilter", AP_CSTRING(ctr), SZ_FNAME)
+ default:
+ AP_CENTERFUNCTION(ctr) = DEF_CENTERFUNCTION
+ call strcpy ("centroid", AP_CSTRING(ctr), SZ_FNAME)
+ }
+ AP_CAPERT(ctr) = cbox
+ AP_CTHRESHOLD(ctr) = DEF_CTHRESHOLD
+ AP_MINSNRATIO(ctr) = DEF_MINSNRATIO
+ AP_CMAXITER(ctr) = DEF_CMAXITER
+ AP_MAXSHIFT(ctr) = DEF_MAXSHIFT
+ AP_CLEAN(ctr) = DEF_CLEAN
+ AP_RCLEAN(ctr) = DEF_RCLEAN
+ AP_RCLIP(ctr) = DEF_RCLIP
+ AP_SIGMACLEAN(ctr) = DEF_CLEANSIGMA
+
+ AP_NCTRPIX(ctr) = 0
+ AP_CTRPIX(ctr) = NULL
+ AP_XCTRPIX(ctr) = NULL
+ AP_YCTRPIX(ctr) = NULL
+
+ AP_OXINIT(ctr) = INDEFR
+ AP_OYINIT(ctr) = INDEFR
+ AP_XCENTER(ctr) = INDEFR
+ AP_YCENTER(ctr) = INDEFR
+ AP_OXCENTER(ctr) = INDEFR
+ AP_OYCENTER(ctr) = INDEFR
+ AP_XERR(ctr) = INDEFR
+ AP_YERR(ctr) = INDEFR
+end
diff --git a/noao/digiphot/apphot/center/apclean.x b/noao/digiphot/apphot/center/apclean.x
new file mode 100644
index 00000000..2e3a827a
--- /dev/null
+++ b/noao/digiphot/apphot/center/apclean.x
@@ -0,0 +1,152 @@
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+
+# AP_CLEAN -- Procedure to clean a data array.
+
+procedure ap_clean (ap, pix, nx, ny, xc, yc)
+
+pointer ap # pointer to the apphot structure
+real pix[nx,ny] # data array
+int nx, ny # size of subarray
+real xc, yc # center of subarray
+
+int apstati()
+real apstatr()
+
+begin
+ switch (apstati (ap, NOISEFUNCTION)) {
+ case AP_NCONSTANT:
+ call ap_cclean (pix, nx, ny, xc, yc, apstatr (ap, SCALE) *
+ apstatr (ap, RCLIP), apstatr (ap, SIGMACLEAN),
+ apstatr (ap, SKYSIGMA), apstatr (ap, MAXSHIFT))
+ case AP_NPOISSON:
+ call ap_pclean (pix, nx, ny, xc, yc, apstatr (ap, SCALE) *
+ apstatr (ap, RCLEAN), apstatr (ap, SCALE) * apstatr (ap,
+ RCLIP), apstatr (ap, SIGMACLEAN), apstatr (ap, SKYSIGMA),
+ apstatr (ap, EPADU), apstatr (ap, MAXSHIFT))
+ default:
+ return
+ }
+end
+
+
+# AP_CCLEAN -- Procedure to clean the subraster assuming the noise is
+# due to a constant sky sigma.
+
+procedure ap_cclean (pix, nx, ny, cxc, cyc, rclip, kclean, skysigma,
+ maxshift)
+
+real pix[nx, ny] # array of pixels
+int nx, ny # dimensions of the subarray
+real cxc, cyc # initial center
+real rclip # cleaning and clipping radius
+real kclean # k-sigma clipping factor
+real skysigma # maxshift
+real maxshift # maximum shift
+
+int i, ii, ixc, j, jj, jyc, ijunk, jjunk
+real mindat, maxdat, rclip2, r2, ksigma
+
+begin
+ # Return if indef valued sigma or sigma <= 0.
+ if (IS_INDEFR(skysigma) || (skysigma <= 0.0))
+ return
+
+ # Find the maximum pixel in the subarray and treat this point as
+ # the center of symmetry if it is less than maxshift from the
+ # initial center.
+
+ call ap_2dalimr (pix, nx, ny, mindat, maxdat, ijunk, jjunk, ixc, jyc)
+ if (abs (cxc - ixc) > maxshift || abs (cyc - jyc) > maxshift) {
+ ixc = int (cxc)
+ jyc = int (cyc)
+ }
+
+ # Clip.
+ rclip2 = rclip ** 2
+ ksigma = kclean * skysigma
+ do j = 1, ny {
+ jj = 2 * jyc - j
+ if (jj < 1 || jj > ny)
+ next
+ do i = 1, ixc {
+ ii = 2 * ixc - i
+ if (ii < 1 || ii > nx)
+ next
+ r2 = (i - ixc) ** 2 + (j - jyc) ** 2
+ if (r2 > rclip2) {
+ if (pix[ii,jj] > pix[i,j] + ksigma)
+ pix[ii,jj] = pix[i,j]
+ else if (pix[i,j] > pix[ii,jj] + ksigma)
+ pix[i,j] = pix[ii,jj]
+ }
+ }
+ }
+end
+
+
+# AP_PCLEAN -- Procedure to clean the subraster assuming that the noise is
+# due to a constant sky value plus poisson noise.
+
+procedure ap_pclean (pix, nx, ny, cxc, cyc, rclean, rclip, kclean, skysigma,
+ padu, maxshift)
+
+real pix[nx, ny] # array of pixels
+int nx, ny # dimensions of the subarray
+real cxc, cyc # initial center
+real rclean, rclip # cleaning and clipping radius
+real kclean # k-sigma clipping factor
+real skysigma # maxshift
+real padu # photons per adu
+real maxshift # maximum shift
+
+int i, ii, ixc, j, jj, jyc, ijunk, jjunk
+real mindat, maxdat, rclean2, rclip2, r2, ksigma, ksigma2
+
+begin
+ # Return if indef-valued sigma.
+ if (IS_INDEFR(skysigma))
+ return
+
+ # Find the maximum pixel in the subarray and treat this point as
+ # the center of symmetry if it is less than maxshift from the
+ # initial center.
+
+ call ap_2dalimr (pix, nx, ny, mindat, maxdat, ijunk, jjunk, ixc, jyc)
+ if (abs (cxc - ixc) > maxshift || abs (cyc - jyc) > maxshift) {
+ ixc = int (cxc)
+ jyc = int (cyc)
+ }
+
+ # Clip.
+ rclean2 = rclean ** 2
+ rclip2 = rclip ** 2
+ ksigma = kclean * skysigma
+ ksigma2 = ksigma ** 2
+ do j = 1, ny {
+ jj = 2 * jyc - j
+ if (jj < 1 || jj > ny)
+ next
+ do i = 1, ixc {
+ ii = 2 * ixc - i
+ if (ii < 1 || ii > nx)
+ next
+ r2 = (i - ixc) ** 2 + (j - jyc) ** 2
+ if (r2 > rclean2 && r2 <= rclip2) {
+ if (pix[ii,jj] > (pix[i,j] + sqrt (pix[i,j] / padu +
+ ksigma2)))
+ pix[ii,jj] = pix[i,j]
+ else if (pix[i,j] > (pix[ii,jj] + sqrt (pix[ii,jj] / padu +
+ ksigma2)))
+ pix[i,j] = pix[ii,jj]
+ }
+ if (r2 > rclip2) {
+ if (pix[ii,jj] > pix[i,j] + ksigma)
+ pix[ii,jj] = pix[i,j]
+ else if (pix[i,j] > pix[ii,jj] + ksigma)
+ pix[i,j] = pix[ii,jj]
+ }
+ }
+ }
+end
diff --git a/noao/digiphot/apphot/center/apcplot.x b/noao/digiphot/apphot/center/apcplot.x
new file mode 100644
index 00000000..6e2845c3
--- /dev/null
+++ b/noao/digiphot/apphot/center/apcplot.x
@@ -0,0 +1,304 @@
+include <mach.h>
+include <gset.h>
+include <pkg/gtools.h>
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/centerdef.h"
+include "../lib/center.h"
+
+# AP_CPLOT -- Procedure to compute radial profile plots for the centering
+# routine.
+
+procedure ap_cplot (ap, sid, gd, makeplot)
+
+pointer ap # the pointer to the apphot structure
+int sid # the output sequence number of the star
+pointer gd # the graphics stream
+int makeplot # the make a plot ?
+
+int nx, ny
+pointer ctr, sp, str, r, gt
+real xcenter, ycenter, xc, yc, rmin, rmax, imin, imax
+real u1, u2, v1, v2, x1, x2, y1, y2
+int apstati()
+pointer ap_gtinit()
+real apstatr()
+
+begin
+ # Check for enabled graphics stream.
+ if (gd == NULL || makeplot == NO)
+ return
+
+ # Check for defined center.
+ xcenter = apstatr (ap, XCENTER)
+ ycenter = apstatr (ap, YCENTER)
+ if (IS_INDEFR(xcenter) || IS_INDEFR(ycenter))
+ return
+
+ # Check for a centering algorithm.
+ if (apstati (ap, CENTERFUNCTION) == AP_NONE)
+ return
+
+ # Get the pixel buffer parameters.
+ ctr = AP_PCENTER(ap)
+ nx = AP_CNX(ctr)
+ ny = AP_CNY(ctr)
+ if (AP_CTRPIX(ctr) == NULL || nx <= 0 || ny <= 0)
+ return
+ xc = AP_CXC(ctr) + (xcenter - apstatr (ap, CXCUR))
+ yc = AP_CYC(ctr) + (ycenter - apstatr (ap, CYCUR))
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (r, nx * ny, TY_REAL)
+
+ # Compute the radii and the plot limits.
+ call ap_ijtor2 (Memr[r], nx, ny, xc, yc)
+ call alimr (Memr[r], nx * ny, rmin, rmax)
+ call alimr (Memr[AP_CTRPIX(ctr)], nx * ny, imin, imax)
+
+ # Reactivate the work station.
+ call greactivate (gd, 0)
+
+ # Save old viewport and window coordinates.
+ call ggview (gd, u1, u2, v1, v2)
+ call ggwind (gd, x1, x2, y1, y2)
+
+ # Initialize the plot.
+ call apstats (ap, IMROOT, Memc[str], SZ_LINE)
+ call sprintf (Memc[str], SZ_LINE, "%s Star %d")
+ call pargstr (Memc[str])
+ call pargi (sid)
+ gt = ap_gtinit (Memc[str], apstatr (ap,OXINIT), apstatr (ap, OYINIT))
+
+ # Make the plot.
+ call gclear (gd)
+ call ap_cpset (gd, gt, ap, rmin, rmax, imin, imax)
+ if (apstati (ap, POSITIVE) == YES)
+ call ap_plotpts (gd, gt, Memr[r], Memr[AP_CTRPIX(ctr)], nx * ny,
+ rmin, rmax, imin + EPSILONR, imax, "plus")
+ else
+ call ap_plotpts (gd, gt, Memr[r], Memr[AP_CTRPIX(ctr)], nx * ny,
+ rmin, rmax, imin, imax - EPSILONR, "plus")
+ call ap_cpreset (gd, gt, ap, rmin, rmax, imin, imax)
+ call ap_cpannotate (gd, ap)
+
+ # Restore the viewport and window coordinates.
+ call gsview (gd, u1, u2, v1, v2)
+ call gswind (gd, x1, x2, y1, y2)
+
+ # Free the space.
+ call ap_gtfree (gt)
+ call gdeactivate (gd, 0)
+ call sfree (sp)
+end
+
+
+# AP_CPSET -- Procedure to set up the parameters for the center radial profile
+# plot.
+
+procedure ap_cpset (gd, gt, ap, xmin, xmax, ymin, ymax)
+
+pointer gd # the graphics stream
+pointer gt # the gtools pointer
+pointer ap # the apphot pointer
+real xmin, xmax # the minimum and maximum radial distance
+real ymin, ymax # the minimum and maximum of y axis (ymin not used)
+
+int fd
+pointer sp, str, title
+real scale, aspect, datalimit, skysigma, threshold, vx1, vx2, vy1, vy2
+real cthreshold
+int stropen(), apstati()
+real apstatr(), gstatr()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (title, SZ_LINE, TY_CHAR)
+
+ # Encode the parameter string.
+ fd = stropen (Memc[str], SZ_LINE, WRITE_ONLY)
+ call sysid (Memc[title], SZ_LINE)
+ call fprintf (fd, "%s\n")
+ call pargstr (Memc[title])
+ call fprintf (fd,
+ "Center: xc=%0.2f yc=%0.2f xerr=%0.2f yerr=%0.2f\n")
+ call pargr (apstatr (ap, OXCENTER))
+ call pargr (apstatr (ap, OYCENTER))
+ call pargr (apstatr (ap, XERR))
+ call pargr (apstatr (ap, YERR))
+ call gt_gets (gt, GTTITLE, Memc[title], SZ_LINE)
+ call fprintf (fd, "%s\n")
+ call pargstr (Memc[title])
+ call strclose (fd)
+
+ # Store some default plotting parameters.
+ scale = apstatr (ap, SCALE)
+ aspect = gstatr (gd, G_ASPECT)
+ call gsetr (gd, G_ASPECT, 0.75)
+
+ # Set the labels and window.
+ datalimit = apstatr (ap, CDATALIMIT)
+ skysigma = apstatr (ap, SKYSIGMA)
+ cthreshold = apstatr (ap, CTHRESHOLD)
+ if (IS_INDEFR(skysigma) || IS_INDEFR(cthreshold))
+ threshold = 0.0
+ else
+ threshold = cthreshold * skysigma
+ if (apstati (ap, POSITIVE) == YES) {
+ call gseti (gd, G_XDRAWAXES, 2)
+ call gswind (gd, xmin / scale, xmax / scale, datalimit + threshold,
+ datalimit + threshold + ymax)
+ call glabax (gd, Memc[str], "", "Intensity")
+ call gseti (gd, G_YDRAWAXES, 0)
+ call gseti (gd, G_XDRAWAXES, 1)
+ call ggview (gd, vx1, vx2, vy1, vy2)
+ call gswind (gd, vx1, vx2, vy1, vy2)
+ call gswind (gd, xmin, xmax, datalimit + threshold,
+ datalimit + threshold + ymax)
+ call glabax (gd, "",
+ "Radial Distance (lower-pixels, upper-scale units)", "")
+ } else {
+ call gseti (gd, G_XDRAWAXES, 2)
+ call gswind (gd, xmin / scale, xmax / scale, datalimit -
+ threshold - ymax, datalimit - threshold)
+ call glabax (gd, Memc[str], "", "Intensity")
+ call gseti (gd, G_YDRAWAXES, 0)
+ call gseti (gd, G_XDRAWAXES, 1)
+ call ggview (gd, vx1, vx2, vy1, vy2)
+ call gswind (gd, vx1, vx2, vy1, vy2)
+ call gswind (gd, xmin, xmax, datalimit - threshold - ymax,
+ datalimit - threshold)
+ call glabax (gd, "",
+ "Radial Distance (lower-pixels, upper-scale units)", "")
+ }
+
+ # Set the window up for plotting the data.
+ call gseti (gd, G_YDRAWAXES, 3)
+ call gseti (gd, G_XDRAWAXES, 3)
+ call gsetr (gd, G_ASPECT, aspect)
+ call gt_sets (gt, GTTYPE, "mark")
+ call gt_setr (gt, GTXMIN, xmin)
+ call gt_setr (gt, GTXMAX, xmax)
+ if (apstati (ap, POSITIVE) == YES) {
+ call gt_setr (gt, GTYMIN, ymin)
+ call gt_setr (gt, GTYMAX, ymax)
+ } else {
+ call gt_setr (gt, GTYMIN, ymin)
+ call gt_setr (gt, GTYMAX, ymax)
+ }
+ call gt_swind (gd, gt)
+
+ call sfree (sp)
+end
+
+
+# AP_CPANNOTATE -- Procedure to annotate the radial plot in center.
+
+procedure ap_cpannotate (gd, ap)
+
+pointer gd # the graphics stream
+pointer ap # the apphot structure
+
+pointer sp, str
+real fwhmpsf, capert, datalimit, threshold, skysigma, cthreshold
+real xmin, xmax, ymin, ymax
+int apstati()
+real apstatr()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call gseti (gd, G_PLTYPE, GL_DASHED)
+ call ggwind (gd, xmin, xmax, ymin, ymax)
+
+ fwhmpsf = 0.5 * apstatr (ap, FWHMPSF) * apstatr (ap, SCALE)
+ capert = 2.0 * fwhmpsf * apstatr (ap, CAPERT)
+ datalimit = apstatr (ap, CDATALIMIT)
+ skysigma = apstatr (ap, SKYSIGMA)
+ cthreshold = apstatr (ap, CTHRESHOLD)
+ if (IS_INDEFR(skysigma) || IS_INDEFR(cthreshold))
+ threshold = 0.0
+ else
+ threshold = cthreshold * skysigma
+ if (apstati (ap, POSITIVE) == YES)
+ threshold = datalimit + threshold
+ else
+ threshold = datalimit - threshold
+
+ # Plot the full width half maximum of the radial profile.
+ if (fwhmpsf >= xmin && fwhmpsf <= xmax) {
+ call gamove (gd, fwhmpsf, ymin)
+ call gadraw (gd, fwhmpsf, ymax)
+ call sprintf (Memc[str], SZ_LINE, "hwhm = %0.2f")
+ call pargr (fwhmpsf)
+ call gtext (gd, fwhmpsf, ymax, Memc[str], "q=h;u=180;v=t;p=r")
+ }
+
+ # Mark the centering aperture.
+ if (capert >= xmin && capert <= xmax) {
+ call gamove (gd, capert, ymin)
+ call gadraw (gd, capert, ymax)
+ call sprintf (Memc[str], SZ_LINE, "cbox half-width = %0.2f")
+ call pargr (capert)
+ call gtext (gd, capert, ymax, Memc[str], "q=h;u=180;v=t;p=r")
+ }
+
+ # Mark the threshold level for centering.
+ call sprintf (Memc[str], SZ_LINE, "threshold = %g")
+ call pargr (threshold)
+ call gtext (gd, xmin, ymin, Memc[str], "q=h")
+
+ # Mark the sky sigma if defined.
+ if (! IS_INDEFR(skysigma) && skysigma >= ymin && skysigma <= ymax) {
+ call gmark (gd, (xmin + xmax) / 2.0, (ymin + ymax) / 2.0,
+ GM_VEBAR, -0.25, -skysigma)
+ call sprintf (Memc[str], SZ_LINE, "sigma = %g")
+ call pargr (skysigma)
+ call gtext (gd, (xmin + xmax) / 2.0, (ymin + ymax + skysigma) / 2.0,
+ Memc[str], "q=h;h=c")
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_CPRSET -- Procedure to reset the plot window after the data points
+# have been plotted.
+
+procedure ap_cpreset (gd, gt, ap, xmin, xmax, ymin, ymax)
+
+pointer gd # the graphics stream
+pointer gt # the gtools pointer
+pointer ap # the apphot pointer
+real xmin, xmax # the minimum and maximum radial distance
+real ymin, ymax # the minimum and maximum of the y axis (ymin not used)
+
+real datalimit, skysigma, threshold, cthreshold
+int apstati()
+real apstatr()
+
+begin
+ # Set the data window.
+ datalimit = apstatr (ap, CDATALIMIT)
+ skysigma = apstatr (ap, SKYSIGMA)
+ cthreshold = apstatr (ap, CTHRESHOLD)
+ if (IS_INDEFR(skysigma) || IS_INDEFR(cthreshold))
+ threshold = 0.0
+ else
+ threshold = cthreshold * skysigma
+ call gt_setr (gt, GTXMIN, xmin)
+ call gt_setr (gt, GTXMAX, xmax)
+ if (apstati (ap, POSITIVE) == YES) {
+ call gt_setr (gt, GTYMIN, datalimit + threshold)
+ call gt_setr (gt, GTYMAX, ymax + datalimit + threshold)
+ } else {
+ call gt_setr (gt, GTYMIN, datalimit - ymax - threshold)
+ call gt_setr (gt, GTYMAX, datalimit - threshold)
+ }
+ call gt_swind (gd, gt)
+end
diff --git a/noao/digiphot/apphot/center/apcpshow.x b/noao/digiphot/apphot/center/apcpshow.x
new file mode 100644
index 00000000..79fdf43e
--- /dev/null
+++ b/noao/digiphot/apphot/center/apcpshow.x
@@ -0,0 +1,66 @@
+include "../lib/center.h"
+include "../lib/display.h"
+
+# AP_CPSHOW -- Procedure to display the current centering algorithm
+# parameters.
+
+procedure ap_cpshow (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+pointer sp, str
+bool itob()
+int apstati()
+real apstatr()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Print the centering algorithm.
+ call printf ("Centering Parameters\n")
+ call apstats (ap, CSTRING, Memc[str], SZ_FNAME)
+ call printf (" %s = %s %s\n")
+ call pargstr (KY_CSTRING)
+ call pargstr (Memc[str])
+ call pargstr (UN_CALGORITHM)
+
+ # Print the rest of the centering parameters.
+ call printf (" %s = %g %s %s = %g %s %s = %g\n")
+ call pargstr (KY_CAPERT)
+ call pargr (2.0 * apstatr (ap, CAPERT))
+ call pargstr (UN_CSCALEUNIT)
+ call pargstr (KY_CTHRESHOLD)
+ call pargr (apstatr (ap, CTHRESHOLD))
+ call pargstr (UN_CSIGMA)
+ call pargstr (KY_MINSNRATIO)
+ call pargr (apstatr (ap, MINSNRATIO))
+
+ call printf (" %s = %d %s = %g %s\n")
+ call pargstr (KY_CMAXITER)
+ call pargi (apstati (ap, CMAXITER))
+ call pargstr (KY_MAXSHIFT)
+ call pargr (apstatr (ap, MAXSHIFT))
+ call pargstr (UN_CNUMBER)
+
+ call printf (" %s = %b %s = %g %s\n")
+ call pargstr (KY_CLEAN)
+ call pargb (itob (apstati (ap, CLEAN)))
+ call pargstr (KY_SIGMACLEAN)
+ call pargr (apstatr (ap, SIGMACLEAN))
+ call pargstr (UN_CSIGMA)
+
+ call printf (" %s = %g %s %s = %g %s\n")
+ call pargstr (KY_RCLEAN)
+ call pargr (apstatr (ap, RCLEAN))
+ call pargstr (UN_CSCALEUNIT)
+ call pargstr (KY_RCLIP)
+ call pargr (apstatr (ap, RCLIP))
+ call pargstr (UN_CSCALEUNIT)
+
+ call printf (" %s = %b\n")
+ call pargstr (KY_MKCENTER)
+ call pargb (itob (apstati (ap, MKCENTER)))
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/center/apcradsetup.x b/noao/digiphot/apphot/center/apcradsetup.x
new file mode 100644
index 00000000..8902c5ef
--- /dev/null
+++ b/noao/digiphot/apphot/center/apcradsetup.x
@@ -0,0 +1,99 @@
+include "../lib/display.h"
+
+define HELPFILE "apphot$center/icenter.key"
+
+# AP_CRADSETUP -- Procedure to set up apphot interactively
+
+procedure ap_cradsetup (ap, im, wx, wy, gd, out, stid)
+
+pointer ap # pointer to apphot structure
+pointer im # pointero to the IRAF image
+real wx, wy # cursor coordinates
+pointer gd # pointer to graphics stream
+int out # output file descriptor
+int stid # output file sequence number
+
+int cier, wcs, key
+pointer sp, cmd
+real xcenter, ycenter, xc, yc, rmin, rmax, imin, imax, rval
+real u1, u2, v1, v2, x1, x2, y1, y2
+
+int ap_showplot(), apfitcenter(), apstati(), clgcur()
+real ap_cfwhmpsf(), ap_ccapert(), ap_csigma()
+real ap_cdatamin(), ap_cdatamax(), ap_crclean(), ap_crclip()
+
+begin
+ # Check for open graphics stream.
+ if (gd == NULL)
+ return
+ call greactivate (gd, 0)
+
+ # Store old viewport and window coordinates.
+ call ggview (gd, u1, u2, v1, v2)
+ call ggwind (gd, x1, x2, y1, y2)
+
+ # Make the plot.
+ if (ap_showplot (ap, im, wx, wy, gd, xcenter, ycenter, rmin, rmax,
+ imin, imax) == ERR) {
+ call gdeactivate (gd, 0)
+ return
+ }
+
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ call printf (
+ "Waiting for setup menu command (?=help, v=default setup, q=quit):\n")
+
+ while (clgcur ("gcommands", xc, yc, wcs, key, Memc[cmd],
+ SZ_LINE) != EOF) {
+
+ switch (key) {
+ case 'q':
+ break
+ case '?':
+ call gpagefile (gd, HELPFILE, "")
+ case 'f':
+ rval = ap_cfwhmpsf (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 's':
+ rval = ap_csigma (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'l':
+ rval = ap_cdatamin (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'u':
+ rval = ap_cdatamax (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'c':
+ rval = ap_ccapert (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'n':
+ rval = ap_crclean (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'p':
+ rval = ap_crclip (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'v':
+ rval = ap_cfwhmpsf (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_ccapert (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_csigma (ap, gd, out, stid, rmin, rmax, imin, imax)
+ #rval = ap_ccthresh (ap, gd, out, stid, rmin, rmax, imin, imax)
+ default:
+ call printf ("Unknown or ambiguous keystroke command\007\n")
+ }
+ call printf (
+ "Waiting for setup menu command (?=help, v=default setup, q=quit):\n")
+ }
+
+ # Set up interactively.
+ call printf (
+ "Interactive setup is complete [Type w to save parameters].\n")
+
+ # Restore old window and viewport coordinates.
+ call gsview (gd, u1, u2, v1, v2)
+ call gswind (gd, x1, x2, y1, y2)
+
+ # Free plots and working space.
+ call sfree (sp)
+ call gdeactivate (gd, 0)
+
+ # Fit the center and plot the results.
+ cier = apfitcenter (ap, im, xcenter, ycenter)
+ call ap_cplot (ap, 0, gd, apstati (ap, RADPLOTS))
+ call ap_qcenter (ap, cier)
+end
diff --git a/noao/digiphot/apphot/center/apcshow.x b/noao/digiphot/apphot/center/apcshow.x
new file mode 100644
index 00000000..8cedbfc2
--- /dev/null
+++ b/noao/digiphot/apphot/center/apcshow.x
@@ -0,0 +1,19 @@
+include "../lib/display.h"
+
+# AP_CSHOW -- Procedure to display the current centering parameters.
+
+procedure ap_cshow (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+bool itob()
+int apstati()
+
+begin
+ call ap_nshow (ap)
+ call printf ("\n")
+ call ap_cpshow (ap)
+ call printf (" %s = %b\n")
+ call pargstr (KY_RADPLOTS)
+ call pargb (itob (apstati (ap, RADPLOTS)))
+end
diff --git a/noao/digiphot/apphot/center/apcsnratio.x b/noao/digiphot/apphot/center/apcsnratio.x
new file mode 100644
index 00000000..0fd0e20d
--- /dev/null
+++ b/noao/digiphot/apphot/center/apcsnratio.x
@@ -0,0 +1,92 @@
+include <mach.h>
+include "../lib/center.h"
+include "../lib/noise.h"
+
+# AP_CSNRATIO -- Procedure to estimate the signal to noise ratio for centering.
+
+real procedure ap_csnratio (ap, array, nx, ny, threshold)
+
+pointer ap # apphot structure
+real array[nx,ny] # data array
+int nx, ny # subraster dimensions
+real threshold # threshold value for snr computation
+
+int apstati()
+real apstatr(), ap_cratio(), ap_pratio()
+
+begin
+ switch (apstati (ap, NOISEFUNCTION)) {
+ case AP_NCONSTANT:
+ return (ap_cratio (array, nx, ny, threshold, apstatr (ap,
+ SKYSIGMA)))
+ case AP_NPOISSON:
+ return (ap_pratio (array, nx, ny, threshold, apstatr (ap,
+ SKYSIGMA), apstatr (ap, EPADU)))
+ default:
+ return (MAX_REAL)
+ }
+end
+
+
+# AP_CRATIO -- Procedure to estimate the signal to noise ratio in the
+# centering aperture assuming that the noise is due to a constant sky
+# sigma. These computations are approximate only.
+
+real procedure ap_cratio (array, nx, ny, sky, noise)
+
+real array[nx,ny] # centering buffer
+int nx, ny # dimensions of the centering buffer
+real sky # mean sky value of the data in ADU
+real noise # estimate of sky noise in ADU
+
+int npts
+real signal, tnoise
+real asumr()
+
+begin
+ npts = nx * ny
+ signal = asumr (array, npts) - npts * sky
+ if (IS_INDEFR(noise))
+ tnoise = 0.0
+ else
+ tnoise = sqrt (npts * noise ** 2)
+ if (signal <= 0.0)
+ return (0.0)
+ else if (tnoise <= 0.0)
+ return (MAX_REAL)
+ else
+ return (signal / tnoise)
+end
+
+
+# AP_PRATIO -- Procedure to estimate the signal to noise ratio in the
+# centering aperture assuming the noise is due to a constant sky sigma
+# and poisson statistics in the image. These computations are
+# approximate only.
+
+real procedure ap_pratio (array, nx, ny, sky, noise, padu)
+
+real array[nx,ny] # centering buffer
+int nx, ny # dimensions of the centering buffer
+real sky # mean sky value of the data in ADU
+real noise # estimate of sky noise in ADU
+real padu # photons per adu
+
+int npts
+real signal, tnoise
+real asumr()
+
+begin
+ npts = nx * ny
+ signal = asumr (array, npts) - npts * sky
+ if (IS_INDEFR(noise))
+ tnoise = sqrt (abs (signal / padu))
+ else
+ tnoise = sqrt (abs (signal / padu) + npts * noise ** 2)
+ if (signal <= 0.0)
+ return (0.0)
+ else if (tnoise <= 0.0)
+ return (MAX_REAL)
+ else
+ return (signal / tnoise)
+end
diff --git a/noao/digiphot/apphot/center/apctr1d.x b/noao/digiphot/apphot/center/apctr1d.x
new file mode 100644
index 00000000..10ee109e
--- /dev/null
+++ b/noao/digiphot/apphot/center/apctr1d.x
@@ -0,0 +1,113 @@
+include <mach.h>
+include "../lib/center.h"
+
+# AP_CTR1D -- Procedure to compute the center from the 1D marginal
+# distributions.
+
+int procedure ap_ctr1d (ctrpix, nx, ny, norm, xc, yc, xerr, yerr)
+
+real ctrpix[nx, ny] # object to be centered
+int nx, ny # dimensions of subarray
+real norm # the normalization factor
+real xc, yc # computed centers
+real xerr, yerr # estimate of centering error
+
+pointer sp, xm, ym
+
+begin
+ call smark (sp)
+ call salloc (xm, nx, TY_REAL)
+ call salloc (ym, ny, TY_REAL)
+
+ # Compute the marginal distributions.
+ call ap_mkmarg (ctrpix, Memr[xm], Memr[ym], nx, ny)
+ call adivkr (Memr[xm], real (ny), Memr[xm], nx)
+ call adivkr (Memr[ym], real (nx), Memr[ym], ny)
+
+ # Get the centers and errors.
+ call ap_cmarg (Memr[xm], nx, norm, xc, xerr)
+ call ap_cmarg (Memr[ym], ny, norm, yc, yerr)
+
+ call sfree (sp)
+ return (AP_OK)
+end
+
+
+# AP_CMARG -- Compute the center and estimate its error given the
+# marginal distribution and the number of points.
+
+procedure ap_cmarg (a, npts, norm, xc, err)
+
+real a[npts] # array
+int npts # number of points
+real norm # the normalization factor
+real xc # center value
+real err # error
+
+int i, npos
+real val, sumi, sumix, sumix2
+
+begin
+ # Initialize.
+ npos = 0
+ sumi = 0.0
+ sumix = 0.0
+ sumix2 = 0.0
+
+ # Accumulate the sums.
+ do i = 1, npts {
+ val = a[i]
+ if (val > 0.0)
+ npos = npos + 1
+ sumi = sumi + val
+ sumix = sumix + val * i
+ sumix2 = sumix2 + val * i ** 2
+ }
+
+ # Compute the position and the error.
+ if (npos <= 0) {
+ xc = (1.0 + npts) / 2.0
+ err = INDEFR
+ } else {
+ xc = sumix / sumi
+ err = (sumix2 / sumi - xc * xc)
+ if (err <= 0.0) {
+ err = 0.0
+ } else {
+ err = sqrt (err / (sumi * norm))
+ if (err > real (npts))
+ err = INDEFR
+ }
+ }
+end
+
+
+# AP_MKMARG -- Accumulate the marginal distributions.
+
+procedure ap_mkmarg (ctrpix, xm, ym, nx, ny)
+
+real ctrpix[nx, ny] # pixels
+real xm[nx] # x marginal distribution
+real ym[ny] # y marginal distribution
+int nx, ny # dimensions of array
+
+int i, j
+real sum
+
+begin
+ # Compute the x marginal.
+ do i = 1, nx {
+ sum = 0.0
+ do j = 1, ny
+ sum = sum + ctrpix[i,j]
+ xm[i] = sum
+ }
+
+ # Compute the y marginal.
+ do j = 1, ny {
+ sum = 0.0
+ do i = 1, nx
+ sum = sum + ctrpix[i,j]
+ ym[j] = sum
+ }
+end
diff --git a/noao/digiphot/apphot/center/apctrbuf.x b/noao/digiphot/apphot/center/apctrbuf.x
new file mode 100644
index 00000000..0a8053b8
--- /dev/null
+++ b/noao/digiphot/apphot/center/apctrbuf.x
@@ -0,0 +1,115 @@
+include <imhdr.h>
+include <math.h>
+include <mach.h>
+include "../lib/apphotdef.h"
+include "../lib/centerdef.h"
+include "../lib/center.h"
+
+# APCTRBUF -- Procedure to fetch the center pixels given the pointer to the
+# IRAF image, the coordinates of the initial center and the width of the APPHOT
+# centering box.
+
+int procedure apctrbuf (ap, im, wx, wy)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to the IRAF image
+real wx, wy # center coordinates
+
+int icpix
+pointer ctr
+real cpix, gdatamin, gdatamax, datamin, datamax
+pointer ap_ctrpix()
+
+begin
+ # Get pointer to centering structure.
+ ctr = AP_PCENTER(ap)
+
+ # Check for 0 sized aperture.
+ if (AP_CAPERT(ctr) <= 0.0)
+ return (AP_CTR_NOAREA)
+
+ # Get the centering buffer of pixels.
+ cpix = max (1.0, AP_CAPERT(ctr) * AP_SCALE(ap))
+ icpix = 2 * int (cpix) + 1
+ if (AP_CTRPIX(ctr) != NULL)
+ call mfree (AP_CTRPIX(ctr), TY_REAL)
+ AP_CTRPIX(ctr) = ap_ctrpix (im, wx, wy, icpix,
+ AP_CXC(ctr), AP_CYC(ctr), AP_CNX(ctr), AP_CNY(ctr))
+ if (AP_CTRPIX(ctr) == NULL)
+ return (AP_CTR_NOAREA)
+
+ # Compute the data limits.
+ if (IS_INDEFR(AP_DATAMIN(ap)))
+ gdatamin = -MAX_REAL
+ else
+ gdatamin = AP_DATAMIN(ap)
+ if (IS_INDEFR(AP_DATAMAX(ap)))
+ gdatamax = MAX_REAL
+ else
+ gdatamax = AP_DATAMAX(ap)
+ call alimr (Memr[AP_CTRPIX(ctr)], AP_CNX(ctr) * AP_CNY(ctr),
+ datamin, datamax)
+
+ if (datamin < gdatamin || datamax > gdatamax)
+ return (AP_CTR_BADDATA)
+ else if (AP_CNX(ctr) < icpix || AP_CNY(ctr) < icpix)
+ return (AP_CTR_OUTOFBOUNDS)
+ else
+ return (AP_OK)
+end
+
+
+# AP_CTRPIX -- Procedure to fetch the pixels to be used for centering.
+
+pointer procedure ap_ctrpix (im, wx, wy, capert, xc, yc, nx, ny)
+
+pointer im # pointer to IRAF image
+real wx, wy # center of subraster to be extracted
+int capert # width of subraster to be extracted
+real xc, yc # center of extracted subraster
+int nx, ny # dimensions of extracted subraster
+
+int i, ncols, nlines, c1, c2, l1, l2, half_capert
+pointer buf, lbuf
+real xc1, xc2, xl1, xl2
+pointer imgs2r()
+
+begin
+ # Check for nonsensical input.
+ half_capert = (capert - 1) / 2
+ if (half_capert <= 0)
+ return (NULL)
+
+ # Test for out of bounds pixels
+ ncols = IM_LEN(im,1)
+ nlines = IM_LEN(im,2)
+ xc1 = wx - half_capert
+ xc2 = wx + half_capert
+ xl1 = wy - half_capert
+ xl2 = wy + half_capert
+ if (xc1 > real (ncols) || xc2 < 1.0 || xl1 > real (nlines) || xl2 < 1.0)
+ return (NULL)
+
+ # Get column and line limits, dimensions and center of subraster.
+ c1 = max (1.0, min (real (ncols), xc1)) + 0.5
+ c2 = min (real (ncols), max (1.0, xc2)) + 0.5
+ l1 = max (1.0, min (real (nlines), xl1)) + 0.5
+ l2 = min (real (nlines), max (1.0, xl2)) + 0.5
+ nx = c2 - c1 + 1
+ ny = l2 - l1 + 1
+ xc = wx - c1 + 1
+ yc = wy - l1 + 1
+
+ # Get pixels and return.
+ if (nx < 1 && ny < 1)
+ return (NULL)
+ else {
+ call malloc (buf, nx * ny, TY_REAL)
+ lbuf = buf
+ do i = l1, l2 {
+ call amovr (Memr[imgs2r (im, c1, c2, i, i)], Memr[lbuf], nx)
+ lbuf = lbuf + nx
+ }
+ return (buf)
+ }
+end
diff --git a/noao/digiphot/apphot/center/apfitcen.x b/noao/digiphot/apphot/center/apfitcen.x
new file mode 100644
index 00000000..bd7224e8
--- /dev/null
+++ b/noao/digiphot/apphot/center/apfitcen.x
@@ -0,0 +1,291 @@
+include <mach.h>
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/noisedef.h"
+include "../lib/centerdef.h"
+include "../lib/center.h"
+
+define CONVERT .424660900 # conversion from fwhmpsf to sigma
+
+# APFITCENTER -- Procedure to fit the centers using either 1) the intensity
+# weighted mean of the marginal distributions, 2) a Gaussian fit to the
+# marginals assuming a fixed sigma or 3) a simplified version of the optimal
+# filtering method using a Gaussian of fixed sigma to model the profile.
+
+int procedure apfitcenter (ap, im, wx, wy)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the IRAF image
+real wx, wy # object coordinates
+
+int i, niter, ier, fier, lowsnr
+pointer ctr, nse
+real cthreshold, datamin, datamax, owx, owy, xshift, yshift, med
+int apctrbuf(), ap_ctr1d(), ap_mctr1d(), ap_gctr1d(), ap_lgctr1d()
+real ap_csnratio(), amedr()
+
+begin
+ ctr = AP_PCENTER(ap)
+ nse = AP_NOISE(ap)
+ ier = AP_OK
+
+ # Initialize.
+ AP_CXCUR(ctr) = wx
+ AP_CYCUR(ctr) = wy
+ AP_OXINIT(ctr) = INDEFR
+ AP_OYINIT(ctr) = INDEFR
+ AP_XCENTER(ctr) = INDEFR
+ AP_YCENTER(ctr) = INDEFR
+ AP_OXCENTER(ctr) = INDEFR
+ AP_OYCENTER(ctr) = INDEFR
+ AP_XSHIFT(ctr) = 0.0
+ AP_YSHIFT(ctr) = 0.0
+ AP_OXSHIFT(ctr) = 0.0
+ AP_OYSHIFT(ctr) = 0.0
+ AP_XERR(ctr) = INDEFR
+ AP_YERR(ctr) = INDEFR
+
+ # Return input coordinates if centering is disabled.
+ if (IS_INDEFR(wx) || IS_INDEFR(wy)) {
+ return (AP_CTR_NOAREA)
+ } else if (AP_CENTERFUNCTION(ctr) == AP_NONE) {
+ AP_XCENTER(ctr) = wx
+ AP_YCENTER(ctr) = wy
+ switch (AP_WCSOUT(ap)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (ap, wx, wy, AP_OXINIT(ctr), AP_OYINIT(ctr), 1)
+ call ap_ltoo (ap, wx, wy, AP_OXCENTER(ctr), AP_OYCENTER(ctr), 1)
+ case WCS_TV:
+ call ap_ltov (im, wx, wy, AP_OXINIT(ctr), AP_OYINIT(ctr), 1)
+ call ap_ltov (im, wx, wy, AP_OXCENTER(ctr), AP_OYCENTER(ctr), 1)
+ default:
+ AP_OXINIT(ctr) = wx
+ AP_OYINIT(ctr) = wy
+ AP_OXCENTER(ctr) = wx
+ AP_OYCENTER(ctr) = wy
+ }
+ return (AP_OK)
+ }
+
+ # Intialize.
+ owx = wx
+ owy = wy
+ niter = 0
+ if (IS_INDEFR(AP_SKYSIGMA(nse)) || IS_INDEFR(AP_CTHRESHOLD(ctr)) ||
+ AP_CTHRESHOLD(ctr) <= 0.0)
+ cthreshold = 0.0
+ else
+ cthreshold = AP_CTHRESHOLD(ctr) * AP_SKYSIGMA(nse)
+
+ repeat {
+
+ # Set initial cursor position.
+ AP_CXCUR(ctr) = owx
+ AP_CYCUR(ctr) = owy
+
+ # Get centering pixels.
+ ier = apctrbuf (ap, im, owx, owy)
+ if (ier == AP_CTR_NOAREA) {
+ AP_XCENTER(ctr) = wx
+ AP_YCENTER(ctr) = wy
+ AP_XSHIFT(ctr) = 0.0
+ AP_YSHIFT(ctr) = 0.0
+ AP_XERR(ctr) = INDEFR
+ AP_YERR(ctr) = INDEFR
+ switch (AP_WCSOUT(ap)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (ap, wx, wy, AP_OXINIT(ctr), AP_OYINIT(ctr), 1)
+ call ap_ltoo (ap, wx, wy, AP_OXCENTER(ctr),
+ AP_OYCENTER(ctr), 1)
+ case WCS_TV:
+ call ap_ltov (im, wx, wy, AP_OXINIT(ctr), AP_OYINIT(ctr), 1)
+ call ap_ltov (im, wx, wy, AP_OXCENTER(ctr),
+ AP_OYCENTER(ctr), 1)
+ default:
+ AP_OXINIT(ctr) = wx
+ AP_OYINIT(ctr) = wy
+ AP_OXCENTER(ctr) = wx
+ AP_OYCENTER(ctr) = wy
+ }
+ AP_OXSHIFT(ctr) = 0.0
+ AP_OYSHIFT(ctr) = 0.0
+ return (ier)
+ }
+
+ # Clean the subraster.
+ if (AP_CLEAN(ctr) == YES)
+ call apclean (ap, Memr[AP_CTRPIX(ctr)], AP_CNX(ctr),
+ AP_CNY(ctr), AP_CXC(ctr), AP_CYC(ctr))
+
+ # Compute the datalimits.
+ if (cthreshold <= 0.0)
+ call alimr (Memr[AP_CTRPIX(ctr)], AP_CNX(ctr) * AP_CNY(ctr),
+ datamin, datamax)
+ else {
+ datamin = MAX_REAL
+ datamax = -MAX_REAL
+ do i = 1, AP_CNY(ctr) {
+ med = amedr (Memr[AP_CTRPIX(ctr)+(i-1)*AP_CNX(ctr)],
+ AP_CNX(ctr))
+ if (med < datamin)
+ datamin = med
+ if (med > datamax)
+ datamax = med
+ }
+ }
+
+ # Apply threshold and check for positive or negative features.
+ if (AP_POSITIVE(ap) == YES) {
+ call apsetr (ap, CDATALIMIT, datamin)
+ call asubkr (Memr[AP_CTRPIX(ctr)], datamin +
+ cthreshold, Memr[AP_CTRPIX(ctr)], AP_CNX(ctr) *
+ AP_CNY(ctr))
+ call amaxkr (Memr[AP_CTRPIX(ctr)], 0.0, Memr[AP_CTRPIX(ctr)],
+ AP_CNX(ctr) * AP_CNY(ctr))
+ } else {
+ call apsetr (ap, CDATALIMIT, datamax)
+ call anegr (Memr[AP_CTRPIX(ctr)], Memr[AP_CTRPIX(ctr)],
+ AP_CNX(ctr) * AP_CNY(ctr))
+ call aaddkr (Memr[AP_CTRPIX(ctr)], datamax -
+ cthreshold, Memr[AP_CTRPIX(ctr)], AP_CNX(ctr) *
+ AP_CNY(ctr))
+ call amaxkr (Memr[AP_CTRPIX(ctr)], 0.0,
+ Memr[AP_CTRPIX(ctr)], AP_CNX(ctr) * AP_CNY(ctr))
+ }
+
+ # Test signal to noise ratio.
+ if (ap_csnratio (ap, Memr[AP_CTRPIX(ctr)], AP_CNX(ctr),
+ AP_CNY(ctr), 0.0) < AP_MINSNRATIO(ctr))
+ lowsnr = YES
+ else
+ lowsnr = NO
+
+ # Compute the x and y centers.
+ switch (AP_CENTERFUNCTION(ctr)) {
+
+ case AP_CENTROID1D:
+ if (AP_CTHRESHOLD(ctr) <= 0.0) {
+ fier = ap_mctr1d (Memr[AP_CTRPIX(ctr)], AP_CNX(ctr),
+ AP_CNY(ctr), AP_EPADU(nse), AP_XCENTER(ctr),
+ AP_YCENTER(ctr), AP_XERR(ctr), AP_YERR(ctr))
+ if (IS_INDEFR (AP_XERR(ctr)))
+ AP_XCENTER(ctr) = AP_CXC(ctr)
+ if (IS_INDEFR (AP_YERR(ctr)))
+ AP_YCENTER(ctr) = AP_CYC(ctr)
+ } else {
+ fier = ap_ctr1d (Memr[AP_CTRPIX(ctr)], AP_CNX(ctr),
+ AP_CNY(ctr), AP_EPADU(nse), AP_XCENTER(ctr),
+ AP_YCENTER(ctr), AP_XERR(ctr), AP_YERR(ctr))
+ if (IS_INDEFR (AP_XERR(ctr)))
+ AP_XCENTER(ctr) = AP_CXC(ctr)
+ if (IS_INDEFR (AP_YERR(ctr)))
+ AP_YCENTER(ctr) = AP_CYC(ctr)
+ }
+
+ case AP_GAUSS1D:
+
+ fier = ap_gctr1d (Memr[AP_CTRPIX(ctr)], AP_CNX(ctr),
+ AP_CNY(ctr), CONVERT * AP_FWHMPSF(ap) * AP_SCALE(ap),
+ AP_CMAXITER(ctr), AP_XCENTER(ctr), AP_YCENTER(ctr),
+ AP_XERR(ctr), AP_YERR(ctr))
+
+ case AP_OFILT1D:
+
+ fier = ap_lgctr1d (Memr[AP_CTRPIX(ctr)], AP_CNX(ctr),
+ AP_CNY(ctr), AP_CXC(ctr), AP_CYC(ctr), CONVERT *
+ AP_FWHMPSF(ap) * AP_SCALE(ap), AP_CMAXITER(ctr),
+ AP_EPADU(nse), AP_SKYSIGMA(nse), AP_XCENTER(ctr),
+ AP_YCENTER(ctr), AP_XERR(ctr), AP_YERR(ctr))
+
+ default:
+ # do nothing gracefully
+ }
+
+ # Confine the next x center to the data box.
+ AP_XCENTER(ctr) = max (0.5, min (AP_CNX(ctr) + 0.5,
+ AP_XCENTER(ctr)))
+ xshift = AP_XCENTER(ctr) - AP_CXC(ctr)
+ AP_XCENTER(ctr) = xshift + owx
+ AP_XSHIFT(ctr) = AP_XCENTER(ctr) - wx
+
+ # Confine the next y center to the data box.
+ AP_YCENTER(ctr) = max (0.5, min (AP_CNY(ctr) + 0.5,
+ AP_YCENTER(ctr)))
+ yshift = AP_YCENTER(ctr) - AP_CYC(ctr)
+ AP_YCENTER(ctr) = yshift + owy
+ AP_YSHIFT(ctr) = AP_YCENTER(ctr) - wy
+
+ switch (AP_WCSOUT(ap)) {
+ case WCS_PHYSICAL, WCS_WORLD:
+ call ap_ltoo (ap, AP_XCENTER(ctr), AP_YCENTER(ctr),
+ AP_OXCENTER(ctr), AP_OYCENTER(ctr), 1)
+ call ap_ltoo (ap, AP_XCENTER(ctr) - AP_XSHIFT(ctr),
+ AP_YCENTER(ctr) - AP_YSHIFT(ctr), AP_OXINIT(ctr),
+ AP_OYINIT(ctr), 1)
+ AP_OXSHIFT(ctr) = AP_OXCENTER(ctr) - AP_OXINIT(ctr)
+ AP_OYSHIFT(ctr) = AP_OYCENTER(ctr) - AP_OYINIT(ctr)
+ case WCS_TV:
+ call ap_ltov (im, AP_XCENTER(ctr), AP_YCENTER(ctr),
+ AP_OXCENTER(ctr), AP_OYCENTER(ctr), 1)
+ call ap_ltov (im, AP_XCENTER(ctr) - AP_XSHIFT(ctr),
+ AP_YCENTER(ctr) - AP_YSHIFT(ctr), AP_OXINIT(ctr),
+ AP_OYINIT(ctr), 1)
+ AP_OXSHIFT(ctr) = AP_OXCENTER(ctr) - AP_OXINIT(ctr)
+ AP_OYSHIFT(ctr) = AP_OYCENTER(ctr) - AP_OYINIT(ctr)
+ default:
+ AP_OXINIT(ctr) = AP_XCENTER(ctr) - AP_XSHIFT(ctr)
+ AP_OYINIT(ctr) = AP_YCENTER(ctr) - AP_YSHIFT(ctr)
+ AP_OXCENTER(ctr) = AP_XCENTER(ctr)
+ AP_OYCENTER(ctr) = AP_YCENTER(ctr)
+ AP_OXSHIFT(ctr) = AP_XSHIFT(ctr)
+ AP_OYSHIFT(ctr) = AP_YSHIFT(ctr)
+
+ }
+
+ # Setup for next iteration.
+ niter = niter + 1
+ owx = AP_XCENTER(ctr)
+ owy = AP_YCENTER(ctr)
+
+ } until ((fier != AP_OK && fier != AP_CTR_NOCONVERGE) ||
+ (niter >= AP_CMAXITER(ctr)) || (abs (xshift) < 1.0 &&
+ abs (yshift) < 1.0))
+
+ # Return appropriate error code.
+ if (fier != AP_OK) {
+ AP_XCENTER(ctr) = wx
+ AP_YCENTER(ctr) = wy
+ AP_XSHIFT(ctr) = 0.0
+ AP_YSHIFT(ctr) = 0.0
+ AP_XERR(ctr) = INDEFR
+ AP_YERR(ctr) = INDEFR
+ switch (AP_WCSOUT(ap)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (ap, wx, wy, AP_OXINIT(ctr), AP_OYINIT(ctr), 1)
+ call ap_ltoo (ap, wx, wy, AP_OXCENTER(ctr), AP_OYCENTER(ctr), 1)
+ case WCS_TV:
+ call ap_ltov (im, wx, wy, AP_OXINIT(ctr), AP_OYINIT(ctr), 1)
+ call ap_ltov (im, wx, wy, AP_OXCENTER(ctr), AP_OYCENTER(ctr), 1)
+ default:
+ AP_OXINIT(ctr) = wx
+ AP_OYINIT(ctr) = wy
+ AP_OXCENTER(ctr) = wx
+ AP_OYCENTER(ctr) = wy
+ }
+ AP_OXSHIFT(ctr) = 0.0
+ AP_OYSHIFT(ctr) = 0.0
+ return (fier)
+ } else if (ier == AP_CTR_BADDATA) {
+ return (AP_CTR_BADDATA)
+ } else if (lowsnr == YES) {
+ return (AP_CTR_LOWSNRATIO)
+ } else if (abs (AP_XSHIFT(ctr)) > (AP_MAXSHIFT(ctr) * AP_SCALE(ap))) {
+ return (AP_CTR_BADSHIFT)
+ } else if (abs (AP_YSHIFT(ctr)) > (AP_MAXSHIFT(ctr) * AP_SCALE(ap))) {
+ return (AP_CTR_BADSHIFT)
+ } else if (ier == AP_CTR_OUTOFBOUNDS) {
+ return (AP_CTR_OUTOFBOUNDS)
+ } else {
+ return (AP_OK)
+ }
+end
diff --git a/noao/digiphot/apphot/center/apgcpars.x b/noao/digiphot/apphot/center/apgcpars.x
new file mode 100644
index 00000000..e40db12e
--- /dev/null
+++ b/noao/digiphot/apphot/center/apgcpars.x
@@ -0,0 +1,27 @@
+include "../lib/display.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+
+# AP_GCPARS -- Procedure to read in the centering parameters from the
+# appropriate parameters files.
+
+procedure ap_gcpars (ap)
+
+pointer ap # pointer to the apphot structure
+
+bool clgetb()
+int btoi()
+
+begin
+ # Initialize the structure.
+ call apcinit (ap, AP_CENTROID1D, 2.5, 2.0, AP_NPOISSON)
+
+ # Get the data dependent parameters.
+ call ap_gdapars (ap)
+
+ # Get the centering algorithm parameters.
+ call ap_gcepars (ap)
+
+ # Make radial plots on stdgraph.
+ call apseti (ap, RADPLOTS, btoi (clgetb ("radplots")))
+end
diff --git a/noao/digiphot/apphot/center/apgctr1d.x b/noao/digiphot/apphot/center/apgctr1d.x
new file mode 100644
index 00000000..e0ac8077
--- /dev/null
+++ b/noao/digiphot/apphot/center/apgctr1d.x
@@ -0,0 +1,105 @@
+include <math/nlfit.h>
+include "../lib/center.h"
+
+define NPARS 4 # the total number of parameters
+define NAPARS 3 # the total number of active parameters
+define TOL 0.001 # the tolerance for convergence
+
+# AP_GCTR1D -- Procedure to compute the x and y centers from the 1D marginal
+# distributions using 1D Gaussian fits. Three parameters are fit for each
+# marginal, the amplitude, the center of the Gaussian function itself
+# and a constant background value. The sigma is set by the user and is
+# assumed to be fixed.
+
+int procedure ap_gctr1d (ctrpix, nx, ny, sigma, maxiter, xc, yc, xerr, yerr)
+
+real ctrpix[nx, ny] # data subarray
+int nx, ny # dimensions of data subarray
+real sigma # sigma of PSF
+int maxiter # maximum number of iterations
+real xc, yc # computed centers
+real xerr, yerr # estimate of centering error
+
+extern cgauss1d, cdgauss1d
+int i, minel, maxel, xier, yier, npar, npts
+pointer sp, x, xm, ym, w, fit, list, nl
+real chisqr, variance, p[NPARS], dp[NPARS]
+int locpr()
+
+begin
+ # Check the number of points.
+ if (nx < NAPARS || ny < NAPARS)
+ return (AP_CTR_NTOO_SMALL)
+ npts = max (nx, ny)
+
+ call smark (sp)
+ call salloc (list, NAPARS, TY_INT)
+ call salloc (xm, nx, TY_REAL)
+ call salloc (ym, ny, TY_REAL)
+ call salloc (x, npts, TY_REAL)
+ call salloc (w, npts, TY_REAL)
+ call salloc (fit, npts, TY_REAL)
+ do i = 1, npts
+ Memr[x+i-1] = i
+
+ # Compute the marginal distributions.
+ call ap_mkmarg (ctrpix, Memr[xm], Memr[ym], nx, ny)
+ call adivkr (Memr[xm], real (nx), Memr[xm], nx)
+ call adivkr (Memr[ym], real (ny), Memr[ym], ny)
+
+ # Specify which parameters are to be fit.
+ Memi[list] = 1
+ Memi[list+1] = 2
+ Memi[list+2] = 4
+
+ # Initialize the x fit parameters.
+ call ap_alimr (Memr[xm], nx, p[4], p[1], minel, maxel)
+ p[1] = p[1] - p[4]
+ p[2] = maxel
+ p[3] = sigma ** 2
+
+ # Compute the x center and error.
+ call nlinitr (nl, locpr (cgauss1d), locpr (cdgauss1d), p, dp, NPARS,
+ Memi[list], NAPARS, TOL, maxiter)
+ call nlfitr (nl, Memr[x], Memr[xm], Memr[w], nx, 1, WTS_UNIFORM, xier)
+ call nlvectorr (nl, Memr[x], Memr[fit], nx, 1)
+ call nlpgetr (nl, p, npar)
+ call nlerrorsr (nl, Memr[xm], Memr[fit], Memr[w], nx, variance,
+ chisqr, dp)
+ call nlfreer (nl)
+ xc = p[2]
+ xerr = dp[2] / sqrt (real (nx))
+ if (xerr > real (nx))
+ xerr = INDEFR
+
+ # Initialize the y fit parameters.
+ call ap_alimr (Memr[ym], ny, p[4], p[1], minel, maxel)
+ p[1] = p[1] - p[4]
+ p[2] = maxel
+ p[3] = sigma ** 2
+
+ # Fit the y marginal.
+ call nlinitr (nl, locpr (cgauss1d), locpr (cdgauss1d), p, dp, NPARS,
+ Memi[list], NAPARS, TOL, maxiter)
+ call nlfitr (nl, Memr[x], Memr[ym], Memr[w], ny, 1, WTS_UNIFORM, yier)
+ call nlvectorr (nl, Memr[x], Memr[fit], ny, 1)
+ call nlpgetr (nl, p, npar)
+ call nlerrorsr (nl, Memr[ym], Memr[fit], Memr[w], ny, variance,
+ chisqr, dp)
+ call nlfreer (nl)
+ yc = p[2]
+ yerr = dp[2] / sqrt (real (ny))
+ if (yerr > real (ny))
+ yerr = INDEFR
+
+ # Return the appropriate error code.
+ call sfree (sp)
+ if (xier == NO_DEG_FREEDOM || yier == NO_DEG_FREEDOM)
+ return (AP_CTR_NTOO_SMALL)
+ else if (xier == SINGULAR || yier == SINGULAR)
+ return (AP_CTR_SINGULAR)
+ else if (xier == NOT_DONE || yier == NOT_DONE)
+ return (AP_CTR_NOCONVERGE)
+ else
+ return (AP_OK)
+end
diff --git a/noao/digiphot/apphot/center/apictr.x b/noao/digiphot/apphot/center/apictr.x
new file mode 100644
index 00000000..3a3bd31e
--- /dev/null
+++ b/noao/digiphot/apphot/center/apictr.x
@@ -0,0 +1,48 @@
+# AP_ICTR -- Given a subraster of pixels and an initial center compute
+# the centroid of the pixels.
+
+procedure ap_ictr (im, wx, wy, radius, emission, xcenter, ycenter)
+
+pointer im # pointer to the iraf image
+real wx # initial x coordinate
+real wy # initial y coordinate
+int radius # half width of centering box
+int emission # emission feature
+real xcenter # fitted x coordinate
+real ycenter # fitted y coordinate
+
+int nx, ny, ier
+pointer cbuf
+real xc, yc, datamin, datamax, junk
+int ap_mctr1d()
+pointer ap_ctrpix()
+
+begin
+ # Get the pixels.
+ cbuf = ap_ctrpix (im, wx, wy, radius, xc, yc, nx, ny)
+ if (cbuf == NULL) {
+ xcenter = wx
+ ycenter = wy
+ return
+ }
+
+ # Fit the center of the subraster.
+ call alimr (Memr[cbuf], nx * ny, datamin, datamax)
+ if (emission == YES)
+ call asubkr (Memr[cbuf], datamin, Memr[cbuf], nx * ny)
+ else {
+ call anegr (Memr[cbuf], Memr[cbuf], nx * ny)
+ call aaddkr (Memr[cbuf], datamax, Memr[cbuf], nx * ny)
+ }
+ ier = ap_mctr1d (Memr[cbuf], nx, ny, 1.0, xcenter, ycenter, junk, junk)
+
+ # Compute the center in image coordinates.
+ if (IS_INDEFR(xcenter))
+ xcenter = wx
+ else
+ xcenter = xcenter + wx - xc
+ if (IS_INDEFR(ycenter))
+ ycenter = wy
+ else
+ ycenter = ycenter + wy - yc
+end
diff --git a/noao/digiphot/apphot/center/aplgctr1d.x b/noao/digiphot/apphot/center/aplgctr1d.x
new file mode 100644
index 00000000..ce6d7c53
--- /dev/null
+++ b/noao/digiphot/apphot/center/aplgctr1d.x
@@ -0,0 +1,87 @@
+include <math.h>
+include "../lib/center.h"
+
+define TOL 0.001 # tolerance for fitting algorithm
+
+# AP_LGCTR1D -- Procedure to compute the center from the 1D marginal
+# distributions using a simplified version of the optimal filtering
+# technique and addopting a Gaussian model for the fit. The method
+# is streamlined by replacing the Gaussian with a simple triangle
+# following L.Goad.
+
+int procedure ap_lgctr1d (ctrpix, nx, ny, cx, cy, sigma, maxiter, norm,
+ skysigma, xc, yc, xerr, yerr)
+
+real ctrpix[nx, ny] # object to be centered
+int nx, ny # dimensions of subarray
+real cx, cy # center in subraster coordinates
+real sigma # sigma of PSF
+int maxiter # maximum number of iterations
+real norm # the normalization factor
+real skysigma # standard deviation of the pixels
+real xc, yc # computed centers
+real xerr, yerr # first guess at errors
+
+int nxiter, nyiter
+pointer sp, xm, ym
+real ratio, constant
+
+int aptopt()
+real asumr()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (xm, nx, TY_REAL)
+ call salloc (ym, ny, TY_REAL)
+
+ # Compute the marginal distributions.
+ call ap_mkmarg (ctrpix, Memr[xm], Memr[ym], nx, ny)
+ xerr = asumr (Memr[xm], nx)
+ yerr = asumr (Memr[ym], ny)
+ call adivkr (Memr[xm], real (nx), Memr[xm], nx)
+ call adivkr (Memr[ym], real (ny), Memr[ym], ny)
+
+ # Compute the x center and error.
+ xc = cx
+ nxiter = aptopt (Memr[xm], nx, xc, sigma, TOL, maxiter, YES)
+ if (xerr <= 0.0)
+ xerr = INDEFR
+ else {
+ if (IS_INDEFR(skysigma))
+ constant = 0.0
+ else
+ constant = 4.0 * SQRTOFPI * sigma * skysigma ** 2
+ ratio = constant / xerr
+ xerr = sigma ** 2 / (xerr * norm)
+ xerr = sqrt (max (xerr, ratio * xerr))
+ if (xerr > real (nx))
+ xerr = INDEFR
+ }
+
+ # Compute the y center and error.
+ yc = cy
+ nyiter = aptopt (Memr[ym], ny, yc, sigma, TOL, maxiter, YES)
+ if (yerr <= 0.0)
+ yerr = INDEFR
+ else {
+ if (IS_INDEFR(skysigma))
+ constant = 0.0
+ else
+ constant = 4.0 * SQRTOFPI * sigma * skysigma ** 2
+ ratio = constant / yerr
+ yerr = sigma ** 2 / (yerr * norm)
+ yerr = sqrt (max (yerr, ratio * yerr))
+ if (yerr > real (ny))
+ yerr = INDEFR
+ }
+
+ # Return appropriate error code.
+ call sfree (sp)
+ if (nxiter < 0 || nyiter < 0)
+ return (AP_CTR_SINGULAR)
+ else if (nxiter > maxiter || nyiter > maxiter)
+ return (AP_CTR_NOCONVERGE)
+ else
+ return (AP_OK)
+end
diff --git a/noao/digiphot/apphot/center/apmctr1d.x b/noao/digiphot/apphot/center/apmctr1d.x
new file mode 100644
index 00000000..5dc47f60
--- /dev/null
+++ b/noao/digiphot/apphot/center/apmctr1d.x
@@ -0,0 +1,88 @@
+include <mach.h>
+include "../lib/center.h"
+
+# AP_MCTR1D -- Procedure to compute the center from the 1D marginal
+# distributions.
+
+int procedure ap_mctr1d (ctrpix, nx, ny, norm, xc, yc, xerr, yerr)
+
+real ctrpix[nx, ny] # object to be centered
+int nx, ny # dimensions of subarray
+real norm # the normalization factor
+real xc, yc # computed centers
+real xerr, yerr # estimate of centering error
+
+pointer sp, xm, ym
+
+begin
+ call smark (sp)
+ call salloc (xm, nx, TY_REAL)
+ call salloc (ym, ny, TY_REAL)
+
+ # Compute the marginal distributions.
+ call ap_mkmarg (ctrpix, Memr[xm], Memr[ym], nx, ny)
+ call adivkr (Memr[xm], real (ny), Memr[xm], nx)
+ call adivkr (Memr[ym], real (nx), Memr[ym], ny)
+
+ # Get the centers and errors.
+ call ap_cmmarg (Memr[xm], nx, norm, xc, xerr)
+ call ap_cmmarg (Memr[ym], ny, norm, yc, yerr)
+
+ call sfree (sp)
+ return (AP_OK)
+end
+
+
+# AP_CMMARG -- Compute the center and estimate its error given the
+# marginal distribution and the number of points. The center is estimated
+# using a centroid which is an optimal solution for a gaussian star with
+# no background noise. The centering error is computing using a variance
+# estimate based on a gaussian star with no background noise.
+
+procedure ap_cmmarg (a, npts, norm, xc, err)
+
+real a[npts] # array
+int npts # number of points
+real norm # the normalization factor
+real xc # center value
+real err # error
+
+int i, npos
+real sumi, sumix, sumix2, mean, val
+real asumr()
+
+begin
+ # Initialize.
+ mean = asumr (a, npts) / npts
+ npos = 0
+ sumi = 0.0
+ sumix = 0.0
+ sumix2 = 0.0
+
+ # Accumulate the sums.
+ do i = 1, npts {
+ val = (a[i] - mean)
+ if (val > 0.0) {
+ npos = npos + 1
+ sumi = sumi + val
+ sumix = sumix + val * i
+ sumix2 = sumix2 + val * i ** 2
+ }
+ }
+
+ # Compute the position and the error.
+ if (npos <= 0) {
+ xc = (1.0 + npts) / 2.0
+ err = INDEFR
+ } else {
+ xc = sumix / sumi
+ err = (sumix2 / sumi - xc * xc)
+ if (err <= 0.0) {
+ err = 0.0
+ } else {
+ err = sqrt (err / ((sumi + mean * npts) * norm))
+ if (err > real (npts))
+ err = INDEFR
+ }
+ }
+end
diff --git a/noao/digiphot/apphot/center/appcenter.x b/noao/digiphot/apphot/center/appcenter.x
new file mode 100644
index 00000000..c2590fa3
--- /dev/null
+++ b/noao/digiphot/apphot/center/appcenter.x
@@ -0,0 +1,84 @@
+include "../lib/apphot.h"
+include "../lib/center.h"
+
+# AP_PCENTER -- Procedure to write the output of centering task to a file.
+
+procedure ap_pcenter (ap, fd, id, lid, ier)
+
+pointer ap # pointer to apphot structure
+int fd # output file descriptor
+int id # id of the star
+int lid # list number
+int ier # comment string
+
+real xpos, ypos
+real apstatr()
+
+begin
+ if (fd == NULL)
+ return
+
+ # Print description of object.
+ xpos = apstatr (ap, OXINIT)
+ ypos = apstatr (ap, OYINIT)
+ call ap_wid (ap, fd, xpos, ypos, id, lid, '\\')
+
+ # Print the computed centers.
+ call ap_wcres (ap, fd, ier, ' ')
+end
+
+
+# AP_QCENTER -- Procedure to print a quick summary of the center task output
+# on the standard output.
+
+procedure ap_qcenter (ap, ier)
+
+pointer ap # pointer to apphot structure
+int ier # comment string
+
+real owx, owy, wx, wy
+pointer sp, imname
+real apstatr()
+
+begin
+ call smark (sp)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+
+ owx = apstatr (ap, OXINIT)
+ owy = apstatr (ap, OYINIT)
+ wx = apstatr (ap, OXCENTER)
+ wy = apstatr (ap, OYCENTER)
+
+ call apstats (ap, IMROOT, Memc[imname], SZ_FNAME)
+ call printf ( "%s %7.2f %7.2f %7.2f %7.2f ")
+ call pargstr (Memc[imname])
+ call pargr (owx)
+ call pargr (owy)
+ call pargr (wx)
+ call pargr (wy)
+ call printf ("%6.2f %6.2f %s\n")
+ call pargr (apstatr (ap, XERR))
+ call pargr (apstatr (ap, YERR))
+ if (ier != AP_OK)
+ call pargstr ("err")
+ else
+ call pargstr ("ok")
+
+ call sfree (sp)
+end
+
+
+# AP_CPHDR -- Procedure to write the banner for the center task to the
+# output file.
+
+procedure ap_cphdr (ap, fd)
+
+pointer ap # apphot descriptor
+int fd # output file descriptor
+
+begin
+ if (fd == NULL)
+ return
+ call ap_idhdr (ap, fd)
+ call ap_chdr (ap, fd)
+end
diff --git a/noao/digiphot/apphot/center/appcpars.x b/noao/digiphot/apphot/center/appcpars.x
new file mode 100644
index 00000000..272fcc07
--- /dev/null
+++ b/noao/digiphot/apphot/center/appcpars.x
@@ -0,0 +1,21 @@
+include "../lib/display.h"
+
+# AP_PCPARS -- Procedure to write out the current centering parameters
+# to the current parameter files.
+
+procedure ap_pcpars (ap)
+
+pointer ap # pointer to apphot structure
+bool itob()
+int apstati()
+
+begin
+ # Write the data dependent parameters.
+ call ap_dapars (ap)
+
+ # Write the centering parameters.
+ call ap_cepars (ap)
+
+ # Set the plotting command.
+ call clputb ("radplots", itob (apstati (ap, RADPLOTS)))
+end
diff --git a/noao/digiphot/apphot/center/aprefitcen.x b/noao/digiphot/apphot/center/aprefitcen.x
new file mode 100644
index 00000000..c50e2efb
--- /dev/null
+++ b/noao/digiphot/apphot/center/aprefitcen.x
@@ -0,0 +1,193 @@
+include <mach.h>
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/noisedef.h"
+include "../lib/centerdef.h"
+include "../lib/center.h"
+
+define CONVERT .424660900 # conversion factor from fwhmpsf to sigma
+
+# APREFITCENTER -- Procedure to refit the centers assuming that the appropriate
+# pixel buffer is in memory. See apfitcenter for further information.
+
+int procedure aprefitcenter (ap, im, ier)
+
+pointer ap # pointer to the apphot structure
+pointer im # the input image descriptor
+int ier # previous error code
+
+int fier
+pointer cen, nse
+int ap_ctr1d(), ap_mctr1d(), ap_gctr1d(), ap_lgctr1d()
+
+begin
+ cen = AP_PCENTER(ap)
+ nse = AP_NOISE(ap)
+
+ # Initialize
+ AP_XCENTER(cen) = AP_CXCUR(cen)
+ AP_YCENTER(cen) = AP_CYCUR(cen)
+ AP_XSHIFT(cen) = 0.0
+ AP_YSHIFT(cen) = 0.0
+ AP_OXSHIFT(cen) = 0.0
+ AP_OYSHIFT(cen) = 0.0
+ AP_XERR(cen) = INDEFR
+ AP_YERR(cen) = INDEFR
+
+ # Return if the center is undefined.
+ if (IS_INDEFR(AP_CXCUR(cen)) || IS_INDEFR(AP_CYCUR(cen))) {
+ AP_OXINIT(cen) = INDEFR
+ AP_OYINIT(cen) = INDEFR
+ AP_OXCENTER(cen) = INDEFR
+ AP_OYCENTER(cen) = INDEFR
+ return (AP_CTR_NOAREA)
+ }
+
+ # Convert the coordinates.
+ switch (AP_WCSOUT(ap)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (ap, AP_CXCUR(cen), AP_CYCUR(cen), AP_OXINIT(cen),
+ AP_OYINIT(cen), 1)
+ call ap_ltoo (ap, AP_CXCUR(cen), AP_CYCUR(cen), AP_OXCENTER(cen),
+ AP_OYCENTER(cen), 1)
+ case WCS_TV:
+ call ap_ltov (im, AP_CXCUR(cen), AP_CYCUR(cen), AP_OXINIT(cen),
+ AP_OYINIT(cen), 1)
+ call ap_ltov (im, AP_CXCUR(cen), AP_CYCUR(cen), AP_OXCENTER(cen),
+ AP_OYCENTER(cen), 1)
+ default:
+ AP_OXINIT(cen) = AP_CXCUR(cen)
+ AP_OYINIT(cen) = AP_CYCUR(cen)
+ AP_OXCENTER(cen) = AP_CXCUR(cen)
+ AP_OYCENTER(cen) = AP_CYCUR(cen)
+ }
+
+ # Return input coordinates if no center fitting.
+ if (AP_CENTERFUNCTION(cen) == AP_NONE)
+ return (AP_OK)
+
+ # Choose the centering algorithm.
+ switch (AP_CENTERFUNCTION(cen)) {
+
+ case AP_CENTROID1D:
+
+ # Compute the x and y centroids.
+ if (AP_CTHRESHOLD(cen) <= 0.0) {
+ fier = ap_mctr1d (Memr[AP_CTRPIX(cen)], AP_CNX(cen),
+ AP_CNY(cen), AP_EPADU(nse), AP_XCENTER(cen),
+ AP_YCENTER(cen), AP_XERR(cen), AP_YERR(cen))
+ if (IS_INDEFR(AP_XERR(cen)))
+ AP_XCENTER(cen) = AP_CXC(cen)
+ if (IS_INDEFR(AP_YERR(cen)))
+ AP_YCENTER(cen) = AP_CYC(cen)
+ } else {
+ fier = ap_ctr1d (Memr[AP_CTRPIX(cen)], AP_CNX(cen),
+ AP_CNY(cen), AP_EPADU(nse), AP_XCENTER(cen),
+ AP_YCENTER(cen), AP_XERR(cen), AP_YERR(cen))
+ if (IS_INDEFR(AP_XERR(cen)))
+ AP_XCENTER(cen) = AP_CXC(cen)
+ if (IS_INDEFR(AP_YERR(cen)))
+ AP_YCENTER(cen) = AP_CYC(cen)
+ }
+ AP_XCENTER(cen) = AP_XCENTER(cen) + AP_CXCUR(cen) - AP_CXC(cen)
+ AP_YCENTER(cen) = AP_YCENTER(cen) + AP_CYCUR(cen) - AP_CYC(cen)
+ AP_XSHIFT(cen) = AP_XCENTER(cen) - AP_CXCUR(cen)
+ AP_YSHIFT(cen) = AP_YCENTER(cen) - AP_CYCUR(cen)
+
+ case AP_GAUSS1D:
+
+ # Compute the 1D Gaussian x and y centers.
+ fier = ap_gctr1d (Memr[AP_CTRPIX(cen)], AP_CNX(cen), AP_CNY(cen),
+ CONVERT * AP_FWHMPSF(ap) * AP_SCALE(ap), AP_CMAXITER(cen),
+ AP_XCENTER(cen), AP_YCENTER(cen), AP_XERR(cen), AP_YERR(cen))
+ AP_XCENTER(cen) = AP_XCENTER(cen) + AP_CXCUR(cen) - AP_CXC(cen)
+ AP_YCENTER(cen) = AP_YCENTER(cen) + AP_CYCUR(cen) - AP_CYC(cen)
+ AP_XSHIFT(cen) = AP_XCENTER(cen) - AP_CXCUR(cen)
+ AP_YSHIFT(cen) = AP_YCENTER(cen) - AP_CYCUR(cen)
+
+ case AP_OFILT1D:
+
+ # Compute the Goad 1D x and y centers.
+ fier = ap_lgctr1d (Memr[AP_CTRPIX(cen)], AP_CNX(cen), AP_CNY(cen),
+ AP_CXC(cen), AP_CYC(cen), CONVERT * AP_FWHMPSF(ap) *
+ AP_SCALE(ap), AP_CMAXITER(cen), AP_EPADU(nse),
+ AP_SKYSIGMA(nse), AP_XCENTER(cen), AP_YCENTER(cen),
+ AP_XERR(cen), AP_YERR(cen))
+ AP_XCENTER(cen) = AP_XCENTER(cen) + AP_CXCUR(cen) - AP_CXC(cen)
+ AP_YCENTER(cen) = AP_YCENTER(cen) + AP_CYCUR(cen) - AP_CYC(cen)
+ AP_XSHIFT(cen) = AP_XCENTER(cen) - AP_CXCUR(cen)
+ AP_YSHIFT(cen) = AP_YCENTER(cen) - AP_CYCUR(cen)
+
+ default:
+
+ # do nothing gracefully
+ }
+
+ # Convert the coordinates.
+ switch (AP_WCSOUT(ap)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (ap, AP_XCENTER(cen), AP_YCENTER(cen),
+ AP_OXCENTER(cen), AP_OYCENTER(cen), 1)
+ call ap_ltoo (ap, AP_XCENTER(cen) - AP_XSHIFT(cen),
+ AP_YCENTER(cen) - AP_YSHIFT(cen), AP_OXINIT(cen),
+ AP_OYINIT(cen), 1)
+ AP_OXSHIFT(cen) = AP_OXCENTER(cen) - AP_OXINIT(cen)
+ AP_OYSHIFT(cen) = AP_OYCENTER(cen) - AP_OYINIT(cen)
+ case WCS_TV:
+ call ap_ltov (im, AP_XCENTER(cen), AP_YCENTER(cen),
+ AP_OXCENTER(cen), AP_OYCENTER(cen), 1)
+ call ap_ltov (im, AP_XCENTER(cen) - AP_XSHIFT(cen),
+ AP_YCENTER(cen) - AP_YSHIFT(cen), AP_OXINIT(cen),
+ AP_OYINIT(cen), 1)
+ AP_OXSHIFT(cen) = AP_OXCENTER(cen) - AP_OXINIT(cen)
+ AP_OYSHIFT(cen) = AP_OYCENTER(cen) - AP_OYINIT(cen)
+ default:
+ AP_OXCENTER(cen) = AP_XCENTER(cen)
+ AP_OYCENTER(cen) = AP_YCENTER(cen)
+ AP_OXINIT(cen) = AP_XCENTER(cen) - AP_XSHIFT(cen)
+ AP_OYINIT(cen) = AP_YCENTER(cen) - AP_YSHIFT(cen)
+ AP_OXSHIFT(cen) = AP_XSHIFT(cen)
+ AP_OYSHIFT(cen) = AP_YSHIFT(cen)
+ }
+
+ # Return appropriate error code.
+ if (fier != AP_OK) {
+ AP_XCENTER(cen) = AP_CXCUR(cen)
+ AP_YCENTER(cen) = AP_CYCUR(cen)
+ AP_XSHIFT(cen) = 0.0
+ AP_YSHIFT(cen) = 0.0
+ AP_XERR(cen) = INDEFR
+ AP_YERR(cen) = INDEFR
+ switch (AP_WCSOUT(ap)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (ap, AP_CXCUR(cen), AP_CYCUR(cen), AP_OXINIT(cen),
+ AP_OYINIT(cen), 1)
+ call ap_ltoo (ap, AP_CXCUR(cen), AP_CYCUR(cen),
+ AP_OXCENTER(cen), AP_OYCENTER(cen), 1)
+ case WCS_TV:
+ call ap_ltov (im, AP_CXCUR(cen), AP_CYCUR(cen), AP_OXINIT(cen),
+ AP_OYINIT(cen), 1)
+ call ap_ltov (im, AP_CXCUR(cen), AP_CYCUR(cen),
+ AP_OXCENTER(cen), AP_OYCENTER(cen), 1)
+ default:
+ AP_OXCENTER(cen) = AP_CXCUR(cen)
+ AP_OYCENTER(cen) = AP_CYCUR(cen)
+ AP_OXINIT(cen) = AP_CXCUR(cen)
+ AP_OYINIT(cen) = AP_CYCUR(cen)
+ }
+ AP_OXSHIFT(cen) = 0.0
+ AP_OYSHIFT(cen) = 0.0
+ return (fier)
+ } else if (ier == AP_CTR_BADDATA) {
+ return (AP_CTR_BADDATA)
+ } else if (ier == AP_CTR_LOWSNRATIO) {
+ return (AP_CTR_LOWSNRATIO)
+ } else if (abs (AP_XSHIFT(cen)) > (AP_MAXSHIFT(cen) * AP_SCALE(ap))) {
+ return (AP_CTR_BADSHIFT)
+ } else if (abs (AP_YSHIFT(cen)) > (AP_MAXSHIFT(cen) * AP_SCALE(ap))) {
+ return (AP_CTR_BADSHIFT)
+ } else if (ier == AP_CTR_OUTOFBOUNDS) {
+ return (AP_CTR_OUTOFBOUNDS)
+ } else
+ return (AP_OK)
+end
diff --git a/noao/digiphot/apphot/center/center.key b/noao/digiphot/apphot/center/center.key
new file mode 100644
index 00000000..f71cd8d3
--- /dev/null
+++ b/noao/digiphot/apphot/center/center.key
@@ -0,0 +1,78 @@
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+v Verify the critical parameters
+w Save the current parameters
+d Plot radial profile of current star
+i Interactively set parameters using current star
+f Fit center of current star
+spbar Fit center of current star, output results
+m Move to next star in coordinate list
+n Center next star in coordinate list, output results
+l Center remaining stars in coordinate list, output results
+e Print error messages
+r Rewind the coordinate list
+q Exit task
+
+
+ Colon Commands
+
+:show [data/center] List the parameters
+:m [n] Move to next [nth] star in coordinate list
+:n [n] Center next [nth] star in coordinate list, output results
+
+
+ Colon Parameter Editing Commands
+
+# Image and file name parameters
+
+:image [string] Image name
+:coords [string] Coordinate file name
+:output [string] Output file name
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Full-width half-maximum of PSF (scale units)
+:emission [y/n] Emission feature (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good data value (counts)
+:datamax [value] Maximum good data value (counts)
+
+# Noise parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per adu)
+:readnoise [value] Readout noise (electrons)
+
+# Observations parameters
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Exposure time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observation (time units)
+
+# Centering parameters
+
+:calgorithm [string] Centering algorithm
+:cbox [value] Width of centering box (scale units)
+:cthreshold [value] Centering intensity threshold (sigma)
+:cmaxiter [value] Maximum number of iterations
+:maxshift [value] Maximum center shift (scale units)
+:minsnratio [value] Minimum signal to noise for centering
+:clean [y/n] Clean subraster before centering
+:rclean [value] Cleaning radius (scale units)
+:rclip [value] Clipping radius (scale units)
+:kclean [value] Clean K-sigma rejection limit (sigma)
+
+# Plotting and marking parameters
+
+:mkcenter [y/n] Mark computed centers on the display
+:radplot [y/n] Plot radial profile of object
diff --git a/noao/digiphot/apphot/center/icenter.key b/noao/digiphot/apphot/center/icenter.key
new file mode 100644
index 00000000..0e5379f0
--- /dev/null
+++ b/noao/digiphot/apphot/center/icenter.key
@@ -0,0 +1,12 @@
+ Interactive Center Setup Menu
+
+ v Mark and verify the critical center parameters (f,s,c)
+
+ f Mark and verify the full-width half-maximum of the psf
+ s Mark and verify the standard deviation of the background
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
+
+ c Mark and verify the centering box half-width
+ n Mark and verify the cleaning radius
+ p Mark and verify the clipping radius
diff --git a/noao/digiphot/apphot/center/mkpkg b/noao/digiphot/apphot/center/mkpkg
new file mode 100644
index 00000000..dde81929
--- /dev/null
+++ b/noao/digiphot/apphot/center/mkpkg
@@ -0,0 +1,54 @@
+# CENTER task
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ apbcenter.x ../lib/apphot.h ../lib/display.h \
+ <fset.h>
+ apcconfirm.x ../lib/apphot.h ../lib/noise.h \
+ ../lib/center.h
+ apcencolon.x ../lib/apphot.h ../lib/center.h \
+ ../lib/display.h ../lib/noise.h
+ apcenter.x ../lib/apphot.h ../lib/center.h \
+ ../lib/display.h <ctype.h> \
+ <gset.h> <imhdr.h>
+ apcerrors.x ../lib/center.h
+ apcfree.x ../lib/apphotdef.h ../lib/centerdef.h
+ apictr.x
+ apcinit.x ../lib/apphotdef.h ../lib/center.h \
+ ../lib/centerdef.h
+ apclean.x ../lib/apphot.h ../lib/center.h \
+ ../lib/noise.h
+ appcpars.x ../lib/display.h
+ apcplot.x ../lib/apphot.h ../lib/apphotdef.h \
+ ../lib/center.h ../lib/centerdef.h \
+ ../lib/noise.h <gset.h> \
+ <pkg/gtools.h> <mach.h>
+ apcpshow.x ../lib/center.h ../lib/display.h
+ apcshow.x ../lib/display.h
+ apcsnratio.x ../lib/center.h ../lib/noise.h \
+ <mach.h>
+ apctr1d.x ../lib/center.h <mach.h>
+ apctrbuf.x ../lib/apphotdef.h ../lib/center.h \
+ ../lib/centerdef.h <imhdr.h> <math.h> \
+ <mach.h>
+ apmctr1d.x ../lib/center.h <mach.h>
+ apfitcen.x ../lib/apphotdef.h ../lib/center.h \
+ ../lib/centerdef.h ../lib/noisedef.h \
+ ../lib/apphot.h <mach.h>
+ apgcpars.x ../lib/center.h ../lib/display.h \
+ ../lib/noise.h
+ apgctr1d.x ../lib/center.h <math/nlfit.h>
+ aplgctr1d.x ../lib/center.h <math.h>
+ appcenter.x ../lib/apphot.h ../lib/center.h
+ apcradsetup.x ../lib/display.h
+ aprefitcen.x ../lib/apphotdef.h ../lib/center.h \
+ ../lib/centerdef.h ../lib/noisedef.h \
+ ../lib/apphot.h <mach.h>
+ t_center.x ../lib/apphot.h ../lib/noise.h \
+ <fset.h> <gset.h> \
+ <imhdr.h>
+ ;
diff --git a/noao/digiphot/apphot/center/t_center.x b/noao/digiphot/apphot/center/t_center.x
new file mode 100644
index 00000000..456b93d2
--- /dev/null
+++ b/noao/digiphot/apphot/center/t_center.x
@@ -0,0 +1,306 @@
+include <fset.h>
+include <gset.h>
+include <imhdr.h>
+include "../lib/apphot.h"
+include "../lib/noise.h"
+
+# T_CENTER -- Procedure to compute accurate centers for a list of objects
+# given a list of starting centers, a set of starting parameters and a list
+# of images.
+
+procedure t_center ()
+
+pointer image # pointer to name of the image
+pointer output # pointer to output file name
+pointer coords # pointer to coordinate file
+pointer plotfile # name of plot metacode file
+pointer graphics # pointer to graphics device
+pointer display # pointer to display device
+int interactive # interactive mode
+int cache # cache image buffer in memory
+int verify # verify parameters
+int update # update parameters
+int verbose # verbose mode
+
+pointer sp, str, cname, outfname, ap, im, id, gd, mgd
+int limlist, lclist, lolist, sid, lid, cl, pfd, out, root, stat, memstat
+int imlist, clist, olist, wcs, req_size, old_size, buf_size
+
+pointer immap(), gopen()
+int imtlen(), imtgetim(), clplen(), clgfil(), btoi(), fnldir(), strncmp()
+int open(), strlen(), apcenter(), imtopenp(), clpopnu(), clgwrd()
+int ap_memstat(), sizeof()
+bool clgetb(), streq()
+errchk gopen
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (coords, SZ_FNAME, TY_CHAR)
+ call salloc (plotfile, SZ_FNAME, TY_CHAR)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+ call salloc (display, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (cname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Set standard output to flush on newline.
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get input and output file names.
+ imlist = imtopenp ("image")
+ limlist = imtlen (imlist)
+ clist = clpopnu ("coords")
+ lclist = clplen (clist)
+ olist = clpopnu ("output")
+ lolist = clplen (olist)
+
+ # Check that image and coordinate list lengths match.
+ if (limlist < 1 || (lclist > 1 && lclist != limlist)) {
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+ call error (0, "Imcompatible image and coordinate list lengths")
+ }
+
+ # Check that image and output list lengths match.
+ if (lolist > 1 && lolist != limlist) {
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+ call error (0, "Imcompatible image and output list lengths")
+ }
+
+ call clgstr ("icommands.p_filename", Memc[cname], SZ_FNAME)
+ if (Memc[cname] != EOS)
+ interactive = NO
+ #else if (lclist == 0)
+ #interactive = YES
+ else
+ interactive = btoi (clgetb ("interactive"))
+ cache = btoi (clgetb ("cache"))
+ verbose = btoi (clgetb ("verbose"))
+ verify = btoi (clgetb ("verify"))
+ update = btoi (clgetb ("update"))
+
+ # Get the centering parameters.
+ call ap_gcpars (ap)
+
+ # confirm the centering algorithm parameters.
+ if (verify == YES && interactive == NO) {
+ call ap_cconfirm (ap, NULL, 1)
+ if (update == YES)
+ call ap_pcpars (ap)
+ }
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_LINE, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (ap, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_LINE, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (ap, WCSOUT, wcs)
+
+ # Get the graphics and display devices.
+ call clgstr ("graphics", Memc[graphics], SZ_FNAME)
+ call clgstr ("display", Memc[display], SZ_FNAME)
+
+ # Open the graphics and image deisplay devices.
+ if (interactive == YES) {
+ if (Memc[graphics] == EOS)
+ gd = NULL
+ else {
+ iferr {
+ gd = gopen (Memc[graphics], APPEND+AW_DEFER, STDGRAPH)
+ } then {
+ call eprintf (
+ "Warning: Error opening the graphics device.\n")
+ gd = NULL
+ }
+ }
+ if (Memc[display] == EOS)
+ id = NULL
+ else if (streq (Memc[graphics], Memc[display]))
+ id = gd
+ else {
+ iferr {
+ id = gopen (Memc[display], APPEND, STDIMAGE)
+ } then {
+ call eprintf (
+ "Warning: Graphics overlay not available for display device.\n")
+ id = NULL
+ }
+ }
+ } else {
+ gd = NULL
+ id = NULL
+ }
+
+ # Open the plot metacode file.
+ call clgstr ("plotfile", Memc[plotfile], SZ_FNAME)
+ if (Memc[plotfile] == EOS)
+ pfd = NULL
+ else
+ pfd = open (Memc[plotfile], APPEND, BINARY_FILE)
+ if (pfd != NULL)
+ mgd = gopen (Memc[graphics], NEW_FILE, pfd)
+ else
+ mgd = NULL
+
+ # Begin looping over the image list.
+ sid = 1
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open image.
+ im = immap (Memc[image], READ_ONLY, 0)
+ call apimkeys (ap, im, Memc[image])
+
+ # Set the image display viewport.
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[image], im, 4)
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+
+ # Open the coordinate file; where coords is assumed to be a simple
+ # text file in which the x and y positions are in columns 1 and 2
+ # respectively and all remaining fields are ignored.
+
+ if (lclist <= 0) {
+ cl = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (clist, Memc[coords], SZ_FNAME)
+ root = fnldir (Memc[coords], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[coords+root], 7) == 0 || root ==
+ strlen (Memc[coords])) {
+ call ap_inname (Memc[image], Memc[outfname], "coo",
+ Memc[outfname], SZ_FNAME)
+ lclist = limlist
+ cl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else if (stat != EOF) {
+ call strcpy (Memc[coords], Memc[outfname], SZ_FNAME)
+ cl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else {
+ call apstats (ap, CLNAME, Memc[outfname], SZ_FNAME)
+ call seek (cl, BOF)
+ }
+ }
+ call apsets (ap, CLNAME, Memc[outfname])
+ call apfroot (Memc[outfname], Memc[str], SZ_LINE)
+ call apsets (ap, CLROOT, Memc[str])
+
+ # Open output text file; if output is "default", dir$default or
+ # a directory specification then the extension "ctr" is added to
+ # the root image name and a suitable version number is appended to
+ # the output name. If the output string is null then no output
+ # file is created.
+
+ if (lolist == 0) {
+ out = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (olist, Memc[output], SZ_FNAME)
+ root = fnldir (Memc[output], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[output+root], 7) == 0 || root ==
+ strlen (Memc[output])) {
+ call apoutname (Memc[image], Memc[outfname], "ctr",
+ Memc[outfname], SZ_FNAME)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ lolist = limlist
+ } else if (stat != EOF) {
+ call strcpy (Memc[output], Memc[outfname], SZ_FNAME)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ } else
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ }
+ call apsets (ap, OUTNAME, Memc[outfname])
+
+ # Fit the centers.
+ if (interactive == NO) {
+ if (Memc[cname] != EOS)
+ stat = apcenter (ap, im, cl, NULL, mgd, NULL, out, sid,
+ NO, cache)
+ else if (cl != NULL) {
+ lid = 1
+ call apbcenter (ap, im, cl, out, sid, lid, mgd, id,
+ verbose)
+ stat = NO
+ } else
+ stat = NO
+ } else
+ stat = apcenter (ap, im, cl, gd, mgd, id, out, sid, YES, cache)
+
+ # Close up image, coordinates, and output file.
+ call imunmap (im)
+ if (cl != NULL) {
+ if (lclist > 1)
+ call close (cl)
+ }
+ if (out != NULL && lolist != 1) {
+ call close (out)
+ if (sid <= 1) {
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ call delete (Memc[outfname])
+ }
+ sid = 1
+ }
+
+ # Uncache memory.
+ call fixmem (old_size)
+
+ if (stat == YES)
+ break
+
+ }
+
+ # If only one coordinate file for a list of images close it.
+ if (cl != NULL && lclist == 1)
+ call close (cl)
+
+ # If only one output file defined for a list of images close it.
+ if (out != NULL && lolist == 1) {
+ call close (out)
+ if (sid <= 1) {
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ call delete (Memc[outfname])
+ }
+ }
+
+ # Close up graphics and image display streams and the plot files.
+ if (id == gd && id != NULL)
+ call gclose (gd)
+ else {
+ if (gd != NULL)
+ call gclose (gd)
+ if (id != NULL)
+ call gclose (id)
+ }
+ if (mgd != NULL)
+ call gclose (mgd)
+ if (pfd != NULL)
+ call close (pfd)
+
+ # Free centering structure.
+ call apcfree (ap)
+
+ # Close up the file lists.
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/centerpars.par b/noao/digiphot/apphot/centerpars.par
new file mode 100644
index 00000000..1692b29e
--- /dev/null
+++ b/noao/digiphot/apphot/centerpars.par
@@ -0,0 +1,14 @@
+# CENTERPARS
+
+calgorithm,s,h,"centroid","|centroid|gauss|none|ofilter|",,Centering algorithm
+cbox,r,h,5.0,,,Centering box width in scale units
+cthreshold,r,h,0.0,,,Centering threshold in sigma above background
+minsnratio,r,h,1.0,0.0,,Minimum signal-to-noise ratio for centering algorithm
+cmaxiter,i,h,10,,,Maximum number of iterations for centering algorithm
+maxshift,r,h,1.0,,,Maximum center shift in scale units
+clean,b,h,no,,,Symmetry clean before centering ?
+rclean,r,h,1.0,,,Cleaning radius in scale units
+rclip,r,h,2.0,,,Clipping radius in scale units
+kclean,r,h,3.0,,,Rejection limit in sigma
+mkcenter,b,h,no,,,Mark the computed center on display ?
+mode,s,h,'ql'
diff --git a/noao/digiphot/apphot/daofind.par b/noao/digiphot/apphot/daofind.par
new file mode 100644
index 00000000..b6af78c1
--- /dev/null
+++ b/noao/digiphot/apphot/daofind.par
@@ -0,0 +1,21 @@
+# DAOFIND
+
+image,s,a,,,,"Input image(s)"
+output,f,h,"default",,,"The output coordinates list(s) (default: image.coo.?)"
+starmap,s,h,"",,,"The output density enhancement image(s)"
+skymap,s,h,"",,,"The output sky image(s)"
+datapars,pset,h,"",,,"Data dependent parameters"
+findpars,pset,h,"",,,"Object detection parameters"
+boundary,s,h,nearest,,,"Boundary extension (constant, nearest, reflect, wrap)"
+constant,r,h,0.0,,,"Constant for constant boundary extension"
+interactive,b,h,no,,,"Interactive mode ?"
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor: [x y wcs] key [cmd]"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the image pixels ?"
+verify,b,h,)_.verify,,,"Verify critical parameters in non-interactive mode ?"
+update,b,h,)_.update,,,"Update critical parameters in non-interactive mode ?"
+verbose,b,h,)_.verbose,,,"Print messages in non-interactive mode ?"
+graphics,s,h,)_.graphics,,,"Graphics device"
+display,s,h,)_.display,,,"Display device"
+mode,s,h,'ql'
diff --git a/noao/digiphot/apphot/daofind/apbfdfind.x b/noao/digiphot/apphot/daofind/apbfdfind.x
new file mode 100644
index 00000000..acf34ae4
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/apbfdfind.x
@@ -0,0 +1,139 @@
+include <imhdr.h>
+include <imio.h>
+include <mach.h>
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/find.h"
+
+# AP_BFDFIND -- Find stars in an image using a pattern matching
+# technique.
+
+procedure ap_bfdfind (im, cnv, sky, out, ap, boundary, constant, verbose)
+
+pointer im # pointer to the input image
+pointer cnv # pointer to the convolved image
+pointer sky # pointer to the sky image
+int out # the output file descriptor
+pointer ap # pointer to the apphot structure
+int boundary # type of boundary extension
+real constant # constant for constant boundary extension
+int verbose # verbose switch
+
+int norm, nxk, nyk, nstars, stid
+pointer sp, gker2d, ngker2d, dker2d, skip
+real a, b, c, f, gsums[LEN_GAUSS], skysigma, skymode, threshold, relerr
+real dmax, dmin, xsigsq, ysigsq
+int apstati(), ap_find()
+real ap_egkernel(), apstatr()
+
+begin
+ # Compute the parameters of the Gaussian kernel.
+ call ap_egparams (FWHM_TO_SIGMA * apstatr (ap, FWHMPSF) *
+ apstatr (ap, SCALE), apstatr (ap, RATIO), apstatr (ap, THETA),
+ apstatr (ap, NSIGMA), a, b, c, f, nxk, nyk)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (gker2d, nxk * nyk, TY_REAL)
+ call salloc (ngker2d, nxk * nyk, TY_REAL)
+ call salloc (dker2d, nxk * nyk, TY_REAL)
+ call salloc (skip, nxk * nyk, TY_INT)
+
+ # Compute the 1 and 2 D kernels.
+ if (IS_INDEFR(apstatr(ap, DATAMIN)) && IS_INDEFR(apstatr(ap,
+ DATAMAX))) {
+ norm = YES
+ dmin = -MAX_REAL
+ dmax = MAX_REAL
+ } else {
+ norm = NO
+ if (IS_INDEFR(apstatr (ap, DATAMIN)))
+ dmin = -MAX_REAL
+ else
+ dmin = apstatr (ap, DATAMIN)
+ if (IS_INDEFR(apstatr (ap, DATAMAX)))
+ dmax = MAX_REAL
+ else
+ dmax = apstatr (ap, DATAMAX)
+ }
+ relerr = ap_egkernel (Memr[gker2d], Memr[ngker2d], Memr[dker2d],
+ Memi[skip], nxk, nyk, gsums, a, b, c, f)
+
+ # Set up the image boundary extension characteristics.
+ call ap_imset (im, boundary, max (1 + nxk / 2, 1 + nyk / 2),
+ constant)
+ call ap_imset (cnv, boundary, max (1 + nxk / 2, 1 + nyk / 2),
+ constant)
+
+ # Convolve the input image with the Gaussian kernel. The resultant
+ # picture constains in each pixel the height of the Gaussian
+ # function centered in the subarray which best represents the data
+ # within a circle of nsigma * sigma of the Gaussian.
+
+ if (IM_ACMODE(cnv) != READ_ONLY) {
+ if (norm == YES)
+ call ap_fconvolve (im, cnv, sky, Memr[ngker2d], Memr[dker2d],
+ Memi[skip], nxk, nyk, gsums[GAUSS_SGOP])
+ else
+ call ap_gconvolve (im, cnv, sky, Memr[gker2d], Memi[skip],
+ nxk, nyk, gsums, dmin, dmax)
+ }
+
+ # Save the task parameters in the database file if the savepars
+ # switch is enabled, otherwise a simple list of detected objects
+ # is written to the data base file.
+
+ call ap_wfdparam (out, ap)
+
+ # Find all the objects in the input image with the specified image
+ # characteristics.
+
+ if (verbose == YES) {
+ call printf ("\nImage: %s ")
+ call pargstr (IM_HDRFILE(im))
+ call printf ("fwhmpsf: %g ratio: %g theta: %g nsigma: %g\n\n")
+ call pargr (apstatr (ap, FWHMPSF))
+ call pargr (apstatr (ap, RATIO))
+ call pargr (apstatr (ap, THETA))
+ call pargr (apstatr (ap, NSIGMA))
+ }
+
+ # Get the skymode and threshold.
+ skysigma = apstatr (ap, SKYSIGMA)
+ if (IS_INDEFR(skysigma)) {
+ skymode = 0.0
+ threshold = 0.0
+ } else {
+ skymode = apstatr (ap, EPADU) * (skysigma ** 2 -
+ (apstatr (ap, READNOISE) / apstatr (ap, EPADU)) ** 2)
+ skymode = max (0.0, skymode)
+ threshold = apstatr (ap, THRESHOLD) * skysigma
+ }
+
+ # Compute the x and y sigma.
+ xsigsq = (apstatr (ap, SCALE) * apstatr (ap, FWHMPSF) / 2.35482) ** 2
+ ysigsq = (apstatr (ap, SCALE) * apstatr (ap, RATIO) *
+ apstatr (ap, FWHMPSF) / 2.35482) ** 2
+
+ # Find the stars.
+ stid = 1
+ nstars = ap_find (ap, im, cnv, out, NULL, Memr[gker2d],
+ Memi[skip], nxk, nyk, skymode, threshold, relerr,
+ apstati (ap,POSITIVE), xsigsq, ysigsq, dmin, dmax,
+ apstatr (ap, SHARPLO), apstatr (ap, SHARPHI), apstatr (ap,
+ ROUNDLO), apstatr (ap, ROUNDHI), verbose, stid, NO)
+
+ if (verbose == YES) {
+ call printf (
+ "\nthreshold: %g relerr: %5.3f %g <= sharp <= %g ")
+ call pargr (threshold)
+ call pargr (relerr)
+ call pargr (apstatr (ap, SHARPLO))
+ call pargr (apstatr (ap, SHARPHI))
+ call printf ("%g <= round <= %g \n\n")
+ call pargr (apstatr (ap, ROUNDLO))
+ call pargr (apstatr (ap, ROUNDHI))
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/daofind/apconvolve.x b/noao/digiphot/apphot/daofind/apconvolve.x
new file mode 100644
index 00000000..0c6f58aa
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/apconvolve.x
@@ -0,0 +1,320 @@
+include <imhdr.h>
+include <imset.h>
+include "../lib/find.h"
+
+# AP_FCONVOLVE -- Solve for the density enhancement image and optionally
+# the sky enhancement image in the case where datamin and datamax are not
+# defined.
+
+procedure ap_fconvolve (im, den, sky, kernel1, kernel2, skip, nxk, nyk, const2)
+
+pointer im # pointer to the input image
+pointer den # pointer to the output density image
+pointer sky # pointer to the output sky image
+real kernel1[nxk,nyk] # the first convolution kernel
+real kernel2[nxk,nyk] # the second convolution kernel
+int skip[nxk,nyk] # the skip array
+int nxk, nyk # dimensions of the kernel
+real const2 # subtraction constant for the skyimage
+
+int i, ncols, nlines, col1, col2, inline, outline
+pointer sp, lineptrs, outbuf1, outbuf2
+pointer imgs2r(), impl2r()
+errchk imgs2r, impl2r, imflush
+
+begin
+ # Set up an array of linepointers.
+ call smark (sp)
+ call salloc (lineptrs, nyk, TY_POINTER)
+
+ # Set the number of image buffers.
+ call imseti (im, IM_NBUFS, nyk)
+
+ ncols = IM_LEN(den,1)
+ nlines = IM_LEN(den,2)
+
+ # Set input image column limits.
+ col1 = 1 - nxk / 2
+ col2 = IM_LEN(im,1) + nxk / 2
+
+ # Initialise the line buffers.
+ inline = 1 - nyk / 2
+ do i = 1 , nyk - 1 {
+ Memi[lineptrs+i] = imgs2r (im, col1, col2, inline, inline)
+ inline = inline + 1
+ }
+
+ # Generate the output image line by line.
+ do outline = 1, nlines {
+
+ # Scroll the input buffers.
+ do i = 1, nyk - 1
+ Memi[lineptrs+i-1] = Memi[lineptrs+i]
+
+ # Read in new image line.
+ Memi[lineptrs+nyk-1] = imgs2r (im, col1, col2, inline,
+ inline)
+
+ # Get first output image line.
+ outbuf1 = impl2r (den, outline)
+ if (outbuf1 == EOF)
+ call error (0, "Error writing first output image.")
+
+ # Generate first output image line.
+ call aclrr (Memr[outbuf1], ncols)
+ do i = 1, nyk
+ call ap_skcnvr (Memr[Memi[lineptrs+i-1]], Memr[outbuf1],
+ ncols, kernel1[1,i], skip[1,i], nxk)
+
+ if (sky != NULL) {
+
+ # Get second output image line.
+ outbuf2 = impl2r (sky, outline)
+ if (outbuf2 == EOF)
+ call error (0, "Error writing second output image.")
+
+ # Generate second output image line.
+ call aclrr (Memr[outbuf2], ncols)
+ do i = 1, nyk
+ call ap_skcnvr (Memr[Memi[lineptrs+i-1]], Memr[outbuf2],
+ ncols, kernel2[1,i], skip[1,i], nxk)
+ call ap_w1sur (Memr[outbuf2], Memr[outbuf1], Memr[outbuf2],
+ ncols, -const2)
+ }
+
+ inline = inline + 1
+ }
+
+ # Flush the output image(s).
+ call imflush (den)
+ if (sky != NULL)
+ call imflush (sky)
+
+ # Free the image buffer pointers.
+ call sfree (sp)
+end
+
+
+# AP_GCONVOLVE -- Solve for the density enhancement image and optionally
+# the sky enhancement image in the case where datamin and datamax are defined.
+
+procedure ap_gconvolve (im, den, sky, kernel1, skip, nxk, nyk, gsums,
+ datamin, datamax)
+
+pointer im # pointer to the input image
+pointer den # pointer to the output density image
+pointer sky # pointer to the output sky image
+real kernel1[nxk,nyk] # the first convolution kernel
+int skip[nxk,nyk] # the sky array
+int nxk, nyk # dimensions of the kernel
+real gsums[ARB] # array of kernel sums
+real datamin, datamax # the good data minimum and maximum
+
+int i, ncols, nlines, col1, col2, inline, outline
+pointer sp, lineptrs, sd, sgd, sg, sgsq, p, outbuf2
+pointer imgs2r(), impl2r()
+errchk imgs2r, impl2r, imflush
+
+begin
+ # Set up an array of linepointers.
+ call smark (sp)
+ call salloc (lineptrs, nyk, TY_POINTER)
+
+ # Set the number of image buffers.
+ call imseti (im, IM_NBUFS, nyk)
+
+ ncols = IM_LEN(den,1)
+ nlines = IM_LEN(den,2)
+
+ # Allocate some working space.
+ call salloc (sd, ncols, TY_REAL)
+ call salloc (sgsq, ncols, TY_REAL)
+ call salloc (sg, ncols, TY_REAL)
+ call salloc (p, ncols, TY_REAL)
+
+ # Set input image column limits.
+ col1 = 1 - nxk / 2
+ col2 = IM_LEN(im,1) + nxk / 2
+
+ # Initialise the line buffers.
+ inline = 1 - nyk / 2
+ do i = 1 , nyk - 1 {
+ Memi[lineptrs+i] = imgs2r (im, col1, col2, inline, inline)
+ inline = inline + 1
+ }
+
+ # Generate the output image line by line.
+ do outline = 1, nlines {
+
+ # Scroll the input buffers.
+ do i = 1, nyk - 1
+ Memi[lineptrs+i-1] = Memi[lineptrs+i]
+
+ # Read in new image line.
+ Memi[lineptrs+nyk-1] = imgs2r (im, col1, col2, inline,
+ inline)
+
+ # Get first output image line.
+ sgd = impl2r (den, outline)
+ if (sgd == EOF)
+ call error (0, "Error writing first output image.")
+
+ # Generate first output image line.
+ call aclrr (Memr[sgd], ncols)
+ call aclrr (Memr[sd], ncols)
+ call amovkr (gsums[GAUSS_SUMG], Memr[sg], ncols)
+ call amovkr (gsums[GAUSS_SUMGSQ], Memr[sgsq], ncols)
+ call amovkr (gsums[GAUSS_PIXELS], Memr[p], ncols)
+ do i = 1, nyk
+ call ap_gdsum (Memr[Memi[lineptrs+i-1]], Memr[sgd], Memr[sd],
+ Memr[sg], Memr[sgsq], Memr[p], ncols, kernel1[1,i],
+ skip[1,i], nxk, datamin, datamax)
+ call ap_gdavg (Memr[sgd], Memr[sd], Memr[sg], Memr[sgsq],
+ Memr[p], ncols, gsums[GAUSS_PIXELS], gsums[GAUSS_DENOM],
+ gsums[GAUSS_SGOP])
+
+ if (sky != NULL) {
+
+ # Get second output image line.
+ outbuf2 = impl2r (sky, outline)
+ if (outbuf2 == EOF)
+ call error (0, "Error writing second output image.")
+
+ # Generate second output image line.
+ call ap_davg (Memr[sd], Memr[sgd], Memr[sg], Memr[p],
+ Memr[outbuf2], ncols)
+ }
+
+ inline = inline + 1
+ }
+
+ # Flush the output image(s).
+ call imflush (den)
+ if (sky != NULL)
+ call imflush (sky)
+
+ # Free the image buffer pointers.
+ call sfree (sp)
+end
+
+
+# AP_SKCNVR -- Compute the convolution kernel using a skip array.
+
+procedure ap_skcnvr (in, out, npix, kernel, skip, nk)
+
+real in[npix+nk-1] # the input vector
+real out[npix] # the output vector
+int npix # the size of the vector
+real kernel[ARB] # the convolution kernel
+int skip[ARB] # the skip array
+int nk # the size of the convolution kernel
+
+int i, j
+real sum
+
+begin
+ do i = 1, npix {
+ sum = out[i]
+ do j = 1, nk {
+ if (skip[j] == YES)
+ next
+ sum = sum + in[i+j-1] * kernel[j]
+ }
+ out[i] = sum
+ }
+end
+
+
+# AP_GDSUM -- Compute the vector sums required to do the convolution.
+
+procedure ap_gdsum (in, sgd, sd, sg, sgsq, p, npix, kernel, skip, nk,
+ datamin, datamax)
+
+real in[npix+nk-1] # the input vector
+real sgd[ARB] # the computed input/output convolution vector
+real sd[ARB] # the computed input/output sum vector
+real sg[ARB] # the input/ouput first normalization factor
+real sgsq[ARB] # the input/ouput second normalization factor
+real p[ARB] # the number of points vector
+int npix # the size of the vector
+real kernel[ARB] # the convolution kernel
+int skip[ARB] # the skip array
+int nk # the size of the convolution kernel
+real datamin, datamax # the good data limits.
+
+int i, j
+real data
+
+begin
+ do i = 1, npix {
+ do j = 1, nk {
+ if (skip[j] == YES)
+ next
+ data = in[i+j-1]
+ if (data < datamin || data > datamax) {
+ sgsq[i] = sgsq[i] - kernel[j] ** 2
+ sg[i] = sg[i] - kernel[j]
+ p[i] = p[i] - 1.0
+ } else {
+ sgd[i] = sgd[i] + kernel[j] * data
+ sd[i] = sd[i] + data
+ }
+ }
+ }
+end
+
+
+# AP_GDAVG -- Compute the vector averages required to do the convolution.
+
+procedure ap_gdavg (sgd, sd, sg, sgsq, p, npix, pixels, denom, sgop)
+
+real sgd[ARB] # the computed input/output convolution vector
+real sd[ARB] # the computed input/output sum vector
+real sg[ARB] # the input/ouput first normalization factor
+real sgsq[ARB] # the input/ouput second normalization factor
+real p[ARB] # the number of points vector
+int npix # the size of the vector
+real pixels # number of pixels
+real denom # kernel normalization factor
+real sgop # kernel normalization factor
+
+int i
+
+begin
+ do i = 1, npix {
+ if (p[i] > 1.5) {
+ if (p[i] < pixels) {
+ sgsq[i] = sgsq[i] - (sg[i] ** 2) / p[i]
+ if (sgsq[i] != 0.0)
+ sgd[i] = (sgd[i] - sg[i] * sd[i] / p[i]) / sgsq[i]
+ else
+ sgd[i] = 0.0
+ } else
+ sgd[i] = (sgd[i] - sgop * sd[i]) / denom
+ } else
+ sgd[i] = 0.0
+ }
+end
+
+
+# AP_DAVG -- Generate the results the optional sky output image.
+
+procedure ap_davg (sd, sgd, sg, p, out, npix)
+
+real sd[ARB] # the computed input/output sum vector
+real sgd[ARB] # the computed input/output convolution vector
+real sg[ARB] # the input/ouput first normalization factor
+real p[ARB] # the number of points vector
+real out[ARB] # the output array
+int npix # the size of the vector
+
+int i
+
+begin
+ do i = 1, npix {
+ if (p[i] > 0.0)
+ out[i] = (sd[i] - sgd[i] * sg[i]) / p[i]
+ else
+ out[i] = 0.0
+ }
+end
diff --git a/noao/digiphot/apphot/daofind/apegkernel.x b/noao/digiphot/apphot/daofind/apegkernel.x
new file mode 100644
index 00000000..3023098d
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/apegkernel.x
@@ -0,0 +1,132 @@
+include <math.h>
+include "../lib/find.h"
+
+# Set up the gaussian fitting structure.
+
+# AP_EGPARAMS -- Calculate the parameters of the elliptical Gaussian needed
+# to compute the kernel.
+
+procedure ap_egparams (sigma, ratio, theta, nsigma, a, b, c, f, nx, ny)
+
+real sigma # sigma of Gaussian in x
+real ratio # Ratio of half-width in y to x
+real theta # position angle of Gaussian
+real nsigma # limit of convolution
+real a, b, c, f # ellipse parameters
+int nx, ny # dimensions of the kernel
+
+real sx2, sy2, cost, sint, discrim
+bool fp_equalr ()
+
+begin
+ # Define some temporary variables.
+ sx2 = sigma ** 2
+ sy2 = (ratio * sigma) ** 2
+ cost = cos (DEGTORAD (theta))
+ sint = sin (DEGTORAD (theta))
+
+ # Compute the ellipse parameters.
+ if (fp_equalr (ratio, 0.0)) {
+ if (fp_equalr (theta, 0.0) || fp_equalr (theta, 180.)) {
+ a = 1. / sx2
+ b = 0.0
+ c = 0.0
+ } else if (fp_equalr (theta, 90.0)) {
+ a = 0.0
+ b = 0.0
+ c = 1. / sx2
+ } else
+ call error (0, "AP_EGPARAMS: Cannot make 1D Gaussian.")
+ f = nsigma ** 2 / 2.
+ nx = 2 * int (max (sigma * nsigma * abs (cost), RMIN)) + 1
+ ny = 2 * int (max (sigma * nsigma * abs (sint), RMIN)) + 1
+ } else {
+ a = cost ** 2 / sx2 + sint ** 2 / sy2
+ b = 2. * (1.0 / sx2 - 1.0 / sy2) * cost * sint
+ c = sint ** 2 / sx2 + cost ** 2 / sy2
+ discrim = b ** 2 - 4. * a * c
+ f = nsigma ** 2 / 2.
+ nx = 2 * int (max (sqrt (-8. * c * f / discrim), RMIN)) + 1
+ ny = 2 * int (max (sqrt (-8. * a * f / discrim), RMIN)) + 1
+ }
+end
+
+
+# AP_EGKERNEL -- Compute the elliptical Gaussian kernel.
+
+real procedure ap_egkernel (gkernel, ngkernel, dkernel, skip, nx, ny, gsums, a,
+ b, c, f)
+
+real gkernel[nx,ny] # output Gaussian amplitude kernel
+real ngkernel[nx,ny] # output normalized Gaussian amplitude kernel
+real dkernel[nx,ny] # output Gaussian sky kernel
+int skip[nx,ny] # output skip subraster
+int nx, ny # input dimensions of the kernel
+real gsums[ARB] # output array of gsums
+real a, b, c, f # ellipse parameters
+
+int i, j, x0, y0, x, y
+real npts, rjsq, rsq, relerr,ef
+
+begin
+ # Initialize.
+ x0 = nx / 2 + 1
+ y0 = ny / 2 + 1
+ gsums[GAUSS_SUMG] = 0.0
+ gsums[GAUSS_SUMGSQ] = 0.0
+ npts = 0.0
+
+ # Compute the kernel and principal sums.
+ do j = 1, ny {
+ y = j - y0
+ rjsq = y ** 2
+ do i = 1, nx {
+ x = i - x0
+ rsq = sqrt (x ** 2 + rjsq)
+ ef = 0.5 * (a * x ** 2 + c * y ** 2 + b * x * y)
+ gkernel[i,j] = exp (-1.0 * ef)
+ if (ef <= f || rsq <= RMIN) {
+ #gkernel[i,j] = exp (-ef)
+ ngkernel[i,j] = gkernel[i,j]
+ dkernel[i,j] = 1.0
+ gsums[GAUSS_SUMG] = gsums[GAUSS_SUMG] + gkernel[i,j]
+ gsums[GAUSS_SUMGSQ] = gsums[GAUSS_SUMGSQ] +
+ gkernel[i,j] ** 2
+ skip[i,j] = NO
+ npts = npts + 1.0
+ } else {
+ #gkernel[i,j] = 0.0
+ ngkernel[i,j] = 0.0
+ dkernel[i,j] = 0.0
+ skip[i,j] = YES
+ }
+ }
+ }
+
+ # Store the remaining sums.
+ gsums[GAUSS_PIXELS] = npts
+ gsums[GAUSS_DENOM] = gsums[GAUSS_SUMGSQ] - gsums[GAUSS_SUMG] ** 2 /
+ npts
+ gsums[GAUSS_SGOP] = gsums[GAUSS_SUMG] / npts
+
+ # Normalize the amplitude kernel.
+ do j = 1, ny {
+ do i = 1, nx {
+ if (skip[i,j] == NO)
+ ngkernel[i,j] = (gkernel[i,j] - gsums[GAUSS_SGOP]) /
+ gsums[GAUSS_DENOM]
+ }
+ }
+
+ # Normalize the sky kernel
+ do j = 1, ny {
+ do i = 1, nx {
+ if (skip[i,j] == NO)
+ dkernel[i,j] = dkernel[i,j] / npts
+ }
+ }
+
+ relerr = 1.0 / gsums[GAUSS_DENOM]
+
+ return (sqrt (relerr))
+end
diff --git a/noao/digiphot/apphot/daofind/apfdcolon.x b/noao/digiphot/apphot/daofind/apfdcolon.x
new file mode 100644
index 00000000..cb618bb9
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/apfdcolon.x
@@ -0,0 +1,282 @@
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/noise.h"
+include "../lib/find.h"
+
+# AP_FDCOLON -- Process colon commands from the daofind task.
+
+procedure ap_fdcolon (ap, im, out, stid, cmdstr, newimage, newbuf, newfit)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the iraf image
+int out # output file descriptor
+int stid # output file sequence number
+char cmdstr # command string
+int newimage # new mage ?
+int newbuf # new center buffer ?
+int newfit # new center fit ?
+
+int cl, junk
+pointer sp, incmd, outcmd
+int strdic()
+
+begin
+ call smark (sp)
+ call salloc (incmd, SZ_LINE, TY_CHAR)
+ call salloc (outcmd, SZ_LINE, TY_CHAR)
+
+ # Get the command.
+ call sscan (cmdstr)
+ call gargwrd (Memc[incmd], SZ_LINE)
+ if (Memc[incmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command making sure that the pointer to the
+ # coords file is always NULL.
+ if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, APCMDS) != 0) {
+ cl = NULL
+ call ap_apcolon (ap, im, cl, out, stid, junk, cmdstr, newimage,
+ junk, junk, junk, junk, newbuf, newfit)
+ if (cl != NULL) {
+ call close (cl)
+ cl = NULL
+ call apsets (ap, CLNAME, "")
+ }
+ } else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, NCMDS) != 0) {
+ call ap_nscolon (ap, im, out, stid, cmdstr, junk, junk,
+ junk, junk, newbuf, newfit)
+ } else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, FCMDS) != 0) {
+ call ap_fcolon (ap, out, stid, cmdstr, newbuf, newfit)
+ } else {
+ call ap_fimcolon (ap, cmdstr)
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_FCOLON -- Process colon commands for setting the find algorithm
+# parameters.
+
+procedure ap_fcolon (ap, out, stid, cmdstr, newbuf, newfit)
+
+pointer ap # pointer to the apphot structure
+int out # output file descriptor
+int stid # file number id
+char cmdstr[ARB] # command string
+int newbuf, newfit # change magnitude parameters
+
+bool bval
+int ncmd
+pointer sp, cmd, str
+real rval
+
+bool itob()
+int strdic(), nscan(), btoi(), apstati()
+real apstatr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Get the command.
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, FCMDS)
+ switch (ncmd) {
+
+ case FCMD_NSIGMA:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_NSIGMA)
+ call pargr (apstatr (ap, NSIGMA))
+ call pargstr (UN_FSIGMA)
+ } else {
+ call apsetr (ap, NSIGMA, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_NSIGMA, rval, UN_FSIGMA,
+ "size of kernel in sigma")
+ newbuf = YES; newfit = YES
+ }
+
+ case FCMD_RATIO:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_RATIO)
+ call pargr (apstatr (ap, RATIO))
+ call pargstr (UN_FNUMBER)
+ } else {
+ call apsetr (ap, RATIO, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_RATIO, rval, UN_FNUMBER,
+ "sigma y / x of Gaussian kernel")
+ newbuf = YES; newfit = YES
+ }
+
+ case FCMD_SHARPLO:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_SHARPLO)
+ call pargr (apstatr (ap, SHARPLO))
+ call pargstr (UN_FNUMBER)
+ } else {
+ call apsetr (ap, SHARPLO, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_SHARPLO, rval, UN_FNUMBER,
+ "lower sharpness bound")
+ newfit = YES
+ }
+
+ case FCMD_SHARPHI:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_SHARPHI)
+ call pargr (apstatr (ap, SHARPHI))
+ call pargstr (UN_FNUMBER)
+ } else {
+ call apsetr (ap, SHARPHI, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_SHARPHI, rval, UN_FNUMBER,
+ "upper sharpness bound")
+ newfit = YES
+ }
+
+ case FCMD_ROUNDLO:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_ROUNDLO)
+ call pargr (apstatr (ap, ROUNDLO))
+ call pargstr (UN_FNUMBER)
+ } else {
+ call apsetr (ap, ROUNDLO, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_ROUNDLO, rval, UN_FNUMBER,
+ "lower roundness bound")
+ newfit = YES
+ }
+
+ case FCMD_ROUNDHI:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_ROUNDHI)
+ call pargr (apstatr (ap, ROUNDHI))
+ call pargstr (UN_FNUMBER)
+ } else {
+ call apsetr (ap, ROUNDHI, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_ROUNDHI, rval, UN_FNUMBER,
+ "upper roundness bound")
+ newfit = YES
+ }
+
+ case FCMD_MKDETECTIONS:
+ call gargb (bval)
+ if (nscan () == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (KY_MKDETECTIONS)
+ call pargb (itob (apstati (ap, MKDETECTIONS)))
+ } else
+ call apseti (ap, MKDETECTIONS, btoi (bval))
+
+ case FCMD_THETA:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_THETA)
+ call pargr (apstatr (ap, THETA))
+ call pargstr (UN_FDEGREES)
+ } else {
+ call apsetr (ap, THETA, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_THETA, rval, UN_FDEGREES,
+ "position angle")
+ newbuf = YES; newfit = YES
+ }
+
+ case FCMD_THRESHOLD:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_THRESHOLD)
+ call pargr (apstatr (ap, THRESHOLD))
+ call pargstr (UN_FSIGMA)
+ } else {
+ call apsetr (ap, THRESHOLD, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_THRESHOLD, rval, UN_FSIGMA,
+ "detection threshold in sigma")
+ newfit = YES
+ }
+
+ default:
+ call printf ("Unknown or ambiguous colon command\7\n")
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_FIMCOLON -- Process colon commands for the daofind task that do
+# not affect the data dependent or find parameters.
+
+procedure ap_fimcolon (ap, cmdstr)
+
+pointer ap # pointer to the apphot structure
+char cmdstr[ARB] # command string
+
+int ncmd
+pointer sp, cmd
+int strdic()
+
+begin
+ # Get the command.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, MISC1)
+ switch (ncmd) {
+ case ACMD_SHOW:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, FSHOWARGS)
+ switch (ncmd) {
+ case FCMD_DATA:
+ call printf ("\n")
+ call ap_nshow (ap)
+ call printf ("\n")
+ case FCMD_FIND:
+ call printf ("\n")
+ call ap_fshow (ap)
+ call printf ("\n")
+ default:
+ call printf ("\n")
+ call ap_fdshow (ap)
+ call printf ("\n")
+ }
+ default:
+ call printf ("Unknown or ambiguous colon command\7\n")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/daofind/apfdconfirm.x b/noao/digiphot/apphot/daofind/apfdconfirm.x
new file mode 100644
index 00000000..ce69cbd9
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/apfdconfirm.x
@@ -0,0 +1,22 @@
+# AP_FDCONFIRM -- Procedure to confirm the critical daofind parameters.
+
+procedure ap_fdconfirm (ap)
+
+pointer ap # pointer to the apphot structure
+
+real rval
+real ap_vfwhmpsf(), ap_vsigma(), ap_vthreshold()
+real ap_vdatamin(), ap_vdatamax()
+
+begin
+ call printf ("\n")
+
+ # Verify the critical parameters.
+ rval = ap_vfwhmpsf (ap)
+ rval = ap_vsigma (ap)
+ rval = ap_vthreshold (ap)
+ rval = ap_vdatamin (ap)
+ rval = ap_vdatamax (ap)
+
+ call printf ("\n")
+end
diff --git a/noao/digiphot/apphot/daofind/apfdfind.x b/noao/digiphot/apphot/daofind/apfdfind.x
new file mode 100644
index 00000000..7778c946
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/apfdfind.x
@@ -0,0 +1,213 @@
+include <imhdr.h>
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/find.h"
+
+define HELPFILE "apphot$daofind/daofind.key"
+
+# AP_FDFIND -- Find objects in an image interactively.
+
+int procedure ap_fdfind (denname, skyname, ap, im, gd, id, out, boundary,
+ constant, save, skysave, interactive, cache)
+
+char denname[ARB] # name of density enhancement image
+char skyname[ARB] # name of the fitted sky image
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the IRAF image
+pointer gd # pointer to the graphics stream
+pointer id # pointer to the image display stream
+int out # output file descriptor
+int boundary # type of boundary extension
+real constant # constatn for constant boundary extension
+int save # save convolved image
+int skysave # save the sky image
+int interactive # interactive mode
+int cache # cache the input image pixels
+
+real wx, wy
+pointer sp, cmd, root, den, sky
+int wcs, key, newimage, newden, newfit, stid, memstat, req_size, old_size
+int buf_size
+
+real apstatr()
+pointer ap_immap()
+int clgcur(), apgqverify(), apgtverify(), sizeof(), ap_memstat()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (root, SZ_FNAME, TY_CHAR)
+
+ # Initialize cursor command.
+ key = ' '
+ Memc[cmd] = EOS
+ call strcpy (" ", Memc[root], SZ_FNAME)
+
+ # Initialize fitting parameters.
+ den = NULL
+ sky = NULL
+ newimage = NO
+ newden = YES
+ newfit = YES
+ memstat = NO
+
+ # Loop over the cursor commands.
+ stid = 1
+ while (clgcur ("icommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+
+ # Store the current cursor coordinates.
+ call ap_vtol (im, wx, wy, wx, wy, 1)
+ call apsetr (ap, CWX, wx)
+ call apsetr (ap, CWY, wy)
+
+ # Process the colon commands.
+ switch (key) {
+
+ # Quit.
+ case 'q':
+ if (interactive == YES && apgqverify ("daofind",
+ ap, key) == YES) {
+ call sfree (sp)
+ if (den != NULL) {
+ call imunmap (den)
+ if (save == NO)
+ call imdelete (denname)
+ }
+ if (sky != NULL)
+ call imunmap (sky)
+ return (apgtverify (key))
+ } else {
+ if (den != NULL) {
+ call imunmap (den)
+ if (save == NO)
+ call imdelete (denname)
+ }
+ if (sky != NULL)
+ call imunmap (sky)
+ call sfree (sp)
+ return (YES)
+ }
+
+ # Get information on keystroke commands.
+ case '?':
+ if ((id != NULL) && (gd == id))
+ call gpagefile (id, HELPFILE, "")
+ else if (interactive == YES)
+ call pagefile (HELPFILE, "[space=morehelp,q=quit,?=help]")
+
+ # Plot a centered stellar radial profile
+ case 'd':
+ if (interactive == YES)
+ call ap_qrad (ap, im, wx, wy, gd)
+
+ # Interactively set the daofind parameters.
+ case 'i':
+ if (interactive == YES) {
+ call ap_fdradsetup (ap, im, wx, wy, gd, out, stid)
+ newden = YES
+ newfit = YES
+ }
+
+ # Verify the critical daofind parameters.
+ case 'v':
+ call ap_fdconfirm (ap)
+ newden = YES
+ newfit = YES
+
+ # Save daofind parameters in the pset files.
+ case 'w':
+ call ap_fdpars (ap)
+
+ # Process apphot : commands.
+ case ':':
+ call ap_fdcolon (ap, im, out, stid, Memc[cmd], newimage,
+ newden, newfit)
+
+ # Determine the viewport and data window of image display.
+ if (newimage == YES) {
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[cmd], im, 4)
+ req_size = MEMFUDGE * (IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im)) + 2 * IM_LEN(im,1) *
+ IM_LEN(im,2) * sizeof (TY_REAL))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+ }
+ newimage = NO
+
+ # Find the stars.
+ case 'f', ' ':
+
+ if (newden == YES) {
+
+ if (den != NULL) {
+ call imunmap (den)
+ call imdelete (denname)
+ }
+ den = ap_immap (denname, im, ap, save)
+ if (memstat == YES)
+ call ap_pcache (den, INDEFI, buf_size)
+
+ if (sky != NULL)
+ call imunmap (sky)
+ if (skysave == YES) {
+ sky = ap_immap (skyname, im, ap, YES)
+ if (memstat == YES)
+ call ap_pcache (den, INDEFI, buf_size)
+ } else
+ sky = NULL
+ newden = NO
+
+ if (key == 'f') {
+ call ap_fdstars (im, ap, den, sky, NULL, id,
+ boundary, constant, NO, stid)
+ } else {
+ call ap_outmap (ap, out, Memc[root])
+ call ap_fdstars (im, ap, den, sky, out, id,
+ boundary, constant, NO, stid)
+ newfit = NO
+ }
+
+ } else if (newfit == YES) {
+
+ if (key == 'f') {
+ call ap_fdstars (im, ap, den, sky, NULL, id,
+ boundary, constant, YES, stid)
+ } else {
+ call ap_outmap (ap, out, Memc[root])
+ call ap_fdstars (im, ap, den, sky, out, id,
+ boundary, constant, YES, stid)
+ newfit = NO
+ }
+
+ } else {
+ call printf ("Detection parameters have not changed\n")
+ }
+
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ stid = 1
+ #newden = NO
+ #newfit = NO
+
+ default:
+ # do nothing
+ call printf ("Unknown or ambiguous keystroke command\n")
+ }
+
+ # Setup for the next object.
+ key = ' '
+ Memc[cmd] = EOS
+ call apsetr (ap, WX, apstatr (ap, CWX))
+ call apsetr (ap, WY, apstatr (ap, CWY))
+
+ }
+
+end
diff --git a/noao/digiphot/apphot/daofind/apfdfree.x b/noao/digiphot/apphot/daofind/apfdfree.x
new file mode 100644
index 00000000..3f1ea762
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/apfdfree.x
@@ -0,0 +1,34 @@
+include "../lib/apphotdef.h"
+
+# AP_FDFREE -- Free the apphot data structure.
+
+procedure ap_fdfree (ap)
+
+pointer ap # pointer to the apphot structure
+
+begin
+ if (ap == NULL)
+ return
+ if (AP_NOISE(ap) != NULL)
+ call ap_noisecls (ap)
+ if (AP_PFIND(ap) != NULL)
+ call ap_fdcls (ap)
+ if (AP_PDISPLAY(ap) != NULL)
+ call ap_dispcls (ap)
+ if (AP_IMBUF(ap) != NULL)
+ call mfree (AP_IMBUF(ap), TY_REAL)
+ if (AP_MW(ap) != NULL)
+ call mw_close (AP_MW(ap))
+ call mfree (ap, TY_STRUCT)
+end
+
+
+# AP_FDCLS -- Free the find data structure.
+
+procedure ap_fdcls (ap)
+
+pointer ap # pointer to the apphot structure
+
+begin
+ call mfree (AP_PFIND(ap), TY_STRUCT)
+end
diff --git a/noao/digiphot/apphot/daofind/apfdgpars.x b/noao/digiphot/apphot/daofind/apfdgpars.x
new file mode 100644
index 00000000..95d87d23
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/apfdgpars.x
@@ -0,0 +1,20 @@
+include "../lib/noise.h"
+include "../lib/display.h"
+
+# AP_FDGPARS -- Open up the apphot data structure and get the daofind input
+# parameters.
+
+procedure ap_fdgpars (ap)
+
+pointer ap # pointer to the apphot structure
+
+begin
+ # Open the apphot structure.
+ call ap_fdinit (ap, 2.0, AP_NPOISSON)
+
+ # Get the data dependent parameters.
+ call ap_gdapars (ap)
+
+ # Get the find parameters.
+ call ap_gfipars (ap)
+end
diff --git a/noao/digiphot/apphot/daofind/apfdinit.x b/noao/digiphot/apphot/daofind/apfdinit.x
new file mode 100644
index 00000000..9c31b494
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/apfdinit.x
@@ -0,0 +1,59 @@
+include "../lib/apphotdef.h"
+include "../lib/finddef.h"
+
+# AP_FDINIT - Initialize the daofind data structure.
+
+procedure ap_fdinit (ap, fwhmpsf, noise)
+
+pointer ap # pointer to the apphot structure
+real fwhmpsf # FWHM of the PSF
+int noise # noise function
+
+begin
+ # Allocate space.
+ call malloc (ap, LEN_APSTRUCT, TY_STRUCT)
+
+ # Set the default global apphot package parameters.
+ call ap_defsetup (ap, fwhmpsf)
+
+ # Setup the noise structure.
+ call ap_noisesetup (ap, noise)
+
+ # Setup the display structure.
+ call ap_dispsetup (ap)
+
+ # Setup the find structure.
+ call ap_fdsetup (ap)
+
+ # Unused structures are set to null.
+ AP_PCENTER(ap) = NULL
+ AP_PSKY(ap) = NULL
+ AP_PPSF(ap) = NULL
+ AP_PPHOT(ap) = NULL
+ AP_POLY(ap) = NULL
+ AP_RPROF(ap) = NULL
+end
+
+
+# AP_FDSETUP -- Initialize the find structure.
+
+procedure ap_fdsetup (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+pointer fnd
+
+begin
+ call malloc (AP_PFIND(ap), LEN_FIND, TY_STRUCT)
+ fnd = AP_PFIND(ap)
+
+ AP_RATIO(fnd) = DEF_RATIO
+ AP_THETA(fnd) = DEF_RATIO
+ AP_NSIGMA(fnd) = DEF_NSIGMA
+
+ AP_THRESHOLD(fnd) = DEF_THRESHOLD
+ AP_SHARPLO(fnd) = DEF_SHARPLO
+ AP_SHARPHI(fnd) = DEF_SHARPHI
+ AP_ROUNDLO(fnd) = DEF_ROUNDLO
+ AP_ROUNDHI(fnd) = DEF_ROUNDLO
+end
diff --git a/noao/digiphot/apphot/daofind/apfdpars.x b/noao/digiphot/apphot/daofind/apfdpars.x
new file mode 100644
index 00000000..108f205b
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/apfdpars.x
@@ -0,0 +1,16 @@
+include "../lib/display.h"
+
+# AP_FDPARS -- Write out the current daofind parameters to the current
+# parameter files.
+
+procedure ap_fdpars (ap)
+
+pointer ap # pointer to apphot structure
+
+begin
+ # Write the data dependent parameters.
+ call ap_dapars (ap)
+
+ # Write the daofind parameters.
+ call ap_fipars (ap)
+end
diff --git a/noao/digiphot/apphot/daofind/apfdradsetup.x b/noao/digiphot/apphot/daofind/apfdradsetup.x
new file mode 100644
index 00000000..708d2690
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/apfdradsetup.x
@@ -0,0 +1,82 @@
+define HELPFILE "apphot$daofind/idaofind.key"
+
+# AP_FDRADSETUP -- Procedure to set up daofind interactively using the radial
+# profile plot of a bright star.
+
+procedure ap_fdradsetup (ap, im, wx, wy, gd, out, stid)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to the IRAF image
+real wx, wy # cursor coordinates
+pointer gd # pointer to graphics stream
+int out # output file descriptor
+int stid # output file sequence number)
+
+int key, wcs
+pointer sp, cmd
+real rmin, rmax, imin, imax, xcenter, ycenter, rval
+real u1, u2, v1, v2, x1, x2, y1, y2
+int ap_showplot(), clgcur()
+real ap_cfwhmpsf(), ap_csigma(), ap_cdatamin(), ap_cdatamax()
+
+begin
+ # Check for open graphics stream.
+ if (gd == NULL)
+ return
+ call greactivate (gd, 0)
+
+ # Store the old viewport and window coordinates.
+ call ggview (gd, u1, u2, v1, v2)
+ call ggwind (gd, x1, x2, y1, y2)
+
+ # Make the plot.
+ if (ap_showplot (ap, im, wx, wy, gd, xcenter, ycenter, rmin, rmax,
+ imin, imax) == ERR) {
+ call gdeactivate (gd, 0)
+ return
+ }
+
+ # Initialize.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ call printf (
+ "Waiting for setup menu command (?=help, v=default setup, q=quit):\n")
+ while (clgcur ("gcommands", xcenter, ycenter, wcs, key, Memc[cmd],
+ SZ_LINE) != EOF) {
+
+ # Enter the cursor setup loop.
+ switch (key) {
+ case 'q':
+ break
+ case '?':
+ call gpagefile (gd, HELPFILE, "")
+ case 'f':
+ rval = ap_cfwhmpsf (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 's':
+ rval = ap_csigma (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'l':
+ rval = ap_cdatamin (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'u':
+ rval = ap_cdatamax (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'v':
+ rval = ap_cfwhmpsf (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_csigma (ap, gd, out, stid, rmin, rmax, imin, imax)
+ default:
+ call printf ("Unknown or ambiguous keystroke command\007\n")
+ }
+ call printf (
+ "Waiting for setup menu command (?=help, v=default setup, q=quit):\n")
+ }
+
+ # Interactive setup is complete.
+ call printf (
+ "Interactive setup is complete. Type w to store parameters.\n")
+
+ # Restore the viewport and window coordinates.
+ call gsview (gd, u1, u2, v1, v2)
+ call gswind (gd, x1, x2, y1, y2)
+
+ call gdeactivate (gd, 0)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/daofind/apfdshow.x b/noao/digiphot/apphot/daofind/apfdshow.x
new file mode 100644
index 00000000..61be95ca
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/apfdshow.x
@@ -0,0 +1,72 @@
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/find.h"
+
+# AP_FDSHOW -- Display the current find parameters.
+
+procedure ap_fdshow (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+begin
+ call ap_nshow (ap)
+ call printf ("\n")
+ call ap_fshow (ap)
+end
+
+
+# AP_FSHOW -- Procedure to display the current data parameters.
+
+procedure ap_fshow (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+pointer sp, str
+bool itob()
+int apstati()
+real apstatr()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Set the object charactersitics.
+ call printf ("Kernel Parameters\n")
+ call printf (" %s = %g %s %s = %b\n")
+ call pargstr (KY_FWHMPSF)
+ call pargr (apstatr (ap, FWHMPSF))
+ call pargstr (UN_ASCALEUNIT)
+ call pargstr (KY_POSITIVE)
+ call pargb (itob (apstati (ap, POSITIVE)))
+
+ call printf (" %s = %g %s %s = %g %s = %g %s\n")
+ call pargstr (KY_NSIGMA)
+ call pargr (apstatr (ap, NSIGMA))
+ call pargstr (UN_FSIGMA)
+ call pargstr (KY_RATIO)
+ call pargr (apstatr (ap, RATIO))
+ call pargstr (KY_THETA)
+ call pargr (apstatr (ap, THETA))
+ call pargstr (UN_FDEGREES)
+
+ # Print the rest of the data dependent parameters.
+ call printf ("\nDetection Parameters\n")
+ call printf (" %s = %g %s\n")
+ call pargstr (KY_THRESHOLD)
+ call pargr (apstatr (ap, THRESHOLD))
+ call pargstr (UN_FSIGMA)
+
+ call printf (" %s = %g %s = %g\n")
+ call pargstr (KY_SHARPLO)
+ call pargr (apstatr (ap, SHARPLO))
+ call pargstr (KY_SHARPHI)
+ call pargr (apstatr (ap, SHARPHI))
+
+ call printf (" %s = %g %s = %g\n")
+ call pargstr (KY_ROUNDLO)
+ call pargr (apstatr (ap, ROUNDLO))
+ call pargstr (KY_ROUNDHI)
+ call pargr (apstatr (ap, ROUNDHI))
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/daofind/apfdstars.x b/noao/digiphot/apphot/daofind/apfdstars.x
new file mode 100644
index 00000000..893619f5
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/apfdstars.x
@@ -0,0 +1,151 @@
+include <imhdr.h>
+include <mach.h>
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/display.h"
+include "../lib/find.h"
+
+# AP_FDSTARS -- Find stars in an image using a pattern matching technique.
+
+procedure ap_fdstars (im, ap, cnv, sky, out, id, boundary, constant,
+ refit, stid)
+
+pointer im # pointer to the input image
+pointer ap # pointer to the apphot structure
+pointer cnv # pointer to the convolved image
+pointer sky # pointer to the sky image
+int out # the output file descriptor
+pointer id # pointer to image display stream
+int boundary # type of boundary extension
+real constant # constant for constant boundary extension
+int refit # detect stars again
+int stid # output file sequence number
+
+int norm, nxk, nyk, nstars
+pointer sp, str, gker2d, ngker2d, dker2d, skip
+real a, b, c, f, skysigma, skymode, threshold, relerr, gsums[LEN_GAUSS]
+real dmin, dmax, xsigsq, ysigsq
+int apstati(), ap_find()
+real ap_egkernel(), apstatr()
+data gker2d/NULL/, ngker2d/NULL/, dker2d/NULL/ skip /NULL/
+
+define detect_ 99
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ if (refit == YES)
+ goto detect_
+
+ # Compute the parameters of the Gaussian kernel.
+ call ap_egparams (FWHM_TO_SIGMA * apstatr (ap, FWHMPSF) * apstatr (ap,
+ SCALE), apstatr (ap, RATIO), apstatr (ap, THETA), apstatr (ap,
+ NSIGMA), a, b, c, f, nxk, nyk)
+
+ # Allocate working space.
+ if (gker2d != NULL)
+ call mfree (gker2d, TY_REAL)
+ call malloc (gker2d, nxk * nyk, TY_REAL)
+ if (ngker2d != NULL)
+ call mfree (ngker2d, TY_REAL)
+ call malloc (ngker2d, nxk * nyk, TY_REAL)
+ if (dker2d != NULL)
+ call mfree (dker2d, TY_REAL)
+ call malloc (dker2d, nxk * nyk, TY_REAL)
+ if (skip != NULL)
+ call mfree (skip, TY_INT)
+ call malloc (skip, nxk * nyk, TY_INT)
+
+ # Compute the 1 and 2 D kernels.
+ if (IS_INDEFR(apstatr(ap, DATAMIN)) && IS_INDEFR(apstatr(ap,
+ DATAMAX))) {
+ norm = YES
+ dmin = -MAX_REAL
+ dmax = MAX_REAL
+ } else {
+ norm = NO
+ if (IS_INDEFR(apstatr (ap, DATAMIN)))
+ dmin = -MAX_REAL
+ else
+ dmin = apstatr (ap, DATAMIN)
+ if (IS_INDEFR(apstatr (ap, DATAMAX)))
+ dmax = MAX_REAL
+ else
+ dmax = apstatr (ap, DATAMAX)
+ }
+ relerr = ap_egkernel (Memr[gker2d], Memr[ngker2d], Memr[dker2d],
+ Memi[skip], nxk, nyk, gsums, a, b, c, f)
+
+ # Set up the image boundary extension characteristics.
+ call ap_imset (im, boundary, max (1 + nxk / 2, 1 + nyk / 2),
+ constant)
+ call ap_imset (cnv, boundary, max (1 + nxk / 2, 1 + nyk / 2),
+ constant)
+
+ # Convolve the input image with the Gaussian kernel. The resultant
+ # picture constains in each pixel the height of the Gaussian
+ # function centered in the subarray which best represents the data
+ # within a circle of nsigma * sigma of the Gaussian.
+
+ if (norm == YES)
+ call ap_fconvolve (im, cnv, sky, Memr[ngker2d], Memr[dker2d],
+ Memi[skip], nxk, nyk, gsums[GAUSS_SGOP])
+ else
+ call ap_gconvolve (im, cnv, sky, Memr[gker2d], Memi[skip],
+ nxk, nyk, gsums, dmin, dmax)
+
+detect_
+
+ # Write the output header file.
+ if (stid <= 1)
+ call ap_wfdparam (out, ap)
+
+ call printf ("\nImage: %s ")
+ call pargstr (IM_HDRFILE(im))
+ call printf ("fwhmpsf: %g ratio: %g theta: %g nsigma: %g\n\n")
+ call pargr (apstatr (ap, FWHMPSF))
+ call pargr (apstatr (ap, RATIO))
+ call pargr (apstatr (ap, THETA))
+ call pargr (apstatr (ap, NSIGMA))
+
+ # Find all the objects in the input image with the specified image
+ # characteristics.
+
+ skysigma = apstatr (ap, SKYSIGMA)
+ if (IS_INDEFR(skysigma)) {
+ skymode = 0.0
+ threshold = 0.0
+ } else {
+ skymode = apstatr (ap, EPADU) * (skysigma ** 2 - (apstatr (ap,
+ READNOISE) / apstatr (ap, EPADU)) ** 2)
+ skymode = max (0.0, skymode)
+ threshold = apstatr (ap, THRESHOLD) * skysigma
+ }
+ xsigsq = (apstatr (ap, SCALE) * apstatr (ap, FWHMPSF) / 2.35482) ** 2
+ ysigsq = (apstatr (ap, SCALE) * apstatr (ap, RATIO) *
+ apstatr (ap, FWHMPSF) / 2.35482) ** 2
+
+ nstars = ap_find (ap, im, cnv, out, id, Memr[gker2d],
+ Memi[skip], nxk, nyk, skymode, threshold, relerr,
+ apstati (ap, POSITIVE), xsigsq, ysigsq, dmin, dmax,
+ apstatr (ap, SHARPLO), apstatr (ap, SHARPHI), apstatr (ap,
+ ROUNDLO), apstatr (ap, ROUNDHI), YES, stid, apstati (ap,
+ MKDETECTIONS))
+ stid = stid + nstars
+
+ call printf ("\nthreshold: %g relerr: %5.3f %g <= sharp <= %g ")
+ call pargr (threshold)
+ call pargr (relerr)
+ call pargr (apstatr (ap, SHARPLO))
+ call pargr (apstatr (ap, SHARPHI))
+ call printf ("%g <= round <= %g \n\n")
+ call pargr (apstatr (ap, ROUNDLO))
+ call pargr (apstatr (ap, ROUNDHI))
+
+ call apstats (ap, OUTNAME, Memc[str], SZ_FNAME)
+ call printf ("Output file: %s\n\n")
+ call pargstr (Memc[str])
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/daofind/apfind.x b/noao/digiphot/apphot/daofind/apfind.x
new file mode 100644
index 00000000..1bcbdd52
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/apfind.x
@@ -0,0 +1,626 @@
+include <gset.h>
+include <mach.h>
+include <imhdr.h>
+include "../lib/apphot.h"
+
+# AP_FIND -- Detect images in the convolved image and then compute image
+# characteristics using the original image.
+
+int procedure ap_find (ap, im, cnv, out, id, ker2d, skip, nxk, nyk, skymode,
+ threshold, relerr, emission, xsigsq, ysigsq, datamin, datamax,
+ sharplo, sharphi, roundlo, roundhi, interactive, stid, mkdetections)
+
+pointer ap # the apphot descriptor
+pointer im # pointer to the input image
+pointer cnv # pointer to the output image
+int out # the output file descriptor
+pointer id # pointer to the display stream
+real ker2d[nxk,ARB] # 2D Gaussian kernel
+int skip[nxk,ARB] # 2D skip kernel
+int nxk, nyk # dimensions of the kernel
+real skymode # estimate of the sky
+real threshold # threshold for image detection
+real relerr # the relative error of the convolution kernel
+int emission # emission features
+real xsigsq, ysigsq # sigma of gaussian in x and y
+real datamin, datamax # minimum and maximum good data values
+real sharplo, sharphi # sharpness limits
+real roundlo,roundhi # roundness parameter limits
+int interactive # interactive mode
+int stid # sequence number
+int mkdetections # mark detections
+
+int inline, i, j, ncols, col1, col2, line1, line2, index, pos
+int xmiddle, ymiddle, nonzero, nobjs, nstars, ntotal
+pointer sp, bufptrs, imlbuf, cnvlbuf, imbuf, cnvbuf, cols
+pointer satur, sharp, round1, round2, x, y
+
+int ap_detect(), ap_test(), apstati()
+pointer imgs2r()
+errchk imgs2r()
+
+begin
+ # Set up useful line and column limits.
+ ncols = IM_LEN(im,1) + nxk - 1
+ col1 = 1 - nxk / 2
+ col2 = IM_LEN(im,1) + nxk / 2
+ line1 = 1 + nyk / 2
+ line2 = IM_LEN(im,2) + nyk / 2
+ xmiddle = 1 + nxk / 2
+ ymiddle = 1 + nyk / 2
+
+ # Compute find the number of defined elements in the kernel.
+ nonzero = 0
+ #skip[xmiddle,ymiddle] = NO
+ do j = 1, nyk {
+ do i = 1, nxk {
+ if (skip[i,j] == NO)
+ nonzero = nonzero + 1
+ }
+ }
+ skip[xmiddle,ymiddle] = YES
+ nonzero = nonzero - 1
+
+ # Set up a cylindrical buffers and some working space for
+ # the detected images.
+ call smark (sp)
+ call salloc (bufptrs, nyk, TY_INT)
+ call salloc (imbuf, nyk * ncols, TY_REAL)
+ call salloc (cnvbuf, nyk * ncols, TY_REAL)
+ call salloc (cols, ncols, TY_INT)
+ call salloc (satur, ncols, TY_INT)
+ call salloc (sharp, ncols, TY_REAL)
+ call salloc (round1, ncols, TY_REAL)
+ call salloc (round2, ncols, TY_REAL)
+ call salloc (x, ncols, TY_REAL)
+ call salloc (y, ncols, TY_REAL)
+
+ # Read in the first nyk - 1 lines.
+ pos = nyk
+ do inline = 1 - nyk / 2, nyk / 2 {
+ imlbuf = imgs2r (im, col1, col2, inline, inline)
+ cnvlbuf = imgs2r (cnv, col1, col2, inline, inline)
+ if (emission == YES) {
+ call amovr (Memr[imlbuf], Memr[imbuf+(inline+ymiddle-2)*ncols],
+ ncols)
+ call amovr (Memr[cnvlbuf], Memr[cnvbuf+(inline+ymiddle-2)*
+ ncols], ncols)
+ } else {
+ call amulkr (Memr[imlbuf], -1.0, Memr[imbuf+(inline+ymiddle-2)*
+ ncols], ncols)
+ call amulkr (Memr[cnvlbuf], -1.0, Memr[cnvbuf+(inline+ymiddle-
+ 2)* ncols], ncols)
+ }
+ Memi[bufptrs+pos-1] = pos - 1
+ pos = pos - 1
+ }
+
+ # Generate the starlist line by line.
+ ntotal = 0
+ pos = nyk
+ do inline = line1, line2 {
+
+ # Setup the buffer pointer array.
+ do j = 2, nyk
+ Memi[bufptrs+j-2] = Memi[bufptrs+j-1]
+ Memi[bufptrs+nyk-1] = pos
+ index = (pos - 1) * ncols
+
+ # Read in new image line.
+ imlbuf = imgs2r (im, col1, col2, inline, inline)
+ cnvlbuf = imgs2r (cnv, col1, col2, inline, inline)
+
+ # Copy new lines into cylindrical buffer.
+ if (emission == YES) {
+ call amovr (Memr[imlbuf], Memr[imbuf+index], ncols)
+ call amovr (Memr[cnvlbuf], Memr[cnvbuf+index], ncols)
+ } else {
+ call amulkr (Memr[imlbuf], -1.0, Memr[imbuf+index], ncols)
+ call amulkr (Memr[cnvlbuf], -1.0, Memr[cnvbuf+index], ncols)
+ }
+
+ # Detect stars in each image line. In order for a given pixel
+ # to be detected as an image the pixel must be above threshold
+ # and be greater than any other pixel within nsigma sigma.
+
+ # Increment the cylindrical buffer.
+ if (mod (pos, nyk) == 0)
+ pos = 1
+ else
+ pos = pos + 1
+
+ nobjs = ap_detect (Memr[cnvbuf], Memi[bufptrs], ncols, skip, nxk,
+ nyk, relerr * threshold, Memi[cols])
+ if (nobjs <= 0)
+ next
+
+ # Compute the sharpness parameter.
+ call ap_sharp_round (Memr[imbuf], Memr[cnvbuf], Memi[bufptrs],
+ ncols, skip, nxk, nyk, Memi[cols], Memi[satur], Memr[round1],
+ Memr[sharp], nobjs, nonzero, skymode, datamin, datamax)
+
+ # Compute the roundness parameters.
+ call ap_xy_round (Memr[imbuf], Memi[bufptrs], ncols, ker2d, nxk,
+ nyk, Memi[cols], inline, Memr[round2], Memr[x],
+ Memr[y], nobjs, skymode, datamin, datamax, xsigsq, ysigsq)
+
+ # Test the image characeteristics of detected objects.
+ nstars = ap_test (Memi[cols], Memr[x], Memr[y], Memi[satur],
+ Memr[round1], Memr[round2], Memr[sharp], nobjs, IM_LEN(im,1),
+ IM_LEN(im,2), sharplo, sharphi, roundlo, roundhi)
+
+ # Mark the stars on the display.
+ if ((nstars > 0) && (interactive == YES) && (id != NULL) &&
+ (mkdetections == YES)) {
+ call greactivate (id, 0)
+ do j = 1, nstars {
+ #call ap_ltov (im, Memr[x+j-1], Memr[y+j-1], xc, yc, 1)
+ #call gmark (id, xc, yc, GM_PLUS, 1.0, 1.0)
+ call gmark (id, Memr[x+j-1], Memr[y+j-1], GM_PLUS, 1.0, 1.0)
+ }
+ call gdeactivate (id, 0)
+ }
+
+ switch (apstati (ap, WCSOUT)) {
+ case WCS_PHYSICAL:
+ call ap_ltoo (ap, Memr[x], Memr[y], Memr[x], Memr[y], nstars)
+ case WCS_TV:
+ call ap_ltov (im, Memr[x], Memr[y], Memr[x], Memr[y], nstars)
+ default:
+ ;
+ }
+
+ # Print results on the standard output.
+ if (interactive == YES)
+ call apstdout (Memr[cnvbuf], Memi[bufptrs], ncols, nyk,
+ Memi[cols], Memr[x], Memr[y], Memr[sharp], Memr[round1],
+ Memr[round2], nstars, ntotal, relerr * threshold)
+
+ # Save the results in the file.
+ call apdtfout (out, Memr[cnvbuf], Memi[bufptrs], ncols, nyk,
+ Memi[cols], Memr[x], Memr[y], Memr[sharp], Memr[round1],
+ Memr[round2], nstars, ntotal, relerr * threshold, stid)
+
+
+ ntotal = ntotal + nstars
+
+ }
+
+ # Free space
+ call sfree (sp)
+
+ return (ntotal)
+end
+
+
+# AP_DETECT -- Detec stellar objects in an image line. In order to be
+# detected as a star the candidate object must be above threshold and have
+# a maximum pixel value greater than any pixels within nsigma * sigma.
+
+int procedure ap_detect (density, ptrs, ncols, skip, nxk, nyk, threshold, cols)
+
+real density[ncols, ARB] # density array
+int ptrs[ARB] # pointer array
+int ncols # x dimesnsion of intensity buffer
+int skip[nxk,ARB] # skip array
+int nxk, nyk # size of convolution kernel
+real threshold # density threshold
+int cols[ARB] # column numbers of detected stars
+
+int i, j, k, kk, middle, nhalf, nobjs
+define nextpix_ 11
+
+begin
+ middle = 1 + nyk / 2
+ nhalf = nxk / 2
+
+ # Loop over all the columns in an image line.
+ nobjs = 0
+ for (i = 1 + nhalf; i <= ncols - nhalf; ) {
+
+ # Test whether the density enhancement is above threshold.
+ if (density[i,ptrs[middle]] < threshold)
+ goto nextpix_
+
+ # Test whether a given density enhancement is a local maximum.
+ do j = 1, nyk {
+ kk = 1
+ do k = i - nhalf, i + nhalf {
+ if (skip[kk,j] == NO) {
+ if (density[i,ptrs[middle]] < density[k,ptrs[j]])
+ goto nextpix_
+ }
+ kk = kk + 1
+ }
+ }
+
+ # Add the detected object to the list.
+ nobjs = nobjs + 1
+ cols[nobjs] = i
+
+ # If a local maximum is detected there can be no need to
+ # check pixels in this row between i and i + nhalf.
+ i = i + nhalf
+nextpix_
+ # Work on the next pixel.
+ i = i + 1
+ }
+
+ return (nobjs)
+end
+
+
+# AP_SHARP_ROUND -- Compute an estimate of the roundness and sharpness of the
+# detected objects. The roundness parameter is computed by comparing a measure
+# of the bilateral symmetry with a measure of the four-fold symmetry. The
+# sharpness parameter is defined as the ratio of the difference between the
+# height of the central pixel and the mean of the surrounding pixels to the
+# density enhancement of the central pixel.
+
+procedure ap_sharp_round (data, density, ptrs, ncols, skip, nxk, nyk, cols,
+ satur, round, sharps, nobjs, nonzero, skymode, datamin, datamax)
+
+real data[ncols,ARB] # image data
+real density[ncols,ARB] # density enhancements
+int ptrs[ARB] # buffer pointers
+int ncols # length of data array
+int skip[nxk,ARB] # 2D kernel
+int nxk, nyk # size of convolution kernel
+int cols[ARB] # array of columns
+int satur[ARB] # array of saturated state parameters
+real round[ARB] # array of roundness parameters
+real sharps[ARB] # array of sharpness parameters
+int nobjs # number of objects
+int nonzero # number of nonzero kernel elements
+real skymode # estimate of the sky mode
+real datamin, datamax # minimum and maximum good data values
+
+int i, j, k, xmiddle, ymiddle, npixels, nhalf
+real pixval, midpix, temp, sharp, sum2, sum4
+
+begin
+ # Loop over the detected objects.
+ nhalf = min (nxk / 2, nyk / 2)
+ xmiddle = 1 + nxk / 2
+ ymiddle = 1 + nyk / 2
+ do i = 1, nobjs {
+
+ # Compute the first estimate of roundness.
+ sum2 = 0.0
+ sum4 = 0.0
+ do k = 0, nhalf {
+ do j = 1, nhalf {
+ sum2 = sum2 +
+ density[cols[i]-k,ptrs[ymiddle-j]] +
+ density[cols[i]+k,ptrs[ymiddle+j]] -
+ density[cols[i]-j,ptrs[ymiddle+k]] -
+ density[cols[i]+j,ptrs[ymiddle-k]]
+ sum4 = sum4 +
+ abs (density[cols[i]-k,ptrs[ymiddle-j]]) +
+ abs (density[cols[i]+k,ptrs[ymiddle+j]]) +
+ abs (density[cols[i]-j,ptrs[ymiddle+k]]) +
+ abs (density[cols[i]+j,ptrs[ymiddle-k]])
+ }
+ }
+ if (sum2 == 0.0)
+ round[i] = 0.0
+ else if (sum4 <= 0.0)
+ round[i] = INDEFR
+ else
+ round[i] = 2.0 * sum2 / sum4
+
+ satur[i] = NO
+
+ # Eliminate the sharpness test if the central pixel is bad.
+ midpix = data[cols[i],ptrs[ymiddle]]
+ if (midpix > datamax) {
+ satur[i] = YES
+ sharps[i] = INDEFR
+ next
+ }
+ if (midpix < datamin) {
+ sharps[i] = INDEFR
+ next
+ }
+
+ # Accumulate the sharpness statistic.
+ sharp = 0.0
+ npixels = nonzero
+ do j = 1, nyk {
+ temp = 0.0
+ do k = 1, nxk {
+ if (skip[k,j] == YES)
+ next
+ pixval = data[cols[i]-xmiddle+k,ptrs[j]]
+ if (pixval > datamax) {
+ satur[i] = YES
+ npixels = npixels - 1
+ } else if (pixval < datamin) {
+ npixels = npixels - 1
+ } else {
+ temp = temp + (pixval - skymode)
+ }
+ }
+ sharp = sharp + temp
+ }
+
+ # Compute the sharpness statistic.
+ if (density[cols[i],ptrs[ymiddle]] <= 0.0 || npixels <= 0)
+ sharps[i] = INDEFR
+ else
+ sharps[i] = (midpix - skymode - sharp / real (npixels)) /
+ density[cols[i],ptrs[ymiddle]]
+
+ }
+end
+
+
+# AP_XY_ROUND -- Estimate the x-y centers and the roundness of the detected
+# objects. The height of the equivalent Gaussian function in x and y is fit by
+# least squares to the marginal distribution of the image data. If either
+# of these of these heights is negative set the roundess characteristic to
+# -MAX_REAL, otherwise compute a roundness characteristic. At the same
+# time setup the necessary sums for computing the first order corection
+# to the centroid of the gaussian profile.
+
+procedure ap_xy_round (data, ptrs, ncols, ker2d, nxk, nyk, cols, inline,
+ rounds, x, y, nobjs, skymode, datamin, datamax, xsigsq, ysigsq)
+
+real data[ncols,ARB] # density enhancements
+int ptrs[ARB] # buffer pointers
+int ncols # number of columns in cylindrical buffer
+real ker2d[nxk,ARB] # the gaussian convolution kernel
+int nxk # size of kernel in x
+int nyk # size of kernel in y
+int cols[ARB] # the input positions
+int inline # the input image line
+real rounds[ARB] # array of sharpness parameters
+real x[ARB] # output x coords
+real y[ARB] # output y coords
+int nobjs # number of objects
+real skymode # estimate of the sky mode
+real datamin, datamax # minium and maximum data values
+real xsigsq, ysigsq # x-y gaussian sigma squared
+
+int i, j, k, xmiddle, ymiddle, n
+real sumgd, sumgsq, sumg, sumd, sumdx, dgdx, sdgdx, sdgdxsq, sddgdx, sgdgdx
+real pixval, p, sg, sd, wt, hx, hy, dx, dy, skylvl, xhalf, yhalf
+
+begin
+ xhalf = real (nxk / 2) + 0.5
+ yhalf = real (nyk / 2) + 0.5
+ xmiddle = 1 + nxk / 2
+ ymiddle = 1 + nyk / 2
+
+ # Loop over the detected objects.
+ do i = 1, nobjs {
+
+ # Initialize the x fit.
+ sumgd = 0.0
+ sumgsq = 0.0
+ sumg = 0.0
+ sumd = 0.0
+ sumdx = 0.0
+ sdgdx = 0.0
+ sdgdxsq = 0.0
+ sddgdx = 0.0
+ sgdgdx = 0.0
+ p = 0.0
+ n = 0
+
+ # Compute the sums required for the x fit.
+ do k = 1, nxk {
+
+ sg = 0.0
+ sd = 0.0
+ do j = 1, nyk {
+ wt = real (ymiddle - abs (j - ymiddle))
+ pixval = data[cols[i]-xmiddle+k,ptrs[j]]
+ if (pixval < datamin || pixval > datamax)
+ next
+ sd = sd + (pixval - skymode) * wt
+ sg = sg + ker2d[k,j] * wt
+ }
+
+ if (sg <= 0.0)
+ next
+ wt = real (xmiddle - abs (k - xmiddle))
+ sumgd = sumgd + wt * sg * sd
+ sumgsq = sumgsq + wt * sg ** 2
+ sumg = sumg + wt * sg
+ sumd = sumd + wt * sd
+ sumdx = sumdx + wt * sd * (xmiddle - k)
+ p = p + wt
+ n = n + 1
+ dgdx = sg * (xmiddle - k)
+ sdgdxsq = sdgdxsq + wt * dgdx ** 2
+ sdgdx = sdgdx + wt * dgdx
+ sddgdx = sddgdx + wt * sd * dgdx
+ sgdgdx = sgdgdx + wt * sg * dgdx
+ }
+
+ # Need at least three points to estimate the x height, position
+ # and local sky brightness of the star.
+
+ if (n <= 2 || p <= 0.0) {
+ x[i] = INDEFR
+ y[i] = INDEFR
+ rounds[i] = INDEFR
+ next
+ }
+
+ # Solve for the height of the best-fitting gaussian to the
+ # xmarginal. Reject the star if the height is non-positive.
+
+ hx = sumgsq - (sumg ** 2) / p
+ if (hx <= 0.0) {
+ x[i] = INDEFR
+ y[i] = INDEFR
+ rounds[i] = INDEFR
+ next
+ }
+ hx = (sumgd - sumg * sumd / p) / hx
+ if (hx <= 0.0) {
+ x[i] = INDEFR
+ y[i] = INDEFR
+ rounds[i] = INDEFR
+ next
+ }
+
+ # Solve for the new x centroid.
+ skylvl = (sumd - hx * sumg) / p
+ dx = (sgdgdx - (sddgdx - sdgdx * (hx * sumg + skylvl * p))) /
+ (hx * sdgdxsq / xsigsq)
+ if (abs (dx) > xhalf) {
+ if (sumd == 0.0)
+ dx = 0.0
+ else
+ dx = sumdx / sumd
+ if (abs (dx) > xhalf)
+ dx = 0.0
+ }
+ x[i] = (cols[i] - xmiddle + 1) + dx
+
+ # Initialize y fit.
+ sumgd = 0.0
+ sumgsq = 0.0
+ sumg = 0.0
+ sumd = 0.0
+ sumdx = 0.0
+ sdgdx = 0.0
+ sdgdxsq = 0.0
+ sddgdx = 0.0
+ sgdgdx = 0.0
+ p = 0.0
+ n = 0
+
+ do j = 1, nyk {
+ sg = 0.0
+ sd = 0.0
+ do k = 1, nxk {
+ wt = real (xmiddle - abs (k - xmiddle))
+ pixval = data[cols[i]-xmiddle+k,ptrs[j]]
+ if (pixval < datamin || pixval > datamax)
+ next
+ sd = sd + (pixval - skymode) * wt
+ sg = sg + ker2d[k,j] * wt
+ }
+ if (sg <= 0.0)
+ next
+ wt = real (ymiddle - abs (j - ymiddle))
+ sumgd = sumgd + wt * sg * sd
+ sumgsq = sumgsq + wt * sg ** 2
+ sumg = sumg + wt * sg
+ sumd = sumd + wt * sd
+ sumdx = sumdx + wt * sd * (j - ymiddle)
+ p = p + wt
+ n = n + 1
+ dgdx = sg * (ymiddle - j)
+ sdgdx = sdgdx + wt * dgdx
+ sdgdxsq = sdgdxsq + wt * dgdx ** 2
+ sddgdx = sddgdx + wt * sd * dgdx
+ sgdgdx = sgdgdx + wt * sg * dgdx
+ }
+
+ # Need at least three points to estimate the y height, position
+ # and local sky brightness of the star.
+
+ if (n <= 2 || p <= 0.0) {
+ x[i] = INDEFR
+ y[i] = INDEFR
+ rounds[i] = INDEFR
+ next
+ }
+
+ # Solve for the height of the best-fitting gaussian to the
+ # y marginal. Reject the star if the height is non-positive.
+
+ hy = sumgsq - (sumg ** 2) / p
+ if (hy <= 0.0) {
+ x[i] = INDEFR
+ y[i] = INDEFR
+ rounds[i] = INDEFR
+ next
+ }
+ hy = (sumgd - sumg * sumd / p) / (sumgsq - (sumg ** 2) / p)
+ if (hy <= 0.0) {
+ x[i] = INDEFR
+ y[i] = INDEFR
+ rounds[i] = INDEFR
+ next
+ }
+
+ # Solve for the new x centroid.
+ skylvl = (sumd - hy * sumg) / p
+ dy = (sgdgdx - (sddgdx - sdgdx * (hy * sumg + skylvl * p))) /
+ (hy * sdgdxsq / ysigsq)
+ if (abs (dy) > yhalf) {
+ if (sumd == 0.0)
+ dy = 0.0
+ else
+ dy = sumdx / sumd
+ if (abs (dy) > yhalf)
+ dy = 0.0
+ }
+ y[i] = (inline - ymiddle + 1) + dy
+
+ # Compute the roundness.
+ rounds[i] = 2.0 * (hx - hy) / (hx + hy)
+ }
+end
+
+
+# AP_TEST -- Test the characteristic of the detected images for roundness
+# and sharpness.
+
+int procedure ap_test (cols, x, y, satur, round1, round2, sharps, nobjs,
+ ncols, nlines, sharplo, sharphi, roundlo, roundhi)
+
+int cols[ARB] # col IDS of detected images
+real x[ARB] # x positions
+real y[ARB] # y positions
+int satur[ARB] # saturation condition
+real round1[ARB] # first roundness parameters
+real round2[ARB] # second roundness parameters
+real sharps[ARB] # sharpness parameters
+int nobjs # number of objects
+int ncols, nlines # size of the input image
+real sharplo, sharphi # sharpness parameters
+real roundlo, roundhi # roundness parameters
+
+int i, nstars
+
+begin
+ # Loop over the detected objects.
+ nstars = 0
+ do i = 1, nobjs {
+
+ # Compute the sharpness statistic
+ if (! IS_INDEFR(sharps[i]) && (sharps[i] < sharplo ||
+ sharps[i] > sharphi))
+ next
+ if (IS_INDEFR(round1[i]) || round1[i] < roundlo ||
+ round1[i] > roundhi)
+ next
+ if (satur[i] == NO) {
+ if (IS_INDEFR(round2[i]) || round2[i] < roundlo ||
+ round2[i] > roundhi)
+ next
+ }
+ if (IS_INDEFR(x[i]) || x[i] < 0.5 || x[i] > (ncols+0.5))
+ next
+ if (IS_INDEFR(y[i]) || y[i] < 0.5 || y[i] > (nlines+0.5))
+ next
+
+ # Add object to the list.
+ nstars = nstars + 1
+ cols[nstars] = cols[i]
+ x[nstars] = x[i]
+ y[nstars] = y[i]
+ sharps[nstars] = sharps[i]
+ round1[nstars] = round1[i]
+ round2[nstars] = round2[i]
+ }
+
+ return (nstars)
+end
diff --git a/noao/digiphot/apphot/daofind/apimset.x b/noao/digiphot/apphot/daofind/apimset.x
new file mode 100644
index 00000000..6f1e8cdc
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/apimset.x
@@ -0,0 +1,17 @@
+include <imset.h>
+
+# AP_IMSET -- Setup image boundary extension charactersitics.
+
+procedure ap_imset (im, boundary, npix, constant)
+
+pointer im # pointer to the image
+int boundary # type of boundary condition
+int npix # number of pixels of boundary entension
+real constant # constant for constant boundary extension
+
+begin
+ call imseti (im, IM_TYBNDRY, boundary)
+ call imseti (im, IM_NBNDRYPIX, npix)
+ if (boundary == BT_CONSTANT)
+ call imsetr (im, IM_BNDRYPIXVAL, constant)
+end
diff --git a/noao/digiphot/apphot/daofind/daofind.key b/noao/digiphot/apphot/daofind/daofind.key
new file mode 100644
index 00000000..e68ceb80
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/daofind.key
@@ -0,0 +1,66 @@
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+v Verify the critical parameters
+w Save the current parameters
+d Plot radial profile of star near cursor
+i Interactively set parameters using star near cursor
+f Find stars in the image
+spbar Find stars in the image, output results
+q Exit task
+
+
+ Colon Commands
+
+:show [data/center] List the parameters
+
+ Colon Parameter Editing Commands
+
+# Image and file name parameters
+
+:image [string] Image name
+:output [string] Output file name
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Full width half maximum of psf (scale units)
+:emission [y/n] Emission feature (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good data value (counts)
+:datamax [value] Maximum good data value (counts)
+
+# Noise description parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per adu)
+:readnoise [value] Readout noise (electrons)
+
+# Observation parameters
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Exposure time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observation (time units)
+
+# Object detection parameters
+
+:nsigma [value] Size of Gaussian kernel (sigma)
+:threshold [value] Detection intensity threshold (counts)
+:ratio [value] Sigmay / sigmax of Gaussian kernel
+:theta [value] Position angle of Gaussian kernel
+:sharplo [value] Lower bound on sharpness
+:sharphi [value] Upper bound on sharpness
+:roundlo [value] Lower bound on roundness
+:roundhi [value] Upper bound on roundness
+
+# Plotting and marking commands
+
+:mkdetections [y/n] Mark detections on the image display
diff --git a/noao/digiphot/apphot/daofind/idaofind.key b/noao/digiphot/apphot/daofind/idaofind.key
new file mode 100644
index 00000000..7da8fe42
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/idaofind.key
@@ -0,0 +1,8 @@
+ Interactive Daofind Setup Menu
+
+ v Mark and verify critical daofind parameters (f,s)
+
+ f Mark and verify the full-width half-maximum of the psf
+ s Mark and verify the standard deviation of the background
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
diff --git a/noao/digiphot/apphot/daofind/mkpkg b/noao/digiphot/apphot/daofind/mkpkg
new file mode 100644
index 00000000..28935c11
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/mkpkg
@@ -0,0 +1,37 @@
+# DAOFIND task
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ apbfdfind.x <imhdr.h> <mach.h> \
+ <imio.h> "../lib/apphot.h" \
+ "../lib/noise.h" "../lib/find.h"
+ apconvolve.x <imhdr.h> <imset.h> \
+ "../lib/find.h"
+ apegkernel.x <math.h> "../lib/find.h"
+ apfdcolon.x "../lib/apphot.h" "../lib/noise.h" \
+ "../lib/find.h" "../lib/display.h"
+ apfdconfirm.x
+ apfdfind.x "../lib/apphot.h" "../lib/display.h" \
+ "../lib/find.h" <imhdr.h>
+ apfdfree.x "../lib/apphotdef.h"
+ apfdgpars.x "../lib/noise.h" "../lib/display.h"
+ apfdinit.x "../lib/apphotdef.h" "../lib/finddef.h"
+ apfdpars.x "../lib/display.h"
+ apfdradsetup.x
+ apfdshow.x "../lib/apphot.h" "../lib/noise.h" \
+ "../lib/find.h"
+ apfdstars.x <imhdr.h> <mach.h> \
+ "../lib/apphot.h" "../lib/noise.h" \
+ "../lib/find.h" "../lib/display.h"
+ apfind.x <imhdr.h> <mach.h> \
+ <gset.h> "../lib/apphot.h"
+ apimset.x <imset.h>
+ t_daofind.x <fset.h> <imhdr.h> \
+ <gset.h> "../lib/apphot.h" \
+ "../lib/noise.h" "../lib/find.h" \
+ <imhdr.h>
+ ;
diff --git a/noao/digiphot/apphot/daofind/t_daofind.x b/noao/digiphot/apphot/daofind/t_daofind.x
new file mode 100644
index 00000000..eaf77fbf
--- /dev/null
+++ b/noao/digiphot/apphot/daofind/t_daofind.x
@@ -0,0 +1,419 @@
+include <imhdr.h>
+include <gset.h>
+include <fset.h>
+include <imhdr.h>
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/find.h"
+
+# T_DAOFIND -- Automatically detect objects in an image given the full
+# width half maximum of the image point spread function and a detection
+# threshold.
+
+procedure t_daofind ()
+
+pointer image # pointer to input image
+pointer denimage # pointer to density enhancement image
+pointer skyimage # pointer to the sky image
+int output # the results file descriptor
+int boundary # type of boundary extension
+real constant # constant for constant boundary extension
+int interactive # interactive mode
+int verify # verify mode
+int update # update critical parameters
+int verbose # verbose mode
+int cache # cache the image pixels
+
+pointer im, cnv, sky, sp, outfname, denname, skyname, str
+pointer ap, cname, display, graphics, id, gd
+int limlist, lolist, densave, skysave, out, root, stat, imlist, olist
+int wcs, req_size, old_size, buf_size, memstat
+
+real clgetr()
+pointer gopen(), immap(), ap_immap()
+int imtlen(), clplen(), btoi(), clgwrd(), aptmpimage()
+int open(), strncmp(), strlen(), fnldir(), ap_fdfind()
+int imtopenp(), clpopnu(), clgfil(), imtgetim(), ap_memstat(), sizeof()
+bool clgetb(), streq()
+
+begin
+ # Flush STDOUT on a new line.
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (denimage, SZ_FNAME, TY_CHAR)
+ call salloc (skyimage, SZ_FNAME, TY_CHAR)
+ call salloc (display, SZ_FNAME, TY_CHAR)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (denname, SZ_FNAME, TY_CHAR)
+ call salloc (skyname, SZ_FNAME, TY_CHAR)
+ call salloc (cname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Fetch the image and output file lists.
+ imlist = imtopenp ("image")
+ limlist = imtlen (imlist)
+ olist = clpopnu ("output")
+ lolist = clplen (olist)
+
+ # Get prefix for density enhancement and sky images.
+ call clgstr ("starmap", Memc[denimage], SZ_FNAME)
+ call clgstr ("skymap", Memc[skyimage], SZ_FNAME)
+
+ # Get the image boundary extensions parameters.
+ boundary = clgwrd ("boundary", Memc[str], SZ_LINE,
+ ",constant,nearest,reflect,wrap,")
+ constant = clgetr ("constant")
+
+ call clgstr ("icommands.p_filename", Memc[cname], SZ_FNAME)
+ if (Memc[cname] != EOS)
+ interactive = NO
+ else
+ interactive = btoi (clgetb ("interactive"))
+ verbose = btoi (clgetb ("verbose"))
+ verify = btoi (clgetb ("verify"))
+ update = btoi (clgetb ("update"))
+ cache = btoi (clgetb ("cache"))
+
+ # Get the parameters.
+ call ap_fdgpars (ap)
+
+ # Confirm the algorithm parameters.
+ if (verify == YES && interactive == NO) {
+ call ap_fdconfirm (ap)
+ if (update == YES)
+ call ap_fdpars (ap)
+ }
+
+ # Get the wcs info.
+ wcs = clgwrd ("wcsout", Memc[str], SZ_LINE, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (ap, WCSOUT, wcs)
+
+ # Get the graphics and display devices.
+ call clgstr ("graphics", Memc[graphics], SZ_FNAME)
+ call clgstr ("display", Memc[display], SZ_FNAME)
+
+ # Open the graphics and display devices.
+ if (interactive == YES) {
+ if (Memc[graphics] == EOS)
+ gd = NULL
+ else {
+ iferr {
+ gd = gopen (Memc[graphics], APPEND+AW_DEFER, STDGRAPH)
+ } then {
+ call eprintf (
+ "Warning: Error opening the graphics device.\n")
+ gd = NULL
+ }
+ }
+ if (Memc[display] == EOS)
+ id = NULL
+ else if (streq (Memc[graphics], Memc[display]))
+ id = gd
+ else {
+ iferr {
+ id = gopen (Memc[display], APPEND, STDIMAGE)
+ } then {
+ call eprintf (
+ "Warning: Graphics overlay not available for display device.\n")
+ id = NULL
+ }
+ }
+ } else {
+ gd = NULL
+ id = NULL
+ }
+
+ # Loop over the images.
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open the image and get the required keywords from the header.
+
+ im = immap (Memc[image], READ_ONLY, 0)
+ call apimkeys (ap, im, Memc[image])
+
+ # Set the image display viewport.
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[image], im, 4)
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * (IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im)) + 2 * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (TY_REAL))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+
+ # Determine the results file name. If output is a null string or
+ # a directory name then the extension "coo" is added to the
+ # root image name and the appropriate version number is appended
+ # in order to construct a default output file name.
+
+ out = NULL
+ if (lolist == 0) {
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (olist, Memc[output], SZ_FNAME)
+ root = fnldir (Memc[output], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[output+root], 7) == 0 || root ==
+ strlen (Memc[output])) {
+ call apoutname (Memc[image], Memc[outfname], "coo",
+ Memc[outfname], SZ_FNAME)
+ lolist = limlist
+ } else if (stat != EOF) {
+ call strcpy (Memc[output], Memc[outfname], SZ_FNAME)
+ } else {
+ call apoutname (Memc[image], Memc[outfname], "coo",
+ Memc[outfname], SZ_FNAME)
+ lolist = limlist
+ }
+ }
+ call apsets (ap, OUTNAME, Memc[outfname])
+
+ # Set up the directory and name for the density enhancement image.
+ # Note that the default value for denimage is the null string
+ # indicating the current directory. If denimage is null or
+ # contains only a directory specification make a temporary image
+ # name using the prefix "den", otherwise use the user specified
+ # prefix.
+
+ densave = aptmpimage (Memc[image], Memc[denimage], "den",
+ Memc[denname], SZ_FNAME)
+
+ # Set up the directory and name for the sky values image.
+
+ skysave = aptmpimage (Memc[image], Memc[skyimage], "sky",
+ Memc[skyname], SZ_FNAME)
+
+ # Find the stars in an image.
+ if (interactive == NO) {
+
+ cnv = NULL
+ if (Memc[cname] != EOS) {
+ stat = ap_fdfind (Memc[denname], Memc[skyname], ap, im,
+ NULL, NULL, out, boundary, constant, densave,
+ skysave, NO, cache)
+ } else {
+ cnv = ap_immap (Memc[denname], im, ap, densave)
+ if (memstat == YES)
+ call ap_pcache (cnv, INDEFI, buf_size)
+ if (skysave == YES) {
+ sky = ap_immap (Memc[skyname], im, ap, skysave)
+ if (memstat == YES)
+ call ap_pcache (sky, INDEFI, buf_size)
+ } else
+ sky = NULL
+ if (Memc[outfname] != EOS)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ else
+ out = NULL
+ call ap_bfdfind (im, cnv, sky, out, ap, boundary,
+ constant, verbose)
+ call imunmap (cnv)
+ if (sky != NULL)
+ call imunmap (sky)
+ if (densave == NO)
+ call imdelete (Memc[denname])
+ stat = NO
+ }
+
+ } else
+ stat = ap_fdfind (Memc[denname], Memc[skyname], ap, im, gd,
+ id, out, boundary, constant, densave, skysave, YES,
+ cache)
+
+ # Clean up files.
+ call imunmap (im)
+ call close (out)
+
+ # Uncache memory
+ call fixmem (old_size)
+
+ if (stat == YES)
+ break
+ }
+
+ # Close up the graphics system.
+ if (id == gd && id != NULL)
+ call gclose (id)
+ else {
+ if (gd != NULL)
+ call gclose (gd)
+ if (id != NULL)
+ call gclose (id)
+ }
+
+ # Close image and output file lists.
+ call ap_fdfree (ap)
+ call imtclose (imlist)
+ call clpcls (olist)
+ call sfree (sp)
+end
+
+
+# AP_IMMAP -- Map the output image.
+
+pointer procedure ap_immap (outname, im, ap, save)
+
+char outname[ARB] # convolved image name
+pointer im # pointer to input image
+pointer ap # pointer to the apphot structure
+int save # save the convolved image
+
+int newimage
+pointer outim
+real tmp_scale, tmp_fwhmpsf, tmp_ratio, tmp_theta, tmp_nsigma
+real tmp_datamin, tmp_datamax
+bool fp_equalr()
+int imaccess()
+pointer immap()
+real apstatr(), imgetr()
+errchk imgetr()
+
+begin
+ # Check to see if the image already exists. If it does not
+ # open a new image and write the PSF characteristics into the
+ # image user area, otherwise fetch the PSF parameters from the image
+ # header.
+
+ if (save == NO || imaccess (outname, READ_ONLY) == NO) {
+
+ outim = immap (outname, NEW_COPY, im)
+ IM_PIXTYPE(outim) = TY_REAL
+ call imaddr (outim, "SCALE", 1.0 / apstatr (ap, SCALE))
+ call imaddr (outim, "FWHMPSF", apstatr (ap, FWHMPSF))
+ call imaddr (outim, "NSIGMA", apstatr (ap, NSIGMA))
+ call imaddr (outim, "RATIO", apstatr (ap, RATIO))
+ call imaddr (outim, "THETA", apstatr (ap, THETA))
+ call imaddr (outim, "DATAMIN", apstatr (ap, DATAMIN))
+ call imaddr (outim, "DATAMAX", apstatr (ap, DATAMIN))
+
+ } else {
+
+ outim = immap (outname, READ_ONLY, 0)
+ iferr (tmp_scale = 1.0 / imgetr (outim, "SCALE"))
+ tmp_scale = INDEFR
+ iferr (tmp_fwhmpsf = imgetr (outim, "FWHMPSF"))
+ tmp_fwhmpsf = INDEFR
+ iferr (tmp_nsigma = imgetr (outim, "NSIGMA"))
+ tmp_nsigma = INDEFR
+ iferr (tmp_ratio = imgetr (outim, "RATIO"))
+ tmp_ratio = INDEFR
+ iferr (tmp_theta = imgetr (outim, "THETA"))
+ tmp_theta = INDEFR
+ iferr (tmp_datamin = imgetr (outim, "DATAMIN"))
+ tmp_datamin = INDEFR
+ iferr (tmp_datamax = imgetr (outim, "DATAMAX"))
+ tmp_datamax = INDEFR
+
+ if (IS_INDEFR(tmp_scale) || ! fp_equalr (tmp_scale, apstatr (ap,
+ SCALE)))
+ newimage = YES
+ else if (IS_INDEFR(tmp_fwhmpsf) || ! fp_equalr (tmp_fwhmpsf,
+ apstatr (ap, FWHMPSF)))
+ newimage = YES
+ else if (IS_INDEFR(tmp_nsigma) || ! fp_equalr (tmp_nsigma,
+ apstatr (ap, NSIGMA)))
+ newimage = YES
+ else if (IS_INDEFR(tmp_ratio) || ! fp_equalr (tmp_ratio,
+ apstatr (ap, RATIO)))
+ newimage = YES
+ else if (IS_INDEFR(tmp_theta) || ! fp_equalr (tmp_theta,
+ apstatr (ap, THETA)))
+ newimage = YES
+ else if (IS_INDEFR(tmp_datamin) || ! fp_equalr (tmp_datamin,
+ apstatr (ap, DATAMIN)))
+ newimage = YES
+ else if (IS_INDEFR(tmp_datamax) || ! fp_equalr (tmp_datamax,
+ apstatr (ap, DATAMAX)))
+ newimage = YES
+ else
+ newimage = NO
+
+ if (newimage == YES) {
+ call imunmap (outim)
+ call imdelete (outname)
+ outim = immap (outname, NEW_COPY, im)
+ IM_PIXTYPE(outim) = TY_REAL
+ call imaddr (outim, "SCALE", 1.0 / apstatr (ap, SCALE))
+ call imaddr (outim, "FWHMPSF", apstatr (ap, FWHMPSF))
+ call imaddr (outim, "NSIGMA", apstatr (ap, NSIGMA))
+ call imaddr (outim, "RATIO", apstatr (ap, RATIO))
+ call imaddr (outim, "THETA", apstatr (ap, THETA))
+ }
+ }
+
+ return (outim)
+end
+
+
+# AP_OUTMAP -- Manufacture an output coordinate file name.
+
+procedure ap_outmap (ap, out, root)
+
+pointer ap # pointer to the apphot structure
+int out # the output file descriptor
+char root[ARB] # root of the previous output file name, may be
+ # updated
+
+int findex, lindex, version
+pointer sp, image, outname, newoutname
+int strmatch(), gstrmatch(), open(), fnldir(), access()
+
+begin
+ if (out != NULL)
+ call close (out)
+
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (outname, SZ_FNAME, TY_CHAR)
+ call salloc (newoutname, SZ_FNAME, TY_CHAR)
+
+ # Get the old names.
+ call apstats (ap, IMNAME, Memc[image], SZ_FNAME)
+ call apstats (ap, OUTNAME, Memc[outname], SZ_FNAME)
+
+ # Manufacture a new name. Search first for existing files with
+ # the form "outname.coo.*" and create a new version number.
+ # If the first search fails look for names containing root
+ # and append a version number to create a new output file
+ # name. Otherwise simply use the output name.
+
+ if (Memc[outname] == EOS) {
+ Memc[newoutname] = EOS
+ } else if (strmatch (Memc[outname], "\.coo\.") > 0) {
+ findex = fnldir (Memc[outname], Memc[newoutname], SZ_FNAME)
+ call apoutname (Memc[image], Memc[newoutname], "coo",
+ Memc[newoutname], SZ_FNAME)
+ } else if (gstrmatch (Memc[outname], root, findex, lindex) > 0) {
+ repeat {
+ version = version + 1
+ call strcpy (Memc[outname], Memc[newoutname], SZ_FNAME)
+ call sprintf (Memc[newoutname+lindex], SZ_FNAME, ".%d")
+ call pargi (version)
+ } until (access (Memc[newoutname], 0, 0) == NO)
+ } else {
+ version = 1
+ call strcpy (Memc[outname], root, SZ_FNAME)
+ call strcpy (Memc[outname], Memc[newoutname], SZ_FNAME)
+ }
+
+ # Open the output image.
+ if (Memc[newoutname] == EOS)
+ out = NULL
+ else
+ out = open (Memc[newoutname], NEW_FILE, TEXT_FILE)
+ call apsets (ap, OUTNAME, Memc[newoutname])
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/datapars.par b/noao/digiphot/apphot/datapars.par
new file mode 100644
index 00000000..15778b9f
--- /dev/null
+++ b/noao/digiphot/apphot/datapars.par
@@ -0,0 +1,25 @@
+# DATAPARS
+
+scale,r,h,1.0,0.0,,Image scale in units per pixel
+fwhmpsf,r,h,2.5,0.0,,FWHM of the PSF in scale units
+emission,b,h,y,,,Features are positive ?
+sigma,r,h,INDEF,,,Standard deviation of background in counts
+datamin,r,h,INDEF,,,Minimum good data value
+datamax,r,h,INDEF,,,Maximum good data value
+
+noise,s,h,"poisson","|constant|poisson|",,Noise model
+ccdread,s,h,"",,,CCD readout noise image header keyword
+gain,s,h,"",,,CCD gain image header keyword
+readnoise,r,h,0.0,,,CCD readout noise in electrons
+epadu,r,h,1.0,,,Gain in electrons per count
+
+exposure,s,h,"",,,Exposure time image header keyword
+airmass,s,h,"",,,Airmass image header keyword
+filter,s,h,"",,,Filter image header keyword
+obstime,s,h,"",,,Time of observation image header keyword
+itime,r,h,1.0,,,Exposure time
+xairmass,r,h,INDEF,,,Airmass
+ifilter,s,h,"INDEF",,,Filter
+otime,s,h,"INDEF",,,Time of observation
+
+mode,s,h,'ql'
diff --git a/noao/digiphot/apphot/doc/apsums.apps b/noao/digiphot/apphot/doc/apsums.apps
new file mode 100644
index 00000000..ea5843bf
--- /dev/null
+++ b/noao/digiphot/apphot/doc/apsums.apps
@@ -0,0 +1,19 @@
+The apphot and daophot package aperture photometry tasks have been modified
+to compute the aperture sums and areas in double precision instead of real
+precision. This change minimizes machine precision errors that can become
+significant for large apertures and very low noise or synthetic data.
+
+These tasks have also been modified to output negative values of the total
+flux should they occur. Formerly these values were being artificially set to
+0.0. This change makes it easier to see the effects of any sky value and machine
+errors.
+
+The modified apertures photometry tasks are available as part of the
+external addon package digiphotx. To retrieve and install digiphotx, ftp
+to 140.252.1.1, login as anonymous, cd to iraf/extern, retrieve the file
+digiphotx.readme, and follow the installation instructions.
+
+
+
+ Lindsey Davis
+ davis@noao.edu
diff --git a/noao/digiphot/apphot/doc/apsums.noao b/noao/digiphot/apphot/doc/apsums.noao
new file mode 100644
index 00000000..fd920b49
--- /dev/null
+++ b/noao/digiphot/apphot/doc/apsums.noao
@@ -0,0 +1,17 @@
+The apphot and daophot package aperture photometry tasks have been modified
+to compute the aperture sums and areas in double precision instead of real
+precision. This change minimizes machine precision errors that can become
+significant for large apertures and very low noise or synthetic data.
+
+These tasks have also been modified to output negative values of the total
+flux should they occur. Formerly these values were being artificially set to
+0.0. This change makes it easier to see the effects of any sky value and machine
+errors.
+
+The modified apertures photometry tasks are available under irafx. Let me
+know if you have any questions about the modified tasks or encounter and
+problems using them.
+
+
+ Lindsey Davis
+ davis@noao.edu
diff --git a/noao/digiphot/apphot/doc/aptest.hlp b/noao/digiphot/apphot/doc/aptest.hlp
new file mode 100644
index 00000000..85fad0d9
--- /dev/null
+++ b/noao/digiphot/apphot/doc/aptest.hlp
@@ -0,0 +1,68 @@
+.help aptest Dec92 noao.digiphot.apphot
+.ih
+NAME
+aptest -- run basic tests on the apphot package tasks
+.ih
+USAGE
+aptest imname
+.ih
+PARAMETERS
+.ls imname
+The name of the output test image. The actual test image is stored in fits
+format in the APPHOT package subdirectory test. If the image already exists
+APTEST will exit with a warning message.
+.le
+.ls aplogfile = ""
+The name of the output log file. By default all the text output is logged
+in a file called \fI"imname.log"\fR. If the log file already exists APTEST will
+exit with a warning message.
+.le
+.ls applotfile = ""
+The name of the output log file. By default all the plot output is logged in
+a file called \fI"imname.plot"\fR. If the plot file already exists APTEST will
+exit with a warning message.
+.le
+.ih
+DESCRIPTION
+APTEST is a simple script which exercises each of the tasks in the APPHOT
+package in turn. At startup APTEST reads a small fits image stored in the
+APPHOT test subdirectory and creates the image \fIimname\fR in the user's
+working directory. APTEST initializes the APPHOT package by returning
+all the parameters to their default state, runs each of the APPHOT
+tasks in non-interactive mode, spools the text output to the file
+\fIaplogfile\fR, and spools the plot output from the RADPROF task to the plot
+metacode file \fIapplotfile\fR.
+.ih
+EXAMPLES
+
+1. Check to see that all the APPHOT tasks are functioning correctly.
+
+.nf
+ ap> apphot
+
+ ... load the apphot package
+
+ ap> aptest testim
+
+ ... run the test script
+
+ ap> lprint testim.log
+
+ ... print the text output
+
+ ap> gkidir testim.plot
+
+ ... list the contents of the plot file
+
+ ap> gkiextract testim.plot 1-N | stdplot
+
+ ... send the plots to the plotter
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+.endhelp
diff --git a/noao/digiphot/apphot/doc/center.hlp b/noao/digiphot/apphot/doc/center.hlp
new file mode 100644
index 00000000..c409c49b
--- /dev/null
+++ b/noao/digiphot/apphot/doc/center.hlp
@@ -0,0 +1,638 @@
+.help center May00 noao.digiphot.apphot
+.ih
+NAME
+center -- compute accurate centers for a list of objects
+.ih
+USAGE
+center image
+.ih
+PARAMETERS
+.ls image
+The list of images containing the objects to be centered.
+.le
+.ls coords = ""
+The list of text files containing initial coordinates for the objects to
+be centered. Objects are listed in coords one object per line with the
+initial coordinate values in columns one and two. The number of coordinate
+files must be zero, one, or equal to the number of images.
+If coords is "default", "dir$default", or a directory specification then an
+coords file name of the form dir$root.extension.version is constructed and
+searched for, where dir is the directory, root is the root image name,
+extension is "coo" and version is the next available version number for the
+file.
+.le
+.ls output = "default"
+The name of the results file or results directory. If output is
+"default", "dir$default", or a directory specification then an output file name
+of the form dir$root.extension.version is constructed, where dir is the
+directory, root is the root image name, extension is "ctr" and version is
+the next available version number for the file. The number of output files
+must be zero, one, or equal to the number of image files. In both interactive
+and batch mode full output is written to output. In interactive mode
+an output summary is also written to the standard output.
+.le
+.ls plotfile = ""
+The name of the file containing radial profile plots of the stars written
+to the output file. If plotfile is defined then a radial profile plot
+is written to plotfile every time a record is written to \fIoutput\fR.
+The user should be aware that this can be a time consuming operation.
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters.
+The critical parameters \fIfwhmpsf\fR and \fIsigma\fR are located in
+datapars. If datapars is undefined then the default parameter set in
+uparm directory is used.
+.le
+.ls centerpars = ""
+The name of the file containing the centering algorithm parameters.
+The critical parameters \fIcalgorithm\fR and \fIcbox\fR are located in
+centerpars. If centerpars is undefined then the default parameter
+set in uparm is used.
+.le
+.ls interactive = yes
+Interactive or non-interactive mode?
+.le
+.ls radplots = no
+If \fIradplots\fR is "yes" and CENTER is run in interactive mode, a radial
+profile of each star is plotted on the screen after the center is fit.
+.le
+.ls icommands = ""
+The image display cursor or image cursor command file.
+.le
+.ls gcommands = ""
+The graphics cursor or graphics cursor command file.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout"
+The coordinate system of the input coordinates read from \fIcoords\fR and
+of the output coordinates written to \fIoutput\fR respectively. The image
+header coordinate system is used to transform from the input coordinate
+system to the "logical" pixel coordinate system used internally,
+and from the internal "logical" pixel coordinate system to the output
+coordinate system. The input coordinate system options are "logical", tv",
+"physical", and "world". The output coordinate system options are "logical",
+"tv", and "physical". The image cursor coordinate system is assumed to
+be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin and wcsout are "logical" and "logical" respectively.
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default cacheing is
+disabled.
+.le
+.ls verify = ")_.verify"
+Verify the critical parameters in non-interactive mode ? Verify may be set to
+the apphot package parameter value (the default), "yes", or "no.
+.le
+.ls update = ")_.update"
+Update the critical parameters in non-interactive mode if \fIverify\fR is
+set to yes? Update may be set to the apphot package parameter value (the
+default), "yes", or "no.
+.le
+.ls verbose = ")_.verbose"
+Print messages on the terminal in non-interactive mode ? Verbose may be set
+to the apphot package parameter value (the default), "yes", or "no.
+.le
+.ls graphics = ")_.graphics"
+The default graphics device.
+Graphics may be set to the apphot package parameter value (the default), "yes",
+or "no.
+.le
+.ls display = ")_.display"
+The default display device. Display may be set to the apphot package
+parameter value (the default), "yes", or "no. By default graphics overlay
+is disabled. Setting display to one of "imdr", "imdg", "imdb", or "imdy"
+enables graphics overlay with the IMD graphics kernel. Setting display to
+"stdgraph" enables CENTER to work interactively from a contour plot.
+.le
+
+.ih
+DESCRIPTION
+CENTER computes accurate centers for a set of objects in the IRAF image
+\fIimage\fR, whose initial coordinates are read from the image display cursor,
+from the text file \fIcoords\fR, or from a cursor command file.
+The computed x and y coordinates, the errors, and the fitting parameters
+are written to the text file \fIoutput\fR.
+
+The coordinates read from \fIcoords\fR are assumed to be in coordinate
+system defined by \fIwcsin\fR. The options are "logical", "tv", "physical",
+and "world" and the transformation from the input coordinate system to
+the internal "logical" system is defined by the image coordinate system.
+The simplest default is the "logical" pixel system. Users working on with
+image sections but importing pixel coordinate lists generated from the parent
+image must use the "tv" or "physical" input coordinate systems.
+Users importing coordinate lists in world coordinates, e.g. ra and dec,
+must use the "world" coordinate system and may need to convert their
+equatorial coordinate units from hours and degrees to degrees and degrees first.
+
+The coordinates written to \fIoutput\fR are in the coordinate
+system defined by \fIwcsout\fR. The options are "logical", "tv",
+and "physical". The simplest default is the "logical" system. Users
+wishing to correlate the output coordinates of objects measured in
+image sections or mosaic pieces with coordinates in the parent
+image must use the "tv" or "physical" coordinate systems.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If cacheing
+is enabled and CENTER is run interactively the first measurement will appear
+to take a long time as the entire image must be read in before the measurement
+is actually made. All subsequent measurements will be very fast because CENTER
+is accessing memory not disk. The point of cacheing is to speed up random
+image access by making the internal image i/o buffers the same size as the
+image itself. However if the input object lists are sorted in row order and
+sparse cacheing may actually worsen not improve the execution time. Also at
+present there is no point in enabling cacheing for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of cacheing in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halves of the image are alternated.
+
+CENTER can be run either interactively or in batch mode by setting the
+parameter \fIinteractive\fR. In interactive mode starting x and y positions
+can either be read directly from the image cursor or read from the text
+file \fIcoords\fR. In interactive mode the user can examine, adjust, and
+save the algorithm parameters, change ojects interactively, query for
+the next or nth object in the list, or fit the entire coordinate list with
+the chosen parameter set. In batch mode the positions can be read from the
+text file \fIcoords\fR or the image cursor can be redirected to a text file
+containing a list of cursor commands as specified by the parameter
+\fIicommands\fR.
+
+.ih
+CURSOR COMMANDS
+
+The following cursor commands are currently available.
+
+.nf
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+v Verify the critical parameters
+w Save the current parameters
+d Plot radial profile of current star
+i Interactively set parameters using current star
+f Fit center of current star
+spbar Fit center of current star, output results
+m Move to next star in coordinate list
+n Center next star in coordinate list, output results
+l Center remaining stars in coordinate list, output results
+e Print error messages
+r Rewind the coordinate list
+q Exit task
+
+
+ Colon Commands
+
+:show [data/center] List the parameters
+:m [n] Move to next [nth] star in coordinate list
+:n [n] Center next [nth] star in coordinate list,
+ output results
+
+
+ Colon Parameter Editing Commands
+
+# Image and file name parameters
+
+:image [string] Image name
+:coords [string] Coordinate file name
+:output [string] Output file name
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Full-width half-maximum of PSF (scale units)
+:emission [y/n] Emission feature (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good data value (counts)
+:datamax [value] Maximum good data value (counts)
+
+# Noise parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per adu)
+:readnoise [value] Readout noise (electrons)
+
+# Observations parameters
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Exposure time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observation (time units)
+
+# Centering parameters
+
+:calgorithm [string] Centering algorithm
+:cbox [value] Width of centering box (scale units)
+:cthreshold [value] Centering intensity threshold (sigma)
+:cmaxiter [value] Maximum number of iterations
+:maxshift [value] Maximum center shift (scale units)
+:minsnratio [value] Minimum signal to noise for centering
+:clean [y/n] Clean subraster before centering
+:rclean [value] Cleaning radius (scale units)
+:rclip [value] Clipping radius (scale units)
+:kclean [value] Clean K-sigma rejection limit (sigma)
+
+# Plotting and marking parameters
+
+:mkcenter [y/n] Mark computed centers on the display
+:radplot [y/n] Plot radial profile of object
+
+
+The following keystroke commands are available from the interactive setup
+menu.
+
+ Interactive Center Setup Menu
+
+ v Mark and verify the critical center parameters (f,s,c)
+
+ f Mark and verify the full-width half-maximum of the psf
+ s Mark and verify the standard deviation of the background
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
+
+ c Mark and verify the centering box half-width
+ n Mark and verify the cleaning radius
+ p Mark and verify the clipping radius
+.fi
+
+.ih
+ALGORITHMS
+
+Descriptions of the data dependent parameters and the centering
+algorithm parameters can be found in the online manual pages for
+\fIdatapars\fR and \fIcenterpars\fR.
+
+.ih
+OUTPUT
+
+In interactive mode the following quantities are written to the terminal
+as each object is measured. Error is a simple string which indicates
+whether an error condition has been flagged. The centers and their errors are
+in pixel units.
+
+.nf
+ image xinit yinit xcenter ycenter xerr yerr error
+.fi
+
+In both interactive and batch mode the full output is written to the
+text file \fIoutput\fR. At the beginning of each file is a header
+listing the current values of the parameters when the first stellar
+record was written. These parameters can be subsequently altered.
+For each star measured the following record is written
+
+.nf
+ image xinit yinit id coords lid
+ xcenter ycenter xshift yshift xerr yerr cier error
+.fi
+
+Image and coords are the name of the image and coordinate file respectively.
+Id and lid are the sequence numbers of stars in the output and coordinate
+files respectively. Cier and error are the centering error code and accompanying
+error message respectively. Xinit, yinit, xcenter, ycenter, xshift, yshift,
+and xerr, yerr are self explanatory and output in pixel units. The sense of
+the xshift and yshift definitions is the following.
+
+.nf
+ xshift = xcenter - xinit
+ yshift = ycenter - yinit
+.fi
+
+In interactive mode a radial profile of each measured object is plotted
+in the graphics window if \fIradplots\fR is "yes".
+
+In interactive and batchmode a radial profile plot is written to
+\fIplotfile\fR if it is defined each time the result of an object
+measurement is written to \fIoutput\fR .
+
+.ih
+ERRORS
+
+If the object centering was error free then the field cier will be zero.
+Non-zero values in the cier column flag the following error conditions.
+
+.nf
+ 0 # No error
+ 101 # The centering box is off the image
+ 102 # The centering box is partially off the image
+ 103 # The S/N ratio is low in the centering box
+ 104 # There are two few points for a good fit
+ 105 # The x or y center fit is singular
+ 106 # The x or y center fit did not converge
+ 107 # The x or y center shift is greater than maxshift
+ 108 # There is bad data in the centering box
+.fi
+
+.ih
+EXAMPLES
+
+1. Compute the centers for a few stars in dev$ypix using the image display
+and the image cursor. Setup the task parameters using the interactive
+setup menu defined by the i keystroke command and a radial profile plot.
+
+.nf
+ ap> display dev$ypix 1 fi+
+
+ ... display the image
+
+ ap> center dev$ypix
+
+ ... type ? to see help screen
+
+ ... move image cursor to a star
+ ... type i to enter the interactive setup menu
+ ... enter the maximum radius in pixels for the radial profile or
+ accept the default with a CR
+ ... type v to get the default menu
+ ... set the fwhmpsf, sigma, and centering box half-width using the
+ graphics cursor and the stellar radial profile plot
+ ... typing <CR> after a prompt leaves the parameter at its default
+ value
+ ... type q to exit setup menu
+
+ ... type the v key to verify the critical parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... move the image cursor to the stars of interest and tap
+ the space bar
+
+ ... type q to quit followed by q to confirm the quit
+
+ ... the output will appear in ypix.ctr.1
+
+.fi
+
+2. Compute the centers for a few stars in dev$ypix using the contour plot
+and the graphics cursor. This option is only useful for those (now very few)
+users who have access to a graphics terminal but not to an image display
+server. Setup the task parameters using the interactive setup menu defined by
+the i key command as in example 1.
+
+.nf
+ ap> show stdimcur
+
+ ... record the default value of stdimcur
+
+ ap> set stdimcur = stdgraph
+
+ ... define the image cursor to be the graphics cursor
+
+ ap> contour dev$ypix
+
+ ... make a contour plot of dev$ypix
+
+ ap> contour dev$ypix >G ypix.plot1
+
+ ... store the contour plot of ypix in the file ypix.plot
+
+ ap> center dev$ypix display=stdgraph
+
+ ... type ? to see the help screen
+
+ ... move graphics cursor to a star
+ ... type i to enter the interactive setup menu
+ ... enter the maximum radius in pixels for the radial profile or
+ accept the default with a CR
+ ... type v key to get the default setup menu
+ ... enter maximum radius in pixels of the radial profile
+ ... set the fwhmpsf, sigma, and centering box half-width
+ using the graphics cursor and the stellar radial profile plot
+ ... typing <CR> after the prompt leaves the parameter at its
+ default value
+ ... type q to quit the setup menu
+
+ ... type the v key to verify critical parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... retype :.read ypix.plot1 to reload the contour plot
+
+ ... move the graphics cursor to the stars of interest and tap
+ the space bar
+
+ ... a one line summary of the answers will appear on the standard
+ output for each star measured
+
+ ... type q to quit followed by q to confirm the quit
+
+ ... full output will appear in the text file ypix.ctr.2
+
+ ap> set stdimcur = <default>
+
+ ... reset stdimcur to its previous value
+.fi
+
+
+3. Setup and run CENTER interactively on a list of objects temporarily
+overriding the fwhmpsf, sigma, and cbox parameters determined in examples
+1 or 2.
+
+.nf
+ ap> daofind dev$ypix fwhmpsf=2.6 sigma=25.0 verify-
+
+ ... make a coordinate list
+
+ ... the output will appear in the text file ypix.coo.1
+
+ ap> center dev$ypix cbox=7.0 coords=ypix.coo.1
+
+ ... type ? for optional help
+
+
+ ... move the graphics cursor to the stars and tap space bar
+
+ or
+
+ ... select stars from the input coordinate list with m / :m #
+ and measure with spbar
+
+ ... measure stars selected from the input coordinate list
+ with n / n #
+
+ ... a one line summary of results will appear on the standard output
+ for each star measured
+
+ ... the output will appear in ypix.ctr.3 ...
+.fi
+
+
+4. Display and measure some stars in an image section and write the output
+coordinates in the coordinate system of the parent image.
+
+.nf
+ ap> display dev$ypix[150:450,150:450] 1
+
+ ... display the image section
+
+ ap> center dev$ypix[150:450,150:450] wcsout=tv
+
+ ... move cursor to stars and type spbar
+
+ ... type q to quit and q again to confirm quit
+
+ ... output will appear in ypix.ctr.4
+
+ ap> pdump ypix.ctr.4 xc,yc yes | tvmark 1 STDIN col=204
+.fi
+
+
+5. Run CENTER in batch mode using the coordinate file and the previously
+saved parameters. Verify the critical parameters.
+
+.nf
+ ap> center dev$ypix coords=ypix.coo.1 verify+ inter-
+
+ ... output will appear in ypix.ctr.5 ...
+.fi
+
+
+6. Repeat example 5 but assume that the input coordinate are ra and dec
+in degrees and degrees, turn off verification, and submit the task to to
+the background.
+
+.nf
+ ap> display dev$ypix
+
+ ap> rimcursor wcs=world > radec.coo
+
+ ... move to selected stars and type any key
+
+ ... type ^Z to quit
+
+ ap> center dev$ypix coords=radec.coo wcsin=world verify- inter- &
+
+ ... output will appear in ypix.ctr.6
+
+ ap> pdump ypix.ctr.6 xc,yc yes | tvmark 1 STDIN col=204
+
+ ... mark the stars on the display
+
+
+7. Run CENTER interactively without using the image display.
+
+.nf
+ ap> show stdimcur
+
+ ... record the default value of stdimcur
+
+ ap> set stdimcur = text
+
+ ... set the image cursor to the standard input
+
+ ap> center dev$ypix coords=ypix.coo.1
+
+ ... type ? for optional help
+
+ ... type :m 3 to set the initial coordinates to those of the
+ third star in the list
+
+ ... type i to enter the interactive setup menu
+ ... enter the maximum radius in pixels for the radial profile or
+ accept the default with a CR
+ ... type v to enter the default menu
+ ... set the fwhmpsf, sigma, and centering box half-width
+ using the graphics cursor and the stellar radial profile plot
+ ... typing <CR> after the prompt leaves the parameter at its default
+ value
+
+ ... type r to rewind the coordinate list
+
+ ... type l to measure all the stars in the coordinate list
+
+ ... a one line summary of the answers will appear on the standard
+ output for each star measured
+
+ ... type q to quit followed by q to confirm the quit
+
+ ... full output will appear in the text file ypix.ctr.7
+
+ ap> set stdimcur = <default>
+
+ ... reset the value of stdimcur
+.fi
+
+8. Use a image cursor command file to drive the CENTER task. The cursor command
+file shown below sets the fwhmpsf, calgorithm, and cbox parameters, computes
+the centers for 3 stars, updates the parameter files, and quits the task.
+
+.nf
+ ap> type cmdfile
+ : calgorithm gauss
+ : fwhmpsf 2.5
+ : cbox 9.0
+ 442 410 101 \040
+ 349 188 101 \040
+ 225 131 101 \040
+ w
+ q
+
+ ap> center dev$ypix icommands=cmdfile verify-
+
+ ... full output will appear in ypix.ctr.8
+.fi
+
+.ih
+BUGS
+
+It is the responsibility of the user to make sure that the image displayed
+in the image display is the same as the image specified by the image parameter.
+
+Commands which draw to the image display are disabled by default.
+To enable graphics overlay on the image display, set the display
+parameter to "imdr", "imdg", "imdb", or "imdy" to get red, green,
+blue or yellow overlays and set the centerpars mkcenter switch to
+"yes". It may be necessary to run gflush and to redisplay the image
+to get the overlays position correctly.
+
+.ih
+SEE ALSO
+datapars, centerpars
+.endhelp
diff --git a/noao/digiphot/apphot/doc/centerpars.hlp b/noao/digiphot/apphot/doc/centerpars.hlp
new file mode 100644
index 00000000..008869f4
--- /dev/null
+++ b/noao/digiphot/apphot/doc/centerpars.hlp
@@ -0,0 +1,206 @@
+.help centerpars May00 noao.digiphot.apphot
+.ih
+NAME
+centerpars -- edit the centering algorithm parameters
+.ih
+USAGE
+centerpars
+.ih
+PARAMETERS
+.ls calgorithm = "centroid"
+The centering algorithm. The "gauss" and "ofilter" options depend critically
+on the value of the fwhmpsf parameter in the DATAPARS task. The centering
+options are:
+.ls none
+The initial positions are assumed to be the true centers. Users
+may select this option if the initial centers are know to be accurate,
+e.g. they were computed by DAOFIND task.
+.le
+.ls centroid
+The object centers are determined by computing the intensity weighted means
+of the marginal profiles in x and y. This is the recommended default algorithm
+for APPHOT users.
+.le
+.ls gauss
+The object centers are computed by fitting a Gaussian of fixed fwhmpsf,
+specified by the DATAPARS fwhmpsf parameter, to the marginal profiles in
+x and y using non-linear least squares techniques.
+.le
+.ls ofilter
+The object centers are computed using optimal filtering techniques,
+a triangular weighting function of half width equal to fwhmpsf as
+specified by the DATAPARS fwhmpsf parameter, and the marginal distributions
+in x and y.
+.le
+.le
+.ls cbox = 5.0 (scale units)
+The width of the subraster used for object centering in units of the
+DATAPARS scale parameter. Cbox must be big enough to include a reasonable
+number of pixels for center determination but not so large so as to include
+a lot of noise. Recommended initial values are 2.5-4.0 * the FWHM of the PSF
+value.
+.le
+.ls cthreshold = 0.0 (sigma units)
+Pixels cthreshold * sigma above (emission features) or below (absorption
+features) the data minimum or maximum respectively are used by the centering
+algorithms where sigma is equal to the value of the DATAPARS sigma parameter.
+Most APPHOT users should leave this value at 0.0 which invokes the appropriate
+default thresholding technique for each centering algorithm. Setting cthreshold
+to INDEF turns off thresholding altogether for all the centering algorithms.
+.le
+.ls minsnratio = 1.0
+The minimum signal to noise ratio for object centering. If the estimated signal
+to noise ratio is less than minsnratio the computed center will be returned
+with an error flag.
+.le
+.ls cmaxiter = 10
+The maximum number of iterations performed by the centering algorithm.
+All the centering algorithms use this parameter.
+.le
+.ls maxshift = 1.0 (scale units)
+The maximum permissible shift of the center with respect to the initial
+coordinates in units of the scale parameter. If the shift produced by the
+centering algorithms is larger than maxshift, the computed center is returned
+with an error flag.
+.le
+.ls clean = no
+Symmetry-clean the centering subrater before centering? APPHOT users should
+leave clean set to "no".
+.le
+.ls rclean = 1.0 (scale units)
+The cleaning radius for the symmetry-clean algorithm in units of the scale
+parameter.
+.le
+.ls rclip = 2.0 (scale units)
+The clipping radius for the symmetry-clean algorithm in units of the scale
+parameter.
+.le
+.ls kclean = 3.0 (sigma)
+The number of sky background standard deviations for the symmetry-clean
+algorithm where sigma is the value of the DATAPARS parameter sigma.
+.le
+.ls mkcenter = no
+Mark the fitted object centers on the displayed image ?
+.le
+.ih
+DESCRIPTION
+
+The centering algorithm parameters control the action of the centering
+algorithms. The default parameters values have been proven to produce
+reasonable results in the majority of cases. Several of the centering
+parameters are defined in terms of the DATAPARS parameter \fIscale\fR,
+the scale of the image, and \fIsigma\fR the standard deviation of
+the sky pixels.
+
+For each object to be measured a subraster of data \fIcbox\fR / \fIscale\fR
+pixels wide around the initial position supplied by the user is extracted
+from the IRAF image. If scale is defined in units of the number
+the half-width half-maximum of the psf per pixel, then a single value of
+cbox can be used for centering objects in images with different psfs.
+
+If \fIclean\fR is "yes" the symmetry-clean algorithm is applied to the
+centering subraster prior to centering. The cleaning algorithm attempts
+to correct defects in the centering subraster by assuming that the image
+is radially symmetric and comparing pixels on opposite sides of the center
+of symmetry. The center of symmetry is assumed to be the maximum pixel
+in the subraster, unless the maximum pixel is more than \fImaxshift /
+scale\fR from the initial center, in which case the initial center is used
+as the center of symmetry. Pixels inside the cleaning radius are not edited.
+Pairs of pixels in the cleaning region, r > \fIrclean\fR / \fIscale\fR
+and r <= \fIrclip\fR / \fIscale\fR and diametrically opposed about the
+center of symmetry are tested for equality. If the difference between the
+pixels is greater than \fIkclean * sigma\fR, the larger value is replaced
+by the smaller. In the cleaning region the sigma is determined by the
+noise model assumed for the data. Pairs of pixels in the clipping region,
+r > \fIrclip\fR / \fIscale\fR are tested in the same manner as those in
+the cleaning region. However the sigma employed is the sigma of the
+sky background. Most APPHOT users should leave clean set to "no".
+
+New centers are computed using the centering algorithm specified by
+\fIcalgorithm\fR, the data specified by \fIcbox / scale\fR, and pixels
+that are some threshold above (below) an estimate of the local minimum
+(maximum). \fICthreshold\fR values of 0.0, a positive number, and INDEF
+invoke the default thresholding algorithm, a threshold equal to the
+local minimum (maximum) plus (minus) \fIdatapars.sigma * cthreshold\fR,
+and a threshold exactly equal to the local minimum (maximum) respectively.
+
+After thresholding the signal to noise ratio of the subraster is estimated.
+If the SNR < \fIminsnratio\fR the new center is still computed but an error
+flag is set.
+
+The default centering algorithm is \fIcentroid\fR. Centroid computes the
+intensity weighted mean and mean error of the centering box x and y marginal
+distributions using points in the marginal arrays above (below) the minimum
+(maximum) data pixel plus (minus) a threshold value.
+
+The threshold value is either the mean, \fIdatapars.sigma * cthreshold\fR
+above (below) the local minimum (maximum) if \fIcthreshold\fR is greater
+than zero, or zero above (below) the local minimum (maximum) if
+\fIcthreshold\fR is INDEF. The centroid algorithm is similar to that
+by the old KPNO Mountain Photometry Code. Note that centroid is the only
+centering algorithm which does not depend on the value of
+\fIdatapars.fwhmpsf\fR.
+
+The centering algorithm \fIgauss\fR computes the new centers by fitting a
+1D Gaussian function to the marginal distributions in x and y using a
+fixed fwhmpsf set by \fIdatapars.fwhmpsf\fR. Initial guesses for the fit
+parameters are derived from the data. The gauss algorithm iterates until
+a best fit solution is achieved.
+
+The final centering algorithm choice \fIofilter\fR employs a variation of the
+optimal filtering technique in which the profile is simulated by a triangle
+function of width \fIdatapars.fwhmpsf\fR.
+
+The default thresholding algorithm for all centering algorithms other
+than "centroid" is no thresholding.
+
+If the computed shift in either coordinate > \fImaxshift\fR / \fIscale\fR,
+the new center is returned but an error flag is set.
+
+.ih
+EXAMPLES
+1. List the centering parameters.
+
+.nf
+ ap> lpar centerpars
+.fi
+
+2. Edit the centering parameters
+
+.nf
+ ap> centerpars
+.fi
+
+3. Edit the CENTERPARS parameters from with the PHOT task.
+
+.nf
+ da> epar phot
+
+ ... edit a few phot parameters
+
+ ... move to the centerpars parameter and type :e
+
+ ... edit the centerpars parameters and type :wq
+
+ ... finish editing the phot parameters and type :wq
+.fi
+
+4. Save the current CENTERPARS parameter set in a text file ctrnite1.par.
+This can also be done from inside a higher level task as in the
+previous example.
+
+.nf
+ da> centerpars
+
+ ... edit the parameters
+
+ ... type ":w ctrnite1.par" from within epar
+.fi
+
+.ih
+BUGS
+
+.ih
+SEE ALSO
+center,phot,wphot,polyphot,radprof
+.endhelp
diff --git a/noao/digiphot/apphot/doc/daofind.hlp b/noao/digiphot/apphot/doc/daofind.hlp
new file mode 100644
index 00000000..ad9687e5
--- /dev/null
+++ b/noao/digiphot/apphot/doc/daofind.hlp
@@ -0,0 +1,579 @@
+.help daofind May00 noao.digiphot.apphot
+.ih
+NAME
+daofind -- automatically detect objects in an image
+.ih
+USAGE
+daofind image
+.ih
+PARAMETERS
+.ls image
+The list of images in which objects are to be detected.
+.le
+.ls output = "default"
+The name of the results file or the results directory. If output is
+"default", "dir$default" or a directory specification then a results file
+name of the form dir$root.extension.version is constructed, where
+dir is the directory, root is the root image name, extension is "coo"
+and version is the next available version number for the file. If the
+output string is undefined then no output file is created. One output
+file is created for every input image.
+.le
+.ls starmap = ""
+The name of the image prefix and/or directory where the density enhancement
+image will be stored. If starmap is undefined or a directory,
+DAOFIND will create a temporary image which is deleted on exit from
+the program. Otherwise starmap is prefixed to the image name
+and the density enhancement image will be saved for use in a subsequent
+run of DAOFIND.
+.le
+.ls skymap = ""
+The name of the image prefix and/or directory where the mean density
+image will be stored. If skymap is undefined or a directory, no mean density
+image is created. Otherwise skymap is prefixed to the image name
+and the mean density image will be saved on disk. Skymap is not used by
+the DAOFIND algorithms, but may be used by the user as a check on DAOFIND,
+since the sum of starmap and skymap is a type of best fit to the original
+image.
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters. The critical
+parameters \fIfwhmpsf\fR and \fIsigma\fR are located here. If \fIdatapars\fR
+is undefined then the default parameter set in the user's uparm directory is
+used.
+.le
+.ls findpars = ""
+The name of the file containing the object detection parameters. The
+parameter \fIthreshold\fR is located here. If findpars is undefined then
+the default parameter set in the user's uparm directory is used.
+.le
+.ls boundary = "nearest"
+The type of boundary extension. The choices are:
+.ls nearest
+Use the value of the nearest boundary pixel.
+.le
+.ls constant
+Use a constant value.
+.le
+.ls reflect
+Generate a value by reflecting around the boundary.
+.le
+.ls wrap
+Generate a value by wrapping around to the other side of the image.
+.le
+.le
+.ls constant = 0
+The constant for constant boundary extension.
+.le
+.ls interactive = no
+Interactive or batch mode?
+.le
+.ls icommands = ""
+The image display cursor or image cursor command file.
+.le
+.ls gcommands = ""
+The graphics cursor or graphics cursor command file.
+.le
+.ls wcsout = ")_.wcsout"
+The coordinate system of the output coordinates written to \fIoutput\fR. The
+image header coordinate system is used to transform from the internal "logical"
+pixel coordinate system to the output coordinate system. The output coordinate
+system options are "logical", "tv", and "physical". The image cursor coordinate
+ system is assumed to be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+The wcsout parameter defaults to the value of the package parameter of the same
+ name. The default values of the package parameters wcsin and wcsout are
+"logical" and "logical" respectively.
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default cacheing is
+disabled.
+.le
+.ls verify = ")_.verify"
+Automatically confirm the critical parameters when running in non-interactive
+mode? Verify may be set to the apphot package parameter value (the default),
+"yes", or "no".
+.le
+.ls update = ")_.update"
+Automatically update the algorithm parameters in non-interactive mode if
+verify is "yes". Update may be set to the apphot package parameter value
+(the default), "yes", or "no".
+.le
+.ls verbose = ")_.verbose"
+Print out information about the progress of the task in non-interactive mode.
+Verbose may be set to the apphot package parameter value (the default), "yes",
+or "no".
+.le
+.ls graphics = ")_.graphics"
+The standard graphics device. Graphics may be set to the apphot package
+parameter value (the default), "yes", or "no".
+.le
+.ls display = ")_.display"
+The standard image display device. Display may be set to the apphot package
+parameter value (the default), "yes", or "no". By default graphics overlay is
+disabled. Setting display to one of "imdr", "imdg", "imdb", or "imdy" enables
+graphics overlay with the IMD graphics kernel. Setting display to "stdgraph"
+enables DAOFIND to work interactively from a contour plot.
+
+.le
+
+.ih
+DESCRIPTION
+
+DAOFIND searches the IRAF images \fIimage\fR for local density maxima,
+which have a full-width half-maximum of \fIdatapars.fwhmpsf\fR and a peak
+amplitude greater than \fIfindpars.threshold\fR * \fIdatapars.sigma\fR above
+the local background, and writes a list of detected objects in the file
+\fIoutput\fR. The detected objects are also listed on the standard output
+if the program is running in interactive mode, or in non-interactive mode
+with the \fIverbose\fR switch is turned on.
+
+The coordinates written to \fIoutput\fR are in the coordinate
+system defined by \fIwcsout\fR. The options are "logical", "tv",
+and "physical". The simplest default is the "logical" system. Users
+wishing to correlate the output coordinates of objects measured in
+image sections or mosaic pieces with coordinates in the parent
+image must use the "tv" or "physical" coordinate systems.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input and output image pixels are cached in memory. If
+cacheing is enabled and DAOFIND is run interactively the first measurement
+will appear to take a long time as the entire image must be read in before the
+measurement is actually made. All subsequent measurements will be very fast
+because DAOFIND is accessing memory not disk. The point of cacheing is to speed
+up random image access by making the internal image i/o buffers the same size
+as the image itself. However if the input object lists are sorted in row order
+and sparse cacheing may actually worsen not improve the execution time. Also at
+present there is no point in enabling cacheing for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of cacheing in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halfs of the image are alternated.
+
+DAOFIND can be run either interactively or in batch mode by setting the
+parameter \fIinteractive\fR. In interactive mode the user can examine,
+adjust, and save algorithm parameters, and fit or refit the entire coordinate
+list with the chosen parameter set. The \fIverify\fR parameter can be used
+to automatically enable confirmation of the critical parameters
+\fIdatapars.fwhmpsf\fR and \fIdatapars.sigma\fR when running in
+non-interactive mode.
+
+
+.ih
+CURSOR COMMANDS
+
+.nf
+
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+v Verify the critical parameters
+w Save the current parameters
+d Plot radial profile of star near cursor
+i Interactively set parameters using star near cursor
+f Find stars in the image
+spbar Find stars in the image, output results
+q Exit task
+
+
+ Colon Commands
+
+:show [data/find] List the parameters
+
+ Colon Parameter Editing Commands
+
+# Image and file name parameters
+
+:image [string] Image name
+:output [string] Output file name
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Full width half maximum of psf (scale units)
+:emission [y/n] Emission feature (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good data value (counts)
+:datamax [value] Maximum good data value (counts)
+
+# Noise description parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per adu)
+:readnoise [value] Readout noise (electrons)
+
+# Observation parameters
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Exposure time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observation (time units)
+
+# Object detection parameters
+
+:nsigma [value] Size of Gaussian kernel (sigma)
+:threshold [value] Detection intensity threshold (counts)
+:ratio [value] Sigmay / sigmax of Gaussian kernel
+:theta [value] Position angle of Gaussian kernel
+:sharplo [value] Lower bound on sharpness
+:sharphi [value] Upper bound on sharpness
+:roundlo [value] Lower bound on roundness
+:roundhi [value] Upper bound on roundness
+
+# Plotting and marking commands
+
+:mkdetections [y/n] Mark detections on the image display
+
+
+The following commands are available inside the interactive setup menu.
+
+
+ Interactive Daofind Setup Menu
+
+ v Mark and verify critical daofind parameters (f,s)
+
+ f Mark and verify the full-width half-maximum of the psf
+ s Mark and verify the standard deviation of the background
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
+.fi
+
+.ih
+ALGORITHMS
+
+DAOFIND approximates the stellar point spread function with an elliptical
+Gaussian function, whose sigma along the semi-major axis is 0.42466 *
+\fIdatapars.fwhmpsf\fR / \fIdatapars.scale\fR pixels, semi-minor to semi-major
+axis ratio is \fIratio\fR, and major axis position angle is \fItheta\fR.
+Using this model, a convolution kernel, truncated at \fInsigma\fR sigma,
+and normalized so as to sum to zero, is constructed.
+
+The density enhancement image \fIstarmap\fR is computed by convolving the input
+image with the Gaussian kernel. This operation is mathematically equivalent to
+fitting, in the least-squares sense, the image data at each point with a
+truncated, lowered elliptical Gaussian function. After convolution each point
+in \fIstarmap\fR contains as estimate of the amplitude of the best fitting
+Gaussian function at that point. Each point in \fIskymap\fR, if the user
+chooses to compute it, contains an estimate of the best fitting sky value
+at that point.
+
+After image convolution , DAOFIND steps through \fIstarmap\fR searching
+for density enhancements greater than \fIfindpars.threshold\fR *
+\fIdatapars.sigma\fR, and brighter than all other density enhancements within
+a semi-major axis of 0.42466 \fIfindpars.nsigma\fR * \fIdatapars.fwhmpsf\fR.
+As the program selects candidates, it computes three shape characteristics,
+sharpness and 2 estimates of roundness. The sharpness statistic measures the
+ratio of, the difference between the height of the central pixel and the mean
+of the surrounding non-bad pixels, to the height of the best fitting Gaussian
+function at that point. The first roundness characteristic computes the ratio
+of a measure of the bilateral symmetry of the object to a measure of the
+four-fold symmetry of the object. The second roundness statistic measures the
+ratio of, the difference in the height of the best fitting Gaussian function
+in x minus the best fitting Gaussian function in y, over the average of the
+best fitting Gaussian functions in x and y. The limits on these parameters
+\fIfindpars.sharplo\fR, \fIfindpars.sharphi\fR \fIfindpars.roundlo\fR, and
+\fIfindpars.roundhi\fR, are set to weed out non-astronomical objects and
+brightness enhancements that are elongated in x and y respectively.
+
+Lastly the x and y centroids of the detected objects are computed by estimating
+the x and y positions of the best fitting 1D Gaussian functions in x and y
+respectively, a rough magnitude is estimated by computing the ratio of the
+amplitude of the best fitting Gaussian at the object position to
+\fIfindpars.threshold\fR * \fIdatapars.sigma\fR, and the object is added to
+the output coordinate file.
+
+.ih
+OUTPUT
+
+In interactive mode or in non-interactive with the verbose switch turned on
+the following quantities are written to the terminal as each object is
+detected.
+
+.nf
+ xcenter ycenter mag sharpness sround ground id
+
+ where
+
+ mag = -2.5 * log10 (peak density / detection threshold)
+.fi
+
+The object centers are in pixels and the magnitude estimate measures the
+ratio of the maximum density enhancement to the detection threshold.
+Sharpness is typically around .5 to .8 for a star with a fwhmpsf similar to
+the pattern star. Both sround and ground are close to zero for a truly
+round star. Id is the sequence number of the star in the list.
+
+In both interactive and batch mode the full output is written to the text
+file \fIoutput\fR. At the beginning of each file is a header, listing
+the current values of the parameters when the first stellar record was
+written. The parameters can subsequently be altered.
+
+.ih
+EXAMPLES
+
+1. Run daofind interactively on dev$ypix using the image display
+and image display cursor. Set the fwhmpsf and sigma parameters
+with the graphics cursor, radial profile plot, and the interactive
+setup key i.
+
+.nf
+ ap> display dev$ypix 1 fi+
+
+ ... display the image
+
+ ap> daofind dev$ypix interactive+
+
+ ... type ? to see help screen
+
+ ... move display cursor to a star
+ ... type i to enter the interactive setup menu
+ ... enter maximum radius in pixels of the radial profile or
+ accept default with a CR
+ ... set the fwhmpsf and sigma using the graphics cursor and the
+ radial profile plot
+ ... typing <CR> leaves the parameters at their default values
+ ... type q to quit setup menu
+
+ ... type the v key to verify the critical parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... type the space bar to detect stars in the image
+
+ ... a 1 line summary of the answers will appear on the standard
+ output for each star measured
+
+ ... type q to quit and q again to confirm the quit
+
+ ... full output will appear in the text file ypix.coo.1
+
+.fi
+
+2. Run daofind interactively on a single image using a contour plot in place
+of the image and the graphics cursor in place of the image cursor.
+This option is only useful for those (now very few) users who have access to
+a graphics terminal but not to an image display server. Set the fwhmpsf and
+sigma parameters with the graphics cursor and radial profile plot and the
+interactive setup key i.
+
+.nf
+ ap> show stdimcur
+
+ ... record the default value of stdimcur
+
+ ap> set stdimcur = stdgraph
+
+ ... define the image cursor to be the graphics cursor
+
+ ap> contour dev$ypix
+
+ ... make a contour plot of dev$ypix
+
+ ap> contour dev$ypix >G ypix.plot1
+
+ ... store the contour plot of ypix in the file ypix.plot
+
+ ap> daofind dev$ypix display=stdgraph interactive+
+
+ ... type ? to see the help screen
+
+ ... move graphics cursor to a setup star
+ ... type i to enter the interactive setup menu
+ ... enter maximum radius in pixels of the radial profile or
+ accept the default with a CR
+ ... set the fwhmpsf and sigma using the graphics cursor and the
+ radial profile plot
+ ... typing <CR> leaves the parameters at their default values
+ ... type q to quit the setup menu
+
+ ... type the v key to confirm the critical parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... retype :.read ypix.plot1 to reload the contour plot
+
+ ... type the space bar to detect stars in the image
+
+ ... a 1 line summary of the answers will appear on the standard
+ output for each star measured
+
+ ... full output will appear in the text file ypix.coo.2
+
+ ap> set stdimcur = <default>
+
+ ... reset the image cursor to its default value
+
+.fi
+
+
+3. Run DAOFIND interactively without using the image display cursor.
+
+.nf
+ ap> show stdimcur
+
+ ... record the default value of stdimcur
+
+ ap> set stdimcur = text
+
+ ... set the image cursor to the standard input
+
+ ap> display dev$ypix 1
+
+ ... display the image
+
+ ap> daofind dev$ypix interactive+
+
+ ... type ? for help
+
+ ... type "442 409 101 i" in response to the image cursor query where
+ x and y are the coordinates of the star to be used as setup,
+ 101 is the default world coordinate system, and i enters the
+ interactive setup menu.
+ ... enter maximum radius in pixels of the radial profile or
+ type CR to accept the default
+ ... set the fwhmpsf and sigma using the graphics cursor and the
+ radial profile plot
+ ... typing <CR> leaves the parameters at their default values
+ ... type q to quit the setup menu
+
+ ... type the v key to verify the parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... type the space bar to detect stars in the image
+
+ ... a 1 line summary of the answers will appear on the standard
+ output for each star measured
+
+ ... type q to quit and q again to confirm
+
+ ... full output will appear in the text file ypix.coo.3
+
+ ap> set stdimcur = <default>
+
+ ... reset the image cursor to its default value
+.fi
+
+
+4. Run daofind on a list of 3 images contained in the file imlist in batch mode.
+The program will ask the user to verify that the fwhmpsf and the threshold are
+correct before beginning execution.
+
+.nf
+ ap> type imlist
+ dev$ypix
+ dev$wpix
+ dev$pix
+
+ ap> daofind @imlist
+
+ ... the output will appear in ypix.coo.4, wpix.coo.1, pix.coo.1
+.fi
+
+
+5. Display and find stars in an image section. Write the output coordinates
+in the coordinate system of the parent image. Mark the detected stars on
+the displayed image.
+
+.nf
+ ap> display dev$ypix[150:450,150:450]
+
+ ... display the image section
+
+ ap> daofind dev$ypix[150:450,150:450] wcsout=tv
+
+ ... output will appear in ypix.coo.5
+
+ ap> tvmark 1 ypix.coo.5 col=204
+.fi
+
+
+6. Repeat example 4 but submit the job to the background and turn off the
+verify switch.
+
+.nf
+ ap> daofind @imlist verify- &
+
+ ... the output will appear in ypix.coo.6, wpix.coo.2, pix.coo.2
+.fi
+
+
+7. Use an image cursor command file to drive the daofind task. The cursor
+command file shown below sets the fwhmpsf, sigma, and threshold parameters,
+located stars in the image, updates the parameter files, and quits the task.
+
+.nf
+ ap> type cmdfile
+ : fwhmpsf 2.5
+ : sigma 5.0
+ : threshold 10.0
+ \040
+ w
+ q
+
+ ap> daofind dev$ypix icommands=cmdfile verify-
+
+ ... full output will appear in ypix.coo.7
+.fi
+
+
+.ih
+TIME REQUIREMENTS
+
+.ih
+BUGS
+
+It is currently the responsibility of the user to make sure that the
+image displayed in the frame is the same as that specified by the image
+parameter.
+
+Commands which draw to the image display are disabled by default.
+To enable graphics overlay on the image display, set the display
+parameter to "imdr", "imdg", "imdb", or "imdy" to get red, green,
+blue or yellow overlays and set the findpars mkdetections switch to
+"yes". It may be necessary to run gflush and to redisplay the image
+to get the overlays position correctly.
+
+.ih
+SEE ALSO
+datapars, findpars
+.endhelp
diff --git a/noao/digiphot/apphot/doc/daofind.noao b/noao/digiphot/apphot/doc/daofind.noao
new file mode 100644
index 00000000..74cc8f00
--- /dev/null
+++ b/noao/digiphot/apphot/doc/daofind.noao
@@ -0,0 +1,21 @@
+
+
+There is a bug in the iraf/daophot ii daofind centering code which results in
+incorrect fractional pixel corrections being computed for the detected objects.
+This error can most easily be detected by plotting the histogram of the
+fractional pixel corrections for an image with a large number of detected
+objects. The histogram will be modulated at around the 20% level with "peaks"
+around the 0.33 and 0.66 fractional pixel values.
+
+This bug is fixed for the next release of iraf and in the external addon
+package digiphotx version of daofind. There is no workaround although it
+should be emphasized that this bug does not affect the centers computed by
+the psf fitting code in the peak, nstar, and allstar tasks. Users concerned
+with precision in the daofind results should upgrade their software, or
+recenter the objects with the phot "centroid" (fast) or "gauss" (more precise)
+routines.
+
+This bug is also present in the standalone version of daophot ii. I have
+reported this problem to Peter Stetson and he has fixed it. Users concerned
+about this bug in the standalone version of daophot ii should obtain a fix
+from Peter Stetson.
diff --git a/noao/digiphot/apphot/doc/datapars.hlp b/noao/digiphot/apphot/doc/datapars.hlp
new file mode 100644
index 00000000..bacc5c77
--- /dev/null
+++ b/noao/digiphot/apphot/doc/datapars.hlp
@@ -0,0 +1,290 @@
+.help datapars May00 noao.digiphot.apphot
+.ih
+NAME
+datapars -- edit the data dependent parameters
+.ih
+USAGE
+datapars
+.ih
+PARAMETERS
+.ls scale = 1.0
+The scale of the image in user units, e.g arcseconds per pixel.
+All APPHOT distance dependent parameters are assumed to be in units of scale.
+If scale = 1.0 these parameters are assumed to be in units of pixels.
+Most APPHOT users should leave scale set to 1.0 unless they intend to
+compare their aperture photometry results directly with data
+in the literature.
+.le
+.ls fwhmpsf = 2.5 (scale units)
+The full-width at half-maximum of the point spread function in scale units.
+The DAOFIND, FITPSF and WPHOT tasks and the "gauss" and "ofilter" centering
+algorithms depend on the value of fwhmpsf. APPHOT users can either determine
+a value for fwhmpsf using an external task such as IMEXAMINE, or make use of
+the interactive capabilities of the APPHOT tasks to set and store it.
+.le
+.ls emission = yes
+The features to be measured are above sky. By default the APPHOT package
+considers all features to be emission features. However all the package tasks
+measure absorption features if emission is set to no.
+.le
+.ls sigma = INDEF
+The standard deviation of the sky pixels. The DAOFIND task and the "constant"
+sky fitting algorithm error estimate depend on the value of sigma. APPHOT
+users should set sigma to a value which is representative of the noise
+in the sky background.
+.le
+.ls datamin = INDEF
+The minimum good pixel value. Datamin defaults to -MAX_REAL, the minimum
+floating point number supported by the host computer. APPHOT users should
+set this parameter if they wish to remove bad data from the sky pixel
+distribution before the sky is fit or if they wish to flag stars with
+bad data in the centering and / or photometry apertures.
+.le
+.ls datamax = INDEF
+The maximum good pixel value. Datamax defaults to MAX_REAL the maximum
+floating point number supported by the host computer.
+APPHOT users should set this parameter if they wish to flag
+saturated stars or stars with bad data in the centering and / or
+photometry apertures.
+.le
+.ls noise = "poisson"
+The noise model used to estimate the uncertainties in the computed APPHOT
+magnitudes. The options are the following:
+.ls poisson
+Poisson statistics in the object and the sky background are used to estimate
+the error in the object measurement. There are two components to the sky
+noise measurement the sky noise in the object aperture and the mean error
+in the estimated sky value.
+.le
+.ls constant
+The standard deviation of the sky background is used to estimate the
+error in the object measurement. There are two components to the error
+estimate the sky noise in the object aperture and the mean error in the
+estimated sky value.
+.le
+
+Most APPHOT users should use the Poisson model appropriate for CCD detectors.
+APPHOT users should also be aware that one or other of the parameters
+gain or epadu must be set correctly in order to compute the magnitude
+errors correctly.
+.le
+.ls ccdread = ""
+The image header keyword defining the readout noise parameter whose units are
+assumed to be electrons.
+.le
+.ls gain = ""
+The image header keyword defining the gain parameter whose units are assumed
+to be electrons per adu.
+.le
+.ls readnoise = 0.0
+The readout noise of the image in electrons. APPHOT users should set this
+parameter or the ccdread parameter to its correct value before running any
+of the APPHOT tasks.
+.le
+.ls epadu = 1.0
+The gain in electrons per adu. APPHOT users should set epadu or ain to its
+correct value before running any of the APPHOT tasks in order to insure that
+the magnitude error estimates are correct.
+.le
+.ls exposure = ""
+The image header exposure time keyword. The time units are arbitrary but
+must be consistent for any list of images whose magnitudes are to be compared.
+The computed magnitudes are normalized to 1 timeunit. Setting the exposure
+parameter will greatly simplify future reduction steps. The value of exposure
+is recorded in the APPHOT output file.
+.le
+.ls airmass = ""
+The image header airmass keyword. The airmass parameter is not used
+directly by APPHOT but the airmass value is stored in the output file
+and its presence there will simplify future calibration steps.
+.le
+.ls filter = ""
+The image header filter id keyword. The filter parameter is not used
+directly by APPHOT but the filter id is stored in the output file
+and its presence there will simplify future calibration steps.
+.le
+.ls obstime = ""
+The image header time of observation keyword. The obstime parameter is not used
+directly by APPHOT but the obstime value is stored in the output file
+and its presence there will simplify future calibration steps.
+.le
+.ls itime = 1.0
+The exposure time for the image in arbitrary units. The APPHOT magnitudes are
+normalized to 1 timeunit using the value of exposure in the image header
+if exposure is defined or the value of itime.
+.le
+.ls xairmass = INDEF
+The airmass value. The airmass is read from the image header if airmass
+is defined or from xairmass. The airmass value is stored in the APPHOT
+output files.
+.le
+.ls ifilter = "INDEF"
+The filter id string. The filter id is read from the image header if filter
+is defined otherwise from ifilter. The filter id is stored in the APPHOT
+output files.
+.le
+.ls otime = "INDEF"
+The value of the time of observation. The time of observation is read from
+the image header if obstime is defined otherwise from otime. The time of
+observation is stored in the APPHOT output files.
+.le
+.ih
+DESCRIPTION
+\fIDatapars\fR sets the image data dependent parameters. These parameters are
+functions, of the instrument optics, the noise characteristics and range of
+linearity of the detector, and the observing conditions. Many of the
+centering, sky fitting, and photometry algorithm parameters in the CENTERPARS,
+FITSKYPARS and PHOTPARS parameter sets scale with the data dependent
+parameters.
+
+The parameter \fIscale\fR sets the scale of the apertures used by the
+centering, sky fitting and photometry algorithms. Scale converts radial
+distance measurements in pixel units to radial distance measurements in
+scale units. The APPHOT parameters, cbox, maxshift, rclean and rclip
+in the CENTERPARS parameter set; annulus, dannulus, and rgrow in
+the FITSKYPARS parameter set; and apertures in the PHOTPARS
+parameter set are expressed in units of the scale. The scale parameter is
+useful in cases where the observations are to be compared to published
+aperture photometry measurements in the literature.
+
+The parameter \fIfwhmpsf\fR defines the full-width at half-maximum of the
+stellar point spread function. Most APPHOT tasks and algorithms do not
+require this parameter. The exceptions are the DAOFIND task, the centering
+algorithms "gauss" and "ofilter", the FITPSF task, and the WPHOT task.
+
+By setting the \fIscale\fR and \fIfwhmpsf\fR appropriately the aperture
+sizes and radial distances may be expressed in terms of the half-width
+at half-maximum of the stellar point spread function. The way to do this
+is to define the scale parameter in units of the number of half-width at
+half-maximum per pixel, set the fwhmpsf parameter to 2.0, and then
+set the remaining scale dependent centering, sky fitting and photometry
+algorithm parameters in CENTERPARS, FITSKYPARS and PHOTPARS to
+appropriate values in units of the half-width at half-maximum of the
+point-spread function. Once an optimum set of algorithm parameters is
+chosen, the user need only alter the DATAPARS scale parameter before
+executing an APPHOT task on a new image.
+
+If \fIemission\fR is "yes", the features to be measured are assumed to be
+above sky. By default the APPHOT package considers all measurements to
+be measurements of emission features. In most cases APPHOT users should
+leave emission set to "yes".
+
+The parameter \fIsigma\fR estimates the standard deviation of the sky
+background pixels. The star finding algorithm in DAOFIND uses sigma
+and the \fIfindpars.threshold\fR parameter to define the stellar
+detection threshold in adu. The centering algorithms uses sigma,
+1) with the \fIcenterpars.kclean\fR parameter to define deviant pixels
+if \fIcenterpars.clean\fR is enabled; 2) to estimate the signal to
+noise ratio in the centering box; 3) and with the \fIcenterpars.cthreshold\fR
+parameter to define the lower intensity limit for the pixels to be used
+for centering. If sigma is undefined or <= 0.0 1) no cleaning is performed
+regardless of the value of centerpars.clean; 2) the background
+noise in the centering box is assumed to be 0; and 3) default cutoff
+intensity intensity is used for centering.
+
+The \fIdatamin\fR and \fIdatamax\fR parameters define the good data range.
+If datamin or datamax are defined bad data is removed from the sky pixel
+distribution before the sky is fit, data containing bad pixels in the
+photometry apertures is flagged, and the corresponding aperture photometry
+magnitudes are set to INDEF. APPHOT users should set datamin and datamax
+to appropriate values before running the APPHOT tasks.
+
+Two noise models are available "constant" and "poisson". If \fInoise\fR =
+constant, the total noise is assumed to be due to noise in the sky background
+alone. If \fInoise\fR = poisson, the total noise includes Poisson noise from
+the object and the sky noise.
+
+The parameters \fIgain\fR and \fIepadu\fR define the image gain.
+The gain parameter specifies which keyword in the image header contains
+the gain value. If gain is undefined or not present in the image header
+the value of epadu is used. Epadu must be in units of electrons per adu.
+APPHOT users should set either gain or epadu before running any
+APPHOT tasks to insure the magnitude error computations are correct.
+
+The two parameters \fIccdread\fR and \fIreadnoise\fR define the image
+readout noise. The ccdread parameter specifies which keyword in the
+image header contains the readout noise value. If ccdread is undefined or
+not present in the image header the value of readnoise is used.
+Readnoise is assumed to be in units of electrons.
+APPHOT users should set either ccdread or readnoise before running any
+APPHOT tasks to insure the magnitude error computations are correct.
+
+The magnitudes are normalized to an exposure time of 1 timeunit using
+the value of the exposure time in the image header parameter \fIexposure\fR
+or \fIitime\fR. If exposure is undefined or not present in the image header
+the value of itime is used. Itime can be in arbitrary units.
+Setting either exposure or itime will simplify future analysis steps.
+
+The parameters \fIairmass\fR and \fIxairmass\fR define the airmass
+of the observation. The airmass parameter specifies which keyword in the
+image header contains the airmass value. If airmass is undefined or
+not present in the image header the value of xairmass is used.
+The airmass values are not used in any APPHOT computations, however their
+presence in the APPHOT output files will simplify future reduction steps.
+
+The parameters \fIfilter\fR and \fIifilter\fR define the filter
+of the observation. The filter parameter specifies which keyword in the
+image header contains the filter id. If filter is undefined or not present
+in the image header the value of ifilter is used. The filter id values are
+not used in any APPHOT computations, however their presence in the APPHOT
+output files can will simplify future reduction steps.
+
+The parameters \fIobstime\fR and \fIotime\fR define the time
+of the observation (e.g. UT). The obstime parameter specifies which keyword
+in the image header contains the time stamp of the observation. If obstime is
+undefined or not present in the image header the value of otime is used.
+The time of observations values are not used in any APPHOT
+computations, however their presence in the APPHOT output files can
+greatly simplify future reduction steps.
+
+.ih
+EXAMPLES
+
+1. List the data dependent parameters.
+
+.nf
+ ap> lpar datapars
+.fi
+
+2. Edit the data dependent parameters.
+
+.nf
+ ap> datapars
+.fi
+
+3. Edit the DATAPARS parameters from within the PHOT task.
+
+.nf
+ da> epar phot
+
+ ... edit a few parameters
+
+ ... move to the datapars parameter and type :e
+
+ ... edit the datapars parameters and type :wq
+
+ ... finish editing the phot parameters and type :wq
+.fi
+
+4. Save the current DATAPARS parameter set in a text file datnite1.par.
+This can also be done from inside a higher level task as in the
+previous example.
+
+.nf
+ da> datapars
+
+ ... edit a few parameters
+
+ ... type ":w datnite1.par" from within epar
+.fi
+
+.ih
+TIME REQUIREMENTS
+
+.ih
+BUGS
+
+.ih
+SEE ALSO
+epar,lpar,daofind,center,fitsky,phot,wphot,polyphot,radprof,fitpsf
+.endhelp
diff --git a/noao/digiphot/apphot/doc/findpars.hlp b/noao/digiphot/apphot/doc/findpars.hlp
new file mode 100644
index 00000000..22fa7668
--- /dev/null
+++ b/noao/digiphot/apphot/doc/findpars.hlp
@@ -0,0 +1,134 @@
+.help findpars May00 noao.digiphot.apphot
+.ih
+NAME
+findpars -- edit the star detection parameters
+.ih
+USAGE
+findpars
+.ih
+PARAMETERS
+.ls threshold = 4.0 (sigma)
+The object detection threshold above local background in units of
+\fIdatapars.sigma\fR.
+.le
+.ls nsigma = 1.5
+The semi-major axis of the Gaussian convolution kernel used to computed the
+density enhancement and mean density images in Gaussian sigma. This semi-
+major axis is equal to min (2.0, 0.42466 * \fInsigma\fR *
+\fIdatapars.fwhmpsf\fR / \fIdatapars.scale\fR) pixels.
+.le
+.ls ratio = 1.0
+The ratio of the sigma of the Gaussian convolution kernel along the minor axis
+direction to the sigma along the major axis direction. \fIRatio\fR defaults
+to 1.0 in which case the image is convolved with a circular Gaussian.
+.le
+.ls theta = 0.0
+The position angle of the major axis of the Gaussian convolution kernel.
+\fITheta\fR is measured in degrees counter-clockwise from the x axis.
+.le
+.ls sharplo = .2, sharphi = 1.0
+\fISharplo\fR and \fIsharphi\fR are numerical cutoffs on the image sharpness
+statistic designed to eliminate brightness maxima which are due to bad pixels
+rather than to astronomical objects.
+.le
+.ls roundlo = -1.0 roundhi = 1.0
+\fIRoundlo\fR and \fIroundhi\fR are numerical cutoffs on the image roundness
+statistic designed to eliminate brightness maxima which are due to bad rows or
+columns, rather than to astronomical objects.
+.le
+.ls mkdetections = no
+Mark the positions of the detected objects on the displayed image ?
+.le
+
+.ih
+DESCRIPTION
+
+DAOFIND approximates the stellar point spread function with an elliptical
+Gaussian function, whose sigma along the semi-major axis is 0.42466 *
+\fIdatapars.fwhmpsf\fR / \fIdatapars.scale\fR pixels, semi-minor to semi-major
+axis ratio is \fIratio\fR, and major axis position angle is \fItheta\fR.
+Using this model, a convolution kernel, truncated at \fInsigma\fR sigma,
+and normalized to sum to zero, is constructed.
+
+The density enhancement image \fIstarmap\fR is computed by convolving the input
+image with the Gaussian kernel. This operation is mathematically equivalent to
+fitting, in the least-squares sense, the image data at each point with a
+truncated, lowered elliptical Gaussian function. After convolution each point
+in \fIstarmap\fR contains as estimate of the amplitude of the best fitting
+Gaussian function at that point. Each point in \fIskymap\fR, if the user
+chooses to compute it, contains an estimate of the best fitting sky value
+at that point.
+
+After image convolution DAOFIND steps through \fIstarmap\fR searching
+for density enhancements greater than \fIfindpars.threshold\fR *
+\fIdatapars.sigma\fR, and brighter than all other density enhancements
+within a semi-major axis of 0.42466 \fIfindpars.nsigma\fR *
+\fIdatapars.fwhmpsf\fR. As the program selects candidates, it computes two
+shape characteristics sharpness and roundness. The sharpness statistic
+measures the ratio of the difference between the height of the central pixel
+and the mean of the surrounding non-bad pixels, to the height of the best
+fitting Gaussian function at that point. The roundness statistics measures
+the ratio of, the difference in the height of the best fitting Gaussian
+function in x minus the best fitting Gaussian function in y, over the average
+of the best fitting Gaussian functions in x and y. The limits on these
+parameters \fIfindpars.sharplo\fR, \fIfindpars.sharphi\fR,
+\fIfindpars.roundlo\fR, and \fIfindpars.roundhi\fR, are set to weed out
+non-astronomical objects and brightness enhancements that are elongated in
+x and y respectively.
+
+Lastly the x and y centroids of the detected objects are computed by
+estimating the x and y positions of the best fitting 1D Gaussian
+functions in x and y respectively, a rough magnitude is estimated
+by computing the ratio of the amplitude of the best fitting Gaussian at
+the object position to \fIfindpars.threshold\fR * \fIdatapars.sigma\fR,
+and the object is added to the output coordinate file.
+
+
+.ih
+EXAMPLES
+
+1. List the object detection parameters.
+
+.nf
+ da> lpar findpars
+.fi
+
+2. Edit the object detection parameters.
+
+.nf
+ da> findpars
+.fi
+
+3. Edit the FINDPARS parameters from within the DAOFIND task.
+
+.nf
+ da> epar daofind
+
+ ... edit a few daofind parameters
+
+ ... move to the findpars parameter and type :e
+
+ ... edit the findpars parameter and type :wq
+
+ ... finish editing the daofind parameters and type :wq
+.fi
+
+4. Save the current FINDPARS parameter set in a text file fndnite1.par.
+This can also be done from inside a higher level task as in the previous
+example.
+
+.nf
+ da> findpars
+
+ ... edit the parameters
+
+ ... type ":w fndnite1.par" from within epar
+.fi
+
+.ih
+BUGS
+
+.ih
+SEE ALSO
+daofind, datapars
+.endhelp
diff --git a/noao/digiphot/apphot/doc/fitpsf.hlp b/noao/digiphot/apphot/doc/fitpsf.hlp
new file mode 100644
index 00000000..8a229508
--- /dev/null
+++ b/noao/digiphot/apphot/doc/fitpsf.hlp
@@ -0,0 +1,680 @@
+.help fitpsf May00 noao.digiphot.apphot
+.ih
+NAME
+fitpsf -- model the point spread function with an analytic function
+.ih
+USAGE
+fitpsf image box
+.ih
+PARAMETERS
+.ls image
+The list of images containing the objects to be measured.
+.le
+.ls box
+The width of the fitting box in scale units.
+.le
+.ls coords = ""
+The list of text files containing initial coordinates for the objects to
+be centered. Objects are listed in coords one object per line with the
+initial coordinate values in columns one and two. The number of coordinate
+files must be zero, one, or equal to the number of images.
+If coords is "default", "dir$default", or a directory specification then an
+coords file name of the form dir$root.extension.version is constructed and
+searched for, where dir is the directory, root is the root image name,
+extension is "coo" and version is the next available version number for the
+file.
+.le
+.ls output = "default"
+The name of the results file or results directory. If output is
+"default", "dir$default", or a directory specification then an output file name
+of the form dir$root.extension.version is constructed, where dir is the
+directory, root is the root image name, extension is "psf" and version is
+the next available version number for the file. The number of output files
+must be zero, one, or equal to the number of image files. In both interactive
+and batch mode full output is written to output. In interactive mode
+an output summary is also written to the standard output.
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters.
+The critical parameters \fIfwhmpsf\fR and \fIsigma\fR are located in
+datapars. If datapars is undefined then the default parameter set in
+uparm directory is used.
+.le
+.ls function = "radgauss"
+The function to be fit. The options are:
+.ls radgauss
+A 2D radial Gaussian function is fit. The parameters of the fitting function
+are: x and y center, sigma of the Gaussian, amplitude of the Gaussian and
+the local sky value.
+.le
+.ls elgauss
+A 2D elliptical Gaussian function is fit. The parameters of the fitting
+function are: x and y center, x and y sigma of the Gaussian, amplitude of
+the Gaussian and the local sky value.
+.le
+.ls moments
+The 0th, 1st and 2nd order moments are computed and used to derive
+estimates of the
+x and y center values, radius of gyration, ellipticity and position
+angle of the object.
+.le
+.le
+.ls maxiter = 50
+The maximum number of iterations that the non-linear fitting routines will
+perform in an attempt to find a satisfactory fit.
+.le
+.ls nreject = 0
+The maximum number of rejection cycles performed after the fit.
+The default is no rejection.
+.le
+.ls kreject = 3.0
+The k-sigma rejection limit in units of sigma.
+.le
+.ls mkbox = no
+Draw the fitting box on the image display?
+.le
+.ls interactive = yes
+Run the task interactively ?
+.le
+.ls icommands = ""
+The image cursor or image cursor command file.
+.le
+.ls gcommands = ""
+The graphics cursor or graphics cursor command file.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout"
+The coordinate system of the input coordinates read from \fIcoords\fR and
+of the output coordinates written to \fIoutput\fR respectively. The image
+header coordinate system is used to transform from the input coordinate
+system to the "logical" pixel coordinate system used internally,
+and from the internal "logical" pixel coordinate system to the output
+coordinate system. The input coordinate system options are "logical", tv",
+"physical", and "world". The output coordinate system options are "logical",
+"tv", and "physical". The image cursor coordinate system is assumed to
+be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin and wcsout are "logical" and "logical" respectively.
+.le
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default cacheing is
+disabled.
+.le
+.ls verify = ")_.verify"
+Verify the critical parameters in non-interactive mode ? Verify may be set to
+the apphot package parameter value (the default), "yes", or "no.
+.le
+.ls update = ")_.update"
+Update the critical parameters in non-interactive mode if verify is set of
+"yes" ? Update may be set to the apphot package parameter value (the default),
+"yes", or "no.
+
+.le
+.ls verbose = ")_.verbose"
+Print messages on the terminal in non-interactive mode ? Verbose may be set
+to the apphot package parameter value (the default), "yes", or "no.
+
+.le
+.ls graphics = ")_.graphics"
+The default graphics device. Graphics may be set to the apphot package
+parameter value (the default), "yes", or "no.
+.le
+.ls display = ")_.display"
+The default display device. Display may be set to the apphot package
+parameter value (the default), "yes", or "no. By default graphics overlay
+is disabled. Setting display to one of "imdr", "imdg", "imdb", or "imdy"
+enables graphics overlay with the IMD graphics kernel. Setting display to
+"stdgraph" enables FITPSF to work interactively from a contour plot.
+.le
+
+.ih
+DESCRIPTION
+
+FITPSF models the stellar brightness distribution of objects in the IRAF image
+\fIimage\fR using non-linear least squares techniques and writes the
+list of model parameters and associated errors to the file \fIoutput\fR.
+Initial coordinates for the objects are read from the image cursor or
+the text file \fIcoords\fR. Pixels in a subraster of width \fIbox * scale\fR
+are extracted and used in the fit.
+
+The coordinates read from \fIcoords\fR are assumed to be in coordinate
+system defined by \fIwcsin\fR. The options are "logical", "tv", "physical",
+and "world" and the transformation from the input coordinate system to
+the internal "logical" system is defined by the image coordinate system.
+The simplest default is the "logical" pixel system. Users working on with
+image sections but importing pixel coordinate lists generated from the parent
+image must use the "tv" or "physical" input coordinate systems.
+Users importing coordinate lists in world coordinates, e.g. ra and dec,
+must use the "world" coordinate system and may need to convert their
+equatorial coordinate units from hours and degrees to degrees and degrees first.
+
+The coordinates written to \fIoutput\fR are in the coordinate
+system defined by \fIwcsout\fR. The options are "logical", "tv",
+and "physical". The simplest default is the "logical" system. Users
+wishing to correlate the output coordinates of objects measured in
+image sections or mosaic pieces with coordinates in the parent
+image must use the "tv" or "physical" coordinate systems.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If cacheing
+is enabled and FITPSF is run interactively the first measurement will appear
+to take a long time as the entire image must be read in before the measurement
+is actually made. All subsequent measurements will be very fast because FITPSF
+is accessing memory not disk. The point of cacheing is to speed up random
+image access by making the internal image i/o buffers the same size as the
+image itself. However if the input object lists are sorted in row order and
+sparse cacheing may actually worsen not improve the execution time. Also at
+present there is no point in enabling cacheing for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of cacheing in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halfs of the image are alternated.
+
+FITPSF can be run either interactively or in batch mode by setting the
+parameter \fIinteractive\fR. In interactive mode starting x and y positions
+can either be read directly from the image cursor or read from the text
+file specified by \fIcoords\fR. In batch mode the estimated
+positions can be read from the text file \fIcoords\fR or the image cursor
+parameter \fIicommands\fR can be redirected to a text file containing
+a list of cursor commands.
+
+.ih
+CURSOR COMMANDS
+
+The currently available cursor commands are listed below.
+
+.nf
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+v Verify the critical parameters
+w Save the current parameters
+d Plot radial profile of current star
+i Interactively set parameters using current star
+f Fit current star
+spbar Fit current star, output results
+m Move to next star in coordinate list
+n Fit next star in coordinate list, output results
+l Fit remaining stars in coordinate list, output results
+e Print error messages
+r Rewind the coordinate list
+q Exit task
+
+
+
+ Colon Commands
+
+:show [data/fit] List the parameters
+:m [n] Move to next [nth] star in coordinate list
+:n [n] Fit next [nth] star in coordinate list, output results
+
+
+ Colon Parameter Editing Commands
+
+# Image and file name parameters
+
+:image [string] Image name
+:coords [string] Coordinate file name
+:output [string] Output file name
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Scale factor (scale units)
+:emission [y/n] Emission feature (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good data value (counts)
+:datamax [value] Maximum good data value (counts)
+
+# Noise description parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per adu)
+:readnoise [value] Readnoise (electrons)
+
+# Observation parameters
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Exposure time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observation (time units)
+
+# Fitting parameters
+
+:function [string] PSF model (radgauss|elgauss|moments)
+:box [value] Width of the fitting box (scale units)
+:maxiter [value] Maximum number of iterations
+:nreject [value] Maximum number of rejection cycles
+:kreject [value] Rejection limit (sigma)
+
+# Plotting and marking functions
+
+:mkbox [y/n] Mark the fitting box on the display
+
+
+The following command are available from within the interactive setup menu.
+
+
+ Interactive Fitpsf Setup Menu
+
+ v Mark and verify the critical fitpsf parameters (f,s,b)
+
+ f Mark and verify the full-width half-maximum of the psf
+ s Mark and verify the standard deviation of the background
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
+
+ b Mark and verify the half-width of the fitting box
+.fi
+
+.ih
+ALGORITHMS
+
+The fitting parameters are \fIfunction\fR, the functional form of the model
+to be fit, \fImaxiter\fR, the maximum number of iterations per fit,
+\fIkreject\fR, the K-sigma rejection limit and \fInreject\fR, the maximum
+number of rejection cycles. The currently available functions are a 2D
+moments analysis "moments", a 2D radial Gaussian "radgauss", and a
+2D elliptical Gaussian "elgauss".
+
+The weighting of the fit is determined by the parameter \fInoise\fR in the
+\fIdatapars\fR file. The two options are \fIconstant\fR, in which all the
+weights are set to 1 and \fIpoisson\fR in which the weights are equal to
+the inverse of the counts divided by the image gain read from the datapars
+\fIgain\fR or \fIepadu\fR parameters plus the square of the readout noise
+determined from the datapars parameters \fIccdread\fR or \fIreadnoise\fR.
+If \fIfunction\fR is either "radgauss" or "ellgauss" then the datapars
+parameter \fIfwhmpsf\fR is used to determine the initial guess for the
+Gaussian sigma. The datapars parameter \fIthreshold\fR determines the
+intensity threshold above which the moment analysis is performed.
+
+.ih
+OUTPUT
+
+In interactive mode the following quantities are printed on the
+terminal as shown below, for the radial Gaussian, elliptical Gaussian and
+moments functions respectively.
+
+.nf
+ image xcenter ycenter rsigma amplitude sky err
+
+ image xcenter ycenter xsigma ysigma rot amplitude sky err
+
+ image xcenter ycenter rgyrat ellip pa amplitude sky err
+
+.fi
+
+In both interactive and batch mode the full output is written to the
+text file \fIoutput\fR. At the beginning of each file is a header
+listing the values of the parameters when the first stellar
+record was written. These parameters can be subsequently altered.
+For each star measured the following record is written for the radial
+Gaussian, elliptical Gaussian, and moments functions respectively.
+
+.nf
+ image xinit yinit id coords lid
+ xcenter ycenter rsigma amplitude sky
+ excenter eycenter ersigma eamplitude esky ier error
+
+ image xinit yinit id coords lid
+ xcenter ycenter xsigma ysigma rot amplitude sky
+ excenter eycenter exsigma eysigma erot eamplitude esky ier\
+ error
+
+ image xinit yinit id coords lid
+ xcenter ycenter rgyrat ellip pa amplitude sky
+ excenter eycenter ergyrat eellip epa eamplitude esky ier\
+ error
+.fi
+
+Image and coords are the name of the image and coordinate files respectively.
+Id and lid are the sequence numbers of stars in the output and coordinate
+files respectively and xinit and yinit are the initial positions.
+Xcenter and ycenter are the computed x and y
+positions of the object. Rsigma, xsigma and ysigma are the distance from
+the center of the Gaussian at which the Gaussian is equal to exp (-0.5)
+of its central value. Xsigma and ysigma refer to those values along the major
+and minor axes of the ellipse respectively. The amplitude and sky refer to
+the amplitude of
+the Gaussian function and a constant background value respectively.
+If function = "moments" amplitude and sky refer to the total intensity
+above threshold and sky is the threshold value. Rot and pa are position angles
+of the major axis measured counter-clockwise with respect to the x axis.
+Rgyrat is the radius
+of gyration of the object and ellip its ellipticity.
+Quantities prefixed by an e represent the errors in the corresponding
+fitted parameters.
+
+.ih
+ERRORS
+
+If all went well in the fitting process the error code stored in the ier
+field described above is 0. Non-zero values of ier flag the following error
+conditions.
+
+.nf
+ 0 # No error
+ 401 # The fitting box is off the image
+ 402 # The fitting box is partially off the image
+ 403 # There are too few points to fit the function
+ 404 # The fit is singular
+ 405 # The fit did not converge
+.fi
+
+.ih
+EXAMPLES
+
+1. Compute the radial Gaussian function parameters for a few stars in dev$ypix
+using the display and the image cursor. Setup the task parameters using
+the interactive setup menu defined by the i key command. Use uniform
+weighting.
+
+.nf
+ ap> display dev$ypix 1 fi+
+
+ ... display the image
+
+ ap> fitpsf dev$ypix 11 noise=constant
+
+ ... type ? to see the help screen
+
+ ... move the image cursor to a star
+ ... type i to enter the interactive setup menu
+ ... enter maximum radius in pixels of the radial profile or type
+ CR to accept the default value
+ ... set the fitting box width, fwhmpsf, and sigma using the graphics
+ cursor and the stellar radial profile plot
+ ... typing <CR> leaves everything at the default value
+ ... type q to quit the setup menu
+
+ ... type the v key to verify the parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... move the image cursor to the stars of interest and tap
+ the space bar
+
+ ... a one line summary of the fitted parameters will appear on the
+ standard output for each star measured
+
+ ... type q to quit and another q to confirm the quit
+
+ ... the full output will appear in ypix.psf.1
+.fi
+
+2. Compute the radial Gaussian function parameters for a few stars in
+dev$ypix using the contour plot and the graphics cursor. Setup the task
+parameters using the interactive setup menu defined by the i key command.
+Use uniform weighting.
+
+.nf
+ ap> show stdimcur
+
+ ... save the current value of stdimcur
+
+ ap> set stdimcur = stdgraph
+
+ ... define the image cursor to be the graphics cursor
+
+ ap> contour dev$ypix >G ypix.plot1
+
+ ... store the contour plot of dev$ypix in the file ypix.plot1
+
+ ap> fitpsf dev$ypix 11.0 noise=constant display=stdgraph
+
+ ... type ? to get a short help page on the screen
+
+ ... move the graphics cursor to a star
+ ... type i to enter the interactive setup menu
+ ... enter the maximum radius in pixels of the radial profile or
+ type CR to accept the default value
+ ... set the fitting box width, fwhmpsf, and sigma using the graphics
+ cursor and the stellar radial profile plot
+ ... typing <CR> leaves everything at the default value
+ ... type q to quit the setup menu
+
+ ... type the v key to verify critical parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... retype :.read ypix.plot1 to reload the contour plot
+
+ ... move the graphics cursor to the stars of interest and tap
+ the space bar
+
+ ... a one line summary of the fitted parameters will appear on the
+ standard output for each star measured
+
+ ... type q to quit and q again to confirm the quit
+
+ ... full output will appear in the text file ypix.psf.2
+.fi
+
+
+3. Setup and run FITPSF interactively on a list of objects temporarily
+overriding the fwhmpsf and sigma parameters determined in examples 1 or 2.
+Use uniform weighting.
+
+.nf
+ ap> daofind dev$ypix fwhmpsf=2.6 sigma=25.0 verify-
+
+ ... make a coordinate list
+
+ ... the output will appear in the text file ypix.coo.1
+
+ ap> fitpsf dev$ypix 11.0 fwhmpsf=2.6 noise=constant coords=ypix.coo.1
+
+ ... type ? for optional help
+
+
+ ... move the graphics cursor to the stars and tap space bar
+
+ or
+
+ ... select stars from the input coordinate list with m / :m #
+ and measure with spbar
+
+ ... measure stars selected from the input coordinate list
+ with n / n #
+
+ ... a one line summary of results will appear on the standard output
+ for each star measured
+
+ ... type q to quit and q again to confirm the quit
+
+ ... the output will appear in ypix.psf.3 ...
+.fi
+
+
+4. Display and fit some stars in an image section and write the output
+coordinates in the coordinate system of the parent image. Use uniform
+weighting.
+
+.nf
+ ap> display dev$ypix[150:450,150:450] 1
+
+ ... display the image section
+
+ ap> fitpsf dev$ypix[150:450,150:450] 11.0 noise=constant wcsout=tv
+
+ ... move cursor to stars and type spbar
+
+ ... type q to quit and q again to confirm quit
+
+ ... output will appear in ypix.psf.4
+
+ ap> pdump ypix.psf.4 xc,yc yes | tvmark 1 STDIN col=204
+.fi
+
+
+5. Run FITPSF in batch mode using the coordinate file and the previously
+saved parameters. Use uniform weighting. Verify the critical parameters.
+
+.nf
+ ap> fitpsf dev$ypix 11.0 coords=ypix.coo.1 noise=constant verify+ \
+ inter-
+
+ ... output will appear in ypix.psf.5 ...
+.fi
+
+6. Repeat example 5 but assume that the input coordinate are ra and dec
+in degrees and degrees, turn off verification, and submit the task to to
+the background. Use uniform weighting.
+
+.nf
+ ap> display dev$ypix 1
+
+ ap> rimcursor wcs=world > radec.coo
+
+ ... move to selected stars and type any key
+
+ ... type ^Z to quit
+
+ ap> fitpsf dev$ypix 11.0 coords=radec.coo noise=constant \
+ wcsin=world verify- inter- &
+
+ ... output will appear in ypix.psf.6
+
+ ap> pdump ypix.psf.6 xc,yc yes | tvmark 1 STDIN col=204
+
+ ... mark the stars on the display
+.fi
+
+7. Run FITPSF interactively without using the image display.
+
+.nf
+ ap> show stdimcur
+
+ ... record the default value of stdimcur
+
+ ap> set stdimcur = text
+
+ ... set the image cursor to the standard input
+
+ ap> fitpsf dev$ypix 11.0 coords=ypix.coo.1 noise=constant
+
+ ... type ? for optional help
+
+ ... type :m 3 to set the initial coordinates to those of the
+ third star in the list
+
+ ... type i to enter the interactive setup menu
+ ... enter the maximum radius in pixels for the radial profile or
+ accept the default with a CR
+ ... type v to enter the default menu
+ ... set the fwhmpsf, sigma, and fitting box size using the
+ graphics cursor and the stellar radial profile plot
+ ... typing <CR> after the prompt leaves the parameter at its default
+ value
+ ... type q to quit the setup menu
+
+ ... type r to rewind the coordinate list
+
+ ... type l to measure all the stars in the coordinate list
+
+ ... a one line summary of the answers will appear on the standard
+ output for each star measured
+
+ ... type q to quit followed by q to confirm the quit
+
+ ... full output will appear in the text file ypix.psf.7
+
+ ap> set stdimcur = <default>
+
+ ... reset the value of stdimcur
+.fi
+
+8. Use an image cursor command file to drive the FITPSF task. The cursor command
+file shown below sets the fwhmpsf, sigma, and noise, computes the model
+fit parameter values for 3 stars, updates the parameter files, and quits
+the task.
+
+.nf
+ ap> type cmdfile
+ : fwhmpsf 2.6
+ : sigma 5.0
+ : noise constant
+ 442 410 101 \040
+ 349 188 101 \040
+ 225 131 101 \040
+ w
+ q
+
+ ap> fitpsf dev$ypix 11.0 icommands=cmdfile verify-
+
+ ... full output will appear in ypix.psf.8
+.fi
+
+
+.ih
+BUGS
+
+In interactive mode the user should not change the type function to be fit
+after the first record is written to the output file. In this case the file
+header and record structure will not match.
+
+It is currently the responsibility of the user to make sure that the
+image displayed in the frame is the same as that specified by the image
+parameter.
+
+Commands which draw to the image display are disabled by default.
+To enable graphics overlay on the image display, set the display
+parameter to "imdr", "imdg", "imdb", or "imdy" to get red, green,
+blue or yellow overlays and set the mkbox switch to"yes".
+It may be necessary to run gflush and to redisplay the image
+to get the overlays position correctly.
+
+.ih
+SEE ALSO
+
+datapars, radprof
+.endhelp
diff --git a/noao/digiphot/apphot/doc/fitsky.hlp b/noao/digiphot/apphot/doc/fitsky.hlp
new file mode 100644
index 00000000..5fc07de9
--- /dev/null
+++ b/noao/digiphot/apphot/doc/fitsky.hlp
@@ -0,0 +1,632 @@
+.help fitsky Dec92 noao.digiphot.apphot
+.ih
+NAME
+fitsky - determine the mode, sigma and skew of the sky pixels
+.ih
+USAGE
+fitsky image
+.ih
+PARAMETERS
+.ls image
+The list of images containing the sky regions to be fit.
+.le
+.ls coords = ""
+The list of text files containing initial coordinates for the objects to
+be centered. Objects are listed in coords one object per line with the
+initial coordinate values in columns one and two. The number of coordinate
+files must be zero, one, or equal to the number of images.
+If coords is "default", "dir$default", or a directory specification then an
+coords file name of the form dir$root.extension.version is constructed and
+searched for, where dir is the directory, root is the root image name,
+extension is "coo" and version is the next available version number for the
+file.
+.le
+.ls output = "default"
+The name of the results file or results directory. If output is
+"default", "dir$default", or a directory specification then an output file name
+of the form dir$root.extension.version is constructed, where dir is the
+directory, root is the root image name, extension is "sky" and version is
+the next available version number for the file. The number of output files
+must be zero, one, or equal to the number of image files. In both interactive
+and batch mode full output is written to output. In interactive mode
+an output summary is also written to the standard output.
+.le
+.ls plotfile = ""
+The name of the file containing radial profile plots of the stars written
+to the output file. If plotfile is defined then a radial profile plot
+is written to plotfile every time a record is written to \fIoutput\fR.
+The user should be aware that this can be a time consuming operation.
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters.
+The critical parameters \fIfwhmpsf\fR and \fIsigma\fR are located in
+datapars. If datapars is undefined then the default parameter set in
+uparm directory is used.
+.le
+.ls fitskypars = ""
+The name of the text file containing the sky fitting parameters. The critical
+parameters \fIsalgorithm\fR, \fIannulus\fR, and \fIdannulus\fR are located here.
+If \fIfitskypars\fR is undefined then the default parameter set in uparm
+directory is used.
+.le
+.ls interactive = yes
+Run the task interactively ?
+.le
+.ls radplots = no
+If \fIradplots\fR is "yes" and PHOT is run in interactive mode, a radial
+profile of each star is plotted on the screen after the star is measured.
+.le
+.ls icommands = ""
+The image display cursor or image cursor command file.
+.le
+.ls gcommands = ""
+The graphics cursor or graphics cursor command file.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout"
+The coordinate system of the input coordinates read from \fIcoords\fR and
+of the output coordinates written to \fIoutput\fR respectively. The image
+header coordinate system is used to transform from the input coordinate
+system to the "logical" pixel coordinate system used internally,
+and from the internal "logical" pixel coordinate system to the output
+coordinate system. The input coordinate system options are "logical", tv",
+"physical", and "world". The output coordinate system options are "logical",
+"tv", and "physical". The image cursor coordinate system is assumed to
+be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin and wcsout are "logical" and "logical" respectively.
+.le
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default cacheing is
+disabled.
+.le
+.ls verify = ")._verify"
+Verify the critical parameters in non-interactive mode ? Verify may be set to
+ the apphot package parameter value (the default), "yes", or "no.
+.le
+.ls update = ")_.update"
+Update the critical parameters in non-interactive mode if verify is yes ?
+Update may be set to the apphot package parameter value (the default), "yes",
+or "no.
+
+.le
+.ls verbose = ")_.verbose"
+Print messages on the terminal in non-interactive mode ? Verbose may be set to
+the apphot package parameter value (the default), "yes", or "no.
+
+.le
+.ls graphics = ")_.graphics"
+The default graphics device. Graphics may be set to the apphot package
+parameter value (the default), "yes", or "no.
+.le
+.ls display = ")_.display"
+The default display device. Display may be set to the apphot package parameter
+value (the default), "yes", or "no. By default graphics overlay is disabled.
+Setting display to one of "imdr", "imdg", "imdb", or "imdy" enables graphics
+overlay with the IMD graphics kernel. Setting display to "stdgraph" enables
+FITSKY to work interactively from a contour plot.
+.le
+
+.ih
+DESCRIPTION
+FITSKY computes accurate sky values for a set of objects in the IRAF image
+\fIimage\fR, whose coordinates are read from the text file \fIcoords\fR or
+the image display cursor, and writes the computed sky values to the text
+file \fIoutput\fR.
+
+The coordinates read from \fIcoords\fR are assumed to be in coordinate
+system defined by \fIwcsin\fR. The options are "logical", "tv", "physical",
+and "world" and the transformation from the input coordinate system to
+the internal "logical" system is defined by the image coordinate system.
+The simplest default is the "logical" pixel system. Users working on with
+image sections but importing pixel coordinate lists generated from the parent
+image must use the "tv" or "physical" input coordinate systems.
+Users importing coordinate lists in world coordinates, e.g. ra and dec,
+must use the "world" coordinate system and may need to convert their
+equatorial coordinate units from hours and degrees to degrees and degrees first.
+
+The coordinates written to \fIoutput\fR are in the coordinate
+system defined by \fIwcsout\fR. The options are "logical", "tv",
+and "physical". The simplest default is the "logical" system. Users
+wishing to correlate the output coordinates of objects measured in
+image sections or mosaic pieces with coordinates in the parent
+image must use the "tv" or "physical" coordinate systems.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If cacheing
+is enabled and FITSKY is run interactively the first measurement will appear
+to take a long time as the entire image must be read in before the measurement
+is actually made. All subsequent measurements will be very fast because FITSKY
+is accessing memory not disk. The point of cacheing is to speed up random
+image access by making the internal image i/o buffers the same size as the
+image itself. However if the input object lists are sorted in row order and
+sparse cacheing may actually worsen not improve the execution time. Also at
+present there is no point in enabling cacheing for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of cacheing in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halfs of the image are alternated.
+
+FITSKY can be run either interactively or in batch mode by setting the parameter
+\fIinteractive\fR. In interactive mode the user may either define the
+list of objects to be measured interactively with the image cursor or
+create an object list prior to running FITSKY. In either case the user may
+adjust the sky fitting parameters until a satisfactory measurement is achieved.
+coordinate list with that set of parameters. In batch mode
+positions are read from the text file \fIcoords\fR or the image cursor
+parameter \fIicommands\fR can be redirected to a cursor command file.
+
+.ih
+CURSOR COMMANDS
+
+The following cursor commands are currently available.
+
+.nf
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+v Verify the critical parameters
+w Save the current parameters
+d Plot radial profile of current star
+i Interactively set parameters using current star
+f Fit sky for current star
+spbar Fit sky for current star, output results
+m Move to next star in coordinate list
+m Fit sky for next star in coordinate list, output results
+l Fit sky for remaining stars in coordinate list, output results
+e Print error messages
+r Rewind the coordinate list
+q Exit task
+
+
+ Colon commands
+
+:show [data/sky] List the parameters
+:m [n] Move to the next [nth] star in coordinate list
+:n [n] Fit sky to next [nth] star in coordinate list, output results
+
+ Colon Parameter Editing Commands
+
+# Image and file name parameters
+
+:image [string] Image name
+:coords [string] Coordinate file name
+:output [string] Output file name
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Full width half maximum PSF (scale units)
+:emission [y/n] Emission feature (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good pixel value (counts)
+:datamax [value] Maximum good pixel value (counts)
+
+# Noise parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per adu)
+:readnoise [value] Readout noise (electrons)
+
+# Observations parameters
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Exposure time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observation (time units)
+
+# Sky fitting algorithm parameters
+
+:salgorithm [string] Sky fitting algorithm
+:skyvalue [value] User supplied sky value (counts)
+:annulus [value] Inner radius of sky annulus (scale units)
+:dannulus [value] Width of sky annulus (scale units)
+:khist [value] Sky histogram extent (+/- sky sigma)
+:smooth [y/n] Lucy smooth the sky histogram
+:binsize [value] Resolution of sky histogram (sky sigma)
+:smaxiter [value] Maximum number of iterations
+:sloclip [value] Low side clipping factor (percent)
+:shiclip [value] High side clipping factor (percent)
+:snreject [value] Maximum number of rejection cycles
+:sloreject [value] Low side pixel rejection limits (sky sigma)
+:shireject [value] High side pixel rejection limits (sky sigma)
+:rgrow [value] Region growing radius (scale units)
+
+# Marking and plotting parameters
+
+:mksky [y/n] Mark sky annuli on the display
+:radplot [y/n] Plot radial profile of sky pixels
+
+
+The following commands are available from within the interactive setup menu.
+
+
+ Interactive Fitsky Setup Menu
+
+ v Mark and verify the critical parameters (a,d,s)
+
+ s Mark and verify the standard deviation of the sky
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
+
+ a Mark and verify the inner radius of the sky annulus
+ d Mark and verify the width of the sky annulus
+ g Mark and verify the region growing radius
+.fi
+
+.ih
+ALGORITHMS
+A brief description of the data dependent parameters and the sky fitting
+parameters can be found in the online manual pages for the DATAPARS
+and FITSKYPARS tasks.
+
+.ih
+OUTPUT
+In interactive mode the following quantities are printed on the standard
+output as each object is measured.
+
+.nf
+ image xinit yinit msky stdev sskew nsky nsrej error
+.fi
+
+In both interactive and batch mode full output is written to the
+text file \fIoutput\fR. At the beginning of each file is a header listing
+the current values of the parameters when the first stellar record was
+written. These parameters can be subsequently altered. For each star
+measured the following record is written.
+
+.nf
+ image xinit yinit id coords lid
+ msky stdev sskew nsky nsrej sier error
+.fi
+
+Image and coords are the name of the image and coordinate file respectively.
+Id and lid are the sequence numbers of stars in the output and coordinate
+files respectively. Sier and error are the error code and accompanying
+error message respectively. Xinit and yinit are the center coordinates
+of the sky annulus in pixels. Msky, stdev and sskew are the sky value,
+standard deviation and skew respectively. Nsky and nsrej are the number of
+sky pixels used and the number of sky pixels rejected respectively.
+
+In interactive mode a radial profile of each measured object is plotted
+in the graphics window if \fIradplots\fR is "yes".
+
+In interactive and batch mode a radial profile plot is written to
+\fIplotfile\fR if it is defined each time the result of an object
+measurement is written to \fIoutput\fR .
+
+.ih
+ERRORS
+If all goes well during the sky fitting process then the error code sier
+will be 0. Non-zero values of sier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 201 # There are no sky pixels in the sky annulus
+ 202 # Sky annulus is partially off the image
+ 203 # The histogram of sky pixels has no width
+ 204 # The histogram of sky pixels is flat or concave
+ 205 # There are too few points for a good sky fit
+ 206 # The sky fit is singular
+ 207 # The sky fit did not converge
+ 208 # The graphics stream is undefined
+ 209 # The file of sky values does not exist
+ 210 # The sky file is at EOF
+ 211 # Cannot read the sky value correctly
+ 212 # The best fit parameters are non-physical
+.fi
+
+.ih
+EXAMPLES
+
+1. Compute the sky values for a few stars in dev$ypix using the display
+and the image cursor. Setup the task parameters using the interactive
+setup menu defined by the i key command and a radial profile plot.
+
+.nf
+ ap> display dev$ypix 1 fi+
+
+ ... display the image
+
+ ap> fitsky dev$ypix
+
+ ... type ? to print an optional help page
+
+ ... move the image cursor to a star
+ ... type i to enter the interactive setup menu
+ ... enter maximum radius in pixels of the radial profile or hit
+ CR to accept the default
+ ... set the inner and outer sky annuli, and sigma using the
+ graphics cursor and the stellar radial profile plot
+ ... typing <CR> leaves everything at the default value
+ ... type q to quit the setup menu
+
+ ... type the v key to verify the parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... move the image cursor to the stars of interest and tap
+ the space bar
+
+ ... a one line summary of the fitted parameters will appear on the
+ standard output for each star measured
+
+ ... type q to quit and q again to confirm the quit
+
+ ... the output will appear in ypix.sky.1
+.fi
+
+2. Compute the sky values for a few stars in dev$ypix using a contour plot
+and the graphics cursor. This option is only useful for those (now very few)
+users who have access to a graphics terminal but not to an image display
+server. Setup the task parameters using the interactive setup menu defined by
+the i key command as in example 1.
+
+.nf
+ ap> show stdimcur
+
+ ... record the default value of stdimcur
+
+ ap> set stdimcur = stdgraph
+
+ ... define the image cursor to be the graphics cursor
+
+ ap> contour dev$ypix
+
+ ... make a contour plot of dev$ypix
+
+ ap> contour dev$ypix >G ypix.plot1
+
+ ... store the contour plot of dev$ypix in the file ypix.plot1
+
+ ap> fitsky dev$ypix display=stdgraph
+
+ ... type ? to get an optional help page
+
+ ... move graphics cursor to a star
+ ... type i to enter the interactive setup menu
+ ... enter maximum radius in pixels of the radial profile or CR
+ to accept the default value
+ ... set the inner and outer sky annuli, and sigma using the
+ graphics cursor and the stellar radial profile plot
+ ... typing <CR> leaves everything at the default value
+ ... type q to quit the setup menu
+
+ ... type the v key to verify the critical parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... retype :.read ypix.plot1 to reload the contour plot
+
+ ... move the graphics cursor to the stars of interest and tap
+ the space bar
+
+ ... a one line summary of the fitted parameters will appear on the
+ standard output for each star measured
+
+ ... type q to quit and q again to verify
+
+ ... full output will appear in the text file ypix.sky.2
+
+ ap> set stdimcur = <default>
+
+ ... reset stdimcur to its previous value
+.fi
+
+3. Setup and run FITSKY interactively on a list of objects temporarily
+overriding the fwhmpsf, sigma, annulus, and dannulus parameters determined
+in examples 1 or 2.
+
+.nf
+ ap> daofind dev$ypix fwhmpsf=2.6 sigma=25.0 verify-
+
+ ... make a coordinate list
+
+ ... the output will appear in the text file ypix.coo.1
+
+ ap> fitsky dev$ypix annulus=12.0 dannulus=5.0 coords=ypix.coo.1
+
+ ... type ? for optional help
+
+
+ ... move the graphics cursor to the stars and tap space bar
+
+ or
+
+ ... select stars from the input coordinate list with m / :m #
+ and measure with spbar
+
+ ... measure stars selected from the input coordinate list
+ with n / n #
+
+ ... a one line summary of results will appear on the standard output
+ for each star measured
+
+ ... type q to quit and q again to confirm the quit
+
+ ... the output will appear in ypix.sky.3 ...
+.fi
+
+
+4. Display and measure some stars in an image section and write the output
+coordinates in the coordinate system of the parent image.
+
+.nf
+ ap> display dev$ypix[150:450,150:450] 1
+
+ ... display the image section
+
+ ap> fitsky dev$ypix[150:450,150:450] wcsout=tv
+
+ ... move cursor to stars and type spbar
+
+ ... type q to quit and q again to confirm quit
+
+ ... output will appear in ypix.sky.4
+
+ ap> pdump ypix.sky.4 xi,yi yes | tvmark 1 STDIN col=204
+.fi
+
+5. Run FITSKY in batch mode using the coordinate file and the previously
+saved parameters. Verify the critical parameters.
+
+.nf
+ ap> fitsky dev$ypix coords=ypix.coo.1 verify+ inter-
+
+ ... output will appear in ypix.sky.5 ...
+.fi
+
+6. Repeat example 5 but assume that the input coordinate are ra and dec
+in degrees and degrees, turn off verification, and submit the task to to
+the background.
+
+.nf
+ ap> display dev$ypix 1
+
+ ap> rimcursor wcs=world > radec.coo
+
+ ... move to selected stars and type any key
+
+ ... type ^Z to quit
+
+ ap> fitsky dev$ypix coords=radec.coo wcsin=world verify- inter- &
+
+ ... output will appear in ypix.sky.6
+
+ ap> pdump ypix.sky.6 xi,yi yes | tvmark 1 STDIN col=204
+
+ ... mark the stars on the display
+.fi
+
+7. Run FITSKY interactively without using the image display.
+
+.nf
+ ap> show stdimcur
+
+ ... record the default value of stdimcur
+
+ ap> set stdimcur = text
+
+ ... set the image cursor to the standard input
+
+ ap> fitsky dev$ypix coords=ypix.coo.1
+
+ ... type ? for optional help
+
+ ... type :m 3 to set the initial coordinates to those of the
+ third star in the list
+
+ ... type i to enter the interactive setup menu
+ ... enter the maximum radius in pixels for the radial profile or
+ accept the default with a CR
+ ... type v to enter the default menu
+ ... set the inner and outer sky annuli, and sigma using the
+ graphics cursor and the stellar radial profile plot
+ ... typing <CR> after the prompt leaves the parameter at its default
+ value
+ ... type q to quit the setup menu
+
+ ... type r to rewind the coordinate list
+
+ ... type l to measure all the stars in the coordinate list
+
+ ... a one line summary of the answers will appear on the standard
+ output for each star measured
+
+ ... type q to quit followed by q to confirm the quit
+
+ ... full output will appear in the text file ypix.sky.7
+
+ ap> set stdimcur = <default>
+
+ ... reset the value of stdimcur
+.fi
+
+8. Use an image cursor command file to drive the FITSKY task. The cursor command
+file shown below sets the annulus and dannulus parameters, computes the sky
+values for 3 stars, updates the parameter files, and quits the task.
+
+.nf
+ ap> type cmdfile
+ : annulus 12.0
+ : dannulus 5.0
+ 442 410 101 \040
+ 349 188 101 \040
+ 225 131 101 \040
+ w
+ q
+
+ ap> fitsky dev$ypix icommands=cmdfile verify-
+
+ ... full output will appear in ypix.sky.8
+.fi
+
+.ih
+TIME REQUIREMENTS
+
+.ih
+BUGS
+It is currently the responsibility of the user to make sure that the
+image displayed in the frame is the same as that specified by the image
+parameter.
+
+Commands which draw to the image display are disabled by default.
+To enable graphics overlay on the image display, set the display
+parameter to "imdr", "imdg", "imdb", or "imdy" to get red, green,
+blue or yellow overlays and set the fitskypars mksky switch to"yes".
+It may be necessary to run gflush and to redisplay the image
+to get the overlays position correctly.
+
+.ih
+SEE ALSO
+datapars, fitskypars, phot, polyphot, radprof
+.endhelp
diff --git a/noao/digiphot/apphot/doc/fitskypars.hlp b/noao/digiphot/apphot/doc/fitskypars.hlp
new file mode 100644
index 00000000..cdb541ba
--- /dev/null
+++ b/noao/digiphot/apphot/doc/fitskypars.hlp
@@ -0,0 +1,219 @@
+.help fitskypars May00 noao.digiphot.apphot
+.ih
+NAME
+fitskypars - edit the sky fitting algorithm parameters
+.ih
+USAGE
+fitskypars
+.ih
+PARAMETERS
+.ls salgorithm = "centroid"
+The sky fitting algorithm to be employed. The sky fitting options are:
+.ls constant
+Use a user supplied constant value \fIskyvalue\fR for the sky.
+This algorithm is useful for measuring large resolved objects on flat
+backgrounds such as galaxies or comments.
+.le
+.ls file
+Read sky values from a text file. This option is useful for importing
+user determined sky values into APPHOT.
+.le
+.ls mean
+Compute the mean of the sky pixel distribution. This algorithm is useful
+for computing sky values in regions with few background counts.
+.le
+.ls median
+Compute the median of the sky pixel distribution. This algorithm is a useful
+for computing sky values in regions with rapidly varying sky backgrounds
+and is a good alternative to "centroid".
+.le
+.ls mode
+Compute the mode of the sky pixel distribution using the computed mean and
+median. This is the recommended algorithm for APPHOT users trying to
+measuring stellar objects in crowded stellar fields. Mode may not perform
+well in regions with rapidly varying sky backgrounds.
+.le
+.ls centroid
+Compute the intensity-weighted mean or centroid of the sky pixel histogram.
+This is the algorithm recommended for most APPHOT users. It is reasonably
+robust in rapidly varying and crowded regions.
+.le
+.ls gauss
+Fit a single Gaussian function to the sky pixel histogram using non-linear
+least-squares techniques.
+.le
+.ls ofilter
+Compute the sky using the optimal filtering algorithm and a triangular
+weighting function and the histogram of the sky pixels.
+.le
+.ls crosscor
+Compute the sky value using the cross-correlation function of the sky pixel
+histogram and a Gaussian noise function with a sigma equal to the
+computed sigma of the sky pixel distribution.
+.le
+.ls histplot
+Mark the peak of the histogram of the sky pixels on a plot of the histogram.
+This algorithm is useful for making careful interactive sky measurements
+for a small number of objects in complicated regions or for checking the
+behavior of other sky algorithms.
+.le
+.ls radplot
+Mark the sky value on a radial distribution plot of the sky pixels.
+This algorithm is useful for making careful interactive sky measurements
+for a small number of objects in complicated regions or for checking the
+behavior of other sky algorithms.
+.le
+.le
+.ls annulus = 10.0 (scale units)
+The inner radius of the annular sky fitting region in units of the DATAPARS
+scale parameter.
+.le
+.ls dannulus = 10.0 (scale units)
+The width of the annular sky fitting region in units of the DATAPARS
+scale parameter.
+.le
+.ls skyvalue
+The constant for constant sky subtraction.
+.le
+.ls smaxiter = 10
+The maximum number of iterations performed by the sky fitting algorithm.
+\fISmaxiter\fR is required by the "gauss" and "ofilter" sky fitting algorithms.
+.le
+.ls sloclip = 0.0 (percent)
+The low-side clipping factor in percentage points of the total number of
+sky pixels.
+.le
+.ls shiclip = 0.0 (percent)
+The high-side clipping factor in percentage points of the total number of
+sky pixels.
+.le
+.ls snreject = 50
+The maximum number of pixel rejection cycles.
+.le
+.ls sloject = 3.0
+The ksigma low-side clipping factor for the pixel rejection phase of the
+sky fitting algorithm. \fIsloreject\fR is in units of the computed sky
+sigma.
+.le
+.ls shiject = 3.0
+The ksigma high-side clipping factor for the pixel rejection phase of the
+sky fitting algorithm. \fIshireject\fR is in units of the computed sky
+sigma.
+.le
+.ls khist = 3.0
+The ksigma clipping factor for computing the histogram of the sky pixels.
+\fIKhist\fR is in units of the computed sky sigma.
+The computed histogram will be 2.0 * khist * sigma wide.
+.le
+.ls binsize = 0.10
+The width of a single bin of the histogram of sky values.
+\fIBinsize\fR is in units of the computed sky sigma.
+.le
+.ls smooth = no
+Boxcar smooth the histogram before computing a sky value ?
+.le
+.ls rgrow = 0.0 (scale units)
+The region growing radius for pixel rejection in the sky region, in units
+of the DATAPARS \fIscale\fR parameter. When a bad sky pixel is detected,
+all pixels within rgrow / scale will be rejected. If rgrow is 0.0
+region growing is not performed.
+.le
+.ls mksky = no
+Mark the sky annulus on the displayed image ?
+.le
+.ih
+DESCRIPTION
+The sky fitting algorithm parameters control the action of the sky fitting
+algorithms. The default parameter settings should give reasonable results in
+the majority of cases. Several of the sky fitting parameters scale with
+image scale, \fIscale\fR which is data dependent. \fIScale\fR is defined in
+the DATAPARS parameter set.
+
+Sky pixels in an annular region of inner radius \fIannulus / scale\fR pixels
+and a width of \fIdannulus / scale\fR pixels are extracted from the IRAF image.
+If the \fIscale\fR parameter is defined in terms of the number of half-width
+at half-maximum of the point spread function per pixel, then single values of
+annulus and dannulus will work well for images with different seeing and
+detector characteristics.
+
+Pixels outside of the good data range specified by \fIdatamin\fR and
+\fIdatamax\fR are rejected from the sky pixel distribution. After bad
+data rejection \fIPloclip\fR and \fIphiclip\fR percent pixels are rejected
+from the low and high sides of the sorted pixel distribution before any
+sky fitting is done.
+
+Sky values are computed using the sky fitting algorithm specified by
+\fIsalgorithm\fR. The default value is "centroid". If \fIsalgorithm\fR
+= "mean", "median" or "mode", the sky value is computed directly from the
+array of sky pixels. The remaining sky fitting algorithms use the histogram
+of the object sky pixels. The computed histogram is \fIkhist\fR * sigma wide
+with a bin width of \fIbinsize\fR * sigma where sigma is the computed
+standard deviation of the sky pixels for each object. If \fIsmooth\fR = yes,
+boxcar smoothing is performed on the computed histogram before sky fitting.
+The mode of the histogram is computed using, a non-linear least squares
+fit to a Gaussian (salgorithm = "gauss"), optimal filtering of the histogram
+(salgorithm = "ofilter"), computing the intensity weighted mean of the
+histogram (salgorithm = "centroid"), or by cross-correlation techniques
+(salgorithm = "crosscor").
+
+Two interactive methods of fitting sky are also available. If \fIsalgorithm\fR
+is "radplot" or "histplot", the user must interactively set the value of the
+sky using a radial profile or a histogram profile plot.
+
+Pixels which deviate from the sky value by more than \fIkreject\fR times the
+computed sky sigma are rejected from the fit. If \fIrgrow\fR > 0, pixels
+within a radius of rgrow / scale of the rejected pixel are also rejected from
+the fit. The rejection procedure iterates until no further pixels are rejected,
+all pixels are rejected, or the maximum number of rejection cycles
+\fIsnreject\fR iterations is reached.
+
+.ih
+EXAMPLES
+1. List the sky fitting parameters.
+
+.nf
+ ap> lpar fitskypars
+.fi
+
+2. Edit the sky fitting parameters.
+
+.nf
+ ap> fitskypars
+.fi
+
+3. Edit the FITSKYPARS parameters from within the PHOT task.
+
+.nf
+ da> epar phot
+
+ ... edit a few phot parameters
+
+ ... move to the fitskypars parameter and type :e
+
+ ... edit the fitskypars parameters and type :wq
+
+ ... finish editing the phot parameters and type :wq
+.fi
+
+4. Save the current FITSKYPARS parameter set in a text file skynite1.par.
+This can also be done from inside a higher level task as in the
+above example.
+
+.nf
+ da> fitskypars
+
+ ... edit some parameters
+
+ ... type ":w skynite1.par" from within epar
+.fi
+
+.ih
+TIME REQUIREMENTS
+
+.ih
+BUGS
+
+.ih
+SEE ALSO
+radprof,fitsky,phot,wphot,polyphot
+.endhelp
diff --git a/noao/digiphot/apphot/doc/pexamine.hlp b/noao/digiphot/apphot/doc/pexamine.hlp
new file mode 100644
index 00000000..f3a031ec
--- /dev/null
+++ b/noao/digiphot/apphot/doc/pexamine.hlp
@@ -0,0 +1,836 @@
+.help pexamine May00 noao.digiphot.apphot
+.ih
+NAME
+pexamine -- interactively examine or edit a photometry catalog
+.ih
+USAGE
+pexamine input output image
+.ih
+PARAMETERS
+.ls input
+The name of the input photometry catalog. \fIInput\fR may be either an
+APPHOT/DAOPHOT text database file or an STSDAS binary table database.
+.le
+.ls output
+The name of the edited output catalog. \fIOutput\fR is either an
+APPHOT/DAOPHOT text database or an STSDAS binary table database
+depending on the file type of \fIinput\fR. If \fIoutput\fR = "" no output
+catalog is written.
+.le
+.ls image
+The name of the input image corresponding to the input photometry
+catalog. If \fIimage\fR is "" no image will be attached to PEXAMINE
+and some interactive catalog examining commands will not be available.
+All the catalog editing commands however are still available.
+.le
+.ls deletions = ""
+The name of an optional output deletions photometry catalog. \fIDeletions\fR
+is either an APPHOT/DAOPHOT text database or an STSDAS binary
+table database depending on the file type of \fIinput\fR. If \fIdeletions\fR
+is "" no deletions file is written.
+.le
+.ls photcolumns = "apphot"
+The list of standard photometry columns that are loaded when pexamine is
+run. The options are listed below.
+.ls "apphot"
+The standard columns for the APPHOT package. The current list is ID,
+XCENTER, YCENTER, MSKY, MAG, and MERR.
+If any of these
+columns are multi-valued, (as in the case of magnitudes measured through
+more than one aperture), the first value is selected.
+The standard list may easily be extended at user request.
+.le
+.ls "daophot"
+The standard columns for the DAOPHOT package. The current list is GROUP, ID,
+XCENTER, YCENTER, MSKY, MAG, MERR, CHI, SHARP and NITER.
+If any of these
+columns are multi-valued, (as in the case of magnitudes measured through
+more than one aperture), the first value is selected.
+The standard list may easily be extended at user request.
+.le
+.ls user list
+A user supplied list of standard columns.
+Column names are listed in full in either upper or
+lower case letters, separated by commas. If more than one value of
+a multi-valued column is requested
+the individual values
+must be listed separately as in the following example
+ID, XCENTER, YCENTER, MAG[1], MERR[1], MAG[2], MERR[2].
+.le
+
+\fIPhotcolumns\fR can be changed interactively from within PEXAMINE at
+the cost of rereading the database.
+.le
+.ls xcolumn = "mag" (magnitude), ycolumn = "merr" (magnitude error)
+The names of the two columns which define the default X-Y plot.
+\fIXcolumn\fR and \fIycolumn\fR must be listed in \fIphotcolumns\fR or
+\fIusercolumns\fR but may be changed interactively by the user.
+If either \fIxcolumn\fR or \fIycolumn\fR is a multi-valued quantity
+and more than one value is listed in \fIphotcolumns\fR or \fIusercolumns\fR
+then the desired value number must be specified explicitly in, e.g.
+MAG[2] or MERR[2].
+.le
+.ls hcolumn = "mag" (magnitude)
+The name of the column which defines the default histogram plot.
+\fIHcolumn\fR must be listed in \fIphotcolumns\fR or
+\fIusercolumns\fR but may be changed interactively by the user.
+If \fIhcolumn\fR is a multi-valued quantity and more than one value is
+listed in \fIphotcolumns\fR or \fIusercolumns\fR then the desired value
+must be specified explicitly in \fIhcolumn\fR, e.g. MAG[2].
+.le
+.ls xposcolumn = "xcenter", yposcolumn = "ycenter"
+The names of the two columns which define the X and Y coordinates in
+\fIimage\fR of the objects in the catalog. This information is
+required if the image display and image cursor are to be used to visually
+identify objects in the image with objects in the catalog or if plots
+of image data are requested. \fIXposcolumn\fR and \fIyposcolumn\fR must
+be listed in \fIphotcolumns\fR or \fIusercolumns\fR but may
+be changed interactively by the user.
+.le
+.ls usercolumns = ""
+The list of columns loaded into memory in addition to the
+standard photometry columns \fIphotcolumns\fR. The column
+names are listed in full in upper or lower case letters and separated by
+commas.
+\fIUsercolumns\fR can be changed interactively from within PEXAMINE at
+the cost of rereading the database.
+.le
+.ls first_star = 1
+The index of the first object to be read out of the catalog.
+.le
+.ls max_nstars = 5000
+The maximum number of objects that are loaded into memory at task
+startup time, beginning at object \fIfirst_star\fR. If there are more
+than \fImax_nstars\fR in the catalog only the first \fImax_nstars\fR
+objects are read in.
+.le
+.ls match_radius = 2.0
+The tolerance in pixels to be used for matching objects in the catalog with
+objects marked on the display with the image cursor.
+.le
+.ls graphics = "stdgraph"
+The default graphics device.
+.le
+.ls use_display = yes
+Use the image display? Users without access to an image display should
+set \fIuse_display\fR to "no".
+.le
+.ls icommands = ""
+The image display cursor. If null the standard image cursor is used whenever
+image cursor input is requested. A cursor file in the appropriate
+format may be substituted by specifying the name of the file.
+Also the image cursor may be changed to query the graphics device or the
+terminal by setting the environment variable "stdimcur" to "stdgraph"
+or "text" respectively.
+.le
+.ls gcommands = ""
+The graphics cursor. If null the standard graphics cursor is used whenever
+graphics cursor input is requested. A cursor file in the appropriate
+format may be substituted by specifying the name of the file.
+.le
+
+.ih
+PLOTTING PARAMETERS
+
+PEXAMINE supports five types of plots 1) an X-Y column plot
+2) a histogram column plot 3) a radial profile plot 4) a surface
+plot and 5) a contour plot.
+Each supported plot type has its own parameter set which
+controls the appearance of the plot.
+The names of the five parameter sets are listed below.
+
+.nf
+ cntrplot Parameters for the contour plot
+ histplot Parameters for the column histogram plot
+ radplot Parameters for radial profile plot
+ surfplot Parameters for surface plot
+ xyplot Parameters for the X-Y column plot
+.fi
+
+The same parameters dealing with graph formats occur in many of the parameter
+sets while some are specific only to one parameter set. In the
+summary below those common to more than one parameter set are shown
+only once. The characters in parenthesis are the graph key prefixes
+for the parameter sets in which the parameter occurs.
+
+.ls angh = -33., angv = 25. (s)
+Horizontal and vertical viewing angles in degrees for surface plots.
+.le
+.ls axes = yes (s)
+Draw axes along the edge of surface plots?
+.le
+.ls banner = yes (chrsx)
+Add a standard banner to a graph? The standard banner includes the
+IRAF user and host identification and the date and time.
+.le
+.ls box = yes (chrx)
+Draw graph box and axes?
+.le
+.ls ceiling = INDEF (cs)
+Ceiling data value for contour and surface plots. A value of INDEF does
+not apply a ceiling. In contour plots a value of 0. also does not
+apply a ceiling.
+.le
+.ls dashpat = 528 (c)
+Dash pattern for negative contours.
+.le
+.ls fill = no (yes) (c) (hrx)
+Fill the output viewport regardless of the device aspect ratio?
+.le
+.ls floor = INDEF (cs)
+Floor data value for contour and surface plots. A value of INDEF does
+not apply a floor. In contour plots a value of 0. also does not
+apply a floor.
+.le
+.ls grid = no (rx)
+Draw grid lines at major tick marks?
+.le
+.ls interval = 0.0 (c)
+Contour interval. If 0.0, a contour interval is chosen which places 20 to 30
+contours spanning the intensity range of the image.
+.le
+.ls label= no (c)
+Label the major contours in the contour plot?
+.le
+.ls logx = no, logy = no (rx) (hrx)
+Plot the x or y axis logarithmically? The default for histogram plots is
+to plot the y axis logarithmically.
+.le
+.ls majrx=5, minrx=5, majry=5, minry=5 (chrx)
+Maximum number of major tick marks on each axis and number of minor tick marks
+between major tick marks.
+.le
+.ls marker = "box" (rx)
+Marker to be drawn. Markers are "point", "box",
+"cross", "plus", "circle", "hline", "vline" or "diamond".
+.le
+.ls nbins = 512 (h)
+The number of bins in, or resolution of, histogram plots.
+.le
+.ls ncolumns = 21, nlines = 21 (cs)
+Number of columns and lines used in contour and surface plots.
+.le
+.ls ncontours = 5 (c)
+Number of contours to be drawn. If 0, the contour interval may be specified,
+otherwise 20 to 30 nicely spaced contours are drawn. A maximum of 40 contours
+can be drawn.
+.le
+.ls nhi = -1 (c)
+If -1, highs and lows are not marked. If 0, highs and lows are marked
+on the plot. If 1, the intensity of each pixel is marked on the plot.
+.le
+.ls rinner = 0, router = 8
+The inner and outer radius of the region whose radial profile is to
+be plotted.
+.le
+.ls round = no (chrx)
+Extend the axes up to "nice" values?
+.le
+.ls szmarker = 1 (rx)
+Size of mark except for points. A positive size less than 1 specifies
+a fraction of the device size. Values of 1, 2, 3, and 4 signify
+default sizes of increasing size.
+.le
+.ls ticklabels = yes (chrx)
+Label the tick marks?
+.le
+.ls top_closed = no (h)
+Include z2 in the top histogram bin? Each bin of the histogram is a
+subinterval that is half open at the top. \fITop_closed\fR decides whether
+those pixels with values equal to z2 are to be counted in the histogram. If
+\fBtop_closed\fR is yes, the top bin will be larger than the other bins.
+.le
+.ls x1 = INDEF, x2 = INDEF, y1 = INDEF, y2 = INDEF (hrx)
+Range of graph along each axis. If INDEF the range is determined from
+the data range. The default y1 for histogram plots is 0.
+.le
+.ls zero = 0. (c)
+Greyscale value of the zero contour, i.e., the value of a zero point shift
+to be applied to the image data before plotting. Does not affect the values
+of the floor and ceiling parameters.
+.le
+.ls z1 = INDEF, z2 = INDEF (h)
+Range of pixel values to be used in histogram. INDEF values default to
+the range in the region being histogramed.
+.le
+
+.ih
+DESCRIPTION
+
+PEXAMINE is a general purpose tool for interactively examining and editing
+photometry catalogs produced by the APPHOT or DAOPHOT packages. It is
+intended to aid the user in assessing the accuracy of the photometry,
+in diagnosing problems with particular catalog objects,
+in searching the photometry data for relationships
+between the computed quantities, and in editing the catalog based on
+those observed relationships. PEXAMINE is intended to complement the
+more batch oriented editing facilities of the SELECT task.
+
+PEXAMINE takes the input catalog \fIinput\fR and the corresponding
+image \fIimage\fR (if defined) and produces an output catalog of selected
+objects \fIoutput\fR (if defined) and an output catalog of deleted objects
+\fIdeletions\fR (if defined). The input catalog may be either an
+APPHOT/DAOPHOT text database or an ST binary table database.
+The file type of the output catalogs \fIoutput\fR and \fIdeletions\fR
+is the same as that of \fIinput\fR.
+
+READING IN THE DATA
+
+PEXAMINE reads the column data specified by \fIphotcolumns\fR and
+\fIusercolumns\fR for up to \fImax_nstars\fR beginning at star
+\fIfirst_star\fR into memory.
+The \fIphotcolumns\fR parameter
+defines the list of standard photometry columns to be loaded. If
+"daophot" or "apphot" is selected then the standard columns
+are GROUP, ID, XCENTER, YCENTER, MSKY, MAG, MERR, CHI, SHARP and NITER
+and ID, XCENTER, YCENTER, MSKY, MAG and MERR respectively.
+Otherwise the user must set \fIphotcolumns\fR to his or her own preferred
+list of standard photometry columns. Non-standard columns may also be
+specified using the parameter \fIusercolumns\fR.
+Valid column lists contain the full names of the specified columns
+in upper or lower case letters, separated by commas.
+Either \fIphotcolumns\fR or
+\fIusercolumns\fR may be redefined interactively by the user after
+the task has started up, but only at the
+expense of rereading the data from \fIinput\fR.
+
+PEXAMINE will fail to load a specified column if that column is
+not in the photometry database, is of a datatype other than
+integer or real, or adding that column would exceed the maximum
+number of columns limit currently set at twenty. The user can
+interactively examine the list of requested and loaded standard
+photometry columns, as well as list all the columns in the input
+after the task has started up.
+
+GRAPHICS AND IMAGE COMMAND MODE
+
+PEXAMINE accepts commands either from the graphics cursor \fIgcommands\fR
+(graphics command mode) or the image display cursor \fIicommands\fR
+if available (image command mode).
+PEXAMINE starts up in graphics command mode, but all the
+interactive commands are accessible from both modes and the user can
+switch modes at any time assuming that the \fIuse_display\fR parameter
+is set to "yes".
+
+PEXAMINE interprets the cursor position in graphics command mode
+differently from how it interprets it in image command mode.
+In graphics command mode the cursor coordinates are the position
+of the cursor in the current plot, whereas in image command mode they
+are the x and y coordinates of the cursor in the displayed image.
+For example, if the user issues a command to PEXAMINE to locate the object
+in the catalog nearest the point in the current X-Y plot marked by
+the graphics cursor, PEXAMINE does so by searching
+the data for the object whose values of \fIxcolumn\fR and \fIycolumn\fR
+most closely match those of the current cursor position.
+If the user issues a command to PEXAMINE to locate the
+object in the catalog corresponding to the object marked on the image
+display with the image cursor,
+PEXAMINE does so by searching the data for
+the object whose values of \fIxposcolumn\fR and \fIyposcoumn\fR
+most closely match and fall within \fImatch_radius\fR of the current
+cursor position.
+
+Input to PEXAMINE is through single keystroke commands or colon
+commands. Keystroke commands are simple commands that may
+optionally use the cursor position but otherwise require no arguments.
+The PEXAMINE keystroke commands fall into three categories, basic
+commands, data examining commands and data editing commands, all
+described in detail in the following sections. Colon commands
+take an optional argument and function differently depending on
+the presence or absence of that argument. When the argument is absent
+colon commands are used to display the
+current value of a parameter or list of parameters. When the argument is
+present they change their current value to that argument.
+The basic colon commands are described in detail below.
+
+BASIC KEYSTROKE COMMANDS
+
+These keystroke commands are used to display the help page, switch from
+graphics to image command mode and quit the task.
+
+.ls ?
+Page through the help for the PEXAMINE task
+.le
+.ls :
+Execute a PEXAMINE colon command.
+.le
+.ls g
+Change to graphics command mode. Throughout PEXAMINE graphics command mode
+is the default. All PEXAMINE commands are available in graphics command
+mode.
+.le
+.ls i
+Change to image command mode.
+All the PEXAMINE commands are available in image command mode.
+However if \fIuse_display\fR is no and the image
+cursor has not been aliased to the standard input or a text file
+image command mode is disabled.
+.le
+.ls q
+Quit PEXAMINE without writing an output catalog.
+PEXAMINE queries the user for confirmation of this option.
+.le
+.ls e
+Quit PEXAMINE and write the output catalog.
+.le
+
+DATA EXAMINING COMMANDS
+
+The data examining commands fall into two categories, those that examine
+the catalog data including 'l' (catalog listing), 'o' (object listing),
+'x' (Y column versus X column plot) and 'h' (histogram column plot)
+commands, and those which examine the image data around specific catalog
+objects including 'r' (radial profile plotting), 's' (surface plotting),
+'c' (contour plotting) and 'm' (pixel dumping). The latter group
+require that \fIimage\fR be defined. A brief summary of each data
+examining command is given below.
+.ls l
+Print out the name, datatype, and units for all the columns in the input
+catalog. The list command can be used to check the contents of the input
+catalog and/or determine why a particualar column was not loaded.
+.le
+.ls o
+Print out the names and values of the stored columns of the object
+nearest the cursor. In graphics mode the current plot type must be
+X-Y. In image command mode the object nearest the cursor must also be
+no more than \fImatch-radius\fR pixels away from the image cursor to be
+found. If an object is found and the current plot type is X-Y
+the graphics cursor is moved to the position of the selected object
+in the X-Y plot.
+.le
+.ls x
+Plot the data in \fIycolumn\fR versus the data in \fIxcolumn\fR excluding
+any already deleted points and identifying objects marked for deletion
+with a cross. X-Y plotting is undefined if \fIxcolumn\fR or \fIycolumn\fR
+is undefined.
+.le
+.ls h
+Plot the histogram of the data in \fIhcolumn\fR excluding any already
+deleted points and those marked for deletion. Histogram plotting is
+disabled if \fIhcolumn\fR is undefined.
+.le
+.ls r
+Plot the radial profile of the object nearest the cursor including
+only pixels within a distance of \fIrinner\fR and \fRrouter\R of
+the object center. Radial profile plotting is disabled if \fIimage\fR
+or \fIxposcolumn\fR or \fIyposcolumn\fR is undefined.
+.le
+.ls s
+Plot the surface plot of the object nearest the cursor including
+only pixels within an image section \fIncols\fR by \fInlines\fR
+around the object center. Surface plotting is disabled if \fIimage\fR
+or \fIxposcolumn\fR or \fIyposcolumn\fR is undefined.
+.le
+.ls c
+Plot the contour plot of the object nearest the cursor including
+only pixels within an image section \fIncols\fR by \fInlines\fR
+around the object center. Contour plotting is disabled if \fIimage\fR
+or \fIxposcolumn\fR or \fIyposcolumn\fR is undefined.
+.le
+.ls m
+Dump the pixel values of a grid of 10 by 10 pixels around the object
+nearest the cursor. Pixel value dumping is disabled if \fIimage\fR
+or \fIxposcolumn\fR or \fIyposcolumn\fR is undefined.
+.le
+.ls p
+Replot the current graph.
+.le
+
+DATA EDITING COMMANDS
+
+Data points can be deleted from the catalog in either graphics command
+mode or image
+command mode. In graphics command mode the
+graphics cursor and either the X-Y or histogram plot is used to delete points.
+In image command mode the image cursor and the displayed
+image are used to delete points. A data point has three possible states
+good, marked for deletion and deleted.
+Any one of the keystroke commands 'd' (delete point), '(' (delete points
+with x less than x cursor), ')' (delete points with x greater than x cursor,
+'^' (delete points with y > y cursor), 'v' (delete points with y < y cursor)
+or 'b' (delete points in a box) can be used to mark points for deletion.
+The 'f' key is used to actually delete the points and replot the data.
+In between marking the points for deletion and actually deleting the marked
+points the 't' (toggle) key can be used to undelete the last set marked.
+The full list of the data editing keystroke commands is given below.
+
+.ls z
+Undelete not just unmark all the data points replot.
+.le
+.ls f
+Delete points marked for deletion and replot. Points marked for deletion
+but not actually deleted will be written to the output catalog and not
+written to the deletions catalog.
+.le
+.ls d
+Mark the point nearest the cursor for deletion.
+.le
+.ls u
+Undelete the marked point nearest the cursor.
+.le
+.ls (
+Mark all points with x values less than the x value of the cursor for
+deletion. In graphics command mode points can only be marked for deletion if
+the current plot type is "xyplot" or "histplot". In image command
+mode \fIxposcolumn\fR and \fIyposcolumn\fR must be defined before
+points can be marked for deletion.
+.le
+.ls )
+Mark all points with x values greater than the x value of the cursor for
+deletion. In graphics command mode points can only be marked for deletion if
+the current plot type is "xyplot" or "histplot". In image command
+mode \fIxposcolumn\fR and \fIyposcolumn\fR must be defined before
+points can be marked for deletion.
+.le
+.ls v
+Mark all points with y values less than the y value of the cursor for
+deletion. In graphics command mode points can only be marked for deletion if
+the current plot type is "xyplot". In image command
+mode \fIxposcolumn\fR and \fIyposcolumn\fR must be defined before
+points can be marked for deletion.
+.le
+.ls ^
+Mark all points with y values greater than the y value of the cursor for
+deletion. In graphics command mode points can only be marked for deletion if
+the current plot type is "xyplot". In image command
+mode \fIxposcolumn\fR and \fIyposcolumn\fR must be defined before
+points can be marked for deletion.
+.le
+.ls b
+Mark all points within a box whose lower left and upper right hand corners
+are marked by the cursor for deletion.
+In graphics mode points can only be marked for deletion if the current
+plot type is "xyplot". In image command mode \fIxposcolumn\fR and
+\fIyposcolumn\fR must be defined before points can be marked for
+deletion.
+.le
+.ls t
+Toggle between marking points for deletion or undeletion. The default
+is to mark points for deletion.
+.le
+
+BASIC COLON COMMANDS
+
+All the PEXAMINE parameters can be changed interactively with colon
+commands, including those which determine which data is read in,
+which data is plotted and the parameters of each plot. A brief description
+of the basic commands is given here. The full list is given in the
+following section.
+
+.ls :photcolumns [col1,col2,...]
+Show or set the list of requested standard photometry columns and the list
+of loaded
+photometry columns. If the user supplies a new list of columns the data will be
+reread from disk.
+.le
+.ls :usercolumns [col1,col2,...]
+Show or set the list of requested user columns and the list of loaded
+user columns. If the user supplies a new list of columns the data will be
+reread from disk.
+.le
+.ls :xcolumn [colname]
+Show or set the name of the column to be plotted along the x axis of the
+X-Y plot.
+.le
+.ls :ycolumn [colname]
+Show or set the name of the column to be plotted along the y axis of the
+X-Y plot.
+.le
+.ls :hcolumn [colname]
+Show or set the name of the column to be whose histogram is to be plotted.
+.le
+.ls :eparam [cntrplot/histplot/radplot/surfplot/xyplot]
+Review or edit the list of parameters for the various plot types.
+.le
+.ls :unlearn [cntrplot/histplot/radplot/surfplot/xyplot]
+Return the list of parameters for the various plot types to their default
+values.
+.le
+.ls :x y key cmd
+Execute any defined keystroke "key" supplying the appropriate x and y
+value in place of the cursor position. In graphics command mode the x
+and y position are assumed to be the position in the current graph.
+In image command mode the x and y position are assumed to be the x and
+y coordinate in the image display.
+.le
+
+.ih
+CURSOR COMMANDS
+
+.nf
+ PEXAMINE Interactive Cursor Keystroke Commands
+
+ Basic Commands
+
+? Print help for the PEXAMINE task
+: PEXAMINE colon commands
+g Activate the graphics cursor
+i Activate the image cursor
+e Exit PEXAMINE and save the edited catalog
+q Quit PEXAMINE and discard the edited catalog
+
+ Data Examining Commands
+
+l List the name, datatype and units for all columns in the catalog
+o Print out the names and values of the stored columns for the
+ object nearest the cursor
+x Replot the current y column versus the current x column
+h Replot the current histogram
+r Plot the radial profile of the object nearest the cursor
+s Plot the surface of the object nearest the cursor
+c Plot the contour plot of the object nearest the cursor
+m Print the data values of the object nearest the cursor
+p Replot the current graph
+
+ Data Editing Commands
+
+z Reinitialize the data by removing all deletions and replot
+d Mark the point nearest the cursor for deletion
+u Undelete the marked point nearest the cursor
+t Toggle between marking points for deletion or undeletion
+( Mark points with X < X (cursor) for deletion or undeletion
+) Mark points with X > X (cursor) for deletion or undeletion
+v Mark points with Y < Y (cursor) for deletion or undeletion
+^ Mark points with Y > Y (cursor) for deletion or undeletion
+b Mark points inside a box for deletion or undeletion
+f Actually delete the marked points and replot
+
+
+ PEXAMINE Interactive Colon Commands
+
+:xcolumn [name] Show/set the X-Y plot X axis quantity
+:ycolumn [name] Show/set the X-Y plot Y axis quantity
+:hcolumn [name] Show/set the histogram plot quantity
+:photcolumns [col1,col2,...] Show/set the list of photometry columns
+:usercolumns [col1,col2,...] Show/set the list of user columns
+:delete [yes/no] Delete or undelete points
+:eparam [x/h/r/s/c] Edit/unlearn the specified plot pset
+ or
+:unlearn
+
+
+ PEXAMINE Interactive X-Y Plotting Commands
+
+:x1 [value] Left world x-coord if not autoscaling
+:x2 [value] Right world x-coord if not autoscaling
+:y1 [value] Lower world y-coord if not autoscaling
+:y2 [value] Upper world y-coord if not autoscaling
+:szmarker [value] Marker size
+:marker [point|box|plus|cross|circle|diamond|hline|vline] Marker type
+:logx [yes/no] Log scale the x axis?
+:logy [yes/no] Log scale the y axis?
+:box [yes/no] Draw box around periphery of window?
+:ticklabels [yes/no] Label tick marks?
+:grid [yes/no] Draw grid lines at major tick marks?
+:majrx [value] Number of major divisions along x axis
+:minrx [value] Number of minor divisions along x axis
+:majry [value] Number of major divisions along y axis
+:minry [value] Number of minor divisions along y axis
+:round [yes/no] Round axes to nice values?
+:fill [yes/no] Fill viewport vs enforce unity aspect ratio?
+
+
+ PEXAMINE Interactive Histogram Plotting Commands
+
+:nbins [value] Number of bins in the histogram
+:z1 [value] Minimum histogram intensity
+:z2 [value] Maximum histogram intensity
+:top_closed [y/n] Include z in the top bin?
+:x1 [value] Left world x-coord if not autoscaling
+:x2 [value] Right world x-coord if not autoscaling
+:y1 [value] Lower world y-coord if not autoscaling
+:y2 [value] Upper world y-coord if not autoscaling
+:logy [yes/no] Log scale the y axis?
+:box [yes/no] Draw box around periphery of window?
+:ticklabels [yes/no] Label tick marks?
+:majrx [value] Number of major divisions along x axis
+:minrx [value] Number of minor divisions along x axis
+:majry [value] Number of major divisions along y axis
+:minry [value] Number of minor divisions along y axis
+:round [yes/no] Round axes to nice values?
+:fill [yes/no] Fill viewport vs enforce unity aspect ratio?
+
+ PEXAMINE Interactive Radial Profile Plotting Commands
+
+:rinner [value] Inner radius of the region to be plotted
+:router [value] Outer radius of the region to be plotted
+:x1 [value] Left world x-coord if not autoscaling
+:x2 [value] Right world x-coord if not autoscaling
+:y1 [value] Lower world y-coord if not autoscaling
+:y2 [value] Upper world y-coord if not autoscaling
+:szmarker [value] Marker size
+:marker [point|box|plus|cross|circle|diamond|hline|vline] Marker type
+:logx [yes/no] Log scale the x axis?
+:logy [yes/no] Log scale the y axis?
+:box [yes/no] Draw box around periphery of window?
+:ticklabels [yes/no] Label tick marks?
+:grid [yes/no] Draw grid lines at major tick marks?
+:majrx [value] Number of major divisions along x axis
+:minrx [value] Number of minor divisions along x axis
+:majry [value] Number of major divisions along y axis
+:minry [value] Number of minor divisions along y axis
+:round [yes/no] Round axes to nice values?
+:fill [yes/no] Fill viewport vs enforce unity aspect ratio?
+
+
+ PEXAMINE Interactive Surface Plotting Commands
+
+:ncolumns [value] Number of columns to be plotted
+:nlines [value] Number of lines to be plotted
+:axes [yes/no] Draw axes?
+:angh [value] Horizontal viewing angle
+:angv [value] Vertical viewing angle
+:floor [value] Minimum value to be plotted
+:ceiling [value] Maximum value to be plotted
+
+
+ PEXAMINE Interactive Contour Plotting Commands
+
+:ncolumns [value] Number of columns to be plotted
+:nlines [value] Number of lines to be plotted
+:floor [value] Minimum value to be plotted
+:ceiling [value] Maximum value to be plotted
+:zero [value] Greyscale value of zero contour
+:ncontours [value] Number of contours to be drawn
+:interval [value] Contour interval
+:nhi [value] Hi/low marking option
+:dashpat [value] Bit pattern for generating dashed lines
+:label [yes/no] Label major contours with their values?
+:box [yes/no] Draw box around periphery of window?
+:ticklabels [yes/no] Label tick marks?
+:majrx [value] Number of major divisions along x axis
+:minrx [value] Number of minor divisions along x axis
+:majry [value] Number of major divisions along y axis
+:minry [value] Number of minor divisions along y axis
+:round [yes/no] Round axes to nice values?
+:fill [yes/no] Fill viewport vs enforce unity aspect ratio?
+.fi
+
+.ih
+EXAMPLES
+
+1. Examine and edit an APPHOT aperture photometry catalog and a DAOPHOT
+allstar catalog without either attaching the associated image or using the
+image display.
+
+.nf
+ pt> pexamine m92.mag.1 m92.mag.ed use_display-
+
+ ... a plot of magnitude error versus magnitude appears on
+ the screen and the graphics cursor comes up ready to accept
+ commands
+
+ ... the user sees a generally smooth trend of increasing
+ magnitude error with increasing magnitude except for a
+ single deviant point at the bright end of the plot
+
+ ... the user decides to remove the deviant point using the
+ 'd' keystroke command to mark the point and the 'f'
+ keystroke command to actually delete and replot the graph
+
+ ... after examining the plot further the user decides to delete
+ all objects for which the magnitude error is > 0.1 magnitudes
+ using the '^' keystroke command, followed by the 'f'
+ keystroke command to actually replot and delete the data.
+
+ ... after deciding that this new plot is satisfactory the user
+ issues the 'e' keystroke command to exit pexamine and save
+ the good data in m92.mag.ed
+
+ pt> pexamine m92.als.1 m92.als.ed use_display-
+
+ ... a plot of magnitude error versus magnitude appears on the
+ screen and the graphics cursor comes up ready to accept
+ commands
+
+ ... after looking at the plot the user decides that what they
+ really want to see is a plot of the goodness of fit parameter
+ chi versus magnitude
+
+ ... the user issues the colon command :ycol chi followed by 'p'
+ keystroke command to replot the data
+
+ ... the user sees a generally smooth trend of increasing
+ chi with increasing magnitude
+
+ ... after examining the plot further the user decides to delete
+ all objects for which the chi value > 2.0 and the
+ magnitude is > 25 using the '^' key and ')' keystroke
+ commands followed by 'f' to save the deletions and replot
+ the data
+
+ ... after deciding that this new plot is satisfactory the user
+ issues the 'e' keystroke command to exit pexamine and save
+ the good data in m92.als.ed
+.fi
+
+2. Examine and edit a DAOPHOT allstar catalog using the subracted image, the
+original image and the image display.
+
+.nf
+ pt> display image.sub 1
+
+ ... display the subtracted image
+
+ pt> pexamine orionk.als.1 orionk.als.ed image xcol=mag ycol=chi
+
+ ... a plot of the goodness of fit versus magnitude appears
+ on the terminal and the graphics cursor comes up ready to
+ accept commands
+
+ ... the user notices some very anomalous chi values and decides
+ to see if these correspond to objects which have poor
+ subtraction on the displayed image
+
+ ... the user switches to image command mode by tapping the 'i'
+ key, moves to the first poorly subtracted object and taps
+ the 'o' key
+
+ ... a list of the values of the loaded columns including chi
+ appears in the text window , the program switchs to graphics
+ mode and places the graphics cursor on the corresponding
+ point in the X-Y plot
+
+ ... the point in question indeed has a very high chi value
+ and the user decides to try and investigate the reason for the
+ anomalous value
+
+ ... the user taps the 'r' key to get a radial profile of the
+ object in the original image
+
+ ... after carefully examining the profile it appears that the
+ object's profile is too broad and that it is not a star
+
+ ... the user switches back to the X-Y plot with the 'x' key,
+ marks the point with the 'd' key and saves the deletions
+ and replots with the 'f' key.
+
+ ... the user goes back to image command mode with the 'i' key
+ and begins investigating the next object
+
+ ... finally after examining the image and making all the changes
+ the user decides to quit and save the changes with the 'e' key
+
+.fi
+
+.ih
+TIME REQUIREMENTS
+
+.ih
+BUGS
+If the display device is on a remote resource the first image cursor
+request will cause PEXAMINE to hang. The remote resource is expecting
+the appropriate password which the user must type in to cause the
+the image cursor to appear. The normal password prompt is
+not being issued or flushed to the terminal. The solution to the problem
+is to put the password in the .irafhosts file
+
+INDEF valued points cannot be accessed by
+PEXAMINE. INDEF valued points should be removed from the input catalog
+with SELECT prior to entering PEXAMINE.
+
+.ih
+SEE ALSO
+ptools.select, ptools.txselect,ptools.tselect
+
+.endhelp
diff --git a/noao/digiphot/apphot/doc/phot.hlp b/noao/digiphot/apphot/doc/phot.hlp
new file mode 100644
index 00000000..a4ee6ffb
--- /dev/null
+++ b/noao/digiphot/apphot/doc/phot.hlp
@@ -0,0 +1,767 @@
+.help phot May00 noao.digiphot.apphot
+.ih
+NAME
+phot -- do aperture photometry on a list of stars
+.ih
+USAGE
+phot image
+.ih
+PARAMETERS
+.ls image
+The list of images containing the objects to be measured.
+.le
+.ls skyfile = ""
+The list of text files containing the sky values, of the measured objects,
+one object per line with x, y, the sky value, sky sigma, sky skew, number of sky
+pixels and number of rejected sky pixels in columns one to seven respectively.
+The number of sky files must be zero, one, or equal to the number of input
+images. A skyfile value is only requested if \fIfitskypars.salgorithm\fR =
+"file" and if PHOT is run non-interactively.
+.le
+.ls coords = ""
+The list of text files containing initial coordinates for the objects to
+be centered. Objects are listed in coords one object per line with the
+initial coordinate values in columns one and two. The number of coordinate
+files must be zero, one, or equal to the number of images. If coords is
+"default", "dir$default", or a directory specification then a coords file name
+of the form dir$root.extension.version is constructed and searched for,
+where dir is the directory, root is the root image name, extension is "coo"
+and version is the next available version number for the file.
+.le
+.ls output = "default"
+The name of the results file or results directory. If output is
+"default", "dir$default", or a directory specification then an output file name
+of the form dir$root.extension.version is constructed, where dir is the
+directory, root is the root image name, extension is "mag" and version is
+the next available version number for the file. The number of output files
+must be zero, one, or equal to the number of image files. In both interactive
+and batch mode full output is written to output. In interactive mode
+an output summary is also written to the standard output.
+.le
+.ls plotfile = ""
+The name of the file containing radial profile plots of the stars written
+to the output file. If plotfile is defined then a radial profile plot
+is written to plotfile every time a record is written to \fIoutput\fR.
+The user should be aware that this can be a time consuming operation.
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters. The critical
+parameters \fIfwhmpsf\fR and \fIsigma\fR are located here. If \fIdatapars\fR
+is undefined then the default parameter set in uparm directory is used.
+.le
+.ls centerpars = ""
+The name of the file containing the centering parameters. The critical
+parameters \fIcalgorithm\fR and \fIcbox\fR are located here.
+If \fIcenterpars\fR is undefined then the default parameter set in
+uparm directory is used.
+.le
+.ls fitskypars = ""
+The name of the text file containing the sky fitting parameters. The critical
+parameters \fIsalgorithm\fR, \fIannulus\fR, and \fIdannulus\fR are located here.
+If \fIfitskypars\fR is undefined then the default parameter set in uparm
+directory is used.
+.le
+.ls photpars = ""
+The name of the file containing the photometry parameters. The critical
+parameter \fIapertures\fR is located here. If \fIphotpars\fR is undefined
+then the default parameter set in uparm directory is used.
+.le
+.ls interactive = yes
+Run the task interactively ?
+.le
+.ls radplots = no
+If \fIradplots\fR is "yes" and PHOT is run in interactive mode, a radial
+profile of each star is plotted on the screen after the star is measured.
+.le
+.ls icommands = ""
+The image display cursor or image cursor command file.
+.le
+.ls gcommands = ""
+The graphics cursor or graphics cursor command file.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout"
+The coordinate system of the input coordinates read from \fIcoords\fR and
+of the output coordinates written to \fIoutput\fR respectively. The image
+header coordinate system is used to transform from the input coordinate
+system to the "logical" pixel coordinate system used internally,
+and from the internal "logical" pixel coordinate system to the output
+coordinate system. The input coordinate system options are "logical", tv",
+"physical", and "world". The output coordinate system options are "logical",
+"tv", and "physical". The image cursor coordinate system is assumed to
+be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin and wcsout are "logical" and "logical" respectively.
+.le
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default cacheing is
+disabled.
+.le
+.ls verify = ")_.verify"
+Verify the critical parameters in non-interactive mode. Verify may
+be set to the value of the apphot package parameter (the default), "yes", or
+"no".
+.le
+.ls update = ")_.update"
+Automatically update the algorithm parameters in non-interactive mode
+if verify is "yes". Update may be set to the value of the apphot
+package parameter (the default), "yes", or "no".
+.le
+.ls verbose = ")_.verbose"
+Print results on the screen in non-interactive mode? Verbose may
+be set to the value of the apphot package parameter (the default),
+"yes", or "no".
+.le
+.ls graphics = ")_.graphics"
+The default graphics device. Graphics may be set to the value of the apphot
+package parameter (the default), "yes", or "no".
+.le
+.ls display = ")_.display"
+The default display device. Display may be set to the apphot package
+parameter value (the default), "yes", or "no. By default graphics overlay is
+disabled. Setting display to one of "imdr", "imdg", "imdb", or "imdy" enables
+graphics overlay with the IMD graphics kernel. Setting display to
+"stdgraph" enables PHOT to work interactively from a contour plot.
+.le
+
+.ih
+DESCRIPTION
+
+PHOT computes accurate centers, sky values, and magnitudes for a list of
+objects in the IRAF image \fIimage\fR whose coordinates are read from
+the text file \fIcoords\fR or the image display cursor, and writes the
+computed x and y coordinates, sky values, and magnitudes to the text
+file \fIoutput\fR.
+
+The coordinates read from \fIcoords\fR are assumed to be in coordinate
+system defined by \fIwcsin\fR. The options are "logical", "tv", "physical",
+and "world" and the transformation from the input coordinate system to
+the internal "logical" system is defined by the image coordinate system.
+The simplest default is the "logical" pixel system. Users working on with
+image sections but importing pixel coordinate lists generated from the parent
+image must use the "tv" or "physical" input coordinate systems.
+Users importing coordinate lists in world coordinates, e.g. ra and dec,
+must use the "world" coordinate system and may need to convert their
+equatorial coordinate units from hours and degrees to degrees and degrees first.
+
+The coordinates written to \fIoutput\fR are in the coordinate
+system defined by \fIwcsout\fR. The options are "logical", "tv",
+and "physical". The simplest default is the "logical" system. Users
+wishing to correlate the output coordinates of objects measured in
+image sections or mosaic pieces with coordinates in the parent
+image must use the "tv" or "physical" coordinate systems.
+
+In interactive mode the user may either define the list of objects to be
+measured interactively with the image curspr or create an object list prior
+to running PHOT. In either case the user may adjust the centering, sky fitting,
+ and photometry algorithm parameters until a satisfactory fit is achieved
+and optionally store the final results in \fIoutput\fR. In batch mode the
+initial positions are read from the text file \fIcoords\fR or the image
+cursor parameter \fIicommands\fR can be redirected to a text file containing
+a list of cursor commands. In batch mode the current set of algorithm
+parameters is used.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If cacheing
+is enabled and PHOT is run interactively the first measurement will appear
+to take a long time as the entire image must be read in before the measurement
+is actually made. All subsequent measurements will be very fast because PHOT
+is accessing memory not disk. The point of cacheing is to speed up random
+image access by making the internal image i/o buffers the same size as the
+image itself. However if the input object lists are sorted in row order and
+sparse cacheing may actually worsen not improve the execution time. Also at
+present there is no point in enabling cacheing for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of cacheing in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halfs of the image are alternated.
+
+PHOT computes accurate centers for each object using the centering
+parameters defined in \fIcenterpars\fR, computes an accurate sky value
+for each object using the sky fitting parameters defined in \fIfitskypars\fR,
+and computes magnitudes using the photometry parameters defined in
+\fIphotpars\fR. The image data characteristics of the data are specified
+in \fIdatapars\fR.
+
+.ih
+CURSOR COMMANDS
+
+The following list of cursor commands are currently available.
+
+.nf
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+v Verify the critical parameters
+w Save the current parameters
+d Plot radial profile of current star
+i Interactively set parameters using current star
+c Fit center for current star
+t Fit sky around the cursor
+a Average sky values fit around several cursor positions
+s Fit sky around current centered star
+p Do photometry for current star, using current sky
+o Do photometry for current star, using current sky, output results
+f Do photometry for current star
+spbar Do photometry for current star, output results
+m Move to next star in coordinate list
+n Do photometry for next star in coordinate list, output results
+l Do photometry for remaining stars in coordinate list, output results
+e Print error messages
+r Rewind coordinate list
+q Exit task
+
+
+Photometry parameters are listed or set with the following commands.
+
+ Colon commands
+
+:show [data/center/sky/phot] List the parameters
+:m [n] Move to next [nth] star in coordinate list
+:n [n] Do photometry for next [nth] star in coordinate list, output results
+
+ Colon Parameter Editing Commands
+
+# Image and file name parameters
+
+:image [string] Image name
+:coords [string] Coordinate file name
+:output [string] Output file name
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Full width half maximum of PSF (scale units)
+:emission [y/n] Emission feature (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good data value (counts)
+:datamax [value] Maximum good data value (counts)
+
+# Noise parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per adu)
+:readnoise [value] Readout noise (electrons)
+
+# Observations parameters
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Integration time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observation (time units)
+
+# Centering algorithm parameters
+
+:calgorithm [string] Centering algorithm
+:cbox [value] Width of the centering box (scale units)
+:cthreshold [value] Centering intensity threshold (sigma)
+:cmaxiter [value] Maximum number of iterations
+:maxshift [value] Maximum center shift (scale units)
+:minsnratio [value] Minimum S/N ratio for centering
+:clean [y/n] Clean subraster before centering
+:rclean [value] Cleaning radius (scale units)
+:rclip [value] Clipping radius (scale units)
+:kclean [value] Clean K-sigma rejection limit (sigma)
+
+# Sky fitting algorithm parameters
+
+:salgorithm [string] Sky fitting algorithm
+:skyvalue [value] User supplied sky value (counts)
+:annulus [value] Inner radius of sky annulus (scale units)
+:dannulus [value] Width of sky annulus (scale units)
+:khist [value] Sky histogram extent (+/- sky sigma)
+:binsize [value] Resolution of sky histogram (sky sigma)
+:smooth [y/n] Lucy smooth the sky histogram
+:sloclip [value] Low-side clipping factor in percent
+:shiclip [value] High-side clipping factor in percent
+:smaxiter [value] Maximum number of iterations
+:snreject [value] Maximum number of rejection cycles
+:sloreject [value] Low-side pixel rejection limits (sky sigma)
+:shireject [value] High-side pixel rejection limits (sky sigma)
+:rgrow [value] Region growing radius (scale units)
+
+# Photometry parameters
+
+:apertures [string] List of aperture radii (scale units)
+:zmag [value] Zero point of magnitude scale
+
+# Plotting and marking parameters
+
+:mkcenter [y/n] Mark computed centers on display
+:mksky [y/n] Mark the sky annuli on the display
+:mkapert [y/n] Mark apertures on the display
+:radplot [y/n] Plot radial profile of object
+
+
+ Interactive Phot Setup Menu
+
+ v Mark and verify the critical parameters (f,s,c,a,d,r)
+
+ f Mark and verify the full-width half-maximum of psf
+ s Mark and verify the standard deviation of the background
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
+
+ c Mark and verify the centering box width
+ n Mark and verify the cleaning radius
+ p Mark and verify the clipping radius
+
+ a Mark and verify the inner radius of the sky annulus
+ d Mark and verify the width of the sky annulus
+ g Mark and verify the region growing radius
+
+ r Mark and verify the aperture radii
+.fi
+
+.ih
+ALGORITHMS
+
+A brief description of the data dependent parameters, centering algorithms,
+sky fitting algorithms and photometry parameters can be found in the
+online help pages for the DATAPARS, CENTERPARS, FITSKYPARS, and PHOTPARS
+tasks.
+
+.ih
+OUTPUT
+
+In interactive mode the following quantities are printed on the standard
+output as each object is measured. Err is a simple string indicating whether
+or not an error was detected in the centering algorithm, the sky fitting
+algorithm or the photometry algorithm. Mag are the magnitudes in apertures 1
+through N respectively and xcenter, ycenter and msky are the x and y centers
+and the sky value respectively.
+
+.nf
+ image xcenter ycenter msky mag[1 ... N] error
+.fi
+
+In both interactive and batch mode full output is written to the text file
+\fIoutput\fR. At the beginning of each file is a header listing the
+current values of the parameters when the first stellar record was written.
+These parameters can be subsequently altered. For each star measured the
+following record is written
+
+.nf
+ image xinit yinit id coords lid
+ xcenter ycenter xshift yshift xerr yerr cier error
+ msky stdev sskew nsky nsrej sier serror
+ itime xairmass ifilter otime
+ rapert sum area flux mag merr pier perr
+.fi
+
+Image and coords are the name of the image and coordinate file respectively.
+Id and lid are the sequence numbers of stars in the output and coordinate
+files respectively. Cier and cerror are the centering algorithm error code
+and accompanying error message respectively. Xinit, yinit, xcenter, ycenter,
+xshift, yshift, and xerr, yerr are self explanatory and output in pixel units.
+The sense of the xshift and yshift definitions is the following.
+
+.nf
+ xshift = xcenter - xinit
+ yshift = ycenter - yinit
+.fi
+
+Sier and serror are the sky fitting error code and accompanying error
+message respectively. Msky, stdev and sskew are the best estimate of the sky
+value (per pixel), standard deviation and skew respectively. Nsky and nsrej
+are the number of sky pixels and the number of sky pixels rejected respectively.
+
+Itime is the exposure time, xairmass is self-evident, ifilter is an
+id string identifying the filter used in the observations, and otime is
+a string containing the time of the observation in whatever units the
+user has set up.
+
+Rapert, sum, area, and flux are the radius of the aperture in scale units,
+the total number of counts including sky in the aperture, the area of the
+aperture in square pixels, and the total number of counts excluding sky
+in the aperture. Mag and merr are the magnitude and error in the magnitude
+in the aperture (see below).
+
+.nf
+ flux = sum - area * msky
+ mag = zmag - 2.5 * log10 (flux) + 2.5 * log10 (itime)
+ merr = 1.0857 * error / flux
+ error = sqrt (flux / epadu + area * stdev**2 +
+ area**2 * stdev**2 / nsky)
+.fi
+
+Pier and perror are photometry error code and accompanying error message.
+
+In interactive mode a radial profile of each measured object is plotted
+in the graphics window if \fIradplots\fR is "yes".
+
+In interactive and batchmode a radial profile plot is written to
+\fIplotfile\fR if it is defined each time the result of an object
+measurement is written to \fIoutput\fR .
+
+.ih
+ERRORS
+
+If the object centering was error free then the field cier will be zero.
+Non-zero values of cier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 101 # The centering box is off image
+ 102 # The centering box is partially off the image
+ 103 # The S/N ratio is low in the centering box
+ 104 # There are two few points for a good fit
+ 105 # The x or y center fit is singular
+ 106 # The x or y center fit did not converge
+ 107 # The x or y center shift is greater than maxshift
+ 108 # There is bad data in the centering box
+.fi
+
+If all goes well during the sky fitting process then the error code sier
+will be 0. Non-zero values of sier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 201 # There are no sky pixels in the sky annulus
+ 202 # Sky annulus is partially off the image
+ 203 # The histogram of sky pixels has no width
+ 204 # The histogram of sky pixels is flat or concave
+ 205 # There are too few points for a good sky fit
+ 206 # The sky fit is singular
+ 207 # The sky fit did not converge
+ 208 # The graphics stream is undefined
+ 209 # The file of sky values does not exist
+ 210 # The sky file is at EOF
+ 211 # Cannot read the sky value correctly
+ 212 # The best fit parameter are non-physical
+.fi
+
+If no error occursor during the measurement of the magnitudes then pier is
+0. Non-zero values of pier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 301 # The aperture is off the image
+ 302 # The aperture is partially off the image
+ 303 # The sky value is undefined
+ 305 # There is bad data in the aperture
+.fi
+
+.ih
+EXAMPLES
+
+1. Compute the magnitudes for a few stars in dev$ypix using the display
+and the image cursor. Setup the task parameters using the interactive
+setup menu defined by the i key command and a radial profile plot.
+
+.nf
+ ap> display dev$ypix 1 fi+
+
+ ... display the image
+
+ ap> phot dev$ypix
+
+ ... type ? to print an optional help page
+
+ ... move the image cursor to a star
+ ... type i to enter the interactive setup menu
+ ... enter maximum radius in pixels of the radial profile or hit
+ CR to accept the default
+ ... set the fwhmpsf, centering radius, inner and outer sky annuli,
+ photometry apertures, and sigma using the graphics cursor and
+ the stellar radial profile plot
+ ... typing <CR> leaves everything at the default value
+ ... type q to quit the setup menu
+
+ ... type the v key to verify the parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... move the image cursor to the stars of interest and tap
+ the space bar
+
+ ... a one line summary of the fitted parameters will appear on the
+ standard output for each star measured
+
+ ... type q to quit and q again to confirm the quit
+
+ ... the output will appear in ypix.mag.1
+.fi
+
+2. Compute the magnitudes for a few stars in dev$ypix using a contour plot
+and the graphics cursor. This option is only useful for those (now very few)
+users who have access to a graphics terminal but not to an image display
+server. Setup the task parameters using the interactive setup menu defined by
+the i key command as in example 1.
+
+.nf
+ ap> show stdimcur
+
+ ... record the default value of stdimcur
+
+ ap> set stdimcur = stdgraph
+
+ ... define the image cursor to be the graphics cursor
+
+ ap> contour dev$ypix
+
+ ... make a contour plot of dev$ypix
+
+ ap> contour dev$ypix >G ypix.plot1
+
+ ... store the contour plot of dev$ypix in the file ypix.plot1
+
+ ap> phot dev$ypix display=stdgraph
+
+ ... type ? to get an optional help page
+
+ ... move graphics cursor to a star
+ ... type i to enter the interactive setup menu
+ ... enter maximum radius in pixels of the radial profile or CR
+ to accept the default value
+ ... set the fwhmpsf, centering radius, inner and outer sky annuli,
+ apertures, and sigma using the graphics cursor and the
+ stellar radial profile plot
+ ... typing <CR> leaves everything at the default value
+ ... type q to quit the setup menu
+
+ ... type the v key to verify the critical parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... retype :.read ypix.plot1 to reload the contour plot
+
+ ... move the graphics cursor to the stars of interest and tap
+ the space bar
+
+ ... a one line summary of the fitted parameters will appear on the
+ standard output for each star measured
+
+ ... type q to quit and q again to verify
+
+ ... full output will appear in the text file ypix.mag.2
+
+ ap> set stdimcur = <default>
+
+ ... reset stdimcur to its previous value
+.fi
+
+
+3. Setup and run PHOT interactively on a list of objects temporarily
+overriding the fwhmpsf, sigma, cbox, annulus, dannulus, and apertures
+parameters determined in examples 1 or 2.
+
+.nf
+ ap> daofind dev$ypix fwhmpsf=2.6 sigma=25.0 verify-
+
+ ... make a coordinate list
+
+ ... the output will appear in the text file ypix.coo.1
+
+ ap> phot dev$ypix cbox=7.0 annulus=12.0 dannulus=5.0 \
+ apertures="3.0,5.0" coords=ypix.coo.1
+
+ ... type ? for optional help
+
+
+ ... move the graphics cursor to the stars and tap space bar
+
+ or
+
+ ... select stars from the input coordinate list with m / :m #
+ and measure with spbar
+
+ ... measure stars selected from the input coordinate list
+ with n / n #
+
+ ... a one line summary of results will appear on the standard output
+ for each star measured
+
+ ... type q to quit and q again to confirm the quit
+
+ ... the output will appear in ypix.mag.3 ...
+.fi
+
+
+4. Display and measure some stars in an image section and write the output
+coordinates in the coordinate system of the parent image.
+
+.nf
+ ap> display dev$ypix[150:450,150:450] 1
+
+ ... display the image section
+
+ ap> phot dev$ypix[150:450,150:450] wcsout=tv
+
+ ... move cursor to stars and type spbar
+
+ ... type q to quit and q again to confirm quit
+
+ ... output will appear in ypix.mag.4
+
+ ap> pdump ypix.mag.4 xc,yc yes | tvmark 1 STDIN col=204
+.fi
+
+5. Run PHOT in batch mode using the coordinate file and the previously
+saved parameters. Verify the critical parameters.
+
+.nf
+ ap> phot dev$ypix coords=ypix.coo.1 verify+ inter-
+
+ ... output will appear in ypix.mag.5 ...
+.fi
+
+6. Repeat example 5 but assume that the input coordinate are ra and dec
+in degrees and degrees, turn off verification, and submit the task to to
+the background.
+
+.nf
+ ap> display dev$ypix 1
+
+ ap> rimcursor wcs=world > radec.coo
+
+ ... move to selected stars and type any key
+
+ ... type ^Z to quit
+
+ ap> phot dev$ypix coords=radec.coo wcsin=world verify- inter- &
+
+ ... output will appear in ypix.mag.6
+
+ ap> pdump ypix.mag.6 xc,yc yes | tvmark 1 STDIN col=204
+
+ ... mark the stars on the display
+.fi
+
+
+7. Run PHOT interactively without using the image display.
+
+.nf
+ ap> show stdimcur
+
+ ... record the default value of stdimcur
+
+ ap> set stdimcur = text
+
+ ... set the image cursor to the standard input
+
+ ap> phot dev$ypix coords=ypix.coo.1
+
+ ... type ? for optional help
+
+ ... type :m 3 to set the initial coordinates to those of the
+ third star in the list
+
+ ... type i to enter the interactive setup menu
+ ... enter the maximum radius in pixels for the radial profile or
+ accept the default with a CR
+ ... type v to enter the default menu
+ ... set the fwhmpsf, centering radius, inner and outer sky annuli,
+ apertures, and sigma using the graphics cursor and the
+ stellar radial profile plot
+ ... typing <CR> after the prompt leaves the parameter at its default
+ value
+ ... type q to quit the setup menu
+
+ ... type r to rewind the coordinate list
+
+ ... type l to measure all the stars in the coordinate list
+
+ ... a one line summary of the answers will appear on the standard
+ output for each star measured
+
+ ... type q to quit followed by q to confirm the quit
+
+ ... full output will appear in the text file ypix.mag.7
+
+ ap> set stdimcur = <default>
+
+ ... reset the value of stdimcur
+.fi
+
+8. Use a image cursor command file to drive the PHOT task. The cursor command
+file shown below sets the cbox, annulus, dannulus, and apertures parameters
+computes the centers, sky values, and magnitudes for 3 stars, updates the
+parameter files, and quits the task.
+
+.nf
+ ap> type cmdfile
+ : cbox 9.0
+ : annulus 12.0
+ : dannulus 5.0
+ : apertures 5.0
+ 442 410 101 \040
+ 349 188 101 \040
+ 225 131 101 \040
+ w
+ q
+
+ ap> phot dev$ypix icommands=cmdfile verify-
+
+ ... full output will appear in ypix.mag.8
+.fi
+
+
+.ih
+BUGS
+
+It is currently the responsibility of the user to make sure that the
+image displayed in the frame is the same as that specified by the image
+parameter.
+
+Commands which draw to the image display are disabled by default.
+To enable graphics overlay on the image display, set the display
+parameter to "imdr", "imdg", "imdb", or "imdy" to get red, green,
+blue or yellow overlays and set the centerpars mkcenter switch to
+"yes", the fitskypars mksky switch to"yes", or the photpars mkapert
+switch to "yes". It may be necessary to run gflush and to redisplay the image
+to get the overlays position correctly.
+
+.ih
+SEE ALSO
+datapars, centerpars, fitskypars, photpars, qphot, wphot, polyphot
+.endhelp
diff --git a/noao/digiphot/apphot/doc/photpars.hlp b/noao/digiphot/apphot/doc/photpars.hlp
new file mode 100644
index 00000000..0a172ba3
--- /dev/null
+++ b/noao/digiphot/apphot/doc/photpars.hlp
@@ -0,0 +1,102 @@
+.help photpars May00 noao.digiphot.apphot
+.ih
+NAME
+photpars -- edit the photometry parameters
+.ih
+USAGE
+photpars
+.ih
+PARAMETERS
+.ls weighting = "constant"
+The type of weighting for the WPHOT task. The weighting parameter is
+ignored by the PHOT task. The options are:
+.ls constant
+Uniform weights of 1 for each pixel are used.
+.le
+.ls cone
+A conical weighting function of full width half maximum \fIfwhmpsf\fR as
+defined in the DATAPARS parameter set is used.
+.le
+.ls gauss
+A Gaussian weighting function of full width half maximum \fIfwhmpsf\fR as
+defined in the DATAPARS parameter set is used.
+.le
+.le
+.ls apertures = "3" (scale units)
+A list of aperture radii in units of the scale parameter or the name of the
+file containing the list of aperture radii. List elements may be separated by
+whitespace or commas. A range syntax of the form ap1:apN:apstep is also
+supported.
+.le
+.ls zmag = 25.00
+The zero point offset for the magnitude scale.
+.le
+.ls mkapert = no
+Mark the photometry apertures on the displayed image ?
+.le
+
+.ih
+DESCRIPTION
+
+The integral of the flux within the circular apertures specified by
+\fIapertures\fR is computed by summing pixels in the aperture with
+the specified weighting function \fIweighting\fR. The fraction of each pixel
+lying within the aperture is computed by an approximation and all the
+approximations are summed. The zero point of the magnitude
+scale is determined by \fIzmag\fR.
+
+\fRApertures\fR is specified in units of the image scale. If \fIscale\fR
+is specified in units of the half-width at half-maximum of the point
+spread function the aperture per pixel a single value of apertures
+will work well on images with differing psfs.
+
+.ih
+EXAMPLES
+
+1. List the PHOTPARS parameters.
+
+.nf
+ da> lpar photpars
+.fi
+
+2. Edit the PHOTPARS parameters.
+
+.nf
+ da> photpars
+.fi
+
+3. Edit the PHOTPARS parameters from within the PHOT task.
+
+.nf
+ da> epar phot
+
+ ... edit a few phot parameters
+
+ ... move to the photpars parameter and type :e
+
+ ... edit the photpars parameters and type :wq
+
+ ... finish editing the phot parameters and type :wq
+
+.fi
+
+4. Save the current PHOTPARS parameter set in a text file photnite1.par.
+This can also be done from inside a higher level task as in the
+above example.
+
+.nf
+ da> photpars
+
+ ... edit some parameters
+
+ ... type ":w photnite1.par" from within epar
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+phot,wphot,radprof
+.endhelp
diff --git a/noao/digiphot/apphot/doc/polymark.hlp b/noao/digiphot/apphot/doc/polymark.hlp
new file mode 100644
index 00000000..e88bc089
--- /dev/null
+++ b/noao/digiphot/apphot/doc/polymark.hlp
@@ -0,0 +1,430 @@
+.help polymark May00 noao.digiphot.apphot
+.ih
+NAME
+polymark -- create or review polygon and coordinate lists for input to the
+polyphot task
+.ih
+USAGE
+polymark image
+.ih
+PARAMETERS
+.ls images
+The list of input images used to define the polygons.
+.le
+.ls coords = "default"
+The input / output center positions file. The center positions for each
+polygonal aperture are read from or written to coords. There may more than one
+center position per polygon. Center positions are written to coords 1 center
+position per line. When the current polygon changes POLYMARK inserts a line
+containing a single ';' after the last center position. If coords is
+"default", "dir$default" or a directory specification then a center position
+file name of the form dir$root.extension.version is constructed, where dir is
+the directory, root is the root image name, extension is "coo" and version is
+the next available version of the file.
+.le
+.ls polygons = "default"
+The name of the polygons file. The vertices of each polygon are read from or
+written to the polygons file. The polygons file contains a list of the
+polygon vertices. Each vertex list is terminated by a line containing a ';'
+after the last vertex. If polygons is "default", "dir$default" or a directory
+specification then an output name of the form dir$root.extension.version is
+constructed, where dir is the directory, root is the root image name, extension
+is "ver" and the version is next available version of the file. The number of
+polygon files must be equal to the number of image files.
+.le
+.ls icommands = ""
+The image cursor or image cursor command file.
+.le
+.ls gcommands = ""
+The graphics cursor or graphics cursor command file.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout"
+The coordinate system of the input coordinates read from or written
+to \fIcoords\fR and \fIpolygons\fR. The image header coordinate system is
+used to transform from the input coordinate system to the "logical" pixel
+coordinate system used internally, and from the internal "logical" pixel
+coordinate system to the output coordinate system. The input coordinate
+system options are "logical", tv", "physical", and "world". The output
+coordinate system options are "logical", "tv", and "physical". The image
+cursor coordinate system is assumed to be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin and wcsout are "logical" and "logical" respectively.
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default cacheing is
+disabled.
+.le
+.ls graphics = ")_.graphics"
+The standard graphics device.
+.le
+.ls display = ")_.display"
+The default display device. Display may be set to the apphot package
+parameter value (the default), "yes", or "no. By default graphics overlay is
+disabled. Setting display to one of "imdr", "imdg", "imdb", or "imdy" enables
+graphics overlay with the IMD graphics kernel. Setting display to
+"stdgraph" enables POLYMARK to work interactively from a contour plot.
+.le
+
+.ih
+DESCRIPTION
+
+POLYMARK creates and / or displays center position and polygons files
+suitable for input to POLYPHOT. For each image in the input list POLYMARK
+creates a polygons file \fIpolygons\fR and center positions file \fIcoords\fR,
+if these do not already exist. The format of the polygons and center
+position files is described in the OUTPUT section.
+
+Polygonal apertures are defined and drawn on the image display using
+the image display cursor and then shifted to the desired center
+using the image display cursor. At any point in the marking process
+the user may rewind the polygon and coordinate file and draw the previously
+defined polygons on the display.
+
+The coordinates read from \fIpolygons\fR or \fIcoords\fR are assumed to be
+in coordinate system defined by \fIwcsin\fR. The options are "logical", "tv",
+"physical", and "world" and the transformation from the input coordinate
+system to the internal "logical" system is defined by the image coordinate
+system. The simplest default is the "logical" pixel system. Users working on
+with image sections but importing pixel coordinate lists generated from the
+parent image must use the "tv" or "physical" input coordinate systems.
+Users importing coordinate lists in world coordinates, e.g. ra and dec,
+must use the "world" coordinate system and may need to convert their
+equatorial coordinate units from hours and degrees to degrees and degrees first.
+
+The coordinates written to \fIpolygons\fR or \fIcoords\fR are in the coordinate
+system defined by \fIwcsout\fR. The options are "logical", "tv", and
+"physical". The simplest default is the "logical" system. Users
+wishing to correlate the output coordinates of objects measured in
+image sections or mosaic pieces with coordinates in the parent
+image must use the "tv" or "physical" coordinate systems.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If cacheing
+is enabled and POLYMARK is run interactively the first measurement will appear
+to take a long time as the entire image must be read in before the measurement
+is actually made. All subsequent measurements will be very fast because POLYMARK
+is accessing memory not disk. The point of cacheing is to speed up random
+image access by making the internal image i/o buffers the same size as the
+image itself. However if the input object lists are sorted in row order and
+sparse cacheing may actually worsen not improve the execution time. Also at
+present there is no point in enabling cacheing for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of cacheing in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halfs of the image are alternated.
+.ih
+CURSOR COMMANDS
+
+The following interactive keystroke and colon commands are available.
+
+.nf
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+d Plot radial profile of star near cursor
+g Define the current polygonal aperture
+f Draw the current polygon on the display
+spbar Draw the current polygon on the display, output the polygon
+r Rewind the polygon list
+m Draw the next polygon in the polygon list on the display
+l Draw all the remaining polygons in the list on the display
+q Exit
+
+ Colon commands
+
+:m [n] Draw the next [nth] polygon in the polygon list on the display
+.fi
+
+.ih
+OUTPUT
+
+A sample polygons file and accompanying coordinates file is listed below.
+
+.nf
+ # Sample Polygons File (2 polygons)
+
+ 200.5 200.5
+ 300.5 200.5
+ 300.5 300.5
+ 200.5 300.5
+ ;
+ 100.4 100.4
+ 120.4 100.4
+ 120.4 120.4
+ 100.4 120.4
+ ;
+.fi
+
+.nf
+ # Sample Coordinates File (2 groups, 1 for each polygon)
+
+ 123.4 185.5
+ 110.4 130.4
+ 150.9 200.5
+ ;
+ 85.6 35.7
+ 400.5 300.5
+ 69.5 130.5
+ ;
+.fi
+
+.ih
+EXAMPLES
+
+1. Create a coordinate list and polygon file using the image display and
+image display cursor. Use polymark to both create and display the
+polygon and polygon center lists.
+
+.nf
+ ap> display dev$ypix 1 fi+
+
+ ... display the image
+
+ ap> polymark dev$ypix display=imdg
+
+ ... type ? for an optional help page
+
+ ... type g to enter the "define a polygon" menu
+ ... move the cursor to the first vertex, tap the space bar
+ to mark the vertex, and repeat for each vertex
+ ... type q to quit the "define a polygon" menu
+ ... mark each vertex only once, POLYPHOT will close the
+ polygon for you
+
+ ... move the cursor to the desired polygon center and
+ tap the space bar to record the polygon
+ ... repeat for all desired polygon centers
+
+ ... type g to define the next polygon
+ ... move the cursor to the first vertex, tap the space bar
+ to mark the vertex and repeat for each vertex
+ ... type q to quit the polygon menu
+ ... mark each vertex only once, POLYPHOT will close the
+ polygon for you
+
+ ... move the cursor to the desired polygon center and
+ tap the space bar
+ ... repeat for all desired polygon centers
+
+ ... type q to quit and q to confirm the quit
+
+ ... output will appear in ypix.coo.1 and ypix.ver.1
+
+
+ ap> display dev$ypix 2 fi+
+
+ ... display the image
+
+ ap> polymark dev$ypix coords=ypix.coo.1 polygons=ypix.ver.1 \
+ display=imdg
+
+ ... type m to mark the first polygon / polygon center on the display
+
+ ... type m to mark the next polygon / polygon center on the display
+
+ ... type l to mark the remaining polygons
+
+ ... type q to quit and q to confirm the quit
+
+
+ ap> display dev$ypix 2 fi+
+
+ ... redisplay the image
+
+ ap> polymark dev$ypix coords="" polygons=ypix.ver.1 \
+ display=imdg
+
+ ... type l to mark the polygon list, note that since there is
+ no coords file the polygons are not shifted
+
+ ... type q to quit and q to confirm the quit
+.fi
+
+
+2. Repeat the previous example using an image section.
+
+.nf
+ ap> display dev$ypix[150:450,150:450] 1 fi+
+
+ ... display the image
+
+
+ ap> polymark dev$ypix[150:450,150:450]] display=imdg wcsout=tv
+
+ ... type ? for an optional help page
+
+ ... type g to enter the "define a polygon" menu
+ ... move the cursor to the first vertex, tap the space bar
+ to mark the vertex, and repeat for each vertex
+ ... type q to quit the "define a polygon" menu
+ ... mark each vertex only once, POLYPHOT will close the
+ polygon for you
+
+ ... move the cursor to the desired polygon center and
+ tap the space bar to record the polygon
+ ... repeat for all desired polygon centers
+
+ ... type g to define the next polygon
+ ... move the cursor to the first vertex, tap the space bar
+ to mark the vertex and repeat for each vertex
+ ... type q to quit the polygon menu
+ ... mark each vertex only once, POLYPHOT will close the
+ polygon for you
+
+ ... move the cursor to the desired polygon center and
+ tap the space bar
+ ... repeat for all desired polygon centers
+
+ ... type q to quit and q to confirm the quit
+
+ ... output will appear in ypix.coo.2 and ypix.ver.2
+
+
+ ap> display dev$ypix[150:450,150:450] 2 fi+
+
+ ... display the image
+
+
+ ap> polymark dev$ypix[150:450,150:450] coords=ypix.coo.2 \
+ polygons=ypix.ver.2 display=imdg wcsin=tv
+
+ ... type m to mark the first polygon / polygon center on the display
+
+ ... type m to mark the next polygon / polygon center on the display
+
+ ... type l to mark the remaining polygons
+
+.fi
+
+
+3. Repeat example 1 using a contour plot instead of the image display.
+
+.nf
+ ap> show stdimcur
+
+ ... record the default value of stdimcur
+
+ ap> set stdimcur = stdgraph
+
+ ... define the image cursor to be the graphics cursor
+
+ ap> contour dev$ypix
+
+ ... draw a contour plot on the screen
+
+ ap> contour dev$ypix >G ypix.plot1
+
+ ... store the contour plot of dev$ypix in the file ypix.plot1
+
+ ap> polymark dev$ypix display=stdgraph
+
+ ... type g to enter the define a polygon menu
+ ... move the cursor to the first vertex, tap the space bar
+ to mark the vertex, and repeat for each vertex
+ ... type q to quit the define a polygon menu
+ ... mark each vertex only once, POLYPHOT will close the
+ polygon for you
+
+ ... move the cursor to the desired polygon center and
+ tap the space bar to record the polygon
+ ... repeat for all desired polygon centers
+
+ ... type g to define the next polygon
+ ... move the cursor to the first vertex, tap the space bar
+ to mark the vertex and repeat for each vertex
+ ... type q to quit the define a polygon menu
+ ... mark each vertex only once, POLYPHOT will close the
+ polygon for you
+
+ ... move the cursor to the desired polygon center and
+ tap the space bar
+ ... repeat for all desired polygon centers
+
+ ... type r to rewind the coordinate and polygon lists
+
+ ... type :.read ypix.plot1 to reread the contour plot
+
+ ... type l to display all the polygons ...
+
+ ... type q to quit and q again to confirm the quit
+
+ ... output will appear in ypix.ver.3 and ypix.coo.3
+
+ ap> contour dev$ypix
+
+ ... redraw the contour plot
+
+ ap> polymark dev$ypix coords="ypix.coo.3" polygons=ypix.ver.3 \
+ display=stdgraph
+
+ ap> set stdimcur = <default>
+
+ ... reset the value of the stdimcur parameter
+.fi
+
+.ih
+BUGS
+
+It is the responsibility of the user to make sure that the image displayed
+in the image display is the same as the image specified by the image parameter.
+
+Commands which draw to the image display are disabled by default. To enable
+graphics overlay on the image display, set the display parameter to "imdr",
+"imdg", "imdb", or "imdy" to get red, green, blue or yellow overlays. It
+may be necessary to run gflush and to redisplay the image to get the overlays
+position correctly.
+
+There are no restrictions on the shape of the polygon but the vertices
+must be listed in order either clockwise or counterclockwise in the
+polygons file.
+
+It is not necessary to close the polygon when drawing on the display.
+POLYMARK will complete the polygon for you.
+
+.ih
+SEE ALSO
+polyphot
+.endhelp
diff --git a/noao/digiphot/apphot/doc/polypars.hlp b/noao/digiphot/apphot/doc/polypars.hlp
new file mode 100644
index 00000000..e31e4dcd
--- /dev/null
+++ b/noao/digiphot/apphot/doc/polypars.hlp
@@ -0,0 +1,69 @@
+.help polypars May00 noao.digiphot.apphot
+.ih
+NAME
+polypars -- edit the polygonal aperture photometry parameters
+.ih
+USAGE
+polypars
+.ih
+PARAMETERS
+.ls zmag = 25.00
+The zero point offset for the magnitude scale.
+.le
+.ls mkpolygon = no
+Draw the polygons on the screen.
+.le
+.ih
+DESCRIPTION
+The zero point of the magnitude scale is determined by \fIzmag\fR.
+
+If the \fImkpolygon\fR switch is enabled polygons are marked on the screen.
+.ih
+EXAMPLES
+
+1. List the polygonal aperture photometry parameters.
+
+.nf
+ ap> lpar polypars
+.fi
+
+2. Edit the polygonal aperture photometry parameters.
+
+.nf
+ ap> polypars
+.fi
+
+3. Edit the POLYPARS parameters from within the POLYPHOT task.
+
+.nf
+ da> epar polyphot
+
+ ... edit a few polyphot parameters
+
+ ... move to the polypars parameter and type :e
+
+ ... edit the polypars parameters and type :wq
+
+ ... finish editing the polyphot parameters and type :wq
+.fi
+
+4. Save the current POLYPARS parameter set in a text file polynite1.par.
+This can also be done from inside a higher level task as in the
+above example.
+
+.nf
+ da> polypars
+
+ ... edit some parameters
+
+ ... type ":w polynite1.par" from within epar
+
+.fi
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+polyphot. polymark
+.endhelp
diff --git a/noao/digiphot/apphot/doc/polyphot.hlp b/noao/digiphot/apphot/doc/polyphot.hlp
new file mode 100644
index 00000000..8bec19d4
--- /dev/null
+++ b/noao/digiphot/apphot/doc/polyphot.hlp
@@ -0,0 +1,791 @@
+.help polyphot May00 noao.digiphot.apphot
+.ih
+NAME
+polyphot -- compute magnitudes inside polygonal apertures
+.ih
+USAGE
+polyphot image
+.ih
+PARAMETERS
+.ls image
+The list of images containing the objects to be measured.
+.le
+.ls coords = ""
+The list of text files containing the center coordinates of the polygons
+to be measured. Polygon centers are listed one per line with the x and y
+coordinates in columns one and two. A ";" character in column terminates
+the polygon center list for the current polygon and tells POLYPHOT to skip
+to the next polygon listed in \fIpolygons\fR. If coords is undefined the
+polygons are not shifted. The number of polygon center files must be
+zero, one, or equal to the number of images. If coords is "default",
+"dir$default", or a directory specification then a coords file name
+of the form dir$root.extension.version is constructed and searched for,
+where dir is the directory, root is the root image name, extension is "coo"
+and version is the next available version number for the file.
+.le
+.ls polygons = ""
+The list of text files containing the vertices of the polygons to be
+measured. The polygon vertices are listed 1 vertext per line with the x and y
+coordinates of each vertex in columns 1 and 2. The vertices list is terminated
+a ';' in column 1. The number of polygon files must be zero, one, or
+equal to the number of images. If polygons is "default", "dir$default", or
+a directory specification then a coords file name of the form
+dir$root.extension.version is constructed and searched for, where dir is the
+directory, root is the root image name, extension is "ver"
+and version is the next available version number for the file.
+.le
+.ls output = "default"
+The name of the results file or results directory. If output is
+"default", "dir$default", or a directory specification then an output file name
+of the form dir$root.extension.version is constructed, where dir is the
+directory, root is the root image name, extension is "ply" and version is
+the next available version number for the file. The number of output files
+must be zero, one, or equal to the number of image files. In both interactive
+and batch mode full output is written to output. In interactive mode
+an output summary is also written to the standard output.
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters. The critical
+parameters \fIfwhmpsf\fR and \fIsigma\fR are located here. If \fIdatapars\fR
+is undefined then the default parameter set in uparm directory is used.
+.le
+.ls centerpars = ""
+The name of the file containing the centering parameters. The critical
+parameters \fIcalgorithm\fR and \fIcbox\fR are located here.
+If \fIcenterpars\fR is undefined then the default parameter set in
+uparm directory is used.
+.le
+.ls fitskypars = ""
+The name of the text file containing the sky fitting parameters. The critical
+parameters \fIsalgorithm\fR, \fIannulus\fR, and \fIdannulus\fR are located here.
+If \fIfitskypars\fR is undefined then the default parameter set in uparm
+directory is used.
+.le
+.ls polypars = ""
+The name of the text file containing the polygon photometry parameters,
+If \fIpolypars\fR is undefined then the default parameter set in
+ uparm directory is used.
+.le
+.ls interactive = yes
+Run the task interactively ?
+.le
+.ls icommands = ""
+The image cursor or image cursor command file.
+.le
+.ls gcommands = ""
+The graphics cursor or graphics cursor command file.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout"
+The coordinate system of the input coordinates read from \fIcoords\fR and
+of the output coordinates written to \fIoutput\fR respectively. The image
+header coordinate system is used to transform from the input coordinate
+system to the "logical" pixel coordinate system used internally,
+and from the internal "logical" pixel coordinate system to the output
+coordinate system. The input coordinate system options are "logical", tv",
+"physical", and "world". The output coordinate system options are "logical",
+"tv", and "physical". The image cursor coordinate system is assumed to
+be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin and wcsout are "logical" and "logical" respectively.
+.le
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default cacheing is
+disabled.
+.le
+.ls verify = ")_.verify"
+Verify the critical parameters in non-interactive mode ? Verify may be set to
+the apphot package parameter value (the default), "yes", or "no.
+.le
+.ls update = ")_.update"
+Update the critical parameters in non-interactive mode if verify is yes ?
+Update may be set to the apphot package parameter value (the default), "yes",
+or "no.
+.le
+.ls verbose = ")_.verbose"
+Print messages in non-interactive mode? Verbose may be set to the apphot
+package parameter value (the default), "yes", or "no.
+.le
+.ls graphics = ")_.graphics"
+The default graphics device. Graphics may be set to the apphot package
+parameter value (the default), "yes",
+or "no.
+.le
+.ls display = ")_.display"
+The default display device. By default graphics overlay is disabled. Display
+may be set to the apphot package parameter value (the default), "yes", or "no.
+Setting display to one of "imdr", "imdg", "imdb", or "imdy" enables graphics
+overlay with the IMD graphics kernel. Setting display to "stdgraph" enables
+POLYPHOT to work interactively from a contour plot.
+.le
+
+.ih
+DESCRIPTION
+
+POLYPHOT computes the magnitude of objects in the IRAF image \fIimage\fR
+inside a list of polygonal apertures whose vertices are listed in the text file
+\fIpolygons\fR or are marked on the display interactively with the
+image cursor. The polygon centers may be read from the polygon center
+file \fIcoords\fR or set interactively with the image cursor.
+
+The coordinates read from \fIcoords\fR are assumed to be in coordinate
+system defined by \fIwcsin\fR. The options are "logical", "tv", "physical",
+and "world" and the transformation from the input coordinate system to
+the internal "logical" system is defined by the image coordinate system.
+The simplest default is the "logical" pixel system. Users working on with
+image sections but importing pixel coordinate lists generated from the parent
+image must use the "tv" or "physical" input coordinate systems.
+Users importing coordinate lists in world coordinates, e.g. ra and dec,
+must use the "world" coordinate system and may need to convert their
+equatorial coordinate units from hours and degrees to degrees and degrees first.
+
+The coordinates written to \fIoutput\fR are in the coordinate
+system defined by \fIwcsout\fR. The options are "logical", "tv",
+and "physical". The simplest default is the "logical" system. Users
+wishing to correlate the output coordinates of objects measured in
+image sections or mosaic pieces with coordinates in the parent
+image must use the "tv" or "physical" coordinate systems.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If cacheing
+is enabled and POLYPHOT is run interactively the first measurement will appear
+to take a long time as the entire image must be read in before the measurement
+is actually made. All subsequent measurements will be very fast because POLYPHOT
+is accessing memory not disk. The point of cacheing is to speed up random
+image access by making the internal image i/o buffers the same size as the
+image itself. However if the input object lists are sorted in row order and
+sparse cacheing may actually worsen not improve the execution time. Also at
+present there is no point in enabling cacheing for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of cacheing in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halfs of the image are alternated.
+
+In interactive mode the user may either define the list of objects to be
+measured interactively with the image cursor or create a polygon and polygon
+center list prior to running POLYPHOT. In either case the user may adjust
+the centering, sky fitting, and photometry algorithm parameters until a
+satisfactory fit is achieved and optionally store the final results
+in \fIoutput\fR. In batch mode the polygon and polygon centers are read
+from the text files \fIpolygons\fR and \fIcoords\fR or the image cursor
+parameter \fIicommands\fR can be redirected to a text file containing
+a list of cursor commands. In batch mode the current set of algorithm
+parameters is used.
+
+.ih
+THE POLYGON and POLYGON CENTERS FILES
+
+A sample polygons file and accompanying coordinates file is listed below.
+
+.nf
+ # Sample Polygons File (2 polygons)
+
+ 200.5 200.5
+ 300.5 200.5
+ 300.5 300.5
+ 200.5 300.5
+ ;
+ 100.4 100.4
+ 120.4 100.4
+ 120.4 120.4
+ 100.4 120.4
+ ;
+.fi
+
+.nf
+ # Sample Coordinates File (2 groups, 1 for each polygon)
+
+ 123.4 185.5
+ 110.4 130.4
+ 150.9 200.5
+ ;
+ 85.6 35.7
+ 400.5 300.5
+ 69.5 130.5
+ ;
+.fi
+
+
+.ih
+CURSOR COMMANDS
+
+The following polyphot commands are currently available.
+
+.nf
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+v Verify the critical parameters
+w Store the current parameters
+d Plot radial profile of current object
+i Define current polygon, graphically set parameters using current object
+g Define current polygon
+c Fit center for current object
+t Fit sky around cursor
+a Average sky values fit around several cursor positions
+s Fit sky around current object
+h Do photometry for current polygon
+j Do photometry for current polygon, output results
+p Do photometry for current object using current sky
+o Do photometry for current object using current sky, output results
+f Do photometry for current object
+spbar Do photometry for current object, output results
+m Move to next object in coordinate list
+n Do photometry for next object in coordinate list, output results
+l Do photometry for remaining objects in list, output results
+r Rewind the polygon list
+e Print error messages
+q Exit task
+
+
+ Colon Commands
+
+:show [data/center/sky/phot] List the parameters
+:m [n] Move to next [nth] object in coordinate list
+:n [n] Do photometry for next [nth] object in coordinate list, output results
+
+
+ Colon Parameter Editing Commands
+
+# Image and file name parameters
+
+:image [string] Image name
+:polygon [string] Polygon file
+:coords [string] Coordinate file
+:output [string] Results file
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Full-width half-maximum of PSF (scale units)
+:emission [y/n] Emission feature (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good pixel value (counts)
+:datamax [value] Maximum good pixel value (counts)
+
+# Noise parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per count)
+:epadu [value] Readout noise (electrons)
+
+# Observing parameters
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Integration time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observation (time units)
+
+# Centering algorithm parameters
+
+:calgorithm [string] Centering algorithm
+:cbox [value] Width of centering box (scale units)
+:cthreshold [value] Centering intensity threshold (sigma)
+:cmaxiter [value] Maximum number of iterations
+:maxshift [value] Maximum center shift (scale units)
+:minsnratio [value] Minimum S/N ratio for centering
+:clean [y/n] Clean subraster before centering
+:rclean [value] Cleaning radius (scale units)
+:rclip [value] Clipping radius (scale units)
+:kclean [value] Clean K-sigma rejection limit (sigma)
+
+# Sky fitting algorithm parameters
+
+:salgorithm [string] Sky fitting algorithm
+:skyvalue [value] User supplied sky value (counts)
+:annulus [value] Inner radius of sky annulus (scale units)
+:dannulus [value] Width of sky annulus (scale units)
+:khist [value] Sky histogram extent (+/- sigma)
+:binsize [value] Resolution of sky histogram (sigma)
+:sloclip [value] Low-side clipping factor in percent
+:shiclip [value] High-side clipping factor in percent
+:smooth [y/n] Lucy smooth the sky histogram
+:smaxiter [value] Maximum number of iterations
+:snreject [value] Maximum number of rejection cycles
+:sloreject [value] Low-side pixel rejection limits (sky sigma)
+:shireject [value] High-side pixel rejection limits (sky sigma)
+:rgrow [value] Region growing radius (scale units)
+
+# Photometry parameters
+
+:zmag [value] Zero point of magnitude scale
+
+# Plotting and marking parameters
+
+:mkcenter [y/n] Mark computed centers on the display
+:mksky [y/n] Mark the sky annuli on the display
+:mkpolygon [y/n] Mark the polygon on the display
+
+
+
+The following commands are available from inside the interactive setup menu.
+
+
+ Interactive Photometry Setup Menu
+
+ v Mark and verify the critical parameters (f,c,s,a,d)
+
+ f Mark and verify the psf full-width half-maximum
+ s Mark and verify the standard deviation of the background
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
+
+ c Mark and verify the centering box width
+ n Mark and verify the cleaning radius
+ p Mark and verify the clipping radius
+
+ a Mark and verify the inner radius of the sky annulus
+ d Mark and verify the width of the sky annulus
+ g Mark and verify the region growing radius
+.fi
+
+.ih
+ALGORITHMS
+
+A brief description of the data dependent parameters, the centering
+algorithms and the sky fitting algorithms can be found in the online
+manual pages for the DATAPARS, CENTERPARS, and FITSKYPARS tasks.
+User measuring extended "fuzzy" features may wish to set the CENTERPARS
+\fIcalgorithm\fR parameter to "none", the FITSKYPARS parameters
+\fIsalgorithm\fR and \fIskyvalue\fR to "constant" and <uservalue> before
+running POLYPHOT.
+
+POLYPHOT computes the intersection of each image line with the line segments
+composing the polygon in order to determine the extent of the polygon. A one
+dimensional summation including a fractional approximation for the end pixels
+is performed over those regions of the image line which intersect the polygon.
+All the 1D summations are summed to give the total integral. The vertices of
+the polygon must be specified in order either clockwise or counterclockwise.
+
+.ih
+OUTPUT
+
+In interactive mode the following quantities are printed on the standard
+output as each object is measured. Error is a simple string which indicates
+whether the task encountered an error in the centering algorithm, the sky
+fitting algorithm or the photometry algorithm. Mag are the magnitudes in
+the polygonal aperture and xcenter, ycenter and msky are the x and y centers
+and the sky value respectively.
+
+.nf
+ image xcenter ycenter msky mag merr error
+.fi
+
+In both interactive and batch mode full output is written to the text file
+\fIoutput\fR. At the beginning of each file is a header listing the current
+values of the parameters when the first stellar record was written. These
+parameters can be subsequently altered. For each star measured the following
+record is written
+
+.nf
+ image xinit yinit id coords lid
+ xcenter ycenter xshift yshift xerr yerr cier error
+ msky stdev sskew nsky nsrej sier serror
+ itime xairmass ifilter otime
+ sum area flux mag merr pier perr
+ polygons pid oldxmean oldymean xmean ymean maxrad nver
+ xvertex yvertex
+.fi
+
+Image and coords are the name of the image and coordinate file respectively.
+Id and lid are the sequence numbers of objects in the output and coordinate
+files respectively. Cier and cerror are the centering error code and
+accompanying error message respectively. Xinit, yinit, xcenter, ycenter,
+xshift, yshift, and xerr, yerr are self explanatory and output in pixel units.
+The sense of the xshift and yshift definitions is the following.
+
+.nf
+ xshift = xcenter - xinit
+ yshift = ycenter - yinit
+.fi
+
+Sier and serror are the sky fitting error code and accompanying error
+message respectively. Msky, stdev and sskew are the best estimate of the
+sky value (per pixel), standard deviation and skew respectively. Nsky and
+nsrej are the number of sky pixels used and the number of sky pixels rejected
+from the fit respectively.
+
+Itime is the exposure time, xairmass is self-evident, ifilter is an id string
+identifying the filter used during the observation, and otime is a string
+specifying the time of the observation in whatever units the user has chosen.
+
+Sum, area, and flux are the total number of counts including sky in the
+polygonal aperture, the area of the aperture in square pixels, and the total
+number of counts in the aperture excluding sky. Mag and merr are the magnitude
+and error in the magnitude in the aperture after subtracting the sky value
+(see below).
+
+.nf
+ flux = sum - area * msky
+ mag = zmag - 2.5 * log10 (flux) + 2.5 * log10 (itime)
+ merr = 1.0857 * error / flux
+ error = sqrt (flux / epadu + area * stdev**2 +
+ area**2 * stdev**2 / nsky)
+.fi
+
+Pier and perror are photometry error code and accompanying error message.
+
+Polygons and pid are the name of the polygons file and the polygon id
+respectively. Oldxmean, oldymean, xmean and ymean are the original and
+current average coordinates of the current polygon. Oldxmean and oldymean
+are the values in the polygons file or the values which correspond to the
+polygon drawn on the display. Xinit and yinit define the position to
+which the polygonal aperture was shifted. Xmean and ymean are generally
+identical to xcenter and ycenter and describe the position of the
+centered polygonal aperture. Maxrad is the maximum
+distance of a polygon vertex from the average of the vertices. Nver, xvertex
+and yvertex are the number of vertices and the coordinates of the vertices
+of the polygonal aperture.
+
+.ih
+ERRORS
+
+If the object centering was error free then the field cier will be zero.
+Non-zero values of cier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 101 # The centering box is off image
+ 102 # The centering box is partially off the image
+ 103 # The S/N ratio is low in the centering box
+ 104 # There are two few points for a good fit
+ 105 # The x or y center fit is singular
+ 106 # The x or y center fit did not converge
+ 107 # The x or y center shift is greater than maxshift
+ 108 # There is bad data in the centering box
+.fi
+
+If all goes well during the sky fitting process then the error code sier
+will be 0. Non-zero values of sier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 201 # There are no sky pixels in the sky annulus
+ 202 # Sky annulus is partially off the image
+ 203 # The histogram of sky pixels has no width
+ 204 # The histogram of sky pixels is flat or concave
+ 205 # There are too few points for a good sky fit
+ 206 # The sky fit is singular
+ 207 # The sky fit did not converge
+ 208 # The graphics stream is undefined
+ 209 # The file of sky values does not exist
+ 210 # The sky file is at EOF
+ 211 # Cannot read the sky value correctly
+ 212 # The best fit parameter are non-physical
+.fi
+
+If no error occurs during the measurement of the magnitudes then pier is
+0. Non-zero values of pier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 801 # The polygon is undefined
+ 802 # The polygon is partially off the image
+ 803 # The polygon is off the image
+ 804 # The sky value is undefined
+ 805 # There is bad data in the aperture
+.fi
+
+.ih
+EXAMPLES
+
+1. Compute the magnitudes inside 2 polygonal aperture for a few regions in
+dev$ypix using the display and the image cursor. Turn off centering and set
+the sky background to 0.0.
+
+.nf
+ ap> display dev$ypix 1 fi+
+
+ ... display the image
+
+ ap> polyphot dev$ypix calgorithm=none salgorithm=constant \
+ skyvalue=0.0 display=imdg mkpolygon+
+
+ ... type ? to print a help page
+
+ ... move image cursor to a region of interest
+
+ ... type g to enter the polygon definition menu
+ ... use the image cursor and spbar key to mark the vertices of
+ the polygonal aperture
+ ... mark each vertex only once, POLYPHOT will close the polygon
+ for you
+ ... type q to quit the polygon definition menu
+
+ ... type the v key to verify the parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... move the image cursor to the objects of interest and tap
+ the space bar, the polygon will be marked on the image
+ display
+
+ ... type g to enter the polygon definition menu
+ ... use the image cursor and spbar key to mark the vertices of
+ the polygonal aperture
+ ... mark each vertex only once, POLYPHOT will close the polygon
+ for you
+ ... type q to quit the polygon definition menu
+
+ ... move the image cursor to the objects of interest and tap
+ the space bar, the polygon will be marked on the image
+ display
+
+ ... a one line summary of the fitted parameters will appear on the
+ standard output for each star measured
+
+ ... the output will appear in ypix.ply.1
+.fi
+
+
+2. Repeat the previous example but use a contour plot and the graphics
+cursor in place of the image display and image cursor. This option is
+really only useful for users (very few these days) with access to a graphics
+terminal but not an image display server.
+
+.nf
+ ap> show stdimcur
+
+ ... determine the default value of stdimcur
+
+ ap> set stdimcur = stdgraph
+
+ ... define the image cursor to be the graphics cursor
+
+ ap> contour dev$ypix
+
+ ... create a contour plot of dev$ypix
+
+ ap> contour dev$ypix >G ypix.plot1
+
+ ... store the contour plot of dev$ypix in the file ypix.plot1
+
+ ap> polyphot dev$ypix calgorithm=none salgorithm=constant \
+ skyvalue=0.0 display=stdgraph mkpolygon+
+
+ ... type ? to print a help page
+
+ ... type the v key to verify the parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... move image cursor to a region of interest
+ ... type g to enter the polygon definition menu
+ ... use the image cursor and spbar key to mark the vertices of
+ the polygonal aperture
+ ... mark each vertex only once, POLYPHOT will close the polygon
+ for you
+ ... type q to quit the polygon definition menu
+
+ ... move the image cursor to the objects of interest and tap
+ the space bar, the polygon will be marked on the contour
+ plot
+
+ ... move image cursor to a region of interest
+ ... type g to enter the polygon definition menu
+ ... use the image cursor and spbar key to mark the vertices of
+ the polygonal aperture
+ ... mark each vertex only once, POLYPHOT will close the polygon
+ for you
+ ... type q to quit the polygon definition menu
+
+ ... move the image cursor to the objects of interest and tap
+ the space bar, the polygon will be marked on the image
+ display
+
+ ... a one line summary of the fitted parameters will appear on the
+ standard output for each star measured and the polygons will
+ be drawn on the display
+
+ ... full output will appear in the text file ypix.ply.2
+
+ ap> reset stdimcur = <default>
+
+ ... reset stdimcur to its default value
+
+
+.fi
+
+3. Setup and run POLYPHOT interactively on a list of objects created with
+POLYMARK.
+
+.nf
+ ap> display dev$ypix 1
+
+ ... display the image
+
+ ap> polymark dev$ypix display=imdg
+
+ ... type g to enter the polygon definition menu
+ ... mark each vertex with the spbar
+ ... mark each vertex only once, POLYPHOT will close the
+ polygon for you
+ ... type q to quit the polygon definition menu
+
+ ... move the cursor to the regions of interest and tap
+ the space bar, the polygon will be marked on the image
+ display
+
+ ... the polygon and polygon centers will be written to the text
+ files ypix.ver.1 and ypix.coo.1 respectively
+
+ ... type q to quit and q again to confirm the quit
+
+ ap> display dev$ypix 2
+
+ ... redisplay the image
+
+ ap> polyphot dev$ypix calgorithm=none salgorithm=constant skyvalue=0.0 \
+ coords=default polygon=default display=imdg mkpolygon+
+
+ ... type n to measure the first polygon in the list
+
+ ... if everything looks okay type l to measure the rest of the stars
+
+ ... a one line summary of results will appear on the standard output
+ for each star measured and the aperture will be drawn on the
+ image display
+
+ ... type q to quit and q again to confirm the quit
+
+ ... the output will appear in ypix.ply.3
+.fi
+
+
+4. Repeat example 3 but work on a section of the input image while
+preserving the coordinate system of the original image.
+
+.nf
+ ap> display dev$ypix[150:450,150:450] 1
+
+ ... display the image
+
+ p> polymark dev$ypix[150:450,150:450] wcsout=tv display=imdg
+
+ ... type g to enter the polygon definition menu
+ ... mark each vertex with the spbar
+ ... mark each vertex only once, POLYPHOT will close the
+ polygon for you
+ ... type q to quit the polygon definition menu
+
+ ... move the cursor to the regions of interest and tap
+ the space bar, the polygon will be marked on the image
+ display
+
+ ... the polygon and polygon centers will be written to the text
+ files ypix.ver.1 and ypix.coo.1 respectively
+
+ ... type q to quit and q again to confirm the quit
+
+ ap> display dev$ypix[150:450,150:450] 2
+
+ ... redisplay the image
+
+ ap> polyphot dev$ypix[150:450,150:450] calgorithm=none \
+ salgorithm=constant skyvalue=0.0 coords=default polygon=default \
+ display=imdg mkpolygon+ wcsin=tv wcsout=tv
+
+ ... type n to measure the first polygon in the list
+
+ ... if everything looks okay type l to measure the rest of the stars
+
+ ... a one line summary of results will appear on the standard output
+ for each star measured and the aperture will be drawn on the
+ image display
+
+ ... type q to quit and q again to confirm the quit
+
+ ... the output will appear in ypix.ply.4
+
+ ap> pdump ypix.ply.4 xc,yc yes | tvmark 2 STDIN col=204
+
+ ... mark the centers of the polygons on the display
+.fi
+
+
+5. Run POLYPHOT in batch mode using a polygon and coordinate file and the
+default parameters. Verify the critical parameters.
+
+.nf
+ ap> polyphot dev$ypix coords=default polygon=default inter- verify+
+
+ ... output will appear in ypix.ply.5
+.fi
+
+
+.ih
+TIMINGS
+.ih
+BUGS
+There are no restrictions on the shape of the polygon but the vertices
+must be listed or marked in order.
+
+When marking the polygon on the display it is not necessary to close
+the polygon. When the user types q to quit the marking the program
+will automatically close the polygon.
+
+It is currently the responsibility of the user to make sure that the
+image displayed on the display is the same as that specified by the image
+parameter.
+
+Commands which draw to the image display are disabled by default.
+To enable graphics overlay on the image display, set the display
+parameter to "imdr", "imdg", "imdb", or "imdy" to get red, green,
+blue or yellow overlays and set the centerpars mkcenter switch to
+"yes", the fitskypars mksky switch to"yes", or the polypars mkpolygon
+switch to "yes". It may be necessary to run gflush and to redisplay the image
+to get the overlays position correctly.
+
+.ih
+SEE ALSO
+datapars,centerpars,fitskypars,polypars,qphot,phot,wphot
+.endhelp
diff --git a/noao/digiphot/apphot/doc/qphot.hlp b/noao/digiphot/apphot/doc/qphot.hlp
new file mode 100644
index 00000000..42e3f5bf
--- /dev/null
+++ b/noao/digiphot/apphot/doc/qphot.hlp
@@ -0,0 +1,647 @@
+.help qphot May00 noao.digiphot.apphot
+.ih
+NAME
+qphot -- quick aperture photometer
+.ih
+USAGE
+qphot image cbox annulus dannulus apertures
+.ih
+PARAMETERS
+.ls image
+The list of images containing the objects to be measured.
+.le
+.ls cbox
+The width of the centering box in pixels.
+.le
+.ls annulus
+The inner radius of the sky annulus in pixels.
+.le
+.ls dannulus
+The width of the sky annulus in pixels.
+.le
+.ls apertures
+The list of aperture radii in pixels. Apertures is a string parameter
+specifying either a single aperture radius e.g. "3.0", a list of aperture
+radii separated by commas e.g. "3.0,5.0,10.0", or a range of aperture radii
+e.g. "1.0:20.0:1.0".
+.le
+.ls coords = ""
+The list of text files containing initial coordinates for the objects to
+be measured. Objects are listed in coords one object per line with the
+initial coordinate values in columns one and two. The number of coordinate
+files must be zero, one, or equal to the number of images. If coords is
+"default", "dir$default", or a directory specification then a coords file name
+of the form dir$root.extension.version is constructed and searched for,
+where dir is the directory, root is the root image name, extension is "coo"
+and version is the next available version number for the file.
+.le
+.ls output = "default"
+The name of the results file or results directory. If output is
+"default", "dir$default", or a directory specification then an output file name
+of the form dir$root.extension.version is constructed, where dir is the
+directory, root is the root image name, extension is "mag" and version is
+the next available version number for the file. The number of output files
+must be zero, one, or equal to the number of image files. In both interactive
+and batch mode full output is written to output. In interactive mode
+an output summary is also written to the standard output.
+.le
+.ls plotfile = ""
+The name of the file containing radial profile plots of the stars written
+to the output file. If plotfile is defined then a radial profile plot
+is written to plotfile every time a record is written to \fIoutput\fR.
+The user should be aware that this can be a time consuming operation.
+.le
+.ls zmag = 25.0
+The zero point of the magnitude scale.
+.le
+.ls exposure = ""
+The image header keyword containing the exposure time.
+.le
+.ls airmass = ""
+The image header keyword containing the airmass of the observation.
+.le
+.ls filter = ""
+The image header keyword containing the filter id of the observation.
+.le
+.ls obstime = ""
+The image header keyword containing the time of the observation.
+.le
+.ls epadu = 1.0
+The gain in photons per adu. Epadu is used to compute the magnitude errors.
+.le
+.ls interactive = yes
+Interactive or batch mode.
+.le
+.ls radplots = no
+If radplots is "yes" and QPHOT is run in interactive mode then a radial profile
+of each star is plotted on the screen after it is measured.
+.le
+.ls icommands = ""
+The image display cursor or image cursor command file.
+.le
+.ls gcommands = ""
+The graphics cursor or graphics cursor command file.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout"
+The coordinate system of the input coordinates read from \fIcoords\fR and
+of the output coordinates written to \fIoutput\fR respectively. The image
+header coordinate system is used to transform from the input coordinate
+system to the "logical" pixel coordinate system used internally,
+and from the internal "logical" pixel coordinate system to the output
+coordinate system. The input coordinate system options are "logical", tv",
+"physical", and "world". The output coordinate system options are "logical",
+"tv", and "physical". The image cursor coordinate system is assumed to
+be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin and wcsout are "logical" and "logical" respectively.
+.le
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default cacheing is
+disabled.
+.le
+.ls verbose = ")_.verbose"
+Print messages in non-interactive mode ? Verbose may be set to the apphot
+package parameter value (the default), "yes", or "no.
+.le
+.ls graphics = ")_.graphics"
+The default graphics device. Graphics may be set to the apphot package
+parameter value (the default), "yes", or "no.
+.le
+.ls display = ")_.display"
+The default display device. Display may be set to the apphot package parameter
+value (the default), "yes", or "no. By default graphics overlay is disabled.
+Setting display to one of "imdr", "imdg", "imdb", or "imdy" enables graphics
+overlay with the IMD graphics kernel. Setting display to "stdgraph" enables
+QPHOT to work interactively from a contour plot.
+.le
+
+.ih
+DESCRIPTION
+QPHOT computes accurate centers, sky values, and magnitudes for a list of
+objects in the IRAF image \fIimage\fR whose initial coordinates are
+read from the image cursor or the coordinate file \fIcoords\fR,
+and writes the computed x and y coordinates, sky values, and
+magnitudes to the text file \fIoutput\fR.
+
+The coordinates read from \fIcoords\fR are assumed to be in coordinate
+system defined by \fIwcsin\fR. The options are "logical", "tv", "physical",
+and "world" and the transformation from the input coordinate system to
+the internal "logical" system is defined by the image coordinate system.
+The simplest default is the "logical" pixel system. Users working on with
+image sections but importing pixel coordinate lists generated from the parent
+image must use the "tv" or "physical" input coordinate systems.
+Users importing coordinate lists in world coordinates, e.g. ra and dec,
+must use the "world" coordinate system and may need to convert their
+equatorial coordinate units from hours and degrees to degrees and degrees first.
+
+The coordinates written to \fIoutput\fR are in the coordinate
+system defined by \fIwcsout\fR. The options are "logical", "tv",
+and "physical". The simplest default is the "logical" system. Users
+wishing to correlate the output coordinates of objects measured in
+image sections or mosaic pieces with coordinates in the parent
+image must use the "tv" or "physical" coordinate systems.
+
+In interactive mode the user measure objects interactively with the image
+cursor, or select them interactively from the coordinate list \fIcoords\fR.
+In batch mode the coordinates can be read directly from \fIcoords\fR, or from
+the cursor command file specified by the parameter \fIicommands\fR.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If cacheing
+is enabled and QPHOT is run interactively the first measurement will appear
+to take a long time as the entire image must be read in before the measurement
+is actually made. All subsequent measurements will be very fast because QPHOT
+is accessing memory not disk. The point of cacheing is to speed up random
+image access by making the internal image i/o buffers the same size as the
+image itself. However if the input object lists are sorted in row order and
+sparse cacheing may actually worsen not improve the execution time. Also at
+present there is no point in enabling cacheing for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of cacheing in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halfs of the image are alternated.
+
+QPHOT computes accurate centers for each object using the centroid
+centering algorithm, pixels inside \fIcbox\fR and the default values of the
+\fIcenterpars\fR parameters. Accurate sky values for each object are
+computed using the \fIcentroid\fR sky fitting algorithm with histogram
+smoothing turned on, pixels inside the sky annulus defined by \fIannulus\fR
+and \fIdannulus\fR, and the default values of the remaining sky fitting
+parameters as defined in the \fIfitskypars\fR parameter set. Magnitudes
+are computed using pixels inside the apertures defined by \fIapertures\fR.
+The user must set the gain \fIepadu\fR to ensure that the magnitude error
+estimates are correctly computed and \fIexposure\fR to normalize the computed
+magnitudes to an exposure time of 1 time unit. The zero point of the magnitude
+scale can be adjusted by setting \fIzmag\fR. \fIAirmass\fR, \fIfilter\fR,
+and \fIobstime\fR are book-keeping parameters. Setting them to appropriate
+values will simplify future analysis and calibration steps.
+
+.ih
+CURSOR COMMANDS
+
+The following list of cursor commands are currently available.
+
+.nf
+ Interactive Photometry Commands
+
+? Print help
+: Colon commands
+w Save the current parameters
+d Plot radial profile of current star
+i Interactively set parameters using current star
+c Fit center of current star
+t Fit sky around the cursor
+a Average sky values fit around several cursor positions
+s Fit sky for current centered star
+p Do photometry for current star, using current sky
+o Do photometry for current star, using current sky, output results
+f Do photometry for current star
+spbar Do photometry for current star, output results
+e Print error messages
+m Move to next star in coordinate list
+n Do photometry for next star in coordinate list, output results
+l Do photometry for remaining stars in coordinate list, output results
+r Rewind the coordinate list
+q Exit task
+
+
+ Colon Commands
+
+:show List the parameters
+:m [n] Move to next [nth] star in coordinate list
+:n [n] Do photometry for next [nth] star in coordinate list, output results
+
+ Colon Parameter Editing Commands
+
+:image [string] Image name
+:output [string] Output file name
+:coords [string] Coords file name
+
+:cbox [value] Width of the centering box (pixels)
+:annulus [value] Inner radius of sky annulus (pixels)
+:dannulus [value] Width of sky annulus (pixels)
+:apertures [string] List of aperture radii (pixels)
+:zmag [value] Zero point of magnitude scale (magnitudes)
+:epadu [value] Gain (electrons per adu)
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+
+:radplot [y/n] Plot radial profile of object
+
+
+The following commands are available from inside the interactive setup menu
+using the i key.
+
+
+ Interactive Qphot Setup Menu
+
+ v Mark and verify the critical parameters (c,a,d,r)
+
+ c Mark and verify the centering box width
+ a Mark and verify the inner radius of the sky annulus
+ d Mark and verify the width of the sky annulus
+ r Mark and verify the aperture radii
+.fi
+
+.ih
+OUTPUT
+In interactive mode the following quantities are printed on the standard
+output as each object is measured. Error is a simple string which indicates
+whether the task encountered an error condition from
+the centering algorithm, the sky fitting algorithm or the photometry
+algorithm respectively. Mag are the magnitudes in
+apertures 1 through N respectively and xcenter, ycenter and msky are the
+x and y centers and the sky value respectively.
+
+.nf
+ image xcenter ycenter msky mag[1 ... N] error
+.fi
+
+In both interactive and batch mode full output is written to the text file
+\fIoutput\fR. At the beginning of each file is a header listing the
+current values of the parameters when the first stellar record was written.
+These parameters can be subsequently altered. For each star measured the
+following record is written.
+
+.nf
+ image xinit yinit id coords lid
+ xcenter ycenter xshift yshift xerr yerr cier cerror
+ msky stdev sskew nsky nsrej sier serror
+ itime xairmass ifilter otime
+ rapert sum area flux mag merr pier perror
+.fi
+
+Image and coords are the name of the image and coordinate file respectively.
+Id and lid are the sequence numbers of stars in the output and coordinate
+files respectively. Cier and cerror are the error code and accompanying
+error message for the center computation. Xinit, yinit, xcenter, ycenter,
+xshift, yshift, and xerr, yerr are self explanatory and output in pixel units.
+The sense of the xshift and yshift definitions is the following.
+
+.nf
+ xshift = xcenter - xinit
+ yshift = ycenter - yinit
+.fi
+
+Sier and serror are the sky fitting error code and accompanying error message
+respectively. Msky, stdev and sskew are the best estimate of the sky value
+(per pixel), standard deviation and skew respectively. Nsky and nsrej are
+the number of sky pixels used and the number of sky pixels rejected
+respectively.
+
+Itime is the exposure time, xairmass is self-evident, ifilter is an
+id string used to identify the filter used during the observation, and
+otime is a string containing the time stamp in whatever units the
+user has written into the image header or the otime parameter.
+
+Rapert, sum, area, and flux are the radius of the aperture in pixels, the
+total number of counts including sky in the aperture, the area of the aperture
+in square pixels, and the total number of counts in the aperture excluding
+sky. Mag and merr are the magnitude and error in the magnitude in the aperture.
+
+.nf
+ flux = sum - area * msky
+ mag = zmag - 2.5 * log10 (flux) + 2.5 * log10 (itime)
+ merr = 1.0857 * err / flux
+ err = sqrt (flux / epadu + area * stdev**2 +
+ area**2 * stdev**2 / nsky)
+.fi
+
+Pier and perror are photometry error code and accompanying error message.
+
+In interactive mode a radial profile of each measured object is plotted
+in the graphics window if \fIradplots\fR is "yes".
+
+In interactive and batchmode a radial profile plot is written to
+\fIplotfile\fR if it is defined each time the result of an object
+measurement is written to \fIoutput\fR .
+
+
+.ih
+ERRORS
+If the object centering was error free then the field cier will be zero.
+Non-zero values of cier flag the following error conditions.
+
+.nf
+0 # No error
+101 # The centering box is off image
+102 # The centering box is partially off the image
+103 # The S/N ratio is low in the centering box
+104 # There are two few points for a good fit
+105 # The x or y center fit is singular
+106 # The x or y center fit did not converge
+107 # The x or y center shift is greater than 1 pixel
+108 # There is bad data in the centering box
+
+.fi
+
+If all goes well during the sky fitting process then the error code sier
+will be 0. Non-zero values of sier flag the following error conditions.
+
+.nf
+0 # No error
+201 # There are no sky pixels in the sky annulus
+202 # Sky annulus is partially off the image
+203 # The histogram of sky pixels has no width
+204 # The histogram of sky pixels is flat or concave
+205 # There are too few points for a good sky fit
+206 # The sky fit is singular
+207 # The sky fit did not converge
+208 # The graphics stream is undefined
+209 # The file of sky values does not exist
+210 # The sky file is at EOF
+211 # Cannot read the sky value correctly
+212 # The best fit parameter are non-physical
+
+.fi
+
+If no error occurs during the measurement of the magnitudes then pier is
+0. Non-zero values of pier flag the following error conditions.
+
+.nf
+0 # No error
+301 # The aperture is off the image
+302 # The aperture is partially off the image
+303 # The sky value is undefined
+305 # There is bad data in the aperture
+.fi
+
+.ih
+EXAMPLES
+
+1. Perform aperture photometry interactively for a few stars in dev$ypix using
+the display and the image cursor.
+
+.nf
+ ap> display dev$ypix 1 fi+
+
+ ... display the image
+
+ ap> qphot dev$ypix 5. 10. 5. 2.,4.,6.0
+
+ ... move image cursor to objects of interest and tap space bar
+
+ ... a 1 line summary will be printed on the standard output
+ for each object measured
+
+ ... type q to quit and q again to confirm the quit
+
+ ... full output will appear in ypix.mag.1
+.fi
+
+
+2. Perform aperture photometry interactively for a few stars in dev$ypix
+using the contour plot and the graphics cursor. This option is only useful
+for those (now very few) users who have access to a graphics terminal but
+not to an image display server. Setup the task parameters using the
+interactive setup menu defined by the i key command as in example 1.
+
+
+.nf
+ ap> show stdimcur
+
+ ... record the default value of stdimcur
+
+ ap> set stdimcur = stdgraph
+
+ ... define the image cursor to be the graphics cursor
+
+ ap> contour dev$ypix
+
+ ... make a contour plot of dev$ypix
+
+ ap> contour dev$pix >G ypix.plot1
+
+ ... store the contour plot of dev$ypix in the file ypix.plot1
+
+ ap> qphot dev$ypix 5. 10. 5. 2.,4.,6.0
+
+ ... type ? to see the help screen
+
+ ... move image cursor to objects of interest and tap space bar
+
+ ... a 1 line summary will be printed on the standard output
+ for each object measured
+
+ ... type q to quit and q again to confirm the quit
+
+ ... full output will be written to ypix.mag.2
+
+ ap> set stdimcur = <default>
+
+ ... reset stdimcur to its previous value
+.fi
+
+
+
+3. Setup and run QPHOT interactively on a list of objects temporarily
+overriding the fwhmpsf, sigma, cbox, annulus, dannulus, and apertures
+ parameters determined in examples 1 or 2.
+
+.nf
+ ap> daofind dev$ypix fwhmpsf=2.6 sigma=25.0 verify-
+
+ ... make a coordinate list
+
+ ... the output will appear in the text file ypix.coo.1
+
+ ap> qphot dev$ypix 7.0 12.0 5.0 "3.0,5.0" coords=ypix.coo.1
+
+ ... type ? for optional help
+
+
+ ... move the graphics cursor to the stars and tap space bar
+
+ or
+
+ ... select stars from the input coordinate list with m / :m #
+ and measure with spbar
+
+ ... measure stars selected from the input coordinate list
+ with n / n #
+
+ ... a one line summary of results will appear on the standard output
+ for each star measured
+
+ ... type q to quit and q again to confirm the quit
+
+ ... the output will appear in ypix.mag.3 ...
+.fi
+
+
+4. Display and measure some stars in an image section and write the output
+coordinates in the coordinate system of the parent image.
+
+.nf
+ ap> display dev$ypix[150:450,150:450] 1
+
+ ... display the image section
+
+ ap> qphot dev$ypix[150:450,150:450] 7.0 12.0 5.0 "3.0,5.0" wcsout=tv
+
+ ... move cursor to stars and type spbar
+
+ ... type q to quit and q again to confirm quit
+
+ ... output will appear in ypix.mag.4
+
+ ap> pdump ypix.mag.4 xc,yc yes | tvmark 1 STDIN col=204
+.fi
+
+
+5. Run QPHOT in batch mode using the coordinate file and the previously
+saved parameters.
+
+.nf
+ ap> qphot dev$ypix 7. 12.0 5.0 "3.0,5.0" coords=ypix.coo.1 inter-
+
+ ... output will appear in ypix.mag.5 ...
+.fi
+
+
+6. Repeat example 5 but assume that the input coordinate are ra and dec
+in degrees and degrees and submit the task to the background.
+
+.nf
+ ap> display dev$ypix
+
+ ap> rimcursor wcs=world > radec.coo
+
+ ... move to selected stars and type any key
+
+ ... type ^Z to quit
+
+ ap> qphot dev$ypix 7.0 12.0 5.0 "3.0,5.0" coords=radec.coo \
+ wcsin=world inter- &
+
+ ... output will appear in ypix.ctr.6
+
+ ap> pdump ypix.mag.6 xc,yc yes | tvmark 1 STDIN col=204
+
+ ... mark the stars on the display
+.fi
+
+
+7. Run QPHOT interactively without using the image display.
+
+.nf
+ ap> show stdimcur
+
+ ... record the default value of stdimcur
+
+ ap> set stdimcur = text
+
+ ... set the image cursor to the standard input
+
+ ap> qphot dev$ypix 7.0 12.0 5.0 "3.0,5.0" coords=ypix.coo.1
+
+ ... type ? for optional help
+
+ ... type :m 3 to set the initial coordinates to those of the
+ third star in the list
+
+ ... type "442 409 101 i" to enter the interactive setup menu
+ ... enter the maximum radius in pixels for the radial profile or
+ accept the default with a CR
+ ... type v to enter the default menu
+ ... reset cbox, annulus, dannulus, and apertures using the graphics
+ cursor and the stellar radial profile plot
+ ... typing <CR> after the prompt leaves the parameter at its default
+ value
+ ... type q to quit the setup menu
+
+ ... type r to rewind the coordinate list
+
+ ... type l to measure all the stars in the coordinate list
+
+ ... a one line summary of the answers will appear on the standard
+ output for each star measured
+
+ ... type q to quit followed by q to confirm the quit
+
+ ... full output will appear in the text file ypix.mag.7
+
+ ap> set stdimcur = <default>
+
+ ... reset the value of stdimcur
+.fi
+
+8. Use a image cursor command file to drive the qphot task. The cursor command
+file shown below computes the centers, sky values, and magnitudes for 3 stars
+and quits the task.
+
+.nf
+ ap> type cmdfile
+ 442 410 101 \040
+ 349 188 101 \040
+ 225 131 101 \040
+ q
+
+ ap> qphot dev$ypix 7.0 12.0 5.0 "3.0,5.0" icommands=cmdfile
+
+ ... full output will appear in ypix.mag.8
+.fi
+
+
+.ih
+BUGS
+
+It is the responsibility of the user to make sure that the image displayed
+in the image display is the same as that specified by the image parameter.
+
+Commands which draw to the image display are disabled by default.
+To enable graphics overlay on the image display, set the display
+parameter to "imdr", "imdg", "imdb", or "imdy" to get red, green,
+blue or yellow overlays. It may be necessary to run gflush and to
+redisplay the image to get the overlays position correctly.
+
+.ih
+SEE ALSO
+phot,wphot,polyphot
+.endhelp
diff --git a/noao/digiphot/apphot/doc/radprof.hlp b/noao/digiphot/apphot/doc/radprof.hlp
new file mode 100644
index 00000000..c6d79251
--- /dev/null
+++ b/noao/digiphot/apphot/doc/radprof.hlp
@@ -0,0 +1,813 @@
+.help radprof May00 noao.digiphot.apphot
+.ih
+NAME
+radprof -- compute the radial profile of an object
+.ih
+USAGE
+radprof image radius step
+.ih
+PARAMETERS
+.ls image
+The name of the image containing the objects to be measured.
+.le
+.ls radius, step
+The size and resolution of the computed radial profile in scale units which is
+equal to radius * \fIscale\fR and step * \fIscale\fR in pixels.
+.le
+.ls coords = ""
+The list of text files containing initial coordinates for the objects to
+be centered. Objects are listed in coords one object per line with the
+initial coordinate values in columns one and two. The number of coordinate
+files must be zero, one, or equal to the number of images. If coords is
+"default", "dir$default", or a directory specification then a coords file name
+of the form dir$root.extension.version is constructed and searched for,
+where dir is the directory, root is the root image name, extension is "prf"
+and version is the next available version number for the file.
+.le
+.ls output = ""
+The name of the results file or results directory.
+If output is "default", "dir$default" or a directory specification then an
+output file name of the form dir$root.extension.version is constructed, where
+dir is the directory, root is the root image name, extension is "prf" and
+version is the next available version of the file. If output is undefined,
+then no output file is created. If output is defined, the number of output files
+is either 1 or the same as the number of input images.
+.le
+.ls plotfile = ""
+The name of the file containing radial profile plots of the stars written
+to the output file. If plotfile is defined then a radial profile plot
+is written to plotfile every time a record is written to \fIoutput\fR.
+The user should be aware that this can be a time consuming operation.
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters. The critical
+parameters \fIfwhmpsf\fR and \fIsigma\fR are located here. If \fIdatapars\fR
+is undefined then the default parameter set in uparm directory is used.
+.le
+.ls centerpars = ""
+The name of the file containing the centering parameters. The critical
+parameters \fIcalgorithm\fR and \fIcbox\fR are located here.
+If \fIcenterpars\fR is undefined then the default parameter set in
+uparm directory is used.
+.le
+.ls fitskypars = ""
+The name of the text file containing the sky fitting parameters. The critical
+parameters \fIsalgorithm\fR, \fIannulus\fR, and \fIdannulus\fR are located here.
+If \fIfitskypars\fR is undefined then the default parameter set in uparm
+directory is used.
+.le
+.ls photpars = ""
+The name of the file containing the photometry parameters. The critical
+parameter \fIapertures\fR is located here. If \fIphotpars\fR is undefined
+then the default parameter set in uparm directory is used.
+.le
+.ls order = 5
+The number of pieces in the spline fit.
+.le
+.ls nreject = 1
+The maximum number of rejection cycles.
+.le
+.ls kreject = 3.0
+The k-sigma rejection limit for the radial profile fit.
+.le
+.ls interactive = yes
+Run the task interactively ?
+.le
+.ls radplots = yes
+If \fIradplots\fR is "yes" and RADPROF is run in interactive mode, a radial
+profile of each star is plotted on the screen after the star is measured.
+.le
+.ls icommands = ""
+The image cursor or image cursor command file.
+.le
+.ls gcommands = ""
+The graphics cursor or graphics cursor command file.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout"
+The coordinate system of the input coordinates read from \fIcoords\fR and
+of the output coordinates written to \fIoutput\fR respectively. The image
+header coordinate system is used to transform from the input coordinate
+system to the "logical" pixel coordinate system used internally,
+and from the internal "logical" pixel coordinate system to the output
+coordinate system. The input coordinate system options are "logical", "tv",
+"physical", and "world". The output coordinate system options are "logical",
+"tv", and "physical". The image cursor coordinate system is assumed to
+be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin and wcsout are "logical" and "logical" respectively.
+.le
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default cacheing is
+disabled.
+.le
+.ls verify = ")_.verify"
+Verify the critical parameters in non-interactive mode ? Verify may be set to
+the apphot package parameter value (the default), "yes", or "no".
+.le
+.ls update = ")_.update"
+Update the critical parameter in non-interactive mode if verify is yes ?
+Update may be set to the apphot package parameter value (the default), "yes",
+or "no".
+.le
+.ls verbose = ")_.verbose"
+Print messages on the screen in non-interactive mode ? Verbose may be set
+to the apphot package parameter value (the default), "yes", or "no".
+
+.le
+.ls graphics = ")_.graphics"
+The default graphics device. Graphics may be set to the apphot package
+parameter value (the default), "yes", or "no.
+.le
+.ls display = ")_.display"
+The default display device. Display may be set to the apphot package
+parameter value (the default), "yes", or "no. By default graphics overlay
+is disabled. Setting display to one of "imdr", "imdg", "imdb", or "imdy"
+enables graphics overlay with the IMD graphics kernel. Setting display to
+"stdgraph" enables RADPROF to work interactively from a contour plot.
+.le
+
+.ih
+DESCRIPTION
+
+The radial profiles of objects in the image \fIimage\fR are computed
+the object center out to the radius \fIradius * scale\fR, in steps of
+\fIstep * scale\fR pixels, and plotted. The initial positions are
+read from the image cursor or the text file \fIcoords\fR.
+
+The coordinates read from \fIcoords\fR are assumed to be in coordinate
+system defined by \fIwcsin\fR. The options are "logical", "tv", "physical",
+and "world" and the transformation from the input coordinate system to
+the internal "logical" system is defined by the image coordinate system.
+The simplest default is the "logical" pixel system. Users working on with
+image sections but importing pixel coordinate lists generated from the parent
+image must use the "tv" or "physical" input coordinate systems.
+Users importing coordinate lists in world coordinates, e.g. ra and dec,
+must use the "world" coordinate system and may need to convert their
+equatorial coordinate units from hours and degrees to degrees and degrees first.
+
+The coordinates written to \fIoutput\fR are in the coordinate
+system defined by \fIwcsout\fR. The options are "logical", "tv",
+and "physical". The simplest default is the "logical" system. Users
+wishing to correlate the output coordinates of objects measured in
+image sections or mosaic pieces with coordinates in the parent
+image must use the "tv" or "physical" coordinate systems.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If cacheing
+is enabled and RADPROF is run interactively the first measurement will appear
+to take a long time as the entire image must be read in before the measurement
+is actually made. All subsequent measurements will be very fast because RADPROF
+is accessing memory not disk. The point of cacheing is to speed up random
+image access by making the internal image i/o buffers the same size as the
+image itself. However if the input object lists are sorted in row order and
+sparse cacheing may actually worsen not improve the execution time. Also at
+present there is no point in enabling cacheing for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of cacheing in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halfs of the image are alternated.
+
+RADPROF can be run either interactively or in batch mode by setting the
+interactive switch to yes. In interactive mode starting x and y coordinates
+can either be read directly from the image cursor or read from the text
+file specified by \fIcoords\fR. In interactive mode the results are
+plotted on the terminal. In batch mode the estimated positions
+are read from the text file \fIcoords\fR or the image cursor parameter
+\fIicommands\fR is redirected to a text file containing a list of cursor
+commands.
+
+.ih
+CURSOR COMMANDS
+
+The RADPROF cursor commands are listed below.
+
+.nf
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+v Verify the critical parameters
+w Store the current parameters
+d Plot radial profile of current star
+i Interactively set parameters using current star
+c Fit center of current star
+t Fit sky around the cursor position
+a Average sky values fit around several cursor positions
+s Fit sky around the current star
+p Fit star using current sky
+o Fit star using current sky, output results
+f Fit current star
+spbar Fit current star, output results
+m Move to next star in coordinate list
+n Fit next star in coordinate list, output results
+l Fit remaining stars in coordinate list, output results
+r Rewind the coordinate list
+e Print error messages
+q Exit task
+
+
+ Colon Commands
+
+:show [data/center/sky/fit] List the parameters
+:m [n] Move to next [nth] object in coordinate list
+:n [n] Fit next [nth] object in coordinate list, output results
+
+
+ Colon Parameter Editing Commands
+
+# Image and file name parameters
+
+:image [string] Image name
+:coords [string] Coordinate file name
+:output [string] Output file name
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Full-width half-maximum of psf (scale units)
+:emission [y/n] Emission features (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good pixel value (counts)
+:datamax [value] Maximum good pixel value (counts)
+
+# Noise parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per adu)
+:readnoise [value] Readout noise (electrons)
+
+# Observing parameters
+
+:exposure [value] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Integration time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observation (time units)
+
+# Centering algorithm parameters
+
+:calgorithm [string] Centering algorithm
+:cbox [value] Width of the centering box (scale units)
+:cthreshold [value] Centering intensity threshold (sigma)
+:cmaxiter [value] Maximum number of iterations
+:maxshift [value] Maximum center shift (scale units)
+:minsnratio [value] Minimum S/N ratio for centering
+:clean [y/n] Clean subraster before centering
+:rclean [value] Cleaning radius (scale units)
+:rclip [value] Clipping radius (scale units)
+:kclean [value] Clean K-sigma rejection limit (sigma)
+
+# Sky fitting algorithm parameters
+
+:salgorithm [string] Sky fitting algorithm
+:skyvalue [value] User supplied sky value (counts)
+:annulus [value] Inner radius of sky annulus (scale units)
+:dannulus [value] Width of sky annulus (scale units)
+:khist [value] Sky histogram extent (+/- sigma)
+:binsize [value] Resolution of sky histogram (sigma)
+:sloclip [value] Low-side clipping factor in percent
+:shiclip [value] High-side clipping factor in percent
+:smaxiter [value] Maximum number of iterations
+:smooth [y/n] Lucy smooth the sky histogram
+:snreject [value] Maximum number of rejection cycles
+:sloreject [value] Low-side pixel rejection limits (sky sigma)
+:shireject [value] High-side pixel rejection limits (sky sigma)
+:rgrow [value] Region growing radius (scale units)
+
+# Photometry parameters
+
+:apertures [string] List of apertures (scale units)
+:zmag [value] Zero point of magnitude scale
+
+# Profile fitting parameters
+
+:radius [value] Maximum profile radius (scale units)
+:step [value] Step size for computed profile (scale units)
+:order [value] Number of spline pieces in fit
+:kreject [value] K-sigma rejection for fit (fit sigma)
+:nreject [value] Maximum number of rejection cycles
+
+# Marking and plotting parameters
+
+:mkcenter [y/n] Mark computed centers on display
+:mksky [y/n] Mark the sky annuli on the display
+:mkapert [y/n] Mark apertures on the display
+:radplot [y/n] Plot the radial profile
+
+
+
+The following commands are available from inside the interactive setup menu.
+
+
+ Interactive Radprof Setup Menu
+
+ v Mark and verify the critical parameters (f,c,s,a,d,r,w,x)
+
+ f Mark and verify the psf full-width half-maximum
+ s Mark and verify the standard deviation of the background
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
+
+ c Mark and verify the centering box width
+ n Mark and verify the cleaning radius
+ p Mark and verify the clipping radius
+
+ a Mark and verify the inner radius of the sky annulus
+ d Mark and verify the width of the sky annulus
+ g Mark and verify the region growing radius
+
+ r Mark and verify the photometry aperture radii
+ w Mark and verify the radius of the radial profile
+ x Mark and verify the step size of radial profile
+.fi
+
+.ih
+ALGORITHMS
+
+Prior to computing the radial profile of the star, RADPROF computes the
+center, estimates a sky value, and does aperture photometry on the star
+using the parameters in the DATAPARS, CENTERPARS, FITSKYPARS, and
+PHOTPARS tasks.
+
+Next the radial and intensity coordinates of all the pixels inside
+\fIradius * scale\fR are computed using the calculated center and sky
+values and fit to a least squares cubic spline of order \fIorder\fR with
+optional bad data rejection. The fit is interpolated at intervals of
+\fIstep_size * scale\fR to derive the output profile and estimate the
+full width at half maximum of the object. The fit noise model parameters
+are defined in DATAPARS.
+
+.ih
+OUTPUT
+
+In interactive mode the following quantities are printed on the standard
+output as each object is measured. Error is a simple string which
+indicates whether an error was encountered in the
+the centering algorithm, the sky fitting algorithm, the photometry
+algorithm or the spline fitting algorithm respectively.
+Mag and merr are the magnitudes and errors in
+aperture N and xcenter, ycenter and msky are the
+x and y centers and the sky value respectively.
+Pfwhm is the fitted full width half maximum of the fitted radial profile.
+
+.nf
+ image xcenter ycenter msky pfwhm mag[N] merr[N] iers
+.fi
+
+In both interactive and batch mode full output is written to the text file
+\fIoutput\fR. At the beginning of each file is a header listing the
+current values of the parameters when the first stellar record was written.
+These parameters can be subsequently altered. For each star measured the
+following record is written
+
+.nf
+ image xinit yinit id coords lid
+ xcenter ycenter xshift yshift xerr yerr cier error
+ msky stdev sskew nsky nsrej sier serror
+ itime xairmass ifilter otime
+ rapert sum area flux mag merr pier perr
+ pfwhm inorm tinorm rier rerror
+ pradius intensity tintensity
+.fi
+
+Image and coords are the name of the image and coordinate file respectively.
+Id and lid are the sequence numbers of stars in the output and coordinate
+files respectively. Cier and cerror are the error code and accompanying
+error message respectively. Xinit, yinit, xcenter, ycenter, xshift, yshift,
+and xerr, yerr are self explanatory and output in pixel units. The sense of
+the xshift and yshift definitions is the following.
+
+.nf
+ xshift = xcenter - xinit
+ yshift = ycenter - yinit
+.fi
+
+Sier and serror are the error code and accompanying error message respectively.
+Msky, stdev and sskew are the best estimate of the sky value (per pixel),
+standard deviation and skew respectively. Nsky and nsrej are the number of
+sky pixels and the number of sky pixels rejected respectively.
+
+Itime is the exposure time, xairmass is self-evident, filter is an id
+string specifying the filter used during the observation and otime is
+a string containing the time of observation in whatever units the user
+has defined.
+
+Rapert, sum, area and flux are the radius of the aperture in pixels, the total
+number of counts including sky in the aperture, the area of the aperture in
+square pixels, and the total number of counts in the aperture excluding sky.
+Mag and merr are the magnitude and error in the magnitude in the aperture
+(see below).
+
+.nf
+ flux = sum - area * msky
+ mag = zmag - 2.5 * log10 (flux) + 2.5 * log10 (itime)
+ merr = 1.0857 * error / flux
+ error = sqrt (flux / epadu + area * stdev**2 +
+ area**2 * stdev**2 / nsky)
+.fi
+
+Pier and perror are photometry error code and accompanying error message.
+
+Pfwhm is the full width at half intensity of the fitted profile. Inorm and
+tinorm are the normalization factors for the fitted radial profile and the
+fitted total intensity profile respectively. Rier and rerror are the spline
+fitting error code and accompanying error message. Pradius, intensity
+and tintensity are the computed radii, intensity and total intensity
+values at each radial step.
+
+
+.ih
+ERRORS
+
+If the object centering was error free then the field cier will be zero.
+Non-zero values of cier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 101 # The centering box is off image
+ 102 # The centering box is partially off the image
+ 103 # The S/N ratio is low in the centering box
+ 104 # There are two few points for a good fit
+ 105 # The x or y center fit is singular
+ 106 # The x or y center fit did not converge
+ 107 # The x or y center shift is greater than maxshift
+ 108 # There is bad data in the centering box
+.fi
+
+If all goes well during the sky fitting process then the error code sier
+will be 0. Non-zero values of sier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 201 # There are no sky pixels in the sky annulus
+ 202 # Sky annulus is partially off the image
+ 203 # The histogram of sky pixels has no width
+ 204 # The histogram of sky pixels is flat or concave
+ 205 # There are too few points for a good sky fit
+ 206 # The sky fit is singular
+ 207 # The sky fit did not converge
+ 208 # The graphics stream is undefined
+ 209 # The file of sky values does not exist
+ 210 # The sky file is at EOF
+ 211 # Cannot read the sky value correctly
+ 212 # The best fit parameter are non-physical
+.fi
+
+If no error occurs during the measurement of the magnitudes then pier is
+0. Non-zero values of pier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 301 # The aperture is off the image
+ 302 # The aperture is partially off the image
+ 303 # The sky value is undefined
+ 305 # There is bad data in the aperture
+.fi
+
+If no error occurs during the profile fitting then rier is 0.
+Non-zero values of rier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 901 # The profile region is off the image
+ 902 # The profile region is partially off the image
+ 903 # There are too few points in the profile
+ 904 # The fit is singular
+ 905 # The sky value is undefined
+.fi
+
+.ih
+EXAMPLES
+
+1. Compute the radial profiles for a few stars in dev$ypix using the
+display and the image cursor. Setup the task parameters using the
+interactive setup menu defined by the i key command.
+
+.nf
+ ap> display dev$ypix 1 fi+
+
+ ... display the image
+
+ ap> radprof dev$ypix 7.0 0.5
+
+ ... type ? to print a short help page
+
+ ... move the image cursor to a star
+ ... type i to enter the interactive setup menu
+ ... enter maximum radius in pixels of the radial profile or
+ CR to accept the default value
+ ... set the fwhmpsf, centering radius, inner and outer sky
+ annuli, apertures, sigma, profile radius and step size
+ using the graphics cursor and the stellar radial profile
+ plot
+ ... typing <CR> leaves everything at the default value
+ ... type q to quit the setup menu
+
+ ... type the v key to verify the parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... move the image cursor to the star of interest and tap
+ the space bar
+
+ ... type :order 3 to change the spline order and see if the
+ fit improves, if it does type w
+
+ ... a radial profile plot will appear on the graphics terminal
+
+ ... type q to quit and q to confirm the quit
+
+ ... by default radprof does not create an output file
+.fi
+
+2. Compute the radial profiles for a few stars in dev$ypix using a contour
+plot and the graphics cursor. Setup the task parameters using the interactive
+setup menu defined by the i key command. This option is only useful for
+those users (now very few) who do not have access to an image display server
+but do have access to a graphics terminal.
+
+.nf
+ ap> show stdimcur
+
+ ... determine the default value of stdimcur
+
+ ap> set stdimcur = stdgraph
+
+ ... define the image cursor to be the graphics cursor
+
+ ap> contour dev$ypix
+
+ ... make a contour plot of dev$ypix
+
+ ap> contour dev$ypix >G ypix.plot1
+
+ ... store the contour plot of dev$ypix in ypix.plot1
+
+ ap> radprof dev$ypix 7.0 0.5
+
+ ... type ? to print the help page
+
+ ... move graphics cursor to a star
+ ... type i to enter the interactive setup menu
+ ... enter maximum radius in pixels of the radial profile or
+ hit CR to accept the default value
+ ... set the fwhmpsf, centering radius, inner and outer sky annuli,
+ apertures, sigma, profile radius and step size using the
+ graphics cursor and the stellar radial profile plot
+ ... typing <CR> leaves everything at the default value
+ ... type q to quit the setup menu
+
+ ... type the v key to verify the parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... type :.read ypix.plot1 to reload the contour plot
+
+ ... move the graphics cursor to the star of interest and tap
+ the space bar
+
+ ... a radial profile plot will appear on the graphics terminal
+
+ ... repeat the above sequence for each additional star
+
+ ... type q to quit and q to confirm the quit
+
+ ... by default radprof does not create an output file
+.fi
+
+3. Setup and run RADPROF interactively on a list of objects temporarily
+overriding the fwhmpsf, sigma, cbox, annulus, dannulus, apertures,
+radius, and step parameters determined in examples 1 or 2.
+
+.nf
+ ap> daofind dev$ypix fwhmpsf=2.6 sigma=25.0 verify-
+
+ ... make a coordinate list
+
+ ... the output will appear in the text file ypix.coo.1
+
+ ap> radprof dev$ypix 7.0 0.5 fwhmpsf=2.6 sigma=5.0 cbox=7.0 \
+ annulus=10.0 dannulus=5.0 apertures=5.0 coords=ypix.coo.1
+
+ ... type ? for optional help
+
+
+ ... move the graphics cursor to the stars and tap space bar
+
+ or
+
+ ... select stars from the input coordinate list with m / :m #
+ and measure with spbar
+
+ ... measure stars selected from the input coordinate list
+ with n / n #
+
+ ... a one line summary of results will appear on the standard output
+ for each star measured
+
+ ... type q to quit and q again to confirm the quit
+
+ ... by default radprof does not create an output file
+.fi
+
+4. Display and fit some stars in an image section and write the output
+coordinates in the coordinate system of the parent image.
+
+.nf
+ ap> display dev$ypix[150:450,150:450] 1
+
+ ... display the image section
+
+ ap> radprof dev$ypix[150:450,150:450] 7.0 0.5 output=default \
+ wcsout=tv
+
+ ... move cursor to stars and type spbar
+
+ ... type q to quit and q again to confirm quit
+
+ ... output will appear in ypix.prf.1
+
+ ap> pdump ypix.prf.1 xc,yc yes | tvmark 1 STDIN col=204
+.fi
+
+
+5. Run RADPROF in batch mode using the coordinate file and the previously
+saved parameters. Save the text and plot output.
+
+.nf
+ ap> radprof dev$ypix 7. 0.5 coords=ypix.coo.1 output="default" \
+ plotfile=ypix.rplots inter- verify-
+
+ ... output will appear in m92.prf.2 and ypix.rplots
+
+ ap> gkidir ypix.rplots
+
+ ... get a listing of the plots in ypix.rplots
+
+ ap> gkiextract ypix.rplots 1-3 | stdplot dev=lw16
+
+ ... extract plots 1-3 and plot them on device lw16
+.fi
+
+6. Repeat example 5 but assume that the input coordinates are ra and dec
+in degrees and degrees, turn off verification, and submit the task to to
+the background.
+
+.nf
+ ap> display dev$ypix 1
+
+ ap> rimcursor wcs=world > radec.coo
+
+ ... move to selected stars and type any key
+
+ ... type ^Z to quit
+
+ ap> radprof dev$ypix 7.0 0.5 coords=radec.coo output=default \
+ plotfile=ypix.rplots2 wcsin=world verify- inter- &
+
+ ... output will appear in ypix.prf.3, plots will appear in
+ ypix.rplots2
+
+ ap> pdump ypix.prf.3 xc,yc yes | tvmark 1 STDIN col=204
+
+ ... mark the stars on the display
+.fi
+
+
+7. Run RADPROF interactively without using the image display.
+
+.nf
+ ap> show stdimcur
+
+ ... record the default value of stdimcur
+
+ ap> set stdimcur = text
+
+ ... set the image cursor to the standard input
+
+ ap> radprof dev$ypix 7.0 0.5 coords=ypix.coo.1
+
+ ... type ? for optional help
+
+ ... type :m 3 to set the initial coordinates to those of the
+ third star in the list
+
+ ... type i to enter the interactive setup menu
+ ... enter the maximum radius in pixels for the radial profile or
+ accept the default with a CR
+ ... type v to enter the default menu
+ ... set the fwhmpsf, centering radius, inner and outer sky annuli,
+ apertures, and sigma using the graphics cursor and the
+ stellar radial profile plot
+ ... typing <CR> after the prompt leaves the parameter at its default
+ value
+ ... type q to quit the setup menu
+
+ ... type r to rewind the coordinate list
+
+ ... type n to measure the next star
+
+ ... a one line summary of the answers will appear on the standard
+ output for each star measured
+
+ ... type q to quit followed by q to confirm the quit
+
+ ... by default no output file is written
+
+ ap> set stdimcur = <default>
+
+ ... reset the value of stdimcur
+.fi
+
+8. Use a image cursor command file to drive the RADPROF task. The cursor
+command file shown below sets the cbox, annulus, dannulus, and apertures
+parameters computes the centers, sky values, magnitudes, and readial profiles
+for 3 stars, updates the parameter files, and quits the task.
+
+.nf
+ ap> type cmdfile
+ : cbox 9.0
+ : annulus 12.0
+ : dannulus 5.0
+ : apertures 5.0
+ 442 410 101 \040
+ 349 188 101 \040
+ 225 131 101 \040
+ w
+ q
+
+ ap> radprof dev$ypix 7.0 0.5 icommands=cmdfile \
+ plotfile=ypix.rplots3 verify-
+
+ ... by default no output file is written, plots will appear in
+ ypix.rplots3
+.fi
+
+
+.ih
+BUGS
+
+It is currently the responsibility of the user to make sure that the
+image displayed in the frame is the same as that specified by the image
+parameter.
+
+Commands which draw to the image display are disabled by default.
+To enable graphics overlay on the image display, set the display
+parameter to "imdr", "imdg", "imdb", or "imdy" to get red, green,
+blue or yellow overlays and set the centerpars mkcenter switch to
+"yes", the fitskypars mksky switch to"yes", or the photpars mkapert
+witch to "yes". It may be necessary to run gflush and to redisplay the image
+to get the overlays position correctly.
+
+.ih
+SEE ALSO
+datapars, centerpars, fitskypars, photpars
+.endhelp
diff --git a/noao/digiphot/apphot/doc/specs/Ap.doc b/noao/digiphot/apphot/doc/specs/Ap.doc
new file mode 100644
index 00000000..66744d58
--- /dev/null
+++ b/noao/digiphot/apphot/doc/specs/Ap.doc
@@ -0,0 +1,1071 @@
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+1. Introduction
+
+ The APPHOT package will provide a set of routines for performing
+aperture photometry on uncrowded or moderately crowded fields, in
+either interactive or batch mode. The basic photometry technique
+employed shall be fractional-pixel aperture integration; no PSF
+fitting techniques shall be employed, and no knowledge of the PSF
+shall be required. This document presents the formal requirements and
+specifications for the package, and describes the algorithms to be
+used.
+
+
+
+2. Requirements
+
+ (1) The program shall take as input an IRAF imagefile containing a
+ starfield which has been corrected for pixel to pixel gain
+ variations, high frequency fluctuations in the background,
+ nonlinearity, and any other instrumental defects affecting the
+ intensity value of a pixel.
+
+ (2) Given as input the approximate coordinates of a single object
+ in the image, the program shall perform the following
+ operations:
+
+ o Determine a constant background value by analysis of
+ an annular region surrounding the object. The
+ background is assumed to be flat in the region of the
+ object, but may contain contaminating objects or
+ defects which shall be detected and eliminated by the
+ fitting algorithm. It shall be permissible for the
+ background region to extend beyond the boundaries of
+ the image; the out of bounds region of the annulus
+ shall be excluded from the fit.
+
+ o Determine the center of the object, taking the
+ approximate object coordinates given as input as a
+ starting point. The center determination shall be
+ resistant to the affects of nearby contaminating
+ objects. The centering algorithm may assume that the
+ object is circularly symmetric, or nearly so, and that
+ the object flux is positive.
+
+ o Determine the integral of object minus background
+ within one or more circular apertures centered upon
+ the object. The integration shall be performed using
+ partial pixel techniques, to minimize the effects of
+ sampling. If the aperture contains any indefinite
+ pixels, or if the aperture extends beyond the boundary
+ of the image, an indefinite result shall be returned.
+
+ (3) The following options shall be provided to modify the
+ operation of the above functions:
+
+
+ -1-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+ o Use a user supplied constant background value and
+ background noise estimate instead of fitting the
+ background.
+
+ o Use the starting center as the actual center in all
+ cases.
+
+ o Use the starting center as the actual center if the
+ object is very faint, but tweak up the center if the
+ signal to noise is above a certain threshold.
+
+ o Allow the object aperture to extend beyond the image
+ boundary, using only that portion of the aperture
+ which is in bounds when computing the aperture
+ integral.
+
+ (4) At a minimum, the following parameters shall be calculated and
+ output for each object:
+
+ o The coordinates of the object, and the estimated error
+ in these coordinates.
+
+ o The mode and standard deviation of the background; the
+ number of pixels left in the background region after
+ pixel rejection.
+
+ o The magnitude of the object, to within an arbitary
+ zero-point, and the statistical uncertainty of the
+ magnitude. If multiple concentric apertures are used,
+ a magnitude and uncertainty shall be given for each.
+
+ (5) The program shall be usable both interactively and in batch
+ mode. In interactive use, the user shall be able to mark the
+ positions of the objects by interactively positioning a cursor
+ on a 2-dim display device. It shall be possible to enter the
+ control parameters for the analysis routines interactively for
+ each object. In batch mode, the control parameters shall be
+ fixed, and object coordinates shall be taken from a user
+ supplied list. The display device shall not be required in
+ batch mode.
+
+ (6) The APPHOT package shall be written in the SPP language in
+ conformance with the standards and conventions of IRAF. The
+ code shall be portable and device independent.
+
+
+
+2.1 Summary of the Limitations of APPHOT
+
+ The APPHOT package is designed to perform simple aperture
+photometry subject to the following restrictions:
+
+ (1) Objects must be circular or nearly circular, since the
+
+
+ -2-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+ aperture is circular.
+
+ (2) All pixels within the object aperture are weighted equally.
+ All pixels in the object aperture must be present; the object
+ aperture may not normally extend outside the image. Defective
+ pixels within the object aperture may not be detected.
+
+ (3) The background must be approximately flat in the neighborhood
+ of the object being measured. The background must have a
+ unique mode, or the background fitting routine will reject the
+ object. Any low frequency fluctuations in the background
+ should be removed before using APPHOT.
+
+ (4) The object aperture must be kept small to minimize the
+ degradation of signal to noise caused by sky pixels within the
+ aperture, and to minimize the effects of crowding. Therefore,
+ the wings of the object will extend beyond the aperture. Good
+ photometric results will be obtained only if the aperture is
+ consistently well centered, and if the shape and diameter of
+ an object is constant throughout the image and invariant with
+ respect to magnitude.
+
+
+
+3. Specifications
+
+ The APPHOT package performs aperture photometry on digitized
+starfields maintained as IRAF imagefiles. Input to the package
+consists of an imagefile, a list of object coordinates, and numerous
+parameters controlling the analysis algorithms. Output consists of
+successive lines of text, where each line summarizes the results of
+the analysis for a particular object. The output may be saved in a
+textfile, which may easily be printed or written onto a card image
+tape for export. The package routines may be used either
+interactively or in batch mode.
+
+The CL callable part of the APPHOT package consists of the following
+routines:
+
+ apphot -- the main aperture photometry routine.
+ coordtr -- translations and rotations of coord lists.
+ fitsky -- computes mode and sigma of a sky region.
+ fitpsf -- compute the FWHM of the PSF.
+ imcursor -- reads the image cursor; used to make lists.
+ immark -- marks objects on the display device.
+ radprof -- computes the radial profile of an object.
+
+Routines for general list manipulation, reading and writing card image
+tapes, reading and writing images to FITS tapes, removing the
+instrumental signature from the data, and so on are available
+elsewhere in the IRAF system. The package is easily extended to
+include peak finding, matching of object lists from different images,
+background fitting and removal, and so on. The APPHOT package shall
+
+
+ -3-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+eventually supplant both the KPNO AUTOPHOT and KPNO "Mountain
+Photometry Code" packages.
+
+
+
+3.1 Standard Analysis Procedures
+
+ Before performing aperture photometry one must determine the radius
+of the object aperture to be used, the inner radius and size of the
+annulus to be used to fit the background, the full width at half max
+(FWHM) of the point spread function (PSF), and so on. Additional
+parameters are required by the centering algorithm. A list of object
+centers must be prepared if APPHOT is to be used in batch mode. The
+standard procedure is as follows:
+
+ (1) Use RADPROF to determine values for the following parameters:
+
+ - the object aperture radius or radii, in pixels
+ - the inner radius of the annular (sky) region
+ - the width of the annular region
+
+ (2) Use FITPSF to fit gaussians to isolated, high signal to noise
+ data objects, to determine the FWHM of the point spread
+ function.
+
+ (3) Use FITSKY to determine the sky sigma (standard deviation).
+ APPHOT assumes that sigma is approximately constant throughout
+ the image.
+
+ (4) If one does not wish to manually mark object positions with
+ the cursor during analysis, i.e. when the analysis is to be
+ done in batch, a list of object coordinates must be prepared.
+ This may be done in many ways:
+
+ o By running RCURSOR with the standard output redirected
+ into the list file.
+
+ o By transforming an existing list with COORDTR, OPSTRM,
+ MATCH, SORT, WINDOW, the editor, or some other filter.
+
+ o By an automatic object finding procedure, if one is
+ available.
+
+ o By any other program which generates a list of object
+ coordinates, where each line of the list describes one
+ object, and where x and y in pixel coordinates are
+ given in columns one and two. Additional columns, if
+ present, are ignored.
+
+ o APPHOT output may be used as coordinate input in a
+ subsequent run.
+
+ (5) Finally, APPHOT is run to measure the objects. The user
+
+
+ -4-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+ should be familiar with the algorithms used to fit the
+ background, measure the object center, and compute the
+ aperture integral, magnitude, and errors. The values of all
+ visible and hidden APPHOT parameters should be inspected
+ before doing any serious processing.
+
+The general purpose IRAF list processing tools may be used for further
+analysis of APPHOT output. Output lists may be filtered to select
+objects based on the value of a list column, i.e., all the objects
+within a certain magnitude range may be selected, objects with
+estimated errors larger than a certain value may be deleted, or a list
+may be sorted using the value in any column. Columns may be extracted
+from a list to form new lists or to provide input to a plot filter,
+and lists may be merged. Arithmetic may be performed on lists to
+calculate colors, etc.
+
+The remainder of this section presents detailed specifications for the
+analysis procedures in the APPHOT package.
+
+
+
+3.2 The APPHOT Program
+
+ The function of the APPHOT procedure is to perform aperture
+photometry on isolated objects within an image. The principal input
+operands are the name of the imagefile and the rough coordinates of
+the objects to be processed. The principal output operands are the
+coordinates and magnitudes of the objects.
+
+In order to perform aperture photometry APPHOT must perform the
+following sequence of operations (the algorithms employed are
+explained in more detail later in this section):
+
+ (1) The mode and sigma of an annular background region centered on
+ the object is calculated.
+
+ (2) The center of the object is determined.
+
+ (3) The background is subracted from the object, and the total
+ flux within the object aperture or apertures is calculated.
+
+Steps (1) and (2) above are optional; the background and center may be
+determined externally, rather than by APPHOT, if desired.
+
+
+3.2.1 APPHOT parameters
+
+ APPHOT has quite a few parameters due to the complexity of the
+algorithms employed. All data dependent parameters are query mode to
+ensure that they get set properly when a new image is processed. The
+data independent algorithm control parameters are hidden mode, and are
+given reasonable default values. The names, datatypes, and default
+values of the APPHOT parameters are shown below.
+
+
+ -5-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+Positional or query mode parameters:
+
+ image filename
+ apertures string
+ annulus real
+ width_annulus real
+ fwhm_psf real
+ sky_sigma real
+
+
+List structured parameters (filename may be given on command line):
+
+ sky_mode *real
+ coords *imcur
+
+
+Hidden parameters:
+
+ spool boolean no
+ output filename "apphot.out"
+ fitsky boolean yes
+ max_sky_iter integer 50
+ growing_radius real 1.0 (fwhm_psf units)
+ k1 real 5.0
+ k2 real 2.0
+ center boolean yes
+ clean boolean yes
+ cleaning_radius real 0.8 (fwhm_psf units)
+ clipping_radius real 1.5 (fwhm_psf units)
+ max_cen_shift real 1.0 (fwhm_psf units)
+ min_snratio real 0.5
+ zmag real 26.0
+ verbose boolean yes
+
+
+The function and format of each of these parameters is explained in
+more detail below.
+
+
+ image The name of the image or image section to be
+ processed.
+
+ output The name of the output textfile used to spool
+ APPHOT output. If null, output will not be
+ spooled. Note that output always appears on the
+ standard output, whether or not spooling is in
+ effect.
+
+ apertures The radii in pixels of the concentric object
+ apertures, given all on the same line, delimited
+ by blanks. At least one aperture must be given;
+ the maximum number of apertures is limited by the
+ length of a line. A sample input string might be
+
+
+ -6-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+ "5.0 5.5 6.0 6.5 7.0". If only a single aperture
+ is to be used, a real expression may be used
+ instead of a string type argument. The apertures
+ need not be given in any particular order. The
+ average radius will be used to compute the
+ uncertainty in the object magnitude.
+
+ annulus The inner radius of the annular sky region, in
+ pixels.
+
+ width_annulus The width of the annular sky region, in pixels.
+
+ fwhm_psf The FWHM of the psf, in pixels. Used as a scale
+ factor to control the internal algorithms.
+
+ sky_sigma The standard deviation (noise value) of a typical
+ region of sky in the image. Used for pixel
+ rejection in the sky fitting algorithm.
+
+ sky_mode The name of a list file containing the mode of the
+ background of each of the objects to be
+ processed. Required only if FITSKY is switched
+ off. If sky fitting is disabled, and no list file
+ is given, APPHOT will query for the sky value.
+
+ coords The name of a list file containing the coordinates
+ of the objects to be processed. If absent,
+ objects may be marked interactively with the
+ cursor.
+
+ fitsky A switch used to specify whether or not the
+ background will be fitted. If background fitting
+ is disabled, the mode and sigma of the background
+ will be read from the SKY_FILE list each time an
+ object is processed.
+
+ max_sky_iter The maximum number of iterations for the sky
+ fitting algorithm. Since the sky fitting
+ algorithm is guaranteed to converge, this
+ parameter should normally have a large value. If
+ the value is zero, the median of the sky region
+ will be used instead of the mode.
+
+ growing_radius The region growing radius for pixel rejection in
+ the sky region, in units of FWHM_PSF. When a bad
+ sky pixel is detected, all pixels within
+ (growing_radius * fwhm_psf) pixels of the bad
+ pixel will be rejected. Used to exclude the wings
+ of contaminating objects from the sky sample, to
+ avoid biasing the mode.
+
+ k1 The k-sigma clipping factor for the first phase of
+ the sky fitting algorithm.
+
+
+ -7-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+ k2 The k-sigma clipping factor for the second,
+ iterative, phase of the sky fitting algorithm.
+
+ center A switch used to specify whether or not centering
+ is to be performed. If centering is disabled, the
+ initial center will be used as the object center.
+
+ clean A switch used to specify whether or not the
+ symmetry-clean algorithm is to be employed during
+ centering.
+
+ cleaning_radius The cleaning radius for the symmetry-clean
+ algorithm, in units of FWHM_PSF.
+
+ clipping_radius The clipping radius for the symmetry-clean
+ algorithm, in units of FWHM_PSF.
+
+ max_cen_shift The maximum permissible shift of center, in units
+ of FWHM_PSF. If the shift produced by the
+ centering algorithm is larger than this value, the
+ fit will terminate and no magnitude will be
+ calculated.
+
+ min_snratio Centering will be skipped if the signal to noise
+ of the object, as calculated from the initial
+ center, is less than the value given by this
+ parameter.
+
+ zmag Zero point for the output magnitude scale.
+
+ verbose If enabled, the output columns are labeled. Note
+ that the presence of column labels in the output
+ may interfere with the use of the list processing
+ tools.
+
+
+
+3.2.2 The APPHOT Background Fitting Algorithm
+
+ A good background fit is essential to aperture photometry. Fitting
+the background is trivial in a sparse field, but difficult in a crowded
+field. In general the background region will contain contaminating
+objects which must be detected and excluded if a good fit is to be
+obtained.
+
+The algorithm employed here is based on the fact that contaminated
+pixels are almost always spatially correlated. Background fitting
+algorithms which work with a one dimensional sample (mode, median), or
+with the one dimensional histogram (mode of hgm) have difficulty
+rejecting the faint wings of contaminated regions. This is a serious
+defect of one dimensional fitting algorithms, because it is these
+faint wings, not the bright central pixels, which are most likely to
+bias the calculated background value.
+
+
+ -8-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+The algorithm used in APPHOT is as follows:
+
+
+ algorithm fit_sky
+
+ begin
+ # Reject gross deviants.
+ compute the median of the annular region
+ detect pixels more than (k1*sky_sigma) from the median
+ reject all such pixels, without region growing
+
+ # Detect and reject contaminating objects.
+ while (number of iterations <= max_sky_iter) {
+ compute the histogram of the reduced sample
+ compute the sigma and mode of the histogram
+ detect pixels more than k2*sigma from the mode
+ reject all such pixels, with region growing
+ if (no pix rejected or all pix rejected)
+ terminate loop
+ }
+
+ return the final mode, sigma, and sample size
+ end
+
+
+The mode of the histogram is found by cross correlating the noise
+function with the histogram. The width of the the noise function is
+given by the standard deviation of the current sample. Pixel
+rejection is performed by locating all pixels more than k2*sigma from
+the mode, and blindly rejecting all pixels within a certain radius of
+each deviant pixel. This simple algorithm works well because the
+sample is large, and therefore there is little penalty for discarding
+pixels that might not be deviant. Region growing also tends to
+accelerate convergence significantly.
+
+Very faint contaminating objects are difficult to detect and reject.
+If there are enough such objects, they should not be rejected, because
+there are probably a few in the object aperture as well. A higher sky
+sigma will be calculated and the computed uncertainty in the magnitude
+will increase. The best solution to this problem may be to increase
+the size of the annulus to minimize the bias and maximize the liklihood
+of a detection.
+
+
+
+3.2.3 The APPHOT Centering Algorithm
+
+ The centering algorithm used in APPHOT is that of Auer and Van
+Altena, with the addition of the symmetry-clean algorithm developed by
+Barry Newell. The main algorithm is as follows:
+
+
+
+
+
+ -9-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+ algorithm get_center
+
+ begin
+ if (centering is disabled) {
+ return initial center, zero uncertainty estimate
+
+ } else if (signal to noise of object < MIN_SNRATIO) {
+ compute uncertainty using initial center
+ return initial center, computed uncertainty
+
+ } else {
+ call measure_center
+ return image center and estimated uncertainty
+ }
+ end
+
+
+The actual center determination is carried out by the following
+algorithm:
+
+
+ algorithm measure_center
+
+ begin
+ extract subarray from the main data array
+
+ # Perform symmetry-cleaning.
+ if (cleaning is enabled) {
+ for (each pair of pixels diametrically opposed about
+ the image center beyond the cleaning radius)
+ if (i2 > i1 + 2*sky_sigma)
+ replace i2 by i1
+ else if (i1 > i2 + 2*sky_sigma)
+ replace i1 by i2
+
+ perform 2*sky_sigma noniterative clip of all pixels
+ beyond the clipping radius, to remove any remaining
+ radially symmetric structures
+ }
+
+ # Compute the image center and uncertainty.
+ compute x and y marginals of the cleaned subarray
+ fit a gaussian of width FWHM_PSF to each marginal
+ compute the centering error from the covariance matrix
+
+ return image center and estimated uncertainty
+ end
+
+
+The effect of the symmetry-clean algorithm is to edit the raster,
+removing any contaminating objects in the vicinity of the primary
+object. This simplifies the fitting algorithm and increases its
+reliability, since it does not have to deal with multipeak marginal
+
+
+ -10-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+distributions.
+
+A gaussian is fitted to the marginal distributions because it is
+expected to yield a better center determination for undersampled
+data. An alternative is to empirically derive the marginal
+distributions of the psf and fit these to each data object. This is a
+better approach in some cases, but in the case of undersampled data it
+is difficult to derive the marginal distributions due to sampling
+effects, and fitting is difficult due to interpolation error. The use
+of a gaussian eliminates interpolation error. Eventually, both
+techniques should be made available.
+
+
+
+3.2.4 The APPHOT Aperture Integration Algorithm
+
+ The integral of the flux within a circular aperture is computed by
+fractional pixel techniques. Pixels are assumed to be square apertures
+arranged in a rectangular grid. The fraction of a pixel which lies
+within the circular APPHOT aperture is computed by an approximation,
+and all such contributions are summed to produce the total integral.
+
+The simplicity of aperture photometry limits the amount of information
+available for error analysis. Using only the noise value for the
+background, the estimated error in the aperture integral is given by
+
+ flux_error = sky_sigma * sqrt (aperture_area)
+
+where "sky_sigma" is either the sigma calculated by the background
+fitting algorithm or the parameter SKY_SIGMA, depending on whether sky
+fitting is enabled, and where "aperture_area" is the fractional pixel
+area of the aperture.
+
+It is possible, however, to produce a more useful error estimate if we
+include some information about the psf. For the purposes of an
+improved error estimate, we assume that the PSF is a gaussian. Given
+the object center, the background, and the FWHM of the PSF, it is
+trivial to fit a two dimensional gaussian to the object. An estimate
+of the average noise value for the pixels within the aperture may then
+be obtained by computing the standard deviation of the residual formed
+by subtracting the fitted two-dimensional gaussian from the data.
+This value is used in place of SKY_SIGMA in the above equation for an
+improved estimate of the actual flux error.
+
+In the limit as the gaussian goes to zero, both uncertainty estimates
+tend to the same value, as they should. For bright objects, the
+uncertainty produced by analysis of the residual will tend to be
+pessimistic, since it is unlikely that the PSF can actually be modeled
+by a simple gaussian. Nonetheless, a plot of uncertainty versus
+magnitude should reveal objects which are blended, which contain bad
+pixels, and so on. The accuracy of the gaussian model will determine
+how reliably deviant objects can be discriminated.
+
+
+
+ -11-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+3.2.5 APPHOT Output
+
+ For each object processed, APPHOT prints a single line of text on
+the standard output. If desired, APPHOT will simultaneously spool
+output into a user specified text file. Each output line will contain
+the following information (excluding the commas):
+
+
+ x,y,cenerr,shift, mode,sigma,nskypix, mag1,...,magn,magerr
+
+where
+
+ x,y object coordinates in pixels
+ cenerr estimated uncertainty in the object center
+ shift shift of center from initial coordinates
+ mode mode of the background
+ sigma sigma of the background
+ nskypix number of sky pixels left after rejection
+ mag1 magnitude within the first annulus
+ magn magnitude within the Nth annulus
+ magerr estimated mag. uncertainty at the average radius
+
+
+Note that the estimated uncertainty in the magnitude is given only for
+the average object aperture radius. The uncertainty for the other
+apertures can easily be calculated given SIGMA and the area of each
+aperture. The zero point for the magnitude scale is given by the
+hidden parameter ZMAG.
+
+Additional information could be calculated and output (such as the
+moments of the object and the skew of the background), but in our
+experience few people ever look at such information, and a more complex
+output format would be required. Probably the calculation of anything
+but object centers, magnitudes, and errors should be left to other
+programs.
+
+
+
+3.3 The COORDTR Program
+
+ The function of COORDTR is to effect a linear translation and/or
+rotation of a coordinate list. COORDTR is a filter; coordinate lines
+are read from the standard input and written to the standard output.
+COORDTR is concerned only with coordinate transformations, and knows
+nothing about image boundaries. A transformed coordinate may no longer
+lie within an image.
+
+ x y other_stuff
+
+The format of a coordinate line is shown above. COORDTR operates only
+on the coordinate pair x,y. Any additional information on the line is
+passed on to the output without modification.
+
+
+
+ -12-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+COORDTR is actually a general purpose list processing operator, and
+belongs in a list processing package, rather than in the APPHOT
+package. When a list processing package is developed, COORDTR will be
+moved to that package.
+
+A COORDTR transformation consists of a linear translation followed by
+a rotation. Either the translation, the rotation, or both may be
+skipped. The COORDTR parameters are summarized below.
+
+
+positional arguments:
+
+ xshift real
+ yshift real
+ xcenter real
+ ycenter real
+ theta real
+
+
+hidden parameters:
+
+ translate boolean yes
+ rotate boolean no
+
+
+If more than two positional arguments are given, COORDTR knows that
+both a translation and a rotation are desired. Otherwise the boolean
+parameters TRANSLATE and ROTATE are read to determine what additional
+parameters are needed. Thus a simple linear translation of +2.5
+pixels in X and -0.2 pixels in Y would be specified by the command
+
+ coordtr (2.5, -.2, < "input", > "output")
+
+which transforms the list in file "input", writing the output into the
+new file "output".
+
+If a rotation is desired, XCENTER, YCENTER, and THETA must be given.
+The first two parameters specify the pixel coordinates of the point
+about which the rotation is to be performed, while THETA specifies the
+rotation angle in degrees. Positive THETA produces a counterclockwise
+rotation, if positive X is to the right and positive Y is up.
+
+
+
+3.4 The FITSKY Program
+
+ The function of the FITSKY program is to determine the mode and
+sigma of the specified annular regions, printing the results (mode,
+sigma, and npix) on the standard output. FITSKY is similar in
+operation to APPHOT, except that its function is to fit sky, not
+perform aperture photometry. The FITSKY parameters are the following:
+
+
+
+
+ -13-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+Positional or query mode parameters:
+
+ image filename
+ annulus real
+ width_annulus real
+ fwhm_psf real
+
+
+List structured parameters (filename may be given on command line):
+
+ coords *imcur
+
+
+Hidden parameters:
+
+ spool boolean no
+ output filename "fitsky.out"
+ max_sky_iter integer 50
+ growing_radius real 1.0 (fwhm_psf units)
+ k1 real 5.0
+ k2 real 2.0
+ verbose boolean yes
+
+
+The names and functions of the FITSKY parameters are the same as those
+for APPHOT. Note that ANNULUS may be set to zero to measure the
+background within a circular aperture. The maximum number of
+iterations may be set to zero to measure the median of the sky sample.
+FITSKY output may be spooled into a file and used as input to APPHOT.
+
+
+
+3.5 The FITPSF Program
+
+ The function of the FITPSF program is to determine the FWHM of the
+point spread function. This is done by selecting an isolated, high
+signal to noise object, computing the x and y marginal profiles, and
+fitting a gaussian to each profile. Output consists of the object
+center, the error in the center, and the FWHM of the fitted gaussians.
+Note that the sigma of a gaussian may be obtained by dividing the FWHM
+by 2.354.
+
+ x y err x_fwhm y_fwhm
+
+The input parameters for the FITPSF program are shown below.
+
+
+
+
+
+
+
+
+
+
+ -14-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+Positional parameters:
+
+ image filename
+ aperture real
+ annulus real
+ width_annulus real
+ sky_mode real
+ coords *imcur
+
+
+Hidden parameters:
+
+ fitsky boolean yes
+ center boolean yes
+ spool boolean no
+ output filename "fitpsf.out"
+ verbose boolean yes
+
+
+If background fitting is disabled, the parameter SKY_MODE defines the
+sky level. The background fitting algorithm is a simple median
+calculation without pixel rejection or iteration. This should be
+sufficient, since FITPSF is expected to be used mainly in uncrowded
+regions on high signal to noise objects.
+
+Note that FITPSF is set up to process a list of input objects. The
+list processing tools (i.e., AVERAGE) may be used to average the
+results to produce the final FWHM of the PSF for the image.
+
+
+
+3.6 The IMCURSOR Program
+
+ The function of the IMCURSOR program is to read the STDIMAGE
+cursor, writing the cursor coordinates on the standard output. The
+cursor is read until the EOF character is entered to terminate the
+loop. The standard output may be redirected into a file to generate a
+coordinate list. IMCURSOR has no parameters.
+
+
+
+3.7 The IMMARK Program
+
+ The function of IMMARK is to draw marks on the diplay device.
+IMMARK is useful for verifying coordinate lists.
+
+
+parameters:
+
+ mark_type string
+ mark_size real
+ coords *imcur
+
+
+
+ -15-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+Output is the current frame of the STDIMAGE device. Mark types
+include "circle", "box", "cross", "plus", and "diamond". The size of
+a mark is given in pixels. The third parameter is a standard
+coordinate list. If no list is given, the image cursor will be read
+instead.
+
+
+
+3.8 The RADPROF Program
+
+ The function of the RADPROF program is to compute the radial
+profile of an object. The output of RADPROF consists of a sequence of
+lines of text, each line defining the profile at a single radius.
+Since RADPROF may generate many lines of output for a single input
+object, it is set up to process only a single input object. A CL
+while loop may be written to process multiple objects, if desired.
+
+
+positional arguments:
+
+ image filename
+ aperture real
+ step_size real
+ annulus real
+ width_annulus real
+ sky_mode real
+
+
+hidden parameters:
+
+ fitsky boolean yes
+ center boolean yes
+ verbose boolean yes
+
+
+The radial profile is calculated from the image center out to the
+radius specified by the parameter APERTURE, in steps of STEP_SIZE
+pixels. The remaining RADPROF parameters are similar to those of
+APPHOT and will not be discussed in detail. If background fitting is
+disabled, the parameter SKY_MODE defines the sky level. The
+background fitting algorithm is a simple median calculation without
+pixel rejection or iteration. This should be sufficient, since
+RADPROF is expected to be used mainly in uncrowded regions on high
+signal to noise objects. Centering is via gaussian fits to the
+marginal profiles, without cleaning.
+
+RADPROF output lines contain the following fields:
+
+ r, i(r), inorm(r), fraction(r)
+
+where
+
+ r radius in pixels
+
+
+ -16-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+ i(r) raw intensity at r
+ inorm(r) normalized intensity at r (range 0-1)
+ fraction(r) fraction of total integral at r
+
+
+RADPROF does not generate any plots. If one wishes to plot the
+contents of an output column, the column may be extracted with a list
+processing filter and piped to a graphics task.
+
+
+
+4.0 Example
+
+ A brief example may help illustrate the use of the package.
+Suppose we want to process a few hundred stars on images "blue" and
+"red". We start by analyzing the blue image.
+
+ ap> radprof blue,15,0.5,20,10
+
+This gives us a radial profile printout for one of the "blue" stars.
+We decide that an aperture radius of 2.5 pixels is about right. The
+annulus will start at a radius of 10.0 pixels and extend to 20.0
+pixels. The next step is to determine the FWHM of the PSF:
+
+ ap> fitpsf blue,3,10,20 | tee spoolfile
+
+By default, the program will take coordinate input by reading the image
+display cursor. When the program is waiting for cursor input, it will
+cause the display cursor to blink rapidly; normally the cursor does not
+blink. One has to be aware of this, because no other prompt is issued.
+We postion the cursor on several stars, and tap the space bar to
+measure each one. When finished we type the EOF character (<ctrl/z>
+on our systems) to terminate the loop. The screen will now look like
+this (the output column labels are ommitted):
+
+ ap> fitpsf blue,3,10,20 | tee spoolfile
+ 283.12 157.40 0.035 2.887 2.751
+ 546.08 213.45 0.023 2.833 2.902
+ 318.32 354.73 0.064 2.791 2.824
+
+Since we elected to use TEE to spool the output, rather than the SPOOL
+parameter of FITPSF, we will not see the results until all stars have
+been measured. The next step is to average the results, to determine
+the final FWHM (the FITPSF output could have been piped directly to
+GETCOLS without using an intermediate spoolfile, if desired).
+
+ ap> getcols spoolfile,"4-5" | getcols | average
+ 2.83133 0.0569725 6
+
+There are many ways this average could have been computed, of course;
+this is only one example. Next, to avoid having to write down the
+FWHM value, we put it into the appropriate APPHOT parameter (note that
+the parameter name is abbreviated).
+
+
+ -17-
+ APPHOT (Aug83) Digital Aperture Photometry Package APPHOT (Aug83)
+
+
+
+ ap> apphot.fwhm = 2.831
+
+Finally, we must determine a representative backround sigma value for
+the image. This is done by using FITSKY to measure several sky areas,
+and averaging column two of the output, much as we did for FITPSF. The
+final value may be saved in "apphot.sky_sigma".
+
+By this point we have determined all the necessary parameters, and it
+is time to do some photometry. The only APPHOT argument we are sure
+of is the image name parameter, so that is all we include on the
+command line:
+
+ ap> apphot blue
+ aperture radii, pixels: 2.4 2.5 2.75 3.0
+ inner radius of sky annulus: 10
+ width of sky annulus (1 - ): 10
+ full width at half max of psf (2.831):
+ standard deviation of the image noise function (23.733):
+
+After responding to the prompts shown above, APPHOT will ask for the
+first pair of object coordinates, and the cursor blink prompt will
+again be given. Several objects may be measured to verify that all is
+working.
+
+The last step is to prepare a list of objects to be processed. The
+simplest way to do this is to interactively mark the objects with the
+cursor. Later, when we process the "red" image, the same coordinate
+list may again be used, possibly after filtering with COORDTR.
+
+ ap> imcursor > objlist
+
+At this point, all of the APPHOT parameters have been set, we have a
+list of objects to be processed, and we are ready to run APPHOT in
+batch mode. We decide to save the output in the file "blue.out". To
+ensure that we have a record of the parameters used for the fit, we
+first print the APPHOT parameters into the output file, then we start
+up the APPHOT batch run.
+
+ ap> lparam apphot > blue.out
+ ap> apphot >> blue.out &
+ [1]
+
+The batch job is now running, appending output lines to the file
+"blue.out". We can proceed to set up the job for the red image, in
+much the same way that we set up the job for the blue image. When
+both jobs finish, we can use the list processing tools to filter out
+the good objects and calculate colors.
diff --git a/noao/digiphot/apphot/doc/specs/Ap.spc b/noao/digiphot/apphot/doc/specs/Ap.spc
new file mode 100644
index 00000000..911d04f1
--- /dev/null
+++ b/noao/digiphot/apphot/doc/specs/Ap.spc
@@ -0,0 +1,1032 @@
+.help apphot Aug83 "Digital Aperture Photometry Package"
+.sh
+1. Introduction
+
+ The APPHOT package will provide a set of routines for performing
+aperture photometry on uncrowded or moderately crowded fields, in either
+interactive or batch mode. The basic photometry technique employed
+shall be fractional-pixel aperture integration; no PSF fitting techniques
+shall be employed, and no knowledge of the PSF shall be required.
+This document presents the formal requirements and specifications for
+the package, and describes the algorithms to be used.
+
+.sh
+2. Requirements
+.ls 4
+.ls (1)
+The program shall take as input an IRAF imagefile containing a starfield
+which has been corrected for pixel to pixel gain variations, high frequency
+fluctuations in the background, nonlinearity, and any other instrumental
+defects affecting the intensity value of a pixel.
+.le
+.ls (2)
+Given as input the approximate coordinates of a single object in the image,
+the program shall perform the following operations:
+.ls 4
+.ls o
+Determine a constant background value by analysis of an annular region
+surrounding the object. The background is assumed to be flat in the region
+of the object, but may contain contaminating objects or defects which
+shall be detected and eliminated by the fitting algorithm.
+It shall be permissible for the background region to extend beyond the
+boundaries of the image; the out of bounds region of the annulus shall
+be excluded from the fit.
+.le
+.ls o
+Determine the center of the object, taking the approximate object
+coordinates given as input as a starting point.
+The center determination shall be resistant to the affects of nearby
+contaminating objects. The centering algorithm may assume that the object
+is circularly symmetric, or nearly so, and that the object flux is positive.
+.le
+.ls o
+Determine the integral of object minus background within one or more
+circular apertures centered upon the object. The integration shall be
+performed using partial pixel techniques, to minimize the effects of
+sampling. If the aperture contains any indefinite pixels, or if the
+aperture extends beyond the boundary of the image, an indefinite result
+shall be returned.
+.le
+.le
+.le
+.ls (3)
+The following options shall be provided to modify the operation of the
+above functions:
+.ls
+.ls o
+Use a user supplied constant background value and background noise estimate
+instead of fitting the background.
+.le
+.ls o
+Use the starting center as the actual center in all cases.
+.le
+.ls o
+Use the starting center as the actual center if the object is very faint,
+but tweak up the center if the signal to noise is above a certain threshold.
+.le
+.ls o
+Allow the object aperture to extend beyond the image boundary,
+using only that portion of the aperture which is in bounds when computing
+the aperture integral.
+.le
+.le
+.le
+.ls (4)
+At a minimum, the following parameters shall be calculated and output
+for each object:
+.ls
+.ls o
+The coordinates of the object, and the estimated error in these coordinates.
+.le
+.ls o
+The mode and standard deviation of the background; the number of pixels
+left in the background region after pixel rejection.
+.le
+.ls o
+The magnitude of the object, to within an arbitary zero-point, and
+the statistical uncertainty of the magnitude. If multiple concentric
+apertures are used, a magnitude and uncertainty shall be given for each.
+.le
+.le
+.le
+.ls (5)
+The program shall be usable both interactively and in batch mode.
+In interactive use, the user shall be able to mark the positions of the
+objects by interactively positioning a cursor on a 2-dim display device.
+It shall be possible to enter the control parameters for the analysis
+routines interactively for each object. In batch mode, the control
+parameters shall be fixed, and object coordinates shall be taken from
+a user supplied list. The display device shall not be required in
+batch mode.
+.le
+.ls (6)
+The APPHOT package shall be written in the SPP language in conformance
+with the standards and conventions of IRAF. The code shall be portable
+and device independent.
+.le
+.le
+
+.sh
+2.1 Summary of the Limitations of APPHOT
+
+ The APPHOT package is designed to perform simple aperture photometry
+subject to the following restrictions:
+.ls
+.ls (1)
+Objects must be circular or nearly circular, since the aperture is
+circular.
+.le
+.ls (2)
+All pixels within the object aperture are weighted equally. All pixels
+in the object aperture must be present; the object aperture may not normally
+extend outside the image. Defective pixels within the object
+aperture may not be detected.
+.le
+.ls (3)
+The background must be approximately flat in the neighborhood of the
+object being measured. The background must have a unique mode,
+or the background fitting routine will reject the object. Any low
+frequency fluctuations in the background should be removed before
+using APPHOT.
+.le
+.ls (4)
+The object aperture must be kept small to minimize the degradation of
+signal to noise caused by sky pixels within the aperture, and to
+minimize the effects of crowding. Therefore, the wings of the object
+will extend beyond the aperture. Good photometric results will be
+obtained only if the aperture is consistently well centered, and if the
+shape and diameter of an object is constant throughout the image and
+invariant with respect to magnitude.
+.le
+.le
+
+.sh
+3. Specifications
+
+ The APPHOT package performs aperture photometry on digitized starfields
+maintained as IRAF imagefiles. Input to the package consists of an imagefile,
+a list of object coordinates, and numerous parameters controlling the analysis
+algorithms. Output consists of successive lines of text, where each line
+summarizes the results of the analysis for a particular object. The output
+may be saved in a textfile, which may easily be printed or written onto a
+card image tape for export. The package routines may be used either
+interactively or in batch mode.
+
+The CL callable part of the APPHOT package consists of the following
+routines:
+
+.ks
+.nf
+ apphot -- the main aperture photometry routine.
+ coordtr -- translations and rotations of coord lists.
+ fitsky -- computes mode and sigma of a sky region.
+ fitpsf -- compute the FWHM of the PSF.
+ imcursor -- reads the image cursor; used to make lists.
+ immark -- marks objects on the display device.
+ radprof -- computes the radial profile of an object.
+.fi
+.ke
+
+Routines for general list manipulation, reading and writing card image tapes,
+reading and writing images to FITS tapes, removing the instrumental signature
+from the data, and so on are available elsewhere in the IRAF system.
+The package is easily extended to include peak finding,
+matching of object lists from different images,
+background fitting and removal, and so on. The APPHOT package shall eventually
+supplant both the KPNO AUTOPHOT and KPNO "Mountain Photometry Code" packages.
+
+.sh
+3.1 Standard Analysis Procedures
+
+ Before performing aperture photometry one must determine the radius
+of the object aperture to be used, the inner radius and size of the annulus
+to be used to fit the background, the full width at half max (FWHM) of
+the point spread function (PSF), and so on.
+Additional parameters are required by the centering algorithm.
+A list of object centers must be prepared if APPHOT is to be used in
+batch mode. The standard procedure is as follows:
+.ls
+.ls (1)
+Use RADPROF to determine values for the following parameters:
+
+.nf
+ - the object aperture radius or radii, in pixels
+ - the inner radius of the annular (sky) region
+ - the width of the annular region
+.fi
+.le
+.ls (2)
+Use FITPSF to fit gaussians to isolated, high signal to noise data objects,
+to determine the FWHM of the point spread function.
+.le
+.ls (3)
+Use FITSKY to determine the sky sigma (standard deviation).
+APPHOT assumes that sigma is approximately constant throughout the image.
+.le
+.ls (4)
+If one does not wish to manually mark object positions with the cursor
+during analysis, i.e. when the analysis is to be done in batch, a list
+of object coordinates must be prepared. This may be done in many ways:
+.ls
+.ls o
+By running RCURSOR with the standard output redirected into the list file.
+.le
+.ls o
+By transforming an existing list with COORDTR, OPSTRM, MATCH, SORT, WINDOW,
+the editor, or some other filter.
+.le
+.ls o
+By an automatic object finding procedure, if one is available.
+.le
+.ls o
+By any other program which generates a list of object coordinates,
+where each line of the list describes one object, and where x and y
+in pixel coordinates are given in columns one and two. Additional
+columns, if present, are ignored.
+.le
+.ls o
+APPHOT output may be used as coordinate input in a subsequent run.
+.le
+.le
+.le
+.ls (5)
+Finally, APPHOT is run to measure the objects. The user should be familiar
+with the algorithms used to fit the background, measure the object center,
+and compute the aperture integral, magnitude, and errors. The values of
+all visible and hidden APPHOT parameters should be inspected before doing
+any serious processing.
+.le
+.le
+
+The general purpose IRAF list processing tools may be used for further
+analysis of APPHOT output.
+Output lists may be filtered to select objects based on the value of a
+list column, i.e., all the objects within a certain magnitude range may
+be selected, objects with estimated errors larger than a certain value
+may be deleted, or a list may be sorted using the value in any column.
+Columns may be extracted from a list to form new lists or to provide input
+to a plot filter, and lists may be merged.
+Arithmetic may be performed on lists to calculate colors, etc.
+
+The remainder of this section presents detailed specifications for the analysis
+procedures in the APPHOT package.
+
+.sh
+3.2 The APPHOT Program
+
+ The function of the APPHOT procedure is to perform aperture photometry
+on isolated objects within an image. The principal input operands are the
+name of the imagefile and the rough coordinates of the objects to be processed.
+The principal output operands are the coordinates and magnitudes of the
+objects.
+
+In order to perform aperture photometry APPHOT must perform the following
+sequence of operations (the algorithms employed are explained in
+more detail later in this section):
+.ls
+.ls (1)
+The mode and sigma of an annular background region centered on the object
+is calculated.
+.le
+.ls (2)
+The center of the object is determined.
+.le
+.ls (3)
+The background is subracted from the object, and the total flux within
+the object aperture or apertures is calculated.
+.le
+.le
+
+Steps (1) and (2) above are optional; the background and center may be
+determined externally, rather than by APPHOT, if desired.
+.sh
+3.2.1 APPHOT parameters
+
+ APPHOT has quite a few parameters due to the complexity of the
+algorithms employed. All data dependent parameters are query mode to
+ensure that they get set properly when a new image is processed.
+The data independent algorithm control parameters are hidden mode,
+and are given reasonable default values. The names, datatypes, and
+default values of the APPHOT parameters are shown below.
+
+
+.ks
+.nf
+Positional or query mode parameters:
+
+ image filename
+ apertures string
+ annulus real
+ width_annulus real
+ fwhm_psf real
+ sky_sigma real
+.fi
+.ke
+
+
+.ks
+.nf
+List structured parameters (filename may be given on command line):
+
+ sky_mode *real
+ coords *imcur
+.fi
+.ke
+
+
+.ks
+.nf
+Hidden parameters:
+
+ spool boolean no
+ output filename "apphot.out"
+ fitsky boolean yes
+ max_sky_iter integer 50
+ growing_radius real 1.0 (fwhm_psf units)
+ k1 real 5.0
+ k2 real 2.0
+ center boolean yes
+ clean boolean yes
+ cleaning_radius real 0.8 (fwhm_psf units)
+ clipping_radius real 1.5 (fwhm_psf units)
+ max_cen_shift real 1.0 (fwhm_psf units)
+ min_snratio real 0.5
+ zmag real 26.0
+ verbose boolean yes
+.fi
+.ke
+
+
+The function and format of each of these parameters is explained in more
+detail below.
+
+.ls
+.ls 16 image
+The name of the image or image section to be processed.
+.le
+.ls output
+The name of the output textfile used to spool APPHOT output.
+If null, output will not be spooled. Note that output always appears on
+the standard output, whether or not spooling is in effect.
+.le
+.ls apertures
+The radii in pixels of the concentric object apertures, given all on the
+same line, delimited by blanks. At least one aperture must be given;
+the maximum number of apertures is limited by the length of a line.
+A sample input string might be "5.0 5.5 6.0 6.5 7.0". If only a single
+aperture is to be used, a real expression may be used instead of a string
+type argument. The apertures need not be given in any particular order.
+The average radius will be used to compute the uncertainty in the
+object magnitude.
+.le
+.ls annulus
+The inner radius of the annular sky region, in pixels.
+.le
+.ls width_annulus
+The width of the annular sky region, in pixels.
+.le
+.ls fwhm_psf
+The FWHM of the psf, in pixels. Used as a scale factor to control the
+internal algorithms.
+.le
+.ls sky_sigma
+The standard deviation (noise value) of a typical region of sky in
+the image. Used for pixel rejection in the sky fitting algorithm.
+.le
+.ls sky_mode
+The name of a list file containing the mode of the background of each of
+the objects to be processed. Required only if FITSKY is switched off.
+If sky fitting is disabled, and no list file is given, APPHOT will query
+for the sky value.
+.le
+.ls coords
+The name of a list file containing the coordinates of the objects to
+be processed. If absent, objects may be marked interactively with the
+cursor.
+.le
+.ls fitsky
+A switch used to specify whether or not the background will be fitted.
+If background fitting is disabled, the mode and sigma of the background
+will be read from the SKY_FILE list each time an object is processed.
+.le
+.ls max_sky_iter
+The maximum number of iterations for the sky fitting algorithm.
+Since the sky fitting algorithm is guaranteed to converge,
+this parameter should normally have a large value. If the value
+is zero, the median of the sky region will be used instead of the mode.
+.le
+.ls growing_radius
+The region growing radius for pixel rejection in the sky region, in units
+of FWHM_PSF. When a bad sky pixel is detected, all pixels within
+(growing_radius * fwhm_psf) pixels of the bad pixel will be rejected.
+Used to exclude the wings of contaminating objects from the sky sample,
+to avoid biasing the mode.
+.le
+.ls k1
+The k-sigma clipping factor for the first phase of the sky fitting algorithm.
+.le
+.ls k2
+The k-sigma clipping factor for the second, iterative, phase of the
+sky fitting algorithm.
+.le
+.ls center
+A switch used to specify whether or not centering is to be performed.
+If centering is disabled, the initial center will be used as the object center.
+.le
+.ls clean
+A switch used to specify whether or not the symmetry-clean algorithm
+is to be employed during centering.
+.le
+.ls cleaning_radius
+The cleaning radius for the symmetry-clean algorithm, in units of
+FWHM_PSF.
+.le
+.ls clipping_radius
+The clipping radius for the symmetry-clean algorithm, in units of
+FWHM_PSF.
+.le
+.ls max_cen_shift
+The maximum permissible shift of center, in units of FWHM_PSF.
+If the shift produced by the centering algorithm is larger than this value,
+the fit will terminate and no magnitude will be calculated.
+.le
+.ls min_snratio
+Centering will be skipped if the signal to noise of the object,
+as calculated from the initial center, is less than the value given
+by this parameter.
+.le
+.ls zmag
+Zero point for the output magnitude scale.
+.le
+.ls verbose
+If enabled, the output columns are labeled. Note that the presence
+of column labels in the output may interfere with the use of the list
+processing tools.
+.le
+.le
+
+.sh
+3.2.2 The APPHOT Background Fitting Algorithm
+
+ A good background fit is essential to aperture photometry. Fitting
+the background is trivial in a sparse field, but difficult in a crowded
+field. In general the background region will contain contaminating objects
+which must be detected and excluded if a good fit is to be obtained.
+
+The algorithm employed here is based on the fact that contaminated pixels
+are almost always spatially correlated. Background fitting algorithms
+which work with a one dimensional sample (mode, median), or with the one
+dimensional histogram (mode of hgm) have difficulty rejecting the faint
+wings of contaminated regions. This is a serious defect of one dimensional
+fitting algorithms, because it is these faint wings, not the bright
+central pixels, which are most likely to bias the calculated background value.
+
+The algorithm used in APPHOT is as follows:
+
+
+.ks
+.nf
+ algorithm fit_sky
+
+ begin
+ # Reject gross deviants.
+ compute the median of the annular region
+ detect pixels more than (k1*sky_sigma) from the median
+ reject all such pixels, without region growing
+
+ # Detect and reject contaminating objects.
+ while (number of iterations <= max_sky_iter) {
+ compute the histogram of the reduced sample
+ compute the sigma and mode of the histogram
+ detect pixels more than k2*sigma from the mode
+ reject all such pixels, with region growing
+ if (no pix rejected or all pix rejected)
+ terminate loop
+ }
+
+ return the final mode, sigma, and sample size
+ end
+.fi
+.ke
+
+
+The mode of the histogram is found by cross correlating the noise function
+with the histogram. The width of the the noise function is given by the
+standard deviation of the current sample. Pixel rejection is
+performed by locating all pixels more than k2*sigma from the mode,
+and blindly rejecting all pixels within a certain radius of each deviant
+pixel. This simple algorithm works well because the sample is large,
+and therefore there is little penalty for discarding pixels that might
+not be deviant. Region growing also tends to accelerate convergence
+significantly.
+
+Very faint contaminating objects are difficult to detect and reject.
+If there are enough such objects, they should not be rejected, because
+there are probably a few in the object aperture as well. A higher sky
+sigma will be calculated and the computed uncertainty in the magnitude
+will increase. The best solution to this problem may be to increase
+the size of the annulus to minimize the bias and maximize the liklihood
+of a detection.
+
+.sh
+3.2.3 The APPHOT Centering Algorithm
+
+ The centering algorithm used in APPHOT is that of Auer and Van Altena,
+with the addition of the symmetry-clean algorithm developed by Barry Newell.
+The main algorithm is as follows:
+
+
+.ks
+.nf
+ algorithm get_center
+
+ begin
+ if (centering is disabled) {
+ return initial center, zero uncertainty estimate
+
+ } else if (signal to noise of object < MIN_SNRATIO) {
+ compute uncertainty using initial center
+ return initial center, computed uncertainty
+
+ } else {
+ call measure_center
+ return image center and estimated uncertainty
+ }
+ end
+.fi
+.ke
+
+
+The actual center determination is carried out by the following
+algorithm:
+
+
+.ks
+.nf
+ algorithm measure_center
+
+ begin
+ extract subarray from the main data array
+
+ # Perform symmetry-cleaning.
+ if (cleaning is enabled) {
+ for (each pair of pixels diametrically opposed about
+ the image center beyond the cleaning radius)
+ if (i2 > i1 + 2*sky_sigma)
+ replace i2 by i1
+ else if (i1 > i2 + 2*sky_sigma)
+ replace i1 by i2
+
+ perform 2*sky_sigma noniterative clip of all pixels
+ beyond the clipping radius, to remove any remaining
+ radially symmetric structures
+ }
+
+ # Compute the image center and uncertainty.
+ compute x and y marginals of the cleaned subarray
+ fit a gaussian of width FWHM_PSF to each marginal
+ compute the centering error from the covariance matrix
+
+ return image center and estimated uncertainty
+ end
+.fi
+.ke
+
+
+The effect of the symmetry-clean algorithm is to edit the raster,
+removing any contaminating objects in the vicinity of the primary object.
+This simplifies the fitting algorithm and increases its reliability,
+since it does not have to deal with multipeak marginal distributions.
+
+A gaussian is fitted to the marginal distributions because it is expected
+to yield a better center determination for undersampled data.
+An alternative is to empirically derive the marginal distributions of
+the psf and fit these to each data object. This is a better approach in
+some cases, but in the case of undersampled data it is difficult to derive
+the marginal distributions due to sampling effects, and fitting is difficult
+due to interpolation error. The use of a gaussian eliminates interpolation
+error. Eventually, both techniques should be made available.
+
+.sh
+3.2.4 The APPHOT Aperture Integration Algorithm
+
+ The integral of the flux within a circular aperture is computed by
+fractional pixel techniques. Pixels are assumed to be square apertures
+arranged in a rectangular grid. The fraction of a pixel which lies within
+the circular APPHOT aperture is computed by an approximation, and all
+such contributions are summed to produce the total integral.
+
+The simplicity of aperture photometry limits the amount of information
+available for error analysis. Using only the noise value for the background,
+the estimated error in the aperture integral is given by
+
+ flux_error = sky_sigma * sqrt (aperture_area)
+
+where "sky_sigma" is either the sigma calculated by the background fitting
+algorithm or the parameter SKY_SIGMA, depending on whether sky fitting
+is enabled, and where "aperture_area" is the fractional pixel area of the
+aperture.
+
+It is possible, however, to produce a more useful error estimate if we
+include some information about the psf. For the purposes of an improved
+error estimate, we assume that the PSF is a gaussian. Given the object center,
+the background, and the FWHM of the PSF, it is trivial to fit a two dimensional
+gaussian to the object. An estimate of the average noise value for the
+pixels within the aperture may then be obtained by computing the standard
+deviation of the residual formed by subtracting the fitted two-dimensional
+gaussian from the data. This value is used in place of SKY_SIGMA in the
+above equation for an improved estimate of the actual flux error.
+
+In the limit as the gaussian goes to zero, both uncertainty estimates tend
+to the same value, as they should. For bright objects, the uncertainty
+produced by analysis of the residual will tend to be pessimistic, since
+it is unlikely that the PSF can actually be modeled by a simple gaussian.
+Nonetheless, a plot of uncertainty versus magnitude should reveal objects
+which are blended, which contain bad pixels, and so on. The accuracy of
+the gaussian model will determine how reliably deviant objects can be
+discriminated.
+
+.sh
+3.2.5 APPHOT Output
+
+ For each object processed, APPHOT prints a single line of text on the
+standard output. If desired, APPHOT will simultaneously spool output into
+a user specified text file. Each output line will contain the following
+information (excluding the commas):
+
+
+.nf
+ x,y,cenerr,shift, mode,sigma,nskypix, mag1,...,magn,magerr
+
+where
+
+ x,y object coordinates in pixels
+ cenerr estimated uncertainty in the object center
+ shift shift of center from initial coordinates
+ mode mode of the background
+ sigma sigma of the background
+ nskypix number of sky pixels left after rejection
+ mag1 magnitude within the first annulus
+ magn magnitude within the Nth annulus
+ magerr estimated mag. uncertainty at the average radius
+.fi
+
+
+Note that the estimated uncertainty in the magnitude is given only for
+the average object aperture radius. The uncertainty for the other
+apertures can easily be calculated given SIGMA and the area of each
+aperture. The zero point for the magnitude scale is given by the
+hidden parameter ZMAG.
+
+Additional information could be calculated and output (such as the
+moments of the object and the skew of the background), but in our
+experience few people ever look at such information, and a more complex
+output format would be required. Probably the calculation of anything
+but object centers, magnitudes, and errors should be left to other
+programs.
+
+.sh
+3.3 The COORDTR Program
+
+ The function of COORDTR is to effect a linear translation and/or
+rotation of a coordinate list. COORDTR is a filter; coordinate lines
+are read from the standard input and written to the standard output.
+COORDTR is concerned only with coordinate transformations, and knows
+nothing about image boundaries. A transformed coordinate may no longer
+lie within an image.
+
+ x y other_stuff
+
+The format of a coordinate line is shown above. COORDTR operates only
+on the coordinate pair x,y. Any additional information on the line is
+passed on to the output without modification.
+
+COORDTR is actually a general purpose list processing operator, and
+belongs in a list processing package, rather than in the APPHOT package.
+When a list processing package is developed, COORDTR will be moved to
+that package.
+
+A COORDTR transformation consists of a linear translation followed
+by a rotation. Either the translation, the rotation, or both may be
+skipped. The COORDTR parameters are summarized below.
+
+
+.ks
+.nf
+positional arguments:
+
+ xshift real
+ yshift real
+ xcenter real
+ ycenter real
+ theta real
+.fi
+.ke
+
+
+.ks
+.nf
+hidden parameters:
+
+ translate boolean yes
+ rotate boolean no
+.fi
+.ke
+
+
+If more than two positional arguments are given, COORDTR knows
+that both a translation and a rotation are desired. Otherwise the
+boolean parameters TRANSLATE and ROTATE are read to determine
+what additional parameters are needed. Thus a simple linear translation
+of +2.5 pixels in X and -0.2 pixels in Y would be specified by the
+command
+
+ coordtr (2.5, -.2, < "input", > "output")
+
+which transforms the list in file "input", writing the output into the
+new file "output".
+
+If a rotation is desired, XCENTER, YCENTER, and THETA must be given.
+The first two parameters specify the pixel coordinates of the point
+about which the rotation is to be performed, while THETA specifies
+the rotation angle in degrees. Positive THETA produces a counterclockwise
+rotation, if positive X is to the right and positive Y is up.
+
+.sh
+3.4 The FITSKY Program
+
+ The function of the FITSKY program is to determine the mode and sigma
+of the specified annular regions, printing the results (mode, sigma, and npix)
+on the standard output. FITSKY is similar in operation to APPHOT, except
+that its function is to fit sky, not perform aperture photometry. The
+FITSKY parameters are the following:
+
+
+.ks
+.nf
+Positional or query mode parameters:
+
+ image filename
+ annulus real
+ width_annulus real
+ fwhm_psf real
+.fi
+.ke
+
+
+.ks
+.nf
+List structured parameters (filename may be given on command line):
+
+ coords *imcur
+.fi
+.ke
+
+
+.ks
+.nf
+Hidden parameters:
+
+ spool boolean no
+ output filename "fitsky.out"
+ max_sky_iter integer 50
+ growing_radius real 1.0 (fwhm_psf units)
+ k1 real 5.0
+ k2 real 2.0
+ verbose boolean yes
+.fi
+.ke
+
+
+The names and functions of the FITSKY parameters are the same as those
+for APPHOT. Note that ANNULUS may be set to zero to measure the
+background within a circular aperture. The maximum number of iterations
+may be set to zero to measure the median of the sky sample.
+FITSKY output may be spooled into a file and used as input to APPHOT.
+
+.sh
+3.5 The FITPSF Program
+
+ The function of the FITPSF program is to determine the FWHM of the
+point spread function. This is done by selecting an isolated, high
+signal to noise object, computing the x and y marginal profiles,
+and fitting a gaussian to each profile. Output consists of the object
+center, the error in the center, and the FWHM of the fitted gaussians.
+Note that the sigma of a gaussian may be obtained by dividing the FWHM
+by 2.354.
+
+ x y err x_fwhm y_fwhm
+
+The input parameters for the FITPSF program are shown below.
+
+
+.ks
+.nf
+Positional parameters:
+
+ image filename
+ aperture real
+ annulus real
+ width_annulus real
+ sky_mode real
+ coords *imcur
+.fi
+.ke
+
+
+.ks
+.nf
+Hidden parameters:
+
+ fitsky boolean yes
+ center boolean yes
+ spool boolean no
+ output filename "fitpsf.out"
+ verbose boolean yes
+.fi
+.ke
+
+
+If background fitting is disabled, the parameter SKY_MODE defines
+the sky level. The background fitting algorithm is a simple median
+calculation without pixel rejection or iteration.
+This should be sufficient, since FITPSF is expected to be used mainly
+in uncrowded regions on high signal to noise objects.
+
+Note that FITPSF is set up to process a list of input objects.
+The list processing tools (i.e., AVERAGE) may be used to average the
+results to produce the final FWHM of the PSF for the image.
+
+.sh
+3.6 The IMCURSOR Program
+
+ The function of the IMCURSOR program is to read the STDIMAGE cursor,
+writing the cursor coordinates on the standard output. The cursor is read
+until the EOF character is entered to terminate the loop. The standard
+output may be redirected into a file to generate a coordinate list.
+IMCURSOR has no parameters.
+
+.sh
+3.7 The IMMARK Program
+
+ The function of IMMARK is to draw marks on the diplay device.
+IMMARK is useful for verifying coordinate lists.
+
+
+.ks
+.nf
+parameters:
+
+ mark_type string
+ mark_size real
+ coords *imcur
+.fi
+.ke
+
+
+Output is the current frame of the STDIMAGE device. Mark types
+include "circle", "box", "cross", "plus", and "diamond". The size of
+a mark is given in pixels. The third parameter is a standard coordinate
+list. If no list is given, the image cursor will be read instead.
+
+.sh
+3.8 The RADPROF Program
+
+ The function of the RADPROF program is to compute the radial profile
+of an object. The output of RADPROF consists of a sequence of lines of
+text, each line defining the profile at a single radius. Since RADPROF
+may generate many lines of output for a single input object, it is set up
+to process only a single input object. A CL while loop may be written
+to process multiple objects, if desired.
+
+
+.ks
+.nf
+positional arguments:
+
+ image filename
+ aperture real
+ step_size real
+ annulus real
+ width_annulus real
+ sky_mode real
+.fi
+.ke
+
+
+.ks
+.nf
+hidden parameters:
+
+ fitsky boolean yes
+ center boolean yes
+ verbose boolean yes
+.fi
+.ke
+
+
+The radial profile is calculated from the image center out to the radius
+specified by the parameter APERTURE, in steps of STEP_SIZE pixels.
+The remaining RADPROF parameters are similar to those of APPHOT and will not be
+discussed in detail. If background fitting is disabled, the parameter
+SKY_MODE defines the sky level. The background fitting algorithm is
+a simple median calculation without pixel rejection or iteration.
+This should be sufficient, since RADPROF is expected to be used mainly
+in uncrowded regions on high signal to noise objects.
+Centering is via gaussian fits to the marginal profiles, without cleaning.
+
+RADPROF output lines contain the following fields:
+
+ r, i(r), inorm(r), fraction(r)
+
+.nf
+where
+
+ r radius in pixels
+ i(r) raw intensity at r
+ inorm(r) normalized intensity at r (range 0-1)
+ fraction(r) fraction of total integral at r
+.fi
+
+
+RADPROF does not generate any plots. If one wishes to plot the contents
+of an output column, the column may be extracted with a list processing
+filter and piped to a graphics task.
+
+.sh
+4.0 Example
+
+ A brief example may help illustrate the use of the package. Suppose
+we want to process a few hundred stars on images "blue" and "red". We
+start by analyzing the blue image.
+
+ ap> radprof blue,15,0.5,20,10
+
+This gives us a radial profile printout for one of the "blue" stars.
+We decide that an aperture radius of 2.5 pixels is about right.
+The annulus will start at a radius of 10.0 pixels and extend to 20.0 pixels.
+The next step is to determine the FWHM of the PSF:
+
+ ap> fitpsf blue,3,10,20 | tee spoolfile
+
+By default, the program will take coordinate input by reading the image
+display cursor. When the program is waiting for cursor input, it will
+cause the display cursor to blink rapidly; normally the cursor does not
+blink. One has to be aware of this, because no other prompt is issued.
+We postion the cursor on several stars, and tap the space bar to measure
+each one. When finished we type the EOF character (<ctrl/z> on our systems)
+to terminate the loop. The screen will now look like this (the output
+column labels are ommitted):
+
+.nf
+ ap> fitpsf blue,3,10,20 | tee spoolfile
+ 283.12 157.40 0.035 2.887 2.751
+ 546.08 213.45 0.023 2.833 2.902
+ 318.32 354.73 0.064 2.791 2.824
+.fi
+
+Since we elected to use TEE to spool the output, rather than the SPOOL
+parameter of FITPSF, we will not see the results until all stars have been
+measured. The next step is to average the results, to determine the
+final FWHM (the FITPSF output could have been piped directly to GETCOLS
+without using an intermediate spoolfile, if desired).
+
+.nf
+ ap> getcols spoolfile,"4-5" | getcols | average
+ 2.83133 0.0569725 6
+.fi
+
+There are many ways this average could have been computed, of course;
+this is only one example. Next, to avoid having to write down the FWHM value,
+we put it into the appropriate APPHOT parameter (note that the parameter
+name is abbreviated).
+
+ ap> apphot.fwhm = 2.831
+
+Finally, we must determine a representative backround sigma value for
+the image. This is done by using FITSKY to measure several sky areas,
+and averaging column two of the output, much as we did for FITPSF. The
+final value may be saved in "apphot.sky_sigma".
+
+By this point we have determined all the necessary parameters, and it is
+time to do some photometry. The only APPHOT argument we are sure of is
+the image name parameter, so that is all we include on the command line:
+
+.nf
+ ap> apphot blue
+ aperture radii, pixels: 2.4 2.5 2.75 3.0
+ inner radius of sky annulus: 10
+ width of sky annulus (1 - ): 10
+ full width at half max of psf (2.831):
+ standard deviation of the image noise function (23.733):
+.fi
+
+After responding to the prompts shown above, APPHOT will ask for the
+first pair of object coordinates, and the cursor blink prompt will again
+be given. Several objects may be measured to verify that all is working.
+
+The last step is to prepare a list of objects to be processed. The simplest
+way to do this is to interactively mark the objects with the cursor.
+Later, when we process the "red" image, the same coordinate list may again
+be used, possibly after filtering with COORDTR.
+
+ ap> imcursor > objlist
+
+At this point, all of the APPHOT parameters have been set, we have
+a list of objects to be processed, and we are ready to run APPHOT in
+batch mode. We decide to save the output in the file "blue.out".
+To ensure that we have a record of the parameters used for the fit,
+we first print the APPHOT parameters into the output file, then we
+start up the APPHOT batch run.
+
+.nf
+ ap> lparam apphot > blue.out
+ ap> apphot >> blue.out &
+ [1]
+.fi
+
+The batch job is now running, appending output lines to the file "blue.out".
+We can proceed to set up the job for the red image, in much the same way
+that we set up the job for the blue image. When both jobs finish, we
+can use the list processing tools to filter out the good objects and
+calculate colors.
diff --git a/noao/digiphot/apphot/doc/specs/apphot.db b/noao/digiphot/apphot/doc/specs/apphot.db
new file mode 100644
index 00000000..df5dc2f3
--- /dev/null
+++ b/noao/digiphot/apphot/doc/specs/apphot.db
@@ -0,0 +1,366 @@
+# APPHOT.DDF -- Data definition for apphot package output
+
+builtin catalog functions
+builtin domain statements
+
+-------------------------------------------------------------------------------
+
+# domain statements
+
+domain bool type=short format="%b"
+domain posint type=short format="%5d"
+domain pixels type=real format="%9.3f"
+domain fwhmpsf type=real format="%9.3f"
+domain counts type=real format="%15.7g"
+domain sigma type=real format="%15.7g"
+domain mag type=real format="%7.3f"
+domain pars type=real format="%15.7g"
+domain electrons type=short format="%5d"
+domain ratio type=real format=%15.7g"
+
+# Apphot database descriptor
+record apphot {
+ iraf char[] "current version of iraf"
+ host char[] "host machine"
+ user char[] "user name"
+ package char[] "package name"
+ version char[] "package version"
+}
+
+--------------------------------------------------------------------------------
+
+# History record (1 per modification of the apphot database)
+record history {
+ task char[] "task name"
+ date ltime "date dask was run"
+ firstrec posint "first record written by task"
+ lastrec posint "last record written by task"
+}
+
+------------------------------------------------------------------------------
+
+# Data dependent parameter set (>= 1 per task execution)
+record datapars {
+ fwhmpsf pixels "full width half max of the psf"
+ emission bool "emission/absorption"
+ noise model char[] "data noise mode"
+ threshold counts "intensity threshold"
+ sigma counts "sigma of sky pixels"
+ gain char[] "image gain keyword"
+ epadu ratio "gain electrons/adu"
+ ccread char[] "image readout noise keyword"
+ readnoise electrons "readout noise electrons"
+}
+
+# Centering algorithm parameter set (>= 1 per task execution)
+record centerpars {
+ calgorithm char[] "centering algoritm"
+ cboxwidth fwhmpsf "centering box width"
+ maxshift fwhmpsf "maximum shift"
+ cmaxiter posint "maximum number of iterations"
+ minsnratio ratio "minimum signal to noise ratio"
+ clean bool "use clean algorithm"
+ rclean fwhmpsf "cleaning radius"
+ rclip fwhmpsf "clipping radius"
+ kclean sigma "sigma clean"
+}
+
+# Sky fitting algorithm parameter set (>= 1 per task execution)
+record fitskypars {
+ salgorithm char[] "sky fitting algorithm"
+ annulus fwhmpsf "inner sky annulus"
+ dannulus fwhmpsf[] "width of inner sky annulus"
+ smaxiter posint "maximum number od iterations"
+ skreject sigma "ksigma rejection"
+ snreject posint "maximum number of rejections"
+ khist sigma "half width of histogram"
+ binsize sigma "binsize of histogram"
+ smooth bool "smooth the histogram"
+ rgrow fwhmpsf "region growing radius"
+ skyvalue counts "user supplied sky value"
+}
+
+# Photometry parameter set (>= 1 per task execution)
+record photpars {
+ weighting char[] "weighting scheme"
+ apertures fwhmpsf "list of apertures"
+ zmagnitude mag "magnitude zero point"
+ exposure char[] "image exposure time keyword"
+ itime "" "exposure time"
+}
+
+# Polygonal photometry parameter set (>= 1 per task execution)
+record polypars {
+ zmagnitude mag "magnitude zero point"
+ exposure char[] "image exposure time keyword"
+ itime "" "exposure time"
+}
+
+# Radial profile fitting parameters (>= 1 per task execution)
+record radprofpars {
+ radius fwhmpsf "maximum profile radius"
+ stepsize fwhmpsf "profile step size"
+ order posint "number of spline pieces in fit"
+ kreject sigma "k sigma rejection"
+ nreject posint "max number of rejection cycles"
+}
+
+# Point spread function modeling parameters (>= 1 per task execution)
+record psfpars {
+ function char[] "analytic function"
+ box fwhmpsf "fitting box size"
+ kreject sigma "sigma rejection limit"
+ nreject posint "max number of rejections"
+}
+
+--------------------------------------------------------------------------------
+
+# Computed center answers (1 per star)
+record center {
+
+ datapars posint "record id of datapars record"
+ centerpars posint "record id of centerpars record"
+
+ image char[] "image name"
+ xinit pixels "initial x position"
+ yinit pixels "initial y position
+ id posint "sequence number in table"
+ coords char[] "coordinate list filename"
+ lid posint "sequence number in coord list"
+
+ xcenter pixels "x center position"
+ ycenter pixels "y center position"
+ xshift pixels "x position shift"
+ yshift pixels "y position shift"
+ xerror pixels "x position error"
+ yerror pixels "y position error"
+ cerrcode posint "centering error code"
+ cerrstring char[] "centering error message"
+
+}
+
+# Computed fitsky answers (1 per star)
+record fitsky {
+
+ datapars posint "record id of datapars record"
+ fitskypars posint "record id of fitskyprs record"
+
+ image char[] "image name"
+ xinit pixels "initial x position"
+ yinit pixels "initial y position
+ id posint "sequence number in table"
+ coords char[] "coordinate list filename"
+ lid posint "sequence number in coord list"
+
+ skyvalue counts "sky value"
+ skysigma counts "standard deviation of sky"
+ skyskew counts "skew of sky pixels"
+ nskypix posint "number of sky pixels"
+ nskyreject posint "number of rejected pixels"
+ serrcode posint "sky fitting error code"
+ serrstring char[] "sky fitting error message"
+
+}
+
+# Computed phot answers (1 per star)
+record phot {
+
+ datapars posint "record id of datapars record"
+ centerpars posint "record id of centerpars record"
+ photpars posint "record id of photometry record"
+
+ image char[] "image name"
+ xinit pixels "initial x position"
+ yinit pixels "initial y position
+ id posint "sequence number in table"
+ coords char[] "coordinate list filename"
+ lid posint "sequence number in coord list"
+
+ xcenter pixels "x center position"
+ ycenter pixels "y center position"
+ xshift pixels "x position shift"
+ yshift pixels "y position shift"
+ xerror pixels "x position error"
+ yerror pixels "y position error"
+ cerrcode posint "centering error code"
+ cerrstring char[] "centering error message"
+
+ skyvalue counts "sky value"
+ skysigma counts "standard deviation of sky"
+ skyskew counts "skew of sky pixels"
+ nskypix posint "number of sky pixels"
+ nskyreject posint "number of rejected pixels"
+ serrcode posint "sky fitting error code"
+ serrstring char[] "sky fitting error message"
+
+ aperts pixels[] "list of apertures"
+ sums counts[] "list of sums"
+ areas pixels[] "list of areas"
+ mags mag[] "list of magnitudes"
+ magerrs mag[] "list of mag errors
+ merrcodes posint[] "list of errcodes
+ merrstrings char[] "list of error messages"
+
+}
+
+# Computed wphot answers (1 per star)
+record wphot {
+
+ datapars posint "record id of datapars record"
+ centerpars posint "record id of centerpars record"
+ fitskypars posint "record id of fitskypars record"
+ photpars posint "record id of photpars record"
+
+ image char[] "image name"
+ xinit pixels "initial x position"
+ yinit pixels "initial y position
+ id posint "sequence number in table"
+ coords char[] "coordinate list filename"
+ lid posint "sequence number in coord list"
+
+ xcenter pixels "x center position"
+ ycenter pixels "y center position"
+ xshift pixels "x position shift"
+ yshift pixels "y position shift"
+ xerror pixels "x position error"
+ yerror pixels "y position error"
+ cerrcode posint "centering error code"
+ cerrstring char[] "centering error message"
+
+ skyvalue counts "sky value"
+ skysigma counts "standard deviation of sky"
+ skyskew counts "skew of sky pixels"
+ nskypix posint "number of sky pixels"
+ nskyreject posint "number of rejected pixels"
+ serrcode posint "sky fitting error code"
+ serrstring char[] "sky fitting error message"
+
+ aperts pixels[] "list of apertures"
+ sums counts[] "list of sums"
+ areas pixels[] "list of areas"
+ mags mag[] "list of magnitudes"
+ magerrs mag[] "list of mag errors
+ merrcode posint[] "list of errcodes
+ merrstrings char[] "list of error messages"
+}
+
+# Computed polyphot answers (1 per star)
+record polyphot {
+
+ datapars posint "record id of datapars record"
+ centerpars posint "record id of centerpars record"
+ fitskypars posint "record id of fitskypars record"
+ polypars posint "record id of polypars record"
+
+ image char[] "image name"
+ xinit pixels "initial x position"
+ yinit pixels "initial y position
+ id posint "sequence number in table"
+ coords char[] "coordinate list filename"
+ lid posint "sequence number in coord list"
+
+ xcenter pixels "x center position"
+ ycenter pixels "y center position"
+ xshift pixels "x position shift"
+ yshift pixels "y position shift"
+ xerror pixels "x position error"
+ yerror pixels "y position error"
+ cerrcode posint "centering error code"
+ cerrstring char[] "centering error message"
+
+ skyvalue counts "sky value"
+ skysigma counts "standard deviation of sky"
+ skyskew counts "skew of sky pixels"
+ nskypix posint "number of sky pixels"
+ nskyreject posint "number of rejected pixels"
+ serrcode posint "sky fitting error code"
+ serrstring char[] "sky fitting error message"
+
+ sum counts[] "aperture sum"
+ area pixels[] "aperture area"
+ mag mag[] "magnitude"
+ magerr mag[] "magnitude error"
+ merrcode posint[] "error code"
+ merrstring char[] "error message"
+
+ polygons char[] "name of polygons files"
+ pid posint "polygon sequence number"
+ oldxmean pixels "original mean x of polygon"
+ oldymean pixels "original mean y of polygon"
+ minradius pixels "min sky radius to exclude polygon"
+ nver posint "number of vertices"
+ xvertices pixels[] "list of x vertices coords"
+ yvertices pixels[] "list of y vertices coords"
+}
+
+# Computed radprof answers (1 per star)
+record radprof {
+
+ datapars posint "record id of datapars record"
+ centerpars posint "record id of centerpars record"
+ fitskypars posint "record id of fitskypars record"
+ photpars posint "record id of photpars record"
+ radprofpars posint "record id of radprofpars record"
+
+ image char[] "image name"
+ xinit pixels "initial x position"
+ yinit pixels "initial y position
+ id posint "sequence number in table"
+ coords char[] "coordinate list filename"
+ lid posint "sequence number in coord list"
+
+ xcenter pixels "x center position"
+ ycenter pixels "y center position"
+ xshift pixels "x position shift"
+ yshift pixels "y position shift"
+ xerror pixels "x position error"
+ yerror pixels "y position error"
+ cerrcode posint "centering error code"
+ cerrstring char[] "centering error message"
+
+ skyvalue counts "sky value"
+ skysigma counts "standard deviation of sky"
+ skyskew counts "skew of sky pixels"
+ nskypix posint "number of sky pixels"
+ nskyreject posint "number of rejected pixels"
+ serrcode posint "sky fitting error code"
+ serrstring char[] "sky fitting error message"
+
+ aperts pixels[] "list of apertures"
+ sums counts[] "list of sums"
+ areas pixels[] "list of areas"
+ mags mag[] "list of magnitudes"
+ magerrs mag[] "list of mag errors
+ merrs posint[] "list of error codes
+ merrstrings char[] "list of error messages"
+
+ pfwhm pixels "fitted profile fwhmpsf"
+ inorm counts "intensity normalization factor"
+ tinorm counts "total intensity normalization factor"
+ errcode posint "error code"
+ errstring char[] "error message"
+ rlist pixels[] "radii"
+ intensities counts[] "fitted intensities"
+ tintensities counts[] "integral of fitted total intensities"
+}
+
+# Computed fitpsf answers (1 per star)
+record fitpsf {
+
+ datapars posint "record id of datapars record"
+ fitpsfpars posint "record id of fitpsf record"
+
+ image char[] "image name"
+ xinit pixels "initial x position"
+ yinit pixels "initial y position
+ id posint "sequence number in table"
+ coords char[] "coordinate list filename"
+ lid posint "sequence number in coord list"
+
+ npars posint "number of parameters"
+ params pars[] "list of parameters"
+ parerrs pars[] "list of parameter errors"
+
+}
+
+-------------------------------------------------------------------------------
diff --git a/noao/digiphot/apphot/doc/specs/apphot.spc b/noao/digiphot/apphot/doc/specs/apphot.spc
new file mode 100644
index 00000000..ecfdf364
--- /dev/null
+++ b/noao/digiphot/apphot/doc/specs/apphot.spc
@@ -0,0 +1,1296 @@
+.EQ
+delim $$
+.EN
+
+.RP
+.TL
+Specifications for the Aperture Photometry Package
+.AU
+Lindsey Davis
+.AI
+.K2 "" "" "*"
+Revised October 1987
+
+.AB
+The APPHOT package is a set of tasks for performing aperture photometry
+on uncrowded or moderately crowded fields, in either interactive or batch mode.
+The photometric technique employed is fractional pixel aperture
+integration. Point spread function fitting techniques are not used and no
+knowledge of the point spread function is required for the computation of
+magnitudes. Separate tasks are provided for creating and modifying object lists,
+computing accurate centers for a list of objects, computing sky values for
+a list of objects and performing aperture photometry inside circular or
+polygonal apertures.
+.AE
+
+.NH
+Introduction
+.PP
+The APPHOT package is a set of tasks for performing
+aperture photometry on uncrowded or moderately crowded fields.
+The photometric technique employed is fractional pixel integration. Point
+spread function techniques are not used and no knowledge of the point spread
+function is required for the computation of magnitudes.
+.PP
+The APPHOT package performs multi-aperture photometry on digitized starfields
+maintained as IRAF image files. Input to the package consists of an
+image file, a list of object coordinates, numerous parameters controlling
+the analysis algorithms and, optionally, the graphics terminal and/or
+display. APPHOT output consists of successive lines of text where each line
+summarizes the results of the analysis for a particular object.
+.PP
+Given starting coordinates and an IRAF image, the principal APPHOT
+task computes accurate centers, sky values and magnitudes
+for a list of objects. Separate
+IRAF callable tasks in APPHOT exist to create and modify object
+lists, to determine image characteristics such as the full width half maximum
+of the point spread function or standard deviation of the sky pixels,
+to compute accurate centers for a list of objects, to compute accurate local sky
+values for a list of objects, and to compute magnitudes inside a polygonal
+aperture.
+
+.NH
+APPHOT Package Requirements
+.NH 2
+APPHOT Package Input
+.NH 3
+The IRAF Image
+.PP
+APPHOT assumes that images exist on disk in IRAF format. Facilities for reading
+and writing images exist elsewhere in IRAF such as in package DATAIO or
+MTLOCAL.
+.PP
+APPHOT assumes that the image data is linear.
+The input image is assumed to have been corrected for those instrumental
+defects which affect the intensity of a pixel. These include pixel to
+pixel variations in the bias values, pixel to pixel gain variations,
+cosmic rays, cosmetic defects, geometric distortion,
+and detector non-linearities.
+.PP
+APPHOT assumes that the local sky background is approximately flat in the
+vicinity of the object being measured. This assumption is equivalent to
+assuming that the local sky region has a unique mode. Therefore any
+variations in the sky background which occur at the same scale as the
+sky region should be removed prior to entering APPHOT.
+.PP
+The point spread function of the image is assumed to be constant for all
+regions of the image. This is particularly critical in the case of faint objects
+for which small apertures which minimize the effects of crowding and
+sky noise in the aperture are used. The wings of the object will
+almost certainly extend beyond the aperture and good results will only be
+obtained if
+objects are consistently well centered and the shape and diameter of an object
+is constant throughout the image and invariant to magnitude.
+
+.NH 3
+The Coordinate Lists
+.PP
+All APPHOT tasks operate on lists of object coordinates or interactive cursor
+input. Lists are maintained as text files,
+one object per line with the x and y coordinates in
+columns one and two respectively. List files may be created interactively
+with either the graphics or image cursor, by a previously executed APPHOT
+task, by a previously executed IRAF task or by a user task.
+.PP
+The x and y coordinates contained in the list file can be either the
+starting centers for the objects of interest or the true centers.
+In either case the aperture centered around the object position must
+not extend beyond the boundary of the image. To obtain reliable results
+from the centering algorithm the starting centers should not be more than
+1 fwhmpsf pixels from the true centers.
+
+.NH 3
+Algorithm Parameters
+.PP
+Many tasks in the APPHOT package have an associated set of algorithm parameters
+which control the operation of the analysis routines. For example the
+centering and sky fitting algorithms each have an associated group of
+parameters.
+The APPHOT tasks supply reasonable defaults for these parameters. However
+the user may alter them at any time in interactive mode or by editing the
+appropriate parameter file before running the task in batch.
+
+.NH 3
+Terminal Graphics and the Image Display
+.PP
+Most APPHOT programs may be run in either interactive or batch mode.
+In interactive mode, the user can mark the positions of objects by
+interactively, positioning the image cursor on the display device.
+Simple cursor commands can interactively alter the algorithm parameters.
+In batch mode the algorithm parameters are
+fixed and object coordinates are taken from the user supplied coordinate list.
+The display device is not required in batch mode.
+.PP
+At present there is no high level IRAF display interface. Therefore the present
+version of APPHOT replaces the display device with terminal
+graphics. For example it is possible to load a contour plot of an image
+or image section, and run the APPHOT tasks, interactively marking
+positions on the plot. This is a temporary measure to tide thing over until
+the display interface is available. Furthermore this option is only
+really suitable for those terminal which have both text and graphics
+windows displayed at the same time.
+.PP
+Certain APPHOT tasks such as FITSKY occasionally require an interactive graphics
+capability. For example it is sometimes desirable to plot the histogram
+of the sky pixels and mark the peak of the histogram interactively rather
+than using the automatic sky fitting routines.
+Graphics capablity has been added to APPHOT tasks as deemed useful.
+
+.NH 2
+APPHOT Package Functions
+.NH 3
+Creating Coordinate Lists
+.PP
+APPHOT task(s) shall exist to create coordinate lists interactively within
+APPHOT by loading the IRAF image into the image display
+and successively marking the objects to be measured with the image cursor.
+It shall be possible to mark the positions of objects on the display, and draw
+circles of arbitrary size around the objects of interest.
+It shall be possible to verify existing coordinate lists by marking the object
+coordinates on the image display.
+.PP
+At present the full image display cababilities do not exist in IRAF.
+Therefore as a temporary measure most tasks will run with a contour
+plot and the graphics cursor as a substitute for the image display and
+image cursor by setting the image cursor to stdgraph and the display
+parameter for each task to stdgraph.
+The output coordinates will be written to a text file and may be used as
+starting coordinates for the APPHOT routines.
+.PP
+Those sites which have SUN workstations can use the IMTOOL facilites to
+create cursor lists.
+.PP
+APPHOT tasks shall exist to automatically detect objects by specifying the IRAF
+image to be searched, plus a few image characteristics such as a detection
+threshold and the full width half maximum of the point spread function.
+The output coordinates plus a few object statistics will be written to a
+text file.
+
+.NH 3
+Coordinate List Operations
+.PP
+General list processing tasks are or will be available in the IRAF lists
+package. Examples of useful currently existing tasks are list sorting by for
+example magnitude and performing a linear transformations
+on coordinate lists.
+.PP
+It may eventually be necessary to add some specialized list processing tasks
+to APPHOT. One example is a list matching facility in which objects in
+common to two lists are combined and output to a third list.
+
+.NH 3
+Determining the Image Characteristics
+.PP
+APPHOT tasks shall exist to estimate certain image
+characteristics such as the full width half maximum of the image point spread
+function and the standard deviation of the background. In order to obtain
+meaningful error estimates it is also necessary to specify the noise
+charactersitics of the detector and a noise model.
+In this version of APPHOT two noise
+functions will be supported a constant sky background noise,
+and constant background noise plus Poisson statistics in the object.
+.PP
+The reason for this capability is that the majority of the APPHOT
+algorithm parameters scale with these two image characteristics.
+For example all the pixel scale dependent parameters such as the centering
+aperture, object apertures, the two sky annuli and the
+maximum shift parameter all scale with the full width half
+maximum of the point spread function. Similarly most of the pixel intensity
+dependent parameters scale with the standard deviation of the sky pixels.
+
+.NH 3
+Centering
+.PP
+An APPHOT task shall exist to determine accurate centers for a list of objects,
+using the approximate object coordinates as a starting point.
+The centering aperture may extend beyond the boundaries of the image but
+a warning message will be generated.
+.PP
+A choice of centering algorithms with a range of efficiency and accuracy will
+be available. The center determination must be resistant to the affects of
+nearby contaminating objects.
+.PP
+The user may opt to use the starting center as the actual center in all cases,
+to use the starting center as the actual center if the object is very faint,
+or tweak up the center if the signal to noise is above a certain threshold.
+.PP
+The output of the centering algorithm will the set of computed coordinates
+and their errors.
+
+.NH 3
+Fitting the Sky
+.PP
+An APPHOT task shall exist to compute a constant background value by analysis
+of an annular region surrounding the object.
+The background is assumed to be flat in the region
+of the object, but may contain contaminating objects or defects which
+shall be detected and eliminated by the fitting algorithm.
+It shall be permissible for the background region to extend beyond the
+boundaries of the image; the out of bounds region of the background shall
+be excluded from the fit.
+.PP
+The user may supply a constant background, with zero-valued noise and skew
+value or read appropriate values from a file instead of computing the
+background.
+.PP
+The output of the sky fitting algorithm shall be
+the mode, standard deviation and skew of the sky as well as the number
+of pixels left in the background region after pixel rejection and the number
+rejected.
+
+.NH 3
+Multi-aperture Photometry
+.PP
+APPHOT routines shall exist to compute the integral of object minus background
+within one or more circular apertures centered upon the object.
+The integration shall be
+performed using partial pixel techniques, to minimize the effects of
+sampling. If the aperture contains any indefinite pixels, or if the
+aperture extends beyond the boundary of the image, an indefinite result
+shall be returned. Both normal and weighted photometry routines shall
+be available.
+.PP
+It shall be possible to normalize the output magnitudes to a user specified
+integration time using values stored in the IRAF image header.
+.PP
+The output shall consist of magnitudes and errors for each of the specified
+apertures.
+.NH 3
+Polygonal Aperture Photometry
+.PP
+Determine the integral of the object within a specified
+polygon. Aperture integration shall be by fractional pixel summation
+of successive image lines.
+
+.NH
+Specifications
+.NH 2
+Apphot CL Callable Tasks
+.PP
+The CL callable part of the APPHOT package consists of the following
+routines:\fL
+
+.nf
+.na
+ mark -- create/verify coordinate lists interactively
+ polymark -- create/verify polygon lists interactively
+ daofind -- automatic image finder from DAOPHOT
+ lintran -- linearly transform a list of coordinates (LISTS package)
+
+ radprof -- compute the radial profile of an object.
+ fitpsf -- model the PSF
+
+ center -- compute accurate centers for a list of objects
+ fitsky -- compute accurate sky values for a list of objects
+ phot -- perform multi-aperture photometry on a set of objects
+ polyphot -- compute the flux inside a set of irregular polygons\fR
+ wphot -- perform weighted multi-aperture photometry
+.ad
+.fi
+
+.NH 2
+Standard Analysis Procedures
+.PP
+A standard reduction procedure would be something as follows.
+.IP 1.
+Estimate the image and data characteristics in the following manner.
+.RS
+.IP 1.
+Use the interactive setup option (i key) in the PHOT task to specify the
+fwhm of the psf,
+the centering apperture, the sky annuli, the photometry apertures as
+well as estimate the sky sigma.
+Examine the results (:show command) and optionally store the
+new parameters in the parameter files (w key).
+.IP 2.
+Use the EPAR task to edit the parameter files directly. For example the
+detector gain and readout noise must be known before running PHOT in
+order to get reliable error estimates.
+.RE
+.IP 2.
+Prepare a coodinate list in one of the following ways.
+.RS
+.IP 1.
+Running MARK or POLYMARK.
+.IP 2.
+Run DAOFIND or some other automatic image finder.
+.IP 3.
+Run another APPHOT task such as CENTER .
+.IP 4.
+Run any other IRAF or user program which generates the appropriate
+format.
+.IP 5.
+Transform an existing list using the LISTS package facilities
+.RE
+.IP 3.
+Run PHOT or WHOT in non-interactive mode to perform the multi-aperture
+photometry. The user should be familiar
+with the algorithms used to measure the object center, to fit the background,
+and compute the aperture integral, magnitude, and errors. The values of
+all visible and hidden PHOT parameters should be inspected before doing
+any serious processing. Note that CENTER and FITSKY can be run independently
+of PHOT and their output used as input to PHOT.
+.EQ
+delim $$
+.EN
+
+.NH 2
+The APPHOT Algorithms
+.PP
+The principal APPHOT algorithms are described below.
+
+.NH 3
+The RADPROF Algorithm
+.PP
+The function of the RADPROF task is to compute the radial profile of
+selected, isolated, high signal to noise objects in an IRAF image.
+.PP
+Given the IRAF image, an initial center, an aperture and a step size,
+RADPROF computes the radial profile of an object in the following manner.
+.IP 1.
+The APPHOT centering routines are used to compute an accurate center for the
+object. The new center is used to compute the radial coordinate for each
+pixel in the subraster.
+.IP 2.
+The APPHOT sky fitting routines are used to compute an accurate sky value
+for the object. The new sky value is used to compute the object intensity
+for each pixel in the subraster.
+.IP 3.
+The CURFIT package routines are used to produce a smooth intensity versus
+radius curve by fitting a cubic least squares spline function to the data
+using linear least squares techniques.
+.IP 4.
+The fitted curve is evaluated at equally spaced intervals to produce the
+final radial profile. The profile is normalised using the r = 0 value.
+.IP 5.
+The smoothed curve is integrated using the
+1D integration routines IMINTERP to evalute the fraction of the total
+integral at each interval.
+.IP 6.
+The three quantities $I sub r$ the raw intensity, $Inorm sub r$ the
+normalized intensity, and $Ifraction sub r$ the fraction of the total
+intensity inside radius at r, are plotted on the terminal and
+output as a function of r to a text file.
+.PP
+RADPROF is used principally to compute the stellar image and setup the
+parameters for doing photometry. Its default output is a radial profile
+plot with the phot parameters marked on it.
+
+.NH 3
+The FITPSF Algorithm
+.PP
+The function of the FITPSF task is to fit an analytic model to an object
+in order to derive information about the point spread function. Given
+an IRAF image, an initial center and an aperture, FITPSF computes the
+model parameters in the following manner.
+.IP 1.
+The fitting function is chosen.
+The present version of FITPSF offers two function choices a 2D radial Gaussian
+function and an elliptical Gaussian function.
+A third option, moment analysis, has been added to the FITPSF package.
+The image characteristics are evaluted by using the 0th, 1st and 2nd order
+moments of the image.
+.IP 2
+Initial guesses for the parameters are made from the subraster data.
+.IP 3
+The parameters and their errors are derived using standard non-linear least
+squares techniques and the NLFIT package.
+
+.NH 3
+The DAOFIND Algorithm
+.PP
+The function of the DAOFIND task is to automatically detect objects
+in an IRAF image above a certain intensity threshold.
+The user specifies an intensiyt threshold,
+the estimated full width half maximum of
+the point spread function,
+and limits on the sharpness and roundness of the objects to be detected.
+DAOFIND produces a list of x and y coordinates and a sharpness
+and roundness statistic for each detected object.
+.PP
+The DAOFIND algorithm works in the following way.
+.IP 1.
+The user specifies an intensity threshold above local sky and estimates
+the full width half maximum of the point spread function.
+.IP 2.
+DAOFIND computes a convolution kernel which is a linear
+function of the brightness values in an approximately circular array of
+pixels. The original data is convolved with the computed kernel.
+The equivalent mathematical
+operation is a convolution of the original data
+with truncated, lowered circular Gaussian function with the specified FWHM,
+computed in such a way as to be the mathematical
+equivalent of fitting a Gaussian stellar profile to the object data by least
+squares. The coefficients of the linear function sum to zero so that the
+overall bias level (local sky) cancels out exactly. Since the function is
+symmetric about a single pixel, a smooth gradient in the sky brightness
+also cancels exactly. Therefore the user does not have to specify an
+absolute brightness threshold but only a threshold above local sky.
+.IP 3
+The convolved data is searched for local maxima. Local maxima which are
+less than the specified threshold are rejected. A pixel is defined to be
+a local maximum when it is the brightest pixel within
+$n ~*~ sigma sub Gauss$.
+.IP 4.
+Using the original data, DAOFIND computes an object sharpness statistic which
+can be used to reject
+hot or cold pixels. The sharp parameter is defined below.
+Detected objects with a sharpness parameter outside the range specifed
+by sharplo and sharphi are rejected. Typical values for sharplo and
+sharphi are 0.2 and 1.0 respectively.
+.nf
+
+ $I sub delta$ = height of best fitting $delta$ function = pixel value
+
+ $I sub Gauss$ = height of best fitting Gaussian function = convolved value
+
+ sharplo <= sharp = ${I sub delta} over {I sub Gauss}$ <= sharphi
+
+.fi
+If the brightness enhancement detected in the convolved data is due to
+a single bright pixel, then the best fitting delta function will have an
+amplitude equal to the height of this pixel above the local background,
+while the amplitude of the best fitting Gaussian will be pulled down by
+the surrounding low valued pixels. Sharp will be a number significantly
+greater than one. A single cold pixel will produce
+brightness enhancements approximately 0.5 * FWHM away
+from the pixel in question in all directions. In this case the height
+of the delta
+function which best fits these spurious maxima is close to zero, while the
+height of the best fitting Gaussian is some small positive number.
+In this case sharp will be close to zero.
+.IP 5.
+The roundess statistic is computed from the original picture data by fitting
+1D Gaussians
+to the marginal sums in x and y. If the height of either 1D
+Gaussian is negative the object is rejected. If both heights are
+positive the roundness parameter is computed.
+.nf
+
+ $DELTA I ~=~ I sub {x ~ Gauss} ~-~ I sub {y ~ Gauss}$
+
+ $<I> ~=~ I sub {x ~ Gauss} ~+~ I sub {y ~ Gauss}$
+
+ $roundlo ~<=~ round ~=~ {DELTA I} over <I> ~<=~ roundhi$
+
+.fi
+Objects which are elongated in the
+x direction have roundness values less than zero and those elongated in
+the y direction have roundness greater than zero.
+Round discriminates only against objects which are elongated
+along either rows or columns. Objects elongated at a 45 degree angle will
+not be rejected.
+.IP 6.
+Finally the approximate x and y centroids of the detected objects,
+rough magnitudes relative to threshold are computed, and object is added
+to the output file.
+
+
+.NH 3
+The CENTER Task
+
+.NH 4
+Centering Package Routines
+.PP
+The following are the principal programmer callable routines routines in the
+centering package.
+.nf
+\fL
+
+ apcinit (ap, cfunction, cbox, fwhmpsf, noise)
+ ier = apfitcenter (ap, im, xinit, yinit)
+ ier = aprefitcenter (ap)
+ value = apstat[ir] (ap, param)
+ apstats (ap, param, str, maxch)
+ apset[sir] (ap, param, value)
+ apcfree (ap)
+
+\fR
+.fi
+.PP
+The following quantities can be examined or set by apstat/apset calls
+.nf
+\fL
+ data 1. fwhmpsf full width half maximum of psf in pixels
+parameters 2. threshold minimum intensity for centering
+ 3. noise noise model
+ 4. sigma standard deviation of background
+ 5. readnoise readout noise of CCD in electrons
+ 6. epadu electrons per adu
+
+centering 1. calgorithm centering algorithm
+parameters 2. positive emission / absorption features
+ 3. cbox centering radius in fwhmpsf
+ 4. cmaxiter maximum number of fitting iterations
+ 5. maxshift maximum permitted shift in fwhmpsf
+ 6. minsnratio minimum permitted signal to noise ratio
+ 7. clean clean subraster before centering
+ 8. rclean cleaning radius in fwhmpsf
+ 9. rclip clipping radius in fwhmpsf
+ 10.kclean k-sigma rejection for cleaning in sigma
+\fR
+.fi
+
+.PP
+The following computed quantities can be examined by apstat calls.
+.nf
+\fL
+ 1. xcenter computed x coordinate
+ 2. ycenter computed y coordinate
+ 3. xerr computed x coordinate error
+ 4. yerr computed y coordinate error
+\fR
+.fi
+.PP
+See the manual pages for CENTER and CENTERPARS for a detailed description
+of the centering parameters.
+
+.NH 4
+The Centering Algorithm
+.PP
+The function of the CENTER task is to compute accurate centers and errors
+for objects in an IRAF image given a list of initial positions and a
+centering aperture.
+.IP 1.
+If the centering algorithm is disabled, the computed center is set to the
+initial center and the uncertainty estimate is set to zero.
+.IP 2.
+If the cleaning algorithm is enabled, clean the subraster before centering.
+.IP 3.
+Estimate is made of the signal to noise of the object. If this quantity is
+less than a certain minimum value the computed center is kept
+but a warning message is issued.
+.IP 4.
+The center and errors are computed using one of several algorithms.
+.IP 5.
+If the computed center is greater than a user specified distance from the
+initial center then the computed center is returned with an error
+message.
+
+.NH 4
+Symmetry Clean Algorithm
+.PP
+The symmetry-clean algorithm attempts to remove defects in the centering
+subraster by assuming that the object has radial symmetry and comparing
+pixels on the opposite sides of the center of symmetry. The algorithm
+works in the following way.
+.IP 1.
+The center of symmetry is computed. Normally the center of symmetry is assumed
+to coincide with the position of the brightest pixel in the subarray.
+However if the maximum pixel is more than a user specified distance away
+from the intial center, the initial center is used as the center of symmetry.
+.IP 2.
+Pixels inside a specified cleaning radius are unaltered.
+.IP 3.
+Pairs of pixels diametrically opposed about the center
+in the cleaning region between the cleaning and clipping
+radii are tested for equality. If the difference between the pixels is
+greater than a specified k-sigma rejection limit, the larger value is replaced
+by the smaller.
+In this region sigma is computed from Poisson statistics.
+.IP 4.
+Pairs of pixels in the clippping
+region are compared in the same manner as those in the cleaning region
+except that sigma is the standard deviation of the sky pixels.
+.PP
+The effect of the symmetry-clean algorithm is to edit the raster,
+removing any contaminating objects in the vicinity of the primary object.
+This simplifies the fitting algorithm and increases its reliability,
+since it does not have to deal with multipeak marginal distributions.
+
+.NH 4
+Signal to Noise Estimate
+
+.PP
+The signal to noise of the object is estimated from the data values
+in the subraster in the following way.
+.nf
+
+ $SNR ~=~ N sub object over {sqrt {n sub pix ~*~sigma sub sky sup 2}}$
+
+ or
+
+ $SNR ~=~ N sub object over {sqrt {N sub object ~+~ n sub pix~*~sigma sub sky sup 2}}$
+
+.fi
+where $N sub *$ is the number of counts in the object above threshold,
+$sigma sub sky$
+is the standard deviation of the pixels in the sky region and
+$n sub pix$ is the number of pixels in the object aperture.
+The first approximation corresponds to constant sky noise only,
+the second includes Poisson noise in the object.
+
+.NH 4
+Centroid
+.PP
+The centroid centering algorithm is similar to that used in MPC and can
+be briefly described as follows. For more detailed description
+see (Stellar Magnitudes From Digital Pictures, 1980, Adams et al).
+.IP 1.
+The marginal distributions in x and y are accumulated.
+.IP 2.
+The intensity weighted centroid positions for the marginals is computed
+using only data pixels which are above the threshold intensity. If the
+threshold parameter is 0 the mean intensity of the marginal is used
+in place of the threshold
+.nf
+
+ $I sub i ~=~ I sub i ~-~ threshold ~~~~~ I sub i ~>~ 0.0$
+
+ $x sub c ~=~ {sum I sub i ~ x sub i} over {sum I sub i}$
+
+.fi
+.IP 3.
+The errors are estimated in the following way
+.nf
+
+ $sigma sup 2 ~=~ {sum I sub i ~ x sub i sup 2} over {sum I sub i} ~-~ x sub c sup 2$
+
+ $err sub xc ~=~ sqrt {{sigma sup 2} ~/~ sum I sub i}$
+
+.fi
+
+.NH 4
+Gaussian Fit to the Marginals
+.PP
+The fit is performed in the following way.
+.IP 1.
+The marginal distributions in x and y are accumulated.
+.IP 2.
+Initial guesses for the parameters of the 1D Gaussians $I sub Gauss$,
+$x sub c$ and $I sub sky$ are derived from the marginal distributions
+themselves. The width $sigma$ is held constant.
+.IP 3.
+The best fit parameters and their errors are derived using non-linear
+least-squares techniques and the NLFIT package.
+
+.NH 4
+Optimal Filtering of Marginals
+.PP
+The fit is performed is the following way.
+.IP 1.
+The marginal distributions in x and y are accumulated.
+.IP 2.
+The centroid of the observed distribution is computed by solving the
+following equation.
+.nf
+
+ $PSI (x sub c ) ~=~ sum omega sub i (x sub c ) ~ PHI sub i ~=~ 0$
+
+ $omega sub i ~=~ {{partial phi sub i} ~/~ {partial x sub c}} over {phi sub i~+~b}$
+
+.fi
+The assumptions are that the observed distribution $PHI sub i$ is correctly
+modeled by the profile function $phi sub i$. The usual choise of profile
+model for centering is a Gaussian. Howver in the interests of speed a triangle
+function has been substituted. This causes at most a 7% increase in the
+random centering error.
+.IP 3.
+The startup procedure is based on the following fact.
+.nf
+
+ $PSI (x sub n )~>~0~~for~~ x sub n ~<~ x sub c$
+
+ $PSI (x sub n ) ~<~0~~for~~ x sub n ~>~ x sub c$
+
+.fi
+The iteration is initialized by assuming that $x sub 1$ = $x sub c$ and
+computing $PSI (x sub 1 )$. The initial x
+value is incremented by $+- sigma sub Gauss$ depending on the sign of $PSI$. The
+search is repeated until $PSI (x sub {n-1})$ and $PSI (x sub n)$ have
+opposite signs. At this point the true center is bracketed by the
+estimated positions $(x sub n, ~ x sub {n-1})$ and we have a table of at
+least 2 values of $PSI (x sub n )$.
+.IP 4.
+The computation proceeds by interpolating in the table of values for the
+estimated position $x sub {n+1}$ where $PSI$ = 0. If the table contains only
+two values as may be the case for the inititial interpolation, linear
+interpolation is used. In all other cases a quadratic fit to the three
+most recent $PSI$ values is used. The computation is complete when
+two successive estimates differ by less than some tolerance typically
+0.001 pixel.
+.IP 5.
+The errors are estimated as follows.
+.nf
+
+ $sigma sup 2 ~=~ ( {int {( partial phi ~/~ partial x sub c )} sup 2 over {
+ phi + b}} ) sup -1$
+
+ $err sub xc ~=~ sqrt {sigma sup 2}$
+
+.fi
+
+.NH 4
+Other Centering Methods
+.PP
+The code is constructed in such a way that new algorithms may be
+easily added at a future date, such as the more sophisticated techniques
+required for accurate astrometry.
+.EQ
+delim $$
+.EN
+.NH 3
+The FITSKY Task
+
+.NH 4
+Sky Fitting Routines
+
+.PP
+The following are the main entry points in the sky fitting package.
+.nf
+\fL
+ apsinit (ap, function, annulus, dannulus, fwhmpsf, noise)
+ ier = apfitsky (ap, im, xpos, ypos, sd, gd)
+ ier = aprefitsky (ap, sd, gd)
+ value = apstat[ir] (ap, param)
+ apstats (ap, param, str, maxch)
+ apset[irs] (ap, param, value)
+ apsfree (ap)
+\fR
+.fi
+.PP
+The following quantities can be examined or set with apset/apstat calls.
+.nf
+\fL
+data 1. fwhmpsf full width half maximum of the psf
+parameters 2. sigma standard deviation of sky pixels
+
+sky fitting 1. annulus inner radius of sky annulus in fwhmpsf
+parameters 2. dannulus outer radius of sky annulus in fwhmpsf
+ 3. sfunction sky fitting algorithm
+ 4. smaxiter maximum number of fitting iterations
+ 5. kreject k-sigma rejection limit sigma
+ 6. nreject maximum number of rejection cycles
+ 7. rgrow region growing radius in fwhmpsf
+
+ 8. khist half-wdth of histogram in sigma
+ 9. binsize binsize of histogram in sigma
+ 10.smooth Lucy smooth the histogram
+
+ 11.skyfile name of text file containing sky values
+ 12.skyvaluser supplied constant value for sky
+\fR
+.fi
+.PP
+The following computed quantities can only be examined with apstat calls.
+.nf
+\fL
+ 1. skymode computed sky value
+ 2. skysig computed sky sigma
+ 3. skyskew computed sky skew
+ 4. nsky number of sky pixels
+ 5. nsky_reject number of rejected sky pixels
+\fR
+.fi
+
+.NH 4
+The Sky Fitting Algorithms
+.PP
+A good background fit is essential to aperture photometry. Fitting
+the background is trivial in a sparse field, but difficult in a crowded
+field. In general the background region will contain contaminating objects
+which must be detected and excluded if a good fit is to be obtained.
+.PP
+The main algorithm used in APPHOT is the following.
+.IP 1.
+If the skyfitting switch is disabled either read the sky values from a text
+file or accept a user supplied constant for the sky.
+.IP 2.
+Perform the initial sky fit using one of the specified algorithms. The
+sky fitting algorithms fall into three general categories, those that use
+the actual sky pixel array itself, those that operate on a histogram of
+sky values and those that rely on user interaction.
+.IP 3.
+If the pixel rejection flags are set perform pixels rejection with optional
+region growing.
+
+.NH 4
+Sky Pixel Array Techniques
+
+.NH 5
+Median
+.IP 1.
+Sort the array of sky pixels. This is necessary to avoid quantization effects.
+.IP 2.
+Compute the median, and the standard deviation and skew with respect to the
+mean.
+.IP 3.
+If the k-sigma rejection limit is greater than zero and the maximum number
+of rejection cycles is greater than one, perform pixel rejection.
+Pixels greater than k-sigma from the median are rejected. Region growing
+is optional.
+.IP 4.
+Stop the rejection cycle on any given iteration if the maximum number of
+rejection cycles ix exceeded, no more sky pixels are left or no more
+pixels are rejected.
+
+.NH 5
+Mode
+.IP 1.
+Sort the array of sky pixels. This is necessary to avoid quantization effects.
+.IP 2.
+Compute the mode, and the standard deviation and skew
+with respect to the mean.
+.nf
+
+ $I sub mode ~=~ 3.0 ~*~ I sub median ~-~ 2.0 ~*~ I sub mean$
+
+.fi
+.IP 3.
+If the k-sigma rejection limit is greater than zero and the maximum number
+of rejection cycles is greater than one, perform pixel rejection.
+Pixels greater than k-sigma from the mode are rejected. Region growing
+is optional.
+.IP 4.
+Stop the rejection cycle on any given iteration if the maximum number of
+rejection cycles ix exceeded, no more sky pixels are left or no more
+pixels are rejected.
+
+
+.NH 4
+Histogram Techniques
+.PP
+The following three techniques all operate on the histogram of the sky pixels.
+The routines all construct the histogram in the following identical manner.
+.IP 1.
+The mean of the sky distribution is computed.
+.IP 2.
+If the user specified standard deviation of the sky pixels is INDEF the
+algorithm computes the standard deviation of the sky pixels with respect
+to the mean.
+.IP 3.
+All pixels within plus or minus sigma standard
+deviations are accumulated into a histogram. The user specifies the bin size.
+.IP 4.
+The histogram may optionally be Lucy smoothed before any operation is performed
+on it.
+
+.NH 5
+Centroid
+.PP
+The mode, sigma and skew of the sky pixels are computed in the following
+manner.
+.IP 1.
+The histogram is compiled as above.
+.IP 2.
+The mode, standard deviation and skew of the sky pixels are computed in the
+following manner.
+
+.nf
+ $I sub 0 ~=~ sum I sub i$
+ $I sub 1 ~=~ sum I sub i ~ x sub i$
+ $I sub 2 ~=~ sum I sub i ~ x sub i sup 2$
+ $I sub 3 ~=~ sum I sub i ~ x sub i sup 3$
+
+ $I sub mode ~=~ {I sub 1} ~/~ {I sub 0}$
+ $sigma ~=~ {( I sub 2 ~/~ I sub 0 ~-~ I sub mode sup 2 )} sup {1/2}$
+ $skew ~=~ ( {I sub 3 ~/~ I sub 0 ~-~ I sub mode ~*~ sigma sup 2 ~-~ I sub mode sup 3} ) sup {1/3}$
+
+.fi
+.IP 3
+If pixel rejection is enabled sky pixels within a user supplied limit of
+the mode are rejected with optional region growing.
+
+.NH 5
+Gaussian Fit
+.PP
+The mode, standard deviation and skew of the sky pixels are derived from a
+model fit in the following way.
+.IP 1.
+The histogram of the sky pixels is compiled as above.
+.IP 2.
+Initial guesses to the model parameters, $N sub max$, $I sub mode$,
+$sigma$, and $skew$ are made from the histogram itself.
+.IP 3.
+Final parameters and their errors are derived using non-linear least squares
+techniques and the NLFIT package.
+.IP 4.
+If pixel rejection is enabled sky pixels within a user supplied limit of
+the computed mode are rejected with optional region growing.
+
+.NH 5
+Optimal Filtering
+.PP
+The method is as follows.
+.IP 1.
+The histogram is compiled as above.
+.IP 2.
+Using the mean of the sky pixels as the intital value of the sky mode,
+a new mode is computed using the optimal filtering technique
+described for centering.
+.IP 4
+If pixel rejection is enabled sky pixels within a user supplied limit of
+the computed mode are rejected with optional region growing.
+
+.NH 5
+Cross Correlation
+.PP
+The method is as follows.
+.IP 1.
+The histogram is compiled as above.
+.IP 2.
+The noise function is estimated using the standard deviation of the sky
+pixels and the cross-correlation function is computed.
+.IP 3.
+The mode is computed using quadratic interpolation around the peak of the
+distribution.
+.IP 4
+If pixel rejection is enabled sky pixels within a user supplied limit of
+the mode are rejected with optional region growing.
+
+.NH 4
+Interactive Techniques
+
+.NH 5
+Histogram Plot
+.PP
+The histogram is compiled as described above and the user marks the peak
+on the histogram plot with the graphics cursor. The sigma and skew of the
+sky distribution with respect to the mean is also computed.
+
+.NH 5
+Radial Distribution
+.PP
+A radial profile plot of the sky region is plotted and the user marks the
+sky value on the plot with the graphics cursor. The sigma and skew of the sky
+distribution with respect to the mean is computed.
+
+.NH 4
+Pixel Rejection and Region Growing
+.PP
+All the sky fitting algorithms permit pixel rejection and
+optional region growing.
+Pixel rejection and region growing are
+performed by locating all pixels more than k * sigma from the mode,
+and blindly rejecting all pixels within a certain radius of each deviant
+pixel. This simple algorithm works well because the sample is large,
+and therefore there is little penalty for discarding pixels that might
+not be deviant. Region growing also tends to accelerate convergence
+significantly.
+.PP
+Very faint contaminating objects are difficult to detect and reject.
+If there are enough such objects, they should not be rejected, because
+there are probably a few in the object aperture as well. A higher sky
+sigma will be calculated and the computed uncertainty in the magnitude
+will increase. The best solution to this problem may be to increase
+the size of the annulus to minimize the bias.
+
+.NH 4
+The Principal PHOT Routines
+.PP
+The main entries in the photometry routine are the following.
+.nf
+\fL
+ apinit (ap, cfunction, cbox, sfunction, annulus, dannulus,
+ aperts, napert, fwhmpsf, noise)
+ ier = apfitcenter (ap, im, xinit, yinit)
+ ier = aprefitcenter (ap)
+ ier = apfitsky (ap, im, xcenter, ycenter, sd, gd)
+ ier = aprefitsky (ap, sd, gd)
+ ier = apmag (ap, im, xcenter, ycenter, skyval, skysig, nsky)
+ ier = apwmag (ap, im, xcenter, ycenter, positive, skyval, skysig, nsky)
+ ier = apremag (ap, positive, skyval, skysig, nsky)
+ ier = apwremag (ap, positive, skyval, skysig, nsky)
+ value = apstat[ir] (ap, param)
+ apstats (ap, param, str, maxch)
+ apset[sir] (ap, param, value)
+ apfree (ap)
+
+\fR
+.fi
+.PP
+The following parameters can be examined or altered by apset/apstat calls.
+.nf
+\fL
+ 1. weighting weighting scheme for wphot
+ 2. aperts list of apertues
+ 3. naperts number of apertures
+ 4. zmag zero point of magnitude scale
+ 5. itime effective integration time
+\fR
+.fi
+.PP
+The following quantities can be examined with apstat calls.
+.nf
+\fL
+
+ 1. sums array of aperture sums
+ 2. areas array of areas
+ 3. mags array of magnitudes
+ 4. magerrs array of magnitude errors
+
+\fR
+.fi
+
+.NH 4
+The PHOT Aperture Integration Algorithm
+.PP
+The integral of the flux within a circular aperture is computed by
+fractional pixel techniques. Pixels are assumed to be square apertures
+arranged in a rectangular grid. The fraction of a pixel which lies within
+the circular APPHOT aperture is computed by an approximation, and all
+such contributions are summed to produce the total integral.
+.PP
+The inclusion of a partial pixel inside the aperture is done as follows.
+.IP 1.
+If the distance of the current pixel from the center of the star, r, is
+exactly equal to the radius of the aperture R then one-half the counts in
+the pixel are included.
+.IP 2.
+If r < R - 0.5 the entire pixel is included while if r > R + 0.5 the pixel
+is wholly excluded.
+.IP 3.
+In between the fraction of the counts varies linearly. A circular aperture
+is approximated by an irregular polygon.
+.PP
+The simplicity of aperture photometry limits the amount of information
+available for error analysis. The following three sources of error are
+considered.
+.IP 1.
+The error due to sky noise in the aperture.
+.nf
+
+ $error sub 1 ~=~ sigma sub sky ~*~ {A sub apert} sup {1/2}$
+
+.fi
+.IP 2.
+The error in the aperture sum.
+.nf
+
+ $error sub 2 ~=~ ( {A sub "sum" ~/~ phpadu} ) sup {1/2}$
+
+.fi
+.IP 3.
+The mean error of the sky.
+.nf
+
+ $error sub 3 ~=~ sigma sub sky ~*~ A sub apert ~/~ nsky sup {1/2}$
+
+
+.fi
+where $sigma sub sky$ is either computed by the background fitting
+algorithm or set by the user,
+and $A sub apert$ is the fractional pixel area of the
+aperture.
+
+.NH 4
+The WPHOT Algorithm
+.PP
+The WPHOT algorithm computes a weighted aperture sum in an attempt to
+minimize noise in the sky. The algorithm is the following where w is
+the weight for each pixel, p is the noise free profile value and
+$sigma$ is the noise per pixel from all sources. (See the paper
+by Stover and Allen 1987 for details)
+.nf
+
+ $A sub sum ~=~ sum {w sub i ~*~ (I sub i ~-~ sky)}$
+
+ $w sub i ~=~ C ~*~ p sub i ~/~ sigma sup 2 sub i$
+
+ $C ~=~ sum {p sub j} / sum {p sub j ~*~ w sub j}$
+.fi
+
+.NH 4
+The POLYPHOT ROUTINES
+.PP
+The principal polyphot routines are the following.
+
+.nf
+\fL
+ apyinit (ap, sfunction, annulus, dannulus, noise)
+ ier = apfitcenter (ap, im, wx, wy)
+ ier = aprefitcenter (ap)
+ ier = apfitsky (ap, im, xcenter, ycenter, sd, gd)
+ ier = aprefitsky (ap, sd, gd)
+ ier = polyfit (ap, im, xver, yver, nver)
+ value = apstat[ir] (ap, param)
+ apstats (ap, param, str, maxch)
+ apset[sir] (ap, param, value)
+ apfree (ap)
+
+\fR
+.fi
+
+.PP
+.NH 4
+The POLYPHOT Algorithm
+.PP
+The function of the POLYPHOT task is to compute the flux inside an
+irregular polygon given a list of the coordinates of the vertices of a polygon.
+The polygon must be entirely inside the image and the vertices of the polygon
+must be specified in clockwise or counterclockwise order.
+The actual algorithm used is as follows.
+.IP 1.
+The range of image lines which intersect the polygon are computed.
+.IP 2.
+For each image line in the specified range the intersection points with the
+polygon are computed.
+.IP 3.
+The flux between pairs of limits is summed using a fractional pixel
+approximation for the endpoints.
+.IP 4.
+The sky is fitted using any of the methods previously discussed and a
+user specified annular region.
+.IP 5.
+The errors are computed as specified in the PHOT specifications.
+.PP
+.EQ
+delim $$
+.EN
+
+.NH
+Example
+.PP
+A brief example may help illustrate the use of the package. Suppose
+we want to process a few hundred stars on image "blue".
+.PP
+The first step is to prepare a list of objects to be measured. The simplest
+way to do this is to interactively mark the objects with the image
+cursor using the display (graphics) device and the RIMCURSOR (RGCURSOR)
+task.
+.nf
+\fL
+
+ ... load image on the display ...
+
+ ap> rimcursor > starlist
+
+ ... move cursor and mark stars ...
+
+
+ ... load contour plot on graphics terminal ...
+
+ ap> rgcursor > starlist
+
+ ... move cursor and mark stars ...
+\fR
+.fi
+
+Alternatively one can run DAOFIND to compute a list of candidate objects
+in the frame.
+The name of the coordinate file is stored in the PHOT parameter set.
+
+.nf
+\fL
+ ap> phot.coords=starlist
+\fR
+.fi
+
+.PP
+The next step is to set up the PHOT parameters interactively.
+First we load the image (contour plot) blue on the display (graphics
+terminal). Next we call up PHOT in interactive mode.
+
+.nf
+\fL
+ ap> phot blue
+ ... cursor appears ...
+
+\fR
+.fi
+
+.PP
+PHOT takes input by reading the image (graphics)
+display (terminal) cursor. In order to display the available commands
+we tap the ? key and the following text appears on the screen.
+
+.nf
+\fL
+ Interactive Phot Commands
+
+? Print options
+: Colon command see below
+i Setup PHOT parameters interactively
+w Write PHOT parameters to the parameter files
+l Process the remainder of the coordinate list
+r Rewind the coordinate list
+c Fit center around the current cursor position
+t Fit sky around the current cursor position
+s Fit sky around the current center position
+p Compute magnitudes around the cursor position
+f Fit center, sky and compute magnitudes
+sp Fit center, sky, compute magnitudes, and save
+q Exit program
+
+Phot parameters are listed or set with the following commands.
+
+:m [n] Move cursor to the [nth] object in the coordinate list
+:n [n] Measure the [nth] object in the coordinate list
+
+:show [center/sky/phot/all] List the aphot parameters
+:fwhmpsf [value] Full width half maximum of the PSF
+:noise [string] Noise model
+:threshold [value] Threshold value for centering
+:sigma [value] Standard deviation of the background
+:ccdread CCD readout noise keyword
+:readnoise Readout noise in electrons
+:gain Gain keyword
+:epadu Electrons per adu
+
+:calgorithm [string] Centering function
+:positive [y/n] Emission or absorption feature
+:cbox [value] Width of the centering box in fwhmpsf
+:cmaxiter [value] Maximum number of centering iterations
+:maxshift [value] Maximum shift in fwhmpf
+:minsnratio [value] Minimum signal to noise ratio of pixels
+:clean [y/n] Clean subraster before centering
+:rclip [value] Clipping radius in fwhmpsf
+:rclean [value] Cleaning radius in fwhmpsf
+:kclean [value] Sigma for clean algorithm
+:mkcenter [y/n] Mark the centers on the display
+
+:salgorithm [string] Sky fitting algorithm
+:annulus [value] Inner radius of sky annulus in fwhmpsf
+:dannulus [value] Width of sky annulus in fwhmpsf
+:skyvalue [value] User supplied sky
+:smaxiter [value] Maximum number of rejection cycles
+:skreject [value] +/- Pixel rejection limits in sky sigma
+:snreject [value] Maximum number of rejection interations
+:khist [value] +/- Sky histogram size in sky sigma
+:binsize [value] Resolution of sky histogram in sky sigma
+:smooth [y/n] Lucy smooth the sky histogram
+:rgrow [value] Region growing radius in fwhmpsf
+:marksky [y/n] Mark the sky annuli on the display
+
+:weighting Weighting for wphot
+:aperts [string] Aperture radii in fwhmpsf
+:zmag [value] Zero point of magnitude scale
+:exposure [string] Exposure time keyword
+:itime [value] Integration time
+\fR
+.fi
+
+.PP
+We select the interactive setup option, move the image
+cursor to a high signal-to-noise, isolated star and tap the i key.
+PHOT responds by plotting the radial profile of the star on the
+screen and requesting the user to mark the fwhm of
+the psf, the centering aperture, the inner and outer sky annuli,
+the sky background and sigma and the set of circular apertures.
+The parameters so set can be examined and/or reset with the : commands as shown
+above. Sample measurements can be made of several stars by moving the
+cursor and typing the f command. Finally when we are happy with the
+parameter set we type w to store the parameters and q to exit the program.
+.PP
+Now we are ready to do photometry. We enter the PHOT program in batch mode.
+
+.nf
+\fL
+ ap> phot blue inter- &
+\fR
+.fi
+
+The batch job is now running, appending output lines to the file "blue.mag.#".
+We can proceed to set up the job for the red image, in much the same way
+that we set up the job for the blue image. When both jobs finish, we
+can use the list processing tools to filter out the good objects and
+calculate colors.
+
+.NH
+The APPHOT Tasks
+.PP
+Manual pages for the APHOT tasks are attached. Although the working of the
+various tasks may change in detail, the help pages attached here should
+provide a good description of the function of each task.
+.PP
+When the package has stabilized a detailed users guide will be written.
diff --git a/noao/digiphot/apphot/doc/specs/apphot.spc.lw b/noao/digiphot/apphot/doc/specs/apphot.spc.lw
new file mode 100644
index 00000000..71285557
--- /dev/null
+++ b/noao/digiphot/apphot/doc/specs/apphot.spc.lw
@@ -0,0 +1,1296 @@
+.EQ
+delim $$
+.EN
+
+.RP
+.TL
+Specifications for the Aperture Photometry Package
+.AU
+Lindsey Davis
+.AI
+.K2 "" "" "*"
+Revised October 1987
+
+.AB
+The APPHOT package is a set of tasks for performing aperture photometry
+on uncrowded or moderately crowded fields, in either interactive or batch mode.
+The photometric technique employed is fractional pixel aperture
+integration. Point spread function fitting techniques are not used and no
+knowledge of the point spread function is required for the computation of
+magnitudes. Separate tasks are provided for creating and modifying object lists,
+computing accurate centers for a list of objects, computing sky values for
+a list of objects and performing aperture photometry inside circular or
+polygonal apertures.
+.AE
+
+.NH
+Introduction
+.PP
+The APPHOT package is a set of tasks for performing
+aperture photometry on uncrowded or moderately crowded fields.
+The photometric technique employed is fractional pixel integration. Point
+spread function techniques are not used and no knowledge of the point spread
+function is required for the computation of magnitudes.
+.PP
+The APPHOT package performs multi-aperture photometry on digitized starfields
+maintained as IRAF image files. Input to the package consists of an
+image file, a list of object coordinates, numerous parameters controlling
+the analysis algorithms and, optionally, the graphics terminal and/or
+display. APPHOT output consists of successive lines of text where each line
+summarizes the results of the analysis for a particular object.
+.PP
+Given starting coordinates and an IRAF image, the principal APPHOT
+task computes accurate centers, sky values and magnitudes
+for a list of objects. Separate
+IRAF callable tasks in APPHOT exist to create and modify object
+lists, to determine image characteristics such as the full width half maximum
+of the point spread function or standard deviation of the sky pixels,
+to compute accurate centers for a list of objects, to compute accurate local sky
+values for a list of objects, and to compute magnitudes inside a polygonal
+aperture.
+
+.NH
+APPHOT Package Requirements
+.NH 2
+APPHOT Package Input
+.NH 3
+The IRAF Image
+.PP
+APPHOT assumes that images exist on disk in IRAF format. Facilities for reading
+and writing images exist elsewhere in IRAF such as in package DATAIO or
+MTLOCAL.
+.PP
+APPHOT assumes that the image data is linear.
+The input image is assumed to have been corrected for those instrumental
+defects which affect the intensity of a pixel. These include pixel to
+pixel variations in the bias values, pixel to pixel gain variations,
+cosmic rays, cosmetic defects, geometric distortion,
+and detector non-linearities.
+.PP
+APPHOT assumes that the local sky background is approximately flat in the
+vicinity of the object being measured. This assumption is equivalent to
+assuming that the local sky region has a unique mode. Therefore any
+variations in the sky background which occur at the same scale as the
+sky region should be removed prior to entering APPHOT.
+.PP
+The point spread function of the image is assumed to be constant for all
+regions of the image. This is particularly critical in the case of faint objects
+for which small apertures which minimize the effects of crowding and
+sky noise in the aperture are used. The wings of the object will
+almost certainly extend beyond the aperture and good results will only be
+obtained if
+objects are consistently well centered and the shape and diameter of an object
+is constant throughout the image and invariant to magnitude.
+
+.NH 3
+The Coordinate Lists
+.PP
+All APPHOT tasks operate on lists of object coordinates or interactive cursor
+input. Lists are maintained as text files,
+one object per line with the x and y coordinates in
+columns one and two respectively. List files may be created interactively
+with either the graphics or image cursor, by a previously executed APPHOT
+task, by a previously executed IRAF task or by a user task.
+.PP
+The x and y coordinates contained in the list file can be either the
+starting centers for the objects of interest or the true centers.
+In either case the aperture centered around the object position must
+not extend beyond the boundary of the image. To obtain reliable results
+from the centering algorithm the starting centers should not be more than
+1 fwhmpsf pixels from the true centers.
+
+.NH 3
+Algorithm Parameters
+.PP
+Many tasks in the APPHOT package have an associated set of algorithm parameters
+which control the operation of the analysis routines. For example the
+centering and sky fitting algorithms each have an associated group of
+parameters.
+The APPHOT tasks supply reasonable defaults for these parameters. However
+the user may alter them at any time in interactive mode or by editing the
+appropriate parameter file before running the task in batch.
+
+.NH 3
+Terminal Graphics and the Image Display
+.PP
+Most APPHOT programs may be run in either interactive or batch mode.
+In interactive mode, the user can mark the positions of objects by
+interactively, positioning the image cursor on the display device.
+Simple cursor commands can interactively alter the algorithm parameters.
+In batch mode the algorithm parameters are
+fixed and object coordinates are taken from the user supplied coordinate list.
+The display device is not required in batch mode.
+.PP
+At present there is no high level IRAF display interface. Therefore the present
+version of APPHOT replaces the display device with terminal
+graphics. For example it is possible to load a contour plot of an image
+or image section, and run the APPHOT tasks, interactively marking
+positions on the plot. This is a temporary measure to tide thing over until
+the display interface is available. Furthermore this option is only
+really suitable for those terminal which have both text and graphics
+windows displayed at the same time.
+.PP
+Certain APPHOT tasks such as FITSKY occasionally require an interactive graphics
+capability. For example it is sometimes desirable to plot the histogram
+of the sky pixels and mark the peak of the histogram interactively rather
+than using the automatic sky fitting routines.
+Graphics capablity has been added to APPHOT tasks as deemed useful.
+
+.NH 2
+APPHOT Package Functions
+.NH 3
+Creating Coordinate Lists
+.PP
+APPHOT task(s) shall exist to create coordinate lists interactively within
+APPHOT by loading the IRAF image into the image display
+and successively marking the objects to be measured with the image cursor.
+It shall be possible to mark the positions of objects on the display, and draw
+circles of arbitrary size around the objects of interest.
+It shall be possible to verify existing coordinate lists by marking the object
+coordinates on the image display.
+.PP
+At present the full image display cababilities do not exist in IRAF.
+Therefore as a temporary measure most tasks will run with a contour
+plot and the graphics cursor as a substitute for the image display and
+image cursor by setting the image cursor to stdgraph and the display
+parameter for each task to stdgraph.
+The output coordinates will be written to a text file and may be used as
+starting coordinates for the APPHOT routines.
+.PP
+Those sites which have SUN workstations can use the IMTOOL facilites to
+create cursor lists.
+.PP
+APPHOT tasks shall exist to automatically detect objects by specifying the IRAF
+image to be searched, plus a few image characteristics such as a detection
+threshold and the full width half maximum of the point spread function.
+The output coordinates plus a few object statistics will be written to a
+text file.
+
+.NH 3
+Coordinate List Operations
+.PP
+General list processing tasks are or will be available in the IRAF lists
+package. Examples of useful currently existing tasks are list sorting by for
+example magnitude and performing a linear transformations
+on coordinate lists.
+.PP
+It may eventually be necessary to add some specialized list processing tasks
+to APPHOT. One example is a list matching facility in which objects in
+common to two lists are combined and output to a third list.
+
+.NH 3
+Determining the Image Characteristics
+.PP
+APPHOT tasks shall exist to estimate certain image
+characteristics such as the full width half maximum of the image point spread
+function and the standard deviation of the background. In order to obtain
+meaningful error estimates it is also necessary to specify the noise
+charactersitics of the detector and a noise model.
+In this version of APPHOT two noise
+functions will be supported a constant sky background noise,
+and constant background noise plus Poisson statistics in the object.
+.PP
+The reason for this capability is that the majority of the APPHOT
+algorithm parameters scale with these two image characteristics.
+For example all the pixel scale dependent parameters such as the centering
+aperture, object apertures, the two sky annuli and the
+maximum shift parameter all scale with the full width half
+maximum of the point spread function. Similarly most of the pixel intensity
+dependent parameters scale with the standard deviation of the sky pixels.
+
+.NH 3
+Centering
+.PP
+An APPHOT task shall exist to determine accurate centers for a list of objects,
+using the approximate object coordinates as a starting point.
+The centering aperture may extend beyond the boundaries of the image but
+a warning message will be generated.
+.PP
+A choice of centering algorithms with a range of efficiency and accuracy will
+be available. The center determination must be resistant to the affects of
+nearby contaminating objects.
+.PP
+The user may opt to use the starting center as the actual center in all cases,
+to use the starting center as the actual center if the object is very faint,
+or tweak up the center if the signal to noise is above a certain threshold.
+.PP
+The output of the centering algorithm will the set of computed coordinates
+and their errors.
+
+.NH 3
+Fitting the Sky
+.PP
+An APPHOT task shall exist to compute a constant background value by analysis
+of an annular region surrounding the object.
+The background is assumed to be flat in the region
+of the object, but may contain contaminating objects or defects which
+shall be detected and eliminated by the fitting algorithm.
+It shall be permissible for the background region to extend beyond the
+boundaries of the image; the out of bounds region of the background shall
+be excluded from the fit.
+.PP
+The user may supply a constant background, with zero-valued noise and skew
+value or read appropriate values from a file instead of computing the
+background.
+.PP
+The output of the sky fitting algorithm shall be
+the mode, standard deviation and skew of the sky as well as the number
+of pixels left in the background region after pixel rejection and the number
+rejected.
+
+.NH 3
+Multi-aperture Photometry
+.PP
+APPHOT routines shall exist to compute the integral of object minus background
+within one or more circular apertures centered upon the object.
+The integration shall be
+performed using partial pixel techniques, to minimize the effects of
+sampling. If the aperture contains any indefinite pixels, or if the
+aperture extends beyond the boundary of the image, an indefinite result
+shall be returned. Both normal and weighted photometry routines shall
+be available.
+.PP
+It shall be possible to normalize the output magnitudes to a user specified
+integration time using values stored in the IRAF image header.
+.PP
+The output shall consist of magnitudes and errors for each of the specified
+apertures.
+.NH 3
+Polygonal Aperture Photometry
+.PP
+Determine the integral of the object within a specified
+polygon. Aperture integration shall be by fractional pixel summation
+of successive image lines.
+
+.NH
+Specifications
+.NH 2
+Apphot CL Callable Tasks
+.PP
+The CL callable part of the APPHOT package consists of the following
+routines:\f(CW
+
+.nf
+.na
+ mark -- create/verify coordinate lists interactively
+ polymark -- create/verify polygon lists interactively
+ daofind -- automatic image finder from DAOPHOT
+ lintran -- linearly transform a list of coordinates (LISTS package)
+
+ radprof -- compute the radial profile of an object.
+ fitpsf -- model the PSF
+
+ center -- compute accurate centers for a list of objects
+ fitsky -- compute accurate sky values for a list of objects
+ phot -- perform multi-aperture photometry on a set of objects
+ polyphot -- compute the flux inside a set of irregular polygons
+ wphot -- perform weighted multi-aperture photometry\fR
+.ad
+.fi
+
+.NH 2
+Standard Analysis Procedures
+.PP
+A standard reduction procedure would be something as follows.
+.IP 1.
+Estimate the image and data characteristics in the following manner.
+.RS
+.IP 1.
+Use the interactive setup option (i key) in the PHOT task to specify the
+fwhm of the psf,
+the centering apperture, the sky annuli, the photometry apertures as
+well as estimate the sky sigma.
+Examine the results (:show command) and optionally store the
+new parameters in the parameter files (w key).
+.IP 2.
+Use the EPAR task to edit the parameter files directly. For example the
+detector gain and readout noise must be known before running PHOT in
+order to get reliable error estimates.
+.RE
+.IP 2.
+Prepare a coodinate list in one of the following ways.
+.RS
+.IP 1.
+Running MARK or POLYMARK.
+.IP 2.
+Run DAOFIND or some other automatic image finder.
+.IP 3.
+Run another APPHOT task such as CENTER .
+.IP 4.
+Run any other IRAF or user program which generates the appropriate
+format.
+.IP 5.
+Transform an existing list using the LISTS package facilities
+.RE
+.IP 3.
+Run PHOT or WHOT in non-interactive mode to perform the multi-aperture
+photometry. The user should be familiar
+with the algorithms used to measure the object center, to fit the background,
+and compute the aperture integral, magnitude, and errors. The values of
+all visible and hidden PHOT parameters should be inspected before doing
+any serious processing. Note that CENTER and FITSKY can be run independently
+of PHOT and their output used as input to PHOT.
+.EQ
+delim $$
+.EN
+
+.NH 2
+The APPHOT Algorithms
+.PP
+The principal APPHOT algorithms are described below.
+
+.NH 3
+The RADPROF Algorithm
+.PP
+The function of the RADPROF task is to compute the radial profile of
+selected, isolated, high signal to noise objects in an IRAF image.
+.PP
+Given the IRAF image, an initial center, an aperture and a step size,
+RADPROF computes the radial profile of an object in the following manner.
+.IP 1.
+The APPHOT centering routines are used to compute an accurate center for the
+object. The new center is used to compute the radial coordinate for each
+pixel in the subraster.
+.IP 2.
+The APPHOT sky fitting routines are used to compute an accurate sky value
+for the object. The new sky value is used to compute the object intensity
+for each pixel in the subraster.
+.IP 3.
+The CURFIT package routines are used to produce a smooth intensity versus
+radius curve by fitting a cubic least squares spline function to the data
+using linear least squares techniques.
+.IP 4.
+The fitted curve is evaluated at equally spaced intervals to produce the
+final radial profile. The profile is normalised using the r = 0 value.
+.IP 5.
+The smoothed curve is integrated using the
+1D integration routines IMINTERP to evalute the fraction of the total
+integral at each interval.
+.IP 6.
+The three quantities $I sub r$ the raw intensity, $Inorm sub r$ the
+normalized intensity, and $Ifraction sub r$ the fraction of the total
+intensity inside radius at r, are plotted on the terminal and
+output as a function of r to a text file.
+.PP
+RADPROF is used principally to compute the stellar image and setup the
+parameters for doing photometry. Its default output is a radial profile
+plot with the phot parameters marked on it.
+
+.NH 3
+The FITPSF Algorithm
+.PP
+The function of the FITPSF task is to fit an analytic model to an object
+in order to derive information about the point spread function. Given
+an IRAF image, an initial center and an aperture, FITPSF computes the
+model parameters in the following manner.
+.IP 1.
+The fitting function is chosen.
+The present version of FITPSF offers two function choices a 2D radial Gaussian
+function and an elliptical Gaussian function.
+A third option, moment analysis, has been added to the FITPSF package.
+The image characteristics are evaluted by using the 0th, 1st and 2nd order
+moments of the image.
+.IP 2
+Initial guesses for the parameters are made from the subraster data.
+.IP 3
+The parameters and their errors are derived using standard non-linear least
+squares techniques and the NLFIT package.
+
+.NH 3
+The DAOFIND Algorithm
+.PP
+The function of the DAOFIND task is to automatically detect objects
+in an IRAF image above a certain intensity threshold.
+The user specifies an intensiyt threshold,
+the estimated full width half maximum of
+the point spread function,
+and limits on the sharpness and roundness of the objects to be detected.
+DAOFIND produces a list of x and y coordinates and a sharpness
+and roundness statistic for each detected object.
+.PP
+The DAOFIND algorithm works in the following way.
+.IP 1.
+The user specifies an intensity threshold above local sky and estimates
+the full width half maximum of the point spread function.
+.IP 2.
+DAOFIND computes a convolution kernel which is a linear
+function of the brightness values in an approximately circular array of
+pixels. The original data is convolved with the computed kernel.
+The equivalent mathematical
+operation is a convolution of the original data
+with truncated, lowered circular Gaussian function with the specified FWHM,
+computed in such a way as to be the mathematical
+equivalent of fitting a Gaussian stellar profile to the object data by least
+squares. The coefficients of the linear function sum to zero so that the
+overall bias level (local sky) cancels out exactly. Since the function is
+symmetric about a single pixel, a smooth gradient in the sky brightness
+also cancels exactly. Therefore the user does not have to specify an
+absolute brightness threshold but only a threshold above local sky.
+.IP 3
+The convolved data is searched for local maxima. Local maxima which are
+less than the specified threshold are rejected. A pixel is defined to be
+a local maximum when it is the brightest pixel within
+$n ~*~ sigma sub Gauss$.
+.IP 4.
+Using the original data, DAOFIND computes an object sharpness statistic which
+can be used to reject
+hot or cold pixels. The sharp parameter is defined below.
+Detected objects with a sharpness parameter outside the range specifed
+by sharplo and sharphi are rejected. Typical values for sharplo and
+sharphi are 0.2 and 1.0 respectively.
+.nf
+
+ $I sub delta$ = height of best fitting $delta$ function = pixel value
+
+ $I sub Gauss$ = height of best fitting Gaussian function = convolved value
+
+ sharplo <= sharp = ${I sub delta} over {I sub Gauss}$ <= sharphi
+
+.fi
+If the brightness enhancement detected in the convolved data is due to
+a single bright pixel, then the best fitting delta function will have an
+amplitude equal to the height of this pixel above the local background,
+while the amplitude of the best fitting Gaussian will be pulled down by
+the surrounding low valued pixels. Sharp will be a number significantly
+greater than one. A single cold pixel will produce
+brightness enhancements approximately 0.5 * FWHM away
+from the pixel in question in all directions. In this case the height
+of the delta
+function which best fits these spurious maxima is close to zero, while the
+height of the best fitting Gaussian is some small positive number.
+In this case sharp will be close to zero.
+.IP 5.
+The roundess statistic is computed from the original picture data by fitting
+1D Gaussians
+to the marginal sums in x and y. If the height of either 1D
+Gaussian is negative the object is rejected. If both heights are
+positive the roundness parameter is computed.
+.nf
+
+ $DELTA I ~=~ I sub {x ~ Gauss} ~-~ I sub {y ~ Gauss}$
+
+ $<I> ~=~ I sub {x ~ Gauss} ~+~ I sub {y ~ Gauss}$
+
+ $roundlo ~<=~ round ~=~ {DELTA I} over <I> ~<=~ roundhi$
+
+.fi
+Objects which are elongated in the
+x direction have roundness values less than zero and those elongated in
+the y direction have roundness greater than zero.
+Round discriminates only against objects which are elongated
+along either rows or columns. Objects elongated at a 45 degree angle will
+not be rejected.
+.IP 6.
+Finally the approximate x and y centroids of the detected objects,
+rough magnitudes relative to threshold are computed, and object is added
+to the output file.
+
+
+.NH 3
+The CENTER Task
+
+.NH 4
+Centering Package Routines
+.PP
+The following are the principal programmer callable routines routines in the
+centering package.
+.nf
+\f(CW
+
+ apcinit (ap, cfunction, cbox, fwhmpsf, noise)
+ ier = apfitcenter (ap, im, xinit, yinit)
+ ier = aprefitcenter (ap)
+ value = apstat[ir] (ap, param)
+ apstats (ap, param, str, maxch)
+ apset[sir] (ap, param, value)
+ apcfree (ap)
+
+\fR
+.fi
+.PP
+The following quantities can be examined or set by apstat/apset calls
+.nf
+\f(CW
+ data 1. fwhmpsf full width half maximum of psf in pixels
+parameters 2. threshold minimum intensity for centering
+ 3. noise noise model
+ 4. sigma standard deviation of background
+ 5. readnoise readout noise of CCD in electrons
+ 6. epadu electrons per adu
+
+centering 1. calgorithm centering algorithm
+parameters 2. positive emission / absorption features
+ 3. cbox centering radius in fwhmpsf
+ 4. cmaxiter maximum number of fitting iterations
+ 5. maxshift maximum permitted shift in fwhmpsf
+ 6. minsnratio minimum permitted signal to noise ratio
+ 7. clean clean subraster before centering
+ 8. rclean cleaning radius in fwhmpsf
+ 9. rclip clipping radius in fwhmpsf
+ 10.kclean k-sigma rejection for cleaning in sigma
+\fR
+.fi
+
+.PP
+The following computed quantities can be examined by apstat calls.
+.nf
+\f(CW
+ 1. xcenter computed x coordinate
+ 2. ycenter computed y coordinate
+ 3. xerr computed x coordinate error
+ 4. yerr computed y coordinate error
+\fR
+.fi
+.PP
+See the manual pages for CENTER and CENTERPARS for a detailed description
+of the centering parameters.
+
+.NH 4
+The Centering Algorithm
+.PP
+The function of the CENTER task is to compute accurate centers and errors
+for objects in an IRAF image given a list of initial positions and a
+centering aperture.
+.IP 1.
+If the centering algorithm is disabled, the computed center is set to the
+initial center and the uncertainty estimate is set to zero.
+.IP 2.
+If the cleaning algorithm is enabled, clean the subraster before centering.
+.IP 3.
+Estimate is made of the signal to noise of the object. If this quantity is
+less than a certain minimum value the computed center is kept
+but a warning message is issued.
+.IP 4.
+The center and errors are computed using one of several algorithms.
+.IP 5.
+If the computed center is greater than a user specified distance from the
+initial center then the computed center is returned with an error
+message.
+
+.NH 4
+Symmetry Clean Algorithm
+.PP
+The symmetry-clean algorithm attempts to remove defects in the centering
+subraster by assuming that the object has radial symmetry and comparing
+pixels on the opposite sides of the center of symmetry. The algorithm
+works in the following way.
+.IP 1.
+The center of symmetry is computed. Normally the center of symmetry is assumed
+to coincide with the position of the brightest pixel in the subarray.
+However if the maximum pixel is more than a user specified distance away
+from the intial center, the initial center is used as the center of symmetry.
+.IP 2.
+Pixels inside a specified cleaning radius are unaltered.
+.IP 3.
+Pairs of pixels diametrically opposed about the center
+in the cleaning region between the cleaning and clipping
+radii are tested for equality. If the difference between the pixels is
+greater than a specified k-sigma rejection limit, the larger value is replaced
+by the smaller.
+In this region sigma is computed from Poisson statistics.
+.IP 4.
+Pairs of pixels in the clippping
+region are compared in the same manner as those in the cleaning region
+except that sigma is the standard deviation of the sky pixels.
+.PP
+The effect of the symmetry-clean algorithm is to edit the raster,
+removing any contaminating objects in the vicinity of the primary object.
+This simplifies the fitting algorithm and increases its reliability,
+since it does not have to deal with multipeak marginal distributions.
+
+.NH 4
+Signal to Noise Estimate
+
+.PP
+The signal to noise of the object is estimated from the data values
+in the subraster in the following way.
+.nf
+
+ $SNR ~=~ N sub object over {sqrt {n sub pix ~*~sigma sub sky sup 2}}$
+
+ or
+
+ $SNR ~=~ N sub object over {sqrt {N sub object ~+~ n sub pix~*~sigma sub sky sup 2}}$
+
+.fi
+where $N sub *$ is the number of counts in the object above threshold,
+$sigma sub sky$
+is the standard deviation of the pixels in the sky region and
+$n sub pix$ is the number of pixels in the object aperture.
+The first approximation corresponds to constant sky noise only,
+the second includes Poisson noise in the object.
+
+.NH 4
+Centroid
+.PP
+The centroid centering algorithm is similar to that used in MPC and can
+be briefly described as follows. For more detailed description
+see (Stellar Magnitudes From Digital Pictures, 1980, Adams et al).
+.IP 1.
+The marginal distributions in x and y are accumulated.
+.IP 2.
+The intensity weighted centroid positions for the marginals is computed
+using only data pixels which are above the threshold intensity. If the
+threshold parameter is 0 the mean intensity of the marginal is used
+in place of the threshold
+.nf
+
+ $I sub i ~=~ I sub i ~-~ threshold ~~~~~ I sub i ~>~ 0.0$
+
+ $x sub c ~=~ {sum I sub i ~ x sub i} over {sum I sub i}$
+
+.fi
+.IP 3.
+The errors are estimated in the following way
+.nf
+
+ $sigma sup 2 ~=~ {sum I sub i ~ x sub i sup 2} over {sum I sub i} ~-~ x sub c sup 2$
+
+ $err sub xc ~=~ sqrt {{sigma sup 2} ~/~ sum I sub i}$
+
+.fi
+
+.NH 4
+Gaussian Fit to the Marginals
+.PP
+The fit is performed in the following way.
+.IP 1.
+The marginal distributions in x and y are accumulated.
+.IP 2.
+Initial guesses for the parameters of the 1D Gaussians $I sub Gauss$,
+$x sub c$ and $I sub sky$ are derived from the marginal distributions
+themselves. The width $sigma$ is held constant.
+.IP 3.
+The best fit parameters and their errors are derived using non-linear
+least-squares techniques and the NLFIT package.
+
+.NH 4
+Optimal Filtering of Marginals
+.PP
+The fit is performed is the following way.
+.IP 1.
+The marginal distributions in x and y are accumulated.
+.IP 2.
+The centroid of the observed distribution is computed by solving the
+following equation.
+.nf
+
+ $PSI (x sub c ) ~=~ sum omega sub i (x sub c ) ~ PHI sub i ~=~ 0$
+
+ $omega sub i ~=~ {{partial phi sub i} ~/~ {partial x sub c}} over {phi sub i~+~b}$
+
+.fi
+The assumptions are that the observed distribution $PHI sub i$ is correctly
+modeled by the profile function $phi sub i$. The usual choise of profile
+model for centering is a Gaussian. Howver in the interests of speed a triangle
+function has been substituted. This causes at most a 7% increase in the
+random centering error.
+.IP 3.
+The startup procedure is based on the following fact.
+.nf
+
+ $PSI (x sub n )~>~0~~for~~ x sub n ~<~ x sub c$
+
+ $PSI (x sub n ) ~<~0~~for~~ x sub n ~>~ x sub c$
+
+.fi
+The iteration is initialized by assuming that $x sub 1$ = $x sub c$ and
+computing $PSI (x sub 1 )$. The initial x
+value is incremented by $+- sigma sub Gauss$ depending on the sign of $PSI$. The
+search is repeated until $PSI (x sub {n-1})$ and $PSI (x sub n)$ have
+opposite signs. At this point the true center is bracketed by the
+estimated positions $(x sub n, ~ x sub {n-1})$ and we have a table of at
+least 2 values of $PSI (x sub n )$.
+.IP 4.
+The computation proceeds by interpolating in the table of values for the
+estimated position $x sub {n+1}$ where $PSI$ = 0. If the table contains only
+two values as may be the case for the inititial interpolation, linear
+interpolation is used. In all other cases a quadratic fit to the three
+most recent $PSI$ values is used. The computation is complete when
+two successive estimates differ by less than some tolerance typically
+0.001 pixel.
+.IP 5.
+The errors are estimated as follows.
+.nf
+
+ $sigma sup 2 ~=~ ( {int {( partial phi ~/~ partial x sub c )} sup 2 over {
+ phi + b}} ) sup -1$
+
+ $err sub xc ~=~ sqrt {sigma sup 2}$
+
+.fi
+
+.NH 4
+Other Centering Methods
+.PP
+The code is constructed in such a way that new algorithms may be
+easily added at a future date, such as the more sophisticated techniques
+required for accurate astrometry.
+.EQ
+delim $$
+.EN
+.NH 3
+The FITSKY Task
+
+.NH 4
+Sky Fitting Routines
+
+.PP
+The following are the main entry points in the sky fitting package.
+.nf
+\f(CW
+ apsinit (ap, function, annulus, dannulus, fwhmpsf, noise)
+ ier = apfitsky (ap, im, xpos, ypos, sd, gd)
+ ier = aprefitsky (ap, sd, gd)
+ value = apstat[ir] (ap, param)
+ apstats (ap, param, str, maxch)
+ apset[irs] (ap, param, value)
+ apsfree (ap)
+\fR
+.fi
+.PP
+The following quantities can be examined or set with apset/apstat calls.
+.nf
+\f(CW
+data 1. fwhmpsf full width half maximum of the psf
+parameters 2. sigma standard deviation of sky pixels
+
+sky fitting 1. annulus inner radius of sky annulus in fwhmpsf
+parameters 2. dannulus outer radius of sky annulus in fwhmpsf
+ 3. sfunction sky fitting algorithm
+ 4. smaxiter maximum number of fitting iterations
+ 5. kreject k-sigma rejection limit sigma
+ 6. nreject maximum number of rejection cycles
+ 7. rgrow region growing radius in fwhmpsf
+
+ 8. khist half-wdth of histogram in sigma
+ 9. binsize binsize of histogram in sigma
+ 10.smooth Lucy smooth the histogram
+
+ 11.skyfile name of text file containing sky values
+ 12.skyvaluser supplied constant value for sky
+\fR
+.fi
+.PP
+The following computed quantities can only be examined with apstat calls.
+.nf
+\f(CW
+ 1. skymode computed sky value
+ 2. skysig computed sky sigma
+ 3. skyskew computed sky skew
+ 4. nsky number of sky pixels
+ 5. nsky_reject number of rejected sky pixels
+\fR
+.fi
+
+.NH 4
+The Sky Fitting Algorithms
+.PP
+A good background fit is essential to aperture photometry. Fitting
+the background is trivial in a sparse field, but difficult in a crowded
+field. In general the background region will contain contaminating objects
+which must be detected and excluded if a good fit is to be obtained.
+.PP
+The main algorithm used in APPHOT is the following.
+.IP 1.
+If the skyfitting switch is disabled either read the sky values from a text
+file or accept a user supplied constant for the sky.
+.IP 2.
+Perform the initial sky fit using one of the specified algorithms. The
+sky fitting algorithms fall into three general categories, those that use
+the actual sky pixel array itself, those that operate on a histogram of
+sky values and those that rely on user interaction.
+.IP 3.
+If the pixel rejection flags are set perform pixels rejection with optional
+region growing.
+
+.NH 4
+Sky Pixel Array Techniques
+
+.NH 5
+Median
+.IP 1.
+Sort the array of sky pixels. This is necessary to avoid quantization effects.
+.IP 2.
+Compute the median, and the standard deviation and skew with respect to the
+mean.
+.IP 3.
+If the k-sigma rejection limit is greater than zero and the maximum number
+of rejection cycles is greater than one, perform pixel rejection.
+Pixels greater than k-sigma from the median are rejected. Region growing
+is optional.
+.IP 4.
+Stop the rejection cycle on any given iteration if the maximum number of
+rejection cycles ix exceeded, no more sky pixels are left or no more
+pixels are rejected.
+
+.NH 5
+Mode
+.IP 1.
+Sort the array of sky pixels. This is necessary to avoid quantization effects.
+.IP 2.
+Compute the mode, and the standard deviation and skew
+with respect to the mean.
+.nf
+
+ $I sub mode ~=~ 3.0 ~*~ I sub median ~-~ 2.0 ~*~ I sub mean$
+
+.fi
+.IP 3.
+If the k-sigma rejection limit is greater than zero and the maximum number
+of rejection cycles is greater than one, perform pixel rejection.
+Pixels greater than k-sigma from the mode are rejected. Region growing
+is optional.
+.IP 4.
+Stop the rejection cycle on any given iteration if the maximum number of
+rejection cycles ix exceeded, no more sky pixels are left or no more
+pixels are rejected.
+
+
+.NH 4
+Histogram Techniques
+.PP
+The following three techniques all operate on the histogram of the sky pixels.
+The routines all construct the histogram in the following identical manner.
+.IP 1.
+The mean of the sky distribution is computed.
+.IP 2.
+If the user specified standard deviation of the sky pixels is INDEF the
+algorithm computes the standard deviation of the sky pixels with respect
+to the mean.
+.IP 3.
+All pixels within plus or minus sigma standard
+deviations are accumulated into a histogram. The user specifies the bin size.
+.IP 4.
+The histogram may optionally be Lucy smoothed before any operation is performed
+on it.
+
+.NH 5
+Centroid
+.PP
+The mode, sigma and skew of the sky pixels are computed in the following
+manner.
+.IP 1.
+The histogram is compiled as above.
+.IP 2.
+The mode, standard deviation and skew of the sky pixels are computed in the
+following manner.
+
+.nf
+ $I sub 0 ~=~ sum I sub i$
+ $I sub 1 ~=~ sum I sub i ~ x sub i$
+ $I sub 2 ~=~ sum I sub i ~ x sub i sup 2$
+ $I sub 3 ~=~ sum I sub i ~ x sub i sup 3$
+
+ $I sub mode ~=~ {I sub 1} ~/~ {I sub 0}$
+ $sigma ~=~ {( I sub 2 ~/~ I sub 0 ~-~ I sub mode sup 2 )} sup {1/2}$
+ $skew ~=~ ( {I sub 3 ~/~ I sub 0 ~-~ I sub mode ~*~ sigma sup 2 ~-~ I sub mode sup 3} ) sup {1/3}$
+
+.fi
+.IP 3
+If pixel rejection is enabled sky pixels within a user supplied limit of
+the mode are rejected with optional region growing.
+
+.NH 5
+Gaussian Fit
+.PP
+The mode, standard deviation and skew of the sky pixels are derived from a
+model fit in the following way.
+.IP 1.
+The histogram of the sky pixels is compiled as above.
+.IP 2.
+Initial guesses to the model parameters, $N sub max$, $I sub mode$,
+$sigma$, and $skew$ are made from the histogram itself.
+.IP 3.
+Final parameters and their errors are derived using non-linear least squares
+techniques and the NLFIT package.
+.IP 4.
+If pixel rejection is enabled sky pixels within a user supplied limit of
+the computed mode are rejected with optional region growing.
+
+.NH 5
+Optimal Filtering
+.PP
+The method is as follows.
+.IP 1.
+The histogram is compiled as above.
+.IP 2.
+Using the mean of the sky pixels as the intital value of the sky mode,
+a new mode is computed using the optimal filtering technique
+described for centering.
+.IP 4
+If pixel rejection is enabled sky pixels within a user supplied limit of
+the computed mode are rejected with optional region growing.
+
+.NH 5
+Cross Correlation
+.PP
+The method is as follows.
+.IP 1.
+The histogram is compiled as above.
+.IP 2.
+The noise function is estimated using the standard deviation of the sky
+pixels and the cross-correlation function is computed.
+.IP 3.
+The mode is computed using quadratic interpolation around the peak of the
+distribution.
+.IP 4
+If pixel rejection is enabled sky pixels within a user supplied limit of
+the mode are rejected with optional region growing.
+
+.NH 4
+Interactive Techniques
+
+.NH 5
+Histogram Plot
+.PP
+The histogram is compiled as described above and the user marks the peak
+on the histogram plot with the graphics cursor. The sigma and skew of the
+sky distribution with respect to the mean is also computed.
+
+.NH 5
+Radial Distribution
+.PP
+A radial profile plot of the sky region is plotted and the user marks the
+sky value on the plot with the graphics cursor. The sigma and skew of the sky
+distribution with respect to the mean is computed.
+
+.NH 4
+Pixel Rejection and Region Growing
+.PP
+All the sky fitting algorithms permit pixel rejection and
+optional region growing.
+Pixel rejection and region growing are
+performed by locating all pixels more than k * sigma from the mode,
+and blindly rejecting all pixels within a certain radius of each deviant
+pixel. This simple algorithm works well because the sample is large,
+and therefore there is little penalty for discarding pixels that might
+not be deviant. Region growing also tends to accelerate convergence
+significantly.
+.PP
+Very faint contaminating objects are difficult to detect and reject.
+If there are enough such objects, they should not be rejected, because
+there are probably a few in the object aperture as well. A higher sky
+sigma will be calculated and the computed uncertainty in the magnitude
+will increase. The best solution to this problem may be to increase
+the size of the annulus to minimize the bias.
+
+.NH 4
+The Principal PHOT Routines
+.PP
+The main entries in the photometry routine are the following.
+.nf
+\f(CW
+ apinit (ap, cfunction, cbox, sfunction, annulus, dannulus,
+ aperts, napert, fwhmpsf, noise)
+ ier = apfitcenter (ap, im, xinit, yinit)
+ ier = aprefitcenter (ap)
+ ier = apfitsky (ap, im, xcenter, ycenter, sd, gd)
+ ier = aprefitsky (ap, sd, gd)
+ ier = apmag (ap, im, xcenter, ycenter, skyval, skysig, nsky)
+ ier = apwmag (ap, im, xcenter, ycenter, positive, skyval, skysig,
+ nsky)
+ ier = apremag (ap, positive, skyval, skysig, nsky)
+ ier = apwremag (ap, positive, skyval, skysig, nsky)
+ value = apstat[ir] (ap, param)
+ apstats (ap, param, str, maxch)
+ apset[sir] (ap, param, value)
+ apfree (ap)
+
+\fR
+.fi
+.PP
+The following parameters can be examined or altered by apset/apstat calls.
+.nf
+\f(CW
+ 1. weighting weighting scheme for wphot
+ 2. aperts list of apertues
+ 3. naperts number of apertures
+ 4. zmag zero point of magnitude scale
+ 5. itime effective integration time
+\fR
+.fi
+.PP
+The following quantities can be examined with apstat calls.
+.nf
+\f(CW
+
+ 1. sums array of aperture sums
+ 2. areas array of areas
+ 3. mags array of magnitudes
+ 4. magerrs array of magnitude errors
+
+\fR
+.fi
+
+.NH 4
+The PHOT Aperture Integration Algorithm
+.PP
+The integral of the flux within a circular aperture is computed by
+fractional pixel techniques. Pixels are assumed to be square apertures
+arranged in a rectangular grid. The fraction of a pixel which lies within
+the circular APPHOT aperture is computed by an approximation, and all
+such contributions are summed to produce the total integral.
+.PP
+The inclusion of a partial pixel inside the aperture is done as follows.
+.IP 1.
+If the distance of the current pixel from the center of the star, r, is
+exactly equal to the radius of the aperture R then one-half the counts in
+the pixel are included.
+.IP 2.
+If r < R - 0.5 the entire pixel is included while if r > R + 0.5 the pixel
+is wholly excluded.
+.IP 3.
+In between the fraction of the counts varies linearly. A circular aperture
+is approximated by an irregular polygon.
+.PP
+The simplicity of aperture photometry limits the amount of information
+available for error analysis. The following three sources of error are
+considered.
+.IP 1.
+The error due to sky noise in the aperture.
+.nf
+
+ $error sub 1 ~=~ sigma sub sky ~*~ {A sub apert} sup {1/2}$
+
+.fi
+.IP 2.
+The error in the aperture sum.
+.nf
+
+ $error sub 2 ~=~ ( {A sub "sum" ~/~ phpadu} ) sup {1/2}$
+
+.fi
+.IP 3.
+The mean error of the sky.
+.nf
+
+ $error sub 3 ~=~ sigma sub sky ~*~ A sub apert ~/~ nsky sup {1/2}$
+
+
+.fi
+where $sigma sub sky$ is either computed by the background fitting
+algorithm or set by the user,
+and $A sub apert$ is the fractional pixel area of the
+aperture.
+
+.NH 4
+The WPHOT Algorithm
+.PP
+The WPHOT algorithm computes a weighted aperture sum in an attempt to
+minimize noise in the sky. The algorithm is the following where w is
+the weight for each pixel, p is the noise free profile value and
+$sigma$ is the noise per pixel from all sources. (See the paper
+by Stover and Allen 1987 for details)
+.nf
+
+ $A sub sum ~=~ sum {w sub i ~*~ (I sub i ~-~ sky)}$
+
+ $w sub i ~=~ C ~*~ p sub i ~/~ sigma sup 2 sub i$
+
+ $C ~=~ sum {p sub j} / sum {p sub j ~*~ w sub j}$
+.fi
+
+.NH 4
+The POLYPHOT ROUTINES
+.PP
+The principal polyphot routines are the following.
+
+.nf
+.na
+\f(CW
+ apyinit (ap, sfunction, annulus, dannulus, noise)
+ ier = apfitcenter (ap, im, wx, wy)
+ ier = aprefitcenter (ap)
+ ier = apfitsky (ap, im, xcenter, ycenter, sd, gd)
+ ier = aprefitsky (ap, sd, gd)
+ ier = polyfit (ap, im, xver, yver, nver)
+ value = apstat[ir] (ap, param)
+ apstats (ap, param, str, maxch)
+ apset[sir] (ap, param, value)
+ apfree (ap)
+
+\fR
+.ad
+.fi
+
+.PP
+.NH 4
+The POLYPHOT Algorithm
+.PP
+The function of the POLYPHOT task is to compute the flux inside an
+irregular polygon given a list of the coordinates of the vertices of a polygon.
+The polygon must be entirely inside the image and the vertices of the polygon
+must be specified in clockwise or counterclockwise order.
+The actual algorithm used is as follows.
+.IP 1.
+The range of image lines which intersect the polygon are computed.
+.IP 2.
+For each image line in the specified range the intersection points with the
+polygon are computed.
+.IP 3.
+The flux between pairs of limits is summed using a fractional pixel
+approximation for the endpoints.
+.IP 4.
+The sky is fitted using any of the methods previously discussed and a
+user specified annular region.
+.IP 5.
+The errors are computed as specified in the PHOT specifications.
+.PP
+.EQ
+delim $$
+.EN
+
+.NH
+Example
+.PP
+A brief example may help illustrate the use of the package. Suppose
+we want to process a few hundred stars on image "blue".
+.PP
+The first step is to prepare a list of objects to be measured. The simplest
+way to do this is to interactively mark the objects with the image
+cursor using the display (graphics) device and the RIMCURSOR (RGCURSOR)
+task.
+.nf
+\f(CW
+
+ ... load image on the display ...
+
+ ap> rimcursor > starlist
+
+ ... move cursor and mark stars ...
+
+
+ ... load contour plot on graphics terminal ...
+
+ ap> rgcursor > starlist
+
+ ... move cursor and mark stars ...
+\fR
+.fi
+
+Alternatively one can run DAOFIND to compute a list of candidate objects
+in the frame.
+The name of the coordinate file is stored in the PHOT parameter set.
+
+.nf
+\f(CW
+ ap> phot.coords=starlist
+\fR
+.fi
+
+.PP
+The next step is to set up the PHOT parameters interactively.
+First we load the image (contour plot) blue on the display (graphics
+terminal). Next we call up PHOT in interactive mode.
+
+.nf
+\f(CW
+ ap> phot blue
+ ... cursor appears ...
+
+\fR
+.fi
+
+.PP
+PHOT takes input by reading the image (graphics)
+display (terminal) cursor. In order to display the available commands
+we tap the ? key and the following text appears on the screen.
+
+.nf
+\f(CW
+ Interactive Phot Commands
+
+? Print options
+: Colon command see below
+i Setup PHOT parameters interactively
+w Write PHOT parameters to the parameter files
+l Process the remainder of the coordinate list
+r Rewind the coordinate list
+c Fit center around the current cursor position
+t Fit sky around the current cursor position
+s Fit sky around the current center position
+p Compute magnitudes around the cursor position
+f Fit center, sky and compute magnitudes
+sp Fit center, sky, compute magnitudes, and save
+q Exit program
+
+Phot parameters are listed or set with the following commands.
+
+:m [n] Move cursor to the [nth] object in the coordinate list
+:n [n] Measure the [nth] object in the coordinate list
+
+:show [center/sky/phot/all] List the aphot parameters
+:fwhmpsf [value] Full width half maximum of the PSF
+:noise [string] Noise model
+:threshold [value] Threshold value for centering
+:sigma [value] Standard deviation of the background
+:ccdread CCD readout noise keyword
+:readnoise Readout noise in electrons
+:gain Gain keyword
+:epadu Electrons per adu
+
+:calgorithm [string] Centering function
+:positive [y/n] Emission or absorption feature
+:cbox [value] Width of the centering box in fwhmpsf
+:cmaxiter [value] Maximum number of centering iterations
+:maxshift [value] Maximum shift in fwhmpf
+:minsnratio [value] Minimum signal to noise ratio of pixels
+:clean [y/n] Clean subraster before centering
+:rclip [value] Clipping radius in fwhmpsf
+:rclean [value] Cleaning radius in fwhmpsf
+:kclean [value] Sigma for clean algorithm
+:mkcenter [y/n] Mark the centers on the display
+
+:salgorithm [string] Sky fitting algorithm
+:annulus [value] Inner radius of sky annulus in fwhmpsf
+:dannulus [value] Width of sky annulus in fwhmpsf
+:skyvalue [value] User supplied sky
+:smaxiter [value] Maximum number of rejection cycles
+:skreject [value] +/- Pixel rejection limits in sky sigma
+:snreject [value] Maximum number of rejection interations
+:khist [value] +/- Sky histogram size in sky sigma
+:binsize [value] Resolution of sky histogram in sky sigma
+:smooth [y/n] Lucy smooth the sky histogram
+:rgrow [value] Region growing radius in fwhmpsf
+:marksky [y/n] Mark the sky annuli on the display
+
+:weighting Weighting for wphot
+:aperts [string] Aperture radii in fwhmpsf
+:zmag [value] Zero point of magnitude scale
+:exposure [string] Exposure time keyword
+:itime [value] Integration time
+\fR
+.fi
+
+.PP
+We select the interactive setup option, move the image
+cursor to a high signal-to-noise, isolated star and tap the i key.
+PHOT responds by plotting the radial profile of the star on the
+screen and requesting the user to mark the fwhm of
+the psf, the centering aperture, the inner and outer sky annuli,
+the sky background and sigma and the set of circular apertures.
+The parameters so set can be examined and/or reset with the : commands as shown
+above. Sample measurements can be made of several stars by moving the
+cursor and typing the f command. Finally when we are happy with the
+parameter set we type w to store the parameters and q to exit the program.
+.PP
+Now we are ready to do photometry. We enter the PHOT program in batch mode.
+
+.nf
+\f(CW
+ ap> phot blue inter- &
+\fR
+.fi
+
+The batch job is now running, appending output lines to the file "blue.mag.#".
+We can proceed to set up the job for the red image, in much the same way
+that we set up the job for the blue image. When both jobs finish, we
+can use the list processing tools to filter out the good objects and
+calculate colors.
+
+.NH
+The APPHOT Tasks
+.PP
+Manual pages for the APPHOT tasks are available in the IRAF on line help
+database.
diff --git a/noao/digiphot/apphot/doc/specs/apphot.spc.toc b/noao/digiphot/apphot/doc/specs/apphot.spc.toc
new file mode 100644
index 00000000..757f9a79
--- /dev/null
+++ b/noao/digiphot/apphot/doc/specs/apphot.spc.toc
@@ -0,0 +1,111 @@
+.LP
+.sp
+1.\h'|0.4i'\fBIntroduction\fP\l'|5.6i.'\0\01
+.sp
+2.\h'|0.4i'\fBAPPHOT Package Requirements\fP\l'|5.6i.'\0\01
+.br
+\h'|0.4i'2.1.\h'|0.9i'APPHOT Package Input\l'|5.6i.'\0\01
+.br
+\h'|0.9i'2.1.1.\h'|1.5i'The IRAF Image\l'|5.6i.'\0\01
+.br
+\h'|0.9i'2.1.2.\h'|1.5i'The Coordinate Lists\l'|5.6i.'\0\02
+.br
+\h'|0.9i'2.1.3.\h'|1.5i'Algorithm Parameters\l'|5.6i.'\0\02
+.br
+\h'|0.9i'2.1.4.\h'|1.5i'Terminal Graphics and the Image Display\l'|5.6i.'\0\02
+.br
+\h'|0.4i'2.2.\h'|0.9i'APPHOT Package Functions\l'|5.6i.'\0\03
+.br
+\h'|0.9i'2.2.1.\h'|1.5i'Creating Coordinate Lists\l'|5.6i.'\0\03
+.br
+\h'|0.9i'2.2.2.\h'|1.5i'Coordinate List Operations\l'|5.6i.'\0\03
+.br
+\h'|0.9i'2.2.3.\h'|1.5i'Determining the Image Characteristics\l'|5.6i.'\0\03
+.br
+\h'|0.9i'2.2.4.\h'|1.5i'Centering\l'|5.6i.'\0\03
+.br
+\h'|0.9i'2.2.5.\h'|1.5i'Fitting the Sky\l'|5.6i.'\0\04
+.br
+\h'|0.9i'2.2.6.\h'|1.5i'Multi-aperture Photometry\l'|5.6i.'\0\04
+.br
+\h'|0.9i'2.2.7.\h'|1.5i'Polygonal Aperture Photometry\l'|5.6i.'\0\04
+.sp
+3.\h'|0.4i'\fBAPPHOT Package Specifications\fP\l'|5.6i.'\0\04
+.br
+\h'|0.4i'3.1.\h'|0.9i'Apphot CL Callable Tasks\l'|5.6i.'\0\04
+.br
+\h'|0.4i'3.2.\h'|0.9i'Standard Analysis Procedures\l'|5.6i.'\0\05
+.br
+\h'|0.4i'3.3.\h'|0.9i'The APPHOT Algorithms\l'|5.6i.'\0\05
+.br
+\h'|0.9i'3.3.1.\h'|1.5i'The RADPROF Algorithm\l'|5.6i.'\0\05
+.br
+\h'|0.9i'3.3.2.\h'|1.5i'The FITPSF Algorithm\l'|5.6i.'\0\06
+.br
+\h'|0.9i'3.3.3.\h'|1.5i'The DAOFIND Algorithm\l'|5.6i.'\0\06
+.br
+\h'|0.9i'3.3.4.\h'|1.5i'The CENTER Algorithm\l'|5.6i.'\0\08
+.br
+\h'|1.5i'3.3.4.1.\h'|2.2i'Centering Package Routines\l'|5.6i.'\0\08
+.br
+\h'|1.5i'3.3.4.2.\h'|2.2i'The General Centering Procedure\l'|5.6i.'\0\09
+.br
+\h'|1.5i'3.3.4.3.\h'|2.2i'Symmetry Clean Algorithm\l'|5.6i.'\010
+.br
+\h'|1.5i'3.3.4.4.\h'|2.2i'Signal to Noise Estimate\l'|5.6i.'\010
+.br
+\h'|1.5i'3.3.4.5.\h'|2.2i'Centroid\l'|5.6i.'\010
+.br
+\h'|1.5i'3.3.4.6.\h'|2.2i'Gaussian Fit to the Marginals\l'|5.6i.'\011
+.br
+\h'|1.5i'3.3.4.7.\h'|2.2i'Radial Gaussian Fit to the Subraster\l'|5.6i.'\011
+.br
+\h'|1.5i'3.3.4.8.\h'|2.2i'Optimal Filtering of Marginals\l'|5.6i.'\011
+.br
+\h'|1.5i'3.3.4.9.\h'|2.2i'2D Optimal Filtering\l'|5.6i.'\012
+.br
+\h'|1.5i'3.3.4.10.\h'|2.2i'Other Centering Methods\l'|5.6i.'\012
+.br
+\h'|0.9i'3.3.5.\h'|1.5i'The FITSKY Task\l'|5.6i.'\013
+.br
+\h'|1.5i'3.3.5.1.\h'|2.2i'Sky Fitting Package Routines\l'|5.6i.'\013
+.br
+\h'|1.5i'3.3.5.2.\h'|2.2i'General Sky Fitting Procedures\l'|5.6i.'\014
+.br
+\h'|1.5i'3.3.5.3.\h'|2.2i'Sky Pixel Array Techniques\l'|5.6i.'\014
+.br
+\h'|2.2i'3.3.5.3.1.\h'|2.9i'Mean\l'|5.6i.'\014
+.br
+\h'|2.2i'3.3.5.3.2.\h'|2.9i'Median\l'|5.6i.'\014
+.br
+\h'|2.2i'3.3.5.3.3.\h'|2.9i'Mode\l'|5.6i.'\015
+.br
+\h'|1.5i'3.3.5.4.\h'|2.2i'Histogram Techniques\l'|5.6i.'\015
+.br
+\h'|2.2i'3.3.5.4.1.\h'|2.9i'Centroid\l'|5.6i.'\015
+.br
+\h'|2.2i'3.3.5.4.2.\h'|2.9i'Gaussian Fit\l'|5.6i.'\016
+.br
+\h'|2.2i'3.3.5.4.3.\h'|2.9i'Optimal Filtering\l'|5.6i.'\016
+.br
+\h'|2.2i'3.3.5.4.4.\h'|2.9i'Cross Correlation\l'|5.6i.'\016
+.br
+\h'|1.5i'3.3.5.5.\h'|2.2i'Interactive Techniques\l'|5.6i.'\016
+.br
+\h'|2.2i'3.3.5.5.1.\h'|2.9i'Histogram Plot\l'|5.6i.'\016
+.br
+\h'|2.2i'3.3.5.5.2.\h'|2.9i'Radial Distribution\l'|5.6i.'\016
+.br
+\h'|1.5i'3.3.5.6.\h'|2.2i'Pixel Rejection and Region Growing\l'|5.6i.'\017
+.br
+\h'|0.9i'3.3.6.\h'|1.5i'The APPHOT Task\l'|5.6i.'\017
+.br
+\h'|1.5i'3.3.6.1.\h'|2.2i'The APPHOT Package Routines\l'|5.6i.'\017
+.br
+\h'|1.5i'3.3.6.2.\h'|2.2i'The APPHOT Aperture Integration Algorithm\l'|5.6i.'\018
+.br
+\h'|0.9i'3.3.7.\h'|1.5i'The POLYPHOT Algorithm \l'|5.6i.'\018
+.sp
+4.\h'|0.4i'\fBExample\fP\l'|5.6i.'\019
+.sp
+5.\h'|0.4i'\fBThe APHOT Tasks\fP\l'|5.6i.'\021
diff --git a/noao/digiphot/apphot/doc/ucache.hlp b/noao/digiphot/apphot/doc/ucache.hlp
new file mode 100644
index 00000000..34a091dd
--- /dev/null
+++ b/noao/digiphot/apphot/doc/ucache.hlp
@@ -0,0 +1,15 @@
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If cacheing
+is enabled and the task is run interactively the first measurement will appear
+to take a long time as the entire image must be read in before the measurement
+is actually made. All subsequent measurements will be very fast because the task
+is accessing memory not disk. The point of cacheing is to speed up random
+image access by making the internal image i/o buffers the same size as the
+image itself. However if the input object lists are sorted in row order and
+sparse cacheing may actually worsen not improve the execution time. Also at
+present there is no point in enabling cacheing for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of cacheing in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halfs of the image are alternated.
diff --git a/noao/digiphot/apphot/doc/userdocs/apuser.ms b/noao/digiphot/apphot/doc/userdocs/apuser.ms
new file mode 100644
index 00000000..24492bcc
--- /dev/null
+++ b/noao/digiphot/apphot/doc/userdocs/apuser.ms
@@ -0,0 +1,1881 @@
+.RP
+
+.TL
+A User's Guide to the IRAF Apphot Package
+
+.AU
+Lindsey Elspeth Davis
+.AI
+
+.K2 "" "" "*"
+Revised May 1989
+
+.AB
+.PP
+The APPHOT package is a set of tasks for performing aperture photometry
+on uncrowded or moderately crowded stellar fields in either interactive or batch
+mode. The photometric technique employed is fractional pixel
+integration. Point spread function fitting techniques are not used and no
+knowledge of the point spread function is required for the computation of
+magnitudes. Separate tasks are provided for creating and modifying object
+lists, computing accurate centers and sky values for a list of objects,
+and performing photometry inside concentric
+circular or polygonal apertures.
+.PP
+This document describes the data preparation required to run APPHOT, how
+to set up the display and graphics devices, how to set the algorithm
+parameters, how to run the package tasks in interactive or batch mode
+and how to selectively examine the results. Detailed descriptions of the
+algorithms can be found in the document \fISpecifications for the
+APPHOT Package\fR by the author.
+.PP
+This document applies to APPHOT under IRAF version 2.8. APPHOT
+can be run under IRAF versions 2.5, 2.6 and 2.7 with only minor changes in
+the task setup. These differences are documented
+where appropriate in the text.
+.AE
+
+.NH
+Introduction
+.PP
+The APPHOT package is a set of tasks for performing
+aperture photometry on uncrowded or moderately crowded fields.
+The photometric technique employed is fractional pixel integration. Point
+spread function techniques are not used and no knowledge of the point spread
+function is required for the computation of magnitudes.
+.PP
+The APPHOT package performs multi-aperture photometry on digitized starfields
+maintained as IRAF image files. Input to the package consists of an
+image file(s), an optional list(s) of object coordinates,
+numerous parameters controlling
+the analysis algorithms and, optionally, the graphics terminal and/or
+display. APPHOT output consists of successive records, where each record
+records the results of the analysis for a single object. Some tasks
+also produce graphics output in the form of plot metacode files.
+.PP
+Given starting coordinates and an IRAF image, the principal APPHOT
+task \fBphot\fR computes accurate centers, sky values and magnitudes
+for a list of objects. Separate
+IRAF callable tasks in APPHOT exist to create and modify object
+lists, to determine image characteristics such as the full width half maximum
+of the point spread function or standard deviation of the sky pixels,
+to compute accurate centers for a list of objects, to compute accurate local sky
+values for a list of objects, and to compute magnitudes inside a polygonal
+aperture.
+.PP
+The image data requirements of the APPHOT package are described in section 2.
+Section 3 describes various ways to tailor the IRAF environment to run
+the APPHOT package. Section 4 describes how to load the APPHOT tasks and how
+use the on-help facility. Section 5 describes how to examine and edit the
+APPHOT task and algorithm parameters. Several methods of creating and
+modifying APPHOT coordinate lists files are described in section 6.
+Sections 7 and 8 describe how to run the APPHOT tasks interactively without
+and with a coordinate list respectively. Batch mode reductions in APPHOT are
+described in section 9. Section 10 describes the format of the APPHOT output
+catalogue and plot files. Section 12 lists various APPHOT recipes for reducing
+common types of astronomical data with APPHOT.
+
+.NH
+Data Preparation and Requirements
+.PP
+APPHOT assumes that the images to be analyzed exist on disk in IRAF readable
+format. Facilities for reading and writing images exist elsewhere in IRAF
+in the DATAIO and MTLOCAL packages. None of the current APPHOT
+tasks alter the disk input images in any way.
+.PP
+APPHOT assumes that the pixel data is linear. The input images should be
+corrected for those instrumental defects which affect the intensity
+of a pixel prior to entering the APPHOT package. These defects include pixel
+to pixel variations in the bias values,
+pixel to pixel gain variations, cosmic rays, cosmetic defects, geometric
+distortion and detector non-linearities. Users should be aware of the IRAF
+CCDRED package for reducing CCD data and the DTOI package for converting
+photographic density data to intensity data.
+.PP
+Extreme valued pixels should be removed from the images prior to entering
+the APPHOT package. These include pixel values at or near the data limits of the
+host machine as well as any host machine values such as INDEF,
+produced by divide by zero, and floating point underflows and overflows.
+Floating point operations involving such numbers may crash
+with arithmetic exception errors. For efficiency and portability reasons
+the APPHOT package and most IRAF routines do not test for these numbers.
+The \fBimreplace\fR and \fBimedit\fP tasks in the PROTO package can be used to replace extreme
+valued pixels. More general system facilities for handling bad pixels
+inside IRAF are planned for the near future.
+.PP
+In order to normalize the magnitude scales of a list of images to a common
+integration time,
+APPHOT requires that the image exposure times be stored in the image header.
+Similarly the correct computation of magnitude errors requires that
+the readout noise and gain parameters also be present in the image
+header or be supplied as constants in the APPHOT parameter files.
+The readout noise must be supplied in units of electrons and the gain
+is assumed to be in electrons per adu. The time units are arbitrary
+but must be consistent for a given set of images.
+APPHOT tasks access this information using a keyword and value scheme.
+The IMAGES package task \fBhedit\fR can be used to insert or edit this
+information prior to entering the APPHOT package. For example the following
+commands will enter the gain, readout noise and exposure time information
+into the headers of a list of images.
+
+.nf
+ \f(CWcl> hedit *.imh gain 14.0 add+ ver-
+ cl> hedit *.imh readout 20.0 add+ ver-
+ cl> hedit *.imh exptime add+ ver+\fR
+.fi
+
+.PP
+The point spread function is assumed to be constant for all regions
+of the image. This is critical in the case of faint objects for
+which small apertures which minimize the effects of crowding and sky noise in
+the aperture are used. The wings of the object will almost certainly extend
+beyond the aperture and good results will only be obtained if objects
+are consistently well centered and the shape and diameter of an object is
+constant throughout the object and invariant to magnitude.
+.PP
+The centering routines built into the APPHOT package assume that
+the images are close to circularly symmetric over the region to be used
+in centering although small deviations do not
+significantly affect the accuracy of the results.
+The user should be aware of the more sophisticated
+but less efficient centering routines in the \fBdaofind\fR and \fBfitpsf\fR
+routines. Several choices of centering algorithm are available in
+APPHOT including no centering.
+.PP
+APPHOT assumes that the local sky background is approximately flat in the
+vicinity of the object being measured. This assumption is equivalent to
+assuming that
+the local sky region has a unique mode. Therefore any variations in the
+sky background which occur at the same scale as the sky region should be
+removed prior to entering the APPHOT package.
+
+.NH
+Setting up the IRAF Environment for APPHOT
+.NH 2
+Script, Compiled and Pset Tasks
+.PP
+IRAF supports three types of tasks: scripts, compiled tasks and pset tasks.
+In order to distinguish one type of task from another, APPHOT users should
+set the cl parameter \fBshowtype\fR to yes as shown below.
+
+.nf
+ \f(CWcl> cl.showtype=yes\fR
+.fi
+
+The cl command \fB?\fR or \fB?\fR \fIpackage\fR identifies script
+tasks by a terminating period and pset tasks by a terminating @.
+No trailing characters are added to the compiled task names. Pset tasks are
+important to the APPHOT package and will be discussed further in
+section 5.
+
+.NH 2
+Other IRAF Packages
+.PP
+Before running APPHOT, users may wish to load the IRAF packages, DATAIO,
+IMAGES,
+TV and PLOT. Various input and output routines exist in the DATAIO package,
+including the fits reader and writer and the cardimage reader and
+writer. The IMAGES package contains routines for basic image arithmetic,
+for computing image statistics, for listing individual pixel values,
+and for examining and
+modifying the image headers. TV, a subpackage of IMAGES, contains the
+\fBdisplay\fR task for loading images into the display device.
+The PLOT package contains tasks for plotting
+image data and for extracting and displaying individual plots from the plot
+metacode files produced by the APPHOT tasks.
+.PP
+Various useful tasks for manipulating and displaying the data produced by
+APPHOT can be found in the PROTO package under the NOAO package. In
+particular the user should be aware of the \fBfields\fR, \fBmkhistogram\fR
+and \fBtvmark\fP tasks.
+
+.NH 2
+The Image Cursor and Display Device
+.PP
+The APPHOT tasks are designed in interactive mode to read the image cursor
+and to perform various actions based on the position of the image cursor
+and the keystroke typed. The image cursor is directed to the display
+device defined by the environment variable \fBstdimage\fR. To check the
+value of the default display device, type the following command.
+
+.nf
+ \f(CWcl> show stdimage
+ imt512\fR
+.fi
+
+In this example the default display device is the 512 pixel square SUN
+imtool window.
+All tasks which write images to the display access this
+device. For example the
+TV package \fBdisplay\fR program will load an image onto this device.
+.PP
+In normal operation IRAF tasks which read the image cursor would read
+the hardware cursor from this device.
+In response to the user command
+
+.nf
+ \f(CWcl> =imcur
+ or
+ cl> show imcur\fR
+.fi
+
+the cursor would come up on the image display ready to accept a
+keystroke command. At this point the user should check that the display
+is reading the correct image coordinates by moving the image cursor to
+the lower left hand corner of the display image and tapping any key.
+The coordinates should read x,y = (1,1) if the whole image was
+displayed.
+.PP
+Cursor readback is currently implemented under IRAF version 2.7 for the
+SUN workstations and the IIS model 70. Users with older versions of IRAF
+or other devices cannot run APPHOT tasks directly from the image display
+device and must redirect the image cursor.
+Two choices are available.
+.IP [1]
+The image cursor can be directed to accept commands from
+the standard input. This is the default setup under IRAF version 2.6.
+This setup can be checked by typing the following command.
+
+.nf
+ \f(CWcl> show stdimcur
+ text\fR
+.fi
+
+If the value of \fBstdimcur\fR is not "text" the user can set this value by
+typing the following.
+
+.nf
+ \f(CWcl> set stdimcur = text\fR
+.fi
+
+Each time the cursor is to be read the user will be prompted for image
+cursor mode text input. The form and syntax of this command are
+described in detail in section 7.3.
+.IP [2]
+Alternatively a contour plot of the image can be used in place of the
+image display and APPHOT tasks can be directed to read the graphics cursor.
+To direct the image cursor to the graphics device the user types
+
+.nf
+ \f(CWcl> set stdimcur = stdgraph\fR
+.fi
+
+This usage permits interactive use of the APPHOT package for users with graphics
+terminals but no image display. This setup is most suitable for terminals
+which permit the text and graphics planes to be displayed simultaneously.
+.RS
+.LP
+It is currently the responsibility of the user to ensure that the image
+displayed on the image display is the same as the image operated on by
+the APPHOT tasks.
+.RE
+
+.NH
+Loading the Apphot Package
+.PP
+At this point the user has the local environment set up and is ready to
+load the APPHOT package. APPHOT resides in the DIGIPHOT package (IRAF
+version 2.8 and later) under the NOAO suite of packages.
+Assuming
+that the NOAO package is already loaded the user types the following.
+
+.nf
+ \f(CWcl> digiphot
+ cl> apphot\fR
+.fi
+
+APPHOT can also be an add-on package (IRAF version 2.7 and earlier)
+installed under the
+LOCAL package. In this case the user types.
+
+.nf
+ \f(CWcl> local
+ cl> apphot\fR
+.fi
+
+The following menu of tasks is displayed.
+
+.nf
+\f(CW
+ apselect daofind fitsky photpars@ polyphot wphot
+ center datapars@ fitskypars@ polymark qphot
+ centerpars@ fitpsf phot polypars@ radprof
+\fR
+.fi
+
+The APPHOT package is now loaded and ready to run.
+A quick one line description of each APPHOT task can be obtained by typing
+the following command.
+
+.nf
+ \f(CWap> help apphot\fR
+.fi
+
+The following text appears.
+.KS
+.nf
+\f(CW
+digiphot.apphot:
+ apselect - Extract select fields from apphot output files
+ center - Compute accurate centers for a list of objects
+ centerpars - Edit the centering parameters
+ daofind - Find stars in an image using the DAO algorithm
+ datapars - Edit the data dependent parameters
+ fitpsf - Model the stellar psf with an analytic function
+ fitsky - Compute sky values in a list of annular or circular
+ regions
+ fitskypars - Edit the sky fitting parameters
+ phot - Measure magnitudes for a list of stars
+ photpars - Edit the photometry parameters
+ polymark - Create polygon and coordinate lists for polyphot
+ polyphot - Measure magnitudes inside a list of polygonal regions
+ polypars - Edit the polyphot parameters
+ qphot - Measure quick magnitudes for a list of stars
+ radprof - Compute the stellar radial profile of a list of stars
+ wphot - Measure magnitudes with weighting
+\fR
+.fi
+.KE
+For the remainder of this document
+we will use the principal APPHOT task \fBphot\fR as an example of how to
+setup the parameters in both interactive and batch mode.
+To get detailed help on the phot task the user types the following.
+
+.nf
+ \f(CWcl> help phot | lprint\fR
+.fi
+
+The help page(s) for the \fBphot\fR task will appear on the local default
+printer.
+
+.NH
+Setting the APPHOT Photometry Task Parameters
+.PP
+The principal APPHOT task PHOT is described in sections 5.1 to 5.6. The
+quick photometry task QPHOT is described in section 5.7 and the
+polygonal aperture photometry task POLYPHOT is described in section
+5.8.
+.NH 2
+The Task Parameters
+.PP
+The \fBphot\fR task parameter set specifies the required image, coordinate
+and output files, the graphics and display devices, the graphics and image
+cursor and the mode of use of the task, interactive or batch. To enter
+and edit the parameter set for the \fBphot\fR task the user types the
+following.
+
+.nf
+ \f(CWcl> epar phot\fR
+.fi
+
+The parameter set for the \fBphot\fR task will appear on the terminal ready
+for editing as follows.
+
+.nf
+\f(CW
+ IRAF
+ Image Reduction and Analysis Facility
+
+ PACKAGE = apphot
+ TASK = phot
+
+ image = Input image
+ (datapar= ) Data dependent parameters
+ (centerp= ) Centering parameters
+ (fitskyp= ) Sky fitting parameters
+ (photpar= ) Photometry parameters
+ (coords = ) Coordinate list
+ skyfile = Sky file
+ (output = default) Results file
+ (plotfil= ) File of plot metacode
+ (graphic= stdgraph) Graphics device
+ (display= stdimage) Display device
+ (command= ) Image cursor: [x y wcs] key [cmd]
+ (cursor = ) Graphics cursor: [x y wcs] key [cmd]
+ (radplot= no) Plot the radial profiles
+ (interac= yes) Mode of use
+ (verify = yes) Verify critical parameters in non
+ interactive mode
+ (verbose= no) Print messages in non interactive mode
+ (mode = ql)
+\fR
+.fi
+
+The \fBphot\fR parameters can be edited in the usual fashion by successively
+moving
+the cursor to the line opposite the parameter name, entering the new value,
+followed by a carriage return, and finally typing a ^Z to exit the
+\fBepar\fR task and update the parameters.
+Some general points about the task
+parameter sets are summarized below. For more detailed descriptions of each
+parameter see the help pages for each task.
+.IP [1]
+\fBImage\fR specifies the list of input image(s) containing the
+stars to be measured. \fBImage\fR may be a list of images, an image
+template or a file containing a list of images.
+For example if we wish to measure stars in three images: m31U, m31B and
+m31V we could specify the \fBimage\fR parameter in the following three ways.
+
+.nf
+\f(CW
+ image = m31B,m31U,m31V Input image
+ or
+ image = m31*.imh Input image
+ or
+ image = @imlist Input image
+\fR
+.fi
+
+"Imlist" is the name of a text file containing the list of images
+one image name per line. The image list file can easily be created with the cl
+package \fBfiles\fR task or the editor.
+.IP [2]
+Four parameter sets, henceforth psets, \fBdatapars\fR, \fBcenterpars\fR,
+\fBfitskypars\fR and \fBphotpars\fR specify the algorithm parameters.
+They are described in detail in later sections.
+.IP [3]
+\fBCoords\fR specifies the name of the coordinate file(s) containing the
+initial positions of the stars to be measured. If \fBcoords\fR = "",
+the current image cursor position is read and used as the initial position.
+The number of files specified by
+\fBcoords\fR must be either one, in which
+case the same coordinate file is used for all the images, or equal in
+number to the set of input images.
+\fBCoords\fR can be a list of files, a file name template,
+or a file
+containing the list of x and y coordinates one per line.
+For example if we have three coordinate files "m31B.coo", "m31U.coo" and
+"m31V.coo" for the three images listed above, we could set the \fBcoords\fR
+parameter in the following three ways.
+
+.nf
+\f(CW
+ (coords = m31B.coo,m31U.coo,m31V.coo) Coordinate list
+ or
+ (coords = m31*.coo) Coordinate list
+ or
+ (coords = @coordlist) Coordinate list
+\fR
+.fi
+
+"Coordlist" is the name of a text file containing the names of the coordinate
+files in the desired order one per line.
+.IP [4]
+\fBOutput\fR specifies the name of the results file(s). If \fBoutput\fR =
+"default" then a single output file is created for
+each input image and the root of the output file name is the name of the
+input image. In the case of the above example \fBphot\fR would create three
+output files called "m31B.mag.1", "m31U.mag.1" and "m31V.mag.1" assuming
+that this was the initial run of \fBphot\fR on these images.
+If the user sets the \fBoutput\fR parameter then the number of output files
+must be either one or equal to the number of input images. For example the
+user could set \fBoutput\fR to either
+
+.nf
+\f(CW
+ (output = m31.out) Results
+ or
+ (output = m31b.out,m31u.out,m31v.out) Results
+\fR
+.fi
+
+If the user sets \fBoutput\fR = "" then no output file is written.
+.IP [5]
+The parameters \fBgraphics\fR and \fBdisplay\fR specify the graphics and
+image display devices. In IRAF version 2.6 and later the APPHOT tasks
+which reference these parameters will in interactive mode issue a warning
+if they cannot open either of these devices
+and continue execution. In IRAF version 2.5 the \fBdisplay\fR parameter must
+be set to "stdgraph" as listed below
+
+.nf
+\f(CW
+ (display= stdgraph) Display device
+\fR
+.fi
+
+or the following system error will be generated.
+
+.nf
+\f(CW
+ "cannot execute connected subprocess x_stdimage.e"
+\fR
+.fi
+Most of the APPHOT tasks use IRAF graphics in interactive mode to allow
+users to set up their parameters and /or examine their results using radial
+profile plots. The \fBgraphics\fR specifies which graphics device these plots
+will be written to. Similarly most IRAF tasks permit the user to optionally
+mark the star positions, apertures and sky annuli on the display device.
+The parameter \fBdisplay\fR specifies which image display device this
+information will be written to. Currently IRAF does not support an image display
+kernel so the display marking features of APPHOT are not available unless
+the user chooses to run APPHOT interactively from a contour plot.
+.IP [6]
+If \fBplotfile\fR is not equal to "", then for each star written to
+\fBoutput\fR
+a radial profile plot is written to the plot metacode file \fBplotfile\fR.
+The \fBplotfile\fR is opened in append mode and succeeding executions
+of \fBphot\fR write to the end of the same file which may in the process
+become very large.
+\fIThe user should be aware that writing radial profile plots
+to \fBplotfile\fI can significantly slow the execution of \fBphot\fR.
+The variable \fBradplots\fR enables radial profile plotting in interactive mode.
+For each star measured a radial profile plot displaying the answers is
+plotted on the screen.
+.IP [7]
+The \fBinteractive\fR parameter switches the task between interactive
+and batch mode.
+In interactive mode plots and text are written to the terminal as well as the
+output file and the user can show and set the parameters. In batch mode
+\fBphot\fR executes silently.
+.IP [8]
+The \fBverify\fP parameter allows the user to verify the critical task
+parameters in non interactive mode. It is normally set to yes but
+should be turned off when submitting jobs to background.
+.IP [9]
+The \fBverbose\fP switch permits the printing of results to the standard
+output in non interactive mode. It is normally turned off.
+
+.NH 2
+APPHOT Psets
+.PP
+APPHOT algorithm parameters have been gathered together into logical
+groups and stored in parameter files. The use of psets permits the
+user to store APPHOT parameters with their relevant datasets rather than
+in the uparm directory and allows APPHOT tasks to share common parameter
+sets. APPHOT presently supports 5 pset files: 1) \fBdatapars\fR which contains
+the data dependent parameter 2) \fBcenterpars\fR which contains the
+centering algorithm parameters 3) \fBfitskypars\fR which contains the
+sky fitting
+algorithm parameters 4) \fBphotpars\fR which contains the multiaperture
+photometry parameters and 5) \fBpolypars\fR which contains the polygonal
+aperture
+photometry parameters. The user should consult the manual page for each
+of the named pset files as well as the attached parameter set document,
+\fIExternal Parameter Sets in the CL and Related Revisions\fR, by Doug Tody.
+.PP
+The default mode of running APPHOT is to edit and store the pset parameter
+files in the uparm directory. For example to edit the
+\fBdatapars\fR parameter set, the user types either
+
+.nf
+ \f(CWcl> epar datapars\fR
+ or
+ \f(CWcl> datapars\fR
+.fi
+
+and edits the file as usual. All the top level tasks which reference this
+pset will pick up the changes from the uparm directory, assuming
+datapars = "".
+.PP
+Alternatively the user can edit the \fBphot\fR
+task and its psets all at once as follows using \fBepar\fR.
+
+.nf
+ \f(CWcl> epar phot\fR
+.fi
+
+Move the cursor to the \fBdatapars\fR parameter line and type \fB:e\fR.
+The menu for the
+\fBdatapars\fR pset will appear and is ready for editing. Edit the desired
+parameters and type \fB:q\fR. \fBEpar\fR will return to the main
+\fBphot\fR parameter set.
+Follow the same procedure for the other three psets
+\fBcenterpars\fR, \fBfitskypars\fR and \fBphotpars\fR and exit the program
+in the usual manner.
+.PP
+Sometimes it is desirable to store a given pset along with the data.
+This provides a facility for keeping many different copies of say the
+\fBdatapars\fR pset with the data.
+The example below shows how to write a pset out to a file in the same directory
+as the data. The user types
+
+.nf
+ \f(CWcl> epar phot\fR
+.fi
+
+as before, enters the datapars menu with \f(CW:e\fR and edits the parameters.
+The command
+
+.nf
+ \f(CW:w data1.par\fR
+.fi
+
+writes the parameter set to a file called "data1.par" and a \fB:q\fR
+returns to the main task menu.
+A file called "data1.par" containing the new \fBdatapars\fR parameters
+will be written in the current directory. At this point the user is in the
+\fBphot\fR parameter set at the line opposite \fBdatapars\fR and
+enters "data1.par" on the line opposite this parameter.
+The next time \fBphot\fR is run the parameters will
+be read from "data1.par" not from the pset in the uparm directory.
+This procedure can be repeated for each data set which has distinct parameters,
+as in for example data taken on separate nights.
+
+.NH 2
+Datapars
+.PP
+All the data dependent parameters have been gathered together in one
+pset \fBdatapars\fR. The idea behind this organization is to facilitate
+setting up the algorithm
+psets for data taken under different conditions. For example the
+user may have determined the optimal centering box size, sky annulus radius
+and width and aperture radii in terms of the current \fBfwhmpsf\fR and the
+rejection criteria in terms of the current background standard deviation
+\fBsigma\fR. In order to use the same setup on
+the next image the user need only reset the \fBscale\fR and background
+\fBsigma\fR parameters to the new values.
+The only pset which need be edited is \fBdatapars\fR.
+.PP
+To examine and edit the \fBdatapars\fR pset type
+
+.nf
+ \f(CWap> datapars\fR
+.fi
+
+and the following menu will appear on the screen.
+
+.nf
+\f(CW
+ IRAF
+ Image Reduction and Analysis Facility
+
+ PACKAGE = apphot
+ TASK = datapars
+
+ (fwhmpsf= 1.) FWHM of the PSF in scale units
+ (emissio= yes) Features are positive
+ (noise = poisson) Noise model
+ (thresho= 0.) Detection threshold in counts above
+ background
+ (cthresh= 0.) Centering threshold in counts above
+ background
+ (sigma = INDEF) Standard deviation of background in counts
+ (scale = 1.) Image scale in units per pixel
+ (ccdread= ) CCD readout noise image header keyword
+ (readnoi= INDEF) CCD readout noise in electrons
+ (gain = ) CCD gain image header keyword
+ (epadu = 1.) Gain in electrons per count
+ (exposur= ) Exposure time image header keyword
+ (itime = INDEF) Integration time
+ (datamin= INDEF) Minimum good data pixel
+ (datamax= INDEF) Maximum good data pixel
+ (mode = ql)
+ ($nargs = 0)
+\fR
+.fi
+
+.PP
+The following is a brief description of the parameters and their function
+as well as some initial setup recommendations.
+
+.PP
+\fBScale\fP is the image scale parameter in units per pixel, for example
+arc-seconds per pixel. All distance dependent parameters in the APPHOT package
+including the centering box width \fBcbox\fP in \fBcenterpars\fP, the
+inner radius and width of the sky annulus, \fBannulus\fP and
+\fBdannulus\fP in \fBfitskypars\fP, and the radii of the concentric
+circular apertures \fBapertures\fP in \fBphotpars\fP are defined
+in scale units, for example arc seconds. This permits easy comparison
+with apertures published in the literature. Some other algorithm
+parameters such as \fBmaxshift\fP in \fBcenterpars\fP and the region
+growing radius \fBrgrow\fP in
+\fBfitskypars\fP are also defined in scale units. By default all
+distance parameters are defined in pixels.
+.PP
+\fBFwhmpsf\fP is used as a first guess for modelling the psf in the
+\fBfitpsf\fP task, is important for the optimal use of the \fBdaofind\fP
+algorithm, and critical for the centering algorithms "gauss" and
+"ofilter" as well as the \fBwphot\fP task.
+\fBFwhmpsf\fR as well as the other distance dependent parameters
+can be set interactively from inside most of the APPHOT tasks.
+.PP
+\fBFwhmpsf\fP and \fBscale\fP can be combined in an interesting way.
+\fBScale\fP can be defined in units of half width half maximum of the psf per
+pixel in which case the value of \fBfwhmpsf\fP should be set to
+\fB2.0\fP by definition. By trial and error and use of the interactive
+setup menu optimal values of the remaining distance dependent parameters
+can be determined in units of \fBscale\fP. Once determined the same
+setup can be reused on another image by simply reseting the \fBscale\fP
+parameter.
+.PP
+APPHOT photometry routines permit measurement of both emission and absorption
+features. For the majority of applications including photometry of
+stars and galaxies
+all "objects" are emission "objects" and the \fBemission\fR parameter should
+be left at yes.
+.PP
+APPHOT currently supports two noise models "constant" and "poisson".
+If \fBnoise\fR = "constant" the magnitude errors are computed from the
+Poisson noise in the sky background plus the readout noise.
+If \fBnoise\fR = "poisson"
+the magnitude errors are computed on the basis of the Poisson noise in the
+constant sky background, Poisson noise in the object and readout noise.
+Most users
+with CCD data will wish to leave \fBnoise\fR = "poisson".
+\fBCthreshold\fR is a parameter required by the centering algorithms.
+If \fBcthreshold\fR > 0.0, pixels below the data minimum plus
+threshold in the centering subraster are not used by the centering algorithm.
+For difficult centering problems the user may wish to adjust
+this parameter.
+The \fBsigma\fR parameter specifies the standard deviation of the background
+in a single pixel. \fBSigma\fR is used
+to estimate the signal to noise ratio in the centering subraster and to set
+the width and bin size of the histogram of sky pixels, the \fBkhist\fR and
+\fBbinsize\fR parameters in the pset \fBfitskypars\fR. Both \fBcthreshold\fR and
+\fBsigma\fR can be set interactively from inside the \fBphot\fR task.
+.PP
+APPHOT currently recognizes three image header keywords \fBccdread\fR,
+\fBgain\fR and \fBexposure\fR. Knowledge of the instrument gain and
+readout noise is required for the correct computation of the magnitude
+errors but not required for the magnitude computation. The units of
+the gain and readout noise are assumed to be electrons per adu
+and electrons respectively.
+Exposure time information is required to normalize the magnitudes computed
+for a series of images to a common exposure time.
+The time units are arbitrary but must be consistent for a set of images.
+If this information is already in the
+image header the user can enter the appropriate header keywords.
+Otherwise the instrument constants gain and readout noise can be entered
+into the parameters \fBepadu\fR and \fBreadnoise\fR.
+If the exposure time information is not present in the image header, the
+user can either edit it in with the \fBhedit\fR task or change the \fBitime\fR
+parameter for each image reduced. If both image header keywords and
+default parameter values are defined the image header keywords take
+precedence.
+.PP
+The two parameters \fBdatamin\fP and \fBdatamax\fP which define the upper
+and lower good data limits respectively are not currently implemented by
+the APPHOT tasks. They will be used in future versions of the package
+to, for example, set the limits over which a detector is linear.
+.PP
+After editing, the new \fBdatapars\fR pset might look like the following.
+This user has chosen to wait and set \fBfwhmpsf\fR, \fBthreshold\fR,
+\fBcthreshold\fR, and \fBsigma\fR interactively from inside \fBphot\fR but
+has decided to set the
+image header parameters \fBccdread\fR, \fBgain\fR and \fBexposure\fR.
+
+.nf
+\f(CW
+ IRAF
+ Image Reduction and Analysis Facility
+
+ PACKAGE = apphot
+ TASK = datapars
+
+ (fwhmpsf= 1.) FWHM of the PSF in scale units
+ (emissio= yes) Features are positive
+ (noise = poisson) Noise model
+ (thresho= 0.) Detection threshold in counts above
+ background
+ (cthresh= 0.) Centering threshold in counts above
+ background
+ (sigma = INDEF) Standard deviation of background in counts
+ (scale = 1.) Image scale in units per pixel
+ (ccdread= readout) CCD readout noise image header keyword
+ (readnoi= INDEF) CCD readout noise in electrons
+ (gain = gain) CCD gain image header keyword
+ (epadu = 1.) Gain in electrons per count
+ (exposur= exptime) Exposure time image header keyword
+ (itime = INDEF) Integration time
+ (datamin= INDEF) Minimum good data pixel
+ (datamax= INDEF) Maximum good data pixel
+ (mode = ql)
+ ($nargs = 0)
+\fR
+.fi
+
+.NH 2
+The Centering Parameters
+.PP
+The centering algorithm parameters have been grouped together in a single
+parameter set \fBcenterpars\fR. To display and edit these parameters type
+the command.
+
+.nf
+ \f(CWap> centerpars\fR
+.fi
+
+The following menu will appear on the terminal.
+
+.nf
+\f(CW
+ IRAF
+ Image Reduction and Analysis Facility
+
+ PACKAGE = apphot
+ TASK = centerpars
+
+ (calgori= centroid) Centering algorithm
+ (cbox = 5.) Centering box width in scale units
+ (maxshif= 1.) Maximum center shift in scale units
+ (minsnra= 1.) Minimum SNR ratio for centering
+ (cmaxite= 10) Maximum iterations for centering algorithm
+ (clean = no) Symmetry clean before centering
+ (rclean = 1.) Cleaning radius in scale units
+ (rclip = 2.) Clipping radius in scale units
+ (kclean = 3.) K-sigma rejection criterion in skysigma
+ (mkcente= no) Mark the computed center
+ (mode = ql)
+ ($nargs = 0)
+\fR
+.fi
+
+.PP
+APPHOT offers three choices for the centering algorithm:
+the default "centroid", "gauss" and "ofilter".
+The default centering algorithm does not depend on \fBfwhmpsf\fR but the
+remaining two do. For reasons of simplicity and efficiency the author
+recommends the default algorithm. In cases where there is significant
+crowding or the data is very noisy users may wish to experiment with
+the other algorithms. Centering can be disabled by setting
+\fBcalgorithm\fR = "none". This option is useful if accurate centers
+have already been computed with the \fBdaofind\fR or \fBfitpsf\fR
+tasks. More detailed information on the APPHOT centering algorithms
+can be found in the document, \fISpecifications for the Apphot Package\fR
+by Lindsey Davis.
+.PP
+The centering box \fBcbox\fR is defined in units of \fBscale\fR.
+Users should try to set \fBcbox\fR as small as possible to avoid
+adding noisy pixels to the centering subraster.
+\fBCbox\fR can also be set interactively from inside the APPHOT \fBphot\fR
+task.
+.PP
+If the computed centers are more than \fBmaxshift\fR / \fBscale\fR pixels
+from the initial centers or the signal-to-noise ratio in the centering
+subraster is less than \fBminsnratio\fR the new center will be computed but
+flagged with a warning message.
+.PP
+For stars which are crowded or contaminated by bad pixels the user may
+wish to enable the cleaning algorithm by setting \fBclean\fR = yes.
+Its use is complicated and not recommended for most data. The algorithm is
+described in the APPHOT specifications document.
+.PP
+If \fBmkcenter\fR=yes, \fBphot\fR tasks will mark the initial
+and final centers and draw a line between them on the default display
+device. At present this option only works if \fBdisplay\fR="stdgraph".
+.PP
+In the above example we have elected to leave the \fBcalgorithm\fR parameter
+at its default value and set \fBcbox\fR interactively from inside the \fBphot\fR
+task.
+
+
+.NH 2
+The Sky Fitting Parameters
+.PP
+The sky fitting algorithm parameters have been grouped together in a single
+parameter set \fBfitskypars\fR. To display and edit these parameters type
+the following command.
+
+.nf
+ \f(CWap> fitskypars\fR
+.fi
+
+The following menu will appear on the terminal.
+
+.nf
+\f(CW
+ IRAF
+ Image Reduction and Analysis Facility
+
+ PACKAGE = apphot
+ TASK = fitskypars
+
+ (salgori= mode) Sky fitting algorithm
+ (annulus= 10.) Inner radius of sky annulus in scale units
+ (dannulu= 10.) Width of sky annulus in scale units
+ (skyvalu= 0.) User sky value
+ (smaxite= 10) Maximum number of sky fitting iterations
+ (snrejec= 50) Maximum number of sky fitting rejection
+ iterations
+ (skrejec= 3.) K-sigma rejection limit in sky sigma
+ (khist = 3.) Half width of histogram in sky sigma
+ (binsize= 0.1) Binsize of histogram in sky sigma
+ (smooth = no) Lucy smooth the histogram
+ (rgrow = 0.) Region growing radius in scale units
+ (mksky = no) Mark sky annuli on the display
+ (mode = ql)
+ ($nargs = 0)
+\fR
+.fi
+
+.PP
+APPHOT offers ten sky fitting algorithms. The algorithms can be grouped
+into 4 categories 1) user supplied sky values including "constant" and "file"
+2) sky pixel distribution algorithms including "median" and "mode",
+3) sky pixel histogram algorithms including "centroid", "crosscor",
+"gauss" and "ofilter" 4) interactive algorithms including "radplot"
+and "histplot".
+The definitions of the mode used by APPHOT is the following.
+
+.nf
+\f(CW mode = 3.0 * median - 2.0 * mean\fP
+.fi
+
+Detailed descriptions of the algorithms can be found in the document,
+\fISpecifications for the Apphot Package\fR by the author. The author recommends
+"mode" the default, and one of the two histogram algorithms "centroid" and
+"crosscor".
+.PP
+The inner radius and width of the sky annulus in terms of \fBscale\fR
+are set by the parameters \fBannulus\fR and \fBdannulus\fR. These can
+easily be set interactively from within the \fBphot\fR task.
+Good statistics require several hundred sky pixels.
+The user should be aware that a circular sky region can be defined by
+setting \fBannulus\fR to 0.
+.PP
+The user should ensure that the parameter \fBsigma\fR in the
+\fBdatapars\fR parameter set is defined if one of the histogram dependent
+sky fitting algorithms is selected.
+The extent and resolution of the sky pixel histogram is determined
+by \fBkhist\fR and \fBbinsize\fR and their relation to \fBsigma\fR.
+If \fBsigma\fR is undefined then the standard deviation of the local
+sky background is used to parameterise \fBkhist\fR and \fBbinsize\fR
+and the histograms of different stars can deviate widely in resolution.
+.PP
+The sky rejection algorithms are controlled by the parameters \fBskreject\fR,
+\fBsnreject\fR and \fBrgrow\fR. It is strongly recommended that the user
+leave pixel rejection enabled. The user should experiment with the region
+growing radius if the local sky regions are severely crowded.
+.PP
+If \fBmksky\fR = yes, \fBphot\fR will mark the inner
+and outer sky annuli. At present this option
+will only work if \fBdisplay\fR = "stdgraph".
+
+.NH 2
+The Photometry Parameters
+.PP
+The photometry algorithm parameters have been grouped together in a single
+parameter set \fBphotpars\fR. To display and edit these parameters type.
+
+.nf
+ \f(CWap> photpars\fR
+.fi
+
+The following menu will appear on the terminal.
+
+.nf
+\f(CW
+ IRAF
+ Image Reduction and Analysis Facility
+
+ PACKAGE = apphot
+ TASK = photpars
+
+ (weighti= constant) Photometric weighting scheme for wphot
+ (apertur= 3.) List of aperture radii in scale units
+ (zmag = 26.) Zero point of magnitude scale
+ (mkapert= no) Draw apertures on the display
+ (mode = ql)
+ ($nargs = 0)
+\fR
+.fi
+
+.PP
+There are three weighting options inside APPHOT. The default is "constant".
+Inside the \fBphot\fR, \fBradprof\fR and \fBpolyphot\fR tasks only constant
+weighting is used. Two other weighting schemes are available for the
+experimental \fBwphot\fR task, "gauss" and "cone". "Gauss" is the more
+highly recommended.
+.PP
+The aperture list is specified by \fBapert\fR in terms of \fBscale\fR.
+The apertures can be entered in any order but are sorted on output.
+\fBApert\fR can be string or the name of a text file containing the
+list of apertures. Apertures can either be listed individually and
+separated by whitespace or commas or a ranges notation of the
+form apstart:apend:apstep can be used.
+These can be set interactively from within the \fBphot\fR task.
+.PP
+Examples of valid aperture strings are listed below.
+
+.nf
+\f(CW
+ 1 2 3
+ 1.0,2.0,3.0
+ 1:10:1
+\fR
+.fi
+
+.PP
+An arbitrary zero point is applied to the magnitude scale with \fBzmag\fR.
+The user can accept the default or experiment with his/her data until
+a suitable value is found. The computation of the magnitude errors
+does not depend on the zero point.
+.PP
+If \fBmkapert\fR = yes, the \fBphot\fR task will draw the concentric
+apertures on the display. At present this option
+works only if \fBdisplay\fR = "stdgraph".
+
+.NH 2
+The QPHOT Task
+.PP
+\fBQphot\fP computes accurate centers, sky values and magnitudes for a list
+of objects using a restricted subset of the full \fBphot\fP parameter set.
+It is intended to be a quick look photometer suitable for use when
+observing on the mountain or in well behaved uncrowded stellar fields.
+.PP
+The user is automatically queried for the critical parameters \fBcbox\fP,
+\fBannulus\fP, \fBdannulus\fP and \fBapertures\fP which are defined in
+terms of pixels. The noise characteristics of the detector are assumed
+to obey Poisson statistics. \fBQphot\fP computes centers for each
+object using the "centroid" centering algorithm. Sky values are
+calculated using the "mode" algorithm. The user can set the zero point
+of the magnitude scale, \fBzmag\fP, the gain of the detector, \fBepadu\fP,
+and exposure time image header keyword, \fBexposure\fP, but all the
+remaining parameters are set to their default values.
+.PP
+\fBQphot\fP can be driven by the image cursor or a coordinate list in
+interactive mode or by a coordinate list in batch mode in exactly
+the same manner as the \fBphot\fP task.
+
+.NH 2
+The \fBPOLYPHOT\fP Task
+.PP
+\fBPolyphot\fP computes accurate centers, sky values and magnitudes for
+a list of objects using polygonal shaped apertures. It is most suitable
+for measuring the magnitudes of large extended irregularly shaped objects.
+.PP
+\fBPolyphot\fP uses \fBdatapars\fP, \fBcenterpars\fP, and
+\fBfitskypars\fP in exactly the same manner as the \fBphot\fP task. In
+general users should set the task parameters in the same way as they
+set them in \fBphot\fP. However users who have defined their polygonal
+apertures interactively may wish to set the centering algorithm
+parameter \fBcalgorithm =\fP "none", to avoid the task trying to center
+on the brightest feature in the aperture.
+.PP
+The apertures are defined either interactively with the image or graphics
+cursor or by two files \fBpolygons\fP and \fBcoords\fP.
+Polygons defines the shape of the polygonal aperture and coords defines the
+initial positions of the apertures. The polygons file may contain
+more than one aperture and the flux through each aperture may be measured
+at more than one position. A detailed description of the file formats
+is given in section 6.4
+
+.NH
+Creating A Coordinate List
+.PP
+All APPHOT tasks operate on either lists of object coordinates or
+interactive cursor
+input. Lists are maintained as text files, one object per line with the x
+and y coordinates in columns one and two respectively. The coordinate and
+polygon files required by the \fBpolyphot\fR task have a different
+format which is described below. List files may be
+created interactively with either the graphics or the image cursor, by a
+previously executed APPHOT task, by a previously executed IRAF task or by
+a user program. Various means of creating coordinate lists within IRAF
+are described below. Comments preceded by a # character and blank lines
+are ignored.
+
+.nf
+\f(CW
+ #Sample Coordinate List
+ 53.6 83.25
+ 100.0 35.8
+ 2.134 86.89
+ .... ....
+\fR
+.fi
+
+.NH 2
+Daofind
+.PP
+\fBDaofind\fR is an APPHOT task which detects stellar objects in an image
+automatically. The user sets the \fBfwhmpsf\fR of the psf for which the
+detection algorithm is to be
+optimized as well as an intensity threshold for detection. \fBDaofind\fR
+locates all the qualifying stars and writes their positions, rough magnitudes
+and shape characteristics to a file. This file can then be assigned to
+the \fBphot\fR task \fBcoords\fR parameter and read directly.
+.PP
+For example if we have an image containing stars for which the \fBfwhmpsf\fR
+is 4.0 pixels and the sigma of the sky background is 10 we might run
+\fBdaofind\fR as follows,
+
+.nf
+ \f(CWcl> daofind image fwhmpsf=4.0 threshold=30.0\fR
+.fi
+
+where we have set our detection threshold at 3.0 * sigma.
+
+.NH 2
+Imtool On the SUN Machines
+.PP
+The SUN IRAF \fBimtool\fR facility supports both image world coordinate
+systems and output coordinate files. Coordinate lists can be created
+interactively by the users in the following way.
+.PP
+Display the IRAF image in the imtool window using the \fBdisplay\fR task.
+Move the mouse to the top of the \fBimtool\fR window, press the right mouse
+button to enter the \fBimtool\fR menu, move the mouse to the setup option and
+release the mouse button. Press
+the return key until the black triangle is opposite the coordinate list file
+name parameter.
+Delete the default file name, enter the full host system path name of the
+desired coordinate file and press return. This name should now appear at
+the top of the imtool window.
+Move the mouse to the quit option and press the left mouse button to
+quit the setup window.
+.PP
+To enter the \fBimtool\fR cursor readout mode type the \fBF6\fR key.
+The x, y and intensity values at the cursor position
+are displayed in the lower right corner of the image.
+To mark stars and output their coordinates to the coordinate file, move
+the image cursor a star and press the left mouse button. A sequence number
+will appear on the display next to the marked position. The numbers can
+be changed from black to white and vice versa by toggling the \fBF5\fR key.
+The coordinate files are opened in append mode in order that stars may be
+added to an already existing list. \fBImtool\fR coordinate files are directly
+readable by all APPHOT tasks.
+
+.NH 2
+Rgcursor and Rimcursor
+.PP
+The LISTS package tasks \fBrgcursor\fR and \fBrimcursor\fR can be used to
+generate coordinate lists interactively. For example a coordinate
+list can be created interactively using the display cursor and
+the image display.
+
+.nf
+\f(CW
+ cl> display image
+
+ ... image appears on the display ...
+
+ cl> rimcursor > image.coo
+
+ ... move display cursor to stars of interest and tape space bar ...
+
+ ... type ^Z to terminate the list ...
+\fR
+.fi
+
+Similarly a coordinate list
+can be created using the graphics cursor and a contour
+plot as shown below.
+
+.nf
+\f(CW
+ cl> contour image
+
+ ... contour plot appears on the terminal ...
+
+ cl> rgcursor > image.coo
+
+ ... move cursor to stars of interest and tap space bar ...
+
+ ... type ^Z to terminate the list ...
+\fR
+.fi
+
+The text file "image.coo" contains the x and y coordinates of the marked stars
+in image pixel units. The output of \fBrimcursor\fR or \fBrgcursor\fR can
+be read directly by the APPHOT \fBphot\fR task.
+\fBRimcursor\fR is only available in IRAF versions 2.7 and later and
+only for selected devices.
+
+.NH 2
+The Polygon List
+.PP
+A utility routine \fBpolymark\fR has been added to the APPHOT package to
+generate polygon and initial center lists for the \fBpolyphot\fR task.
+The format of the polygon files is 1 vertex per line with the
+x and y coordinates of the vertex in columns 1 and 2 respectively.
+A line containing the single character ';' terminates the lists of vertices.
+There can be more than one polygon in a single polygon file.
+
+.nf
+\f(CW
+ Sample Polygon File
+
+ 1.0 1.0
+ 1.0 51.0
+ 51.0 51.0
+ 51.0 1.0
+ ;
+ 80.0 80.0
+ 80.0 131.0
+ 131.0 131.0
+ 131.0 80.0
+ ;
+\fR
+.fi
+
+.PP
+The accompanying coordinate file is optional. If no coordinate file is given
+the initial center for the polygon is the mean of its vertices in the
+polygon file. If a
+coordinate file is specified the initial center for the polygon is the
+position in the coordinate file. Each polygonal aperture may be moved
+to several positions.
+
+.nf
+\f(CW
+ Sample Polyphot Coords File
+
+ 50. 30.
+ 80. 100.
+ 60. 33.
+ ;
+ 90. 50.
+ 55. 90.
+ 12. 122.
+ ;
+\fR
+.fi
+
+For example all the coordinates in group 1 will be measured using the
+aperture defined by polygon 1 and all the coordinates
+in group 2 will be measured with the aperture defined by polygon 2.
+
+.NH 2
+User Program
+.PP
+Obviously any user program which produces a text file with the coordinates
+listed 1 per line with x and y in columns 1 and 2 can be used to produce
+APPHOT coordinate files.
+
+.NH 2
+Modifying an Existing Coordinate List
+.PP
+The LISTS package routine \fBlintran\fR has been linked into the APPHOT
+package. It can be used to perform simple coordinate transformations on
+coordinate lists including shifts, magnifications, and rotations.
+
+.NH
+Running Apphot in Interactive Mode Without a Coordinate List
+.PP
+There are currently three ways to run the \fBphot\fR interactively without
+a coordinate list:
+1) read image display cursor commands 2) read
+graphics cursor commands 3) read commands
+from the standard input. The three methods are briefly discussed below.
+Detailed examples of all three methods of operation can be found in
+the manual pages for each task.
+
+.NH 2
+Reading Image Cursor Commands
+.PP
+The default method of running APPHOT. The user loads an image onto
+the display, types \fBphot\fR and enters the image name. The image cursor
+appears on the display and the program is ready to accept user commands.
+This option is not available under IRAF version 2.6 and earlier
+because interactive image cursor readback was not available.
+
+.NH 2
+Redirecting the Image Cursor to the Graphics Cursor
+.PP
+\fBPhot\fR reads the graphics cursor and executes various keystroke
+commands. The environment variable \fBstdimcur\fR must be set to "stdgraph".
+For full access
+to all the graphics commands the parameter \fBdisplay\fR must also be set
+to "stdgraph".
+The user creates a contour plot of the image on the graphics terminal
+with the \fBcontour\fR task, types \fBphot\fR and answers the image name query.
+The graphics cursor appears on the contour plot ready for input.
+The user can move around the plot with the cursor successively marking stars.
+
+.NH 2
+Redirecting the Image Cursor to the Standard Input
+.PP
+The user can enter cursor commands directly on the standard input.
+The environment variable \fBstdimcur\fR must be set to "text".
+When the user types the task name \fBphot\fR and enters the image
+name, the following prompt appears.
+
+.nf
+ \f(CWImage cursor [xcoord ycoord wcs] key [cmd]:\fR
+.fi
+
+\fIXcoord\fR and \fIycoord\fR are the coordinates of the object of
+interest, \fIwcs\fR is the current world coordinate system, always 1,
+\fIkey\fR is a single
+character and \fIcmd\fR is an APPHOT task command.
+To perform the default action of
+the \fBphot\fR task the user responds as follows.
+
+.nf
+ \f(CWImage cursor [xcoord ycoord wcs] key [cmd]: 36. 42. 1\fR
+.fi
+
+\fBPhot\fR measures the magnitude of the star near pixel coordinates
+x,y = (36.,42.) and writes the result to the output file.
+In IRAF version 2.5 all the cursor command fields must be typed.
+The square brackets
+indicate those fields which are optional under IRAF version 2.6 and later.
+Users with SUN
+workstations may wish to combine the IMTOOL coordinate list cursor readback
+facilities which generate coordinate lists with this mode of running APPHOT
+interactively.
+
+.NH 2
+The Interactive Keystroke Commands
+.PP
+A conscious effort has been made to keep the definitions of all the
+keystroke commands within the APPHOT package as similar as possible.
+The following are the most commonly used keystrokes in the APPHOT package.
+
+.NH 3
+The ? (Help) Keystroke Command
+.PP
+The ? key prints the help page describing the cursor keystroke and colon
+show commands for the specific APPHOT task. An abbreviated help page
+is typed by default when a user enters a task in interactive mode.
+The ? key can be typed at any point in the APPHOT task.
+
+.NH 3
+The :show (Set and Print parameter) Commands
+.PP
+Any APPHOT parameter can be displayed by typing :\fIparameter\fR command
+in interactive mode.
+For example to show the current value of the \fBfwhmpsf\fR parameter
+type the following command.
+
+.nf
+ \f(CW:fwhmpsf\fR
+.fi
+
+To set any APPHOT parameter type :\fIparameter\fR "value". For example
+to set the \fBfwhmpsf\fR to 2.0 type.
+
+.nf
+ \f(CW:fwhmpsf 2.0\fR
+.fi
+
+To display all the centering parameters type.
+
+.nf
+ \f(CW:show center\fR
+.fi
+
+Similarly the sky fitting and photometry parameters can be displayed by
+typing.
+
+.nf
+ \f(CW:show sky\fR
+ \f(CW:show phot\fR
+.fi
+
+All the parameters can be displayed with the following command.
+
+.nf
+ \f(CW:show\fR
+.fi
+
+.NH 3
+The i (Interactive Setup) Keystroke Command
+.PP
+This extremely useful key allows one to set up the principal APPHOT
+parameters interactively. To use this feature move the image cursor to a star on
+the display, or move the graphics cursor to a star on the contour plot
+and tap the i key,
+or enter the x and y coordinates, and the world coordinate system
+of the star and the i key manually. The program will query the user for
+the size of the extraction box and plot a radial profile of the star
+on the terminal. The user sets the \fBfwhmpsf\fR, the centering
+aperture \fBcbox\fR, the inner sky annulus \fBannulus\fR and \fBdannulus\fR,
+the list of apertures \fBaperts\fR and the data \fBsigma\fR,
+\fBthreshold\fR and \fBcthreshold\fR using the graphics cursor and the
+radial profile plot.
+The cursor comes up on the plot at the position of the appropriate parameter.
+Typing return will preserve the old value.
+If the cursor is outside the range of values on the plot the old value
+is kept.
+.PP
+Setting \fBsigma\fP, \fBcthreshold\fP, and \fBthreshold\fP
+interactively requires two keystrokes. In each case the measured parameter
+is the difference between the two y coordinates of the graphics
+cursor. It is recommended in general that the user leave \fBcthreshold\fP
+at zero.
+
+.NH 3
+The v (Verify) Keystroke Command
+.PP
+The v key verifies that the values of the critical task parameters
+currently in memory are the ones that the user wants. To each verify query
+the user either types CR to verify the current value or enters a new
+value.
+
+.NH 3
+The w (Write to Psets) Keystroke Command
+.PP
+The w key writes the current values of the parameters in memory to the
+appropriate psets.
+This feature is useful for saving values marked with the
+i key. On exiting APPHOT a prompt will remind the user that the current
+parameters in memory must be stored in the psets or lost.
+
+.NH 3
+The d (Radial Profile Plot) Keystroke Command
+.PP
+The d key plots a centered radial profile of a star on the graphics device.
+
+.NH 3
+The f (Fit) Keystroke Command
+.PP
+This key performs the default action of each APPHOT task without writing
+any results
+to the output file. In the \fBphot\fR task the f key will center, fit the
+local sky and compute the magnitudes for a star. This key allows the user to
+experiment interactively with the data, changing the default parameters,
+remeasuring magnitudes and so on before actually writing out any data.
+
+.NH 3
+The Space Bar (Fit and Write out Results) Keystroke Command
+.PP
+This key performs the default action of the task and writes the results
+to the output catalog.
+
+.NH
+Running Apphot In Interactive Mode From A Coordinate List
+.PP
+This is currently the best method for running APPHOT interactively for users
+without image cursor readback facilities. APPHOT tasks
+can pick stars out of the list sequentially or by number, measure stars
+sequentially or by number, rewind the coordinate lists and remeasure all
+the stars. Stars which are not in the coordinate list can still be
+measured and added to the output catalog.
+
+.IP [1]
+The :m (Move) Keystroke Command
+.RS
+.LP
+This command moves the cursor to the next or a specified star in the
+coordinate list. If the hardware cursor on the
+device being read from is enabled the actual physical cursor will move
+to the requested star. For
+example a user might decide that star # 10 in the coordinate list is the best
+setup star. He/she simply types a :m 10 to move to the star in
+question followed by the i key to setup the parameters interactively.
+.RE
+
+.IP [2]
+The :n (Next) Keystroke Command
+.RS
+.LP
+This command moves to the next or specified star in the list, performs the
+default action of the task and writes the results to the output file.
+This key is particularly useful in examining the results of a large batch
+run.
+For example, a user measures the magnitudes of 500 stars using APPHOT in
+batch mode. He/she is suspicious about the results for twenty of the most
+crowded stars. By rerunning APPHOT in interactive mode using the original
+coordinate list, the user can selectively call up the stars in question,
+plot their radial profiles, and examine the results interactively.
+.RE
+
+.IP [3]
+The l (List) Keystroke Command
+.RS
+.LP
+This command measures all the stars in the coordinate list sequentially from
+the current position in the file.
+.RE
+
+.IP [4]
+The r (Rewind) Keystroke Command
+.RS
+.LP
+This command rewinds the coordinate list.
+.RE
+
+.NH
+Running Apphot in Batch Mode
+.PP
+This is the simplest way to run APPHOT. Once the parameters are set and stored
+in the pset files the program can be run in batch by setting the parameter
+\fBinteractive\fR = no. The program will read the coordinate list
+sequentially computing results for each star and writing them to the
+output file.
+
+.NH
+Apphot Output
+.PP
+APPHOT tasks write their output to text and/or plot files as well as to the
+standard output and graphics terminals.
+
+.NH 2
+Text Files
+.PP
+All APPHOT records are written to text files.
+The parameters for the task are listed at the beginning of each APPHOT
+output text file and identified with a #K string.
+The header record is not written until the record
+for the first star is to be written to the database. Parameter changes will
+generate a one line entry in the output text file.
+The data records follow the header record in the order in which they
+were computed.
+If the output file parameter \fBoutput\fR = "" no output file is written.
+This is the default action for the \fBradprof\fR task.
+If \fBoutput\fR = "default",
+the output file name is constructed using the image name.
+
+.NH 2
+Plot Files
+.PP
+Some APPHOT tasks can optionally produce graphics output.
+These files are maintained as plot metacode and may contain many individual
+plots.
+A directory of plots in each metacode file can be obtained with
+\fBgkidir\fR. Individual plots can be extracted with \fBgkiextract\fR and
+combined and plotted with \fBgkimosaic\fR.
+
+.NH 2
+Running Apselect on Apphot Output Files
+.PP
+Individual fields can be extracted from the APPHOT output files using
+the \fBapselect\fR task and a keyword and expression scheme.
+For example the user may wish
+to extract the x and y center coordinates, the sky value and the
+magnitudes from the APPHOT \fBphot\fR catalog. Using apselect they
+would type.
+
+.nf
+ \f(CWcl> apselect output xc,yc,msky,mag yes > magsfile\fR
+.fi
+
+The selected fields would appear in the textfile "magsfile".
+
+.NH
+Apphot Recipes
+.PP
+In the following section three APPHOT reduction sessions which illustrate
+different methods of using the APPHOT package are described. In the
+first example the user wishes to compute magnitudes for a large number
+of stars in a single image. In the second example he/she wishes to
+measure the magnitude of a single standard star in each of a long list of
+images. Finally in the last example the user wishes to measure the
+magnitude of an elliptical galaxy through a list of apertures.
+Each example assumes that the user has started with the default set of
+package parameters.
+
+.NH 2
+Infrared photometry of a Star Field in Orion
+.PP
+An observer has an IRAF image on disk of a star forming region in Orion taken
+with the
+IR CCD camera. The Orion image is a composite formed from 64 separate
+IR images using the PROTO \fBirmosaic\fR and \fBiralign\fR tasks.
+The Orion image contains about 400 stars but is only moderately crowded. The
+observer decides to use the APPHOT package to reduce his data.
+.PP
+The observer decides to run the \fBdaofind\fR routines to create a coordinate
+list of stars, to run \fBphot\fR in interactive mode with the image cursor
+directed to the standard input to setup and store the \fBphot\fR task
+parameters and finally, to run \fBphot\fR in batch mode to do the photometry.
+.PP
+To create the coordinate list the user needs to supply the full width half
+maximum of the pointspread function and an intensity threshold
+above background to the
+\fBdaofind\fR program. Using the PLOT package task \fBimplot\fR the user
+examines several stars in the image and decides that the \fBfwhmpsf\fR
+should be 3.0
+pixels and that the standard deviation of the background should be 10.0
+counts.
+The user decides to include all stars with a peak intensity greater
+than five standard deviations above local background in the coordinate list.
+The user runs \fBdaofind\fR as follows.
+
+.nf
+ \f(CWap> daofind orion fwhmpsf=3.0 threshold=50.0\fR
+.fi
+
+The x and y coordinates, a magnitude estimate and some statistics on image
+sharpness and roundness are output to the file "orion.coo.1".
+The user can obtain a printout of the coordinate
+list by typing.
+
+.nf
+ \f(CWap> lprint orion.coo.1\fR
+.fi
+
+.PP
+Next the user decides to set up the parameters of the \fBphot\fR task.
+Using the \fBepar\fR task he enters the phot task parameter menu,
+types "orion" opposite the \fBimage\fR parameter and "orion.coo.1"
+opposite the \fBcoords\fR parameter. Next he moves the cursor opposite
+the \fBdatapars\fR parameter and types \fB:e\fR to enter the \fBdatapars\fR
+menu. He sets the gain parameter \fBepadu\fR to 5.0 electrons per adu
+and the readout noise \fBreadnoise\fR to 5.0 electrons. He types \fB:q\fR to
+quit and save the \fBdatapars\fR parameters and \fB^Z\fR to quit and save the
+\fBphot\fR parameters.
+.PP
+Now the user is ready to enter the \fBphot\fR task in interactive mode to set
+up the remaining data dependent parameters. The user types the following
+sequence of commands in response to the cursor prompt. Note that the
+example below assumes that the image cursor has been directed to the
+standard input. The image cursor comes up on the screen in the form of
+a prompt. This example could equally well be run from the image hardware
+cursor in which case the cursor would appear on the displayed image. The
+keystroke commands are identical in the two cases.
+
+.br
+
+.nf
+\f(CW
+ ap> phot orion
+
+ ... \fIload the phot task\fR ...
+
+ Image cursor [xcoord ycoord wcs] key [cmd]: ?
+
+ ... \fIprint help page for phot task\fR ...
+
+ Image cursor [xcoord ycoord wcs] key [cmd]: :radplots yes
+
+ ... \fIenable radial profile plotting\fR ...
+
+ Image cursor [xcoord ycoord wcs] key [cmd]: :m 10
+
+ ... \fImove to star 10 in the coordinate list\fR ...
+
+ Image cursor [xcoord ycoord wcs] key [cmd]: i
+
+ ... \fIenter interactive setup mode using star 10\fR ...
+
+ ... \fImark fwhmpsf, cbox, sky annulus, apertures on the plot\fR ...
+
+ ... \fIleave sigma and cthreshold at their default values\fR ...
+
+ ... \fIcheck answers on radial profile plot of the results\fR ...
+
+ Image cursor [xcoord ycoord wcs] key [cmd]: v
+
+ ... \fIverify the critical parameters\fR ...
+
+ Image cursor [xcoord ycoord wcs] key [cmd]: :radplots no
+
+ ... \fIdisable radial profile plotting\fR ...
+
+ Image cursor [xcoord ycoord wcs] key [cmd]: w
+
+ ... \fIstore new parameters in the psets\fR ...
+
+ Image cursor [xcoord ycoord wcs] key [cmd]: q
+
+ ... \fIquit interactive cursor loop\fR ...
+
+ q
+
+ ... \fIquit the phot task\fR ...
+
+\fR
+.fi
+.PP
+The user decides he is happy with the current parameter set and decides
+to run the \fBphot\fR task in batch and submit it as a background task.
+
+.nf
+ \f(CWap> phot orion inter- verify- &\fR
+.fi
+
+The results will appear in the text file "orion.mag.1".
+
+.NH 2
+Landolt Standards
+.PP
+The user has 100 UBVRI images of 20 Landolt Standards
+taken on a single night. These frames have been taken at various short
+exposures.
+The user wishes to process all this data
+in batch mode with the output records going to a single file.
+.PP
+The observer decides to run the \fBdaofind\fR task to create a coordinate
+list for each image, to run \fBphot\fR on a representative image
+in interactive mode with the image cursor
+directed to the standard input to set up and store the \fBphot\fR task
+parameters, and finally to run \fBphot\fR in batch mode on all the images
+to do the photometry.
+.PP
+Note that the example below assumes that the image cursor has been redirected
+to the standard input. The image cursor comes up on the screen in the
+form of a prompt. This example could equally well be run from the image
+hardware cursor in which case the cursor would appear on the displayed
+image. The keystroke commands are identical in the two cases.
+.PP
+To create the coordinate list the user needs to supply the full width half
+maximum of the point spread function and an intensity threshold above
+local background to the
+\fBdaofind\fR task. Using the PLOT package task \fBimplot\fR the user
+examines the Landolt standards in several images and decides that the
+average \fBfwhmpsf\fR is 4.3
+pixels and that the standard deviation of the background is 15.0 counts.
+Note that if the user has access to an image display \fBfwhmpsf\fP and
+\fBthreshold\fP can be determined interactively from inside the
+daofind task itself.
+The user decides to include all stars with a peak intensity greater
+than five standard deviations above local background in the coordinate list,
+which should include weak and spurious objects.
+The user runs \fBdaofind\fR as follows.
+
+.nf
+ \f(CWap> daofind lan*.imh fwhmpsf=4.3 threshold=75.0 verify- &\fP
+.fi
+
+The x and y coordinates, an initial guess at the magnitude and some
+sharpness and roundness characteristics are output to the files "lan*.coo.1".
+For example the image lan100350.imh will now have a corresponding
+coordinate file lan100350.coo;1. The user may wish at this point
+to quickly check the coordinate files for spurious objects.
+.PP
+Next the user decides to set up the parameters of the phot task.
+Using the \fBepar\fR task he enters the phot task parameter set,
+enters "lan100350b" opposite the \fBimage\fR parameter and "lan100350b.coo.1"
+opposite the \fBcoords\fR parameter. Next he moves the cursor opposite
+the \fBdatapars\fR parameter and types \fB:e\fR to enter the \fBdatapars\fR
+menu. He sets the gain parameter \fBepadu\fR to 10 electrons per adu
+and the readout noise \fBreadnoise\fR to 50.0 electrons.
+Finally in order to normalize all the magnitudes the user enters
+the image header exposure time keyword "itime" opposite the
+\fBexposure\fP parameter. He types \fB:q\fR to
+quit and save the \fBdatapars\fR parameters and \fB^Z\fR to quit and save the
+\fBphot\fR parameters.
+.PP
+Now the user is ready to enter the \fBphot\fR task in interactive mode to set
+up the remaining data dependent parameters. The user types the following
+sequence of commands in response to the cursor prompt.
+
+.nf
+\f(CW
+ ap> phot lan100350.imh
+
+ ... \fIload the phot task\fR ...
+
+ Image cursor [xcoord ycoord wcs] key [cmd]: ?
+
+ ... \fIprint help page for phot task\fR ...
+
+ Image cursor [xcoord ycoord wcs] key [cmd]: :radplots yes
+
+ ... \fIenable radial profile plotting\fR ...
+
+ Image cursor [xcoord ycoord wcs] key [cmd]: :m #n
+
+ ... \fImove to star n in the coordinate list\fR ...
+
+ Image cursor [xcoord ycoord wcs] key [cmd]: i
+
+ ... \fIenter interactive setup mode using star n\fR ...
+
+ ... \fImark fwhmpsf, cbox, sky annulus, apertures on the plot\fR ...
+
+ ... \fIleave sigma and cthreshold at their default values\fR ...
+
+ ... \fIcheck answers on radial profile plot of the results\fR ...
+
+ Image cursor [xcoord ycoord wcs] key [cmd]: v
+
+ ... \fIverify the critical parameters\fR ...
+
+ Image cursor [xcoord ycoord wcs] key [cmd]: :radplots no
+
+ ... \fIdisable radial profile plotting\fR ...
+
+ Image cursor [xcoord ycoord wcs] key [cmd]: w
+
+ ... \fIstore new parameters in the psets\fR ...
+
+ Image cursor [xcoord ycoord wcs] key [cmd]: q
+
+ ... \fIquit interactive cursor loop\fR ...
+
+ q
+
+ ... \fIquit the phot task\fR ...
+
+\fR
+.fi
+.PP
+Finally the user runs the \fBphot\fR task on the full list of images,
+with their corresponding parameter sets and dumps the output to a single
+text file named "output".
+
+.nf
+ \f(CWap> phot lan*.imh coords="lan*.coo.*" output=output veri- inter- &\fR
+.fi
+
+The results will appear in the text file "output".
+
+.NH 2
+Aperture Photometry of an Elliptical Galaxy
+.PP
+The user has a single image of the elliptical galaxy N315. She
+wishes to measure the magnitude of this galaxy through a list of apertures
+equal to those published in a well known catalogue of photoelectric photometry.
+Her data has been sky subtracted to give an average background value of 0.0
+and the standard deviation of the sky background is 20.0 counts.
+From the published aperture photometry
+and the scale of her telescope she knows that she wishes to measure
+the galaxy through aperture radii of 10.5, 15.2, 20.8, and 25.6 arc seconds.
+.PP
+The user wishes to work in interactive mode using a contour plot
+of the image and the graphics cursor to enter commands to the \fBphot\fR
+task. She therefore sets the image cursor to "stdgraph" as follows.
+
+.nf
+ \f(CWap> set stdimcur = stdgraph\fR
+.fi
+
+.PP
+Next she makes a contour plot of the image and writes it to
+a plot metacode file as follows.
+
+.nf
+\f(CW
+ ap> contour N315
+
+ ... \fIcontour plot appears on the terminal\fR ...
+
+ ap> =gcur
+
+ ... \fIenter cursor mode\fR ...
+
+ :.write n315.plot
+
+ ... \fIwrite the plot to a file\fR ...
+
+ q
+
+ ... \fIexit cursor mode\fR ...
+
+\fR
+.fi
+.PP
+Now the user is ready to set up the parameters of the \fBphot\fR task.
+Since she already knows the values of the parameters she wishes to use
+she types
+
+.nf
+ \f(CWap> epar phot\fR
+.fi
+
+to enter the phot task menu. She positions the cursor opposite
+\fBimage\fR parameter and types "N315", opposite \fBdispay\fR and
+types "stdgraph".
+Next she moves the cursor opposite
+the \fBdatapars\fR parameter and types \fB:e\fR to enter the \fBdatapars\fR
+menu. She makes sure that \fBscale =\fP 0.75 arc-seconds per pixel the scale
+of the telescope, sets the standard deviation
+of the sky background \fBsigma\fR to 20.0, sets the gain
+parameter \fBepadu\fR to 5 electrons per adu
+and the readout noise \fBreadnoise\fR to 5.0 electrons. She types \fB:q\fR to
+quit and save the \fBdatapars\fR parameters. She decides to leave the
+centering parameters in \fBcenterpars\fR at their default values.
+\fBCbox\fP in particular will be 5.0 arcseconds wide. The user
+has already removed a low order polynomial sky background from this image.
+She wishes to fix the sky value at 0.0. She moves the cursor opposite
+the \fBfitskypars\fR parameter and types \fB:e\fR to enter the sky fitting menu.
+She types "constant" opposite the \fBsalgorithm\fR parameter, "0.0"
+opposite the \fBskyvalue\fR parameter and \fB:e\fR to exit
+the sky fitting parameter menu. Finally she enters the \fBphotpars\fR
+menu and enters the aperture string "10.5,15.2,20.8,25.6" opposite
+the \fBapert\fR parameter.
+.PP
+To measure the galaxy she types
+
+.nf
+ \f(CWap> phot N315\fR
+.fi
+
+to enter the phot task, positions the cursor on the center of the
+galaxy in the contour plot and taps the space bar to make the measurement.
+The results are written to the file "N315.mag.1".
diff --git a/noao/digiphot/apphot/doc/wphot.hlp b/noao/digiphot/apphot/doc/wphot.hlp
new file mode 100644
index 00000000..69bfd7c7
--- /dev/null
+++ b/noao/digiphot/apphot/doc/wphot.hlp
@@ -0,0 +1,780 @@
+.help wphot May00 noao.digiphot.apphot
+.ih
+NAME
+wphot -- perform weighted aperture photometry on a list of stars
+.ih
+USAGE
+wphot image
+.ih
+PARAMETERS
+.ls image
+The list of images containing the objects to be measured.
+.le
+.ls skyfile = ""
+The list of text files containing the sky values, of the measured objects,
+one object per line with x, y, the sky value, sky sigma, sky skew, number of sky
+pixels and number of rejected sky pixels in columns one to seven respectively.
+The number of sky files must be zero, one, or equal to the number of input
+images. A skyfile value is only requested if \fIfitskypars.salgorithm\fR =
+"file" and if WPHOT is run non-interactively.
+.le
+.ls coords = ""
+The list of text files containing initial coordinates for the objects to
+be centered. Objects are listed in coords one object per line with the
+initial coordinate values in columns one and two. The number of coordinate
+files must be zero, one, or equal to the number of images. If coords is
+"default", "dir$default", or a directory specification then a coords file name
+of the form dir$root.extension.version is constructed, where dir is the
+directory, root is the root image name, extension is "coo" and version is
+the next available version number for the file.
+.le
+.ls output = "default"
+The name of the results file or results directory. If output is
+"default", "dir$default", or a directory specification then an output file name
+of the form dir$root.extension.version is constructed, where dir is the
+directory, root is the root image name, extension is "omag" and version is
+the next available version number for the file. The number of output files
+must be zero, one, or equal to the number of image files. In both interactive
+and batch mode full output is written to output. In interactive mode
+an output summary is also written to the standard output.
+.le
+.ls plotfile = ""
+The name of the file containing radial profile plots of the stars written
+to the output file. If plotfile is defined then a radial profile plot
+is written to plotfile every time a record is written to \fIoutput\fR.
+The user should be aware that this can be a time consuming operation.
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters. The critical
+parameters \fIfwhmpsf\fR and \fIsigma\fR are located here. If \fIdatapars\fR
+is undefined then the default parameter set in uparm directory is used.
+.le
+.ls centerpars = ""
+The name of the file containing the centering parameters. The critical
+parameters \fIcalgorithm\fR and \fIcbox\fR are located here.
+If \fIcenterpars\fR is undefined then the default parameter set in
+uparm directory is used.
+.le
+.ls fitskypars = ""
+The name of the text file containing the sky fitting parameters. The critical
+parameters \fIsalgorithm\fR, \fIannulus\fR, and \fIdannulus\fR are located here.
+If \fIfitskypars\fR is undefined then the default parameter set in uparm
+directory is used.
+.le
+.ls photpars = ""
+The name of the file containing the photometry parameters. The critical
+parameter \fIapertures\fR is located here. If \fIphotpars\fR is undefined
+then the default parameter set in uparm directory is used.
+.le
+.ls interactive = yes
+Run the task interactively ?
+.le
+.ls radplots = no
+If \fIradplots\fR is "yes" and PHOT is run in interactive mode, a radial
+profile of each star is plotted on the screen after the star is measured.
+.le
+.ls icommands = ""
+The image display cursor or image cursor command file.
+.le
+.ls gcommands = ""
+The graphics cursor or graphics cursor command file.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout"
+The coordinate system of the input coordinates read from \fIcoords\fR and
+of the output coordinates written to \fIoutput\fR respectively. The image
+header coordinate system is used to transform from the input coordinate
+system to the "logical" pixel coordinate system used internally,
+and from the internal "logical" pixel coordinate system to the output
+coordinate system. The input coordinate system options are "logical", tv",
+"physical", and "world". The output coordinate system options are "logical",
+"tv", and "physical". The image cursor coordinate system is assumed to
+be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin and wcsout are "logical" and "logical" respectively.
+.le
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default cacheing is
+disabled.
+.le
+.ls verify = ")_.verify"
+Verify the critical parameters in non-interactive mode. Verify may be set to
+the apphot package parameter value (the default), "yes", or "no".
+.le
+.ls update = ")_.update"
+Update the critical parameters in non-interactive mode if verify is yes.
+Update may be set to the apphot package parameter value (the default), "yes",
+or "no".
+
+.le
+.ls verbose = ")_.verbose"
+Print messages on the terminal about actions taken in non-interactive mode.
+Verbose may be set to the apphot package parameter value (the default), "yes",
+or "no".
+.le
+.ls graphics = ")_.graphics"
+The default graphics device. Graphics may be set to the apphot package
+parameter value (the default), "yes", or "no".
+
+.le
+.ls display = ")_.display"
+The default display device. Graphics may be set to the apphot package
+parameter value (the default), "yes", or "no. By default graphics overlay
+is disabled. Setting display to one of "imdr", "imdg", "imdb", or "imdy"
+enables graphics overlay with the IMD graphics kernel. Setting display to
+"stdgraph" enables WPHOT to work interactively from a contour plot.
+.le
+
+.ih
+DESCRIPTION
+WPHOT computes accurate centers, sky values, and weighted magnitudes for a
+list of objects in the IRAF image \fIimage\fR whose initial coordinates are read
+from the text file \fIcoords\fR or image display cursor, and writes the
+computed x and y coordinates, sky values and magnitudes to the text file
+\fIoutput\fR.
+
+The coordinates read from \fIcoords\fR are assumed to be in coordinate
+system defined by \fIwcsin\fR. The options are "logical", "tv", "physical",
+and "world" and the transformation from the input coordinate system to
+the internal "logical" system is defined by the image coordinate system.
+The simplest default is the "logical" pixel system. Users working on with
+image sections but importing pixel coordinate lists generated from the parent
+image must use the "tv" or "physical" input coordinate systems.
+Users importing coordinate lists in world coordinates, e.g. ra and dec,
+must use the "world" coordinate system and may need to convert their
+equatorial coordinate units from hours and degrees to degrees and degrees first.
+
+The coordinates written to \fIoutput\fR are in the coordinate
+system defined by \fIwcsout\fR. The options are "logical", "tv",
+and "physical". The simplest default is the "logical" system. Users
+wishing to correlate the output coordinates of objects measured in
+image sections or mosaic pieces with coordinates in the parent
+image must use the "tv" or "physical" coordinate systems.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If cacheing
+is enabled and WPHOT is run interactively the first measurement will appear
+to take a long time as the entire image must be read in before the measurement
+is actually made. All subsequent measurements will be very fast because WPHOT
+is accessing memory not disk. The point of cacheing is to speed up random
+image access by making the internal image i/o buffers the same size as the
+image itself. However if the input object lists are sorted in row order and
+sparse cacheing may actually worsen not improve the execution time. Also at
+present there is no point in enabling cacheing for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of cacheing in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halfs of the image are alternated.
+
+In interactive mode the user may either define the list of objects to be
+measured interactively with the image cursor or create an object list prior
+to entering WPHOT. In either case the user may adjust the centering, sky
+fitting and photometry parameters until a satisfactory fit is achieved and
+only then store the final results in \fIoutput\fR. In batch
+mode the initial positions are read from the text file \fIcoords\fR
+or the image cursor parameter \fIicommands\fR is redirected to a text
+file containing a list of cursor commands.
+
+.ih
+CURSOR COMMANDS
+
+The following list of cursor commands are currently available.
+
+.nf
+ Interactive Photometry Commands
+
+? Print help
+: Colon commands
+v Verify the critical parameters
+w Store the current parameters
+d Plot radial profile of current star
+i Interactively set parameters using current star
+c Fit center of current star
+t Fit sky around the cursor
+a Average sky values fit around several cursor positions
+s Fit sky around the current star
+p Do photometry for current star, using current sky
+o Do photometry for current star, using current sky, output results
+f Do photometry for current star
+spbar Do photometry for current star, output results
+m Move to next star in coordinate list
+n Do photometry for next star in coordinate list, output results
+l Do photometry for remaining stars in coordinate list, output results
+r Rewind the coordinate list
+e Print error messages
+q Exit task
+
+
+ Colon Commands
+
+:show [data/center/sky/fit] Show parameters
+:m [n] Move to next [nth] star in the coordinate list
+:n [n] Do photometry for next [nth] star in coordinate list, output results
+
+
+ Colon Parameter Editing Commands
+
+# Image and file parameters
+
+:image [string] Image name
+:coords [string] Coordinate file name
+:output [string] Output file name
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Full-width half-maximum of PSF (scale units)
+:emission [y/n] Emission features (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good pixel value (counts)
+:datamax [value] Maximum good pixel value (counts)
+
+# Noise parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per adu)
+:readnoise [value] Readout noise (electrons)
+
+# Observations parameters
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Integration time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observations (time units)
+
+# Centering algorithm parameters
+
+:calgorithm [string] Centering algorithm
+:cbox [value] Width of the centering box (scale units)
+:cthreshold [value] Centering intensity threshold (sigma)
+:cmaxiter [value] Maximum number of iterations
+:maxshift [value] Maximum center shift (scale units)
+:minsnratio [value] Minimum S/N ratio for centering
+:clean [y/n] Clean subraster before centering
+:rclean [value] Cleaning radius (scale units)
+:rclip [value] Clipping radius (scale units)
+:kclean [value] Clean K-sigma rejection limit (sigma)
+
+# Sky fitting algorithm parameters
+
+:salgorithm [string] Sky fitting algorithm
+:skyvalue [value] User supplied sky value (counts)
+:annulus [value] Inner radius of sky annulus (scale units)
+:dannulus [value] Width of sky annulus (scale units)
+:khist [value] Sky histogram extent (+/- sigma)
+:binsize [value] Resolution of sky histogram (sigma)
+:smooth [y/n] Lucy smooth the sky histogram
+:sloclip [value] Low-side clipping factor in percent
+:shiclip [value] High-side clipping factor in percent
+:smaxiter [value] Maximum number of iterations
+:snreject [value] Maximum number of rejection cycles
+:sloreject [value] Low-side pixel rejection limits (sky sigma)
+:shireject [value] High-side pixel rejection limits (sky sigma)
+:rgrow [value] Region growing radius (scale units)
+
+# Photometry parameters
+
+:weighting [string] Weighting function (constant|cone|gauss)
+:apertures [string] List of aperture radii (scale units)
+:zmag [value] Zero point of magnitude scale
+
+# Plotting and marking parameters
+
+:mkcenter [y/n] Mark computed centers on display
+:mksky [y/n] Mark the sky annuli on the display
+:mkapert [y/n] Mark apertures on the display
+:radplot [y/n] Plot radial profile of object
+
+
+
+The following commands are available from inside the interactive setup menu.
+
+
+ Interactive Phot/Wphot Setup Menu
+
+ v Mark and verify the critical parameters (f,s,c,a,d,r)
+
+ f Mark and verify the full-width half-maximum of psf
+ s Mark and verify the standard deviation of the background
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
+
+ c Mark and verify the centering box width
+ n Mark and verify the cleaning radius
+ p Mark and verify the clipping radius
+
+ a Mark and verify the inner radius of the sky annulus
+ d Mark and verify the width of the sky annulus
+ g Mark and verify the region growing radius
+
+ r Mark and verify the aperture radii
+.fi
+
+.ih
+ALGORITHMS
+
+WPHOT computes accurate centers for each object using the centering
+parameters defined in the CENTERPARS task, computes an accurate sky value
+for each object using the sky fitting parameters defined in FITSKYPARS task,
+and computes magnitudes using the photometry parameters defined in the
+PHOTPARS task. The data dependent parameter are defined in the DATAPARS task.
+
+Three weighting functions are currently supported: constant, cone and gauss.
+Constant weighting, the default gives identical results to the PHOT task.
+Pixels are weighted by the fraction of their area inside the circular
+aperture. For cone and gauss weighting an additional triangular or gaussian
+weighting function of full width half maximum equal to \fIfwhmpsf\fR is
+applied to the pixels before aperture summing.
+
+This task is currently experimental. Further algorithm work is required.
+
+.ih
+OUTPUT
+
+In interactive mode the following quantities are printed on the standard
+output as each object is measured. Error is a simple string which
+indicates whether the task encountered any errors in the
+the centering algorithm, the sky fitting algorithm or the photometry
+algorithm. Mag and merr are the magnitudes and errors in
+apertures 1 through N respectively and xcenter, ycenter and msky are the
+x and y centers and the sky value respectively.
+
+.nf
+ image xcenter ycenter msky mag[1 ... N] error
+.fi
+
+In both interactive and batch mode full output is written to the text file
+\fIoutput\fR. At the beginning of each file is a header listing the
+current values of the parameters when the first stellar record was written.
+These parameters can be subsequently altered. For each star measured the
+following record is written
+
+.nf
+ image xinit yinit id coords lid
+ xcenter ycenter xshift yshift xerr yerr cier error
+ msky stdev sskew nsky nsrej sier serror
+ itime xairmass ifilter otime
+ rapert sum area flux mag merr pier perr
+.fi
+
+Image and coords are the name of the image and coordinate file respectively.
+Id and lid are the sequence numbers of stars in the output and coordinate
+files respectively. Cier and cerror are the error code and accompanying
+error message respectively. Xinit, yinit, xcenter, ycenter, xshift, yshift,
+and xerr, yerr are self explanatory and output in pixel units. The sense of
+the xshift and yshift definitions is the following.
+
+.nf
+ xshift = xcenter - xinit
+ yshift = ycenter - yinit
+.fi
+
+Sier and serror are the error code and accompanying error message respectively.
+Msky, stdev and sskew are the best estimate of the sky value (per pixel),
+standard deviation and skew respectively. Nsky and nsrej are the number of
+sky pixels and the number of sky pixels rejected respectively.
+
+Itime is the exposure time, xairmass is self-evident, ifilter is an id
+string identifying the filter used during the observation, and otime is
+a string specifying the time of the observation in whatever units the
+user has defined.
+
+Rapert, sum, area, and flux are the radius of the aperture in pixels, the total
+number of counts including sky in the aperture, the area of the aperture
+in square pixels, and the total number of counts in the aperture excluding
+sky. Mag and merr are the magnitude and error in the magnitude
+in the aperture (see below).
+
+.nf
+ flux = sum - area * msky
+ mag = zmag - 2.5 * log10 (flux) + 2.5 * log10 (itime)
+ merr = 1.0857 * error / flux
+ error = sqrt (flux / epadu + area * stdev**2 +
+ area**2 * stdev**2 / nsky)
+.fi
+
+Pier and perror are photometry error code and accompanying error message.
+
+In interactive mode a radial profile of each measured object is plotted
+in the graphics window if \fIradplots\fR is "yes".
+
+In interactive and batchmode a radial profile plot is written to
+\fIplotfile\fR if it is defined each time the result of an object
+measurement is written to \fIoutput\fR .
+
+.ih
+ERRORS
+If the object centering was error free then the field cier will be zero.
+Non-zero values of cier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 101 # The centering box is off image
+ 102 # The centering box is partially off the image
+ 103 # The S/N ratio is low in the centering box
+ 104 # There are two few points for a good fit
+ 105 # The x or y center fit is singular
+ 106 # The x or y center fit did not converge
+ 107 # The x or y center shift is greater than maxshift
+ 108 # There is bad data in the centering box
+.fi
+
+If all goes well during the sky fitting process then the error code sier
+will be 0. Non-zero values of sier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 201 # There are no sky pixels in the sky annulus
+ 202 # Sky annulus is partially off the image
+ 203 # The histogram of sky pixels has no width
+ 204 # The histogram of sky pixels is flat or concave
+ 205 # There are too few points for a good sky fit
+ 206 # The sky fit is singular
+ 207 # The sky fit did not converge
+ 208 # The graphics stream is undefined
+ 209 # The file of sky values does not exist
+ 210 # The sky file is at EOF
+ 211 # Cannot read the sky value correctly
+ 212 # The best fit parameter are non-physical
+.fi
+
+If no error occurs during the measurement of the magnitudes then pier is
+0. Non-zero values of pier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 301 # The aperture is off the image
+ 302 # The aperture is partially off the image
+ 303 # The sky value is undefined
+ 305 # There is bad data in the aperture
+.fi
+
+.ih
+EXAMPLES
+
+1. Compute the magnitudes for a few stars in dev$ypix using the display
+and the image cursor. Setup the task parameters using the interactive
+setup menu defined by the i key command and a radial profile plot.
+
+.nf
+ ap> display dev$ypix 1 fi+
+
+ ... display the image
+
+ ap> wphot dev$ypix
+
+ ... type ? to print an optional help page
+
+ ... move the image cursor to a star
+ ... type i to enter the interactive setup menu
+ ... enter maximum radius in pixels of the radial profile or hit
+ CR to accept the default
+ ... set the fwhmpsf, centering radius, inner and outer sky annuli,
+ photometry apertures, and sigma using the graphics cursor and the
+ stellar radial profile plot
+ ... typing <CR> leaves everything at the default value
+ ... type q to quit the setup menu
+
+ ... type the v key to verify the parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... move the image cursor to the stars of interest and tap
+ the space bar
+
+ ... a one line summary of the fitted parameters will appear on the
+ standard output for each star measured
+
+ ... type q to quit and q again to confirm the quit
+
+ ... the output will appear in ypix.omag.1
+.fi
+
+2. Compute the magnitudes for a few stars in dev$ypix using a contour plot
+and the graphics cursor. This option is only useful for those (now very few)
+users who have access to a graphics terminal but not to an image display
+server. Setup the task parameters using the interactive setup menu defined by
+the i key command as in example 1.
+
+.nf
+ ap> show stdimcur
+
+ ... record the default value of stdimcur
+
+ ap> set stdimcur = stdgraph
+
+ ... define the image cursor to be the graphics cursor
+
+ ap> contour dev$ypix
+
+ ... make a contour plot of dev$ypix
+
+ ap> contour dev$ypix >G ypix.plot1
+
+ ... store the contour plot of dev$ypix in the file ypix.plot1
+
+ ap> wphot dev$ypix display=stdgraph
+
+ ... type ? to get an optional help page
+
+ ... move graphics cursor to a star
+ ... type i to enter the interactive setup menu
+ ... enter maximum radius in pixels of the radial profile or CR
+ to accept the default value
+ ... set the fwhmpsf, centering radius, inner and outer sky annuli,
+ apertures, and sigma using the graphics cursor and the
+ stellar radial profile plot
+ ... typing <CR> leaves everything at the default value
+ ... type q to quit the setup menu
+
+ ... type the v key to verify the critical parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... retype :.read ypix.plot1 to reload the contour plot
+
+ ... move the graphics cursor to the stars of interest and tap
+ the space bar
+
+ ... a one line summary of the fitted parameters will appear on the
+ standard output for each star measured
+
+ ... type q to quit and q again to verify
+
+ ... full output will appear in the text file ypix.omag.2
+
+ ap> set stdimcur = <default>
+
+ ... reset stdimcur to its previous value
+.fi
+
+
+3. Setup and run PHOT interactively on a list of objects temporarily
+overriding the fwhmpsf, sigma, cbox, annulus, dannulus, and apertures
+parameters determined in examples 1 or 2.
+
+.nf
+ ap> daofind dev$ypix fwhmpsf=2.6 sigma=25.0 verify-
+
+ ... make a coordinate list
+
+ ... the output will appear in the text file ypix.coo.1
+
+ ap> wphot dev$ypix cbox=7.0 annulus=12.0 dannulus=5.0 \
+ apertures="3.0,5.0" coords=ypix.coo.1
+
+ ... type ? for optional help
+
+
+ ... move the graphics cursor to the stars and tap space bar
+
+ or
+
+ ... select stars from the input coordinate list with m / :m #
+ and measure with spbar
+
+ ... measure stars selected from the input coordinate list
+ with n / n #
+
+ ... a one line summary of results will appear on the standard output
+ for each star measured
+
+ ... type q to quit and q again to confirm the quit
+
+ ... the output will appear in ypix.omag.3 ...
+.fi
+
+
+4. Display and measure some stars in an image section and write the output
+coordinates in the coordinate system of the parent image.
+
+.nf
+ ap> display dev$ypix[150:450,150:450] 1
+
+ ... display the image section
+
+ ap> wphot dev$ypix[150:450,150:450] wcsout=tv
+
+ ... move cursor to stars and type spbar
+
+ ... type q to quit and q again to confirm quit
+
+ ... output will appear in ypix.omag.4
+
+ ap> pdump ypix.omag.4 xc,yc yes | tvmark 1 STDIN col=204
+.fi
+
+
+5. Run PHOT in batch mode using the coordinate file and the previously
+saved parameters. Verify the critical parameters.
+
+.nf
+ ap> wphot dev$ypix coords=ypix.coo.1 verify+ inter-
+
+ ... output will appear in ypix.omag.5 ...
+.fi
+
+
+6. Repeat example 5 but assume that the input coordinate are ra and dec
+in degrees and degrees, turn off verification, and submit the task to to
+the background.
+
+.nf
+ ap> display dev$ypix 1
+
+ ap> rimcursor wcs=world > radec.coo
+
+ ... move to selected stars and type any key
+
+ ... type ^Z to quit
+
+ ap> wphot dev$ypix coords=radec.coo wcsin=world verify- inter- &
+
+ ... output will appear in ypix.omag.6
+
+ ap> pdump ypix.omag.6 xc,yc yes | tvmark 1 STDIN col=204
+
+ ... mark the stars on the display
+.fi
+
+
+7. Run PHOT interactively without using the image display.
+
+.nf
+ ap> show stdimcur
+
+ ... record the default value of stdimcur
+
+ ap> set stdimcur = text
+
+ ... set the image cursor to the standard input
+
+ ap> wphot dev$ypix coords=ypix.coo.1
+
+ ... type ? for optional help
+
+ ... type :m 3 to set the initial coordinates to those of the
+ third star in the list
+
+ ... type i to enter the interactive setup menu
+ ... enter the maximum radius in pixels for the radial profile or
+ accept the default with a CR
+ ... type v to enter the default menu
+ ... set the fwhmpsf, centering radius, inner and outer sky annuli,
+ apertures, and sigma using the graphics cursor and the
+ stellar radial profile plot
+ ... typing <CR> after the prompt leaves the parameter at its default
+ value
+ ... type q to quit the setup menu
+
+ ... type r to rewind the coordinate list
+
+ ... type l to measure all the stars in the coordinate list
+
+ ... a one line summary of the answers will appear on the standard
+ output for each star measured
+
+ ... type q to quit followed by q to confirm the quit
+
+ ... full output will appear in the text file ypix.omag.7
+
+ ap> set stdimcur = <default>
+
+ ... reset the value of stdimcur
+.fi
+
+
+8. Use a image cursor command file to drive the PHOT task. The cursor command
+file shown below sets the cbox, annulus, dannulus, and apertures parameters
+computes the centers, sky values, and magnitudes for 3 stars, updates the
+parameter files, and quits the task.
+
+.nf
+ ap> type cmdfile
+ : cbox 9.0
+ : annulus 12.0
+ : dannulus 5.0
+ : apertures 5.0
+ 442 410 101 \040
+ 349 188 101 \040
+ 225 131 101 \040
+ w
+ q
+
+ ap> wphot dev$ypix icommands=cmdfile verify-
+
+ ... full output will appear in ypix.omag.8
+.fi
+
+
+
+
+.ih
+BUGS
+This task is experimental and requires more work.
+
+It is currently the responsibility of the user to make sure that the
+image displayed in the frame is the same as that specified by the image
+parameter.
+
+Commands which draw to the image display are disabled by default.
+To enable graphics overlay on the image display, set the display
+parameter to "imdr", "imdg", "imdb", or "imdy" to get red, green,
+blue or yellow overlays and set the centerpars mkcenter switch to
+"yes", the fitskypars mksky switch to"yes", or the photpars mkapert
+witch to "yes". It may be necessary to run gflush and to redisplay the image
+to get the overlays position correctly.
+
+
+.ih
+SEE ALSO
+datapars, centerpars, fitskypars, photpars, qphot, phot, polyphot
+.endhelp
diff --git a/noao/digiphot/apphot/findpars.par b/noao/digiphot/apphot/findpars.par
new file mode 100644
index 00000000..f357fd76
--- /dev/null
+++ b/noao/digiphot/apphot/findpars.par
@@ -0,0 +1,12 @@
+# FINDPARS
+
+threshold,r,h,4.0,,,Threshold in sigma for feature detection
+nsigma,r,h,1.5,,,Width of convolution kernel in sigma
+ratio,r,h,1.0,0.0,1.0,Ratio of minor to major axis of Gaussian kernel
+theta,r,h,0.0,0.0,180.0,Position angle of major axis of Gaussian kernel
+sharplo,r,h,.2,,,Lower bound on sharpness for feature detection
+sharphi,r,h,1.0,,,Upper bound on sharpness for feature detection
+roundlo,r,h,-1.0,,,Lower bound on roundness for feature detection
+roundhi,r,h,1.0,,,Upper bound on roundness for feature detection
+mkdetections,b,h,no,,,Mark detected stars on the display ?
+mode,s,h,'ql'
diff --git a/noao/digiphot/apphot/fitpsf.par b/noao/digiphot/apphot/fitpsf.par
new file mode 100644
index 00000000..d578683b
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf.par
@@ -0,0 +1,24 @@
+# FITPSF
+
+image,f,a,,,,"The input image(s)"
+box,r,a,,,,"The fitting box width in scale units"
+coords,f,h,"",,,"The input coordinate list(s) (default: image.coo.?)"
+output,f,h,"default",,,"The output fit file(s) (default: image.psf.?)"
+datapars,pset,h,"",,,"Data dependent parameters"
+function,s,h,"radgauss","|radgauss|elgauss|moments|",,"The fitting function"
+maxiter,i,h,50,,,"The maximum number of fitting iterations"
+nreject,i,h,0,,,"The maximum number of rejection cycles"
+kreject,r,h,3.0,,,The K-sigma rejection limit"
+mkbox,b,h,no,,,"Draw the fitting box on the display ?"
+interactive,b,h,yes,,,"Interactive mode ?"
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor: [x y wcs] key [cmd]"
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the input image pixels in memory ?"
+verify,b,h,)_.verify,,,"Verify critical parameters in non-interactive mode ?"
+update,b,h,)_.update,,,"Update critical parameters in non-interactive mode ?"
+verbose,b,h,)_.verbose,,,"Print messages in non-interactive mode ?"
+graphics,s,h,)_.graphics,,,"Graphics device"
+display,s,h,)_.display,,,"Display device"
+mode,s,h,'ql'
diff --git a/noao/digiphot/apphot/fitpsf/apbfitpsf.x b/noao/digiphot/apphot/fitpsf/apbfitpsf.x
new file mode 100644
index 00000000..9854ab9f
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/apbfitpsf.x
@@ -0,0 +1,95 @@
+include <fset.h>
+include "../lib/apphot.h"
+include "../lib/display.h"
+
+# APBFITPSF -- Procedure to fit a functional form to the PSF for a list of
+# objects.
+
+procedure apbfitpsf (ap, im, cl, out, gid, id, ld, interactive)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to IRAF image
+int cl # starlist file descriptor
+int out # output file descriptor
+pointer gid # image display stream
+int id # initial id
+int ld # list number
+int interactive # interactive mode
+
+int ier, ild, stdin
+pointer sp, str
+real wx, wy
+int fscan, nscan(), strncmp(), apsffit(), apstati()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+ call fstats (cl, F_FILENAME, Memc[str], SZ_FNAME)
+
+ # Initialize.
+ ild = ld
+
+ # Print query if input is STDIN.
+ if (strncmp ("STDIN", Memc[str], 5) == 0) {
+ stdin = YES
+ call printf ("Type object x and y coordinates (^Z or ^D to end): ")
+ call flush (STDOUT)
+ } else
+ stdin = NO
+
+ # Loop over the interesting objects.
+ while (fscan(cl) != EOF) {
+
+ # Decode the centers.
+ call gargr (wx)
+ call gargr (wy)
+ if (nscan () != 2) {
+ if (stdin == YES) {
+ call printf (
+ "Type object x and y coordinates (^Z or ^D to end): ")
+ call flush (STDOUT)
+ }
+ next
+ }
+
+ # Transform the input coordinates.
+ switch (apstati(ap,WCSIN)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_itol (ap, wx, wy, wx, wy, 1)
+ case WCS_TV:
+ call ap_vtol (im, wx, wy, wx, wy, 1)
+ default:
+ ;
+ }
+
+ # Store the current cursor coordinates.
+ call apsetr (ap, CWX, wx)
+ call apsetr (ap, CWY, wy)
+
+ # Fit the psf.
+ ier = apsffit (ap, im, wx, wy)
+
+ # Output the results.
+ if (interactive == YES) {
+ call ap_qppsf (ap, ier)
+ if (gid != NULL)
+ call appfmark (ap, gid, apstati (ap, MKPSFBOX))
+ }
+ if (id == 1)
+ call ap_param (ap, out, "fitpsf")
+ call ap_ppsf (ap, out, id, ild, ier)
+
+ # Prepare for the next object.
+ id = id + 1
+ ild = ild + 1
+ call apsetr (ap, WX, wx)
+ call apsetr (ap, WY, wy)
+ if (stdin == YES) {
+ call printf (
+ "Type object x and y coordinates (^D or ^Z to end): ")
+ call flush (STDOUT)
+ }
+
+ }
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/fitpsf/apfbuf.x b/noao/digiphot/apphot/fitpsf/apfbuf.x
new file mode 100644
index 00000000..428c30cb
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/apfbuf.x
@@ -0,0 +1,88 @@
+include <imhdr.h>
+include "../lib/apphotdef.h"
+include "../lib/fitpsfdef.h"
+include "../lib/fitpsf.h"
+
+# APFBUF -- Procedure to fetch the subraster of pixels to be fitted given the
+# pointer to the IRAF image, the coordinates of the center and the apphot
+# structure.
+
+int procedure apfbuf (ap, im, wx, wy)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to the IRAF image
+real wx, wy # center coordinates
+
+int ippix
+pointer psf
+real ppix
+pointer ap_psfpix()
+
+begin
+ # Check for 0 sized aperture.
+ psf = AP_PPSF(ap)
+ if (AP_PSFAPERT(psf) <= 0.0)
+ return (AP_NOPSFAREA)
+
+ # Get the PSF pixels.
+ ppix = max (1.0, AP_PSFAPERT(psf) * AP_SCALE(ap))
+ ippix = 2 * int (ppix) + 1
+ AP_PSFPIX(psf) = ap_psfpix (im, wx, wy, ippix, AP_PXC(psf), AP_PYC(psf),
+ AP_PNX(psf), AP_PNY(psf))
+ if (AP_PSFPIX(psf) == NULL)
+ return (AP_NOPSFAREA)
+ else if (AP_PNX(psf) < ippix || AP_PNY(psf) < ippix)
+ return (AP_PSF_OUTOFBOUNDS)
+ else
+ return (AP_OK)
+end
+
+
+# AP_PSFPIX -- Procedure to fetch the pixels to be used for centering.
+
+pointer procedure ap_psfpix (im, wx, wy, papert, xc, yc, nx, ny)
+
+pointer im # pointer to IRAF image
+real wx, wy # center of subraster to be extracted
+int papert # width of subraster to be extracted
+real xc, yc # center of extracted subraster
+int nx, ny # dimensions of extracted subraster
+
+int ncols, nlines, c1, c2, l1, l2, half_papert
+pointer buf
+real xc1, xc2, xl1, xl2
+pointer imgs2r()
+
+begin
+ # Check for nonsensical input.
+ half_papert = (papert - 1) / 2
+ if (half_papert <= 0)
+ return (NULL)
+
+ # Test for out of bounds pixels
+ ncols = IM_LEN(im,1)
+ nlines = IM_LEN(im,2)
+ xc1 = wx - half_papert
+ xc2 = wx + half_papert
+ xl1 = wy - half_papert
+ xl2 = wy + half_papert
+ if (xc1 > real (ncols) || xc2 < 1.0 || xl1 > real (nlines) || xl2 < 1.0)
+ return (NULL)
+
+ # Get column and line limits, dimensions and center of subraster.
+ c1 = max (1.0, min (real (ncols), xc1)) + 0.5
+ c2 = min (real (ncols), max (1.0, xc2)) + 0.5
+ l1 = max (1.0, min (real (nlines), xl1)) + 0.5
+ l2 = min (real (nlines), max (1.0, xl2)) + 0.5
+ nx = c2 - c1 + 1
+ ny = l2 - l1 + 1
+ xc = wx - c1 + 1
+ yc = wy - l1 + 1
+
+ # Get pixels and return.
+ buf = imgs2r (im, c1, c2, l1, l2)
+ if (buf == EOF)
+ return (NULL)
+ else
+ return (buf)
+end
diff --git a/noao/digiphot/apphot/fitpsf/apfitpsf.x b/noao/digiphot/apphot/fitpsf/apfitpsf.x
new file mode 100644
index 00000000..94957b6a
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/apfitpsf.x
@@ -0,0 +1,344 @@
+include <ctype.h>
+include <gset.h>
+include <imhdr.h>
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/fitpsf.h"
+
+define HELPFILE "apphot$fitpsf/fitpsf.key"
+
+# APFITPSF -- Procedure to fit a functional form to the PSF for a list of
+# objects in interactive mode.
+
+int procedure apfitpsf (ap, im, cl, gd, id, out, stid, interactive, cache)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to IRAF image
+int cl # starlist file descriptor
+pointer gd # graphics pointer
+pointer id # display pointer
+int out # output file descriptor
+int stid # output file sequence number
+int interactive # interactive mode
+int cache # cache the input image pixels
+
+real wx, wy, xlist, ylist
+pointer sp, cmd
+int wcs, key, newimage, newbuf, newfit, newlist, ltid, ier
+int ip, oid, colonkey, prev_num, req_num, buf_size, req_size, old_size
+int memstat
+
+real apstatr()
+int clgcur(), apgscur(), apsffit(), apsfrefit(), apstati()
+int apgqverify(), apgtverify(), ctoi(), apnew(), ap_memstat(), sizeof()
+
+define endswitch_ 99
+
+begin
+ # Initialize.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Initialize the cursor commands.
+ key = ' '
+ Memc[cmd] = EOS
+
+ # Initialize the fitting commands.
+ newimage = NO
+ newbuf = YES
+ newfit = YES
+ ier = AP_OK
+
+ # Initialize the sequencing.
+ newlist = NO
+ ltid = 0
+
+ # Loop over the cursor commands.
+ while (clgcur ("icommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+
+ # Store the cursor coordinates
+ call ap_vtol (im, wx, wy, wx, wy, 1)
+ call apsetr (ap, CWX, wx)
+ call apsetr (ap, CWY, wy)
+
+ # Test to see if the cursor moved.
+ if (apnew (ap, wx, wy, xlist, ylist, newlist) == YES) {
+ newbuf = YES
+ newfit = YES
+ }
+
+ # Loop over the cursor commands.
+ switch (key) {
+
+ # Quit.
+ case 'q':
+ if (interactive == YES) {
+ if (apgqverify ("fitpsf", ap, key) == YES) {
+ call sfree (sp)
+ return (apgtverify (key))
+ }
+ } else {
+ call sfree (sp)
+ return (NO)
+ }
+
+
+ # Print error messages.
+ case 'e':
+ if (interactive == YES)
+ call ap_pferrors (ap, ier)
+
+ # Print the help pages.
+ case '?':
+ if ((id != NULL) && (id == gd))
+ call gpagefile (id, HELPFILE, "")
+ else if (interactive == YES)
+ call pagefile (HELPFILE, "[space=morehelp,q=quit,?=help]")
+
+ # Rewind the list.
+ case 'r':
+ if (cl != NULL) {
+ call seek (cl, BOFL)
+ ltid = 0
+ } else if (interactive == YES)
+ call printf ("No coordinate list\n")
+
+ # Process the fitpsf colon commands.
+ case ':':
+ for (ip = 1; IS_WHITE(Memc[cmd+ip-1]); ip = ip + 1)
+ ;
+ colonkey = Memc[cmd+ip-1]
+
+ switch (colonkey) {
+ case 'm', 'n':
+
+ # Show/set fitpsf parameters.
+ if (Memc[cmd+ip] != EOS && Memc[cmd+ip] != ' ') {
+ call apsfcolon (ap, im, cl, out, stid, ltid, Memc[cmd],
+ newimage, newbuf, newfit)
+ goto endswitch_
+ }
+
+ # No coordinate list.
+ if (cl == NULL) {
+ if (interactive == YES)
+ call printf ("No coordinate list\n")
+ goto endswitch_
+ }
+
+ # Get next object from the list.
+ ip = ip + 1
+ prev_num = ltid
+ if (ctoi (Memc[cmd], ip, req_num) <= 0)
+ req_num = ltid + 1
+
+ # Fetch the next object from the list.
+ if (apgscur (cl, id, xlist, ylist, prev_num, req_num,
+ ltid) == EOF) {
+ if (interactive == YES)
+ call printf (
+ "End of coordinate list, use r key to rewind\n")
+ goto endswitch_
+ }
+
+ # Convert the coordinates.
+ switch (apstati (ap, WCSIN)) {
+ case WCS_PHYSICAL, WCS_WORLD:
+ call ap_itol (ap, xlist, ylist, xlist, ylist, 1)
+ case WCS_TV:
+ call ap_vtol (im, xlist, ylist, xlist, ylist, 1)
+ default:
+ ;
+ }
+
+ # Move to the next object.
+ newlist = YES
+ if (colonkey == 'm') {
+ newbuf = YES
+ newfit = YES
+ goto endswitch_
+ }
+
+ # Measure the next object.
+ ier = apsffit (ap, im, xlist, ylist)
+ if (id != NULL) {
+ call appfmark (ap, id, apstati (ap, MKPSFBOX))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ if (interactive == YES)
+ call ap_qppsf (ap, ier)
+ if (stid == 1)
+ call ap_param (ap, out, "fitpsf")
+ call ap_ppsf (ap, out, stid, ltid, ier)
+ stid = stid + 1
+ newbuf = NO
+ newfit = NO
+
+ default:
+ call apsfcolon (ap, im, cl, out, stid, ltid, Memc[cmd],
+ newimage, newbuf, newfit)
+ }
+
+ # Reestablish the image viewport and window.
+ if (newimage == YES) {
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[cmd], im, 4)
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+ }
+
+ newimage = NO
+
+ # Plot a centered stellar radial profile.
+ case 'd':
+ if (interactive == YES) {
+ call ap_qrad (ap, im, wx, wy, gd)
+ newbuf = YES
+ newfit = YES
+ }
+
+ # Verify the parameters interactively.
+ case 'v':
+ call ap_pfconfirm (ap, out, stid)
+ newbuf = YES
+ newfit = YES
+
+ # Interactively set up fitpsf parameters.
+ case 'i':
+ if (interactive == YES) {
+ call ap_pfradsetup (ap, im, wx, wy, gd, out, stid)
+ newbuf = YES
+ newfit = YES
+ }
+
+ # Save the parameters.
+ case 'w':
+ call ap_ppfpars (ap)
+
+ # Fit the PSF and save the results.
+ case 'f', ' ':
+ if (newbuf == YES)
+ ier = apsffit (ap, im, wx, wy)
+ else if (newfit == YES)
+ ier = apsfrefit (ap, im)
+ if (id != NULL) {
+ call appfmark (ap, id, apstati (ap, MKPSFBOX))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ if (interactive == YES)
+ call ap_qppsf (ap, ier)
+ newbuf = NO
+ newfit = NO
+
+ if (key == ' ') {
+ if (stid == 1)
+ call ap_param (ap, out, "fitpsf")
+ if (newlist == YES)
+ call ap_ppsf (ap, out, stid, ltid, ier)
+ else
+ call ap_ppsf (ap, out, stid, 0, ier)
+ stid = stid + 1
+ }
+
+
+ # Get, measure the next star in the coordinate list.
+ case 'm', 'n':
+
+ # No coordinate file.
+ if (cl == NULL) {
+ if (interactive == YES)
+ call printf ("No coordinate list\n")
+ goto endswitch_
+ }
+
+ prev_num = ltid
+ req_num = ltid + 1
+ if (apgscur (cl, id, xlist, ylist, prev_num, req_num,
+ ltid) == EOF) {
+ if (interactive == YES)
+ call printf (
+ "End of coordinate list, use r key to rewind\n")
+ goto endswitch_
+ }
+
+ # Convert coordinates if necessary.
+ switch (apstati (ap, WCSIN)) {
+ case WCS_PHYSICAL, WCS_WORLD:
+ call ap_itol (ap, xlist, ylist, xlist, ylist, 1)
+ case WCS_TV:
+ call ap_vtol (im, xlist, ylist, xlist, ylist, 1)
+ default:
+ ;
+ }
+
+ # Move to next object.
+ newlist = YES
+ if (key == 'm') {
+ newbuf = YES
+ newfit = YES
+ goto endswitch_
+ }
+
+ # Measure next object.
+ ier = apsffit (ap, im, xlist, ylist)
+ if (id != NULL) {
+ call appfmark (ap, id, apstati (ap, MKPSFBOX))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ if (interactive == YES)
+ call ap_qppsf (ap, ier)
+ if (stid == 1)
+ call ap_param (ap, out, "fitpsf")
+ call ap_ppsf (ap, out, stid, ltid, ier)
+ stid = stid + 1
+ newbuf = NO
+ newfit = NO
+
+ # Process the remainder of the coordinate list.
+ case 'l':
+ if (cl != NULL) {
+ oid = stid
+ ltid = ltid + 1
+ call apbfitpsf (ap, im, cl, out, id, stid, ltid, YES)
+ ltid = ltid + stid - oid + 1
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ } else if (interactive == YES)
+ call printf ("No coordinate list\n")
+
+ default:
+ # do nothing
+ call printf ("Unknown keystroke command\n")
+ }
+
+endswitch_
+ # Setup for the next object by setting the default keystroke
+ # command and storing the old cursor coordinates in the
+ # centering structure.
+
+ key = ' '
+ Memc[cmd] = EOS
+ call apsetr (ap, WX, apstatr (ap, CWX))
+ call apsetr (ap, WY, apstatr (ap, CWY))
+
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/fitpsf/apgpfpars.x b/noao/digiphot/apphot/fitpsf/apgpfpars.x
new file mode 100644
index 00000000..ed4b93ab
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/apgpfpars.x
@@ -0,0 +1,40 @@
+include "../lib/display.h"
+include "../lib/noise.h"
+include "../lib/fitpsf.h"
+
+# AP_GPFPARS -- Procedure to fetch the fitpsf parameters.
+
+procedure ap_gpfpars (ap)
+
+pointer ap # pointer to the apphot structure
+
+int function
+pointer sp, str
+bool clgetb()
+int clgeti(), btoi(), clgwrd()
+real clgetr()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Open the apphot structure.
+ call apsfinit (ap, AP_RADGAUSS, 3.5, 2.0, AP_NPOISSON)
+ call apsetr (ap, PSFAPERT, clgetr ("box") / 2.0)
+
+ # Get the data dependent parameters.
+ call ap_gdapars (ap)
+
+ # Get the rest of the FITPSF fitting parameters.
+ function = clgwrd ("function", Memc[str], SZ_LINE, PSFFUNCS)
+ call apsets (ap, PSFSTRING, Memc[str])
+ call apseti (ap, PSFUNCTION, function)
+ call apseti (ap, PMAXITER, clgeti ("maxiter"))
+ call apseti (ap, PNREJECT, clgeti ("nreject"))
+ call apsetr (ap, PK2, clgetr ("kreject"))
+
+ # Get the plotting parameters.
+ call apseti (ap, MKPSFBOX, btoi (clgetb ("mkbox")))
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/fitpsf/appfconfirm.x b/noao/digiphot/apphot/fitpsf/appfconfirm.x
new file mode 100644
index 00000000..30e111b2
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/appfconfirm.x
@@ -0,0 +1,58 @@
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/fitpsf.h"
+
+# AP_PFCONFIRM -- Procedure to confirm the critical fitpsf parameters.
+
+procedure ap_pfconfirm (ap, out, stid)
+
+pointer ap # pointer to the apphot structure
+int out # the output file descriptor
+int stid # the output file sequence number
+
+pointer sp, str
+real fwhmpsf, psfapert, datamin, datamax
+int apstati()
+real apstatr(), ap_vfwhmpsf(), ap_vpsfapert()
+real ap_vdatamin(), ap_vdatamax()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ call printf ("\n")
+
+ # Confirm the fitting function.
+ call ap_vpfstring (ap, Memc[str], SZ_FNAME)
+
+ # Confirm the fwhmpsf.
+ if (apstati (ap, PSFUNCTION) != AP_MOMENTS)
+ fwhmpsf = ap_vfwhmpsf (ap)
+ else
+ fwhmpsf = apstatr (ap, FWHMPSF)
+
+ # Confirm the fitting box.
+ psfapert = 2.0 * ap_vpsfapert (ap)
+
+ # Confirm the good data minimum and maximum values.
+ datamin = ap_vdatamin (ap)
+ datamax = ap_vdatamax (ap)
+
+ call printf ("\n")
+
+ # Update the database file.
+ if (out != NULL && stid > 1) {
+ call ap_sparam (out, KY_PSFSTRING, Memc[str], UN_PSFMODEL,
+ "psf fitting function")
+ call ap_rparam (out, KY_FWHMPSF, fwhmpsf, UN_ASCALEUNIT,
+ "full width half maximum of the psf")
+ call ap_rparam (out, KY_PSFAPERT, psfapert, UN_PSFSCALEUNIT,
+ "width of fitting box")
+ call ap_rparam (out, KY_DATAMIN, datamin, UN_ACOUNTS,
+ "minimum good data value")
+ call ap_rparam (out, KY_DATAMAX, datamax, UN_ACOUNTS,
+ "maximum good data value")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/fitpsf/appferrors.x b/noao/digiphot/apphot/fitpsf/appferrors.x
new file mode 100644
index 00000000..20ed8820
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/appferrors.x
@@ -0,0 +1,26 @@
+include "../lib/fitpsf.h"
+
+# AP_PFERRORS -- Print detailed fitpsf error messages on the standard output.
+
+procedure ap_pferrors (ap, ier)
+
+pointer ap # pointer to apphot structure (unused)
+int ier # integer error code
+
+begin
+ switch (ier) {
+ case AP_NOPSFAREA:
+ call printf (
+ "The psf fitting aperture is outside the image.\n")
+ case AP_PSF_OUTOFBOUNDS:
+ call printf (
+ "The psf fitting aperture is partially outside the image.\n")
+ case AP_NPSF_TOO_SMALL:
+ call printf (
+ "The number of data points is too few for psf fitting.\n")
+ case AP_PSF_SINGULAR:
+ call printf ("The psf fitting solution is singular.\n")
+ case AP_PSF_NOCONVERGE:
+ call printf ("The psf fitting solution did not converge.\n")
+ }
+end
diff --git a/noao/digiphot/apphot/fitpsf/appfradsetup.x b/noao/digiphot/apphot/fitpsf/appfradsetup.x
new file mode 100644
index 00000000..aaae9be6
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/appfradsetup.x
@@ -0,0 +1,86 @@
+define HELPFILE "apphot$fitpsf/ifitpsf.key"
+
+# AP_PFRADSETUP -- Procedure to set up fitpsf interactively
+
+procedure ap_pfradsetup (ap, im, wx, wy, gd, out, stid)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to to the IRAF image
+real wx, wy # cursor coordinates
+pointer gd # pointer to graphics stream
+int out # output file descriptor
+int stid # output file sequence number
+
+int ier, wcs, key
+pointer sp, cmd
+real xcenter, ycenter, rmin, rmax, imin, imax, xc, yc, rval
+real u1, u2, v1, v2, x1, x2, y1, y2
+
+int apsffit(), clgcur(), ap_showplot()
+real ap_cfwhmpsf(), ap_cpapert(), ap_cdatamin(), ap_cdatamax()
+
+begin
+ if (gd == NULL)
+ return
+ call greactivate (gd, 0)
+ call gclear (gd)
+
+ # Save old viewport and window coordinates
+ call ggview (gd, u1, u2, v1, v2)
+ call ggwind (gd, x1, x2, y1, y2)
+
+ # plot the radial profile.
+ if (ap_showplot (ap, im, wx, wy, gd, xcenter, ycenter, rmin, rmax,
+ imin, imax) == ERR) {
+ call gdeactivate (gd, 0)
+ return
+ }
+
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ call printf (
+ "Waiting for setup menu command (?=help, v=default setup, q=quit):\n")
+ while (clgcur ("gcommands", xc, yc, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+
+ switch (key) {
+
+ case 'q':
+ break
+ case '?':
+ call gpagefile (gd, HELPFILE, "")
+ case 'f':
+ rval = ap_cfwhmpsf (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'l':
+ rval = ap_cdatamin (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'u':
+ rval = ap_cdatamax (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'b':
+ rval = ap_cpapert (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'v':
+ rval = ap_cpapert (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_cfwhmpsf (ap, gd, out, stid, rmin, rmax, imin, imax)
+ default:
+ call printf ("Unknown or ambiguous keystroke command\007\n")
+ }
+ call printf (
+ "Waiting for setup menu command (?=help, v=default setup, q=quit):\n")
+ }
+
+ # Interactive setup is complete.
+ call printf (
+ "Interactive setup is complete. Type w to save parameters.\n")
+
+ # Restore old viewport and window coords.
+ call gsview (gd, u1, u2, v1, v2)
+ call gswind (gd, x1, x2, y1, y2)
+
+ call gdeactivate (gd, 0)
+ call sfree (sp)
+
+ # Fit the object.
+ ier = apsffit (ap, im, xcenter, ycenter)
+ call ap_qppsf (ap, ier)
+end
diff --git a/noao/digiphot/apphot/fitpsf/apppfpars.x b/noao/digiphot/apphot/fitpsf/apppfpars.x
new file mode 100644
index 00000000..58f40bcf
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/apppfpars.x
@@ -0,0 +1,34 @@
+include "../lib/fitpsf.h"
+include "../lib/display.h"
+
+# AP_PPFPARS -- Procedure to write the fitpsf parameters to a parameter file.
+
+procedure ap_ppfpars (ap)
+
+pointer ap # pointer to apphot structure
+
+pointer sp, str
+bool itob()
+int apstati()
+real apstatr()
+
+begin
+ # Initialize and open psets.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Store the psf fitting parameters.
+ call clputr ("box", 2.0 * apstatr (ap, PSFAPERT))
+ call apstats (ap, PSFSTRING, Memc[str], SZ_FNAME)
+ call clpstr ("function", Memc[str])
+ call clputi ("maxiter", apstati (ap, PMAXITER))
+ call clputr ("kreject", apstatr (ap, PK2))
+ call clputi ("nreject", apstati (ap, PNREJECT))
+ call clputb ("mkbox", itob (apstati (ap, MKPSFBOX)))
+
+ # Store the data dependent parameters.
+ call ap_dapars (ap)
+
+ # Closeup.
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/fitpsf/apppsf.x b/noao/digiphot/apphot/fitpsf/apppsf.x
new file mode 100644
index 00000000..c3604c87
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/apppsf.x
@@ -0,0 +1,123 @@
+include "../lib/apphotdef.h"
+include "../lib/fitpsfdef.h"
+include "../lib/apphot.h"
+include "../lib/fitpsf.h"
+
+# AP_PPSF -- Procedure to write the results of fitpsf to the output file.
+
+procedure ap_ppsf (ap, fd, id, lid, ier)
+
+pointer ap # pointer to apphot structure
+int fd # output file descriptor
+int id # sequence number of star
+int lid # list id of star
+int ier # comment string
+
+real apstatr()
+
+begin
+ # Initialize.
+ if (fd == NULL)
+ return
+
+ # Print the stars id.
+ call ap_wid (ap, fd, apstatr (ap, OPFXCUR), apstatr (ap, OPFYCUR), id,
+ lid, '\\')
+
+ # Print the parameters.
+ call ap_wfres (ap, fd, ier)
+end
+
+
+# AP_QPPSF -- Procedure to print the results of fitpsf on the standard output
+# in short form.
+
+procedure ap_qppsf (ap, ier)
+
+pointer ap # pointer to apphot structure
+int ier # comment string
+
+pointer sp, imname, psf
+
+begin
+ # Initialize.
+ call smark (sp)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+ psf = AP_PPSF(ap)
+
+ # Print the parameters on the standard output.
+ call apstats (ap, IMROOT, Memc[imname], SZ_FNAME)
+ switch (AP_PSFUNCTION(psf)) {
+ case AP_RADGAUSS:
+ call printf (
+ "%s %8.2f %8.2f %6.3f %8g %8g %s\n")
+ call pargstr (Memc[imname])
+ call pargr (Memr[AP_PPARS(psf)+1])
+ call pargr (Memr[AP_PPARS(psf)+2])
+ call pargr (Memr[AP_PPARS(psf)+3])
+ call pargr (Memr[AP_PPARS(psf)])
+ call pargr (Memr[AP_PPARS(psf)+4])
+ if (ier != AP_OK)
+ call pargstr ("err")
+ else
+ call pargstr ("ok")
+ case AP_ELLGAUSS:
+ call printf ("%s %8.2f %8.2f %6.3f %6.3f ")
+ call pargstr (Memc[imname])
+ call pargr (Memr[AP_PPARS(psf)+1])
+ call pargr (Memr[AP_PPARS(psf)+2])
+ call pargr (Memr[AP_PPARS(psf)+3])
+ call pargr (Memr[AP_PPARS(psf)+4])
+ call printf ("%6.1f %8g %8g %s\n")
+ call pargr (Memr[AP_PPARS(psf)+5])
+ call pargr (Memr[AP_PPARS(psf)])
+ call pargr (Memr[AP_PPARS(psf)+6])
+ if (ier != AP_OK)
+ call pargstr ("err")
+ else
+ call pargstr ("ok")
+ case AP_MOMENTS:
+ call printf ("%s %8.2f %8.2f %6.3f %6.3f ")
+ call pargstr (Memc[imname])
+ call pargr (Memr[AP_PPARS(psf)+1])
+ call pargr (Memr[AP_PPARS(psf)+2])
+ call pargr (Memr[AP_PPARS(psf)+3])
+ call pargr (Memr[AP_PPARS(psf)+4])
+ call printf ("%6.1f %8g %8g %s\n")
+ call pargr (Memr[AP_PPARS(psf)+5])
+ call pargr (Memr[AP_PPARS(psf)])
+ call pargr (Memr[AP_PPARS(psf)+6])
+ if (ier != AP_OK)
+ call pargstr ("err")
+ else
+ call pargstr ("ok")
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_PFHDR -- Procedure to write the banner for the fitpsf output file.
+
+procedure ap_pfhdr (ap, fd)
+
+pointer ap # pointer to the apphot strucuture
+int fd # output file descriptor
+
+int apstati()
+
+begin
+ if (fd == NULL)
+ return
+
+ switch (apstati (ap, PSFUNCTION)) {
+ case AP_RADGAUSS:
+ call radhdr (ap, fd)
+ case AP_ELLGAUSS:
+ call elhdr (ap, fd)
+ case AP_MOMENTS:
+ call momhdr (ap, fd)
+ default:
+ ;
+ }
+end
diff --git a/noao/digiphot/apphot/fitpsf/appsfshow.x b/noao/digiphot/apphot/fitpsf/appsfshow.x
new file mode 100644
index 00000000..3317bd22
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/appsfshow.x
@@ -0,0 +1,59 @@
+include "../lib/display.h"
+include "../lib/fitpsf.h"
+
+# AP_PSFSHOW -- Procedure to print the fitpsf parameters on the standard output.
+
+procedure ap_psfshow (ap)
+
+pointer ap # pointer to the apphot structure
+
+begin
+ call ap_nshow (ap)
+ call printf ("\n")
+ call ap_pfshow (ap)
+end
+
+
+# AP_PFSHOW -- Procedure to print out the fitting parameters on the standard
+# output.
+
+procedure ap_pfshow (ap)
+
+pointer ap # pointer to apphot structure
+
+pointer sp, str
+bool itob()
+int apstati()
+real apstatr()
+
+begin
+ # Print the PSF fitting parameters.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ call printf ("Psf Modelling Parameters\n")
+ call apstats (ap, PSFSTRING, Memc[str], SZ_FNAME)
+ call printf (" %s = %s\n")
+ call pargstr (KY_PSFSTRING)
+ call pargstr (Memc[str])
+
+ call printf (" %s = %g %s %s = %d\n")
+ call pargstr (KY_PSFAPERT)
+ call pargr (2.0 * apstatr (ap, PSFAPERT))
+ call pargstr (UN_PSFSCALEUNIT)
+ call pargstr (KY_PMAXITER)
+ call pargi (apstati (ap, PMAXITER))
+
+ call printf (" %s = %g %s %s = %d\n")
+ call pargstr (KY_PK2)
+ call pargr (apstatr (ap, PK2))
+ call pargstr (UN_PSFSIGMA)
+ call pargstr (KY_PNREJECT)
+ call pargi (apstati (ap, PNREJECT))
+
+ call printf (" %s = %b\n")
+ call pargstr (KY_MKPSFBOX)
+ call pargb (itob (apstati (ap, MKPSFBOX)))
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/fitpsf/apsfcolon.x b/noao/digiphot/apphot/fitpsf/apsfcolon.x
new file mode 100644
index 00000000..cb4d4521
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/apsfcolon.x
@@ -0,0 +1,238 @@
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/noise.h"
+include "../lib/fitpsf.h"
+
+# APSFCOLON -- Process the fitpsf task colon commands.
+
+procedure apsfcolon (ap, im, cl, out, stid, ltid, cmdstr, newimage, newbuf,
+ newfit)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the iraf image
+int cl # coordinate file descriptor
+int out # output file descriptor
+int stid # output file sequence number
+int ltid # coord file sequence number
+char cmdstr # command string
+int newimage # new image ?
+int newbuf # new psf buffer ?
+int newfit # new psf fit ?
+
+int junk
+pointer sp, incmd, outcmd
+int strdic()
+
+begin
+ call smark (sp)
+ call salloc (incmd, SZ_LINE, TY_CHAR)
+ call salloc (outcmd, SZ_LINE, TY_CHAR)
+
+ # Get the command.
+ call sscan (cmdstr)
+ call gargwrd (Memc[incmd], SZ_LINE)
+ if (Memc[incmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, PSFCMDS) != 0)
+ call ap_fitcolon (ap, out, stid, cmdstr, newbuf, newfit)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, APCMDS) != 0)
+ call ap_apcolon (ap, im, cl, out, stid, ltid, cmdstr, newimage,
+ junk, junk, junk, junk, newbuf, newfit)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, NCMDS) != 0)
+ call apnscolon (ap, im, out, stid, cmdstr, junk, junk,
+ junk, junk, newbuf, newfit)
+ else
+ call ap_pfimcolon (ap, cmdstr)
+
+ call sfree (sp)
+end
+
+
+# AP_FITCOLON -- Procedure to show/set the fitpsf parameters.
+
+procedure ap_fitcolon (ap, out, stid, cmdstr, newbuf, newfit)
+
+pointer ap # pointer to the apphot structure
+int out # output file descriptor
+int stid # output file sequence number
+char cmdstr # command string
+int newbuf # new psf buffer
+int newfit # new psf fit
+
+bool bval
+int ncmd, ival, stat
+pointer sp, cmd, str
+real rval
+
+bool itob()
+int nscan(), strdic(), apstati(), btoi()
+real apstatr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Get the command.
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, PSFCMDS)
+ switch (ncmd) {
+ case PFCMD_FUNCTION:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (nscan() == 1) {
+ call apstats (ap, PSFSTRING, Memc[str], SZ_FNAME)
+ call printf ("%s = %s\n")
+ call pargstr (KY_PSFSTRING)
+ call pargstr (Memc[str])
+ } else {
+ stat = strdic (Memc[cmd], Memc[cmd], SZ_LINE, PSFFUNCS)
+ if (stat > 0) {
+ call apseti (ap, PSFUNCTION, stat)
+ call apsets (ap, PSFSTRING, Memc[cmd])
+ switch (stat) {
+ case AP_RADGAUSS:
+ call apseti (ap, NPARS, 5)
+ case AP_ELLGAUSS:
+ call apseti (ap, NPARS, 7)
+ case AP_MOMENTS:
+ call apseti (ap, NPARS, 7)
+ }
+ if (stid > 1)
+ call ap_sparam (out, "FUNCTION", Memc[cmd], "model",
+ "fitting function")
+ newfit = YES
+ }
+ }
+ case PFCMD_BOX:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_PSFAPERT)
+ call pargr (2.0 * apstatr (ap, PSFAPERT))
+ call pargstr (UN_PSFSCALEUNIT)
+ } else {
+ call apsetr (ap, PSFAPERT, rval / 2.0)
+ if (stid > 1)
+ call ap_rparam (out, KY_PSFAPERT, rval, UN_PSFSCALEUNIT,
+ "fitting box width")
+ newbuf = YES
+ newfit = YES
+ }
+ case PFCMD_KREJECT:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_PK2)
+ call pargr (apstatr (ap, PK2))
+ call pargstr (UN_PSFSIGMA)
+ } else {
+ call apsetr (ap, PK2, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_PK2, rval, UN_PSFSIGMA,
+ "k-sigma rejection criterion")
+ newfit = YES
+ }
+ case PFCMD_MAXITER:
+ call gargi (ival)
+ if (nscan () == 1) {
+ call printf ("%s = %d\n")
+ call pargstr (KY_PMAXITER)
+ call pargi (apstati (ap, PMAXITER))
+ } else {
+ call apseti (ap, PMAXITER, ival)
+ if (stid > 1)
+ call ap_iparam (out, KY_PMAXITER, ival, UN_PSFNUMBER,
+ "maximum number of iterations")
+ newfit = YES
+ }
+ case PFCMD_NREJECT:
+ call gargi (ival)
+ if (nscan () == 1) {
+ call printf ("%s = %d\n")
+ call pargstr (KY_PNREJECT)
+ call pargi (apstati (ap, PNREJECT))
+ } else {
+ call apseti (ap, PNREJECT, ival)
+ if (stid > 1)
+ call ap_iparam (out, KY_PNREJECT, ival, UN_PSFNUMBER,
+ "maximum number of rejection cycles")
+ newfit = YES
+ }
+ case PFCMD_MKBOX:
+ call gargb (bval)
+ if (nscan() == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (KY_MKPSFBOX)
+ call pargb (itob (apstati (ap, MKPSFBOX)))
+ } else
+ call apseti (ap, MKPSFBOX, btoi (bval))
+ default:
+ # do nothing gracefully
+ call printf ("Unknown or ambiguous colon command\n")
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_PFIMCOLON -- Procedure to process fitpsf commands that are not fitpsf
+# parameters.
+
+procedure ap_pfimcolon (ap, cmdstr)
+
+pointer ap # pointer to the apphot structure
+char cmdstr # command string
+
+int ncmd
+pointer sp, cmd
+int strdic()
+
+begin
+ # Get the command.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, MISC1)
+ switch (ncmd) {
+ case ACMD_SHOW:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, PFSHOWARGS)
+ switch (ncmd) {
+ case PFCMD_DATA:
+ call printf ("\n")
+ call ap_nshow (ap)
+ call printf ("\n")
+ case PFCMD_FIT:
+ call printf ("\n")
+ call ap_pfshow (ap)
+ call printf ("\n")
+ default:
+ call printf ("\n")
+ call ap_psfshow (ap)
+ call printf ("\n")
+ }
+ default:
+ call printf ("Unknown or ambigous colon command\7\n")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/fitpsf/apsfelgauss.x b/noao/digiphot/apphot/fitpsf/apsfelgauss.x
new file mode 100644
index 00000000..df1a9ef4
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/apsfelgauss.x
@@ -0,0 +1,185 @@
+include <math.h>
+include <math/nlfit.h>
+include "../lib/noise.h"
+include "../lib/fitpsf.h"
+
+define NPARAMETERS 7
+define TOL 0.001
+
+# APSFELGAUSS -- Procedure to fit an elliptical Gaussian function to the
+# stellar data.
+
+int procedure apsfelgauss (ctrpix, nx, ny, emission, fwhmpsf, datamin,
+ datamax, noise, gain, sigma, maxiter, k2, nreject, par, perr, npar)
+
+real ctrpix[nx,ny] # object to be centered
+int nx, ny # dimensions of subarray
+int emission # emission or absorption object
+real fwhmpsf # full width half max of the psf
+real datamin # minimum good data value
+real datamax # maximum good data value
+int noise # noise model
+real gain # the gain parameter
+real sigma # constant term to noise
+int maxiter # maximum number of iterations
+real k2 # k-sigma rejection criterion
+int nreject # maximum number of rejection cycles
+real par[ARB] # parameters
+real perr[ARB] # errors in parameters
+int npar # number of parameters
+
+extern elgauss, delgauss
+int i, j, npts, fier, imin,imax
+pointer sp, x, w, list, zfit, nl, ptr
+real sumw, dummy, chisqr, locut, hicut, ptemp
+int locpr(), apreject()
+real asumr(), apwssqr()
+
+begin
+ # Initialize.
+ npts = nx * ny
+ if (npts < NPARAMETERS)
+ return (AP_NPSF_TOO_SMALL)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (x, 2 * npts, TY_REAL)
+ call salloc (w, npts, TY_REAL)
+ call salloc (zfit, npts, TY_REAL)
+ call salloc (list, NPARAMETERS, TY_INT)
+
+ # Define the active parameters.
+ do i = 1, NPARAMETERS
+ Memi[list+i-1] = i
+
+ # Set up the varaibles array.
+ ptr = x
+ do j = 1, ny {
+ do i = 1, nx {
+ Memr[ptr] = i
+ Memr[ptr+1] = j
+ ptr = ptr + 2
+ }
+ }
+
+ # Set up the weight array.
+ switch (noise) {
+ case AP_NCONSTANT:
+ call amovkr (1.0, Memr[w], npts)
+ case AP_NPOISSON:
+ call amaxkr (ctrpix, 0.0, Memr[w], npts)
+ if (gain > 0.0)
+ call adivkr (Memr[w], gain, Memr[w], npts)
+ if (! IS_INDEFR(sigma))
+ call aaddkr (Memr[w], sigma ** 2, Memr[w], npts)
+ call apreciprocal (Memr[w], Memr[w], npts, 1.0)
+ default:
+ call amovkr (1.0, Memr[w], npts)
+ }
+
+ # Make an initial guess at the fitting parameters.
+ if (emission == YES)
+ call ap_wlimr (ctrpix, Memr[w], nx * ny, datamin, datamax,
+ par[7], par[1], imin, imax)
+ else
+ call ap_wlimr (ctrpix, Memr[w], nx * ny, datamin, datamax,
+ par[7], par[1], imax, imin)
+ par[1] = par[1] - par[7]
+ if (mod (imax, nx) == 0)
+ imin = imax / nx
+ else
+ imin = imax / nx + 1
+ par[3] = imin
+ imin = imax - (imin - 1) * nx
+ par[2] = imin
+ par[4] = (fwhmpsf ** 2 / 4.0)
+ par[5] = (fwhmpsf ** 2 / 4.0)
+ par[6] = 0.0
+
+ # Get the centers and errors.
+ call nlinitr (nl, locpr (elgauss), locpr (delgauss), par, perr,
+ NPARAMETERS, Memi[list], NPARAMETERS, TOL, maxiter)
+ call nlfitr (nl, Memr[x], ctrpix, Memr[w], npts, 2, WTS_USER, fier)
+
+ # Perform the rejection cycle.
+ if (nreject > 0 && k2 > 0.0) {
+ do i = 1, nreject {
+ call nlvectorr (nl, Memr[x], Memr[zfit], npts, 2)
+ call asubr (ctrpix, Memr[zfit], Memr[zfit], npts)
+ chisqr = apwssqr (Memr[zfit], Memr[w], npts)
+ sumw = asumr (Memr[w], npts)
+ if (sumw <= 0.0)
+ break
+ else if (chisqr <= 0.0)
+ break
+ else
+ chisqr = sqrt (chisqr / sumw)
+ locut = - k2 * chisqr
+ hicut = k2 * chisqr
+ if (apreject (Memr[zfit], Memr[w], npts, locut, hicut) == 0)
+ break
+ call nlpgetr (nl, par, npar)
+ call nlfreer (nl)
+ call nlinitr (nl, locpr (elgauss), locpr (delgauss), par,
+ perr, NPARAMETERS, Memi[list], NPARAMETERS, TOL, maxiter)
+ call nlfitr (nl, Memr[x], ctrpix, Memr[w], npts, 2, WTS_USER,
+ fier)
+ }
+ }
+
+ # Fetch the parameters.
+ call nlvectorr (nl, Memr[x], Memr[zfit], npts, 2)
+ call nlpgetr (nl, par, npar)
+ par[4] = sqrt (abs(par[4]))
+ par[5] = sqrt (abs(par[5]))
+
+ # Fetch the errors.
+ call nlerrorsr (nl, ctrpix, Memr[zfit], Memr[w], npts, dummy,
+ chisqr, perr)
+ perr[4] = sqrt (perr[4])
+ perr[5] = sqrt (perr[5])
+
+ # Compute the mean errors.
+ dummy = 0.0
+ do i = 1, npts {
+ if (Memr[w+i-1] > 0.0)
+ dummy = dummy + 1.0
+ }
+ dummy = sqrt (dummy)
+ if (dummy > 0.0)
+ call adivkr (perr, dummy, perr, npar)
+
+ # Transform the parameters.
+ par[6] = mod (RADTODEG(par[6]), 360.0)
+ if (par[6] < 0.0)
+ par[6] = 360.0 + par[6]
+ if (par[6] > 90.0 && par[6] <= 270.0)
+ par[6] = par[6] - 180.0
+ else if (par[6] > 270.0 && par[6] <= 360.0)
+ par[6] = par[6] - 360.0
+ if (par[5] > par[4]) {
+ if (par[6] > 0.0)
+ par[6] = par[6] - 90.0
+ else if (par[6] < 0.0)
+ par[6] = par[6] + 90.0
+ ptemp = par[4]
+ par[4] = par[5]
+ par[5] = ptemp
+ }
+ perr[6] = mod (RADTODEG(perr[6]), 360.0)
+
+ call nlfreer (nl)
+
+ call sfree (sp)
+
+ # Return the appropriate error code.
+ if (fier == NO_DEG_FREEDOM) {
+ return (AP_NPSF_TOO_SMALL)
+ } else if (fier == SINGULAR) {
+ return (AP_PSF_SINGULAR)
+ } else if (fier == NOT_DONE) {
+ return (AP_PSF_NOCONVERGE)
+ } else {
+ return (AP_OK)
+ }
+end
diff --git a/noao/digiphot/apphot/fitpsf/apsffit.x b/noao/digiphot/apphot/fitpsf/apsffit.x
new file mode 100644
index 00000000..2e6d6dbc
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/apsffit.x
@@ -0,0 +1,136 @@
+include <mach.h>
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/fitpsfdef.h"
+include "../lib/noisedef.h"
+include "../lib/fitpsf.h"
+
+# APSFFIT -- Procedure to fit an analytic function to the PSF.
+
+int procedure apsffit (ap, im, wx, wy)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the IRAF image
+real wx, wy # object coordinates
+
+int ier, fier
+pointer psf, nse
+real datamin, datamax, dmin, dmax, threshold
+int apfbuf(), apsfradgauss(), apsfelgauss(), apsfmoments()
+
+begin
+ # Initialize.
+ psf = AP_PPSF(ap)
+ nse = AP_NOISE(ap)
+ AP_PFXCUR(psf) = wx
+ AP_PFYCUR(psf) = wy
+ if (IS_INDEFR(wx) || IS_INDEFR(wy)) {
+ AP_OPFXCUR(psf) = INDEFR
+ AP_OPFYCUR(psf) = INDEFR
+ } else {
+ switch (AP_WCSOUT(ap)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (ap, wx, wy, AP_OPFXCUR(psf), AP_OPFYCUR(psf), 1)
+ case WCS_TV:
+ call ap_ltov (im, wx, wy, AP_OPFXCUR(psf), AP_OPFYCUR(psf), 1)
+ default:
+ AP_OPFXCUR(psf) = wx
+ AP_OPFYCUR(psf) = wy
+ }
+ }
+ call amovkr (INDEFR, Memr[AP_PPARS(psf)], AP_MAXNPARS(psf))
+ call amovkr (INDEFR, Memr[AP_PPERRS(psf)], AP_MAXNPARS(psf))
+
+ # Fetch the buffer of pixels.
+ ier = apfbuf (ap, im, wx, wy)
+ if (ier == AP_NOPSFAREA)
+ return (AP_NOPSFAREA)
+
+ # Compute the min and max of the data subraster.
+ if (IS_INDEFR(AP_DATAMIN(ap)))
+ datamin = -MAX_REAL
+ else
+ datamin = AP_DATAMIN(ap)
+ if (IS_INDEFR(AP_DATAMAX(ap)))
+ datamax = MAX_REAL
+ else
+ datamax = AP_DATAMAX(ap)
+
+ switch (AP_PSFUNCTION(psf)) {
+
+ case AP_RADGAUSS:
+
+ fier = apsfradgauss (Memr[AP_PSFPIX(psf)], AP_PNX(psf), AP_PNY(psf),
+ AP_POSITIVE(ap), AP_FWHMPSF(ap) * AP_SCALE(ap), datamin,
+ datamax, AP_NOISEFUNCTION(nse), AP_EPADU(nse),
+ AP_READNOISE(nse) / AP_EPADU(nse), AP_PMAXITER(psf),
+ AP_PK2(psf), AP_PNREJECT(psf), Memr[AP_PPARS(psf)],
+ Memr[AP_PPERRS(psf)], AP_PSFNPARS(psf))
+
+ Memr[AP_PPARS(psf)+1] = Memr[AP_PPARS(psf)+1] + wx - AP_PXC(psf)
+ Memr[AP_PPARS(psf)+2] = Memr[AP_PPARS(psf)+2] + wy - AP_PYC(psf)
+
+ case AP_ELLGAUSS:
+
+ fier = apsfelgauss (Memr[AP_PSFPIX(psf)], AP_PNX(psf), AP_PNY(psf),
+ AP_POSITIVE(ap), AP_FWHMPSF(ap) * AP_SCALE(ap), datamin,
+ datamax, AP_NOISEFUNCTION(nse), AP_EPADU(nse),
+ AP_READNOISE(nse) / AP_EPADU(nse), AP_PMAXITER(psf),
+ AP_PK2(psf), AP_PNREJECT(psf), Memr[AP_PPARS(psf)],
+ Memr[AP_PPERRS(psf)], AP_PSFNPARS(psf))
+
+ Memr[AP_PPARS(psf)+1] = Memr[AP_PPARS(psf)+1] + wx - AP_PXC(psf)
+ Memr[AP_PPARS(psf)+2] = Memr[AP_PPARS(psf)+2] + wy - AP_PYC(psf)
+
+ case AP_MOMENTS:
+
+ call alimr (Memr[AP_PSFPIX(psf)], AP_PNX(psf) * AP_PNY(psf),
+ dmin, dmax)
+ dmin = max (dmin, datamin)
+ dmax = min (dmax, datamax)
+ threshold = 0.0
+
+ if (AP_POSITIVE(ap) == YES)
+ fier = apsfmoments (Memr[AP_PSFPIX(psf)], AP_PNX(psf),
+ AP_PNY(psf), dmin + threshold, dmax,
+ AP_POSITIVE(ap), Memr[AP_PPARS(psf)], Memr[AP_PPERRS(psf)],
+ AP_PSFNPARS(psf))
+ else
+ fier = apsfmoments (Memr[AP_PSFPIX(psf)], AP_PNX(psf),
+ AP_PNY(psf), dmax - threshold, dmin,
+ AP_POSITIVE(ap), Memr[AP_PPARS(psf)],
+ Memr[AP_PPERRS(psf)], AP_PSFNPARS(psf))
+
+ Memr[AP_PPARS(psf)+1] = Memr[AP_PPARS(psf)+1] + wx - AP_PXC(psf)
+ Memr[AP_PPARS(psf)+2] = Memr[AP_PPARS(psf)+2] + wy - AP_PYC(psf)
+
+ default:
+
+ # do nothing gracefully
+
+ }
+
+ switch (AP_WCSOUT(ap)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (ap, Memr[AP_PPARS(psf)+1], Memr[AP_PPARS(psf)+2],
+ Memr[AP_PPARS(psf)+1], Memr[AP_PPARS(psf)+2], 1)
+ case WCS_TV:
+ call ap_ltov (im, Memr[AP_PPARS(psf)+1], Memr[AP_PPARS(psf)+2],
+ Memr[AP_PPARS(psf)+1], Memr[AP_PPARS(psf)+2], 1)
+ default:
+ ;
+ }
+
+ # Return the appropriate error code.
+ if (fier == AP_OK) {
+ if (ier == AP_PSF_OUTOFBOUNDS)
+ return (AP_PSF_OUTOFBOUNDS)
+ else
+ return (AP_OK)
+ } else if (fier == AP_NPSF_TOO_SMALL) {
+ call amovkr (INDEFR, Memr[AP_PPARS(psf)], AP_PSFNPARS(psf))
+ call amovkr (INDEFR, Memr[AP_PPERRS(psf)], AP_PSFNPARS(psf))
+ return (AP_NPSF_TOO_SMALL)
+ } else
+ return (fier)
+end
diff --git a/noao/digiphot/apphot/fitpsf/apsffree.x b/noao/digiphot/apphot/fitpsf/apsffree.x
new file mode 100644
index 00000000..6bac4607
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/apsffree.x
@@ -0,0 +1,52 @@
+include "../lib/apphotdef.h"
+include "../lib/fitpsfdef.h"
+
+# APSFFREE -- Procedure to free the point spread fitting structure.
+
+procedure apsffree (ap)
+
+pointer ap # pointer to the apphot structure
+
+begin
+ if (ap == NULL)
+ return
+ if (AP_NOISE(ap) != NULL)
+ call ap_noisecls (ap)
+ if (AP_PDISPLAY(ap) != NULL)
+ call ap_dispcls (ap)
+ if (AP_PPSF(ap) != NULL)
+ call ap_psfcls (ap)
+ if (AP_IMBUF(ap) != NULL)
+ call mfree (AP_IMBUF(ap), TY_REAL)
+ if (AP_MW(ap) != NULL)
+ call mw_close (AP_MW(ap))
+ call mfree (ap, TY_STRUCT)
+end
+
+
+# AP_PSFCLS -- Procedure to close up the point spread fitting function
+# and arrays
+
+procedure ap_psfcls (ap)
+
+pointer ap # pointer to apphot structure
+
+pointer psf
+
+begin
+ if (AP_PPSF(ap) == NULL)
+ return
+ psf = AP_PPSF(ap)
+ #if (AP_PSFPIX(psf) != NULL)
+ #call mfree (AP_PSFPIX(psf), TY_REAL)
+ if (AP_PSFXPIX(psf) != NULL)
+ call mfree (AP_PSFXPIX(psf), TY_REAL)
+ if (AP_PSFYPIX(psf) != NULL)
+ call mfree (AP_PSFYPIX(psf), TY_REAL)
+ if (AP_PPARS(psf) != NULL)
+ call mfree (AP_PPARS(psf), TY_REAL)
+ if (AP_PPERRS(psf) != NULL)
+ call mfree (AP_PPERRS(psf), TY_REAL)
+ if (AP_PPSF(ap) != NULL)
+ call mfree (AP_PPSF(ap), TY_STRUCT)
+end
diff --git a/noao/digiphot/apphot/fitpsf/apsfinit.x b/noao/digiphot/apphot/fitpsf/apsfinit.x
new file mode 100644
index 00000000..19e5a42d
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/apsfinit.x
@@ -0,0 +1,94 @@
+include "../lib/apphotdef.h"
+include "../lib/fitpsfdef.h"
+include "../lib/fitpsf.h"
+
+# APSFINIT - Procedure to initialize the point spread modelling structure.
+
+procedure apsfinit (ap, function, rbox, fwhmpsf, noise)
+
+pointer ap # pointer to the apphot structure
+int function # fitting function
+real rbox # fitting radius
+real fwhmpsf # full width half max of psf
+int noise # noise model
+
+begin
+ # Initialize the image parameters.
+ call malloc (ap, LEN_APSTRUCT, TY_STRUCT)
+
+ # Set up the global apphot package parameters.
+ call ap_defsetup (ap, fwhmpsf)
+
+ # Setup noise model.
+ call ap_noisesetup (ap, noise)
+
+ # Set up the point spread fitting function.
+ call ap_psfsetup (ap, function, rbox)
+
+ # Set display options.
+ call ap_dispsetup (ap)
+
+ # Set remaining unused structure pointers to NULL.
+ AP_PCENTER(ap) = NULL
+ AP_PSKY(ap) = NULL
+ AP_PPHOT(ap) = NULL
+ AP_POLY(ap) = NULL
+ AP_RPROF(ap) = NULL
+end
+
+
+# AP_PSFSETUP -- Procedure to define the PSF fitting parameters.
+
+procedure ap_psfsetup (ap, function, rbox)
+
+pointer ap # pointer to apphot structure
+int function # fitting function
+real rbox # fitting aperture
+
+pointer psf
+
+begin
+ call malloc (AP_PPSF(ap), LEN_PSFSTRUCT, TY_STRUCT)
+ psf = AP_PPSF(ap)
+
+ # Set PSF fitting function.
+ AP_PSFUNCTION(psf) = function
+ switch (function) {
+ case AP_RADGAUSS:
+ call strcpy ("radgauss", AP_PSFSTRING(psf), SZ_FNAME)
+ case AP_ELLGAUSS:
+ call strcpy ("elgauss", AP_PSFSTRING(psf), SZ_FNAME)
+ case AP_MOMENTS:
+ call strcpy ("moments", AP_PSFSTRING(psf), SZ_FNAME)
+ default:
+ call strcpy ("radgauss", AP_PSFSTRING(psf), SZ_FNAME)
+ }
+ AP_PFXCUR(psf) = INDEFR
+ AP_PFYCUR(psf) = INDEFR
+ switch (function) {
+ case AP_RADGAUSS:
+ AP_PSFNPARS(psf) = 5
+ case AP_ELLGAUSS:
+ AP_PSFNPARS(psf) = 7
+ case AP_MOMENTS:
+ AP_PSFNPARS(psf) = 7
+ }
+
+ # Set remaining PSF parameters.
+ AP_PSFAPERT(psf) = rbox
+ AP_MAXNPARS(psf) = DEF_MAXNPARS
+ AP_PK2(psf) = DEF_PK2
+ AP_PMAXITER(psf) = DEF_PMAXITER
+ AP_PNREJECT(psf) = DEF_PNREJECT
+
+ # Initialize buffers.
+ AP_LENPSFBUF(psf) = 0
+ AP_NPSFPIX(psf) = 0
+ AP_PSFPIX(psf) = NULL
+ AP_PSFXPIX(psf) = NULL
+ AP_PSFYPIX(psf) = NULL
+
+ # Allocate space for computed parameters.
+ call calloc (AP_PPARS(psf), AP_MAXNPARS(psf), TY_REAL)
+ call calloc (AP_PPERRS(psf), AP_MAXNPARS(psf), TY_REAL)
+end
diff --git a/noao/digiphot/apphot/fitpsf/apsfmoments.x b/noao/digiphot/apphot/fitpsf/apsfmoments.x
new file mode 100644
index 00000000..ddae00f2
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/apsfmoments.x
@@ -0,0 +1,106 @@
+include <math.h>
+include "../lib/fitpsf.h"
+
+define NPARAMETERS 7
+
+# APSFMOMENTS -- Procedure to compute the 0, 1st and second moments of an
+# image and estimate the x,y center, the ellipticity and the position angle.
+
+int procedure apsfmoments (ctrpix, nx, ny, lthreshold, uthreshold, positive,
+ par, perr, npar)
+
+real ctrpix[nx, ny] # object to be centered
+int nx, ny # dimensions of subarray
+real lthreshold # lower threshold for moment computation
+real uthreshold # upper threshold for moment computation
+int positive # emission feature
+real par[ARB] # parameters
+real perr[ARB] # errors in parameters
+int npar # number of parameters
+
+int i, j
+real temp, sumi, sumxi, sumyi, sumx2i, sumy2i, sumxyi, r2, varx, vary, varxy
+bool fp_equalr()
+
+begin
+ # Initialize the sums.
+ sumi = 0.0
+ sumxi = 0.0
+ sumyi = 0.0
+ sumxyi = 0.0
+ sumx2i = 0.0
+ sumy2i = 0.0
+
+ # Accumulate the moments.
+ if (positive == YES) {
+ do j = 1, ny {
+ do i = 1, nx {
+ if (ctrpix[i,j] > uthreshold)
+ next
+ temp = ctrpix[i,j] - lthreshold
+ if (temp <= 0.0)
+ next
+ sumi = sumi + temp
+ sumxi = sumxi + i * temp
+ sumyi = sumyi + j * temp
+ sumxyi = sumxyi + i * j * temp
+ sumx2i = sumx2i + i * i * temp
+ sumy2i = sumy2i + j * j * temp
+ }
+ }
+ } else {
+ do j = 1, ny {
+ do i = 1, nx {
+ if (ctrpix[i,j] < uthreshold)
+ next
+ temp = lthreshold - ctrpix[i,j]
+ if (temp <= 0.0)
+ next
+ sumi = sumi + temp
+ sumxi = sumxi + i * temp
+ sumyi = sumyi + j * temp
+ sumxyi = sumxyi + i * j * temp
+ sumx2i = sumx2i + i * i * temp
+ sumy2i = sumy2i + j * j * temp
+ }
+ }
+ }
+
+ # Compute the parameters.
+ if (fp_equalr (sumi, 0.0)) {
+ par[1] = 0.0
+ par[2] = (1 + nx) / 2.0
+ par[3] = (1 + ny) / 2.0
+ par[4] = 0.0
+ par[5] = 0.0
+ par[6] = 0.0
+ par[7] = lthreshold
+ } else {
+ par[1] = sumi
+ par[2] = sumxi / sumi
+ par[3] = sumyi / sumi
+ varx = max (0.0, sumx2i / sumi - par[2] ** 2)
+ vary = max (0.0, sumy2i / sumi - par[3] ** 2)
+ r2 = varx + vary
+ if (r2 <= 0.0) {
+ par[4] = 0.0
+ par[5] = 0.0
+ par[6] = 0.0
+ } else {
+ par[4] = sqrt (r2)
+ varxy = sumxyi / sumi - par[2] * par[3]
+ par[5] = sqrt ((varx - vary) ** 2 + 4.0 * varxy ** 2) / r2
+ par[6] = (0.5 * r2 * (1.0 + par[5]) - vary)
+ if (fp_equalr (par[6], 0.0))
+ par[6] = 90.0
+ else
+ par[6] = RADTODEG (atan (varxy / par[6]))
+ }
+ par[7] = lthreshold
+ }
+
+ # Compute the errors.
+ npar = NPARAMETERS
+ call amovkr (0.0, perr, NPARAMETERS)
+ return (AP_OK)
+end
diff --git a/noao/digiphot/apphot/fitpsf/apsfradgauss.x b/noao/digiphot/apphot/fitpsf/apsfradgauss.x
new file mode 100644
index 00000000..0b4a93c6
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/apsfradgauss.x
@@ -0,0 +1,183 @@
+include <math/nlfit.h>
+include "../lib/noise.h"
+include "../lib/fitpsf.h"
+
+define NPARAMETERS 5
+define TOL 0.001
+
+# APSFRADGAUSS -- Fit a radial Gaussian function to the data.
+
+int procedure apsfradgauss (ctrpix, nx, ny, emission, fwhmpsf, datamin,
+ datamax, noise, gain, sigma, maxiter, k2, nreject, par, perr, npar)
+
+real ctrpix[nx, ny] # object to be centered
+int nx, ny # dimensions of subarray
+int emission # emission or absorption version
+real fwhmpsf # full width half max of the psf
+real datamin # minimum good data value
+real datamax # maximum good data value
+int noise # noise model to be used
+real gain # the gain in the data
+real sigma # sigma of constant noise term
+int maxiter # maximum number of iterations
+real k2 # k-sigma rejection criterion
+int nreject # maximum number of rejection cycles
+real par[ARB] # parameters
+real perr[ARB] # errors in parameters
+int npar # number of parameters
+
+extern gaussr, dgaussr
+int i, j, npts, list, imin, imax, fier
+pointer sp, x, w, zfit, nl, ptr
+real sumw, dummy, chisqr, locut, hicut
+int locpr(), apreject()
+real asumr(), apwssqr()
+
+begin
+ # Initialize.
+ npts = nx * ny
+ if (npts < NPARAMETERS)
+ return (AP_NPSF_TOO_SMALL)
+
+ call smark (sp)
+ call salloc (x, 2 * npts, TY_REAL)
+ call salloc (w, npts, TY_REAL)
+ call salloc (zfit, npts, TY_REAL)
+ call salloc (list, NPARAMETERS, TY_INT)
+
+ # Define the active parameters.
+ do i = 1, NPARAMETERS
+ Memi[list+i-1] = i
+
+ # Set variables array.
+ ptr = x
+ do j = 1, ny {
+ do i = 1, nx {
+ Memr[ptr] = i
+ Memr[ptr+1] = j
+ ptr = ptr + 2
+ }
+ }
+
+ # Define the weight array.
+ switch (noise) {
+ case AP_NCONSTANT:
+ call amovkr (1.0, Memr[w], npts)
+ case AP_NPOISSON:
+ call amaxkr (ctrpix, 0.0, Memr[w], npts)
+ if (gain > 0.0)
+ call adivkr (Memr[w], gain, Memr[w], npts)
+ if (! IS_INDEFR(sigma))
+ call aaddkr (Memr[w], sigma ** 2, Memr[w], npts)
+ call apreciprocal (Memr[w], Memr[w], npts, 1.0)
+ default:
+ call amovkr (1.0, Memr[w], npts)
+ }
+
+ # Make an initial guess at the parameters.
+ if (emission == YES)
+ call ap_wlimr (ctrpix, Memr[w], npts, datamin, datamax,
+ par[5], par[1], imin, imax)
+ else
+ call ap_wlimr (ctrpix, Memr[w], npts, datamin, datamax,
+ par[1], par[5], imax, imin)
+ par[1] = par[1] - par[5]
+ if (mod (imax, nx) == 0)
+ imin = imax / nx
+ else
+ imin = imax / nx + 1
+ par[3] = imin
+ imin = imax - (imin - 1) * nx
+ par[2] = imin
+ par[4] = (fwhmpsf ** 2 / 4.0)
+
+ # Fit the function and the errors.
+ call nlinitr (nl, locpr (gaussr), locpr (dgaussr), par, perr,
+ NPARAMETERS, Memi[list], NPARAMETERS, TOL, maxiter)
+ call nlfitr (nl, Memr[x], ctrpix, Memr[w], npts, 2, WTS_USER, fier)
+
+ # Perform the rejection cycle.
+ if ((nreject > 0) && (k2 > 0.0)) {
+ do i = 1, nreject {
+ call nlvectorr (nl, Memr[x], Memr[zfit], npts, 2)
+ call asubr (ctrpix, Memr[zfit], Memr[zfit], npts)
+ chisqr = apwssqr (Memr[zfit], Memr[w], npts)
+ sumw = asumr (Memr[w], npts)
+ if (sumw <= 0.0)
+ break
+ else if (chisqr <= 0.0)
+ break
+ else
+ chisqr = sqrt (chisqr / sumw)
+ locut = - k2 * chisqr
+ hicut = k2 * chisqr
+ if (apreject (Memr[zfit], Memr[w], npts, locut, hicut) == 0)
+ break
+ call nlpgetr (nl, par, npar)
+ call nlfreer (nl)
+ call nlinitr (nl, locpr (gaussr), locpr (dgaussr), par, perr,
+ NPARAMETERS, Memi[list], NPARAMETERS, TOL, maxiter)
+ call nlfitr (nl, Memr[x], ctrpix, Memr[w], npts, 2, WTS_USER,
+ fier)
+ }
+ }
+
+ # Get the parameters.
+ call nlpgetr (nl, par, npar)
+ par[4] = sqrt (abs(par[4]))
+
+ # Get the errors.
+ call nlvectorr (nl, Memr[x], Memr[zfit], npts, 2)
+ call nlerrorsr (nl, ctrpix, Memr[zfit], Memr[w], npts, dummy,
+ chisqr, perr)
+ perr[4] = sqrt (abs(perr[4]))
+
+ # Compute the mean errors in the parameters.
+ dummy = 0.0
+ do i = 1, npts {
+ if (Memr[w+i-1] > 0.0)
+ dummy = dummy + 1.0
+ }
+ dummy = sqrt (dummy)
+ if (dummy > 0.0)
+ call adivkr (perr, dummy, perr, npar)
+
+ call nlfreer (nl)
+
+ call sfree (sp)
+
+ # Return the appropriate error code.
+ if (fier == NO_DEG_FREEDOM) {
+ return (AP_NPSF_TOO_SMALL)
+ } else if (fier == SINGULAR) {
+ return (AP_PSF_SINGULAR)
+ } else if (fier == NOT_DONE) {
+ return (AP_PSF_NOCONVERGE)
+ } else {
+ return (AP_OK)
+ }
+end
+
+
+# APREJECT -- Reject points outside of the specified intensity limits by
+# setting their weights to zero.
+
+int procedure apreject (pix, w, npts, locut, hicut)
+
+real pix[ARB] # data
+real w[ARB] # weights
+int npts # number of data points
+real locut, hicut # data limits
+
+int i, nreject
+
+begin
+ nreject = 0
+ do i = 1, npts {
+ if ((pix[i] < locut || pix[i] > hicut) && w[i] > 0.0) {
+ w[i] = 0.0
+ nreject = nreject + 1
+ }
+ }
+ return (nreject)
+end
diff --git a/noao/digiphot/apphot/fitpsf/apsfrefit.x b/noao/digiphot/apphot/fitpsf/apsfrefit.x
new file mode 100644
index 00000000..a1b950fa
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/apsfrefit.x
@@ -0,0 +1,113 @@
+include <mach.h>
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/fitpsfdef.h"
+include "../lib/fitpsf.h"
+include "../lib/noisedef.h"
+
+# APSFREFIT -- Procedure to fit a function to the data already in the
+# data buffers.
+
+int procedure apsfrefit (ap, im)
+
+pointer ap # pointer to the apphot structure
+pointer im # the input image descriptor
+
+int ier
+pointer psf, nse
+int apsfradgauss(), apsfelgauss(), apsfmoments()
+real datamin, datamax, dmin, dmax, threshold
+
+begin
+ psf = AP_PPSF(ap)
+ nse = AP_NOISE(ap)
+ call amovkr (INDEFR, Memr[AP_PPARS(psf)], AP_MAXNPARS(psf))
+ call amovkr (INDEFR, Memr[AP_PPERRS(psf)], AP_MAXNPARS(psf))
+
+ # Compute the minimum and maximum good data value.
+ if (IS_INDEFR(AP_DATAMIN(ap)))
+ datamin = -MAX_REAL
+ else
+ datamin = AP_DATAMIN(ap)
+ if (IS_INDEFR(AP_DATAMAX(ap)))
+ datamax = MAX_REAL
+ else
+ datamax = AP_DATAMAX(ap)
+
+ switch (AP_PSFUNCTION(psf)) {
+
+ case AP_RADGAUSS:
+
+ ier = apsfradgauss (Memr[AP_PSFPIX(psf)], AP_PNX(psf), AP_PNY(psf),
+ AP_POSITIVE(ap), AP_FWHMPSF(ap) * AP_SCALE(ap), datamin,
+ datamax, AP_NOISEFUNCTION(nse), AP_EPADU(nse),
+ AP_READNOISE(nse) / AP_EPADU(nse), AP_PMAXITER(psf),
+ AP_PK2(psf), AP_PNREJECT(psf), Memr[AP_PPARS(psf)],
+ Memr[AP_PPERRS(psf)], AP_PSFNPARS(psf))
+
+ Memr[AP_PPARS(psf)+1] = Memr[AP_PPARS(psf)+1] + AP_PFXCUR(psf) -
+ AP_PXC(psf)
+ Memr[AP_PPARS(psf)+2] = Memr[AP_PPARS(psf)+2] + AP_PFYCUR(psf) -
+ AP_PYC(psf)
+
+ case AP_ELLGAUSS:
+
+ ier = apsfelgauss (Memr[AP_PSFPIX(psf)], AP_PNX(psf), AP_PNY(psf),
+ AP_POSITIVE(ap), AP_FWHMPSF(ap) * AP_SCALE(ap), datamin,
+ datamax, AP_NOISEFUNCTION(nse), AP_EPADU(nse),
+ AP_READNOISE(nse) / AP_EPADU(nse), AP_PMAXITER(psf),
+ AP_PK2(psf), AP_PNREJECT(psf), Memr[AP_PPARS(psf)],
+ Memr[AP_PPERRS(psf)], AP_PSFNPARS(psf))
+
+ Memr[AP_PPARS(psf)+1] = Memr[AP_PPARS(psf)+1] + AP_PFXCUR(psf) -
+ AP_PXC(psf)
+ Memr[AP_PPARS(psf)+2] = Memr[AP_PPARS(psf)+2] + AP_PFYCUR(psf) -
+ AP_PYC(psf)
+
+ case AP_MOMENTS:
+
+ call alimr (Memr[AP_PSFPIX(psf)], AP_PNX(psf) * AP_PNY(psf),
+ dmin, dmax)
+ dmin = max (dmin, datamin)
+ dmax = min (dmax, datamax)
+ threshold = 0.0
+
+ if (AP_POSITIVE(ap) == YES)
+ ier = apsfmoments (Memr[AP_PSFPIX(psf)], AP_PNX(psf),
+ AP_PNY(psf), dmin + threshold, dmax,
+ AP_POSITIVE(ap), Memr[AP_PPARS(psf)],
+ Memr[AP_PPERRS(psf)], AP_PSFNPARS(psf))
+ else
+ ier = apsfmoments (Memr[AP_PSFPIX(psf)], AP_PNX(psf),
+ AP_PNY(psf), dmax + threshold, dmin,
+ AP_POSITIVE(ap), Memr[AP_PPARS(psf)],
+ Memr[AP_PPERRS(psf)], AP_PSFNPARS(psf))
+
+ Memr[AP_PPARS(psf)+1] = Memr[AP_PPARS(psf)+1] + AP_PFXCUR(psf) -
+ AP_PXC(psf)
+ Memr[AP_PPARS(psf)+2] = Memr[AP_PPARS(psf)+2] + AP_PFYCUR(psf) -
+ AP_PYC(psf)
+
+ default:
+
+ # do nothing gracefully
+ }
+
+ switch (AP_WCSOUT(ap)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (ap, Memr[AP_PPARS(psf)+1], Memr[AP_PPARS(psf)+2],
+ Memr[AP_PPARS(psf)+1], Memr[AP_PPARS(psf)+2], 1)
+ case WCS_TV:
+ call ap_ltov (im, Memr[AP_PPARS(psf)+1], Memr[AP_PPARS(psf)+2],
+ Memr[AP_PPARS(psf)+1], Memr[AP_PPARS(psf)+2], 1)
+ default:
+ ;
+ }
+
+ if (ier == AP_NPSF_TOO_SMALL) {
+ call amovkr (INDEFR, Memr[AP_PPARS(psf)], AP_PSFNPARS(psf))
+ call amovkr (INDEFR, Memr[AP_PPERRS(psf)], AP_PSFNPARS(psf))
+ }
+
+ return (ier)
+end
diff --git a/noao/digiphot/apphot/fitpsf/fitpsf.key b/noao/digiphot/apphot/fitpsf/fitpsf.key
new file mode 100644
index 00000000..f7ab725e
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/fitpsf.key
@@ -0,0 +1,73 @@
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+v Verify the critical parameters
+w Save the current parameters
+d Plot radial profile of current star
+i Interactively set parameters using current star
+f Fit current star
+spbar Fit current star, output results
+m Move to next star in coordinate list
+n Fit next star in coordinate list, output results
+l Fit remaining stars in coordinate list, output results
+e Print error messages
+r Rewind the coordinate list
+q Exit task
+
+
+
+ Colon Commands
+
+:show [data/fit] List the parameters
+:m [n] Move to next [nth] star in coordinate list
+:n [n] Fit next [nth] star in coordinate list, output results
+
+
+ Colon Parameter Editing Commands
+
+# Image and file name parameters
+
+:image [string] Image name
+:coords [string] Coordinate file name
+:output [string] Output file name
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Scale factor (scale units)
+:emission [y/n] Emission feature (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good data value (counts)
+:datamax [value] Maximum good data value (counts)
+
+# Noise description parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per adu)
+:readnoise [value] Readnoise (electrons)
+
+# Observation parameters
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Exposure time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observation (time units)
+
+# Fitting parameters
+
+:function [string] PSF model (radgauss|elgauss|moments)
+:box [value] Width of the fitting box (scale units)
+:maxiter [value] Maximum number of iterations
+:nreject [value] Maximum number of rejection cycles
+:kreject [value] Rejection limit (sigma)
+
+# Plotting and marking functions
+
+:mkbox [y/n] Mark the fitting box on the display
diff --git a/noao/digiphot/apphot/fitpsf/ifitpsf.key b/noao/digiphot/apphot/fitpsf/ifitpsf.key
new file mode 100644
index 00000000..9bbb4ba9
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/ifitpsf.key
@@ -0,0 +1,10 @@
+ Interactive Fitpsf Setup Menu
+
+ v Mark and verify the critical fitpsf parameters (f,s,b)
+
+ f Mark and verify the full-width half-maximum of the psf
+ s Mark and verify the standard deviation of the background
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
+
+ b Mark and verify the half-width of the fitting box
diff --git a/noao/digiphot/apphot/fitpsf/mkpkg b/noao/digiphot/apphot/fitpsf/mkpkg
new file mode 100644
index 00000000..8e8efb12
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/mkpkg
@@ -0,0 +1,44 @@
+# FITPSF Task Routines
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ apbfitpsf.x <fset.h> ../lib/apphot.h \
+ ../lib/display.h
+ apfbuf.x <imhdr.h> ../lib/apphotdef.h \
+ ../lib/fitpsfdef.h ../lib/fitpsf.h
+ apfitpsf.x <ctype.h> <gset.h> \
+ ../lib/apphot.h ../lib/display.h \
+ ../lib/fitpsf.h <imhdr.h>
+ apppfpars.x ../lib/display.h ../lib/fitpsf.h
+ apgpfpars.x ../lib/display.h ../lib/fitpsf.h \
+ ../lib/noise.h
+ appfconfirm.x ../lib/apphot.h ../lib/noise.h \
+ ../lib/fitpsf.h
+ appferrors.x ../lib/fitpsf.h
+ apppsf.x ../lib/apphotdef.h ../lib/fitpsfdef.h \
+ ../lib/fitpsf.h ../lib/apphot.h
+ appsfshow.x ../lib/display.h ../lib/fitpsf.h
+ appfradsetup.x
+ apsfcolon.x ../lib/display.h ../lib/fitpsf.h \
+ ../lib/apphot.h ../lib/noise.h
+ apsfelgauss.x <math.h> ../lib/fitpsf.h \
+ <math/nlfit.h> ../lib/noise.h
+ apsffree.x ../lib/apphotdef.h ../lib/fitpsfdef.h
+ apsfinit.x ../lib/apphotdef.h ../lib/fitpsfdef.h \
+ ../lib/fitpsf.h
+ apsffit.x ../lib/apphotdef.h ../lib/fitpsfdef.h \
+ ../lib/noisedef.h ../lib/fitpsf.h \
+ ../lib/apphot.h <mach.h>
+ apsfmoments.x <math.h> ../lib/fitpsf.h
+ apsfradgauss.x ../lib/fitpsf.h <math/nlfit.h> \
+ ../lib/noise.h
+ apsfrefit.x ../lib/apphotdef.h ../lib/fitpsfdef.h \
+ ../lib/fitpsf.h ../lib/noisedef.h \
+ ../lib/apphot.h <mach.h>
+ t_fitpsf.x <fset.h> <gset.h> \
+ ../lib/apphot.h <imhdr.h>
+ ;
diff --git a/noao/digiphot/apphot/fitpsf/t_fitpsf.x b/noao/digiphot/apphot/fitpsf/t_fitpsf.x
new file mode 100644
index 00000000..28345a09
--- /dev/null
+++ b/noao/digiphot/apphot/fitpsf/t_fitpsf.x
@@ -0,0 +1,288 @@
+include <gset.h>
+include <fset.h>
+include <imhdr.h>
+include "../lib/apphot.h"
+
+# T_FITPSF -- Procedure to fit an analytic function to the PSF for a list
+# of objects in a list of images.
+
+procedure t_fitpsf ()
+
+pointer image # pointer to the name of the image
+pointer output # pointer to the output file name
+pointer coords # pointer to the coordinate file
+pointer graphics # pointer to the graphics display device
+pointer display # pointer to the display device
+int interactive # mode of use
+int cache # cache the input image pixels
+int verify # verify critical parameters
+int update # update the critical parameter
+int verbose # verbose mode
+
+pointer sp, outfname, ap, im, gd, id, cname, str
+int cl, out, limlist, lclist, lolist, lid, sid, root, stat, memstat
+int imlist, clist, olist, wcs, req_size, buf_size, old_size
+
+pointer gopen(), immap()
+int imtlen(), imtgetim(), clplen(), btoi(), clgfil(), fnldir()
+int open(), strncmp(), strlen(), apfitpsf(), imtopenp(), clpopnu()
+int clgwrd(), ap_memstat(), sizeof()
+bool clgetb(), streq()
+errchk gopen
+
+begin
+ # Allocate workin space.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (coords, SZ_FNAME, TY_CHAR)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+ call salloc (display, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (cname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Set standard output to flush on newline.
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get input image list.
+ imlist = imtopenp ("image")
+ limlist = imtlen (imlist)
+
+ # Get input coordinate lists.
+ clist = clpopnu ("coords")
+ lclist = clplen (clist)
+
+ # Get output file list and check for zero length list.
+ olist = clpopnu ("output")
+ lolist = clplen (olist)
+
+ # Check that image and coordinate list lengths match.
+ if (limlist < 1 || (lclist > 1 && lclist != limlist)) {
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+ call error (0, "Imcompatable image and coordinate list lengths")
+ }
+
+ # Check that image and output list lengths match.
+ if (lolist > 1 && lolist != limlist) {
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+ call error (0, "Imcompatable image and output list lengths")
+ }
+
+ call clgstr ("icommands.p_filename", Memc[cname], SZ_FNAME)
+ if (Memc[cname] != EOS)
+ interactive = NO
+ #else if (lclist == 0)
+ #interactive = YES
+ else
+ interactive = btoi (clgetb ("interactive"))
+ cache = btoi (clgetb("cache"))
+ verify = btoi (clgetb ("verify"))
+ update = btoi (clgetb ("update"))
+ verbose = btoi (clgetb ("verbose"))
+
+ # Get the parameters.
+ call ap_gpfpars (ap)
+ if (verify == YES && interactive == NO) {
+ call ap_pfconfirm (ap, NULL, 1)
+ if (update == YES)
+ call ap_ppfpars (ap)
+ }
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_LINE, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (ap, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_LINE, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (ap, WCSOUT, wcs)
+
+ # Get the graphics and display devices.
+ call clgstr ("graphics", Memc[graphics], SZ_FNAME)
+ call clgstr ("display", Memc[display], SZ_FNAME)
+
+ # Open the graphics and display devices.
+ if (interactive == YES) {
+ if (Memc[graphics] == EOS)
+ gd = NULL
+ else {
+ iferr {
+ gd = gopen (Memc[graphics], APPEND+AW_DEFER, STDGRAPH)
+ } then {
+ call eprintf (
+ "Warning: Error opening graphics device.\n")
+ gd = NULL
+ }
+ }
+ if (Memc[display] == EOS)
+ id = NULL
+ else if (streq (Memc[graphics], Memc[display]))
+ id = gd
+ else {
+ iferr {
+ id = gopen (Memc[display], APPEND, STDIMAGE)
+ } then {
+ call eprintf (
+ "Warning: Graphics overlay not available for display device.\n")
+ id = NULL
+ }
+ }
+ } else {
+ id = NULL
+ gd = NULL
+ }
+
+ # Begin looping over the image list.
+ sid = 1
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open the image.
+ im = immap (Memc[image], READ_ONLY, 0)
+ call apimkeys (ap, im, Memc[image])
+
+ # Set the image display viewport.
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[image], im, 4)
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+
+ # Open coordinate file, where coords is assumed to be a simple text
+ # file in which the x and y positions are in columns 1 and 2
+ # respectively and all remaining fields are ignored.
+
+ if (lclist <= 0) {
+ cl = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (clist, Memc[coords], SZ_FNAME)
+ root = fnldir (Memc[coords], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[coords+root], 7) == 0 || root ==
+ strlen (Memc[coords])) {
+ call ap_inname (Memc[image], Memc[outfname], "coo",
+ Memc[outfname], SZ_FNAME)
+ lclist = limlist
+ cl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else if (stat != EOF) {
+ call strcpy (Memc[coords], Memc[outfname], SZ_FNAME)
+ cl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else {
+ call apstats (ap, CLNAME, Memc[outfname], SZ_FNAME)
+ call seek (cl, BOF)
+ }
+ }
+ call apsets (ap, CLNAME, Memc[outfname])
+ call apfroot (Memc[outfname], Memc[str], SZ_LINE)
+ call apsets (ap, CLROOT, Memc[str])
+
+ # Open output text file, if output is "default", dir$default or
+ # a directory specification then the extension "psf" is added on
+ # to the image name and a suitable version number is appended to
+ # the output name. If the output string is null then no output
+ # file is written.
+
+ if (lolist == 0) {
+ out = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (olist, Memc[output], SZ_FNAME)
+ root = fnldir (Memc[output], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[output+root], 7) == 0 || root ==
+ strlen (Memc[output])) {
+ call apoutname (Memc[image], Memc[outfname], "psf",
+ Memc[outfname], SZ_FNAME)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ lolist = limlist
+ } else if (stat != EOF) {
+ call strcpy (Memc[output], Memc[outfname], SZ_FNAME)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ } else
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ }
+ call apsets (ap, OUTNAME, Memc[outfname])
+
+ # Fit the PSF.
+ if (interactive == NO) {
+ if (Memc[cname] != EOS)
+ stat = apfitpsf (ap, im, cl, NULL, NULL, out, sid, NO,
+ cache)
+ else if (cl != NULL) {
+ lid = 1
+ call apbfitpsf (ap, im, cl, out, id, sid, lid, verbose)
+ stat = NO
+ } else
+ stat = NO
+ } else
+ stat = apfitpsf (ap, im, cl, gd, id, out, sid, YES, cache)
+
+ # Cleanup.
+ call imunmap (im)
+ if (cl != NULL) {
+ if (lclist > 1)
+ call close (cl)
+ }
+ if (out != NULL && lolist != 1) {
+ call close (out)
+ if (sid <= 1) {
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ call delete (Memc[outfname])
+ }
+ sid = 1
+ }
+
+ # Uncache memory.
+ call fixmem (old_size)
+
+ if (stat == YES)
+ break
+ }
+
+ # Close the plot files.
+ if (id == gd && id != NULL)
+ call gclose (id)
+ else {
+ if (id != NULL)
+ call gclose (id)
+ if (gd != NULL)
+ call gclose (gd)
+ }
+
+ # If only one coordinate file for a list of images close file.
+ if (cl != NULL && lclist == 1)
+ call close (cl)
+
+ # If only one output file for a list of images close file.
+ if (out != NULL && lolist == 1) {
+ call close (out)
+ if (sid <= 1) {
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ call delete (Memc[outfname])
+ }
+ }
+
+ # Close up the PSF fitting structure.
+ call apsffree (ap)
+
+ # Close up the lists.
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/fitsky.par b/noao/digiphot/apphot/fitsky.par
new file mode 100644
index 00000000..3899b0e8
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky.par
@@ -0,0 +1,21 @@
+# FITSKY
+
+image,f,a,,,,"The input image(s)"
+coords,f,h,"",,,"The input coordinate list(s) (default: image.coo.?)"
+output,f,h,"default",,,"The output sky file(s) (default: image.sky.?)"
+plotfile,f,h,"",,,"The output metacode plot file"
+datapars,pset,h,"",,,"Data dependent parameters"
+fitskypars,pset,h,"",,,"Sky fitting parameters"
+interactive,b,h,yes,,,"Interactive mode ?"
+radplots,b,h,no,,,"Plot radial profiles in interactive mode ?"
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor: [x y wcs] key [cmd]"
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the input image pixels in memory ?"
+verify,b,h,)_.verify,,,"Verify critical parameters in non-interactive mode ?"
+update,b,h,)_.update,,,"Update critical parameters in non-interactive mode ?"
+verbose,b,h,)_.verbose,,,"Print messages in non-interactive mode ?"
+graphics,s,h,)_.graphics,,,"Graphics device"
+display,s,h,)_.display,,,"Display device"
+mode,s,h,'ql'
diff --git a/noao/digiphot/apphot/fitsky/apavsky.x b/noao/digiphot/apphot/fitsky/apavsky.x
new file mode 100644
index 00000000..c7e38c0e
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apavsky.x
@@ -0,0 +1,107 @@
+include "../lib/display.h"
+include "../lib/fitsky.h"
+
+# AP_AVSKY -- Compute an estimate of the sky value by averaging several
+# individual sky values measured in different parts of the frame.
+
+int procedure ap_avsky (ap, im, stid, sd, id, gd, interactive)
+
+pointer ap # the pointer to the main apphot data structure
+pointer im # the pointer to the input image
+int stid # the current sequence number
+int sd # the sky file descriptor
+pointer id # the display stream descriptor
+pointer gd # the graphics stream descriptor
+int interactive # interactive mode
+
+int wcs, key, nmsky, nmsigma, nmskew, nsky, nrej, sier, ier
+pointer sp, cmd
+real wx, wy, msky, msigma, mskew
+int clgcur(), apfitsky(), apstati()
+real apstatr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Initialize the skyvalues.
+ msky = 0.0
+ nmsky = 0
+ msigma = 0.0
+ nmsigma = 0
+ mskew = 0.0
+ nmskew = 0
+ nsky = 0
+ nrej = 0
+ ier = AP_OK
+
+ call printf (
+ "\nMeasure sky around several cursor positions (t=measure, q=quit)\n")
+ while (clgcur ("icommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+
+ switch (key) {
+ case 'q':
+ break
+
+ case 't':
+ sier = apfitsky (ap, im, wx, wy, sd, gd)
+ if (sier != AP_OK)
+ ier = sier
+
+ if (id != NULL) {
+ call apmark (ap, id, NO, apstati (ap, MKSKY), NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_splot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qspsky (ap, sier)
+
+ if (! IS_INDEFR(apstatr (ap, SKY_MODE))) {
+ msky = msky + apstatr (ap, SKY_MODE)
+ nmsky = nmsky + 1
+ }
+ if (! IS_INDEFR(apstatr (ap, SKY_SIGMA))) {
+ msigma = msigma + apstatr (ap, SKY_SIGMA)
+ nmsigma = nmsigma + 1
+ }
+ if (! IS_INDEFR(apstatr (ap, SKY_SKEW))) {
+ mskew = mskew + apstatr (ap, SKY_SKEW)
+ nmskew = nmskew + 1
+ }
+ nsky = nsky + apstati (ap, NSKY)
+ nrej = nrej + apstati (ap, NSKY_REJECT)
+
+ default:
+ ;
+ }
+ }
+
+ # Compute the average values.
+ if (nmsky > 0)
+ msky = msky / nmsky
+ else
+ msky = INDEFR
+ if (nmsigma > 0)
+ msigma = msigma / nmsigma
+ else
+ msigma = INDEFR
+ if (nmskew > 0)
+ mskew = mskew / nmskew
+ else
+ mskew = INDEFR
+
+ # Store the average values.
+ call apsetr (ap, SKY_MODE, msky)
+ call apsetr (ap, SKY_SIGMA, msigma)
+ call apsetr (ap, SKY_SKEW, mskew)
+ call apseti (ap, NSKY, nsky)
+ call apseti (ap, NSKY_REJECT, nrej)
+
+ call sfree (sp)
+
+ return (ier)
+end
diff --git a/noao/digiphot/apphot/fitsky/apbsky.x b/noao/digiphot/apphot/fitsky/apbsky.x
new file mode 100644
index 00000000..28e96288
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apbsky.x
@@ -0,0 +1,98 @@
+include <fset.h>
+include "../lib/apphot.h"
+include "../lib/display.h"
+
+# APBSKY -- Procedure to determine the sky statistics for a list of objects
+# in batch mode using a simple coordinate list.
+
+procedure apbsky (ap, im, cl, sd, out, id, ld, gd, mgd, gid, interactive)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to IRAF image
+int cl # starlist file descriptor
+int sd # sky file descriptor
+int out # output file descriptor
+int id, ld # sequence and list numbers
+int gd # pointer to stdgraph stream
+pointer mgd # pointer to graphics metacode file
+pointer gid # pointer to image display stream
+int interactive # interactive mode
+
+int stdin, ier, ild
+pointer sp, str
+real wx, wy
+int apfitsky(), fscan(), nscan(), strncmp(), apstati()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+ call fstats (cl, F_FILENAME, Memc[str], SZ_FNAME)
+
+ # Initialize.
+ ild = ld
+
+ # Print the query.
+ if (strncmp ("STDIN", Memc[str], 5) == 0) {
+ stdin = YES
+ call printf ("Type object x and y coordinates (^D or ^Z to end): ")
+ call flush (STDOUT)
+ } else
+ stdin = NO
+
+ # Loop over the coordinate file.
+ while (fscan (cl) != EOF) {
+
+ # Fetch and store the coordinates.
+ call gargr (wx)
+ call gargr (wy)
+ if (nscan () != 2) {
+ if (stdin == YES) {
+ call printf (
+ "Type object x and y coordinates (^D or ^Z to end): ")
+ call flush (STDOUT)
+ }
+ next
+ }
+
+ # Transform the input coordinates.
+ switch (apstati(ap,WCSIN)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_itol (ap, wx, wy, wx, wy, 1)
+ case WCS_TV:
+ call ap_vtol (im, wx, wy, wx, wy, 1)
+ default:
+ ;
+ }
+ call apsetr (ap, CWX, wx)
+ call apsetr (ap, CWY, wy)
+
+ # Fit the sky value.
+ ier = apfitsky (ap, im, wx, wy, sd, gd)
+
+ # Print the sky values.
+ if (interactive == YES) {
+ call ap_qspsky (ap, ier)
+ if (gid != NULL)
+ call apmark (ap, gid, NO, apstati (ap, MKSKY), NO)
+ }
+ call ap_splot(ap, id, mgd, YES)
+ if (id == 1)
+ call ap_param (ap, out, "fitsky")
+ call ap_pssky (ap, out, id, ild, ier)
+
+ # Set up for the next object.
+ id = id + 1
+ ild = ild + 1
+ call apsetr (ap, WX, wx)
+ call apsetr (ap, WY, wy)
+
+ # print query
+ if (stdin == YES) {
+ call printf (
+ "Type object x and y coordinates (^D or ^Z to end): ")
+ call flush (STDOUT)
+ }
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/fitsky/apcentroid.x b/noao/digiphot/apphot/fitsky/apcentroid.x
new file mode 100644
index 00000000..310db85d
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apcentroid.x
@@ -0,0 +1,244 @@
+include <mach.h>
+include "../lib/fitsky.h"
+
+# AP_CENTROID -- Procedure to find the mode, width and skew of the sky
+# distribution by computing the moments of the histogram.
+
+int procedure ap_centroid (skypix, coords, wgt, index, nskypix, snx, sny, k1,
+ hwidth, binsize, smooth, losigma, hisigma, rgrow, maxiter, sky_mode,
+ sky_sigma, sky_skew, nsky, nsky_reject)
+
+real skypix[ARB] # array of sky pixels
+int coords[ARB] # array of coordinates for regions growing
+real wgt[ARB] # array of weights for rejection
+int index[ARB] # array of sorted indices
+int nskypix # the number of sky pixels
+int snx, sny # the maximum dimensions of sky raster
+real k1 # extent of the histogram in skysigma
+real hwidth # width of the histogram
+real binsize # the size of the histogram in sky sigma
+int smooth # smooth the histogram before fitting
+real losigma, hisigma # upper and lower k-sigma rejection limits
+real rgrow # region growing radius in pixels
+int maxiter # maximum number of rejection cycles
+real sky_mode # computed sky value
+real sky_sigma # computed sigma of the sky pixels
+real sky_skew # skew of sky pixels
+int nsky # number of sky pixels used in fit
+int nsky_reject # number of sky pixels rejected
+
+double dsky, sumpx, sumsqpx, sumcbpx
+int nreject, nbins, nker, ier, i, j
+pointer sp, hgm, shgm
+real dmin, dmax, sky_mean, hmin, hmax, dh, locut, hicut, cut
+real sky_zero
+int ap_grow_hist2(), aphigmr()
+real ap_asumr(), apmedr()
+
+begin
+ # Intialize.
+ nsky = nskypix
+ nsky_reject = 0
+ sky_mode = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ if (nskypix <= 0)
+ return (AP_NOSKYAREA)
+
+ # Compute the histogram width and binsize.
+ sky_zero = ap_asumr (skypix, index, nskypix) / nskypix
+ call ap_ialimr (skypix, index, nskypix, dmin, dmax)
+ call apfimoments (skypix, index, nskypix, sky_zero, sumpx, sumsqpx,
+ sumcbpx, sky_mean, sky_sigma, sky_skew)
+ sky_mean = apmedr (skypix, index, nskypix)
+ sky_mean = max (dmin, min (sky_mean, dmax))
+ if (! IS_INDEFR(hwidth) && hwidth > 0.0) {
+ hmin = sky_mean - k1 * hwidth
+ hmax = sky_mean + k1 * hwidth
+ dh = binsize * hwidth
+ } else {
+ cut = min (sky_mean - dmin, dmax - sky_mean, k1 * sky_sigma)
+ hmin = sky_mean - cut
+ hmax = sky_mean + cut
+ dh = binsize * cut / k1
+ }
+
+ # Compute the number of histogram bins and the histogram resolution.
+ if (dh <= 0.0) {
+ nbins = 1
+ dh = 0.0
+ } else {
+ nbins = 2 * nint ((hmax - sky_mean) / dh) + 1
+ dh = (hmax - hmin) / (nbins - 1)
+ }
+
+ # Check for a valid histogram.
+ if (nbins < 2 || k1 <= 0.0 || sky_sigma < dh || dh <= 0.0 ||
+ sky_sigma <= 0.0) {
+ sky_mode = sky_mean
+ sky_sigma = 0.0
+ sky_skew = 0.0
+ return (AP_NOHISTOGRAM)
+ }
+
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (hgm, nbins, TY_REAL)
+ call salloc (shgm, nbins, TY_REAL)
+
+ # Accumulate the histogram.
+ call aclrr (Memr[hgm], nbins)
+ nsky_reject = nsky_reject + aphigmr (skypix, wgt, index, nskypix,
+ Memr[hgm], nbins, hmin, hmax)
+ nsky = nskypix - nsky_reject
+
+ # Do the initial rejection.
+ if (nsky_reject > 0) {
+ do i = 1, nskypix {
+ if (wgt[index[i]] <= 0.0) {
+ dsky = skypix[index[i]] - sky_zero
+ sumpx = sumpx - dsky
+ sumsqpx = sumsqpx - dsky ** 2
+ sumcbpx = sumcbpx - dsky ** 3
+ }
+ }
+ call apmoments (sumpx, sumsqpx, sumcbpx, nsky, sky_zero, sky_mean,
+ sky_sigma, sky_skew)
+ }
+
+ # Fit the mode, sigma an skew of the histogram.
+ if (smooth == YES) {
+ nker = max (1, nint (sky_sigma / dh))
+ #call ap_lucy_smooth (Memr[hgm], Memr[shgm], nbins, nker, 2)
+ call ap_bsmooth (Memr[hgm], Memr[shgm], nbins, nker, 2)
+ call ap_imode (Memr[shgm], nbins, hmin, hmax, YES, sky_mode, ier)
+ } else
+ call ap_imode (Memr[hgm], nbins, hmin, hmax, NO, sky_mode, ier)
+ sky_mode = max (dmin, min (sky_mode, dmax))
+ if ((IS_INDEFR(losigma) && IS_INDEFR(hisigma)) || (sky_sigma < dh) ||
+ maxiter < 1) {
+ call sfree (sp)
+ return (AP_OK)
+ }
+
+ # Fit histogram with pixel rejection and optional region growing.
+ do i = 1, maxiter {
+
+ # Compute new histogram limits.
+ if (IS_INDEFR(losigma))
+ locut = -MAX_REAL
+ else
+ locut = sky_mode - losigma * sky_sigma
+ if (IS_INDEFR(hisigma))
+ hicut = MAX_REAL
+ else
+ hicut = sky_mode + hisigma * sky_sigma
+
+ # Reject pixels.
+ nreject = 0
+ do j = 1, nskypix {
+ if (skypix[index[j]] >= locut && skypix[index[j]] <= hicut)
+ next
+ if (rgrow > 0.0)
+ nreject = nreject + ap_grow_hist2 (skypix, coords,
+ wgt, nskypix, sky_zero, index[j], snx, sny, Memr[hgm],
+ nbins, hmin, hmax, rgrow, sumpx, sumsqpx, sumcbpx)
+ else if (wgt[index[j]] > 0.0) {
+ call ap_hgmsub2 (Memr[hgm], nbins, hmin, hmax,
+ skypix[index[j]], sky_zero, sumpx, sumsqpx, sumcbpx)
+ wgt[index[j]] = 0.0
+ nreject = nreject + 1
+ }
+ }
+ if (nreject == 0)
+ break
+ nsky_reject = nsky_reject + nreject
+ nsky = nskypix - nsky_reject
+ if (nsky <= 0)
+ break
+
+ # Recompute the moments.
+ call apmoments (sumpx, sumsqpx, sumcbpx, nsky, sky_zero, sky_mean,
+ sky_sigma, sky_skew)
+
+ # Recompute the histogram peak.
+ if (smooth == YES) {
+ nker = max (1, nint (sky_sigma / dh))
+ #call ap_lucy_smooth (Memr[hgm], Memr[shgm], nbins, nker, 2)
+ call ap_bsmooth (Memr[hgm], Memr[shgm], nbins, nker, 2)
+ call ap_imode (Memr[shgm], nbins, hmin, hmax, YES, sky_mode,
+ ier)
+ } else
+ call ap_imode (Memr[hgm], nbins, hmin, hmax, NO, sky_mode, ier)
+ sky_mode = max (dmin, min (sky_mode, dmax))
+ if (sky_sigma <= dh || ier != AP_OK)
+ break
+ }
+
+ # Return the error codes.
+ call sfree (sp)
+ if (nsky == 0 || nsky_reject == nskypix || ier == AP_NOHISTOGRAM) {
+ nsky = 0
+ nsky_reject = nskypix
+ sky_mode = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ return (AP_NSKY_TOO_SMALL)
+ } else
+ return (AP_OK)
+end
+
+
+# AP_IMODE -- Procedure to compute the 1st, 2nd and third moments of the
+# histogram of sky pixels.
+
+procedure ap_imode (hgm, nbins, z1, z2, smooth, sky_mode, ier)
+
+real hgm[ARB] # histogram
+int nbins # number of bins
+real z1, z2 # min and max of the histogram
+int smooth # is the histogram smoothed
+real sky_mode # mode of histogram
+int ier # error code
+
+int i, noccup
+double sumi, sumix, x, dh
+real hmean, dz
+real asumr()
+
+begin
+ # Initialize the sums.
+ sumi = 0.0
+ sumix = 0.0
+
+ # Compute a continuum level.
+ if (smooth == NO)
+ hmean = asumr (hgm, nbins) / nbins
+ else {
+ call alimr (hgm, nbins, dz, hmean)
+ hmean = 2.0 * hmean / 3.0
+ }
+
+ # Accumulate the sums.
+ noccup = 1
+ dz = (z2 - z1) / (nbins - 1)
+ x = z1 + 0.5 * dz
+ do i = 1, nbins {
+ dh = hgm[i] - hmean
+ if (dh > 0.0d0) {
+ sumi = sumi + dh
+ sumix = sumix + dh * x
+ noccup = noccup + 1
+ }
+ x = x + dz
+ }
+
+ # Compute the sky mode, sigma and skew.
+ if (sumi > 0.0) {
+ sky_mode = sumix / sumi
+ ier = AP_OK
+ } else {
+ sky_mode = INDEFR
+ ier = AP_NOHISTOGRAM
+ }
+end
diff --git a/noao/digiphot/apphot/fitsky/apcrosscor.x b/noao/digiphot/apphot/fitsky/apcrosscor.x
new file mode 100644
index 00000000..757addcc
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apcrosscor.x
@@ -0,0 +1,288 @@
+include <mach.h>
+include "../lib/fitsky.h"
+
+# AP_CROSSCOR -- Procedure to compute the sky value by calculating the
+# cross-correlation function of the histogram of the sky pixels and
+# a Gaussian function with the same sigma as the sky distribution.
+# The peak of the cross-correlation function is found by parabolic
+# interpolation.
+
+int procedure ap_crosscor (skypix, coords, wgt, index, nskypix, snx, sny, k1,
+ hwidth, binsize, smooth, losigma, hisigma, rgrow, maxiter, sky_mode,
+ sky_sigma, sky_skew, nsky, nsky_reject)
+
+real skypix[ARB] # array of sky pixels
+int coords[ARB] # array of sky coordinates for region growing
+real wgt[ARB] # array of weights for rejection
+int index[ARB] # array of sort indices
+int nskypix # the number of sky pixels
+int snx, sny # the maximum dimensions of sky raster
+real k1 # half-width of the histogram in sky sigma
+real hwidth # the input sky sigma
+real binsize # the size of the histogram in sky sigma
+int smooth # smooth the histogram before fitting (not used)
+real losigma, hisigma # upper and lower rejection limits
+real rgrow # region growing radius in pixels
+int maxiter # maximum number of rejection cycles
+real sky_mode # computed sky value
+real sky_sigma # computed standard deviation of the sky pixels
+real sky_skew # computed skew of sky pixels
+int nsky # number of sky pixels used in fit
+int nsky_reject # number of sky pixels rejected
+
+double dsky, sumpx, sumsqpx, sumcbpx
+int nreject, nbins, nker, nsmooth, ier, i, j
+pointer sp, x, hgm, shgm, kernel
+real dmin, dmax, hmin, hmax, dh, kmin, kmax, locut, hicut, sky_mean, cut
+real sky_zero
+int ap_grow_hist2(), aphigmr()
+real ap_asumr(), apmedr()
+
+begin
+ # Initialize.
+ nsky = nskypix
+ nsky_reject = 0
+ sky_mode = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ if (nskypix <= 0)
+ return (AP_NOSKYAREA)
+
+ # Set up initial guess at sky mean, sigma and skew.
+ sky_zero = ap_asumr (skypix, index, nskypix) / nskypix
+ call ap_ialimr (skypix, index, nskypix, dmin, dmax)
+ call apfimoments (skypix, index, nskypix, sky_zero,
+ sumpx, sumsqpx, sumcbpx, sky_mean, sky_sigma, sky_skew)
+ sky_mean = apmedr (skypix, index, nskypix)
+ sky_mean = max (dmin, min (sky_mean, dmax))
+
+ # Compute the width and bin size of the histogram.
+ if (! IS_INDEFR(hwidth) && hwidth > 0.0) {
+ hmin = sky_mean - k1 * hwidth
+ hmax = sky_mean + k1 * hwidth
+ dh = binsize * hwidth
+ } else {
+ cut = min (sky_mean - dmin, dmax - sky_mean, k1 * sky_sigma)
+ hmin = sky_mean - cut
+ hmax = sky_mean + cut
+ dh = binsize * cut / k1
+ }
+
+ # Compute the number of bins in and the width of the kernel.
+ if (dh <= 0.0) {
+ nbins = 1
+ nker = 1
+ nsmooth = 1
+ dh = 0.0
+ } else {
+ nbins = 2 * nint ((hmax - sky_mean) / dh) + 1
+ nker = 2 * nint (2.0 * (hmax - sky_mean) / (dh * 3.0)) + 1
+ nsmooth = nbins - nker + 1
+ dh = (hmax - hmin) / (nbins - 1)
+ }
+ kmin = - dh * (nker / 2 + 0.5)
+ kmax = dh * (nker / 2 + 0.5)
+
+ # Test for a valid histogram.
+ if (nbins < 2 || k1 <= 0.0 || sky_sigma <= 0.0 || dh <= 0.0 ||
+ sky_sigma <= dh) {
+ sky_mode = sky_mean
+ sky_sigma = 0.0
+ sky_skew = 0.0
+ return (AP_NOHISTOGRAM)
+ }
+
+ # Allocate space for the histogram and kernel.
+ call smark (sp)
+ call salloc (x, nbins, TY_REAL)
+ call salloc (hgm, nbins, TY_REAL)
+ call salloc (shgm, nbins, TY_REAL)
+ call salloc (kernel, nker, TY_REAL)
+
+ # Set up x array.
+ do i = 1, nbins
+ Memr[x+i-1] = i
+ call amapr (Memr[x], Memr[x], nbins, 1.0, real (nbins),
+ hmin + 0.5 * dh, hmax + 0.5 * dh)
+
+ # Accumulate the histogram.
+ call aclrr (Memr[hgm], nbins)
+ call aclrr (Memr[shgm], nbins)
+ nsky_reject = nsky_reject + aphigmr (skypix, wgt, index, nskypix,
+ Memr[hgm], nbins, hmin, hmax)
+ nsky = nskypix - nsky_reject
+
+ # Perform the initial rejection cycle.
+ if (nsky_reject > 0.0) {
+ do i = 1, nskypix {
+ if (wgt[index[i]] <= 0.0) {
+ dsky = skypix[index[i]] - sky_zero
+ sumpx = sumpx - dsky
+ sumsqpx = sumsqpx - dsky ** 2
+ sumcbpx = sumcbpx - dsky ** 3
+ }
+ }
+ call apmoments (sumpx, sumsqpx, sumcbpx, nsky, sky_zero, sky_mean,
+ sky_sigma, sky_skew)
+ }
+
+ # Construct kernel and convolve with histogram.
+ if (sky_sigma > 0.0) {
+ call ap_gauss_kernel (Memr[kernel], nker, kmin, kmax, sky_sigma)
+ call acnvr (Memr[hgm], Memr[shgm+nker/2], nsmooth, Memr[kernel],
+ nker)
+ } else
+ call amovr (Memr[hgm], Memr[shgm], nbins)
+ call ap_corfit (Memr[x], Memr[shgm], nbins, sky_mode, ier)
+ sky_mode = max (dmin, min (sky_mode, dmax))
+ if (ier != OK) {
+ call sfree (sp)
+ return (ier)
+ }
+ if ((IS_INDEFR(losigma) && IS_INDEFR(hisigma)) || (sky_sigma <= dh) ||
+ maxiter < 1) {
+ call sfree (sp)
+ return (AP_OK)
+ }
+
+ # Fit histogram with pixel rejection and optional region growing.
+ do i = 1, maxiter {
+
+ # Compute new histogram limits.
+ if (IS_INDEFR(losigma))
+ locut = -MAX_REAL
+ else
+ locut = sky_mode - losigma * sky_sigma
+ if (IS_INDEFR(hisigma))
+ hicut = MAX_REAL
+ else
+ hicut = sky_mode + hisigma * sky_sigma
+
+ # Detect rejected pixels.
+ nreject = 0
+ do j = 1, nskypix {
+ if (skypix[index[j]] >= locut && skypix[index[j]] <= hicut)
+ next
+ if (rgrow > 0.0)
+ nreject = nreject + ap_grow_hist2 (skypix, coords,
+ wgt, nskypix, sky_zero, index[j], snx, sny,
+ Memr[hgm], nbins, hmin, hmax, rgrow, sumpx, sumsqpx,
+ sumcbpx)
+ else if (wgt[index[j]] > 0.0) {
+ call ap_hgmsub2 (Memr[hgm], nbins, hmin, hmax,
+ skypix[index[j]], sky_zero, sumpx, sumsqpx, sumcbpx)
+ wgt[index[j]] = 0.0
+ nreject = nreject + 1
+ }
+ }
+ if (nreject == 0)
+ break
+
+ # Update the sky parameters.
+ nsky_reject = nsky_reject + nreject
+ nsky = nskypix - nsky_reject
+ if (nsky <= 0)
+ break
+ call apmoments (sumpx, sumsqpx, sumcbpx, nsky, sky_zero, sky_mean,
+ sky_sigma, sky_skew)
+ if (sky_sigma <= dh)
+ break
+
+ # Recompute the peak of the histogram.
+ call ap_gauss_kernel (Memr[kernel], nker, kmin, kmax, sky_sigma)
+ call aclrr (Memr[shgm], nbins)
+ call acnvr (Memr[hgm], Memr[shgm+nker/2], nsmooth, Memr[kernel],
+ nker)
+ call ap_corfit (Memr[x], Memr[shgm], nbins, sky_mode, ier)
+ sky_mode = max (dmin, min (sky_mode, dmax))
+ if (ier != AP_OK)
+ break
+ }
+
+ # Return the appropriate error code.
+ call sfree (sp)
+ if (nsky == 0 || nsky_reject == nskypix) {
+ nsky = 0
+ nsky_reject = nskypix
+ sky_mode = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ return (AP_NSKY_TOO_SMALL)
+ } else if (ier != AP_OK) {
+ sky_mode = sky_mean
+ sky_sigma = 0.0
+ sky_skew = 0.0
+ return (ier)
+ } else
+ return (AP_OK)
+end
+
+
+# AP_GAUSS_KERNEL -- Procedure to compute a Gaussian kernel of given length
+# and sigma.
+
+procedure ap_gauss_kernel (kernel, nker, kmin, kmax, sky_sigma)
+
+real kernel[ARB] # kernel
+int nker # length of kernel
+real kmin, kmax # limits of the kernel
+real sky_sigma # sigma of the sky
+
+int i
+real dk, x, sumx
+
+begin
+ # Return 1 if unit sized kernel.
+ if (nker == 1) {
+ kernel[1] = 1.0
+ return
+ }
+
+ # Intialize.
+ sumx = 0.0
+ x = kmin
+ dk = (kmax - kmin ) / (nker - 1)
+
+ # Compute and normalize the kernel.
+ do i = 1, nker {
+ kernel[i] = exp (- (x ** 2) / (2. * sky_sigma ** 2))
+ sumx = sumx + kernel[i]
+ x = x + dk
+ }
+ do i = 1, nker
+ kernel[i] = kernel[i] / sumx
+end
+
+
+# AP_CORFIT -- Procedure to compute the peak of the cross-correlation
+# function using parabolic interpolation.
+
+procedure ap_corfit (x, shgm, nbins, sky_mode, ier)
+
+real x[ARB] # x coordinates of histogram
+real shgm[ARB] # convolved histogram
+int nbins # number of histogram bins
+real sky_mode # computed sky_mode
+int ier # error code
+
+int bin
+real max, xo, dh1, dh2
+
+begin
+ call ap_amaxel (shgm, nbins, max, bin)
+ if (max <= 0) {
+ ier = AP_FLAT_HIST
+ } else if (bin == 1) {
+ sky_mode = x[1]
+ ier = AP_OK
+ } else if (bin == nbins) {
+ sky_mode = x[nbins]
+ ier = AP_OK
+ } else {
+ xo = 0.5 * (x[bin] + x[bin-1])
+ dh1 = shgm[bin] - shgm[bin-1]
+ dh2 = shgm[bin] - shgm[bin+1]
+ sky_mode = xo + (x[bin] - x[bin-1]) * (dh1 / (dh1 + dh2))
+ ier = AP_OK
+ }
+end
diff --git a/noao/digiphot/apphot/fitsky/apfitsky.x b/noao/digiphot/apphot/fitsky/apfitsky.x
new file mode 100644
index 00000000..1c105b79
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apfitsky.x
@@ -0,0 +1,452 @@
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/noisedef.h"
+include "../lib/fitskydef.h"
+include "../lib/fitsky.h"
+
+# APFITSKY -- Procedure to the compute the sky value in an annular region
+# around a given position in the IRAF image.
+
+int procedure apfitsky (ap, im, wx, wy, sd, gd)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the IRAF image
+real wx # object x coordinate
+real wy # object y coordinate
+int sd # pointer to input text file containing sky values
+pointer gd # pointer to graphics stream
+
+int ier, nclip, nsky, ilo, ihi
+pointer sky, nse, gt
+real x, y
+int apskybuf(), ap_mode(), ap_centroid(), ap_histplot(), ap_readsky()
+int ap_median(), ap_radplot(), ap_gauss(), ap_lgsky(), ap_crosscor()
+int ap_mean(), ap_clip()
+pointer ap_gtinit()
+
+begin
+ # Initialize.
+ sky = AP_PSKY(ap)
+ nse = AP_NOISE(ap)
+ AP_SXCUR(sky) = wx
+ AP_SYCUR(sky) = wy
+ if (IS_INDEFR(wx) || IS_INDEFR(wy)) {
+ AP_OSXCUR(sky) = INDEFR
+ AP_OSYCUR(sky) = INDEFR
+ } else {
+ switch (AP_WCSOUT(ap)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (ap, wx, wy, AP_OSXCUR(sky), AP_OSYCUR(sky), 1)
+ case WCS_TV:
+ call ap_ltov (im, wx, wy, AP_OSXCUR(sky), AP_OSYCUR(sky), 1)
+ default:
+ AP_OSXCUR(sky) = wx
+ AP_OSYCUR(sky) = wy
+ }
+ }
+
+ AP_SKY_MODE(sky) = INDEFR
+ AP_SKY_SIG(sky) = INDEFR
+ AP_SKY_SKEW(sky) = INDEFR
+ AP_NSKY(sky) = 0
+ AP_NSKY_REJECT(sky) = 0
+ if (IS_INDEFR(wx) || IS_INDEFR(wy))
+ return (AP_NOSKYAREA)
+
+ switch (AP_SKYFUNCTION(sky)) {
+
+ case AP_MEAN:
+
+ # Fetch the sky pixels.
+ ier = apskybuf (ap, im, wx, wy)
+ if (ier != AP_OK)
+ return (ier)
+
+ # Initialze the weights.
+ call amovkr (1.0, Memr[AP_SWGT(sky)], AP_NSKYPIX(sky))
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky), ilo,
+ ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call ap_index (Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ # Compute the mean of the sky pixel distribution with pixel
+ # rejection and region growing.
+ ier = ap_mean (Memr[AP_SKYPIX(sky)], Memi[AP_COORDS(sky)],
+ Memr[AP_SWGT(sky)], Memi[AP_INDEX(sky)+ilo-1],
+ nsky, AP_SNX(sky), AP_SNY(sky), AP_SLOREJECT(sky),
+ AP_SHIREJECT(sky), AP_RGROW(sky) * AP_SCALE(ap),
+ AP_SNREJECT(sky), AP_SKY_MODE(sky), AP_SKY_SIG(sky),
+ AP_SKY_SKEW(sky), AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+
+ return (ier)
+
+ case AP_MEDIAN:
+
+ # Fetch the sky pixels.
+ ier = apskybuf (ap, im, wx, wy)
+ if (ier != AP_OK)
+ return (ier)
+
+ # Initialze the weights.
+ call amovkr (1.0, Memr[AP_SWGT(sky)], AP_NSKYPIX(sky))
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky), ilo,
+ ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call apqsort (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ # Compute the median of the sky pixel distribution with pixel
+ # rejection and region growing.
+ ier = ap_median (Memr[AP_SKYPIX(sky)], Memi[AP_COORDS(sky)],
+ Memr[AP_SWGT(sky)], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_SNX(sky), AP_SNY(sky), AP_SLOREJECT(sky),
+ AP_SHIREJECT(sky), AP_RGROW(sky) * AP_SCALE(ap),
+ AP_SNREJECT(sky), AP_SKY_MODE(sky), AP_SKY_SIG(sky),
+ AP_SKY_SKEW(sky), AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+
+ return (ier)
+
+ case AP_MODE:
+
+ # Fetch the sky pixels.
+ ier = apskybuf (ap, im, wx, wy)
+ if (ier != AP_OK)
+ return (ier)
+
+ # Initialze the weights.
+ call amovkr (1.0, Memr[AP_SWGT(sky)], AP_NSKYPIX(sky))
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky), ilo,
+ ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call apqsort (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ # Compute the median of the sky pixel distribution with pixel
+ # rejection and region growing.
+ ier = ap_mode (Memr[AP_SKYPIX(sky)], Memi[AP_COORDS(sky)],
+ Memr[AP_SWGT(sky)], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_SNX(sky), AP_SNY(sky), AP_SLOREJECT(sky),
+ AP_SHIREJECT(sky), AP_RGROW(sky) * AP_SCALE(ap),
+ AP_SNREJECT(sky), AP_SKY_MODE(sky), AP_SKY_SIG(sky),
+ AP_SKY_SKEW(sky), AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+
+ return (ier)
+
+ case AP_CENTROID:
+
+ # Fetch the sky pixels.
+ ier = apskybuf (ap, im, wx, wy)
+ if (ier != AP_OK)
+ return (ier)
+
+ # Initialze the weights.
+ call amovkr (1.0, Memr[AP_SWGT(sky)], AP_NSKYPIX(sky))
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky), ilo,
+ ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call ap_index (Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ # Compute the sky value by performing a moment analysis of the
+ # sky pixel histogram.
+ ier = ap_centroid (Memr[AP_SKYPIX(sky)], Memi[AP_COORDS(sky)],
+ Memr[AP_SWGT(sky)], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_SNX(sky), AP_SNY(sky), AP_K1(sky), INDEFR,
+ AP_BINSIZE(sky), AP_SMOOTH(sky), AP_SLOREJECT(sky),
+ AP_SHIREJECT(sky), AP_RGROW(sky) * AP_SCALE(ap),
+ AP_SMAXITER(sky), AP_SKY_MODE(sky), AP_SKY_SIG(sky),
+ AP_SKY_SKEW(sky), AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+
+ return (ier)
+
+ case AP_CONSTANT:
+
+ # Set the sky value to a constant.
+ AP_SKY_MODE(sky) = AP_SKYBACKGROUND(sky)
+ AP_SKY_SIG(sky) = AP_SKYSIGMA(nse)
+ AP_SKY_SKEW(sky) = INDEFR
+ AP_NSKY(sky) = 0
+ AP_NSKY_REJECT(sky) = 0
+ return (AP_OK)
+
+ case AP_SKYFILE:
+
+ # Read the sky values from a file.
+ if (sd == NULL)
+ return (AP_NOSKYFILE)
+ ier = ap_readsky (sd, x, y, AP_SKY_MODE(sky), AP_SKY_SIG(sky),
+ AP_SKY_SKEW(sky), AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ if (ier == EOF)
+ return (AP_EOFSKYFILE)
+ else if (ier != 7)
+ return (AP_BADSKYSCAN)
+ else if (AP_NSKY(sky) <= 0)
+ return (AP_NOSKYAREA)
+ else
+ return (AP_OK)
+
+ case AP_RADPLOT:
+
+ # Check the status of the graphics stream.
+ if (gd == NULL)
+ return (AP_NOGRAPHICS)
+
+ # Fetch the sky pixels.
+ ier = apskybuf (ap, im, wx, wy)
+ if (ier != AP_OK)
+ return (ier)
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky), ilo,
+ ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call ap_index (Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ # Mark the sky level on the radial profile plot.
+ call gactivate (gd, 0)
+ gt = ap_gtinit (AP_IMROOT(ap), wx, wy)
+ ier = ap_radplot (gd, gt, Memr[AP_SKYPIX(sky)],
+ Memi[AP_COORDS(sky)], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_SXC(sky), AP_SYC(sky), AP_SNX(sky), AP_SNY(sky),
+ AP_SCALE(ap), AP_SKY_MODE(sky), AP_SKY_SKEW(sky),
+ AP_SKY_SIG(sky), AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+ call ap_gtfree (gt)
+ call gdeactivate (gd, 0)
+
+ return (ier)
+
+ case AP_HISTPLOT:
+
+ # Check the status of the graphics stream.
+ if (gd == NULL)
+ return (AP_NOGRAPHICS)
+
+ # Fetch the sky pixels.
+ ier = apskybuf (ap, im, wx, wy)
+ if (ier != AP_OK)
+ return (ier)
+
+ # Initialze the weights.
+ call amovkr (1.0, Memr[AP_SWGT(sky)], AP_NSKYPIX(sky))
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky),
+ ilo, ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call ap_index (Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ # Mark the peak of the histogram on the histogram plot.
+ #call gactivate (gd, 0)
+ gt = ap_gtinit (AP_IMROOT(ap), wx, wy)
+ ier = ap_histplot (gd, gt, Memr[AP_SKYPIX(sky)],
+ Memr[AP_SWGT(sky)], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_K1(sky), INDEFR, AP_BINSIZE(sky), AP_SMOOTH(sky),
+ AP_SKY_MODE(sky), AP_SKY_SIG(sky), AP_SKY_SKEW(sky),
+ AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+ call ap_gtfree (gt)
+ #call gdeactivate (gd, 0)
+
+ return (ier)
+
+ case AP_OFILT:
+
+ # Fetch the sky pixels.
+ ier = apskybuf (ap, im, wx, wy)
+ if (ier != AP_OK)
+ return (ier)
+
+ # Initialze the weights.
+ call amovkr (1.0, Memr[AP_SWGT(sky)], AP_NSKYPIX(sky))
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky),
+ ilo, ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call ap_index (Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ # Compute the sky value using the histogram of the sky pixels
+ # and a variation of the optimal filtering technique.
+ ier = ap_lgsky (Memr[AP_SKYPIX(sky)], Memi[AP_COORDS(sky)],
+ Memr[AP_SWGT(sky)], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_SNX(sky), AP_SNY(sky), AP_K1(sky), INDEFR,
+ AP_BINSIZE(sky), AP_SMOOTH(sky), AP_SLOREJECT(sky),
+ AP_SHIREJECT(sky), AP_RGROW(sky) * AP_SCALE(ap),
+ AP_SMAXITER(sky), AP_SKY_MODE(sky), AP_SKY_SIG(sky),
+ AP_SKY_SKEW(sky), AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+
+ return (ier)
+
+ case AP_GAUSS:
+
+ # Fetch the sky pixels.
+ ier = apskybuf (ap, im, wx, wy)
+ if (ier != AP_OK)
+ return (ier)
+
+ # Initialze the weights.
+ call amovkr (1.0, Memr[AP_SWGT(sky)], AP_NSKYPIX(sky))
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky),
+ ilo, ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call ap_index (Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ # Compute the sky value by a fitting a skewed Gaussian function
+ # to the sky pixel histogram.
+ ier = ap_gauss (Memr[AP_SKYPIX(sky)], Memi[AP_COORDS(sky)],
+ Memr[AP_SWGT(sky)], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_SNX(sky), AP_SNY(sky), AP_SMAXITER(sky), AP_K1(sky),
+ INDEFR, AP_BINSIZE(sky), AP_SMOOTH(sky),
+ AP_SLOREJECT(sky), AP_SHIREJECT(sky), AP_RGROW(sky) *
+ AP_SCALE(ap), AP_SNREJECT(sky), AP_SKY_MODE(sky),
+ AP_SKY_SIG(sky), AP_SKY_SKEW(sky), AP_NSKY(sky),
+ AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+
+ return (ier)
+
+ case AP_CROSSCOR:
+
+ # Fetch the sky pixels.
+ ier = apskybuf (ap, im, wx, wy)
+ if (ier != AP_OK)
+ return (ier)
+
+ # Initialze the weights.
+ call amovkr (1.0, Memr[AP_SWGT(sky)], AP_NSKYPIX(sky))
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky),
+ ilo, ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call ap_index (Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ # Fit the sky value by computing the cross-correlation
+ # function of the histogram and an estimate of the noise
+ # distribution.
+ ier = ap_crosscor (Memr[AP_SKYPIX(sky)], Memi[AP_COORDS(sky)],
+ Memr[AP_SWGT(sky)], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_SNX(sky), AP_SNY(sky), AP_K1(sky), INDEFR,
+ AP_BINSIZE(sky), AP_SMOOTH(sky), AP_SLOREJECT(sky),
+ AP_SHIREJECT(sky), AP_RGROW(sky) * AP_SCALE(ap),
+ AP_SMAXITER(sky), AP_SKY_MODE(sky), AP_SKY_SIG(sky),
+ AP_SKY_SKEW(sky), AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+
+ return (ier)
+
+ default:
+
+ AP_SKY_MODE(sky) = INDEFR
+ AP_SKY_SIG(sky) = INDEFR
+ AP_SKY_SKEW(sky) = INDEFR
+ AP_NSKY(sky) = AP_NSKYPIX(sky)
+ AP_NSKY_REJECT(sky) = 0
+ return (AP_OK)
+ }
+end
diff --git a/noao/digiphot/apphot/fitsky/apgauss.x b/noao/digiphot/apphot/fitsky/apgauss.x
new file mode 100644
index 00000000..860301dc
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apgauss.x
@@ -0,0 +1,296 @@
+include <mach.h>
+include <math/nlfit.h>
+include "../lib/fitsky.h"
+
+define TOL .001 # Fitting tolerance
+
+# AP_GAUSS -- Procedure to compute the peak, width and skew of the histogram
+# by fitting a skewed Gaussian function to the histogram.
+
+int procedure ap_gauss (skypix, coords, wgt, index, nskypix, snx, sny, maxfit,
+ k1, hwidth, binsize, smooth, losigma, hisigma, rgrow, maxiter,
+ sky_mode, sky_sigma, sky_skew, nsky, nsky_reject)
+
+real skypix[ARB] # array of unsorted sky pixels
+int coords[ARB] # array of coordinates for region growing
+real wgt[ARB] # weights for pixel rejection
+int index[ARB] # array of sort indices
+int nskypix # the number of sky pixels
+int snx, sny # the maximum dimensions of sky raster
+int maxfit # maximum number of iterations per fit
+real k1 # extent of the histogram in skysigma
+real hwidth # width of the histogram
+real binsize # the size of the histogram in sky sigma
+int smooth # smooth the histogram before fitting
+real losigma, hisigma # upper and lower sigma rejection criterion
+real rgrow # region growing radius in pixels
+int maxiter # maximum number of rejection cycles
+real sky_mode # computed sky value
+real sky_sigma # computed sigma of the sky pixels
+real sky_skew # skew of sky pixels
+int nsky # number of sky pixels used in fit
+int nsky_reject # number of sky pixels rejected
+
+double dsky, sumpx, sumsqpx, sumcbpx
+int i, j, nreject, nbins, nker, ier
+pointer sp, x, hgm, shgm, w
+real sky_mean, sky_msigma, dmin, dmax, hmin, hmax, dh, locut, hicut, cut
+real sky_zero
+int ap_grow_hist2(), aphigmr()
+real ap_asumr(), apmedr()
+
+begin
+ # Initialize.
+ nsky = nskypix
+ nsky_reject = 0
+ sky_mode = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ if (nskypix <= 0)
+ return (AP_NOSKYAREA)
+
+ # Compute initial guess for sky statistics.
+ sky_zero = ap_asumr (skypix, index, nskypix) / nskypix
+ call ap_ialimr (skypix, index, nskypix, dmin, dmax)
+ call apfimoments (skypix, index, nskypix, sky_zero, sumpx, sumsqpx,
+ sumcbpx, sky_mean, sky_msigma, sky_skew)
+ sky_mean = apmedr (skypix, index, nskypix)
+ sky_mean = max (dmin, min (sky_mean, dmax))
+
+ # Compute the width and bin size of the sky histogram.
+ if (! IS_INDEFR(hwidth) && hwidth > 0.0) {
+ hmin = sky_mean - k1 * hwidth
+ hmax = sky_mean + k1 * hwidth
+ dh = binsize * hwidth
+ } else {
+ cut = min (sky_mean - dmin, dmax - sky_mean, k1 * sky_msigma)
+ hmin = sky_mean - cut
+ hmax = sky_mean + cut
+ dh = binsize * cut / k1
+ }
+
+ # Compute the number of histogram bins and width of smoothing kernel.
+ if (dh <= 0.0) {
+ nbins = 1
+ dh = 0.0
+ } else {
+ nbins = 2 * nint ((hmax - sky_mean) / dh) + 1
+ dh = (hmax - hmin) / (nbins - 1)
+ }
+
+ # Test for a valid histogram.
+ if (sky_msigma <= dh || dh <= 0.0 || k1 <= 0.0 || sky_msigma <= 0.0 ||
+ nbins < 4) {
+ sky_mode = sky_mean
+ sky_sigma = 0.0
+ sky_skew = 0.0
+ return (AP_NOHISTOGRAM)
+ }
+
+ # Allocate temporary working space.
+ call smark (sp)
+ call salloc (x, nbins, TY_REAL)
+ call salloc (hgm, nbins, TY_REAL)
+ call salloc (shgm, nbins, TY_REAL)
+ call salloc (w, nbins, TY_REAL)
+
+ # Compute the x array.
+ do i = 1, nbins
+ Memr[x+i-1] = i
+ call amapr (Memr[x], Memr[x], nbins, 1.0, real (nbins),
+ hmin + 0.5 * dh, hmax + 0.5 * dh)
+
+ # Accumulate the histogram.
+ call aclrr (Memr[hgm], nbins)
+ nsky_reject = nsky_reject + aphigmr (skypix, wgt, index, nskypix,
+ Memr[hgm], nbins, hmin, hmax)
+ nsky = nskypix - nsky_reject
+
+ # Do the initial rejection.
+ if (nsky_reject > 0) {
+ do i = 1, nskypix {
+ if (wgt[index[i]] <= 0.0) {
+ dsky = skypix[index[i]] - sky_zero
+ sumpx = sumpx - dsky
+ sumsqpx = sumsqpx - dsky ** 2
+ sumcbpx = sumcbpx - dsky ** 3
+ }
+ }
+ call apmoments (sumpx, sumsqpx, sumcbpx, nsky, sky_zero,
+ sky_mean, sky_msigma, sky_skew)
+ }
+
+ # Find the mode, sigma and skew of the histogram.
+ if (smooth == YES) {
+ nker = max (1, nint (sky_msigma / dh))
+ #call ap_lucy_smooth (Memr[hgm], Memr[shgm], nbins, nker, 2)
+ call ap_bsmooth (Memr[hgm], Memr[shgm], nbins, nker, 2)
+ call ap_hist_mode (Memr[x], Memr[shgm], Memr[w], nbins,
+ sky_mode, sky_sigma, sky_skew, maxfit, TOL, ier)
+ } else
+ call ap_hist_mode (Memr[x], Memr[hgm], Memr[w], nbins,
+ sky_mode, sky_sigma, sky_skew, maxfit, TOL, ier)
+ sky_mode = max (dmin, min (sky_mode, dmax))
+ if (ier != AP_OK) {
+ call sfree (sp)
+ return (ier)
+ }
+ if ((IS_INDEFR(losigma) && IS_INDEFR(hisigma)) || sky_sigma <= dh ||
+ maxiter < 1) {
+ call sfree (sp)
+ return (AP_OK)
+ }
+
+ # Fit histogram with pixel rejection and optional region growing.
+ do i = 1, maxiter {
+
+ # Compute the new rejection limits.
+ if (IS_INDEFR(losigma))
+ locut = -MAX_REAL
+ else
+ locut = sky_mode - losigma * sky_msigma
+ if (IS_INDEFR(hisigma))
+ hicut = MAX_REAL
+ else
+ hicut = sky_mode + hisigma * sky_msigma
+
+ # Detect and reject pixels.
+ nreject = 0
+ do j = 1, nskypix {
+ if (skypix[index[j]] >= locut && skypix[index[j]] <= hicut)
+ next
+ if (rgrow > 0.0)
+ nreject = nreject + ap_grow_hist2 (skypix, coords,
+ wgt, nskypix, sky_zero, index[j], snx, sny, Memr[hgm],
+ nbins, hmin, hmax, rgrow, sumpx, sumsqpx, sumcbpx)
+ else if (wgt[index[j]] > 0.0) {
+ call ap_hgmsub2 (Memr[hgm], nbins, hmin, hmax,
+ skypix[index[j]], sky_zero, sumpx, sumsqpx, sumcbpx)
+ wgt[index[j]] = 0.0
+ nreject = nreject + 1
+ }
+ }
+ if (nreject == 0)
+ break
+ nsky_reject = nsky_reject + nreject
+ nsky = nskypix - nsky_reject
+ if (nsky <= 0)
+ break
+ call apmoments (sumpx, sumsqpx, sumcbpx, nsky, sky_zero,
+ sky_mean, sky_msigma, sky_skew)
+
+ # Recompute mean, mode, sigma and skew.
+ if (smooth == YES) {
+ nker = max (1, nint (sky_msigma / dh))
+ #call ap_lucy_smooth (Memr[hgm], Memr[shgm], nbins, nker, 2)
+ call ap_bsmooth (Memr[hgm], Memr[shgm], nbins, nker, 2)
+ call ap_hist_mode (Memr[x], Memr[shgm], Memr[w], nbins,
+ sky_mode, sky_sigma, sky_skew, maxfit, TOL, ier)
+ } else
+ call ap_hist_mode (Memr[x], Memr[hgm], Memr[w], nbins,
+ sky_mode, sky_sigma, sky_skew, maxfit, TOL, ier)
+ sky_mode = max (dmin, min (sky_mode, dmax))
+ if (ier != AP_OK)
+ break
+ if (sky_sigma <= dh)
+ break
+ }
+
+ # Return appropriate error code.
+ call sfree (sp)
+ if (nsky == 0 || nsky_reject == nskypix) {
+ nsky = 0
+ nsky_reject = nskypix
+ sky_mode = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ return (AP_NSKY_TOO_SMALL)
+ } else if (ier == AP_NSKY_TOO_SMALL) {
+ return (AP_NSKY_TOO_SMALL)
+ } else if (ier != AP_OK) {
+ return (ier)
+ } else
+ return (AP_OK)
+end
+
+
+# AP_HIST_MODE -- Procedure to fit the skewed Gaussian function to the histogram
+# of the sky pixels.
+
+procedure ap_hist_mode (x, hgm, w, nbins, sky_mode, sky_sigma, sky_skew,
+ maxiter, tol, ier)
+
+real x[ARB] # x array
+real hgm[ARB] # histogram
+real w[ARB] # weights
+int nbins # number of bins
+real sky_mode # sky value
+real sky_sigma # sky sigma
+real sky_skew # sky skew
+int maxiter # max number of iterations
+real tol # tolerances
+int ier # error code
+
+extern gausskew, dgausskew
+int i, imin, imax, np, fier
+pointer sp, list, fit, nl
+real p[4], dp[4], dummy1
+int locpr()
+
+begin
+ # Allocate working memory.
+ call smark (sp)
+ call salloc (list, 4, TY_INT)
+ call salloc (fit, nbins, TY_REAL)
+
+ # Initialize.
+ do i = 1, 4
+ Memi[list+i-1] = i
+
+ # Compute initial guesses for the parameters.
+ call ap_alimr (hgm, nbins, dummy1, p[1], imin, imax)
+ p[2] = x[imax]
+ #p[3] = max (sky_sigma ** 2, abs (x[2] - x[1]) ** 2)
+ p[3] = abs ((x[nbins] - x[1]) / 6.0) ** 2
+ p[4] = 0.0
+ np = 4
+
+ # Fit the histogram.
+ call nlinitr (nl, locpr (gausskew), locpr (dgausskew), p, dp, np,
+ Memi[list], 4, tol, maxiter)
+ call nlfitr (nl, x, hgm, w, nbins, 1, WTS_UNIFORM, fier)
+ call nlvectorr (nl, x, Memr[fit], nbins, 1)
+ call nlpgetr (nl, p, np)
+ call nlfreer (nl)
+
+ call sfree (sp)
+
+ # Return the appropriate error code.
+ ier = AP_OK
+ if (fier == NO_DEG_FREEDOM) {
+ sky_mode = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ ier = AP_NSKY_TOO_SMALL
+ } else {
+ if (fier == SINGULAR)
+ ier = AP_SKY_SINGULAR
+ else if (fier == NOT_DONE)
+ ier = AP_SKY_NOCONVERGE
+ if (p[2] < x[1] || p[2] > x[nbins]) {
+ sky_mode = x[imax]
+ ier = AP_BADPARAMS
+ } else
+ sky_mode = p[2]
+ if (p[3] <= 0.0) {
+ sky_sigma = 0.0
+ sky_skew = 0.0
+ ier = AP_BADPARAMS
+ } else {
+ sky_sigma = sqrt (p[3])
+ sky_skew = 1.743875281 * abs (p[4]) ** (1.0 / 3.0) * sky_sigma
+ if (p[4] < 0.0)
+ sky_skew = - sky_skew
+ }
+ }
+end
diff --git a/noao/digiphot/apphot/fitsky/apgrowhist.x b/noao/digiphot/apphot/fitsky/apgrowhist.x
new file mode 100644
index 00000000..6f01a789
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apgrowhist.x
@@ -0,0 +1,136 @@
+# AP_GROW_HIST -- Procedure to reject pixels with region growing.
+
+int procedure ap_grow_hist (skypix, coords, wgt, nskypix, index, snx, sny, hgm,
+ nbins, z1, z2, rgrow)
+
+real skypix[ARB] # sky pixels
+int coords[ARB] # sky pixel coordinates
+real wgt[ARB] # array of weights
+int nskypix # number of sky pixels
+int index # index of pixel to be rejected
+int snx, sny # size of sky subraster
+real hgm[ARB] # histogram
+int nbins # number of bins
+real z1, z2 # value of first and last histogram bin
+real rgrow # region growing radius
+
+int j, k, ixc, iyc, ymin, ymax, xmin, xmax, nreject, cstart, c, bin
+real dh, r2, rgrow2, d
+
+begin
+ # Find the x and y coordinates of the pixel to be rejected.
+ ixc = mod (coords[index], snx)
+ if (ixc == 0)
+ ixc = snx
+ iyc = (coords[index] - ixc) / snx + 1
+
+ # Find the coordinate space to be used for regions growing.
+ ymin = max (1, int (iyc - rgrow))
+ ymax = min (sny, int (iyc + rgrow))
+ xmin = max (1, int (ixc - rgrow))
+ xmax = min (snx, int (ixc + rgrow))
+ if (ymin <= iyc)
+ cstart = min (nskypix, max (1, index - int (rgrow) + snx *
+ (ymin - iyc)))
+ else
+ cstart = index
+
+ # Perform the region growing.
+ dh = real (nbins - 1) / (z2 - z1)
+ rgrow2 = rgrow ** 2
+ nreject = 0
+ do j = ymin, ymax {
+ d = rgrow2 - (j - iyc) ** 2
+ if (d <= 0.0)
+ d = 0.0
+ else
+ d = sqrt (d)
+ do k = max (xmin, int (ixc - d)), min (xmax, int (ixc + d)) {
+ c = k + (j - 1) * snx
+ while (coords[cstart] < c && cstart < nskypix)
+ cstart = cstart + 1
+ r2 = (k - ixc) ** 2 + (j - iyc) ** 2
+ if (r2 <= rgrow2 && c == coords[cstart] && wgt[cstart] > 0.0) {
+ nreject = nreject + 1
+ wgt[cstart] = 0.0
+ if (skypix[cstart] >= z1 && skypix[cstart] <= z2) {
+ bin = int ((skypix[cstart] - z1) * dh) + 1
+ hgm[bin] = hgm[bin] - 1.0
+ }
+ }
+ }
+ }
+
+ return (nreject)
+end
+
+
+# AP_GROW_HIST2 -- Procedure to reject pixels with region growing.
+
+int procedure ap_grow_hist2 (skypix, coords, wgt, nskypix, sky_zero, index,
+ snx, sny, hgm, nbins, z1, z2, rgrow, sumpx, sumsqpx, sumcbpx)
+
+real skypix[ARB] # sky pixels
+int coords[ARB] # coordinates
+real wgt[ARB] # array of weights
+int nskypix # number of sky pixels
+real sky_zero # the sky zero point for moment analysis
+int index # index of pixel to be rejected
+int snx, sny # size of sky subraster
+real hgm[ARB] # histogram
+int nbins # number of bins
+real z1, z2 # value of first and last histogram bin
+real rgrow # region growing radius
+double sumpx # sum of sky values
+double sumsqpx # sum of sky values squared
+double sumcbpx # sum of sky values cubed
+
+double dsky
+int j, k, ixc, iyc, ymin, ymax, xmin, xmax, nreject, cstart, c, bin
+real dh, r2, rgrow2, d
+
+begin
+ # Find the coordinates of the region growing center.
+ ixc = mod (coords[index], snx)
+ if (ixc == 0)
+ ixc = snx
+ iyc = (coords[index] - ixc) / snx + 1
+
+ ymin = max (1, int (iyc - rgrow))
+ ymax = min (sny, int (iyc + rgrow))
+ xmin = max (1, int (ixc - rgrow))
+ xmax = min (snx, int (ixc + rgrow))
+ dh = real (nbins - 1) / (z2 - z1)
+ if (ymin <= iyc)
+ cstart = min (nskypix, max (1, index - int (rgrow) + snx *
+ (ymin - iyc)))
+ else
+ cstart = index
+
+ # Perform the region growing.
+ nreject = 0
+ rgrow2 = rgrow ** 2
+ do j = ymin, ymax {
+ d = sqrt (rgrow2 - (j - iyc) ** 2)
+ do k = max (xmin, int (ixc - d)), min (xmax, int (ixc + d)) {
+ c = k + (j - 1) * snx
+ while (coords[cstart] < c && cstart < nskypix)
+ cstart = cstart + 1
+ r2 = (k - ixc) ** 2 + (j - iyc) ** 2
+ if (r2 <= rgrow2 && c == coords[cstart] && wgt[cstart] > 0.0) {
+ nreject = nreject + 1
+ wgt[cstart] = 0.0
+ dsky = skypix[cstart] - sky_zero
+ sumpx = sumpx - dsky
+ sumsqpx = sumsqpx - dsky ** 2
+ sumcbpx = sumcbpx - dsky ** 3
+ if (skypix[cstart] >= z1 && skypix[cstart] <= z2) {
+ bin = int ((skypix[cstart] - z1) * dh) + 1
+ hgm[bin] = hgm[bin] - 1.0
+ }
+ }
+ }
+ }
+
+ return (nreject)
+end
diff --git a/noao/digiphot/apphot/fitsky/apgspars.x b/noao/digiphot/apphot/fitsky/apgspars.x
new file mode 100644
index 00000000..8ca7f52c
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apgspars.x
@@ -0,0 +1,26 @@
+include "../lib/display.h"
+include "../lib/noise.h"
+include "../lib/fitsky.h"
+
+# AP_SGPARS -- Procedure to fetch the parameters for the fitsky task.
+
+procedure ap_sgpars (ap)
+
+pointer ap # pointer to apphot structure
+
+bool clgetb()
+int btoi()
+
+begin
+ # Open the apphot structure.
+ call apsinit (ap, AP_MODE, 10.0, 10.0, 2.0, AP_NPOISSON)
+
+ # Get the data dependent parameters.
+ call ap_gdapars (ap)
+
+ # Get the sky fitting parameters.
+ call ap_gsapars (ap)
+
+ # Get radial plots.
+ call apseti (ap, RADPLOTS, btoi (clgetb ("radplots")))
+end
diff --git a/noao/digiphot/apphot/fitsky/aphgmsub.x b/noao/digiphot/apphot/fitsky/aphgmsub.x
new file mode 100644
index 00000000..ae969bba
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/aphgmsub.x
@@ -0,0 +1,51 @@
+# AP_HGMSUB -- Procedure to subtract a point from an existing histogram.
+
+procedure ap_hgmsub (hgm, nbins, z1, z2, skypix)
+
+real hgm[ARB] # histogram
+int nbins # number of bins
+real z1, z2 # range of histogram
+real skypix # sky value
+
+int bin
+real dh
+
+begin
+ if (skypix < z1 || skypix > z2)
+ return
+ dh = real (nbins - 1) / (z2 - z1)
+ bin = int ((skypix - z1) * dh) + 1
+ hgm[bin] = hgm[bin] - 1.0
+end
+
+
+# AP_HGMSUB2 -- Procedure to subract points from the accumulated sums
+# and the existing histogram.
+
+procedure ap_hgmsub2 (hgm, nbins, z1, z2, skypix, sky_zero, sumpx, sumsqpx,
+ sumcbpx)
+
+real hgm[ARB] # histogram
+int nbins # number of bins
+real z1, z2 # range of histogram
+real skypix # sky value
+real sky_zero # sky zero point for moment analysis
+double sumpx # sum of the sky pixel values
+double sumsqpx # sum of the squares of the sky pixel values
+double sumcbpx # sum of the cubes of the sky pixel values
+
+double dsky
+int bin
+real dh
+
+begin
+ if (skypix < z1 || skypix > z2)
+ return
+ dsky = skypix - sky_zero
+ sumpx = sumpx - dsky
+ sumsqpx = sumsqpx - dsky ** 2
+ sumcbpx = sumcbpx - dsky ** 3
+ dh = real (nbins - 1) / (z2 - z1)
+ bin = int ((skypix - z1) * dh) + 1
+ hgm[bin] = hgm[bin] - 1.0
+end
diff --git a/noao/digiphot/apphot/fitsky/aphistplot.x b/noao/digiphot/apphot/fitsky/aphistplot.x
new file mode 100644
index 00000000..49c00071
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/aphistplot.x
@@ -0,0 +1,233 @@
+include <gset.h>
+include <pkg/gtools.h>
+include "../lib/fitsky.h"
+
+# AP_HISTPLOT -- Procedure to the sky value using a plot of the sky histogram
+# and cursor readback.
+
+int procedure ap_histplot (gd, gt, skypix, wgt, index, nskypix, k1, hwidth,
+ binsize, smooth, sky_mode, sky_sigma, sky_skew, nsky, nsky_reject)
+
+pointer gd # pointer to graphics stream
+pointer gt # pointer to GTOOLS structure
+real skypix[ARB] # array of unsorted sky pixels
+real wgt[ARB] # array of weights for rejection
+int index[ARB] # array of sort indices
+int nskypix # number of sky pixels
+real k1 # rejection criterion
+real hwidth # half width of histogram in k1 units
+real binsize # histogram binsize in units of sigma
+int smooth # smooth the histogram
+real sky_mode # sky value
+real sky_sigma # sigma of sky pixels
+real sky_skew # skew of sky pixels
+int nsky # number of sky pixels
+int nsky_reject # number of rejected sky pixels
+
+double dsky, sumpx, sumsqpx, sumcbpx
+int i, nbins, nker, wcs, key
+pointer sp, x, hgm, shgm, cmd
+real dmin, dmax, hmin, hmax, dh, ymin, ymax, symin, symax, wx, wy
+real u1, u2, v1, v2, x1, x2, y1, y2, cut, sky_mean, sky_zero
+int clgcur(), aphigmr()
+real apmedr(), ap_asumr()
+
+begin
+ # Check for valid graphics stream.
+ if (gd == NULL)
+ return (AP_NOGRAPHICS)
+
+ # Initialize.
+ nsky = nskypix
+ nsky_reject = 0
+ sky_mode = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ if (nskypix <= 0)
+ return (AP_SKY_OUTOFBOUNDS)
+
+ # Compute an initial guess at the sky distribution.
+ sky_zero = ap_asumr (skypix, index, nskypix) / nskypix
+ call ap_ialimr (skypix, index, nskypix, dmin, dmax)
+ call apfimoments (skypix, index, nskypix, sky_zero, sumpx, sumsqpx,
+ sumcbpx, sky_mean, sky_sigma, sky_skew)
+ sky_mode = apmedr (skypix, index, nskypix)
+ sky_mode = max (dmin, min (sky_mode, dmax))
+
+ # Compute histogram width and binsize.
+ if (! IS_INDEFR(hwidth) && hwidth > 0.0) {
+ hmin = sky_mode - k1 * hwidth
+ hmax = sky_mode + k1 * hwidth
+ dh = binsize * hwidth
+ } else {
+ cut = min (sky_mode - dmin, dmax - sky_mode, k1 * sky_sigma)
+ hmin = sky_mode - cut
+ hmax = sky_mode + cut
+ dh = binsize * cut / k1
+ }
+
+ # Compute the number of histgram bins and the histogram resolution.
+ if (dh <= 0.0) {
+ nbins = 1
+ dh = 0.0
+ } else {
+ nbins = 2 * nint ((hmax - sky_mode) / dh) + 1
+ dh = (hmax - hmin) / (nbins - 1)
+ }
+
+ # Test for a valid histogram.
+ if (dh <= 0.0 || k1 <= 0.0 || sky_sigma <= 0.0 || sky_sigma <= dh ||
+ nbins < 2) {
+ sky_mode = sky_mode
+ sky_sigma = 0.0
+ sky_skew = 0.0
+ return (AP_NOHISTOGRAM)
+ }
+
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (x, nbins, TY_REAL)
+ call salloc (hgm, nbins, TY_REAL)
+ call salloc (shgm, nbins, TY_REAL)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Compute the x array and accumulate the histogram.
+ do i = 1, nbins
+ Memr[x+i-1] = i
+ call amapr (Memr[x], Memr[x], nbins, 1.0, real (nbins),
+ hmin + 0.5 * dh, hmax + 0.5 * dh)
+ call aclrr (Memr[hgm], nbins)
+ nsky_reject = nsky_reject + aphigmr (skypix, wgt, index, nskypix,
+ Memr[hgm], nbins, hmin, hmax)
+ nsky = nskypix - nsky_reject
+
+ # Subtract rejected pixels and recompute the moments.
+ if (nsky_reject > 0) {
+ do i = 1, nskypix {
+ if (wgt[index[i]] <= 0.0) {
+ dsky = skypix[index[i]] - sky_zero
+ sumpx = sumpx - dsky
+ sumsqpx = sumsqpx - dsky ** 2
+ sumcbpx = sumcbpx - dsky ** 3
+ }
+ }
+ }
+ call apmoments (sumpx, sumsqpx, sumcbpx, nsky, sky_zero, sky_mean,
+ sky_sigma, sky_skew)
+
+ # Smooth the histogram and compute the histogram plot limits.
+ if (smooth == YES) {
+ nker = max (1, nint (sky_sigma / dh))
+ #call ap_lucy_smooth (Memr[hgm], Memr[shgm], nbins, nker, 2)
+ call ap_bsmooth (Memr[hgm], Memr[shgm], nbins, nker, 2)
+ call alimr (Memr[hgm], nbins, ymin, ymax)
+ call alimr (Memr[shgm], nbins, symin, symax)
+ ymin = min (ymin, symin)
+ ymax = max (ymax, symax)
+ } else
+ call alimr (Memr[hgm], nbins, ymin, ymax)
+
+ # Store the old viewport and window coordinates.
+ call greactivate (gd, 0)
+ call ggview (gd, u1, u2, v1, v2)
+ call ggwind (gd, x1, x2, y1, y2)
+
+ # Plot the raw and smoothed histograms.
+ call ap_set_hplot (gd, gt, hmin, hmax, ymin, ymax, nbins, smooth)
+ if (smooth == YES) {
+ call ap_plothist (gd, gt, Memr[x], Memr[hgm], nbins, "histogram",
+ GL_SOLID)
+ call ap_plothist (gd, gt, Memr[x], Memr[shgm], nbins, "line",
+ GL_SOLID)
+ } else
+ call ap_plothist (gd, gt, Memr[x], Memr[hgm], nbins, "histogram",
+ GL_SOLID)
+
+ # Mark the peak of the histogram with the cursor.
+ call printf (
+ "Mark histogram peak (%g) [space=mark,q=quit,:.help=help:]")
+ call pargr (sky_mode)
+ call gscur (gd, sky_mode, (ymin + ymax) / 2.0)
+ while (clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+ if (key == 'q')
+ break
+ else
+ sky_mode = max (hmin, min (wx, hmax))
+ call printf (
+ "Mark histogram peak (%g) [space=mark,q=quit,:.help=help:]")
+ call pargr (sky_mode)
+ }
+
+ # Store the old viewport and window coordinates.
+ call gsview (gd, u1, u2, v1, v2)
+ call gswind (gd, x1, x2, y1, y2)
+
+ # Close up.
+ call gflush (gd)
+ call gdeactivate (gd, 0)
+ call sfree (sp)
+ return (AP_OK)
+end
+
+
+# AP_PLOTHIST -- Procedure plot the histogram.
+
+procedure ap_plothist (gd, gt, x, hgm, nbins, plottype, polytype)
+
+pointer gd # pointer to graphics stream
+pointer gt # GTOOLS pointer
+real x[ARB] # the histogram bin values
+real hgm[ARB] # histogram
+int nbins # number of bins
+char plottype[ARB] # the plot type "histogram" or "line"
+int polytype # polyline type
+
+begin
+ call gt_sets (gt, GTTYPE, plottype)
+ call gt_seti (gt, GTLINE, polytype)
+ call gt_plot (gd, gt, x, hgm, nbins)
+ call gflush (gd)
+end
+
+
+# AP_SET_HPLOT -- Procedure to set up the histogram plot.
+
+procedure ap_set_hplot (gd, gt, xmin, xmax, ymin, ymax, nbins, smooth)
+
+pointer gd # pointer to GRAPHICS stream
+pointer gt # pointer to GTOOLS structure
+real xmin, xmax # min and max of x vector
+real ymin, ymax # min and max of y vector
+int nbins # number of bins
+int smooth # smooth histogram
+
+pointer sp, str
+
+begin
+ # Initialize
+ call gclear (gd)
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Set up the gtools parameter string.
+ call sprintf (Memc[str], SZ_LINE,
+ "Sky Histogram: nbins = %d hmin = %g hmax = %g smooth=%b")
+ call pargi (nbins)
+ call pargr (xmin)
+ call pargr (xmax)
+ call pargi (smooth)
+ call gt_sets (gt, GTPARAMS, Memc[str])
+
+ # Set up the plot axes.
+ call gt_sets (gt, GTXLABEL, "Sky Values")
+ call gt_sets (gt, GTYLABEL, "Number of Pixels")
+ call gt_setr (gt, GTXMIN, xmin)
+ call gt_setr (gt, GTXMAX, xmax)
+ call gt_setr (gt, GTYMIN, ymin)
+ call gt_setr (gt, GTYMAX, ymax)
+ call gt_swind (gd, gt)
+ call gt_labax (gd, gt)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/fitsky/aplgsky.x b/noao/digiphot/apphot/fitsky/aplgsky.x
new file mode 100644
index 00000000..db5b4a19
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/aplgsky.x
@@ -0,0 +1,216 @@
+include <mach.h>
+include "../lib/fitsky.h"
+
+define TOL 0.001 # Fitting tolerance
+
+# AP_LGSKY -- Procedure to fit the peak and width of the histogram using
+# repeated convolutions and a triangle function.
+
+int procedure ap_lgsky (skypix, coords, wgt, index, nskypix, snx, sny, k1,
+ hwidth, binsize, smooth, losigma, hisigma, rgrow, maxiter, sky_mode,
+ sky_sigma, sky_skew, nsky, nsky_reject)
+
+real skypix[ARB] # array of sky pixels
+int coords[ARB] # array of coordinates of region growing
+real wgt[ARB] # array of weights for rejection
+int index[ARB] # array of sort indices
+int nskypix # the number of sky pixels
+int snx, sny # the maximum dimensions of sky raster
+real k1 # extent of the histogram in skysigma
+real hwidth # width of histogram
+real binsize # the size of the histogram in sky sigma
+int smooth # smooth the histogram before fitting
+real losigma, hisigma # upper and lower sigma rejection limits
+real rgrow # region growing radius in pixels
+int maxiter # maximum number of rejection cycles
+real sky_mode # computed sky value
+real sky_sigma # computed sigma of the sky pixels
+real sky_skew # skew of sky pixels
+int nsky # number of sky pixels used in fit
+int nsky_reject # number of sky pixels rejected
+
+double dsky, sumpx, sumsqpx, sumcbpx
+int nreject, nbins, nker, i, j, iter
+pointer sp, hgm, shgm
+real dmin, dmax, hmin, hmax, dh, locut, hicut, sky_mean, center, cut
+real sky_zero
+int ap_grow_hist2(), aphigmr(), aptopt()
+real ap_asumr(), apmedr(), apmapr()
+
+begin
+ # Initialize.
+ nsky = nskypix
+ nsky_reject = 0
+ sky_mode = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ if (nskypix <= 0)
+ return (AP_NOSKYAREA)
+
+ # Compute a first guess for the parameters.
+ sky_zero = ap_asumr (skypix, index, nskypix) / nskypix
+ call ap_ialimr (skypix, index, nskypix, dmin, dmax)
+ call apfimoments (skypix, index, nskypix, sky_zero, sumpx, sumsqpx,
+ sumcbpx, sky_mean, sky_sigma, sky_skew)
+ sky_mean = apmedr (skypix, index, nskypix)
+ sky_mean = max (dmin, min (sky_mean, dmax))
+
+ # Compute the width and bin size of histogram.
+ if (! IS_INDEFR(hwidth) && hwidth > 0.0) {
+ hmin = sky_mean - k1 * hwidth
+ hmax = sky_mean + k1 * hwidth
+ dh = binsize * hwidth
+ } else {
+ cut = min (sky_mean - dmin, dmax - sky_mean, k1 * sky_sigma)
+ hmin = sky_mean - cut
+ hmax = sky_mean + cut
+ dh = binsize * cut / k1
+ }
+
+ # Compute the number of histogram bins and the resolution.
+ # filter.
+ if (dh <= 0.0) {
+ nbins = 1
+ dh = 0.0
+ } else {
+ nbins = 2 * nint ((hmax - sky_mean) / dh) + 1
+ dh = (hmax - hmin) / (nbins - 1)
+ }
+
+ # Test for a valid histogram.
+ if (nbins < 2 || k1 <= 0.0 || sky_sigma <= 0.0 || dh <= 0.0 ||
+ sky_sigma <= dh) {
+ sky_mode = sky_mean
+ sky_sigma = 0.0
+ sky_skew = 0.0
+ return (AP_NOHISTOGRAM)
+ }
+
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (hgm, nbins, TY_REAL)
+ call salloc (shgm, nbins, TY_REAL)
+
+ # Accumulate the histogram.
+ call aclrr (Memr[hgm], nbins)
+ nsky_reject = nsky_reject + aphigmr (skypix, wgt, index, nskypix,
+ Memr[hgm], nbins, hmin, hmax)
+ nsky = nskypix - nsky_reject
+
+ # Perform the initial rejection.
+ if (nsky_reject > 0) {
+ do i = 1, nskypix {
+ if (wgt[index[i]] <= 0.0) {
+ dsky = skypix[index[i]] - sky_zero
+ sumpx = sumpx - dsky
+ sumsqpx = sumsqpx - dsky ** 2
+ sumcbpx = sumcbpx - dsky ** 3
+ }
+ }
+ call apmoments (sumpx, sumsqpx, sumcbpx, nsky, sky_zero,
+ sky_mean, sky_sigma, sky_skew)
+ }
+
+ # Fit the peak of the histogram.
+ center = apmapr ((hmin + hmax) / 2.0, hmin + 0.5 * dh,
+ hmax + 0.5 * dh, 1.0, real (nbins))
+ if (smooth == YES) {
+ nker = max (1, nint (sky_sigma / dh))
+ #call ap_lucy_smooth (Memr[hgm], Memr[shgm], nbins, nker, 2)
+ call ap_bsmooth (Memr[hgm], Memr[shgm], nbins, nker, 2)
+ iter = aptopt (Memr[shgm], nbins, center, sky_sigma / dh,
+ TOL, maxiter, NO)
+ } else
+ iter = aptopt (Memr[hgm], nbins, center, sky_sigma / dh, TOL,
+ maxiter, NO)
+ sky_mode = apmapr (center, 1.0, real (nbins), hmin + 0.5 * dh,
+ hmax + 0.5 * dh)
+ sky_mode = max (dmin, min (sky_mode, dmax))
+ if (iter < 0) {
+ call sfree (sp)
+ return (AP_SKY_NOCONVERGE)
+ }
+ if ((IS_INDEFR(losigma) && IS_INDEFR(hisigma)) || (sky_sigma <= dh) ||
+ (maxiter < 1)) {
+ call sfree (sp)
+ return (AP_OK)
+ }
+
+ # Fit the histogram with pixel rejection and optional region growing.
+ do i = 1, maxiter {
+
+ # Compute new histogram limits.
+ if (IS_INDEFR(losigma))
+ locut = -MAX_REAL
+ else
+ locut = sky_mode - losigma * sky_sigma
+ if (IS_INDEFR(hisigma))
+ hicut = MAX_REAL
+ else
+ hicut = sky_mode + hisigma * sky_sigma
+
+ # Detect and reject the pixels.
+ nreject = 0
+ do j = 1, nskypix {
+ if (skypix[index[j]] >= locut && skypix[index[j]] <= hicut)
+ next
+ if (rgrow > 0.0)
+ nreject = nreject + ap_grow_hist2 (skypix, coords,
+ wgt, nskypix, sky_zero, index[j], snx, sny, Memr[hgm],
+ nbins, hmin, hmax, rgrow, sumpx, sumsqpx, sumcbpx)
+ else if (wgt[index[j]] > 0.0) {
+ call ap_hgmsub2 (Memr[hgm], nbins, hmin, hmax,
+ skypix[index[j]], sky_zero, sumpx, sumsqpx, sumcbpx)
+ wgt[index[j]] = 0.0
+ nreject = nreject + 1
+ }
+ }
+ if (nreject == 0)
+ break
+
+ # Recompute the data limits.
+ nsky_reject = nsky_reject + nreject
+ nsky = nskypix - nsky_reject
+ if (nsky <= 0)
+ break
+ call apmoments (sumpx, sumsqpx, sumcbpx, nsky, sky_zero,
+ sky_mean, sky_sigma, sky_skew)
+ if (sky_sigma <= dh)
+ break
+
+ # Refit the sky.
+ if (smooth == YES) {
+ nker = max (1, nint (sky_sigma / dh))
+ #call ap_lucy_smooth (Memr[hgm], Memr[shgm], nbins, nker, 2)
+ call ap_bsmooth (Memr[hgm], Memr[shgm], nbins, nker, 2)
+ iter = aptopt (Memr[shgm], nbins, center, sky_sigma / dh,
+ TOL, maxiter, NO)
+ } else
+ iter = aptopt (Memr[hgm], nbins, center, sky_sigma / dh,
+ TOL, maxiter, NO)
+ sky_mode = apmapr (center, 1.0, real (nbins), hmin + 0.5 * dh,
+ hmax + 0.5 * dh)
+ sky_mode = max (dmin, min (sky_mode, dmax))
+ if (iter < 0)
+ break
+ }
+
+ # Return an appropriate error code.
+ call sfree (sp)
+ if (nsky == 0 || nsky_reject == nskypix) {
+ nsky = 0
+ nsky_reject = nskypix
+ sky_mode = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ return (AP_NSKY_TOO_SMALL)
+ } else if (sky_sigma <= 0.0) {
+ sky_sigma = 0.0
+ sky_skew = 0.0
+ return (AP_OK)
+ } else if (iter < 0) {
+ return (AP_SKY_NOCONVERGE)
+ } else {
+ return (AP_OK)
+ }
+end
diff --git a/noao/digiphot/apphot/fitsky/apmean.x b/noao/digiphot/apphot/fitsky/apmean.x
new file mode 100644
index 00000000..f134f02c
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apmean.x
@@ -0,0 +1,120 @@
+include <mach.h>
+include "../lib/fitsky.h"
+
+# AP_MEAN -- Procedure to calculate the mean of the sky pixel array.
+
+int procedure ap_mean (skypix, coords, wgt, index, nskypix, snx, sny, losigma,
+ hisigma, rgrow, maxiter, sky_mean, sky_sigma, sky_skew, nsky,
+ nsky_reject)
+
+real skypix[ARB] # unsorted array of skypixels
+int coords[ARB] # coordinate array for region growing
+real wgt[ARB] # the weight array for rejection
+int index[ARB] # sorted array of indices
+int nskypix # total number of sky pixels
+int snx, sny # dimensions of the sky subraster
+real losigma, hisigma # number of sky_sigma for rejection
+real rgrow # radius of region growing
+int maxiter # maximum number of cycles of rejection
+real sky_mean # computed sky value
+real sky_sigma # the computed sky sigma
+real sky_skew # skewness of sky distribution
+int nsky # the number of sky pixels used
+int nsky_reject # the number of sky pixels rejected
+
+double dsky, sumpx, sumsqpx, sumcbpx
+int i, j, nreject
+real sky_zero, dmin, dmax, locut, hicut
+int ap_grow_regions()
+real ap_asumr()
+
+begin
+ # Intialize.
+ nsky = nskypix
+ nsky_reject = 0
+ sky_mean = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ if (nskypix <= 0)
+ return (AP_NOSKYAREA)
+
+ # Compute the mean, sigma and skew.
+ sky_zero = ap_asumr (skypix, index, nskypix) / nskypix
+ call apfimoments (skypix, index, nskypix, sky_zero, sumpx, sumsqpx,
+ sumcbpx, sky_mean, sky_sigma, sky_skew)
+ call ap_ialimr (skypix, index, nskypix, dmin, dmax)
+ sky_mean = max (dmin, min (sky_mean, dmax))
+
+ # Decide whether to do the rejection cycle.
+ if (maxiter < 1 || (IS_INDEFR(losigma) && IS_INDEFR(hisigma)) ||
+ sky_sigma <= 0.0)
+ return (AP_OK)
+
+ # Reject points within k1 * sky_sigma of the median.
+ do i = 1, maxiter {
+
+ # Compute the new rejection limits.
+ if (IS_INDEFR(losigma))
+ locut = max (-MAX_REAL, dmin)
+ else if (i == 1)
+ locut = sky_mean - min (sky_mean - dmin, dmax - sky_mean,
+ losigma * sky_sigma)
+ else
+ locut = sky_mean - losigma * sky_sigma
+ if (IS_INDEFR(hisigma))
+ hicut = min (MAX_REAL, dmax)
+ else if (i == 1)
+ hicut = sky_mean + min (dmax - sky_mean, sky_mean - dmin,
+ hisigma * sky_sigma)
+ else
+ hicut = sky_mean + hisigma * sky_sigma
+
+ nreject = 0
+ do j = 1, nskypix {
+ if (wgt[index[j]] <= 0.0)
+ next
+ if (skypix[index[j]] < locut || skypix[index[j]] > hicut) {
+ if (rgrow > 0.0) {
+ nreject = ap_grow_regions (skypix, coords, wgt,
+ nskypix, sky_zero, index[j], snx, sny, rgrow,
+ sumpx, sumsqpx, sumcbpx)
+ } else {
+ dsky = (skypix[index[j]] - sky_zero)
+ sumpx = sumpx - dsky
+ sumsqpx = sumsqpx - dsky ** 2
+ sumcbpx = sumcbpx - dsky ** 3
+ wgt[index[j]] = 0.0
+ nreject = nreject + 1
+ }
+ }
+ }
+
+ # Test the number of rejected pixels.
+ if (nreject <= 0)
+ break
+ nsky_reject = nsky_reject + nreject
+
+ # Test that some pixels actually remain.
+ nsky = nskypix - nsky_reject
+ if (nsky <= 0)
+ break
+
+ # Recompute the mean, sigma and skew.
+ call apmoments (sumpx, sumsqpx, sumcbpx, nsky, sky_zero,
+ sky_mean, sky_sigma, sky_skew)
+ if (sky_sigma <= 0.0)
+ break
+ sky_mean = max (dmin, min (sky_mean, dmax))
+ }
+
+ # Return an appropriate error code.
+ if (nsky == 0 || nsky_reject == nskypix) {
+ nsky = 0
+ nsky_reject = nskypix
+ sky_mean = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ return (AP_NSKY_TOO_SMALL)
+ } else
+ return (AP_OK)
+end
diff --git a/noao/digiphot/apphot/fitsky/apmedian.x b/noao/digiphot/apphot/fitsky/apmedian.x
new file mode 100644
index 00000000..5998492c
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apmedian.x
@@ -0,0 +1,184 @@
+include <mach.h>
+include "../lib/fitsky.h"
+
+define MEDCUT 0.025
+
+# AP_MEDIAN -- Procedure to calculate the median of the sky pixel array.
+
+int procedure ap_median (skypix, coords, wgt, index, nskypix, snx, sny, losigma,
+ hisigma, rgrow, maxiter, sky_med, sky_sigma, sky_skew, nsky,
+ nsky_reject)
+
+real skypix[ARB] # unsorted array of sky pixels
+int coords[ARB] # coordinate array for regions growing
+real wgt[ARB] # array of weights for rejections
+int index[ARB] # sky pixel indices in sort order
+int nskypix # total number of sky pixels
+int snx, sny # dimensions of the sky subraster
+real losigma, hisigma # upper and lower sigma for rejection
+real rgrow # radius of region growing
+int maxiter # maximum number of cycles of rejection
+real sky_med # computed sky value
+real sky_sigma # the computed sky sigma
+real sky_skew # skewness of sky distribution
+int nsky # the number of sky pixels used
+int nsky_reject # the number of sky pixels rejected
+
+double dsky, sumpx, sumsqpx, sumcbpx
+int i, j, ilo, ihi, il, ih, med, medcut
+real sky_zero, sky_mean, locut, hicut, dmin, dmax
+int ap_grow_regions(), apimed()
+real apsmed(), apwsmed(), ap_asumr()
+
+begin
+ # Intialize.
+ nsky = nskypix
+ nsky_reject = 0
+ sky_med = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ if (nskypix <= 0)
+ return (AP_NOSKYAREA)
+
+ # Sort the sky pixels and compute the median, mean, sigma and skew.
+ # MEDCUT tries to correct for quantization effects
+ call ap_ialimr (skypix, index, nskypix, dmin, dmax)
+ sky_zero = ap_asumr (skypix, index, nskypix) / nskypix
+ medcut = nint (MEDCUT * real (nskypix))
+ sky_med = apsmed (skypix, index, nskypix, medcut)
+ sky_med = max (dmin, min (sky_med, dmax))
+ call apfimoments (skypix, index, nskypix, sky_zero, sumpx, sumsqpx,
+ sumcbpx, sky_mean, sky_sigma, sky_skew)
+ sky_mean = max (dmin, min (sky_mean, dmax))
+ if (maxiter < 1 || (IS_INDEFR(losigma) && IS_INDEFR(hisigma)) ||
+ sky_sigma <= 0.0)
+ return (AP_OK)
+ #call printf (
+ #"mean=%g med=%g sigma=%g nsky=%d nrej=%d dmin=%g dmax=%g\n")
+ #call pargr (sky_mean)
+ #call pargr (sky_med)
+ #call pargr (sky_sigma)
+ #call pargi (nsky)
+ #call pargi (nsky_reject)
+ #call pargr (dmin)
+ #call pargr (dmax)
+
+ # Reject points outside losigma * sky_sigma and hisigma * sky_sigma
+ # of the median.
+ ilo = 1
+ ihi = nskypix
+ do i = 1, maxiter {
+
+ # Compute the new rejection limits.
+ if (IS_INDEFR(losigma))
+ locut = max (-MAX_REAL, dmin)
+ else if (i == 1)
+ locut = sky_med - min (sky_med - dmin, dmax - sky_med,
+ losigma * sky_sigma)
+ else
+ locut = sky_med - losigma * sky_sigma
+ if (IS_INDEFR(hisigma))
+ hicut = min (MAX_REAL, dmax)
+ else if (i == 1)
+ hicut = sky_med + min (dmax - sky_med, sky_med - dmin,
+ hisigma * sky_sigma)
+ else
+ hicut = sky_med + hisigma * sky_sigma
+ #call printf (" locut=%g hicut=%g\n")
+ #call pargr (locut)
+ #call pargr (hicut)
+
+ # Detect pixels to be rejected.
+ for (il = ilo; il <= nskypix; il = il + 1) {
+ if (skypix[index[il]] >= locut)
+ break
+ }
+ for (ih = ihi; ih >= 1; ih = ih - 1) {
+ if (skypix[index[ih]] <= hicut)
+ break
+ }
+ if (il == ilo && ih == ihi)
+ break
+
+ # Reject pixels with optional region growing.
+ if (rgrow > 0.0) {
+
+ # Reject low side pixels with region growing.
+ do j = ilo, il - 1
+ nsky_reject = nsky_reject + ap_grow_regions (skypix, coords,
+ wgt, nskypix, sky_zero, index[j], snx, sny, rgrow,
+ sumpx, sumsqpx, sumcbpx)
+
+ # Reject high side pixels with region growing.
+ do j = ih + 1, ihi
+ nsky_reject = nsky_reject + ap_grow_regions (skypix, coords,
+ wgt, nskypix, sky_zero, index[j], snx, sny, rgrow,
+ sumpx, sumsqpx, sumcbpx)
+
+ # Recompute the median.
+ # and the median pixel
+ nsky = nskypix - nsky_reject
+ med = apimed (wgt, index, il, ih, (nsky + 1) / 2)
+
+
+ } else {
+
+ # Recompute the number of sky pixels, the number of rejected
+ # pixels and median pixel
+ nsky_reject = nsky_reject + (il - ilo) + (ihi - ih)
+ nsky = nskypix - nsky_reject
+ med = (ih + il) / 2
+
+ # Reject pixels on the low side.
+ do j = ilo, il - 1 {
+ dsky = skypix[index[j]] - sky_zero
+ sumpx = sumpx - dsky
+ sumsqpx = sumsqpx - dsky ** 2
+ sumcbpx = sumcbpx - dsky ** 3
+ }
+
+ # Reject pixels on the high side.
+ do j = ih + 1, ihi {
+ dsky = skypix[index[j]] - sky_zero
+ sumpx = sumpx - dsky
+ sumsqpx = sumsqpx - dsky ** 2
+ sumcbpx = sumcbpx - dsky ** 3
+ }
+ }
+ if (nsky <= 0)
+ break
+
+ # Recompute the median, sigma and skew.
+ medcut = nint (MEDCUT * real (nsky))
+ sky_med = apwsmed (skypix, index, wgt, nskypix, med, medcut)
+ sky_med = max (dmin, min (sky_med, dmax))
+ call apmoments (sumpx, sumsqpx, sumcbpx, nsky, sky_zero,
+ sky_mean, sky_sigma, sky_skew)
+ sky_mean = max (dmin, min (sky_mean, dmax))
+ #call printf (
+ #" mean=%g med=%g sigma=%g nsky=%d nrej=%d dmin=%g dmax=%g\n")
+ #call pargr (sky_mean)
+ #call pargr (sky_med)
+ #call pargr (sky_sigma)
+ #call pargi (nsky)
+ #call pargi (nsky_reject)
+ #call pargr (dmin)
+ #call pargr (dmax)
+
+ if (sky_sigma <= 0.0)
+ break
+ ilo = il
+ ihi = ih
+ }
+
+ # Return an appropriate error code.
+ if (nsky == 0 || nsky_reject == nskypix) {
+ nsky = 0
+ nsky_reject = nskypix
+ sky_med = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ return (AP_NSKY_TOO_SMALL)
+ } else
+ return (AP_OK)
+end
diff --git a/noao/digiphot/apphot/fitsky/apmode.x b/noao/digiphot/apphot/fitsky/apmode.x
new file mode 100644
index 00000000..fc32ba43
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apmode.x
@@ -0,0 +1,185 @@
+include <mach.h>
+include "../lib/fitsky.h"
+
+define MEDCUT 0.025
+
+# AP_MODE -- Procedure to calculate the mode of the sky pixel array.
+
+int procedure ap_mode (skypix, coords, wgt, index, nskypix, snx, sny, losigma,
+ hisigma, rgrow, maxiter, sky_mode, sky_sigma, sky_skew, nsky,
+ nsky_reject)
+
+real skypix[ARB] # unsorted array of skypixels
+int coords[ARB] # coordinate array for regions growing
+real wgt[ARB] # array of weights for rejection
+int index[ARB] # indices in sort order
+int nskypix # total number of sky pixels
+int snx, sny # dimensions of the sky subraster
+real losigma, hisigma # number of sky_sigma for rejection
+real rgrow # radius of region growing
+int maxiter # maximum number of cycles of rejection
+real sky_mode # computed sky value
+real sky_sigma # the computed sky sigma
+real sky_skew # skew of sky pixels
+int nsky # the number of sky pixels used
+int nsky_reject # the number of sky pixels rejected
+
+double dsky, sumpx, sumsqpx, sumcbpx
+int i, j, ilo, ihi, il, ih, med, medcut
+real dmin, dmax, locut, hicut, sky_zero, sky_mean, sky_med
+int ap_grow_regions(), apimed()
+real apsmed(), apwsmed(), ap_asumr()
+
+begin
+ # Initialize.
+ nsky = nskypix
+ nsky_reject = 0
+ sky_mode = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ if (nskypix <= 0)
+ return (AP_NOSKYAREA)
+
+ # Compute the median, sigma, skew and sky mode.
+ sky_zero = ap_asumr (skypix, index, nskypix) / nskypix
+ call ap_ialimr (skypix, index, nskypix, dmin, dmax)
+ medcut = nint (MEDCUT * real (nskypix))
+ sky_med = apsmed (skypix, index, nskypix, medcut)
+ sky_med = max (dmin, min (sky_med, dmax))
+ call apfimoments (skypix, index, nskypix, sky_zero, sumpx, sumsqpx,
+ sumcbpx, sky_mean, sky_sigma, sky_skew)
+ sky_mean = max (dmin, min (sky_mean, dmax))
+ if (sky_mean < sky_med)
+ sky_mode = sky_mean
+ else
+ sky_mode = 3.0 * sky_med - 2.0 * sky_mean
+ sky_mode = max (dmin, min (sky_mode, dmax))
+ if (maxiter < 1 || (IS_INDEFR(losigma) && IS_INDEFR(hisigma)) ||
+ sky_sigma <= 0.0)
+ return (AP_OK)
+
+ # Reject points outside losigma * sky_sigma and hisigma * sky_sigma
+ # of the mode.
+ ilo = 1
+ ihi = nskypix
+ do i = 1, maxiter {
+
+ # Compute the new rejection limits.
+ if (i == 1) {
+ if (IS_INDEFR(losigma))
+ locut = max (-MAX_REAL, dmin)
+ else
+ locut = sky_med - min (sky_med - dmin, dmax - sky_med,
+ losigma * sky_sigma)
+ if (IS_INDEFR(hisigma))
+ hicut = min (MAX_REAL, dmax)
+ else
+ hicut = sky_med + min (sky_med - dmin, dmax - sky_med,
+ hisigma * sky_sigma)
+ } else {
+ if (IS_INDEFR(losigma))
+ locut = max (-MAX_REAL, dmin)
+ else
+ locut = sky_mode - losigma * sky_sigma
+ if (IS_INDEFR(hisigma))
+ hicut = min (MAX_REAL, dmax)
+ else
+ hicut = sky_mode + hisigma * sky_sigma
+ }
+ #call eprintf ("i=%d mean=%g median=%g mode=%g locut=%g hicut=%g\n")
+ #call pargi (i)
+ #call pargr (sky_mean)
+ #call pargr (sky_med)
+ #call pargr (sky_mode)
+ #call pargr (locut)
+ #call pargr (hicut)
+
+ # Perform lower bound pixel rejection.
+ for (il = ilo; il <= nskypix; il = il + 1) {
+ if (skypix[index[il]] >= locut)
+ break
+ }
+
+ # Perform upper bound pixel rejection.
+ for (ih = ihi; ih >= 1; ih = ih - 1) {
+ if (skypix[index[ih]] <= hicut)
+ break
+ }
+ if (il == ilo && ih == ihi)
+ break
+
+ # Compute number of rejected pixels with optional region growing.
+ if (rgrow > 0.0) {
+
+ # Reject lower bound pixels with region growing.
+ do j = ilo, il - 1
+ nsky_reject = nsky_reject + ap_grow_regions (skypix, coords,
+ wgt, nskypix, sky_zero, index[j], snx, sny, rgrow,
+ sumpx, sumsqpx, sumcbpx)
+
+ # Reject upper bound pixels with region growing.
+ do j = ih + 1, ihi
+ nsky_reject = nsky_reject + ap_grow_regions (skypix, coords,
+ wgt, nskypix, sky_zero, index[j], snx, sny, rgrow,
+ sumpx, sumsqpx, sumcbpx)
+
+ # Compute the new median.
+ nsky = nskypix - nsky_reject
+ med = apimed (wgt, index, il, ihi, (nsky + 1) / 2)
+
+ } else {
+
+ # Recompute the number of sky pixels, number of rejected
+ # pixels and the median.
+ nsky_reject = nsky_reject + (il - ilo) + (ihi - ih)
+ nsky = nskypix - nsky_reject
+ med = (ih + il) / 2
+
+ # Reject number of lower bound pixels.
+ do j = ilo, il - 1 {
+ dsky = skypix[index[j]] - sky_zero
+ sumpx = sumpx - dsky
+ sumsqpx = sumsqpx - dsky ** 2
+ sumcbpx = sumcbpx - dsky ** 3
+ }
+
+ # Reject number of upper bound pixels.
+ do j = ih + 1, ihi {
+ dsky = skypix[index[j]] - sky_zero
+ sumpx = sumpx - dsky
+ sumsqpx = sumsqpx - dsky ** 2
+ sumcbpx = sumcbpx - dsky ** 3
+ }
+ }
+ if (nsky <= 0)
+ break
+
+ # Recompute mean, median, mode, sigma and skew.
+ medcut = nint (MEDCUT * real (nsky))
+ sky_med = apwsmed (skypix, index, wgt, nskypix, med, medcut)
+ sky_med = max (dmin, min (sky_med, dmax))
+ call apmoments (sumpx, sumsqpx, sumcbpx, nsky, sky_zero,
+ sky_mean, sky_sigma, sky_skew)
+ sky_mean = max (dmin, min (sky_mean, dmax))
+ if (sky_mean < sky_med)
+ sky_mode = sky_mean
+ else
+ sky_mode = 3.0 * sky_med - 2.0 * sky_mean
+ sky_mode = max (dmin, min (sky_mode, dmax))
+ if (sky_sigma <= 0.0)
+ break
+ ilo = il
+ ihi = ih
+ }
+
+ # Return an appropriate error code.
+ if (nsky == 0 || nsky_reject == nskypix) {
+ nsky = 0
+ nsky_reject = nskypix
+ sky_mode = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ return (AP_NSKY_TOO_SMALL)
+ } else
+ return (AP_OK)
+end
diff --git a/noao/digiphot/apphot/fitsky/appsky.x b/noao/digiphot/apphot/fitsky/appsky.x
new file mode 100644
index 00000000..8da9773e
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/appsky.x
@@ -0,0 +1,103 @@
+include "../lib/apphot.h"
+include "../lib/fitsky.h"
+
+# AP_PSSKY -- Procedure to write the results of the fitsky task to
+# the output file.
+
+procedure ap_pssky (ap, fd, id, ld, ier)
+
+pointer ap # pointer to apphot structure
+int fd # output file descriptor
+int id # sequence number of star
+int ld # list number of star
+int ier # error code
+
+real apstatr()
+
+begin
+ # Return if NULL file descriptor.
+ if (fd == NULL)
+ return
+
+ # Print the object id and computed sky values.
+ call ap_wid (ap, fd, apstatr (ap, OSXCUR), apstatr (ap, OSYCUR), id,
+ ld, '\\')
+ call ap_wsres (ap, fd, ier, ' ')
+end
+
+
+# AP_QSPSKY -- Procedure to print a quick summary of the fitsky task on the
+# standard output.
+
+procedure ap_qspsky (ap, ier)
+
+pointer ap # pointer to apphot structure
+int ier # error code
+
+pointer sp, imname
+int apstati()
+real apstatr()
+
+begin
+ # Print out the results on the standard output.
+ call smark (sp)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+ call apstats (ap, IMROOT, Memc[imname], SZ_FNAME)
+ call printf ( "%s %8.2f %8.2f %8g %8g ")
+ call pargstr (Memc[imname])
+ call pargr (apstatr (ap, OSXCUR))
+ call pargr (apstatr (ap, OSYCUR))
+ call pargr (apstatr (ap, SKY_MODE))
+ call pargr (apstatr (ap, SKY_SIGMA))
+ call printf ("%8g %5d %5d %s\n")
+ call pargr (apstatr (ap, SKY_SKEW))
+ call pargi (apstati (ap, NSKY))
+ call pargi (apstati (ap, NSKY_REJECT))
+ if (ier != AP_OK)
+ call pargstr ("err")
+ else
+ call pargstr ("ok")
+ call sfree (sp)
+end
+
+
+# AP_QASPSKY -- Procedure to print a quick summary of the fitsky task on the
+# standard output.
+
+procedure ap_qaspsky (ap, ier)
+
+pointer ap # pointer to apphot structure
+int ier # error code
+
+int apstati()
+real apstatr()
+
+begin
+ # Print out the results on the standard output.
+ call printf ( " Averages %8g %8g ")
+ call pargr (apstatr (ap, SKY_MODE))
+ call pargr (apstatr (ap, SKY_SIGMA))
+ call printf ("%8g %5d %5d %s\n\n")
+ call pargr (apstatr (ap, SKY_SKEW))
+ call pargi (apstati (ap, NSKY))
+ call pargi (apstati (ap, NSKY_REJECT))
+ if (ier != AP_OK)
+ call pargstr ("err")
+ else
+ call pargstr ("ok")
+end
+
+# AP_SPHDR -- Procedure to write the banner for the fitsky task to the
+# output file.
+
+procedure ap_sphdr (ap, fd)
+
+pointer ap # pointer to apphot structure
+int fd # output file descriptor
+
+begin
+ if (fd == NULL)
+ return
+ call ap_idhdr (ap, fd)
+ call ap_shdr (ap, fd)
+end
diff --git a/noao/digiphot/apphot/fitsky/appspars.x b/noao/digiphot/apphot/fitsky/appspars.x
new file mode 100644
index 00000000..50da0f84
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/appspars.x
@@ -0,0 +1,22 @@
+include "../lib/display.h"
+
+# AP_PSPARS -- Procedure to write out the current sky fitting parameters
+# to the parameter files.
+
+procedure ap_pspars (ap)
+
+pointer ap # pointer to apphot structure
+
+bool itob()
+int apstati()
+
+begin
+ # Write the data dependent parameters.
+ call ap_dapars (ap)
+
+ # Write the sky fitting parameters.
+ call ap_sapars (ap)
+
+ # Radial profile plots
+ call clputb ("radplots", itob (apstati (ap, RADPLOTS)))
+end
diff --git a/noao/digiphot/apphot/fitsky/apradplot.x b/noao/digiphot/apphot/fitsky/apradplot.x
new file mode 100644
index 00000000..d9d19992
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apradplot.x
@@ -0,0 +1,91 @@
+include "../lib/fitsky.h"
+
+# AP_RADPLOT -- Procedure to compute the mode, sigma, and skew of the sky by
+# eye using a radial profile plot of the sky pixels and cursor readback.
+
+int procedure ap_radplot (gd, gt, skypix, coords, index, nskypix, sxc, syc,
+ snx, sny, scale, sky_mode, sky_skew, sky_sigma, nsky,
+ nsky_reject)
+
+pointer gd # pointer to graphics stream
+pointer gt # pointer to gtools structure
+real skypix[ARB] # array of sky pixels
+int coords[ARB] # array of sky coordinates
+int index[ARB] # the index array
+int nskypix # number of sky pixels
+real sxc, syc # sky subraster center
+int snx, sny # sky subraster size
+real scale # the image scale
+real sky_mode # computed sky value
+real sky_sigma # computed sigma of sky pixels
+real sky_skew # computed skew of sky pixels
+int nsky # number of sky pixels used in fit
+int nsky_reject # number of rejected sky pixels
+
+double sumpx, sumsqpx, sumcbpx
+int wcs, key
+pointer sp, r, cmd
+real wx, wy, xmin, xmax, ymin, ymax, u1, u2, v1, v2, x1, x2, y1, y2
+real sky_zero
+int clgcur()
+real ap_asumr()
+
+begin
+ if (gd == NULL)
+ return (AP_NOGRAPHICS)
+
+ # Initialize.
+ nsky = nskypix
+ nsky_reject = 0
+ sky_mode = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ if (nskypix <= 0)
+ return (AP_SKY_OUTOFBOUNDS)
+
+ call smark (sp)
+ call salloc (r, nskypix, TY_REAL)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Compute an initial guess at the data characteristics.
+ nsky = nskypix
+ sky_zero = ap_asumr (skypix, index, nskypix) / nskypix
+ call apfimoments (skypix, index, nskypix, sky_zero, sumpx, sumsqpx,
+ sumcbpx, sky_mode, sky_sigma, sky_skew)
+
+ # Store the old window and viewport coordinates.
+ call ggview (gd, u1, u2, v1, v2)
+ call ggwind (gd, x1, x2, y1, y2)
+
+ # Compute the radial profile
+ call ap_xytor (coords, index, Memr[r], nskypix, sxc, syc, snx)
+ call alimr (Memr[r], nskypix, xmin, xmax)
+ call alimr (skypix, nskypix, ymin, ymax)
+
+ # Plot the radial profile.
+ call gclear (gd)
+ call ap_rset (gd, gt, xmin, xmax, ymin, ymax, scale)
+ call ap_plotrad (gd, gt, Memr[r], skypix, nskypix, "plus")
+
+ # Mark the sky level with the cursor.
+ call printf ("Mark sky level (%g) [space=mark,q=quit,:.help=help]:")
+ call pargr (sky_mode)
+ call gscur (gd, (xmin + xmax) / 2.0, sky_mode)
+ while (clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+ if (key == 'q')
+ break
+ else
+ sky_mode = wy
+ call printf ("Mark sky level (%g) [space=mark,q=quit,:.help=help]:")
+ call pargr (sky_mode)
+ call gscur (gd, (xmin + xmax) / 2.0, sky_mode)
+ }
+
+ # Store the old window and viewport coordinates.
+ call gsview (gd, u1, u2, v1, v2)
+ call gswind (gd, x1, x2, y1, y2)
+
+ call sfree (sp)
+ return (AP_OK)
+end
diff --git a/noao/digiphot/apphot/fitsky/apreadsky.x b/noao/digiphot/apphot/fitsky/apreadsky.x
new file mode 100644
index 00000000..3db9a183
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apreadsky.x
@@ -0,0 +1,40 @@
+# AP_READSKY -- Procedure to read sky values, sigma and skew from a file
+# The x and y positions, sky mode, sigma, and skew values, number of sky
+# pixels and number of rejected sky pixels are assumed to be columns
+# 1 to 7 respectively.
+
+int procedure ap_readsky (fd, x, y, sky_mode, sky_sigma, sky_skew, nsky,
+ nsky_reject)
+
+int fd # sky file descriptor
+real x, y # center of sky annulus
+real sky_mode # sky valye
+real sky_sigma # sky sigma
+real sky_skew # skew of sky pixels
+int nsky # number of sky pixels
+int nsky_reject # number of rejected pixesl
+
+int stat
+int fscan(), nscan()
+
+begin
+ # Initialize.
+ sky_mode = INDEFR
+ sky_sigma = INDEFR
+ sky_skew = INDEFR
+ nsky = 0
+ nsky_reject = 0
+
+ # Read in and decode a sky file text line.
+ stat = fscan (fd)
+ if (stat == EOF)
+ return (EOF)
+ call gargr (x)
+ call gargr (y)
+ call gargr (sky_mode)
+ call gargr (sky_sigma)
+ call gargr (sky_skew)
+ call gargi (nsky)
+ call gargi (nsky_reject)
+ return (nscan ())
+end
diff --git a/noao/digiphot/apphot/fitsky/aprefitsky.x b/noao/digiphot/apphot/fitsky/aprefitsky.x
new file mode 100644
index 00000000..bc4ed6c2
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/aprefitsky.x
@@ -0,0 +1,371 @@
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/noisedef.h"
+include "../lib/fitskydef.h"
+include "../lib/fitsky.h"
+
+# APREFITSKY -- Procedure to fit the sky using the pixels currently stored in
+# the sky fitting buffers.
+
+int procedure aprefitsky (ap, im, gd)
+
+pointer ap # pointer to the apphot structure
+pointer im # the input image descriptor
+pointer gd # pointer to graphics stream
+
+int ier, nclip, nsky, ilo, ihi
+pointer sky, nse, gt
+int ap_mode(), ap_centroid(), ap_histplot(), ap_median()
+int ap_radplot(), ap_gauss(), ap_lgsky(), ap_crosscor()
+int ap_mean(), ap_clip()
+pointer ap_gtinit()
+
+begin
+ # Initialize.
+ sky = AP_PSKY(ap)
+ nse = AP_NOISE(ap)
+ AP_SKY_MODE(sky) = INDEFR
+ AP_SKY_SIG(sky) = INDEFR
+ AP_SKY_SKEW(sky) = INDEFR
+ AP_NSKY(sky) = 0
+ AP_NSKY_REJECT(sky) = 0
+ if (IS_INDEFR(AP_SXCUR(sky)) || IS_INDEFR(AP_SYCUR(sky))) {
+ AP_OSXCUR(sky) = AP_SXCUR(sky)
+ AP_OSYCUR(sky) = AP_SYCUR(sky)
+ } else {
+ switch (AP_WCSOUT(ap)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (ap, AP_SXCUR(sky), AP_SYCUR(sky), AP_OSXCUR(sky),
+ AP_OSYCUR(sky), 1)
+ case WCS_TV:
+ call ap_ltov (im, AP_SXCUR(sky), AP_SYCUR(sky), AP_OSXCUR(sky),
+ AP_OSYCUR(sky), 1)
+ default:
+ AP_OSXCUR(sky) = AP_SXCUR(sky)
+ AP_OSYCUR(sky) = AP_SYCUR(sky)
+ }
+ }
+
+ if (IS_INDEFR(AP_SXCUR(sky)) || IS_INDEFR(AP_SYCUR(sky)))
+ return (AP_NOSKYAREA)
+
+ switch (AP_SKYFUNCTION(sky)) {
+
+ case AP_MEAN:
+
+ # Initialize the weights.
+ call amovkr (1.0, Memr[AP_SWGT(sky)], AP_NSKYPIX(sky))
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky), ilo,
+ ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call ap_index (Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ ier = ap_mean (Memr[AP_SKYPIX(sky)], Memi[AP_COORDS(sky)],
+ Memr[AP_SWGT(sky)], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_SNX(sky), AP_SNY(sky), AP_SLOREJECT(sky),
+ AP_SHIREJECT(sky), AP_RGROW(sky) * AP_SCALE(ap),
+ AP_SNREJECT(sky), AP_SKY_MODE(sky), AP_SKY_SIG(sky),
+ AP_SKY_SKEW(sky), AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+
+ return (ier)
+
+ case AP_MEDIAN:
+
+ # Initialize the weights.
+ call amovkr (1.0, Memr[AP_SWGT(sky)], AP_NSKYPIX(sky))
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky), ilo,
+ ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call apqsort (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ ier = ap_median (Memr[AP_SKYPIX(sky)], Memi[AP_COORDS(sky)],
+ Memr[AP_SWGT(sky)], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_SNX(sky), AP_SNY(sky), AP_SLOREJECT(sky),
+ AP_SHIREJECT(sky), AP_RGROW(sky) * AP_SCALE(ap),
+ AP_SNREJECT(sky), AP_SKY_MODE(sky), AP_SKY_SIG(sky),
+ AP_SKY_SKEW(sky), AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+ return (ier)
+
+ case AP_MODE:
+
+ # Initialize the weights.
+ call amovkr (1.0, Memr[AP_SWGT(sky)], AP_NSKYPIX(sky))
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky), ilo,
+ ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call apqsort (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ ier = ap_mode (Memr[AP_SKYPIX(sky)], Memi[AP_COORDS(sky)],
+ Memr[AP_SWGT(sky)], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_SNX(sky), AP_SNY(sky), AP_SLOREJECT(sky),
+ AP_SHIREJECT(sky), AP_RGROW(sky) * AP_SCALE(ap),
+ AP_SNREJECT(sky), AP_SKY_MODE(sky), AP_SKY_SIG(sky),
+ AP_SKY_SKEW(sky), AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+
+ return (ier)
+
+ case AP_CENTROID:
+
+ # Initialize the weights.
+ call amovkr (1.0, Memr[AP_SWGT(sky)], AP_NSKYPIX(sky))
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky), ilo,
+ ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call ap_index (Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ ier = ap_centroid (Memr[AP_SKYPIX(sky)], Memi[AP_COORDS(sky)],
+ Memr[AP_SWGT(sky)+ilo-1], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_SNX(sky), AP_SNY(sky), AP_K1(sky), INDEFR,
+ AP_BINSIZE(sky), AP_SMOOTH(sky), AP_SLOREJECT(sky),
+ AP_SHIREJECT(sky), AP_RGROW(sky) * AP_SCALE(ap),
+ AP_SMAXITER(sky), AP_SKY_MODE(sky), AP_SKY_SIG(sky),
+ AP_SKY_SKEW(sky), AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+
+ return (ier)
+
+ case AP_CONSTANT:
+
+ AP_SKY_MODE(sky) = AP_SKYBACKGROUND(sky)
+ AP_SKY_SIG(sky) = AP_SKYSIGMA(nse)
+ AP_SKY_SKEW(sky) = INDEFR
+ AP_NSKY(sky) = 0
+ AP_NSKY_REJECT(sky) = 0
+ return (AP_OK)
+
+ case AP_SKYFILE:
+
+ return (AP_OK)
+
+ case AP_RADPLOT:
+
+ # Check the status of the graphics stream.
+ if (gd == NULL)
+ return (AP_NOGRAPHICS)
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky), ilo,
+ ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call ap_index (Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ call gactivate (gd, 0)
+ gt = ap_gtinit (AP_IMROOT(ap), AP_SXCUR(sky), AP_SYCUR(sky))
+ ier = ap_radplot (gd, gt, Memr[AP_SKYPIX(sky)],
+ Memi[AP_COORDS(sky)], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_SXC(sky), AP_SYC(sky), AP_SNX(sky), AP_SNY(sky),
+ AP_SCALE(ap), AP_SKY_MODE(sky), AP_SKY_SIG(sky),
+ AP_SKY_SKEW(sky), AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+ call ap_gtfree (gt)
+ call gdeactivate (gd, 0)
+
+ return (ier)
+
+ case AP_HISTPLOT:
+
+ # Check the status of the graphics stream.
+ if (gd == NULL)
+ return (AP_NOGRAPHICS)
+
+ # Initialize the weights.
+ call amovkr (1.0, Memr[AP_SWGT(sky)], AP_NSKYPIX(sky))
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky), ilo,
+ ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call ap_index (Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ #call gactivate (gd, 0)
+ gt = ap_gtinit (AP_IMROOT(ap), AP_SXCUR(sky), AP_SYCUR(sky))
+ ier = ap_histplot (gd, gt, Memr[AP_SKYPIX(sky)],
+ Memr[AP_SWGT(sky)], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_K1(sky), INDEFR, AP_BINSIZE(sky), AP_SMOOTH(sky),
+ AP_SKY_MODE(sky), AP_SKY_SIG(sky), AP_SKY_SKEW(sky),
+ AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+ call ap_gtfree (gt)
+
+ return (ier)
+
+ case AP_OFILT:
+
+ # Initialize the weights.
+ call amovkr (1.0, Memr[AP_SWGT(sky)], AP_NSKYPIX(sky))
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky), ilo,
+ ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call ap_index (Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ ier = ap_lgsky (Memr[AP_SKYPIX(sky)], Memi[AP_COORDS(sky)],
+ Memr[AP_SWGT(sky)], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_SNX(sky), AP_SNY(sky), AP_K1(sky), INDEFR,
+ AP_BINSIZE(sky), AP_SMOOTH(sky), AP_SLOREJECT(sky),
+ AP_SHIREJECT(sky), AP_RGROW(sky) * AP_SCALE(ap),
+ AP_SMAXITER(sky), AP_SKY_MODE(sky), AP_SKY_SIG(sky),
+ AP_SKY_SKEW(sky), AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+
+ return (ier)
+
+ case AP_GAUSS:
+
+ # Initialize the weights.
+ call amovkr (1.0, Memr[AP_SWGT(sky)], AP_NSKYPIX(sky))
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky), ilo,
+ ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call ap_index (Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ ier = ap_gauss (Memr[AP_SKYPIX(sky)], Memi[AP_COORDS(sky)],
+ Memr[AP_SWGT(sky)], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_SNX(sky), AP_SNY(sky), AP_SMAXITER(sky),
+ AP_K1(sky), INDEFR, AP_BINSIZE(sky), AP_SMOOTH(sky),
+ AP_SLOREJECT(sky), AP_SHIREJECT(sky), AP_RGROW(sky) *
+ AP_SCALE(ap), AP_SNREJECT(sky), AP_SKY_MODE(sky),
+ AP_SKY_SIG(sky), AP_SKY_SKEW(sky), AP_NSKY(sky),
+ AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+
+ return (ier)
+
+ case AP_CROSSCOR:
+
+ # Initialize the weights.
+ call amovkr (1.0, Memr[AP_SWGT(sky)], AP_NSKYPIX(sky))
+
+ # Clip the data.
+ if (AP_SLOCLIP(sky) > 0.0 || AP_SHICLIP(sky) > 0.0) {
+ nclip = ap_clip (Memr[AP_SKYPIX(sky)], Memi[AP_INDEX(sky)],
+ AP_NSKYPIX(sky), AP_SLOCLIP(sky), AP_SHICLIP(sky), ilo,
+ ihi)
+ if (nclip >= AP_NSKYPIX(sky))
+ return (AP_NSKY_TOO_SMALL)
+ nsky = AP_NSKYPIX(sky) - nclip
+ } else {
+ nclip = 0
+ call ap_index (Memi[AP_INDEX(sky)], AP_NSKYPIX(sky))
+ ilo = 1
+ nsky = AP_NSKYPIX(sky)
+ }
+
+ ier = ap_crosscor (Memr[AP_SKYPIX(sky)], Memi[AP_COORDS(sky)],
+ Memr[AP_SWGT(sky)], Memi[AP_INDEX(sky)+ilo-1], nsky,
+ AP_SNX(sky), AP_SNY(sky), AP_K1(sky), INDEFR,
+ AP_BINSIZE(sky), AP_SMOOTH(sky), AP_SLOREJECT(sky),
+ AP_SHIREJECT(sky), AP_RGROW(sky) * AP_SCALE(ap),
+ AP_SMAXITER(sky), AP_SKY_MODE(sky), AP_SKY_SIG(sky),
+ AP_SKY_SKEW(sky), AP_NSKY(sky), AP_NSKY_REJECT(sky))
+ AP_NSKY_REJECT(sky) = AP_NBADSKYPIX(sky) + nclip +
+ AP_NSKY_REJECT(sky)
+
+ return (ier)
+
+ default:
+
+ AP_SKY_MODE(sky) = INDEFR
+ AP_SKY_SIG(sky) = INDEFR
+ AP_SKY_SKEW(sky) = INDEFR
+ AP_NSKY(sky) = AP_NSKYPIX(sky)
+ AP_NSKY_REJECT(sky) = 0
+ return (AP_OK)
+ }
+end
diff --git a/noao/digiphot/apphot/fitsky/aprgrow.x b/noao/digiphot/apphot/fitsky/aprgrow.x
new file mode 100644
index 00000000..902b91d6
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/aprgrow.x
@@ -0,0 +1,64 @@
+# AP_GROW_REGIONS -- Perform region growing around a rejected pixel.
+
+int procedure ap_grow_regions (skypix, coords, wgt, nskypix, sky_zero,
+ index, snx, sny, rgrow, sumpx, sumsqpx, sumcbpx)
+
+real skypix[ARB] # sky pixels
+int coords[ARB] # sky cordinates
+real wgt[ARB] # weights
+int nskypix # total number of sky pixels
+real sky_zero # sky zero point for moment analysis
+int index # index of pixel to be rejected
+int snx, sny # size of sky subraster
+real rgrow # region growing radius
+double sumpx, sumsqpx, sumcbpx # sum and sum of squares of sky pixels
+
+double dsky
+int j, k, ixc, iyc, xmin, xmax, ymin, ymax, cstart, c, nreject
+real rgrow2, r2, d
+
+begin
+ # Find the center of the region to be rejected.
+ ixc = mod (coords[index], snx)
+ if (ixc == 0)
+ ixc = snx
+ iyc = (coords[index] - ixc) / snx + 1
+
+ # Define the region to be searched.
+ rgrow2 = rgrow ** 2
+ ymin = max (1, int (iyc - rgrow))
+ ymax = min (sny, int (iyc + rgrow))
+ xmin = max (1, int (ixc - rgrow))
+ xmax = min (snx, int (ixc + rgrow))
+ if (ymin <= iyc)
+ cstart = min (nskypix, max (1, index - int (rgrow) + snx *
+ (ymin - iyc)))
+ else
+ cstart = index
+
+ # Reject the pixels.
+ nreject = 0
+ do j = ymin, ymax {
+ d = rgrow2 - (j - iyc) ** 2
+ if (d <= 0.0)
+ d = 0.0
+ else
+ d = sqrt (d)
+ do k = max (xmin, int (ixc - d)), min (xmax, int (ixc + d)) {
+ c = k + (j - 1) * snx
+ while (coords[cstart] < c && cstart < nskypix)
+ cstart = cstart + 1
+ r2 = (k - ixc) ** 2 + (j - iyc) ** 2
+ if (r2 <= rgrow2 && c == coords[cstart] && wgt[cstart] > 0.0) {
+ dsky = skypix[cstart] - sky_zero
+ sumpx = sumpx - dsky
+ sumsqpx = sumsqpx - dsky ** 2
+ sumcbpx = sumcbpx - dsky ** 3
+ nreject = nreject + 1
+ wgt[cstart] = 0.0
+ }
+ }
+ }
+
+ return (nreject)
+end
diff --git a/noao/digiphot/apphot/fitsky/apsconfirm.x b/noao/digiphot/apphot/fitsky/apsconfirm.x
new file mode 100644
index 00000000..43c0b168
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apsconfirm.x
@@ -0,0 +1,74 @@
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/fitsky.h"
+
+# AP_SCONFIRM -- Procedure to confirm the critical fitsky parameters.
+
+procedure ap_sconfirm (ap, out, stid)
+
+pointer ap # pointer to the apphot structure
+int out # output file descriptor
+int stid # output file sequence number
+
+pointer sp, str
+real annulus, dannulus, skysigma, datamin, datamax
+int apstati()
+real apstatr(), ap_vannulus(), ap_vdannulus(), ap_vsigma()
+real ap_vdatamin(), ap_vdatamax()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ call printf ("\n")
+
+ # Confirm the sky fitting algorithm.
+ call ap_vsstring (ap, Memc[str], SZ_FNAME)
+
+ # Confirm the remaining parameters.
+ if (apstati (ap, SKYFUNCTION) != AP_CONSTANT &&
+ apstati (ap, SKYFUNCTION) != AP_SKYFILE) {
+
+ # Confirm the sky annulus parameter.
+ annulus = ap_vannulus (ap)
+
+ # Confirm the width of the sky annulus.
+ dannulus = ap_vdannulus (ap)
+
+ } else {
+
+ annulus = apstatr (ap, ANNULUS)
+ dannulus = apstatr (ap, DANNULUS)
+
+ }
+
+ # Confirm the sky sigma parameter.
+ if (apstati (ap, SKYFUNCTION) != AP_SKYFILE)
+ skysigma = ap_vsigma (ap)
+ else
+ skysigma = apstatr (ap, SKYSIGMA)
+
+ # Confirm the minimum and maximum good data values.
+ datamin = ap_vdatamin (ap)
+ datamax = ap_vdatamax (ap)
+
+ call printf ("\n")
+
+ # Update the database file.
+ if (out != NULL && stid > 1) {
+ call ap_sparam (out, KY_SSTRING, Memc[str], UN_SALGORITHM,
+ "sky fitting algorithm")
+ call ap_rparam (out, KY_ANNULUS, annulus, UN_SSCALEUNIT,
+ "inner radius of sky annulus")
+ call ap_rparam (out, KY_DANNULUS, dannulus, UN_SSCALEUNIT,
+ "width of the sky annulus")
+ call ap_rparam (out, KY_SKYSIGMA, skysigma, UN_NCOUNTS,
+ "standard deviation of 1 sky pixel")
+ call ap_rparam (out, KY_DATAMIN, datamin, UN_ACOUNTS,
+ "minimum good data value")
+ call ap_rparam (out, KY_DATAMAX, datamax, UN_ACOUNTS,
+ "maximum good data value")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/fitsky/apserrors.x b/noao/digiphot/apphot/fitsky/apserrors.x
new file mode 100644
index 00000000..80c8f0a7
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apserrors.x
@@ -0,0 +1,42 @@
+include "../lib/fitsky.h"
+
+# AP_SERRORS -- Program to print out detailed fitsky error messages when the
+# program is run in interactive mode.
+
+procedure ap_serrors (ap, ier)
+
+pointer ap # pointer to apphot structure (not used)
+int ier # integer error code
+
+begin
+ switch (ier) {
+ case AP_NOSKYAREA:
+ call printf ("The are no pixels in the sky annulus.\n")
+ case AP_SKY_OUTOFBOUNDS:
+ call printf ("The sky annulus is outside of the image.\n")
+ case AP_NOHISTOGRAM:
+ call printf ("The sky histogram has no width.\n")
+ case AP_FLAT_HIST:
+ call printf ("The sky histogram is flat or concave.\n")
+ case AP_NSKY_TOO_SMALL:
+ call printf ("The number of sky points is too small.\n")
+ case AP_SKY_SINGULAR:
+ call printf ("The sky fit is singular.\n")
+ case AP_SKY_NOCONVERGE:
+ call printf ("The sky fit did not converge.\n")
+ case AP_NOGRAPHICS:
+ call printf ("Interactive graphics are not available.\n")
+ case AP_NOSKYFILE:
+ call printf (
+ "The text file containing sky values does not exist.\n")
+ case AP_EOFSKYFILE:
+ call printf ("The sky file is at EOF.\n")
+ case AP_BADSKYSCAN:
+ call printf (
+ "An error occurred in decoding the current line in the sky file.\n")
+ case AP_BADPARAMS:
+ call printf ("Out of range mode or -ve sigma in Gaussian fit.\n")
+ default:
+ call printf ("")
+ }
+end
diff --git a/noao/digiphot/apphot/fitsky/apsfree.x b/noao/digiphot/apphot/fitsky/apsfree.x
new file mode 100644
index 00000000..63d41090
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apsfree.x
@@ -0,0 +1,48 @@
+include "../lib/apphotdef.h"
+include "../lib/fitskydef.h"
+
+# APSFREE -- Procedure to free the sky fitting structure.
+
+procedure apsfree (ap)
+
+pointer ap # pointer to the apphot structure
+
+begin
+ if (ap == NULL)
+ return
+ if (AP_NOISE(ap) != NULL)
+ call ap_noisecls (ap)
+ if (AP_PDISPLAY(ap) != NULL)
+ call ap_dispcls (ap)
+ if (AP_PSKY(ap) != NULL)
+ call ap_skycls (ap)
+ if (AP_IMBUF(ap) != NULL)
+ call mfree (AP_IMBUF(ap), TY_REAL)
+ if (AP_MW(ap) != NULL)
+ call mw_close (AP_MW(ap))
+ call mfree (ap, TY_STRUCT)
+end
+
+
+# AP_SKYCLS -- Procedure to close up the sky fitting arrays.
+
+procedure ap_skycls (ap)
+
+pointer ap # pointer to the apphot structure
+
+pointer sky
+
+begin
+ sky = AP_PSKY(ap)
+ if (sky == NULL)
+ return
+ if (AP_SKYPIX(sky) != NULL)
+ call mfree (AP_SKYPIX(sky), TY_REAL)
+ if (AP_INDEX(sky) != NULL)
+ call mfree (AP_INDEX(sky), TY_INT)
+ if (AP_COORDS(sky) != NULL)
+ call mfree (AP_COORDS(sky), TY_INT)
+ if (AP_SWGT(sky) != NULL)
+ call mfree (AP_SWGT(sky), TY_REAL)
+ call mfree (AP_PSKY(ap), TY_STRUCT)
+end
diff --git a/noao/digiphot/apphot/fitsky/apsinit.x b/noao/digiphot/apphot/fitsky/apsinit.x
new file mode 100644
index 00000000..e180835f
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apsinit.x
@@ -0,0 +1,116 @@
+include "../lib/apphotdef.h"
+include "../lib/fitskydef.h"
+include "../lib/fitsky.h"
+
+# APSINIT - Procedure to initialize the sky fitting structure and parameters.
+
+procedure apsinit (ap, function, annulus, dannulus, fwhmpsf, noise)
+
+pointer ap # pointer to the apphot structure
+int function # sky fitting algorithm
+real annulus # radius of sky annulus
+real dannulus # width of sky annulus
+real fwhmpsf # FWHM of the PSF
+int noise # noise function
+
+begin
+ # Set up the object parameters.
+ call malloc (ap, LEN_APSTRUCT, TY_STRUCT)
+
+ # Set up the global apphot package parameters.
+ call ap_defsetup (ap, fwhmpsf)
+
+ # Set up the noise model parameters.
+ call ap_noisesetup (ap, noise)
+
+ # Set up the display options.
+ call ap_dispsetup (ap)
+
+ # Initialize the sky fitting parameters.
+ call ap_skysetup (ap, function, annulus, dannulus)
+
+ # Unused structures are set to null.
+ AP_PCENTER(ap) = NULL
+ AP_PPHOT(ap) = NULL
+ AP_POLY(ap) = NULL
+ AP_PPSF(ap) = NULL
+ AP_RPROF(ap) = NULL
+end
+
+
+# AP_SKYSETUP -- Procedure to set up the sky fitting arrays and parameters.
+
+procedure ap_skysetup (ap, function, annulus, dannulus)
+
+pointer ap # pointer to apphot structure
+int function # sky fitting function
+real annulus # inner radius of sky annulus
+real dannulus # outer radius of sky annulus
+
+pointer sky
+
+begin
+ call malloc (AP_PSKY(ap), LEN_SKYSTRUCT, TY_STRUCT)
+ sky = AP_PSKY(ap)
+ AP_SXCUR(sky) = INDEFR
+ AP_SYCUR(sky) = INDEFR
+
+ # Initialize the sky fitting parameters.
+ AP_SKYFUNCTION(sky) = function
+ switch (function) {
+ case AP_CONSTANT:
+ call strcpy ("constant", AP_SSTRING(sky), SZ_FNAME)
+ case AP_MODE:
+ call strcpy ("mode", AP_SSTRING(sky), SZ_FNAME)
+ case AP_CENTROID:
+ call strcpy ("centroid", AP_SSTRING(sky), SZ_FNAME)
+ case AP_SKYFILE:
+ call strcpy ("file", AP_SSTRING(sky), SZ_FNAME)
+ case AP_HISTPLOT:
+ call strcpy ("histplot", AP_SSTRING(sky), SZ_FNAME)
+ case AP_RADPLOT:
+ call strcpy ("radplot", AP_SSTRING(sky), SZ_FNAME)
+ case AP_MEDIAN:
+ call strcpy ("median", AP_SSTRING(sky), SZ_FNAME)
+ case AP_GAUSS:
+ call strcpy ("gauss", AP_SSTRING(sky), SZ_FNAME)
+ case AP_OFILT:
+ call strcpy ("ofilt", AP_SSTRING(sky), SZ_FNAME)
+ case AP_CROSSCOR:
+ call strcpy ("crosscor", AP_SSTRING(sky), SZ_FNAME)
+ case AP_MEAN:
+ call strcpy ("mean", AP_SSTRING(sky), SZ_FNAME)
+ default:
+ AP_SKYFUNCTION(sky) = DEF_SKYFUNCTION
+ call strcpy ("mode", AP_SSTRING(sky), SZ_FNAME)
+ }
+
+ AP_SKYBACKGROUND(sky) = DEF_SKYVALUE
+ AP_ANNULUS(sky) = annulus
+ AP_DANNULUS(sky) = dannulus
+ AP_K1(sky) = DEF_K1
+ AP_BINSIZE(sky) = DEF_BINSIZE
+ AP_SMOOTH(sky) = DEF_SMOOTH
+ AP_SLOCLIP(sky) = DEF_SLOCLIP
+ AP_SHICLIP(sky) = DEF_SHICLIP
+ AP_SMAXITER(sky) = DEF_SMAXITER
+ AP_RGROW(sky) = DEF_RGROW
+ AP_SNREJECT(sky) = DEF_SNREJECT
+ AP_SLOREJECT(sky) = DEF_SLOREJECT
+ AP_SHIREJECT(sky) = DEF_SHIREJECT
+
+ # Initialize the sky pixel buffers.
+ AP_LENSKYBUF(sky) = 0
+ AP_NSKYPIX(sky) = 0
+ AP_SKYPIX(sky) = NULL
+ AP_INDEX(sky) = NULL
+ AP_COORDS(sky) = NULL
+ AP_SWGT(sky) = NULL
+
+ # Initialize results parameters.
+ AP_SKY_MODE(sky) = INDEFR
+ AP_SKY_SIG(sky) = INDEFR
+ AP_SKY_SKEW(sky) = INDEFR
+ AP_NSKY(sky) = 0
+ AP_NSKY_REJECT(sky) = 0
+end
diff --git a/noao/digiphot/apphot/fitsky/apsky.x b/noao/digiphot/apphot/fitsky/apsky.x
new file mode 100644
index 00000000..40faac3d
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apsky.x
@@ -0,0 +1,346 @@
+include <ctype.h>
+include <gset.h>
+include <imhdr.h>
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/fitsky.h"
+
+define HELPFILE "apphot$fitsky/fitsky.key"
+
+# APSKY -- Procedure to interactively determine sky values in an annular
+# region around a list of objects.
+
+int procedure apsky (ap, im, cl, sd, gd, mgd, id, out, stid, interactive, cache)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to IRAF image
+int cl # starlist file descriptor
+int sd # the sky file descriptor
+pointer gd # pointer to graphcis descriptor
+pointer mgd # pointer to graphics metacode file
+pointer id # pointer to image display stream
+int out # output file descriptor
+int stid # output file sequence number
+int interactive # interactive mode
+int cache # cache the input image pixels
+
+real wx, wy, xlist, ylist
+pointer sp, cmd
+int wcs, key, colonkey, newimage, newobject, newsky, newlist, ier
+int ip, ltid, oid, prev_num, req_num, buf_size, req_size, old_size
+int memstat
+
+real apstatr()
+int clgcur(), apfitsky(), aprefitsky(), apgscur(), ctoi(), apstati()
+int apgqverify(), apgtverify(), apnew(), ap_memstat(), sizeof()
+
+define endswitch_ 99
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Initialize cursor command.
+ key = ' '
+ Memc[cmd] = EOS
+
+ # Initialize fitting parameters.
+ newimage = NO
+ newobject = YES
+ newsky = YES
+ ier = AP_OK
+
+ # Initialize sequencing.
+ newlist = NO
+ ltid = 0
+
+ # Loop over the cursor commands.
+ while (clgcur ("icommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+
+ # Store the current cursor coordinates.
+ call ap_vtol (im, wx, wy, wx, wy, 1)
+ call apsetr (ap, CWX, wx)
+ call apsetr (ap, CWY, wy)
+
+ # Test to see if the cursor has moved.
+ if (apnew (ap, wx, wy, xlist, ylist, newlist) == YES) {
+ newobject = YES
+ newsky = YES
+ }
+
+ # Loop over the colon commands.
+ switch (key) {
+
+ # Quit.
+ case 'q':
+ if (interactive == YES) {
+ if (apgqverify ("fitsky", ap, key) == YES) {
+ call sfree (sp)
+ return (apgtverify (key))
+ }
+ } else {
+ call sfree (sp)
+ return (NO)
+ }
+
+ # Print the error messages.
+ case 'e':
+ if (interactive == YES)
+ call ap_serrors (ap, ier)
+
+ # Print the help page.
+ case '?':
+ if ((id != NULL) && (id == gd))
+ call gpagefile (id, HELPFILE, "")
+ else if (interactive == YES)
+ call pagefile (HELPFILE, "[space=morehelp,q=quit,?=help]")
+
+ # Rewind the coordinate file.
+ case 'r':
+ if (cl != NULL) {
+ call seek (cl, BOFL)
+ ltid = 0
+ } else if (interactive == YES)
+ call printf ("No coordinate list\n")
+
+ # Verify the critical parameters.
+ case 'v':
+ call ap_sconfirm (ap, out, stid)
+ newobject = YES
+ newsky = YES
+
+ # Save the sky fitting parameters.
+ case 'w':
+ call ap_pspars (ap)
+
+ # Draw a centered radial profile plot.
+ case 'd':
+ if (interactive == YES) {
+ call ap_qrad (ap, im, wx, wy, gd)
+ newobject = YES
+ newsky = YES
+ }
+
+ # Interactively set up sky fitting parameters.
+ case 'i':
+ if (interactive == YES) {
+ call ap_sradsetup (ap, im, wx, wy, gd, out, stid)
+ newobject = YES
+ newsky = YES
+ }
+
+ # Process fitsky colon commands.
+ case ':':
+ for (ip = 1; IS_WHITE(Memc[cmd+ip-1]); ip = ip + 1)
+ ;
+ colonkey = Memc[cmd+ip-1]
+ switch (colonkey) {
+ case 'm', 'n':
+
+ # Show/set fitsky commands.
+ if (Memc[cmd+ip] != EOS && Memc[cmd+ip] != ' ') {
+ call apskycolon (ap, im, cl, out, stid, ltid,
+ Memc[cmd], newimage, newobject, newsky)
+ goto endswitch_
+ }
+
+ # No coordinate list.
+ if (cl == NULL) {
+ if (interactive == YES)
+ call printf ("No coordinate list\n")
+ goto endswitch_
+ }
+
+ # Get next object from the list.
+ ip = ip + 1
+ prev_num = ltid
+ if (ctoi (Memc[cmd], ip, req_num) <= 0)
+ req_num = ltid + 1
+
+ # Fetch the next object from the list.
+ if (apgscur (cl, id, xlist, ylist, prev_num, req_num,
+ ltid) == EOF) {
+ if (interactive == YES)
+ call printf (
+ "End of coordinate list, use r key to rewind\n")
+ goto endswitch_
+ }
+
+ # Convert the coordinates.
+ switch (apstati (ap, WCSIN)) {
+ case WCS_PHYSICAL, WCS_WORLD:
+ call ap_itol (ap, xlist, ylist, xlist, ylist, 1)
+ case WCS_TV:
+ call ap_vtol (im, xlist, ylist, xlist, ylist, 1)
+ default:
+ ;
+ }
+
+ # Move to the next object.
+ newlist = YES
+ if (colonkey == 'm') {
+ newobject = YES
+ newsky = YES
+ goto endswitch_
+ }
+
+ # Measure the next object.
+ ier = apfitsky (ap, im, xlist, ylist, sd, gd)
+ if (id != NULL) {
+ call apmark (ap, id, NO, apstati (ap, MKSKY), NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_splot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qspsky (ap, ier)
+ if (stid == 1)
+ call ap_param (ap, out, "fitsky")
+ call ap_splot (ap, stid, mgd, YES)
+ call ap_pssky (ap, out, stid, ltid, ier)
+ stid = stid + 1
+ newobject = NO; newsky = NO
+
+ default:
+ call apskycolon (ap, im, cl, out, stid, ltid, Memc[cmd],
+ newimage, newobject, newsky)
+ }
+
+ if (newimage == YES) {
+ if ((id != NULL) && (gd != id))
+ call ap_gswv (id, Memc[cmd], im, 4)
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+ }
+
+ newimage = NO
+
+ # Fit the sky and store the results.
+ case 'f', ' ':
+ if (newobject == YES)
+ ier = apfitsky (ap, im, wx, wy, sd, gd)
+ else if (newsky == YES)
+ ier = aprefitsky (ap, im, gd)
+ if (id != NULL) {
+ call apmark (ap, id, NO, apstati (ap, MKSKY), NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_splot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qspsky (ap, ier)
+ newobject = NO; newsky = NO
+
+ if (key == ' ') {
+ if (stid == 1)
+ call ap_param (ap, out, "fitsky")
+ if (newlist == YES)
+ call ap_pssky (ap, out, stid, ltid, ier)
+ else
+ call ap_pssky (ap, out, stid, 0, ier)
+ call ap_splot (ap, stid, mgd, YES)
+ stid = stid + 1
+ }
+
+ # Get, fit the next object in the list.
+ case 'm', 'n':
+
+ # No coordinate file.
+ if (cl == NULL) {
+ if (interactive == YES)
+ call printf ("No coordinate list\n")
+ goto endswitch_
+ }
+
+ # Need to rewind coordinate file.
+ prev_num = ltid
+ req_num = ltid + 1
+ if (apgscur (cl, id, xlist, ylist, prev_num, req_num,
+ ltid) == EOF) {
+ if (interactive == YES)
+ call printf (
+ "End of coordinate list, use r key to rewind\n")
+ goto endswitch_
+
+ }
+
+ # Convert coordinates if necessary.
+ switch (apstati (ap, WCSIN)) {
+ case WCS_PHYSICAL, WCS_WORLD:
+ call ap_itol (ap, xlist, ylist, xlist, ylist, 1)
+ case WCS_TV:
+ call ap_vtol (im, xlist, ylist, xlist, ylist, 1)
+ default:
+ ;
+ }
+
+ # Move to the next object.
+ newlist = YES
+ if (key == 'm') {
+ newobject = YES
+ newsky = YES
+ goto endswitch_
+ }
+
+ # Measure the next object.
+ ier = apfitsky (ap, im, xlist, ylist, sd, gd)
+ if (id != NULL) {
+ call apmark (ap, id, NO, apstati (ap, MKSKY), NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_splot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qspsky (ap, ier)
+ if (stid == 1)
+ call ap_param (ap, out, "fitsky")
+ call ap_pssky (ap, out, stid, ltid, ier)
+ call ap_splot (ap, stid, mgd, YES)
+ stid = stid + 1
+ newobject = NO
+ newsky = NO
+
+ # Process the remainder of the list.
+ case 'l':
+ if (cl != NULL) {
+ ltid = ltid + 1
+ oid = stid
+ call apbsky (ap, im, cl, sd, out, stid, ltid, gd, mgd, id,
+ YES)
+ ltid = ltid + stid - oid + 1
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ } else if (interactive == YES)
+ call printf ("No coordinate list\n")
+
+ default:
+ # do nothing
+ call printf ("Unknown or ambiguous keystroke command\n")
+ }
+
+endswitch_
+
+ # Setup for the next object.
+ key = ' '
+ Memc[cmd] = EOS
+ call apsetr (ap, WX, apstatr (ap, CWX))
+ call apsetr (ap, WY, apstatr (ap, CWY))
+
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/fitsky/apskybuf.x b/noao/digiphot/apphot/fitsky/apskybuf.x
new file mode 100644
index 00000000..cacd4737
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apskybuf.x
@@ -0,0 +1,254 @@
+include <imhdr.h>
+include <math.h>
+include <mach.h>
+include "../lib/apphotdef.h"
+include "../lib/fitskydef.h"
+include "../lib/fitsky.h"
+
+# APSKYBUF -- Procedure to fetch the sky pixels given the pointer to the
+# IRAF image, the coordinates of the center and the size of the apphot
+# sky annulus.
+
+int procedure apskybuf (ap, im, wx, wy)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to the IRAF image
+real wx, wy # center coordinates
+
+int lenbuf
+pointer sky
+real annulus, dannulus, datamin, datamax
+int ap_skypix(), ap_bskypix()
+
+begin
+ # Check for 0 radius annulus.
+ sky = AP_PSKY(ap)
+ annulus = AP_ANNULUS(sky) * AP_SCALE(ap)
+ dannulus = AP_DANNULUS(sky) * AP_SCALE(ap)
+ if (dannulus <= 0.0)
+ return (AP_NOSKYAREA)
+
+ # Allocate space for sky pixels.
+ lenbuf = PI * (2.0 * annulus + dannulus + 1.0) * (dannulus + 0.5)
+
+ if (lenbuf != AP_LENSKYBUF(sky)) {
+ if (AP_SKYPIX(sky) != NULL)
+ call mfree (AP_SKYPIX(sky), TY_REAL)
+ call malloc (AP_SKYPIX(sky), lenbuf, TY_REAL)
+ if (AP_COORDS(sky) != NULL)
+ call mfree (AP_COORDS(sky), TY_INT)
+ call malloc (AP_COORDS(sky), lenbuf, TY_INT)
+ if (AP_INDEX(sky) != NULL)
+ call mfree (AP_INDEX(sky), TY_INT)
+ call malloc (AP_INDEX(sky), lenbuf, TY_INT)
+ if (AP_SWGT(sky) != NULL)
+ call mfree (AP_SWGT(sky), TY_REAL)
+ call malloc (AP_SWGT(sky), lenbuf, TY_REAL)
+ AP_LENSKYBUF(sky) = lenbuf
+ }
+
+ # Fetch the sky pixels.
+ if (IS_INDEFR(AP_DATAMIN(ap)) && IS_INDEFR(AP_DATAMAX(ap))) {
+ AP_NSKYPIX(sky) = ap_skypix (im, wx, wy, annulus, (annulus +
+ dannulus), Memr[AP_SKYPIX(sky)], Memi[AP_COORDS(sky)],
+ AP_SXC(sky), AP_SYC(sky), AP_SNX(sky), AP_SNY(sky))
+ AP_NBADSKYPIX(sky) = 0
+ } else {
+ if (IS_INDEFR(AP_DATAMIN(ap)))
+ datamin = -MAX_REAL
+ else
+ datamin = AP_DATAMIN(ap)
+ if (IS_INDEFR(AP_DATAMAX(ap)))
+ datamax = MAX_REAL
+ else
+ datamax = AP_DATAMAX(ap)
+ AP_NSKYPIX(sky) = ap_bskypix (im, wx, wy, annulus, (annulus +
+ dannulus), datamin, datamax, Memr[AP_SKYPIX(sky)],
+ Memi[AP_COORDS(sky)], AP_SXC(sky), AP_SYC(sky), AP_SNX(sky),
+ AP_SNY(sky), AP_NBADSKYPIX(sky))
+ }
+
+ if (AP_NSKYPIX(sky) <= 0) {
+ if (AP_NBADSKYPIX(sky) <= 0)
+ return (AP_SKY_OUTOFBOUNDS)
+ else
+ return (AP_NSKY_TOO_SMALL)
+ } else
+ return (AP_OK)
+end
+
+
+# AP_SKYPIX -- Procedure to fetch the sky pixels from the image
+
+int procedure ap_skypix (im, wx, wy, rin, rout, skypix, coords, xc, yc,
+ nx, ny)
+
+pointer im # pointer to IRAF image
+real wx, wy # center of sky annulus
+real rin, rout # inner and outer radius of sky annulus
+real skypix[ARB] # skypixels
+int coords[ARB] # sky subraster coordinates [i + nx * (j - 1)]
+real xc, yc # center of sky subraster
+int nx, ny # max dimensions of sky subraster (output)
+
+int i, j, ncols, nlines, c1, c2, l1, l2, nskypix
+pointer buf
+real xc1, xc2, xl1, xl2, rin2, rout2, rj2, r2
+pointer imgs2r()
+
+#pointer tbuf
+
+begin
+ if (rout <= rin)
+ return (0)
+
+ # Test for out of bounds sky regions.
+ ncols = IM_LEN(im,1)
+ nlines = IM_LEN(im,2)
+ xc1 = wx - rout
+ xc2 = wx + rout
+ xl1 = wy - rout
+ xl2 = wy + rout
+ if (xc2 < 1.0 || xc1 > real (ncols) || xl2 < 1.0 || xl1 > real (nlines))
+ return (0)
+
+ # Compute the column and line limits.
+ c1 = max (1.0, min (real (ncols), wx - rout)) + 0.5
+ c2 = min (real (ncols), max (1.0, wx + rout)) + 0.5
+ l1 = max (1.0, min (real (nlines), wy - rout)) + 0.5
+ l2 = min (real (nlines), max (1.0, wy + rout)) + 0.5
+ nx = c2 - c1 + 1
+ ny = l2 - l1 + 1
+ xc = wx - c1 + 1
+ yc = wy - l1 + 1
+
+ # Fetch the sky pixels.
+ rin2 = rin ** 2
+ rout2 = rout ** 2
+ nskypix = 0
+
+ do j = l1, l2 {
+ buf = imgs2r (im, c1, c2, j, j)
+ rj2 = (wy - j) ** 2
+ do i = c1, c2 {
+ r2 = (wx - i) ** 2 + rj2
+ if (r2 > rin2 && r2 <= rout2) {
+ skypix[nskypix+1] = Memr[buf+i-c1]
+ coords[nskypix+1] = (i - c1 + 1) + nx * (j - l1)
+ nskypix = nskypix + 1
+ }
+ }
+ }
+
+ #buf = imgs2r (im, c1, c2, l1, l2)
+ #tbuf = buf
+ #do j = l1, l2 {
+ #rj2 = (wy - j) ** 2
+ #do i = c1, c2 {
+ #r2 = (wx - i) ** 2 + rj2
+ #if (r2 > rin2 && r2 <= rout2) {
+ #skypix[nskypix+1] = Memr[tbuf+i-c1]
+ #coords[nskypix+1] = (i - c1 + 1) + nx * (j - l1)
+ #nskypix = nskypix + 1
+ #}
+ #}
+ #tbuf = tbuf + nx
+ #}
+
+ return (nskypix)
+end
+
+
+# AP_BSKYPIX -- Procedure to fetch the sky pixels from the image
+
+int procedure ap_bskypix (im, wx, wy, rin, rout, datamin, datamax,
+ skypix, coords, xc, yc, nx, ny, nbad)
+
+pointer im # pointer to IRAF image
+real wx, wy # center of sky annulus
+real rin, rout # inner and outer radius of sky annulus
+real datamin # minimum good value
+real datamax # maximum good value
+real skypix[ARB] # skypixels
+int coords[ARB] # sky subraster coordinates [i + nx * (j - 1)]
+real xc, yc # center of sky subraster
+int nx, ny # max dimensions of sky subraster (output)
+int nbad # number of bad pixels
+
+int i, j, ncols, nlines, c1, c2, l1, l2, nskypix
+pointer buf
+real xc1, xc2, xl1, xl2, rin2, rout2, rj2, r2, pixval
+pointer imgs2r()
+
+#pointer tbuf
+
+begin
+ if (rout <= rin)
+ return (0)
+
+ # Test for out of bounds sky regions.
+ ncols = IM_LEN(im,1)
+ nlines = IM_LEN(im,2)
+ xc1 = wx - rout
+ xc2 = wx + rout
+ xl1 = wy - rout
+ xl2 = wy + rout
+ if (xc2 < 1.0 || xc1 > real (ncols) || xl2 < 1.0 || xl1 > real (nlines))
+ return (0)
+
+ # Compute the column and line limits.
+ c1 = max (1.0, min (real (ncols), wx - rout)) + 0.5
+ c2 = min (real (ncols), max (1.0, wx + rout)) + 0.5
+ l1 = max (1.0, min (real (nlines), wy - rout)) + 0.5
+ l2 = min (real (nlines), max (1.0, wy + rout)) + 0.5
+ nx = c2 - c1 + 1
+ ny = l2 - l1 + 1
+ xc = wx - c1 + 1
+ yc = wy - l1 + 1
+
+ rin2 = rin ** 2
+ rout2 = rout ** 2
+ nskypix = 0
+ nbad = 0
+
+ # Fetch the sky pixels.
+ do j = l1, l2 {
+ buf = imgs2r (im, c1, c2, j, j)
+ rj2 = (wy - j) ** 2
+ do i = c1, c2 {
+ r2 = (wx - i) ** 2 + rj2
+ if (r2 > rin2 && r2 <= rout2) {
+ pixval = Memr[buf+i-c1]
+ if (pixval < datamin || pixval > datamax)
+ nbad = nbad + 1
+ else {
+ skypix[nskypix+1] = pixval
+ coords[nskypix+1] = (i - c1 + 1) + nx * (j - l1)
+ nskypix = nskypix + 1
+ }
+ }
+ }
+ }
+
+ #buf = imgs2r (im, c1, c2, l1, l2)
+ #tbuf = buf
+ #do j = l1, l2 {
+ #rj2 = (wy - j) ** 2
+ #do i = c1, c2 {
+ #r2 = (wx - i) ** 2 + rj2
+ #if (r2 > rin2 && r2 <= rout2) {
+ #pixval = Memr[tbuf+i-c1]
+ #if (pixval < datamin || pixval > datamax)
+ #nbad = nbad + 1
+ #else {
+ #skypix[nskypix+1] = pixval
+ #coords[nskypix+1] = (i - c1 + 1) + nx * (j - l1)
+ #nskypix = nskypix + 1
+ #}
+ #}
+ #}
+ #tbuf = tbuf + nx
+ #}
+
+ return (nskypix)
+end
diff --git a/noao/digiphot/apphot/fitsky/apskycolon.x b/noao/digiphot/apphot/fitsky/apskycolon.x
new file mode 100644
index 00000000..35b59aa9
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apskycolon.x
@@ -0,0 +1,367 @@
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/fitsky.h"
+include "../lib/display.h"
+
+
+# APSKYCOLON -- Procedure to process the fitsky colon commands.
+
+procedure apskycolon (ap, im, cl, out, stid, ltid, cmdstr, newimage,
+ newskybuf, newsky)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the iraf image
+int cl # coordinate file descriptor
+int out # output file descriptor
+int stid # output file sequence number
+int ltid # coord list sequence number
+char cmdstr[ARB] # command string
+int newimage # new image ?
+int newskybuf # new sky buffer ?
+int newsky # new sky fit ?
+
+int junk
+pointer sp, incmd, outcmd
+int strdic()
+
+begin
+ # Get the command.
+ call smark (sp)
+ call salloc (incmd, SZ_LINE, TY_CHAR)
+ call salloc (outcmd, SZ_LINE, TY_CHAR)
+ call sscan (cmdstr)
+ call gargwrd (Memc[incmd], SZ_LINE)
+ if (Memc[incmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, SCMDS) != 0)
+ call apscolon (ap, out, stid, cmdstr, newskybuf, newsky)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, APCMDS) != 0)
+ call ap_apcolon (ap, im, cl, out, stid, ltid, cmdstr,
+ newimage, junk, junk, newskybuf, newsky, junk, junk)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, NCMDS) != 0)
+ call apnscolon (ap, im, out, stid, cmdstr, junk, junk,
+ newskybuf, newsky, junk, junk)
+ else
+ call ap_simcolon (ap, cmdstr)
+
+ call sfree (sp)
+end
+
+
+# APSCOLON -- Procedure to examine and edit the sky fitting parameters.
+
+procedure apscolon (ap, out, stid, cmdstr, newbuf, newfit)
+
+pointer ap # pointer to the apphot structure
+int out # output file descriptor
+int stid # output file number
+char cmdstr # command string
+int newbuf # new sky buffer
+int newfit # new sky fit
+
+bool bval
+int ncmd, ival, stat
+pointer sp, cmd
+real rval
+
+bool itob()
+int nscan(), strdic(), btoi(), apstati()
+real apstatr()
+
+
+begin
+ # Get the command
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, SCMDS)
+ switch (ncmd) {
+ case SCMD_ANNULUS:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_ANNULUS)
+ call pargr (apstatr (ap, ANNULUS))
+ call pargstr (UN_SSCALEUNIT)
+ } else {
+ call apsetr (ap, ANNULUS, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_ANNULUS, rval, UN_SSCALEUNIT,
+ "inner radius of sky annulus")
+ newbuf = YES
+ newfit = YES
+ }
+ case SCMD_DANNULUS:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_DANNULUS)
+ call pargr (apstatr (ap, DANNULUS))
+ call pargstr (UN_SSCALEUNIT)
+ } else {
+ call apsetr (ap, DANNULUS, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_DANNULUS, rval, UN_SSCALEUNIT,
+ "width of the sky annulus")
+ newbuf = YES
+ newfit = YES
+ }
+ case SCMD_SALGORITHM:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, SSTRING, Memc[cmd], SZ_FNAME)
+ call printf ("%s = %s\n")
+ call pargstr (KY_SSTRING)
+ call pargstr (Memc[cmd])
+ } else {
+ stat = strdic (Memc[cmd], Memc[cmd], SZ_LINE, SFUNCS)
+ if (stat > 0) {
+ call apseti (ap, SKYFUNCTION, stat)
+ call apsets (ap, SSTRING, Memc[cmd])
+ if (stid > 1)
+ call ap_sparam (out, KY_SSTRING, Memc[cmd],
+ UN_SALGORITHM, "sky fitting algorithm")
+ newfit = YES
+ }
+ }
+ case SCMD_KHIST:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_K1)
+ call pargr (apstatr (ap, K1))
+ call pargstr (UN_SSIGMA)
+ } else {
+ call apsetr (ap, K1, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_K1, rval, UN_SSIGMA,
+ "half width of sky histogram")
+ newfit = YES
+ }
+ case SCMD_SLOREJECT:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_SLOREJECT)
+ call pargr (apstatr (ap, SLOREJECT))
+ call pargstr (UN_SSIGMA)
+ } else {
+ call apsetr (ap, SLOREJECT, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_SLOREJECT, rval, UN_SSIGMA,
+ "lower k-sigma rejection criterion")
+ newfit = YES
+ }
+ case SCMD_SHIREJECT:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_SHIREJECT)
+ call pargr (apstatr (ap, SHIREJECT))
+ call pargstr (UN_SSIGMA)
+ } else {
+ call apsetr (ap, SHIREJECT, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_SHIREJECT, rval, UN_SSIGMA,
+ "upper k-sigma rejection criterion")
+ newfit = YES
+ }
+ case SCMD_SLOCLIP:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_SLOCLIP)
+ call pargr (apstatr (ap, SLOCLIP))
+ call pargstr (UN_SPERCENT)
+ } else {
+ call apsetr (ap, SLOCLIP, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_SLOCLIP, rval, UN_SPERCENT,
+ "lower k-sigma rejection criterion")
+ newfit = YES
+ }
+ case SCMD_SHICLIP:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_SHICLIP)
+ call pargr (apstatr (ap, SHICLIP))
+ call pargstr (UN_SPERCENT)
+ } else {
+ call apsetr (ap, SHICLIP, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_SHICLIP, rval, UN_SPERCENT,
+ "lower k-sigma rejection criterion")
+ newfit = YES
+ }
+ case SCMD_SMAXITER:
+ call gargi (ival)
+ if (nscan () == 1) {
+ call printf ("%s = %d\n")
+ call pargstr (KY_SMAXITER)
+ call pargi (apstati (ap, SMAXITER))
+ } else {
+ call apseti (ap, SMAXITER, ival)
+ if (stid > 1)
+ call ap_iparam (out, KY_SMAXITER, ival, UN_SNUMBER,
+ "maximum number of iterations")
+ newfit = YES
+ }
+ case SCMD_BINSIZE:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_BINSIZE)
+ call pargr (apstatr (ap, BINSIZE))
+ call pargstr (UN_SSIGMA)
+ } else {
+ call apsetr (ap, BINSIZE, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_BINSIZE, rval, UN_SSIGMA,
+ "width of the sky histogram bin")
+ newfit = YES
+ }
+ case SCMD_SMOOTH:
+ call gargb (bval)
+ if (nscan () == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (KY_SMOOTH)
+ call pargb (itob (apstati (ap, SMOOTH)))
+ } else {
+ call apseti (ap, SMOOTH, btoi (bval))
+ if (stid > 1)
+ call ap_bparam (out, KY_SMOOTH, bval, UN_SSWITCH,
+ "Lucy smooth the histogram")
+ newfit = YES
+ }
+ case SCMD_RGROW:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_RGROW)
+ call pargr (apstatr (ap, RGROW))
+ call pargstr (UN_SSCALEUNIT)
+ } else {
+ call apsetr (ap, RGROW, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_RGROW, rval, UN_SSCALEUNIT,
+ "region growing radius")
+ newfit = YES
+ }
+ case SCMD_SNREJECT:
+ call gargi (ival)
+ if (nscan () == 1) {
+ call printf ("%s = %d\n")
+ call pargstr (KY_SNREJECT)
+ call pargi (apstati (ap, SNREJECT))
+ } else {
+ call apseti (ap, SNREJECT, ival)
+ if (stid > 1)
+ call ap_iparam (out, KY_SNREJECT, ival, UN_SNUMBER,
+ "maximum number of rejection cycles")
+ newfit = YES
+ }
+ case SCMD_SKYVALUE:
+ call gargr (rval)
+ if (nscan () == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (KY_SKY_BACKGROUND)
+ call pargr (apstatr (ap, SKY_BACKGROUND))
+ call pargstr (UN_SCOUNTS)
+ } else {
+ call apsetr (ap, SKY_BACKGROUND, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_SKY_BACKGROUND, rval,
+ UN_SCOUNTS, "user supplied sky value")
+ newfit = YES
+ }
+ case SCMD_MKSKY:
+ call gargb (bval)
+ if (nscan () == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (KY_MKSKY)
+ call pargb (itob (apstati (ap, MKSKY)))
+ } else {
+ call apseti (ap, MKSKY, btoi (bval))
+ }
+ default:
+ # do nothing gracefully
+ call printf ("Unrecognized command\7\n")
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_SIMCOLON -- Procedure to process fitsky commands which alter parameters
+# other than the sky fitting parameters themselves.
+
+procedure ap_simcolon (ap, cmdstr)
+
+pointer ap # pointer to the apphot structure
+char cmdstr[ARB] # command string
+
+bool bval
+int ncmd
+pointer sp, cmd
+bool itob()
+int strdic(), nscan(), apstati(), btoi()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Get the command.
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the commands.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, MISC)
+ switch (ncmd) {
+ case ACMD_SHOW:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, SSHOWARGS)
+ switch (ncmd) {
+ case SCMD_DATA:
+ call printf ("\n")
+ call ap_nshow (ap)
+ call printf ("\n")
+ case SCMD_SKY:
+ call printf ("\n")
+ call ap_spshow (ap)
+ call printf ("\n")
+ default:
+ call printf ("\n")
+ call ap_sshow (ap)
+ call printf ("\n")
+ }
+ case ACMD_RADPLOTS:
+ call gargb (bval)
+ if (nscan () == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (KY_RADPLOTS)
+ call pargb (itob (apstati (ap, RADPLOTS)))
+ } else {
+ call apseti (ap, RADPLOTS, btoi (bval))
+ }
+ default:
+ call printf ("Unknown or ambiguous colon command\7\n")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/fitsky/apsplot.x b/noao/digiphot/apphot/fitsky/apsplot.x
new file mode 100644
index 00000000..0a75b0c8
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apsplot.x
@@ -0,0 +1,244 @@
+include <pkg/gtools.h>
+include <gset.h>
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/fitskydef.h"
+include "../lib/fitsky.h"
+
+# AP_SPLOT -- Procedure to compute radial profile plots for the sky fitting
+# routine.
+
+procedure ap_splot (ap, sid, gd, makeplot)
+
+pointer ap # pointer to the apphot structure
+int sid # id number of the star
+pointer gd # graphics stream
+int makeplot # make a plot
+
+int nx, ny, nskypix
+pointer sp, sky, str, r, gt
+real xcenter, ycenter, rmin, rmax, imin, imax
+real u1, u2, v1, v2, x1, x2, y1, y2
+int apstati()
+pointer ap_gtinit()
+real apstatr()
+
+begin
+ # Initialize.
+ if (gd == NULL || makeplot == NO)
+ return
+
+ # Check for defined center and non-constant algorithm.
+ xcenter = apstatr (ap, SXCUR)
+ ycenter = apstatr (ap, SYCUR)
+ if (IS_INDEFR(xcenter) || IS_INDEFR(ycenter))
+ return
+ if (apstati (ap, SKYFUNCTION) == AP_CONSTANT)
+ return
+
+ # Check that a buffer of sky pixels exists.
+ sky = AP_PSKY(ap)
+ nskypix = AP_NSKYPIX(sky)
+ nx = AP_SNX(sky)
+ ny = AP_SNY(sky)
+ if (nskypix <= 0 || nx <= 0 || ny <= 0)
+ return
+
+ # Allocate working space
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (r, nskypix, TY_REAL)
+
+ # Compute the radii and the plot limits.
+ call ap_xytor (Memi[AP_COORDS(sky)], Memi[AP_INDEX(sky)],
+ Memr[r], nskypix, AP_SXC(sky), AP_SYC(sky), nx)
+ call alimr (Memr[r], nskypix, rmin, rmax)
+ rmin = rmin - 1.0
+ rmax = rmax + 1.0
+ call alimr (Memr[AP_SKYPIX(sky)], nskypix, imin, imax)
+
+ # Reactivate the work station.
+ call greactivate (gd, 0)
+
+ # Store the viewport and window coordinates.
+ call ggview (gd, u1, u2, v1, v2)
+ call ggwind (gd, x1, x2, y1, y2)
+
+ # Initialize the plot.
+ call apstats (ap, IMROOT, Memc[str], SZ_LINE)
+ call sprintf (Memc[str], SZ_LINE, "%s Star %d")
+ call pargstr (Memc[str])
+ call pargi (sid)
+ gt = ap_gtinit (Memc[str], apstatr (ap,OSXCUR), apstatr(ap,OSYCUR))
+
+ # Draw the plot.
+ call gclear (gd)
+ call ap_spset (gd, gt, ap, rmin, rmax, imin, imax)
+ call ap_spannotate (gd, ap, rmin, rmax, imin, imax)
+ call ap_plotrad (gd, gt, Memr[r], Memr[AP_SKYPIX(sky)], nskypix, "plus")
+
+ # Restore the viewport and window coordinates.
+ call gsview (gd, u1, u2, v1, v2)
+ call gswind (gd, x1, x2, y1, y2)
+
+ # Free the space.
+ call ap_gtfree (gt)
+ call gdeactivate (gd, 0)
+ call sfree (sp)
+end
+
+
+# AP_SPSET -- Procedure to set up the parameters for the fitsky radial profile
+# plot.
+
+procedure ap_spset (gd, gt, ap, xmin, xmax, ymin, ymax)
+
+pointer gd # graphics stream
+pointer gt # gtools pointer
+pointer ap # apphot pointer
+real xmin, xmax # minimum and maximum radial distance
+real ymin, ymax # minimum and maximum of the y axis
+
+int fd
+pointer sp, str, title
+real aspect, scale, vx1, vx2, vy1, vy2
+int apstati(), stropen()
+real apstatr(), gstatr()
+
+begin
+ call smark (sp)
+ call salloc (str, 3 * SZ_LINE, TY_CHAR)
+ call salloc (title, SZ_LINE, TY_CHAR)
+
+ # Encode the parameter string.
+ fd = stropen (Memc[str], 3 * SZ_LINE, WRITE_ONLY)
+
+ call sysid (Memc[title], SZ_FNAME)
+ call fprintf (fd, "%s\n")
+ call pargstr (Memc[title])
+
+ call fprintf (fd,
+ "Sky: value=%0.2f sigma=%0.2f skew=%0.2f nsky=%d nreject=%d\n")
+ call pargr (apstatr (ap, SKY_MODE))
+ call pargr (apstatr (ap, SKY_SIGMA))
+ call pargr (apstatr (ap, SKY_SKEW))
+ call pargi (apstati (ap, NSKY))
+ call pargi (apstati (ap, NSKY_REJECT))
+
+ call gt_gets (gt, GTTITLE, Memc[title], SZ_LINE)
+ call fprintf (fd, "%s\n")
+ call pargstr (Memc[title])
+
+ call strclose (fd)
+
+ # Set the aspect ratio.
+ scale = apstatr (ap, SCALE)
+ aspect = gstatr (gd, G_ASPECT)
+ call gsetr (gd, G_ASPECT, 0.75)
+
+ # Set the labels and window.
+ call gseti (gd, G_XDRAWAXES, 2)
+ call gswind (gd, xmin / scale, xmax / scale, ymin, ymax)
+ call glabax (gd, Memc[str], "", "Intensity")
+ call gseti (gd, G_YDRAWAXES, 0)
+ call gseti (gd, G_XDRAWAXES, 1)
+ call ggview (gd, vx1, vx2, vy1, vy2)
+ call gsview (gd, vx1, vx2, vy1, vy2)
+ call gswind (gd, xmin, xmax, ymin, ymax)
+ call glabax (gd, "",
+ "Radial Distance (lower-pixels, upper-scale units)", "")
+
+ call gseti (gd, G_YDRAWAXES, 3)
+ call gseti (gd, G_XDRAWAXES, 3)
+ call gsetr (gd, G_ASPECT, aspect)
+ call gt_sets (gt, GTTYPE, "mark")
+
+ call sfree (sp)
+end
+
+
+# AP_SPANNOTATE -- Procedure to annotate the radial plot in fitsky.
+
+procedure ap_spannotate (gd, ap, xmin, xmax, ymin, ymax)
+
+pointer gd # graphics stream
+pointer ap # apphot structure
+real xmin, xmax # min and max of x axis
+real ymin, ymax # min and max of y axis
+
+pointer sp, str
+real annulus, dannulus, sigma, skyval, skysigma
+real apstatr ()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call gseti (gd, G_PLTYPE, GL_DASHED)
+
+ # Mark the inner sky annulus.
+ annulus = apstatr (ap, SCALE) * apstatr (ap, ANNULUS)
+ if (annulus >= xmin && annulus <= xmax) {
+ call gamove (gd, annulus, ymin)
+ call gadraw (gd, annulus, ymax)
+ call sprintf (Memc[str], SZ_LINE, "inner sky radius = %0.2f")
+ call pargr (annulus)
+ call gtext (gd, annulus, ymax, Memc[str], "q=h;u=180;v=t;p=r")
+ }
+
+ # Mark the outer sky annulus.
+ dannulus = annulus + apstatr (ap, SCALE) * apstatr (ap, DANNULUS)
+ if (dannulus >= xmin && dannulus <= xmax) {
+ call gamove (gd, dannulus, ymin)
+ call gadraw (gd, dannulus, ymax)
+ call sprintf (Memc[str], SZ_LINE, "outer sky radius = %0.2f")
+ call pargr (dannulus)
+ call gtext (gd, dannulus, ymax, Memc[str], "q=h;u=180;v=t;p=r")
+ }
+
+ # Mark the sky sigma if defined.
+ sigma = apstatr (ap, SKY_SIGMA)
+ if (! IS_INDEFR(sigma)) {
+ call gmark (gd, (xmin + xmax) / 2.0, (ymin + ymax) / 2.0,
+ GM_VEBAR, -0.25, -sigma)
+ call sprintf (Memc[str], SZ_LINE, "sigma = %g")
+ call pargr (sigma)
+ call gtext (gd, (xmin + xmax) / 2.0, (ymin + ymax + sigma) / 2.0,
+ Memc[str], "q=h;h=c")
+ }
+
+ # Mark the sky value.
+ call gseti (gd, G_PLTYPE, GL_SOLID)
+ skyval = apstatr (ap, SKY_MODE)
+ if (skyval >= ymin && skyval <= ymax) {
+ call gamove (gd, xmin, skyval)
+ call gadraw (gd, xmax, skyval)
+ }
+
+ # Mark the upper sky sigma.
+ call gseti (gd, G_PLTYPE, GL_DASHED)
+ if (! IS_INDEFR(apstatr (ap, SKY_SIGMA)))
+ skysigma = skyval + apstatr (ap, SHIREJECT) * apstatr (ap,
+ SKY_SIGMA)
+ else
+ skysigma = INDEFR
+ if (! IS_INDEFR(skysigma) && (skysigma >= ymin) && skysigma <= ymax) {
+ call gamove (gd, xmin, skysigma)
+ call gadraw (gd, xmax, skysigma)
+ #call sprintf (Memc[str], SZ_LINE, "sky sigma= %g")
+ #call pargr (skysigma)
+ }
+
+ # Mark the lower sky sigma
+ if (! IS_INDEFR(apstatr (ap, SKY_SIGMA)))
+ skysigma = skyval - apstatr (ap, SLOREJECT) * apstatr (ap,
+ SKY_SIGMA)
+ else
+ skysigma = INDEFR
+ if (! IS_INDEFR(skysigma) && (skysigma >= ymin) && skysigma <= ymax) {
+ call gamove (gd, xmin, skysigma)
+ call gadraw (gd, xmax, skysigma)
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/fitsky/apsradsetup.x b/noao/digiphot/apphot/fitsky/apsradsetup.x
new file mode 100644
index 00000000..fd4039f8
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apsradsetup.x
@@ -0,0 +1,97 @@
+include "../lib/display.h"
+include "../lib/fitsky.h"
+
+define HELPFILE "apphot$fitsky/ifitsky.key"
+
+# AP_SRADSETUP -- Procedure to set up the sky fitting interactively using
+# radial profile plot around the given coordinates.
+
+procedure ap_sradsetup (ap, im, wx, wy, gd, out, stid)
+
+pointer ap # pointer to apphot structure
+pointer im # pointero to the IRAF image
+real wx, wy # cursor coordinates
+pointer gd # pointer to graphics stream
+int out # output file descriptor
+int stid # output file sequence number
+
+int ier, key, wcs
+pointer sp, cmd
+real xcenter, ycenter, xc, yc, rmin, rmax, imin, imax, rval
+real u1, u2, v1, v2, x1, x2, y1, y2
+
+int apstati(), apfitsky(), clgcur(), ap_showplot()
+real apstatr(), ap_cannulus(), ap_cdannulus(), ap_csigma()
+real ap_cdatamin(), ap_cdatamax(), ap_crgrow()
+
+begin
+ if (gd == NULL)
+ return
+ call greactivate (gd, 0)
+
+ # Store the old window and viewport coordinates.
+ call ggview (gd, u1, u2, v1, v2)
+ call ggwind (gd, x1, x2, y1, y2)
+
+ # Plot the profile.
+ if (ap_showplot (ap, im, wx, wy, gd, xcenter, ycenter, rmin, rmax,
+ imin, imax) == ERR) {
+ call gdeactivate (gd, 0)
+ return
+ }
+
+ # Allocate memory.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ call printf (
+ "Waiting for setup menu command (?=help, v=default setup, q=quit):")
+ while (clgcur ("gcommands", xc, yc, wcs, key, Memc[cmd],
+ SZ_LINE) != EOF) {
+
+ switch (key) {
+
+ case 'q':
+ break
+ case '?':
+ call gpagefile (gd, HELPFILE, "")
+ case 's':
+ rval = ap_csigma (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'l':
+ rval = ap_cdatamin (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'u':
+ rval = ap_cdatamax (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'a':
+ rval = ap_cannulus (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'd':
+ rval = ap_cdannulus (ap, gd, out, stid, apstatr (ap, ANNULUS),
+ rmin, rmax, imin, imax)
+ case 'g':
+ rval = ap_crgrow (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'v':
+ rval = ap_cannulus (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_cdannulus (ap, gd, out, stid, apstatr (ap, ANNULUS),
+ rmin, rmax, imin, imax)
+ rval = ap_csigma (ap, gd, out, stid, rmin, rmax, imin, imax)
+ default:
+ call printf ("Unknown or ambiguous keystroke command\007\n")
+ }
+ call printf (
+ "Waiting for setup menu command (?=help, v=default setup, q=quit):")
+ }
+ call printf (
+ "Interactive setup is complete. Type w to store parameters.\n")
+
+ # Store the old window and viewport coordinates.
+ call gsview (gd, u1, u2, v1, v2)
+ call gswind (gd, x1, x2, y1, y2)
+
+ # Free the plotting space.
+ call sfree (sp)
+ call gdeactivate (gd, 0)
+
+ # Fit the new sky value and print it on the standard output.
+ ier = apfitsky (ap, im, xcenter, ycenter, NULL, gd)
+ call ap_splot (ap, 0, gd, apstati (ap, RADPLOTS))
+ call ap_qspsky (ap, ier)
+end
diff --git a/noao/digiphot/apphot/fitsky/apsshow.x b/noao/digiphot/apphot/fitsky/apsshow.x
new file mode 100644
index 00000000..da54bfbf
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/apsshow.x
@@ -0,0 +1,99 @@
+include "../lib/display.h"
+include "../lib/fitsky.h"
+
+
+# AP_SSHOW -- Procedure to print sky fitting parameters on the terminal.
+
+procedure ap_sshow (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+bool itob()
+int apstati()
+
+begin
+ call ap_nshow (ap)
+ call printf ("\n")
+ call ap_spshow (ap)
+ call printf (" %s = %b\n")
+ call pargstr (KY_RADPLOTS)
+ call pargb (itob (apstati (ap, RADPLOTS)))
+end
+
+
+# AP_SPSHOW -- Procedure to print sky fitting parameters on the terminal.
+
+procedure ap_spshow (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+pointer sp, str
+bool itob()
+int apstati()
+real apstatr()
+
+begin
+ # Print the image characteristics
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Print the sky fitting parameters.
+ call printf ("Sky Fitting Parameters\n")
+ call apstats (ap, SSTRING, Memc[str], SZ_FNAME)
+ call printf (" %s = %s %s %s = %g %s\n")
+ call pargstr (KY_SSTRING)
+ call pargstr (Memc[str])
+ call pargstr (UN_SALGORITHM)
+ call pargstr (KY_SKY_BACKGROUND)
+ call pargr (apstatr (ap, SKY_BACKGROUND))
+ call pargstr (UN_SCOUNTS)
+
+ call printf (" %s = %g %s %s = %g %s\n")
+ call pargstr (KY_ANNULUS)
+ call pargr (apstatr (ap, ANNULUS))
+ call pargstr (UN_SSCALEUNIT)
+ call pargstr (KY_DANNULUS)
+ call pargr (apstatr (ap, DANNULUS))
+ call pargstr (UN_SSCALEUNIT)
+
+ call printf (" %s = %g %s %s = %g %s %s = %b\n")
+ call pargstr (KY_K1)
+ call pargr (apstatr (ap, K1))
+ call pargstr (UN_SSIGMA)
+ call pargstr (KY_BINSIZE)
+ call pargr (apstatr (ap, BINSIZE))
+ call pargstr (UN_SSIGMA)
+ call pargstr (KY_SMOOTH)
+ call pargb (itob (apstati (ap, SMOOTH)))
+
+ call printf (" %s = %g %s %s = %g %s\n")
+ call pargstr (KY_SLOCLIP)
+ call pargr (apstatr (ap, SLOCLIP))
+ call pargstr (UN_SPERCENT)
+ call pargstr (KY_SHICLIP)
+ call pargr (apstatr (ap, SHICLIP))
+ call pargstr (UN_SPERCENT)
+
+ call printf (" %s = %g %s %s = %g %s %s = %d\n")
+ call pargstr (KY_SLOREJECT)
+ call pargr (apstatr (ap, SLOREJECT))
+ call pargstr (UN_SSIGMA)
+ call pargstr (KY_SHIREJECT)
+ call pargr (apstatr (ap, SHIREJECT))
+ call pargstr (UN_SSIGMA)
+ call pargstr (KY_SMAXITER)
+ call pargi (apstati (ap, SMAXITER))
+
+ call printf (" %s = %d %s = %g %s\n")
+ call pargstr (KY_SNREJECT)
+ call pargi (apstati (ap, SNREJECT))
+ call pargstr (KY_RGROW)
+ call pargr (apstatr (ap, RGROW))
+ call pargstr (UN_SSCALEUNIT)
+
+ call printf (" %s = %b\n")
+ call pargstr (KY_MKSKY)
+ call pargb (itob (apstati (ap, MKSKY)))
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/fitsky/fitsky.key b/noao/digiphot/apphot/fitsky/fitsky.key
new file mode 100644
index 00000000..ee515bf1
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/fitsky.key
@@ -0,0 +1,81 @@
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+v Verify the critical parameters
+w Save the current parameters
+d Plot radial profile of current star
+i Interactively set parameters using current star
+f Fit sky for current star
+spbar Fit sky for current star, output results
+m Move to next star in coordinate list
+m Fit sky for next star in coordinate list, output results
+l Fit sky for remaining stars in coordinate list, output results
+e Print error messages
+r Rewind the coordinate list
+q Exit task
+
+
+ Colon commands
+
+:show [data/sky] List the parameters
+:m [n] Move to the next [nth] star in coordinate list
+:n [n] Fit sky to next [nth] star in coordinate list, output results
+
+ Colon Parameter Editing Commands
+
+# Image and file name parameters
+
+:image [string] Image name
+:coords [string] Coordinate file name
+:output [string] Output file name
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Full width half maximum PSF (scale units)
+:emission [y/n] Emission feature (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good pixel value (counts)
+:datamax [value] Maximum good pixel value (counts)
+
+# Noise parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per adu)
+:readnoise [value] Readout noise (electrons)
+
+# Observations parameters
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Exposure time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observation (time units)
+
+# Sky fitting algorithm parameters
+
+:salgorithm [string] Sky fitting algorithm
+:skyvalue [value] User supplied sky value (counts)
+:annulus [value] Inner radius of sky annulus (scale units)
+:dannulus [value] Width of sky annulus (scale units)
+:khist [value] Sky histogram extent (+/- sky sigma)
+:smooth [y/n] Lucy smooth the sky histogram
+:binsize [value] Resolution of sky histogram (sky sigma)
+:smaxiter [value] Maximum number of iterations
+:sloclip [value] Low side clipping factor (percent)
+:shiclip [value] High side clipping factor (percent)
+:snreject [value] Maximum number of rejection cycles
+:sloreject [value] Low side pixel rejection limits (sky sigma)
+:shireject [value] High side pixel rejection limits (sky sigma)
+:rgrow [value] Region growing radius (scale units)
+
+# Marking and plotting parameters
+
+:mksky [y/n] Mark sky annuli on the display
+:radplot [y/n] Plot radial profile of sky pixels
diff --git a/noao/digiphot/apphot/fitsky/ifitsky.key b/noao/digiphot/apphot/fitsky/ifitsky.key
new file mode 100644
index 00000000..bd651bc3
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/ifitsky.key
@@ -0,0 +1,11 @@
+ Interactive Fitsky Setup Menu
+
+ v Mark and verify the critical parameters (a,d,s)
+
+ s Mark and verify the standard deviation of the sky
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
+
+ a Mark and verify the inner radius of the sky annulus
+ d Mark and verify the width of the sky annulus
+ g Mark and verify the region growing radius
diff --git a/noao/digiphot/apphot/fitsky/mkpkg b/noao/digiphot/apphot/fitsky/mkpkg
new file mode 100644
index 00000000..a72edc57
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/mkpkg
@@ -0,0 +1,59 @@
+# FITSKY Task Tools
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ apavsky.x ../lib/display.h ../lib/fitsky.h
+ apbsky.x <fset.h> ../lib/apphot.h \
+ ../lib/display.h
+ apcentroid.x <mach.h> ../lib/fitsky.h
+ apcrosscor.x <mach.h> ../lib/fitsky.h
+ apfitsky.x ../lib/apphotdef.h ../lib/noisedef.h \
+ ../lib/fitskydef.h ../lib/fitsky.h \
+ ../lib/apphot.h
+ apgauss.x <mach.h> ../lib/fitsky.h \
+ <math/nlfit.h>
+ apgrowhist.x
+ apgspars.x ../lib/display.h ../lib/fitsky.h \
+ ../lib/noise.h
+ aphgmsub.x
+ aphistplot.x <gset.h> <pkg/gtools.h> \
+ ../lib/fitsky.h
+ aplgsky.x <mach.h> ../lib/fitsky.h
+ apmean.x <mach.h> ../lib/fitsky.h
+ apmedian.x <mach.h> ../lib/fitsky.h
+ apmode.x <mach.h> ../lib/fitsky.h
+ appsky.x ../lib/fitsky.h ../lib/apphot.h
+ apradplot.x ../lib/fitsky.h
+ apreadsky.x
+ aprefitsky.x ../lib/apphotdef.h ../lib/noisedef.h \
+ ../lib/fitskydef.h ../lib/fitsky.h \
+ ../lib/apphot.h
+ aprgrow.x
+ apsconfirm.x ../lib/apphot.h ../lib/noise.h \
+ ../lib/fitsky.h
+ apserrors.x ../lib/fitsky.h
+ apsfree.x ../lib/apphotdef.h ../lib/fitskydef.h
+ apsinit.x ../lib/apphotdef.h ../lib/fitskydef.h \
+ ../lib/fitsky.h
+ apsky.x <ctype.h> <gset.h> \
+ ../lib/apphot.h ../lib/display.h \
+ ../lib/fitsky.h <imhdr.h>
+ apskybuf.x <imhdr.h> <math.h> \
+ ../lib/apphotdef.h ../lib/fitskydef.h \
+ ../lib/fitsky.h <mach.h>
+ apskycolon.x ../lib/apphot.h ../lib/fitsky.h \
+ ../lib/display.h ../lib/noise.h
+ apsradsetup.x ../lib/display.h ../lib/fitsky.h
+ appspars.x ../lib/display.h
+ apsplot.x <pkg/gtools.h> <gset.h> \
+ ../lib/apphot.h ../lib/noise.h \
+ ../lib/fitsky.h ../lib/fitskydef.h \
+ ../lib/apphotdef.h
+ apsshow.x ../lib/display.h ../lib/fitsky.h
+ t_fitsky.x <fset.h> <gset.h> \
+ ../lib/apphot.h <imhdr.h>
+ ;
diff --git a/noao/digiphot/apphot/fitsky/t_fitsky.x b/noao/digiphot/apphot/fitsky/t_fitsky.x
new file mode 100644
index 00000000..c9fb7db8
--- /dev/null
+++ b/noao/digiphot/apphot/fitsky/t_fitsky.x
@@ -0,0 +1,303 @@
+include <gset.h>
+include <fset.h>
+include <imhdr.h>
+include "../lib/apphot.h"
+
+# T_FITSKY -- Procedure to fit sky values in a an annular region around
+# a list of objects.
+
+procedure t_fitsky ()
+
+pointer image # pointer to the name of the image
+pointer output # pointer to output file name
+pointer coords # coordinate file
+pointer plotfile # pointer to file of graphics metacode
+pointer graphics # pointer to graphics display device
+pointer display # pointer to display device
+int interactive # mode of use
+int cache # cache the image pixels in memory
+int verify # verify critical parameters
+int update # update the critical parameter
+int verbose # verbose mode
+
+pointer sp, outfname, cname, ap, im, mgd, gd, id, str
+int sid, lid, limlist, lclist, lolist, out, cl, pfd, root, stat, memstat
+int imlist, clist, olist, wcs, req_size, old_size, buf_size
+
+pointer immap(), gopen()
+int imtlen(), imtgetim(), clplen(), clgfil(), btoi(), fnldir(), strncmp()
+int strlen(), apsky(), imtopenp(), clpopnu(), open(), clgwrd(), ap_memstat()
+int sizeof()
+bool clgetb(), streq()
+errchk gopen
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (coords, SZ_FNAME, TY_CHAR)
+ call salloc (plotfile, SZ_FNAME, TY_CHAR)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+ call salloc (display, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (cname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Set the standard output to flush on a newline.
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get input and output file names.
+ imlist = imtopenp ("image")
+ limlist = imtlen (imlist)
+ clist = clpopnu ("coords")
+ lclist = clplen (clist)
+ olist = clpopnu ("output")
+ lolist = clplen (olist)
+
+ # Check that image and coordinate list lengths match.
+ if (limlist < 1 || (lclist > 1 && lclist != limlist)) {
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+ call error (0, "Imcompatable image and coordinate list lengths")
+ }
+
+ # Check that image and output list lengths match.
+ if (lolist > 1 && lolist != limlist) {
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+ call error (0, "Imcompatible image and output list lengths")
+ }
+
+ call clgstr ("icommands.p_filename", Memc[cname], SZ_FNAME)
+ if (Memc[cname] != EOS)
+ interactive = NO
+ #else if (lclist == 0)
+ #interactive = YES
+ else
+ interactive = btoi (clgetb ("interactive"))
+ cache = btoi (clgetb("cache"))
+ verify = btoi (clgetb ("verify"))
+ update = btoi (clgetb ("update"))
+ verbose = btoi (clgetb ("verbose"))
+
+ # Get the parameters.
+ call ap_sgpars (ap)
+ if (verify == YES && interactive == NO) {
+ call ap_sconfirm (ap, NULL, 1)
+ if (update == YES)
+ call ap_pspars (ap)
+ }
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_LINE, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (ap, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_LINE, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (ap, WCSOUT, wcs)
+
+ # Get the graphics and display devices.
+ call clgstr ("graphics", Memc[graphics], SZ_FNAME)
+ call clgstr ("display", Memc[display], SZ_FNAME)
+
+ # Open plot files.
+ if (interactive == YES) {
+ if (Memc[graphics] == EOS)
+ gd = NULL
+ else {
+ iferr {
+ gd = gopen (Memc[graphics], APPEND+AW_DEFER, STDGRAPH)
+ } then {
+ call eprintf (
+ "Warning: Error opening graphics device.\n")
+ gd = NULL
+ }
+ }
+ if (Memc[display] == EOS)
+ id = NULL
+ else if (streq (Memc[graphics], Memc[display]))
+ id = gd
+ else {
+ iferr {
+ id = gopen (Memc[display], APPEND, STDIMAGE)
+ } then {
+ call eprintf (
+ "Warning: Graphics overlay not available for display device.\n")
+ id = NULL
+ }
+ }
+ } else {
+ gd = NULL
+ id = NULL
+ }
+
+ # Open the plot metacode file.
+ call clgstr ("plotfile", Memc[plotfile], SZ_FNAME)
+ if (Memc[plotfile] == EOS)
+ pfd = NULL
+ else
+ pfd = open (Memc[plotfile], APPEND, BINARY_FILE)
+ if (pfd != NULL)
+ mgd = gopen (Memc[graphics], NEW_FILE, pfd)
+ else
+ mgd = NULL
+
+ # Begin looping over image list.
+ sid = 1
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open image.
+ im = immap (Memc[image], READ_ONLY, 0)
+ call apimkeys (ap, im, Memc[image])
+
+ # Set the image display viewport.
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[image], im, 4)
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+
+ # Open the coordinate file, where coords is assumed to be a simple
+ # text file in which the x and y positions are in columns 1 and 2
+ # respectively and all remaining fields are ignored.
+
+ if (lclist <= 0) {
+ cl = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (clist, Memc[coords], SZ_FNAME)
+ root = fnldir (Memc[coords], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[coords+root], 7) == 0 || root ==
+ strlen (Memc[coords])) {
+ call ap_inname (Memc[image], Memc[outfname], "coo",
+ Memc[outfname], SZ_FNAME)
+ lclist = limlist
+ cl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else if (stat != EOF) {
+ call strcpy (Memc[coords], Memc[outfname], SZ_FNAME)
+ cl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else {
+ call apstats (ap, CLNAME, Memc[outfname], SZ_FNAME)
+ call seek (cl, BOF)
+ }
+ }
+ call apsets (ap, CLNAME, Memc[outfname])
+ call apfroot (Memc[outfname], Memc[str], SZ_LINE)
+ call apsets (ap, CLROOT, Memc[str])
+
+ # Open the output text file, if output is "default", dir$default
+ # or a directory specification then the extension "sky" is added
+ # to the image name and a suitable version number is appended to
+ # the output name. If the output string is null to output file
+ # is created.
+
+ if (lolist == 0) {
+ out = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (olist, Memc[output], SZ_FNAME)
+ root = fnldir (Memc[output], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[output+root], 7) == 0 || root ==
+ strlen (Memc[output])) {
+ call apoutname (Memc[image], Memc[outfname], "sky",
+ Memc[outfname], SZ_FNAME)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ lolist = limlist
+ } else if (stat != EOF) {
+ call strcpy (Memc[output], Memc[outfname], SZ_FNAME)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ } else
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ }
+ call apsets (ap, OUTNAME, Memc[outfname])
+
+ # Fit the sky
+ if (interactive == NO) {
+ if (Memc[cname] != EOS)
+ stat = apsky (ap, im, cl, NULL, NULL, mgd, NULL, out,
+ sid, NO, cache)
+ else if (cl != NULL) {
+ lid = 1
+ call apbsky (ap, im, cl, NULL, out, sid, lid, gd, mgd, id,
+ verbose)
+ stat = NO
+ } else
+ stat = NO
+ } else
+ stat = apsky (ap, im, cl, NULL, gd, mgd, id, out, sid, YES,
+ cache)
+
+ # Cleanup.
+ call imunmap (im)
+ if (cl != NULL) {
+ if (lclist > 1)
+ call close (cl)
+ }
+ if (out != NULL && lolist != 1) {
+ call close (out)
+ if (sid <= 1) {
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ call delete (Memc[outfname])
+ }
+ sid = 1
+ }
+
+ # Uncache memory.
+ call fixmem (old_size)
+
+ if (stat == YES)
+ break
+ }
+
+ # If only one coordinate file for a list of images close.
+ if (cl != NULL && lclist == 1)
+ call close (cl)
+
+ # If only one output file for a list of images close.
+ if (out != NULL && lolist == 1) {
+ call close (out)
+ if (sid <= 1) {
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ call delete (Memc[outfname])
+ }
+ }
+
+ # Close up plot files.
+ if (id == gd && id != NULL) {
+ call gclose (id)
+ } else {
+ if (gd != NULL)
+ call gclose (gd)
+ if (id != NULL)
+ call gclose (id)
+ }
+ if (mgd != NULL)
+ call gclose (mgd)
+ if (pfd != NULL)
+ call close (pfd)
+
+ # Free sky fitting structure
+ call apsfree (ap)
+
+ # Close up lists.
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/fitskypars.par b/noao/digiphot/apphot/fitskypars.par
new file mode 100644
index 00000000..2a90cf33
--- /dev/null
+++ b/noao/digiphot/apphot/fitskypars.par
@@ -0,0 +1,17 @@
+# SKY FITTING PARAMETERS
+
+salgorithm,s,h,"centroid","|median|mode|centroid|gauss|crosscor|ofilter|histplot|radplot|constant|file|mean|",,Sky fitting algorithm
+annulus,r,h,10.0,,,Inner radius of sky annulus in scale units
+dannulus,r,h,10.0,,,Width of sky annulus in scale units
+skyvalue,r,h,0.0,,,User sky value
+smaxiter,i,h,10,,,Maximum number of sky fitting iterations
+sloclip,r,h,0.0,,,Lower clipping factor in percent
+shiclip,r,h,0.0,,,Upper clipping factor in percent
+snreject,i,h,50,,,Maximum number of sky fitting rejection iterations
+sloreject,r,h,3.0,,,Lower K-sigma rejection limit in sky sigma
+shireject,r,h,3.0,,,Upper K-sigma rejection limit in sky sigma
+khist,r,h,3.0,,,Half width of histogram in sky sigma
+binsize,r,h,0.10,,,Binsize of histogram in sky sigma
+smooth,b,h,no,,,Boxcar smooth the histogram
+rgrow,r,h,0.0,,,Region growing radius in scale units
+mksky,b,h,no,,,Mark sky annuli on the display
diff --git a/noao/digiphot/apphot/lib/apphot.h b/noao/digiphot/apphot/lib/apphot.h
new file mode 100644
index 00000000..b9c7fb33
--- /dev/null
+++ b/noao/digiphot/apphot/lib/apphot.h
@@ -0,0 +1,110 @@
+# APPHOT header file
+
+# APPHOT parameters (# 1 - 100)
+
+define IMNAME 1 # Image name
+define IMROOT 2 # Image name
+define CLNAME 3 # Coordinates file name
+define CLROOT 4 # Coordinates file name
+define PLOTFILE 5 # Name of the plotfile
+define OUTNAME 6 # Output file name
+
+define WCSIN 7 # Input WCS
+define WCSOUT 8 # Input WCS
+define MW 9 # MWCS descriptor
+define CTIN 10 # Input WCS transformation
+define CTOUT 11 # Output WCS transformation
+
+define SCALE 12 # Scale in pixels / unit
+define FWHMPSF 13 # Full width half maximum of the PSF
+define POSITIVE 14 # Emission or absorption feature
+define DATAMIN 15 # Minimum good data value
+define DATAMAX 16 # Maximum good data value
+
+define ITIME 17 # Exposure time
+define AIRMASS 18 # Airmass keyword
+define FILTER 19 # Filter keyword
+define OBSTIME 20 # Time of observation keyword
+
+define XAIRMASS 21 # Airmass value
+define FILTERID 22 # Filter id
+define OTIME 23 # Time stamp
+define EXPOSURE 24 # Exposure time keyword
+
+define WX 25 # Previous X cursor position
+define WY 26 # Previous Y cursor position
+define CWX 27 # Current X cursor position
+define CWY 28 # Current Y cursor position
+
+# Define the WCS types
+
+define WCSINSTR "|logical|tv|physical|world|"
+define WCSOUTSTR "|logical|tv|physical|"
+define WCS_LOGICAL 1
+define WCS_TV 2
+define WCS_PHYSICAL 3
+define WCS_WORLD 4
+
+# define APPHOT keywords
+
+define KY_FWHMPSF "fwhmpsf"
+define KY_IMNAME "image"
+define KY_POSITIVE "emission"
+define KY_ITIME "itime"
+define KY_EXPOSURE "exposure"
+define KY_DATAMIN "datamin"
+define KY_DATAMAX "datamax"
+define KY_OUTNAME "output"
+define KY_CLNAME "coords"
+define KY_SCALE "scale"
+define KY_AIRMASS "airmass"
+define KY_XAIRMASS "xairmass"
+define KY_FILTER "filter"
+define KY_FILTERID "ifilter"
+define KY_OBSTIME "obstime"
+define KY_OTIME "otime"
+
+# define APPHOT units strings
+
+define UN_ASCALEUNIT "scaleunit"
+define UN_ASWITCH "switch"
+define UN_ACOUNTS "counts"
+define UN_AUNITS "units"
+define UN_ATIMEUNIT "timeunit"
+define UN_AKEYWORD "keyword"
+define UN_ANAME "name"
+define UN_ANUMBER "number"
+
+# APPHOT string commands
+
+define APCMDS "|fwhmpsf|emission|exposure|itime|datamin|datamax|image|coords|output|scale|airmass|xairmass|filter|ifilter|obstime|otime|"
+
+define APCMD_FWHMPSF 1
+define APCMD_EMISSION 2
+define APCMD_EXPOSURE 3
+define APCMD_ITIME 4
+define APCMD_DATAMIN 5
+define APCMD_DATAMAX 6
+define APCMD_IMAGE 7
+define APCMD_COORDS 8
+define APCMD_OUTPUT 9
+define APCMD_SCALE 10
+define APCMD_AIRMASS 11
+define APCMD_XAIRMASS 12
+define APCMD_FILTER 13
+define APCMD_FILTERID 14
+define APCMD_OBSTIME 15
+define APCMD_OTIME 16
+
+
+# Define the memory cacheing fudge factor
+
+define MEMFUDGE 1.05
+
+# Miscellaneous commands
+
+define MISC "|show|radplots|"
+define MISC1 "|show|"
+
+define ACMD_SHOW 1
+define ACMD_RADPLOTS 2
diff --git a/noao/digiphot/apphot/lib/apphotdef.h b/noao/digiphot/apphot/lib/apphotdef.h
new file mode 100644
index 00000000..a63b6dbd
--- /dev/null
+++ b/noao/digiphot/apphot/lib/apphotdef.h
@@ -0,0 +1,80 @@
+# APPHOT Structure
+
+define LEN_APSTRUCT (36 + 12 * SZ_FNAME + 12)
+
+# apphot definitions
+
+define AP_VERSION Memi[$1] # Package version number
+define AP_CWX Memr[P2R($1+1)] # Current x cursor coordinate
+define AP_CWY Memr[P2R($1+2)] # Current y cursor coordinate
+define AP_WX Memr[P2R($1+3)] # Previous x cursor coordinate
+define AP_WY Memr[P2R($1+4)] # Previous y cursor coordinate
+define AP_FWHMPSF Memr[P2R($1+5)] # FWHM of the PSF
+define AP_SCALE Memr[P2R($1+6)] # Scale in pixels / unit (internal)
+define AP_POSITIVE Memi[$1+7] # Emission feature ?
+define AP_DATAMIN Memr[P2R($1+8)] # Mininum good data value
+define AP_DATAMAX Memr[P2R($1+9)] # Maximum good data value
+define AP_ITIME Memr[P2R($1+10)] # Exposure time
+define AP_XAIRMASS Memr[P2R($1+11)] # Air mass
+
+# pointer to the apphot strucutures
+
+define AP_NOISE Memi[$1+12] # Pointer to noise structure
+define AP_PCENTER Memi[$1+13] # Pointer to center structure
+define AP_PSKY Memi[$1+14] # Pointer to sky structure
+define AP_PPSF Memi[$1+15] # Pointer to psf structure
+define AP_PPHOT Memi[$1+16] # Pointer to phot structure
+define AP_PDISPLAY Memi[$1+17] # Pointer to display structure
+define AP_POLY Memi[$1+18] # Pointer to polyphot structure
+define AP_RPROF Memi[$1+19] # Pointer to radprof strucuture
+define AP_PFIND Memi[$1+20] # Pointer to the find structure
+
+# pointer to sequential access buffer (not used currently)
+
+define AP_SEQUENTIAL Memi[$1+21] # Sequential or random access
+define AP_IMBUF Memi[$1+22] # Pointer to internal buffer
+define AP_HWIDTH Memi[$1+23] # Half-width of buffer in image lines
+define AP_IMX1 Memi[$1+24] # Lower column limit of buffer
+define AP_IMX2 Memi[$1+25] # Upper column limit of buffer
+define AP_IMY1 Memi[$1+26] # Lower line limit of buffer
+define AP_IMY2 Memi[$1+27] # Upper line limit of buffer
+
+# pointer to the wcs info
+
+
+define AP_WCSIN Memi[$1+28] # the input wcs
+define AP_WCSOUT Memi[$1+29] # the output wcs
+define AP_MW Memi[$1+30] # the mwcs pointer
+define AP_CTIN Memi[$1+31] # the input transformation pointer
+define AP_CTOUT Memi[$1+32] # the output transformation pointer
+
+# image, file and keyword names
+
+define AP_IMNAME Memc[P2C($1+36)] # IRAF image name
+define AP_IMROOT Memc[P2C($1+36+SZ_FNAME+1)] # IRAF image root name
+define AP_CLNAME Memc[P2C($1+36+2*SZ_FNAME+2)] # Coordinate list
+define AP_CLROOT Memc[P2C($1+36+3*SZ_FNAME+3)] # Coordinate list root
+define AP_PLOTFILE Memc[P2C($1+36+4*SZ_FNAME+4)] # Plotfile
+define AP_OUTNAME Memc[P2C($1+36+5*SZ_FNAME+5)] # Output
+define AP_EXPOSURE Memc[P2C($1+36+6*SZ_FNAME+6)] # Exposure keyword
+define AP_AIRMASS Memc[P2C($1+36+7*SZ_FNAME+7)] # Airmass keyword
+define AP_FILTER Memc[P2C($1+36+8*SZ_FNAME+8)] # Filter keyword
+define AP_FILTERID Memc[P2C($1+36+9*SZ_FNAME+9)] # Filter id
+define AP_OBSTIME Memc[P2C($1+36+10*SZ_FNAME+10)] # Obstime keyword
+define AP_OTIME Memc[P2C($1+36+11*SZ_FNAME+11)] # Time of observation
+
+# default definitions
+
+define DEF_SCALE 1.0000
+define DEF_POSITIVE YES
+define DEF_DATAMIN INDEFR
+define DEF_DATAMAX INDEFR
+
+define DEF_EXPOSURE ""
+define DEF_AIRMASS ""
+define DEF_FILTER ""
+define DEF_OBSTIME ""
+define DEF_ITIME INDEFR
+define DEF_XAIRMASS INDEFR
+define DEF_FILTERID "INDEF"
+define DEF_OTIME "INDEF"
diff --git a/noao/digiphot/apphot/lib/center.h b/noao/digiphot/apphot/lib/center.h
new file mode 100644
index 00000000..ecf672f3
--- /dev/null
+++ b/noao/digiphot/apphot/lib/center.h
@@ -0,0 +1,102 @@
+# CENTER defintions
+
+# centering algorithms
+
+define AP_CENTROID1D 1 # 1D centroiding
+define AP_GAUSS1D 2 # 1D Gaussian
+define AP_NONE 3 # No centering
+define AP_OFILT1D 4 # 1-D optimal filtering
+
+# centering errors (# 101 - 200)
+
+define AP_OK 0 # No error
+define AP_CTR_NOAREA 101 # No pixels for centering
+define AP_CTR_OUTOFBOUNDS 102 # Centering aperture extends oob
+define AP_CTR_LOWSNRATIO 103 # S/N ratio too low for centering
+define AP_CTR_NTOO_SMALL 104 # Too few histogram bins
+define AP_CTR_SINGULAR 105 # Fit is singular
+define AP_CTR_NOCONVERGE 106 # Solution does not converge
+define AP_CTR_BADSHIFT 107 # Max shift parameter exceeded
+define AP_CTR_BADDATA 108 # Bad data in centering subraster
+
+# centering parameters (# 101 - 200)
+
+define CAPERT 101
+define CENTERFUNCTION 102
+define MINSNRATIO 103
+define MAXSHIFT 104
+define CLEAN 105
+define RCLEAN 106
+define RCLIP 107
+define SIGMACLEAN 108
+define OXINIT 109
+define OYINIT 110
+define XCENTER 111
+define YCENTER 112
+define OXCENTER 113
+define OYCENTER 114
+define XERR 115
+define YERR 116
+define CMAXITER 117
+define CXCUR 118
+define CYCUR 119
+define XSHIFT 120
+define YSHIFT 121
+define OXSHIFT 122
+define OYSHIFT 123
+define CSTRING 124
+define CDATALIMIT 125
+define CTHRESHOLD 126
+
+# center keywords
+
+define KY_CAPERT "cboxwidth"
+define KY_CSTRING "calgorithm"
+define KY_MINSNRATIO "minsnratio"
+define KY_MAXSHIFT "maxshift"
+define KY_CLEAN "clean"
+define KY_RCLEAN "rclean"
+define KY_RCLIP "rclip"
+define KY_SIGMACLEAN "kclean"
+define KY_CMAXITER "cmaxiter"
+define KY_CTHRESHOLD "cthreshold"
+
+# center unit strings
+
+#define UN_CAPERT "scaleunit"
+#define UN_CSTRING "algorithm"
+#define UN_MINSNRATIO "number"
+#define UN_MAXSHIFT "scaleunit"
+#define UN_CLEAN "switch"
+#define UN_RCLEAN "scaleunit"
+#define UN_RCLIP "scaleunit"
+#define UN_SIGMACLEAN "sigma"
+#define UN_CMAXITER "number"
+#define UN_CTHRESHOLD "sigma"
+
+define UN_CSCALEUNIT "scaleunit"
+define UN_CNUMBER "number"
+define UN_CSIGMA "sigma"
+define UN_CSWITCH "switch"
+define UN_CALGORITHM "algorithm"
+
+# center string commands
+
+define CSHOWARGS "|data|center|"
+define CFUNCS "|centroid|gauss|none|ofilter|"
+define CCMDS "|cboxwidth|calgorithm|maxshift|minsnratio|cmaxiter|clean|rclean|rclip|kclean|mkcenter|cthreshold|"
+
+define CCMD_CBOXWIDTH 1
+define CCMD_CALGORITHM 2
+define CCMD_MAXSHIFT 3
+define CCMD_MINSNRATIO 4
+define CCMD_CMAXITER 5
+define CCMD_CLEAN 6
+define CCMD_RCLEAN 7
+define CCMD_RCLIP 8
+define CCMD_KCLEAN 9
+define CCMD_MKCENTER 10
+define CCMD_CTHRESHOLD 11
+
+define CCMD_DATA 1
+define CCMD_CENTER 2
diff --git a/noao/digiphot/apphot/lib/centerdef.h b/noao/digiphot/apphot/lib/centerdef.h
new file mode 100644
index 00000000..c9dcd6a4
--- /dev/null
+++ b/noao/digiphot/apphot/lib/centerdef.h
@@ -0,0 +1,60 @@
+# CENTER header file
+
+define LEN_CENSTRUCT (36 + SZ_FNAME + 1)
+
+# centering parameters
+
+define AP_CENTERFUNCTION Memi[$1] # Centering algorithm
+define AP_CAPERT Memr[P2R($1+1)] # Centering box half-width
+define AP_CTHRESHOLD Memr[P2R($1+2)] # Threshold above cdatalimit
+define AP_MAXSHIFT Memr[P2R($1+3)] # Maximum center shift
+define AP_MINSNRATIO Memr[P2R($1+4)] # Minimum s/n ratio
+define AP_CLEAN Memi[$1+5] # Clean before centering
+define AP_RCLEAN Memr[P2R($1+6)] # Cleaning radius
+define AP_RCLIP Memr[P2R($1+7)] # Clipping radius
+define AP_SIGMACLEAN Memr[P2R($1+8)] # Sky sigma for cleaning
+define AP_CMAXITER Memi[$1+9] # Maximum number of iterations
+
+# centering buffers
+
+define AP_CTRPIX Memi[$1+10] # Pointer to pixels
+define AP_XCTRPIX Memi[$1+11] # Pointer to x coords (not used)
+define AP_YCTRPIX Memi[$1+12] # Pointer to y coords (not used)
+define AP_NCTRPIX Memi[$1+13] # Number of pixels (not used)
+define AP_LENCTRBUF Memi[$1+14] # Centering buffer sz (not used)
+define AP_CXCUR Memr[P2R($1+15)] # Centering buffer x center
+define AP_CYCUR Memr[P2R($1+16)] # Centering buffer y center
+define AP_CXC Memr[P2R($1+17)] # X center of subraster
+define AP_CYC Memr[P2R($1+18)] # Y center of subraster
+define AP_CNX Memi[$1+19] # Y dimension of subraster
+define AP_CNY Memi[$1+20] # Y dimension of subraster
+
+# center fitting output
+
+define AP_OXINIT Memr[P2R($1+21)] # initial output x center
+define AP_OYINIT Memr[P2R($1+22)] # initial output y center
+define AP_XCENTER Memr[P2R($1+23)] # computed x center
+define AP_YCENTER Memr[P2R($1+24)] # computed y center
+define AP_OXCENTER Memr[P2R($1+25)] # computed output x center
+define AP_OYCENTER Memr[P2R($1+26)] # computed output y center
+define AP_XSHIFT Memr[P2R($1+27)] # total x shift
+define AP_YSHIFT Memr[P2R($1+28)] # total y shift
+define AP_OXSHIFT Memr[P2R($1+29)] # total output x shift
+define AP_OYSHIFT Memr[P2R($1+30)] # total output y shift
+define AP_XERR Memr[P2R($1+31)] # x error
+define AP_YERR Memr[P2R($1+32)] # y error
+define AP_CDATALIMIT Memr[P2R($1+33)] # min (max) of subraster
+define AP_CSTRING Memc[P2C($1+34)]# centering algorithm id
+
+# default setup values for centering parameters
+
+define DEF_CENTERFUNCTION AP_CENTROID1D
+define DEF_CAPERT 2.5
+define DEF_CTHRESHOLD 0.0
+define DEF_MINSNRATIO 1.0
+define DEF_CMAXITER 10
+define DEF_MAXSHIFT 1.0
+define DEF_CLEAN NO
+define DEF_RCLEAN 1.0
+define DEF_RCLIP 2.0
+define DEF_CLEANSIGMA 3.0
diff --git a/noao/digiphot/apphot/lib/display.h b/noao/digiphot/apphot/lib/display.h
new file mode 100644
index 00000000..ae8ff523
--- /dev/null
+++ b/noao/digiphot/apphot/lib/display.h
@@ -0,0 +1,21 @@
+# APPHOT display parameters
+
+# display parameters (# 501 - 600)
+
+define MKSKY 501
+define MKCENTER 502
+define MKAPERT 503
+define MKPOLYGON 504
+define MKPSFBOX 505
+define RADPLOTS 506
+define MKDETECTIONS 507
+
+# display parameters
+
+define KY_MKSKY "mksky"
+define KY_MKCENTER "mkcenter"
+define KY_MKAPERT "mkapert"
+define KY_MKPOLYGON "mkpolygon"
+define KY_MKPSFBOX "mkbox"
+define KY_RADPLOTS "radplots"
+define KY_MKDETECTIONS "mkdetections"
diff --git a/noao/digiphot/apphot/lib/displaydef.h b/noao/digiphot/apphot/lib/displaydef.h
new file mode 100644
index 00000000..8add188d
--- /dev/null
+++ b/noao/digiphot/apphot/lib/displaydef.h
@@ -0,0 +1,23 @@
+# APPHOT display structure
+
+define LEN_DISPLAYSTRUCT 10
+
+# display parameters
+
+define AP_MKSKY Memi[$1] # Mark sky circles
+define AP_MKCENTER Memi[$1+1] # Mark center circles
+define AP_MKAPERT Memi[$1+2] # Mark aperture circles
+define AP_MKPOLYGON Memi[$1+3] # Mark polygon
+define AP_MKPSFBOX Memi[$1+4] # Mark psf fitting box
+define AP_RADPLOTS Memi[$1+5] # Make radial plots
+define AP_MKDETECTIONS Memi[$1+6] # Mark detected stars
+
+# default values for the display parameters
+
+define DEF_MKSKY NO
+define DEF_MKCENTER NO
+define DEF_MKAPERT NO
+define DEF_MKPOLYGON NO
+define DEF_MKPSFBOX NO
+define DEF_RADPLOTS NO
+define DEF_MKDETECTIONS NO
diff --git a/noao/digiphot/apphot/lib/find.h b/noao/digiphot/apphot/lib/find.h
new file mode 100644
index 00000000..b5e3760b
--- /dev/null
+++ b/noao/digiphot/apphot/lib/find.h
@@ -0,0 +1,75 @@
+# Find header file
+
+# find parameters (# 701 - 800)
+
+define RATIO 701
+define THETA 702
+define NSIGMA 703
+define SHARPLO 704
+define SHARPHI 705
+define ROUNDLO 706
+define ROUNDHI 707
+define THRESHOLD 708
+
+# find keyword units
+
+define KY_RATIO "ratio"
+define KY_THETA "theta"
+define KY_NSIGMA "nsigma"
+define KY_SHARPLO "sharplo"
+define KY_SHARPHI "sharphi"
+define KY_ROUNDLO "roundlo"
+define KY_ROUNDHI "roundhi"
+define KY_THRESHOLD "threshold"
+
+# find parameter units
+
+#define UN_RATIO "number"
+#define UN_THETA "degrees"
+#define UN_NSIGMA "sigma"
+#define UN_SHARPLO "number"
+#define UN_SHARPHI "number"
+#define UN_ROUNDLO "number"
+#define UN_ROUNDHI "number"
+#define UN_THRESHOLD "sigma"
+
+define UN_FNUMBER "number"
+define UN_FSIGMA "sigma"
+define UN_FDEGREES "degrees"
+
+# define daofind commands
+
+define FSHOWARGS "|data|find|"
+define FCMDS "|nsigma|ratio|sharplo|sharphi|roundlo|roundhi|mkdetections|\
+theta|threshold|"
+
+# define daofind command strings
+
+define FCMD_NSIGMA 1
+define FCMD_RATIO 2
+define FCMD_SHARPLO 3
+define FCMD_SHARPHI 4
+define FCMD_ROUNDLO 5
+define FCMD_ROUNDHI 6
+define FCMD_MKDETECTIONS 7
+define FCMD_THETA 8
+define FCMD_THRESHOLD 9
+
+define FCMD_DATA 1
+define FCMD_FIND 2
+
+
+# define the gaussian sums structure
+
+define LEN_GAUSS 10
+
+define GAUSS_SUMG 1
+define GAUSS_SUMGSQ 2
+define GAUSS_PIXELS 3
+define GAUSS_DENOM 4
+define GAUSS_SGOP 5
+
+# miscellaneous
+
+define FWHM_TO_SIGMA 0.42467
+define RMIN 2.001
diff --git a/noao/digiphot/apphot/lib/finddef.h b/noao/digiphot/apphot/lib/finddef.h
new file mode 100644
index 00000000..4ea9e99d
--- /dev/null
+++ b/noao/digiphot/apphot/lib/finddef.h
@@ -0,0 +1,26 @@
+# FIND header file
+
+define LEN_FIND (10)
+
+# find model parameters
+
+define AP_RATIO Memr[P2R($1)] # Gaussian axis ratio
+define AP_THETA Memr[P2R($1+1)] # Gaussian position angle
+define AP_NSIGMA Memr[P2R($1+2)] # Size of convolution kernel
+define AP_SHARPLO Memr[P2R($1+3)] # Lower sharpness bound
+define AP_SHARPHI Memr[P2R($1+4)] # Upper sharpness bound
+define AP_ROUNDLO Memr[P2R($1+5)] # Lower roundness bound
+define AP_ROUNDHI Memr[P2R($1+6)] # Higher roundness bound
+define AP_THRESHOLD Memr[P2R($1+7)] # Threshold in sigma for detection
+
+
+# noise model defaults
+
+define DEF_RATIO 1.0
+define DEF_THETA 0.0
+define DEF_NSIGMA 1.5
+define DEF_SHARPLO 0.2
+define DEF_SHARPHI 1.0
+define DEF_ROUNDLO -1.0
+define DEF_ROUNDHI 1.0
+define DEF_THRESHOLD 0.0
diff --git a/noao/digiphot/apphot/lib/fitpsf.h b/noao/digiphot/apphot/lib/fitpsf.h
new file mode 100644
index 00000000..5aa5f04c
--- /dev/null
+++ b/noao/digiphot/apphot/lib/fitpsf.h
@@ -0,0 +1,72 @@
+# FITPSF header file
+
+# fitpsf functions
+
+define AP_RADGAUSS 1 # Radial Gaussian
+define AP_ELLGAUSS 2 # Elliptical Gaussian
+define AP_MOMENTS 3 # Moment analysis
+
+# fitpsf errors (# 401 - 500)
+
+define AP_OK 0 # no error
+define AP_NOPSFAREA 401 # No pixels for PSF
+define AP_PSF_OUTOFBOUNDS 402 # PSF aperture extends oob
+define AP_NPSF_TOO_SMALL 403 # Too few PSF points
+define AP_PSF_SINGULAR 404 # Fit is singular
+define AP_PSF_NOCONVERGE 405 # Solution does not converge
+
+# fitpsf parameters (# 401 - 500)
+
+define PSFUNCTION 401
+define MAXNPARS 402
+define PK2 403
+define PMAXITER 404
+define PSFAPERT 405
+define NPARS 406
+define PARS 407
+define PERRS 408
+define PNREJECT 409
+define PFXCUR 410
+define PFYCUR 411
+define OPFXCUR 412
+define OPFYCUR 413
+define PSFSTRING 414
+
+# define fitpsf keywords
+
+define KY_PSFUNCTION "function"
+define KY_PSFAPERT "box"
+define KY_PK2 "kreject"
+define KY_PMAXITER "maxiter"
+define KY_PNREJECT "nreject"
+define KY_PSFSTRING "function"
+
+# define fitpsf units
+
+#define UN_PSFUNCTION "model"
+#define UN_PSFAPERT "scaleunit"
+#define UN_PK2 "sigma"
+#define UN_PMAXITER "number"
+#define UN_PNREJECT "number"
+#define UN_PSFSTRING "model"
+
+define UN_PSFSCALEUNIT "scaleunit"
+define UN_PSFNUMBER "number"
+define UN_PSFMODEL "model"
+define UN_PSFSIGMA "sigma"
+
+# fitpsf string constants
+
+define PFSHOWARGS "|data|fit|"
+define PSFFUNCS "|radgauss|elgauss|moments|"
+define PSFCMDS "|function|box|kreject|maxiter|nreject|mkbox|"
+
+define PFCMD_DATA 1
+define PFCMD_FIT 2
+
+define PFCMD_FUNCTION 1
+define PFCMD_BOX 2
+define PFCMD_KREJECT 3
+define PFCMD_MAXITER 4
+define PFCMD_NREJECT 5
+define PFCMD_MKBOX 6
diff --git a/noao/digiphot/apphot/lib/fitpsfdef.h b/noao/digiphot/apphot/lib/fitpsfdef.h
new file mode 100644
index 00000000..bbd88ad0
--- /dev/null
+++ b/noao/digiphot/apphot/lib/fitpsfdef.h
@@ -0,0 +1,43 @@
+# FITPSF header file
+
+define LEN_PSFSTRUCT (25 + SZ_FNAME + 1)
+
+# fitpsf parameters
+
+define AP_PSFUNCTION Memi[$1] # PSF function
+define AP_PSFNPARS Memi[$1+1] # Number of parameters
+define AP_MAXNPARS Memi[$1+2] # Maximum number of parameters
+define AP_PSFAPERT Memr[P2R($1+3)] # Half-width of fitting box
+define AP_PMAXITER Memi[$1+4] # Maximum number of iterations
+define AP_PK2 Memr[P2R($1+5)] # Rejection limit in sigma
+define AP_PNREJECT Memi[$1+6] # Maximum number of rejections
+
+# fitpsf buffers
+
+define AP_PSFPIX Memi[$1+7] # Pointer to pixels
+define AP_PSFXPIX Memi[$1+8] # X coordinates array (not used)
+define AP_PSFYPIX Memi[$1+9] # Y coordinates array (not used)
+define AP_NPSFPIX Memi[$1+10] # Number of pixels (not used)
+define AP_LENPSFBUF Memi[$1+11] # Length of pixel buffer (not used)
+define AP_PXC Memr[P2R($1+12)]# X center of subraster
+define AP_PYC Memr[P2R($1+13)]# Y center of subraster
+define AP_PNX Memi[$1+14] # X dimension of subraster
+define AP_PNY Memi[$1+15] # Y dimension of subraster
+define AP_PFXCUR Memr[P2R($1+16)]# X initial position
+define AP_PFYCUR Memr[P2R($1+17)]# Y initial position
+define AP_OPFXCUR Memr[P2R($1+18)]# X initial position
+define AP_OPFYCUR Memr[P2R($1+19)]# Y initial position
+
+# fitpsf answers
+
+define AP_PPARS Memi[$1+20] # fitted parameters
+define AP_PPERRS Memi[$1+21] # errors in the parameters
+define AP_PSFSTRING Memc[P2C($1+22)] # functions string
+
+# default fitpsf parameters
+
+define DEF_MAXNPARS 10
+define DEF_PSFUNCTION AP_RADGAUSS
+define DEF_PMAXITER 50
+define DEF_PK2 3.0
+define DEF_PNREJECT 1
diff --git a/noao/digiphot/apphot/lib/fitsky.h b/noao/digiphot/apphot/lib/fitsky.h
new file mode 100644
index 00000000..b4cedaea
--- /dev/null
+++ b/noao/digiphot/apphot/lib/fitsky.h
@@ -0,0 +1,128 @@
+# FITSKY definitions
+
+# define the sky fitting algorithms
+
+define AP_CONSTANT 1 # Use a constant sky
+define AP_MODE 2 # Compute the mode of the sky pixels
+define AP_CENTROID 3 # Compute the peak of the histogram
+define AP_SKYFILE 4 # Get values from a file
+define AP_HISTPLOT 5 # Mark the sky on a histogram plot
+define AP_MEDIAN 6 # Take median of sky pixels
+define AP_RADPLOT 7 # Mark sky on radial profile plot
+define AP_GAUSS 8 # Non-linear fit to a Gaussian
+define AP_OFILT 9 # Optimal filtering
+define AP_CROSSCOR 10 # Cross correlation method
+define AP_MEAN 11 # Compute the mean of the sky pixels
+
+# define sky fitting errors (# 201 - 300)
+
+define AP_OK 0 # No error
+define AP_NOSKYAREA 201 # Width of the annulus is <= 0.0 pixels
+define AP_SKY_OUTOFBOUNDS 202 # Sky annulus out of bounds
+define AP_NOHISTOGRAM 203 # Cannot make a histogram
+define AP_FLAT_HIST 204 # Histogram is flat or concave
+define AP_NSKY_TOO_SMALL 205 # Too few points for fit
+define AP_SKY_SINGULAR 206 # Fit is singular
+define AP_SKY_NOCONVERGE 207 # Solution does not converge
+define AP_NOGRAPHICS 208 # NULL graphics pointer
+define AP_NOSKYFILE 209 # NULL sky file descriptor
+define AP_EOFSKYFILE 210 # End of sky file
+define AP_BADSKYSCAN 211 # Incomplete scan of sky file
+define AP_BADPARAMS 212 # Non-physical parameters
+
+# sky fitting parameters (# 201 - 300)
+
+define SKYFUNCTION 201
+define ANNULUS 202
+define DANNULUS 203
+define SKY_BACKGROUND 204
+define K1 205
+define BINSIZE 206
+define SMOOTH 207
+define SMAXITER 208
+define SLOCLIP 209
+define SHICLIP 210
+define SNREJECT 211
+define SLOREJECT 212
+define SHIREJECT 213
+define RGROW 214
+define SKY_MODE 215
+define SKY_SIGMA 216
+define SKY_SKEW 217
+define NSKY 218
+define NSKY_REJECT 219
+define SXCUR 220
+define SYCUR 221
+define OSXCUR 222
+define OSYCUR 223
+define SSTRING 224
+
+# define sky fitting keywords
+
+define KY_SSTRING "salgorithm"
+define KY_ANNULUS "annulus"
+define KY_DANNULUS "dannulus"
+define KY_SKY_BACKGROUND "skyvalue"
+define KY_K1 "khist"
+define KY_BINSIZE "binsize"
+define KY_SMOOTH "smooth"
+define KY_SMAXITER "smaxiter"
+define KY_SLOCLIP "sloclip"
+define KY_SHICLIP "shiclip"
+define KY_SNREJECT "snreject"
+define KY_SLOREJECT "sloreject"
+define KY_SHIREJECT "shireject"
+define KY_RGROW "rgrow"
+
+# define sky fitting units strings
+
+#define UN_SSTRING "algorithm"
+#define UN_ANNULUS "scaleunit"
+#define UN_DANNULUS "scaleunit"
+#define UN_SKY_BACKGROUND "counts"
+#define UN_K1 "sigma"
+#define UN_BINSIZE "sigma"
+#define UN_SMOOTH "switch"
+#define UN_SMAXITER "number"
+#define UN_SLOCLIP "percent"
+#define UN_SHICLIP "percent"
+#define UN_SNREJECT "number"
+#define UN_SLOREJECT "sigma"
+#define UN_SHIREJECT "sigma"
+#define UN_RGROW "scaleunit"
+
+define UN_SALGORITHM "algorithm"
+define UN_SSCALEUNIT "scaleunit"
+define UN_SSIGMA "sigma"
+define UN_SNUMBER "number"
+define UN_SPERCENT "percent"
+define UN_SCOUNTS "counts"
+define UN_SSWITCH "switch"
+
+# fitsky string definitions
+
+define SSHOWARGS "|data|sky|"
+define SFUNCS "|constant|mode|centroid|file|histplot|median|\
+radplot|gauss|ofilter|crosscor|mean|"
+define SCMDS "|annulus|dannulus|salgorithm|khist|sloreject|\
+shireject|smaxiter|binsize|smooth|rgrow|snreject|skyvalue|mksky|sloclip|\
+shiclip|"
+
+define SCMD_ANNULUS 1
+define SCMD_DANNULUS 2
+define SCMD_SALGORITHM 3
+define SCMD_KHIST 4
+define SCMD_SLOREJECT 5
+define SCMD_SHIREJECT 6
+define SCMD_SMAXITER 7
+define SCMD_BINSIZE 8
+define SCMD_SMOOTH 9
+define SCMD_RGROW 10
+define SCMD_SNREJECT 11
+define SCMD_SKYVALUE 12
+define SCMD_MKSKY 13
+define SCMD_SLOCLIP 14
+define SCMD_SHICLIP 15
+
+define SCMD_DATA 1
+define SCMD_SKY 2
diff --git a/noao/digiphot/apphot/lib/fitskydef.h b/noao/digiphot/apphot/lib/fitskydef.h
new file mode 100644
index 00000000..f768851f
--- /dev/null
+++ b/noao/digiphot/apphot/lib/fitskydef.h
@@ -0,0 +1,65 @@
+# FITSKY structure
+
+define LEN_SKYSTRUCT (36 + SZ_FNAME + 1)
+
+# sky fitting parameters
+
+define AP_SKYFUNCTION Memi[$1] # sky fitting algorithm
+define AP_ANNULUS Memr[P2R($1+1)] # inner radius of annulus in scale
+define AP_DANNULUS Memr[P2R($1+2)] # annulus width in scale
+define AP_SKYBACKGROUND Memr[P2R($1+3)] # user defined sky value
+define AP_K1 Memr[P2R($1+4)] # K-sigma histogram rejection
+define AP_BINSIZE Memr[P2R($1+5)] # histogram binsize in sky sigma
+define AP_SMOOTH Memi[$1+6] # Smooth histogram ?
+define AP_SMAXITER Memi[$1+7] # maximum number of iterations
+define AP_SLOCLIP Memr[P2R($1+8)] # lower clipping percentile
+define AP_SHICLIP Memr[P2R($1+9)] # lower clipping percentile
+define AP_SNREJECT Memi[$1+10] # maximum number of rejection cycles
+define AP_SLOREJECT Memr[P2R($1+11)] # lower K-sigma rejection for pixels
+define AP_SHIREJECT Memr[P2R($1+12)] # higher K-sigma rejection for pixels
+define AP_RGROW Memr[P2R($1+13)] # region growing radius in scale
+
+# sky buffer definitions
+
+define AP_SKYPIX Memi[$1+14] # pointer to sky pixels
+define AP_INDEX Memi[$1+15] # pointer to ordering array
+define AP_COORDS Memi[$1+16] # pointer to sky coordinates array
+define AP_SWGT Memi[$1+17] # pointer to sky weights
+define AP_NSKYPIX Memi[$1+18] # number of sky pixels
+define AP_NBADSKYPIX Memi[$1+19] # number of bad sky pixels
+define AP_LENSKYBUF Memi[$1+20] # length of sky buffers
+define AP_SXCUR Memr[P2R($1+21)] # x center of sky annulus
+define AP_SYCUR Memr[P2R($1+22)] # y center of sky annulus
+define AP_SXC Memr[P2R($1+23)] # x center of sky subraster
+define AP_SYC Memr[P2R($1+24)] # y center of sky subraster
+define AP_SNX Memi[$1+25] # x dimension of sky subraster
+define AP_SNY Memi[$1+26] # y dimension of sky subraster
+
+# fitsky output
+
+define AP_OSXCUR Memr[P2R($1+27)] # x center of sky annulus
+define AP_OSYCUR Memr[P2R($1+28)] # y center of sky annulus
+define AP_SKY_MODE Memr[P2R($1+29)] # computed sky value
+define AP_SKY_SIG Memr[P2R($1+30)] # computed sky sigma
+define AP_SKY_SKEW Memr[P2R($1+31)] # computed sky skew
+define AP_NSKY Memi[$1+32] # number of sky pix
+define AP_NSKY_REJECT Memi[$1+33] # number of rejected sky pix
+
+define AP_SSTRING Memc[P2C($1+34)] # salgorithm string
+
+# default setup values for sky fitting
+
+define DEF_SKYFUNCTION AP_MODE
+define DEF_SKYVALUE 0.0
+define DEF_ANNULUS 10.
+define DEF_DANNULUS 10.
+define DEF_SLOCLIP 0.0
+define DEF_SHICLIP 0.0
+define DEF_SNREJECT 50
+define DEF_SLOREJECT 3.0
+define DEF_SHIREJECT 3.0
+define DEF_SMAXITER 10
+define DEF_RGROW 0.0
+define DEF_K1 3.0
+define DEF_BINSIZE 0.10
+define DEF_SMOOTH NO
diff --git a/noao/digiphot/apphot/lib/noise.h b/noao/digiphot/apphot/lib/noise.h
new file mode 100644
index 00000000..32ef1ed1
--- /dev/null
+++ b/noao/digiphot/apphot/lib/noise.h
@@ -0,0 +1,54 @@
+# Noise model header file
+
+# noise parameters (# 601 - 700)
+
+define SKYSIGMA 601
+define EPADU 603
+define NOISEFUNCTION 604
+define GAIN 605
+define NSTRING 606
+define CCDREAD 607
+define READNOISE 608
+
+# noise keywords
+
+define KY_SKYSIGMA "sigma"
+define KY_EPADU "epadu"
+define KY_GAIN "gain"
+define KY_NSTRING "noise"
+define KY_CCDREAD "ccdread"
+define KY_READNOISE "readnoise"
+
+# noise parameter units
+
+#define UN_SKYSIGMA "counts"
+#define UN_EPADU "e-/adu"
+#define UN_GAIN "keyword"
+#define UN_NSTRING "model"
+#define UN_CCDREAD "keyword"
+#define UN_READNOISE "e-"
+
+define UN_NKEYWORD "keyword"
+define UN_NCOUNTS "counts"
+define UN_NELECTRONS "e-"
+define UN_NMODEL "model"
+define UN_NEPADU "e-/adu"
+
+# noise functions
+
+define AP_NCONSTANT 1
+define AP_NPOISSON 2
+
+# noise model strings
+
+define NCMDS "|noise|sigma|epadu|gain|ccdread|readnoise|"
+define NFUNCS "|constant|poisson|"
+
+# noise string cases
+
+define NCMD_NOISE 1
+define NCMD_SIGMA 2
+define NCMD_EPADU 3
+define NCMD_GAIN 4
+define NCMD_CCDREAD 5
+define NCMD_READNOISE 6
diff --git a/noao/digiphot/apphot/lib/noisedef.h b/noao/digiphot/apphot/lib/noisedef.h
new file mode 100644
index 00000000..3d67f5ec
--- /dev/null
+++ b/noao/digiphot/apphot/lib/noisedef.h
@@ -0,0 +1,21 @@
+# APPHOT header file
+
+define LEN_APNOISE (10 + 3 * SZ_FNAME + 3)
+
+# noise model parameters
+
+define AP_NOISEFUNCTION Memi[$1] # Noise function
+define AP_SKYSIGMA Memr[P2R($1+2)] # Sky sigma in counts
+define AP_EPADU Memr[P2R($1+3)] # Photons per adu
+define AP_READNOISE Memr[P2R($1+4)] # CCD readnoise in adu
+define AP_GAIN Memc[P2C($1+6)] # Gain keyword
+define AP_NSTRING Memc[P2C($1+6+SZ_FNAME+1)] # Noise model
+define AP_CCDREAD Memc[P2C($1+6+2*SZ_FNAME+2)] # Readnoise
+
+# noise model defaults
+
+define DEF_SKYSIGMA INDEFR
+define DEF_EPADU 1.0
+define DEF_CCDREAD ""
+define DEF_GAIN ""
+define DEF_READNOISE INDEFR
diff --git a/noao/digiphot/apphot/lib/phot.h b/noao/digiphot/apphot/lib/phot.h
new file mode 100644
index 00000000..ca9430f5
--- /dev/null
+++ b/noao/digiphot/apphot/lib/phot.h
@@ -0,0 +1,86 @@
+# APPHOT header file
+
+# phot errors (# 301 - 400)
+
+define AP_OK 0 # no error
+define AP_APERT_NOAPERT 301 # no aperture area
+define AP_APERT_OUTOFBOUNDS 302 # 1 or more apertures out of bounds
+define AP_APERT_NOSKYMODE 303 # INDEF valued sky
+define AP_APERT_NEGMAG 304 # 0 or -ve magnitude
+define AP_APERT_BADDATA 305 # bad pixels in aperture
+
+# phot parameters and answers (# 301 - 400)
+
+define ZMAG 301
+define APERTS 302
+define NAPERTS 303
+define MAGS 304
+define MAGERRS 305
+define PXCUR 306
+define PYCUR 307
+define OPXCUR 308
+define OPYCUR 309
+define AREAS 310
+define SUMS 311
+define PWEIGHTS 312
+define PWSTRING 313
+define APSTRING 314
+
+# define the phot keywords
+
+define KY_ZMAG "zmag"
+define KY_PWSTRING "weighting"
+define KY_APERTS "apertures"
+
+# define the phot units
+
+#define UN_ZMAG "zeropoint"
+#define UN_PWSTRING "model"
+#define UN_APERTS "scaleunit"
+
+define UN_PZMAG "zeropoint"
+define UN_PMODEL "model"
+define UN_PSCALEUNIT "scaleunit"
+
+# define the weighting functions
+
+define AP_PWCONSTANT 1 # uniform weighting
+define AP_PWCONE 2 # a cone of given fwhm is used
+define AP_PWGAUSS 3 # a Gaussian of given fwhm is used
+
+# phot strings
+
+define PCMDS "|apertures|zmag|mkapert|weighting|"
+define PSHOWARGS "|center|sky|phot|data|"
+define PWFUNCS "|constant|cone|gauss|"
+define QCMDS "|show|cboxwidth|annulus|dannulus|apertures|zmag|epadu|exposure|radplots|image|output|coords|airmass|filter|obstime|"
+
+define PCMD_APERTURES 1
+define PCMD_ZMAG 2
+define PCMD_MKAPERT 3
+define PCMD_WEIGHTING 4
+
+define PCMD_CENTER 1
+define PCMD_SKY 2
+define PCMD_PHOT 3
+define PCMD_DATA 4
+
+define QCMD_SHOW 1
+define QCMD_CBOXWIDTH 2
+define QCMD_ANNULUS 3
+define QCMD_DANNULUS 4
+define QCMD_APERTURES 5
+define QCMD_ZMAG 6
+define QCMD_EPADU 7
+define QCMD_EXPOSURE 8
+define QCMD_RADPLOTS 9
+define QCMD_IMAGE 10
+define QCMD_OUTPUT 11
+define QCMD_COORDS 12
+define QCMD_AIRMASS 13
+define QCMD_FILTER 14
+define QCMD_OBSTIME 15
+
+# miscellaneous
+
+define MAX_NAPERTS 100
diff --git a/noao/digiphot/apphot/lib/photdef.h b/noao/digiphot/apphot/lib/photdef.h
new file mode 100644
index 00000000..3d02f11a
--- /dev/null
+++ b/noao/digiphot/apphot/lib/photdef.h
@@ -0,0 +1,43 @@
+# PHOT header file
+
+define LEN_PHOTSTRUCT (30 + SZ_FNAME + SZ_LINE + 2)
+
+# photmetry aperture parameters
+
+define AP_NAPERTS Memi[$1] # Number of apertures
+define AP_PXCUR Memr[P2R($1+1)] # X aperture center
+define AP_PYCUR Memr[P2R($1+2)] # Y aperture center
+define AP_NMAXAP Memi[$1+3] # Maximum number of apertures
+define AP_NMINAP Memi[$1+4] # Minimum number of apertures
+define AP_APERTS Memi[$1+5] # Pointer to aperture array
+define AP_APIX Memi[$1+6] # Pointer to pixels
+define AP_XAPIX Memi[$1+7] # Pointer to x coords array (not used)
+define AP_YAPIX Memi[$1+8] # Pointer to y coords array (not used)
+define AP_NAPIX Memi[$1+9] # Number of pixels (not used)
+define AP_LENABUF Memi[$1+10] # Size of pixels buffer (not used)
+define AP_AXC Memr[P2R($1+11)] # X center of subraster
+define AP_AYC Memr[P2R($1+12)] # X center of subraster
+define AP_ANX Memi[$1+13] # X dimension of subraster
+define AP_ANY Memi[$1+14] # Y dimension of subraster
+define AP_OPXCUR Memr[P2R($1+15)] # X aperture center
+define AP_OPYCUR Memr[P2R($1+16)] # Y aperture center
+
+# photometry output
+
+define AP_MAGS Memi[$1+17] # Pointer to magnitude array
+define AP_MAGERRS Memi[$1+18] # Pointer to mag errors array
+define AP_AREA Memi[$1+19] # Pointer to areas array
+define AP_SUMS Memi[$1+20] # Pointer to aperture sums array
+
+# photometry parameters
+
+define AP_ZMAG Memr[P2R($1+21)] # Zero point of magnitude scale
+define AP_PWEIGHTS Memi[$1+22] # Weighting function for ophot
+define AP_PWSTRING Memc[P2C($1+24)] # Weights string
+define AP_APSTRING Memc[P2C($1+24+SZ_FNAME+1)] # Apertures string
+
+# phot default defintions
+
+define DEF_ZMAG 25.0
+define DEF_APERTS "3.0"
+define DEF_PWEIGHTS AP_PWCONSTANT
diff --git a/noao/digiphot/apphot/lib/polyphot.h b/noao/digiphot/apphot/lib/polyphot.h
new file mode 100644
index 00000000..d41751c2
--- /dev/null
+++ b/noao/digiphot/apphot/lib/polyphot.h
@@ -0,0 +1,63 @@
+# POLYPHOT header file
+
+# polyphot error codes (# 801 - 900)
+
+define PY_NOPOLYGON 801
+define PY_OUTOFBOUNDS 802
+define PY_NOPIX 803
+define PY_NOSKYMODE 804
+define PY_BADDATA 805
+define PY_OK 0
+
+# polyphot parameters and answers (# 801 - 900)
+
+define PYXMEAN 801
+define PYYMEAN 802
+define PYCX 803
+define PYCY 804
+define OPYXMEAN 805
+define OPYYMEAN 806
+define OPYCX 807
+define OPYCY 808
+define PYFLUX 809
+define PYNPIX 810
+define PYNVER 811
+define PYMINRAD 812
+define PYX 813
+define PYY 814
+define PYZMAG 815
+define PYMAG 816
+define PYMAGERR 817
+define PYNAME 818
+define PYROOT 819
+define PYBADPIX 820
+
+# polyphot keywords
+
+define KY_PYZMAG "zmag"
+define KY_PYNAME "polyfile"
+
+# polyphot units
+
+define UN_PYZMAG "zeropoint"
+
+# miscellaneous polyphot definitions
+
+define MAX_NVERTICES 900
+define NEXT_POLYGON 0
+define NEXT_OBJECT 1
+define THIS_OBJECT 2
+
+# polyphot strings
+
+define PYSHOWARGS "|center|sky|phot|data|"
+define PYCMDS "|zmag|mkpolygon|polygons|"
+
+define PLCMD_CENTER 1
+define PLCMD_SKY 2
+define PLCMD_PHOT 3
+define PLCMD_DATA 4
+
+define PLCMD_ZMAG 1
+define PLCMD_MKPOLYGON 2
+define PLCMD_POLYGONS 3
diff --git a/noao/digiphot/apphot/lib/polyphotdef.h b/noao/digiphot/apphot/lib/polyphotdef.h
new file mode 100644
index 00000000..4b354bfc
--- /dev/null
+++ b/noao/digiphot/apphot/lib/polyphotdef.h
@@ -0,0 +1,37 @@
+# POLYPHOT header file
+
+define LEN_PYSTRUCT (25 + 2 * SZ_FNAME + 2)
+
+# polyphot parameters
+
+define AP_PYZMAG Memr[P2R($1)] # Zero point of mag scale
+
+# polygon parameters
+
+define AP_PYXMEAN Memr[P2R($1+1)] # Original mean X of polygon
+define AP_PYYMEAN Memr[P2R($1+2)] # Original mean Y of polygon
+define AP_PYCX Memr[P2R($1+3)] # Current mean X of polygon
+define AP_PYCY Memr[P2R($1+4)] # Current mean Y of polygon
+define AP_PYX Memr[P2R($1+5)] # Previous mean X of polygon
+define AP_PYY Memr[P2R($1+6)] # Previous mean Y of polygon
+define AP_PYNVER Memi[$1+7] # Number of vertices
+define AP_PYMINRAD Memr[P2R($1+8)] # Minimum sky fitting radius in scale
+define AP_OPYXMEAN Memr[P2R($1+9)] # Original output mean X of polygon
+define AP_OPYYMEAN Memr[P2R($1+10)]# Original output mean Y of polygon
+define AP_OPYCX Memr[P2R($1+11)]# Current output mean X of polygon
+define AP_OPYCY Memr[P2R($1+12)]# Current output mean Y of polygon
+
+# polyphot answers
+
+define AP_PYBADPIX Memi[$1+13] # Are there bad pixels ?
+define AP_PYFLUX Memd[P2D($1+14)]# Flux
+define AP_PYNPIX Memd[P2D($1+16)]# Polygon area
+define AP_PYMAG Memr[P2R($1+18)]# Magnitude
+define AP_PYMAGERR Memr[P2R($1+19)]# Magnitude error
+
+define AP_PYNAME Memc[P2C($1+21)]# Polygons file name
+define AP_PYROOT Memc[P2C($1+21+SZ_FNAME+1)]# Polygons file name
+
+# polyphot defaults
+
+define DEF_PYZMAG 25.0
diff --git a/noao/digiphot/apphot/lib/radprof.h b/noao/digiphot/apphot/lib/radprof.h
new file mode 100644
index 00000000..56572c50
--- /dev/null
+++ b/noao/digiphot/apphot/lib/radprof.h
@@ -0,0 +1,66 @@
+# RADPROF header file
+
+# radprof error codes (# 901 - 1000)
+
+define AP_OK 0
+define AP_RP_NOPROFILE 901
+define AP_RP_OUTOFBOUNDS 902
+define AP_RP_NPTS_TOO_SMALL 903
+define AP_RP_SINGULAR 904
+define AP_RP_NOSKYMODE 905
+
+# radprof fit parameters and answers (# 901 - 1000)
+
+define RPXCUR 901
+define RPYCUR 902
+define ORPXCUR 903
+define ORPYCUR 904
+define RPRADIUS 905
+define RPSTEP 906
+define RPKSIGMA 907
+define RPNREJECT 908
+define RPORDER 909
+define INORM 910
+define TNORM 911
+define DNORM 912
+define RPFWHM 913
+define RPNPTS 914
+define RPNDATA 915
+define RPNDATAREJ 916
+
+# define radprof keywords
+
+define KY_RPRADIUS "radius"
+define KY_RPSTEP "stepsize"
+define KY_RPORDER "order"
+define KY_RPKSIGMA "kreject"
+define KY_RPNREJECT "nreject"
+
+# define radprof units
+
+#define UN_RPRADIUS "scaleunit"
+#define UN_RPSTEP "scaleunit"
+#define UN_RPORDER "number"
+#define UN_RPKSIGMA "sigma"
+#define UN_RPNREJECT "number"
+
+define UN_RSCALEUNIT "scaleunit"
+define UN_RNUMBER "number"
+define UN_RSIGMA "sigma"
+
+# radprof strings
+
+define RPSHOWARGS "|center|sky|phot|fit|data|"
+define RPCMDS "|radius|stepsize|order|kreject|nreject|"
+
+define RCMD_CENTER 1
+define RCMD_SKY 2
+define RCMD_PHOT 3
+define RCMD_FIT 4
+define RCMD_DATA 5
+
+define RCMD_RADIUS 1
+define RCMD_STEPSIZE 2
+define RCMD_ORDER 3
+define RCMD_KREJECT 4
+define RCMD_NREJECT 5
diff --git a/noao/digiphot/apphot/lib/radprofdef.h b/noao/digiphot/apphot/lib/radprofdef.h
new file mode 100644
index 00000000..1fcb3dcc
--- /dev/null
+++ b/noao/digiphot/apphot/lib/radprofdef.h
@@ -0,0 +1,38 @@
+# RADPROF header file
+
+define LEN_RPSTRUCT 30
+
+# Radprof data parameters
+
+define AP_RPXCUR Memr[P2R($1)] # X image center in pixels
+define AP_RPYCUR Memr[P2R($1+1)] # Y image center in pixels
+define AP_RPIX Memi[$1+2] # Pointer to radial profile pixels
+define AP_RPXC Memr[P2R($1+3)] # X center of subraster
+define AP_RPYC Memr[P2R($1+4)] # Y center of subraster
+define AP_RPNX Memi[$1+5] # Subraster length in x
+define AP_RPNY Memi[$1+6] # Subraster length in y
+define AP_ORPXCUR Memr[P2R($1+7)] # output system X image center in pixels
+define AP_ORPYCUR Memr[P2R($1+8)] # output system Y image center in pixels
+
+# Radprof fit parameters
+
+define AP_RPRADIUS Memr[P2R($1+9)] # Radprof radius in scale
+define AP_RPSTEP Memr[P2R($1+10)]# Radprof step size in scale
+define AP_RPORDER Memi[$1+11] # Order of the spline3 fit
+define AP_RPKSIGMA Memr[P2R($1+12)]# Radprof K-rejection criterion in sigma
+define AP_RPNREJECT Memi[$1+13] # Maximum number of rejection cycles
+
+# Radprof answers
+
+define AP_RPNPTS Memi[$1+14] # Number of points in radial profile
+define AP_RPDIST Memi[$1+15] # Pointer to radial distance array
+define AP_INTENSITY Memi[$1+16] # Pointer to fitted intensity array
+define AP_DINTENSITY Memi[$1+17] # Pointer incremental intensity array
+define AP_TINTENSITY Memi[$1+18] # Pointer to total intensity array
+define AP_INORM Memr[P2R($1+19)]# Normalization for intensity profile
+define AP_TINORM Memr[P2R($1+20)]# Normalization for total intensity
+define AP_DNORM Memr[P2R($1+21)]# Normalization for incremental inten
+define AP_RPFWHM Memr[P2R($1+22)]# Fitted profile FWHM
+define AP_RPNDATA Memi[$1+23] # Number of data points
+define AP_RPNDATAREJ Memi[$1+24] # Number of points rejected from fit
+define AP_RPNBAD Memi[$1+25] # Number of bad pixel points
diff --git a/noao/digiphot/apphot/mkpkg b/noao/digiphot/apphot/mkpkg
new file mode 100644
index 00000000..861aeea4
--- /dev/null
+++ b/noao/digiphot/apphot/mkpkg
@@ -0,0 +1,39 @@
+# Make the APPHOT package
+
+$call relink
+$exit
+
+update:
+ $call relink
+ $call install
+ ;
+
+relink:
+ $set LIBS = "-lnlfit -liminterp -lcurfit -lds -lxtools"
+ $update libpkg.a
+ $omake x_apphot.x
+ $link x_apphot.o libpkg.a $(LIBS) -o xx_apphot.e
+ ;
+
+linkonly:
+ $set LIBS = "-lnlfit -liminterp -lcurfit -lds -lxtools"
+ $link x_apphot.o libpkg.a $(LIBS) -o xx_apphot.e
+ $call install
+ ;
+
+install:
+ $move xx_apphot.e noaobin$x_apphot.e
+ ;
+
+libpkg.a:
+ @aplib
+ @aputil
+ @center
+ @daofind
+ @fitpsf
+ @fitsky
+ @phot
+ @polyphot
+ @radprof
+ @wphot
+ ;
diff --git a/noao/digiphot/apphot/pexamine.par b/noao/digiphot/apphot/pexamine.par
new file mode 100644
index 00000000..809e2943
--- /dev/null
+++ b/noao/digiphot/apphot/pexamine.par
@@ -0,0 +1,20 @@
+# The PEXAMINE task parameter set
+
+input,s,a,,,,"Name of the input catalog"
+output,s,a,"",,,"Name of the edited output catalog"
+image,s,a,"",,,Name of the image corresponding to the input catalog
+deletions,s,h,"",,,"Name of the output catalog for deleted entries"
+photcolumns,s,h,"apphot",,,"Names of the standard photometry columns"
+xcolumn,s,h,mag,,,"Catalog column which is the X axis of X-Y plot"
+ycolumn,s,h,merr,,,"Catalog column which is the Y axis of X-Y plot"
+hcolumn,s,h,mag,,,"Catalog column which is to be binned"
+xposcolumn,s,h,"xcenter",,,"Name of the x coordinate column"
+yposcolumn,s,h,"ycenter",,,"Name of the y coordinate column"
+usercolumns,s,h,"",,,"Names of additional user selected columns"
+first_star,i,h,1,1,,First star in the catalog to load
+max_nstars,i,h,5000,1,,Maximum number of stars to load
+match_radius,r,h,2.0,,,Matching radius for positional coincidence on display
+graphics,s,h,"stdgraph",,,The graphics device
+use_display,b,h,yes,,,Use the image display ?
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor: [x y wcs] key [cmd]"
diff --git a/noao/digiphot/apphot/phot.par b/noao/digiphot/apphot/phot.par
new file mode 100644
index 00000000..87570ac2
--- /dev/null
+++ b/noao/digiphot/apphot/phot.par
@@ -0,0 +1,24 @@
+# PHOT parameters
+
+image,f,a,,,,"The input image(s)"
+skyfile,f,a,"",,,"The input sky file(s)"
+coords,f,h,"",,,"The input coordinate files(s) (default: image.coo.?)"
+output,f,h,"default",,,"The output photometry file(s) (default: image.mag.?)"
+plotfile,f,h,"",,,"The output plots metacode file"
+datapars,pset,h,"",,,"Data dependent parameters"
+centerpars,pset,h,"",,,"Centering parameters"
+fitskypars,pset,h,"",,,"Sky fitting parameters"
+photpars,pset,h,"",,,"Photometry parameters"
+interactive,b,h,yes,,,"Interactive mode ?"
+radplots,b,h,no,,,"Plot the radial profiles in interactive mode ?"
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor: [x y wcs] key [cmd]"
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the input image pixels in memory ?"
+verify,b,h,)_.verify,,,"Verify critical parameters in non-interactive mode ?"
+update,b,h,)_.update,,,"Update critical parameters in non-interactive mode ?"
+verbose,b,h,)_.verbose,,,"Print messages in non-interactive mode ?"
+graphics,s,h,)_.graphics,,,"Graphics device"
+display,s,h,)_.display,,,"Display device"
+mode,s,h,'ql'
diff --git a/noao/digiphot/apphot/phot/apbphot.x b/noao/digiphot/apphot/phot/apbphot.x
new file mode 100644
index 00000000..ea6ee325
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apbphot.x
@@ -0,0 +1,115 @@
+include <fset.h>
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+
+# APBPHOT -- Procedure to compute the magnitudes for a list of objects
+# interactively.
+
+procedure apbphot (ap, im, cl, sd, out, id, ld, gd, mgd, gid, interactive)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to IRAF image
+int cl # starlist file descriptor
+int sd # sky file descriptor
+int out # output file descriptor
+int id, ld # sequence and list numbers
+pointer gd # pointer to stdgraph stream
+pointer mgd # pointer to plot metacode file
+pointer gid # pointer to image display stream
+int interactive # interactive pr batch mode
+
+int stdin, ild, radius, cier, sier, pier
+pointer sp, str
+real wx, wy
+int fscan(), nscan(), apfitsky(), apfitcenter(), apmag(), strncmp()
+int apstati()
+real apstatr()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+ call fstats (cl, F_FILENAME, Memc[str], SZ_FNAME)
+
+ # Initialize
+ ild = ld
+ radius = 4 * (apstatr (ap, ANNULUS) + apstatr (ap, DANNULUS) + 1.0) *
+ apstatr (ap, SCALE)
+ call ap_imbuf (ap, radius, YES)
+
+ # Print query.
+ if (strncmp ("STDIN", Memc[str], 5) == 0) {
+ stdin = YES
+ call printf ("Type object x and y coordinates (^D or ^Z to end): ")
+ call flush (STDOUT)
+ } else
+ stdin = NO
+
+ # Loop over the coordinate file.
+ while (fscan (cl) != EOF) {
+
+ # Get and store the coordinates.
+ call gargr (wx)
+ call gargr (wy)
+ if (nscan () != 2) {
+ if (stdin == YES) {
+ call printf (
+ "Type object x and y coordinates (^D or ^Z to end): ")
+ call flush (STDOUT)
+ }
+ next
+ }
+
+
+ # Transform the input coordinates.
+ switch (apstati(ap,WCSIN)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_itol (ap, wx, wy, wx, wy, 1)
+ case WCS_TV:
+ call ap_vtol (im, wx, wy, wx, wy, 1)
+ default:
+ ;
+ }
+ call apsetr (ap, CWX, wx)
+ call apsetr (ap, CWY, wy)
+
+ # Center the coordinates, fit the sky and compute magnitudes.
+ cier = apfitcenter (ap, im, wx, wy)
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), sd, gd)
+ pier = apmag (ap, im, apstatr (ap, XCENTER), apstatr (ap, YCENTER),
+ apstati (ap, POSITIVE), apstatr (ap, SKY_MODE),
+ apstatr (ap, SKY_SIGMA), apstati (ap, NSKY))
+
+ # Print the results if interactive mode.
+ if (interactive == YES) {
+ call ap_qpmag (ap, cier, sier, pier)
+ if (gid != NULL)
+ call apmark (ap, gid, apstati (ap, MKCENTER), apstati (ap,
+ MKSKY), apstati (ap, MKAPERT))
+ }
+
+ # Write the results.
+ if (id == 1)
+ call ap_param (ap, out, "phot")
+ call ap_pmag (ap, out, id, ild, cier, sier, pier)
+
+ # Make plots if mgd is enabled.
+ call ap_pplot (ap, im, id, mgd, YES)
+
+ # Prepare for the next object.
+ id = id + 1
+ ild = ild + 1
+ call apsetr (ap, WX, wx)
+ call apsetr (ap, WY, wy)
+ if (stdin == YES) {
+ call printf (
+ "Type object x and y coordinates (^Z or ^D to end): ")
+ call flush (STDOUT)
+ }
+ }
+
+ call ap_imbuf (ap, 0, YES)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/phot/apcomags.x b/noao/digiphot/apphot/phot/apcomags.x
new file mode 100644
index 00000000..c6d15a16
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apcomags.x
@@ -0,0 +1,118 @@
+include <mach.h>
+include "../lib/noise.h"
+
+# APCOPMAGS -- Procedure to compute the magnitudes from the aperture sums,
+# areas and sky values.
+
+procedure apcopmags (sums, areas, mags, magerrs, naperts, sky, sigma, nsky,
+ zmag, noise, padu)
+
+double sums[ARB] # aperture sums
+double areas[ARB] # aperture areas
+real mags[ARB] # output magnitudes
+real magerrs[ARB] # errors in the magnitudes
+int naperts # number of apertures
+real sky # sky value
+real sigma # sigma of the sky values
+int nsky # number of sky pixels
+real zmag # sky value, sigma and zero point magnitudes
+int noise # noise model
+real padu # photons per adu
+
+int i
+real err1, err2, err3, err
+
+begin
+ # Compute the magnitudes and errors
+ do i = 1, naperts {
+ mags[i] = sums[i] - areas[i] * sky
+ if (mags[i] <= 0.0)
+ mags[i] = INDEFR
+ else {
+ if (IS_INDEFR(sigma))
+ err1 = 0.0
+ else
+ err1 = areas[i] * sigma ** 2
+ switch (noise) {
+ case AP_NCONSTANT:
+ err2 = 0.0
+ case AP_NPOISSON:
+ err2 = mags[i] / padu
+ default:
+ err2 = 0.0
+ }
+ if (nsky <= 0)
+ err3 = 0.0
+ else if (IS_INDEFR(sigma))
+ err3 = 0.0
+ else
+ err3 = sigma ** 2 * areas[i] ** 2 / nsky
+ err = err1 + err2 + err3
+ if (err <= 0.0)
+ magerrs[i] = 0.0
+ else {
+ magerrs[i] = 1.0857 * sqrt (err) / mags[i]
+ }
+ mags[i] = zmag - 2.5 * log10 (mags[i])
+ }
+ }
+end
+
+
+# APCONMAGS -- Procedure to compute the magnitudes from the aperture sums,
+# areas and sky values.
+
+procedure apconmags (sums, areas, mags, magerrs, naperts, sky, sigma, nsky,
+ zmag, noise, padu, readnoise)
+
+double sums[ARB] # aperture sums
+double areas[ARB] # aperture areas
+real mags[ARB] # output magnitudes
+real magerrs[ARB] # errors in the magnitudes
+int naperts # number of apertures
+real sky # sky value
+real readnoise # readout noise in electrons
+real sigma # sigma of the sky values
+int nsky # number of sky pixels
+real zmag # sky value, sigma and zero point magnitudes
+int noise # noise model
+real padu # photons per adu
+
+int i
+real err1, err2, err3, err
+
+begin
+ # Compute the magnitudes and errors
+ do i = 1, naperts {
+ mags[i] = areas[i] * sky - sums[i]
+ if (mags[i] <= 0.0)
+ mags[i] = INDEFR
+ else {
+ if (IS_INDEFR(readnoise))
+ err1 = 0.0
+ else
+ err1 = areas[i] * (readnoise / padu) ** 2
+ switch (noise) {
+ case AP_NCONSTANT:
+ err2 = 0.0
+ case AP_NPOISSON:
+ err2 = abs (sums[i]) / padu
+ default:
+ err2 = 0.0
+ }
+ if (nsky <= 0)
+ err3 = 0.0
+ else if (IS_INDEFR(sigma))
+ err3 = 0.0
+ else
+ err3 = sigma ** 2 * areas[i] ** 2 / nsky
+ err = err1 + err2 + err3
+ if (err <= 0.0)
+ magerrs[i] = 0.0
+ else {
+ magerrs[i] = 1.0857 * sqrt (err) / abs (sums[i])
+ }
+ mags[i] = zmag - 2.5 * log10 (mags[i])
+ }
+ }
+end
diff --git a/noao/digiphot/apphot/phot/apgppars.x b/noao/digiphot/apphot/phot/apgppars.x
new file mode 100644
index 00000000..09961678
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apgppars.x
@@ -0,0 +1,35 @@
+include "../lib/display.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+
+# AP_GPPARS -- Procedure to fetch the phot task parameters.
+
+procedure ap_gppars (ap)
+
+pointer ap # pointer to apphot structure
+
+bool clgetb()
+int btoi()
+
+begin
+ # Open the apphot strucuture.
+ call appinit (ap, AP_CENTROID1D, 2.5, AP_MODE, 10.0, 10.0, 3.0, 1,
+ AP_PWCONSTANT, 2.0, AP_NPOISSON)
+
+ # Get the data dependent parameters.
+ call ap_gdapars (ap)
+
+ # Get the centering algorithm parameters.
+ call ap_gcepars (ap)
+
+ # Get the sky fitting parameters.
+ call ap_gsapars (ap)
+
+ # Get the photometry parameters.
+ call ap_gphpars (ap)
+
+ # Get the plotting parameters.
+ call apseti (ap, RADPLOTS, btoi (clgetb ("radplots")))
+end
diff --git a/noao/digiphot/apphot/phot/apgqppars.x b/noao/digiphot/apphot/phot/apgqppars.x
new file mode 100644
index 00000000..dea31951
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apgqppars.x
@@ -0,0 +1,75 @@
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+
+# AP_GQPPARS -- Procedure to fetch the phot task parameters.
+
+procedure ap_gqppars (ap)
+
+pointer ap # pointer to apphot structure
+
+int naperts
+pointer mp, aperts, str, apstr
+real cbox, annulus, dannulus
+bool clgetb()
+int ap_getaperts(), btoi()
+real clgetr()
+
+begin
+ call smark (mp)
+ call salloc (aperts, MAX_NAPERTS, TY_REAL)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (apstr, SZ_LINE, TY_CHAR)
+
+ # Get the center, sky fitting and photometry apertures.
+ cbox = clgetr ("cbox") / 2.0
+ annulus = clgetr ("annulus")
+ dannulus = clgetr ("dannulus")
+ call clgstr ("apertures", Memc[apstr], SZ_LINE)
+ naperts = ap_getaperts (Memc[apstr], Memr[aperts], MAX_NAPERTS)
+
+ # Open the apphot structure.
+ if (naperts <= 0.0)
+ call appinit (ap, AP_CENTROID1D, cbox, AP_CENTROID, annulus,
+ dannulus, 0.0, 1, AP_PWCONSTANT, 2.5, AP_NPOISSON)
+ else
+ call appinit (ap, AP_CENTROID1D, cbox, AP_CENTROID, annulus,
+ dannulus, Memr[aperts], naperts, AP_PWCONSTANT, 2.5,
+ AP_NPOISSON)
+
+ # Set remaining parameters.
+ call apseti (ap, SMOOTH, YES)
+
+ if (naperts > 0)
+ call apsets (ap, APSTRING, Memc[apstr])
+ call apsetr (ap, ZMAG, clgetr ("zmag"))
+
+ call clgstr ("exposure", Memc[str], SZ_FNAME)
+ call apsets (ap, EXPOSURE, Memc[str])
+
+ call clgstr ("airmass", Memc[str], SZ_FNAME)
+ call apsets (ap, AIRMASS, Memc[str])
+ call apsetr (ap, XAIRMASS, INDEFR)
+
+ call clgstr ("filter", Memc[str], SZ_FNAME)
+ call apsets (ap, FILTER, Memc[str])
+ call apsets (ap, FILTERID, "INDEF")
+
+ call clgstr ("obstime", Memc[str], SZ_FNAME)
+ call apsets (ap, OBSTIME, Memc[str])
+ call apsets (ap, OTIME, "INDEF")
+
+ call apsetr (ap, EPADU, clgetr ("epadu"))
+
+ # Print the display parameters.
+ call apseti (ap, MKCENTER, btoi (true))
+ call apseti (ap, MKSKY, btoi (true))
+ call apseti (ap, MKAPERT, btoi (true))
+ call apseti (ap, RADPLOTS, btoi (clgetb ("radplots")))
+
+ # Close the pset files.
+ call sfree (mp)
+end
diff --git a/noao/digiphot/apphot/phot/apmag.x b/noao/digiphot/apphot/phot/apmag.x
new file mode 100644
index 00000000..e1490be2
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apmag.x
@@ -0,0 +1,118 @@
+include <mach.h>
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/noisedef.h"
+include "../lib/photdef.h"
+include "../lib/phot.h"
+
+# APMAG -- Procedure to compute the magnitudes inside a set of apertures for
+# a single of object.
+
+int procedure apmag (ap, im, wx, wy, positive, skyval, skysig, nsky)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the IRAF image
+real wx, wy # object coordinates
+int positive # emission or absorption features
+real skyval # sky value
+real skysig # sky sigma
+int nsky # number of sky pixels
+
+int c1, c2, l1, l2, ier, nap
+pointer sp, nse, phot, temp
+real datamin, datamax, zmag
+int apmagbuf()
+
+begin
+ # Initalize.
+ phot = AP_PPHOT(ap)
+ nse = AP_NOISE(ap)
+ AP_PXCUR(phot) = wx
+ AP_PYCUR(phot) = wy
+ if (IS_INDEFR(wx) || IS_INDEFR(wy)) {
+ AP_OPXCUR(phot) = INDEFR
+ AP_OPYCUR(phot) = INDEFR
+ } else {
+ switch (AP_WCSOUT(ap)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (ap, wx, wy, AP_OPXCUR(phot), AP_OPYCUR(phot), 1)
+ case WCS_TV:
+ call ap_ltov (im, wx, wy, AP_OPXCUR(phot), AP_OPYCUR(phot), 1)
+ default:
+ AP_OPXCUR(phot) = wx
+ AP_OPYCUR(phot) = wy
+ }
+ }
+
+ call amovkd (0.0d0, Memd[AP_SUMS(phot)], AP_NAPERTS(phot))
+ call amovkd (0.0d0, Memd[AP_AREA(phot)], AP_NAPERTS(phot))
+ call amovkr (INDEFR, Memr[AP_MAGS(phot)], AP_NAPERTS(phot))
+ call amovkr (INDEFR, Memr[AP_MAGERRS(phot)], AP_NAPERTS(phot))
+
+ # Make sure the center is defined.
+ if (IS_INDEFR(wx) || IS_INDEFR(wy))
+ return (AP_APERT_NOAPERT)
+
+ # Fetch the aperture pixels.
+ ier = apmagbuf (ap, im, wx, wy, c1, c2, l1, l2)
+ if (ier == AP_APERT_NOAPERT)
+ return (AP_APERT_NOAPERT)
+
+ call smark (sp)
+ call salloc (temp, AP_NAPERTS(phot), TY_REAL)
+
+ # Do photometry for all the apertures.
+ call amulkr (Memr[AP_APERTS(phot)], AP_SCALE(ap), Memr[temp],
+ AP_NAPERTS(phot)]
+ if (IS_INDEFR(AP_DATAMIN(ap)) && IS_INDEFR(AP_DATAMAX(ap))) {
+ call apmeasure (im, wx, wy, c1, c2, l1, l2, Memr[temp],
+ Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)], AP_NMAXAP(phot))
+ AP_NMINAP(phot) = AP_NMAXAP(phot) + 1
+ } else {
+ if (IS_INDEFR(AP_DATAMIN(ap)))
+ datamin = -MAX_REAL
+ else
+ datamin = AP_DATAMIN(ap)
+ if (IS_INDEFR(AP_DATAMAX(ap)))
+ datamax = MAX_REAL
+ else
+ datamax = AP_DATAMAX(ap)
+ call apbmeasure (im, wx, wy, c1, c2, l1, l2, datamin, datamax,
+ Memr[temp], Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)],
+ AP_NMAXAP(phot), AP_NMINAP(phot))
+ }
+
+ # Make sure that the sky value has been defined.
+ if (IS_INDEFR(skyval))
+ ier = AP_APERT_NOSKYMODE
+ else {
+
+ # Check for bad pixels.
+ if ((ier == AP_OK) && (AP_NMINAP(phot) <= AP_NMAXAP(phot)))
+ ier = AP_APERT_BADDATA
+
+ nap = min (AP_NMINAP(phot) - 1, AP_NMAXAP(phot))
+
+ # Compute the magnitudes and errors.
+ if (positive == YES)
+ call apcopmags (Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)],
+ Memr[AP_MAGS(phot)], Memr[AP_MAGERRS(phot)],
+ nap, skyval, skysig, nsky, AP_ZMAG(phot),
+ AP_NOISEFUNCTION(nse), AP_EPADU(nse))
+ else
+ call apconmags (Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)],
+ Memr[AP_MAGS(phot)], Memr[AP_MAGERRS(phot)],
+ nap, skyval, skysig, nsky, AP_ZMAG(phot),
+ AP_NOISEFUNCTION(nse), AP_EPADU(nse), AP_READNOISE(nse))
+
+ # Compute correction for itime.
+ zmag = 2.5 * log10 (AP_ITIME(ap))
+ call aaddkr (Memr[AP_MAGS(phot)], zmag, Memr[AP_MAGS(phot)], nap)
+ }
+
+ call sfree (sp)
+ if (ier != AP_OK)
+ return (ier)
+ else
+ return (AP_OK)
+end
diff --git a/noao/digiphot/apphot/phot/apmagbuf.x b/noao/digiphot/apphot/phot/apmagbuf.x
new file mode 100644
index 00000000..15034561
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apmagbuf.x
@@ -0,0 +1,89 @@
+include <imhdr.h>
+include "../lib/apphotdef.h"
+include "../lib/photdef.h"
+include "../lib/phot.h"
+
+# APMAGBUF -- Procedure to determine the mapping of the aperture list
+# into the input image.
+
+int procedure apmagbuf (ap, im, wx, wy, c1, c2, l1, l2)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to the IRAF image
+real wx, wy # center coordinates
+int c1, c2 # column limits
+int l1, l2 # line limits
+
+int i
+pointer phot
+real rbuf
+int ap_photpix()
+
+begin
+ # Check for 0 radius aperture.
+ phot = AP_PPHOT(ap)
+ if (Memr[AP_APERTS(phot)] <= 0.0)
+ return (AP_APERT_NOAPERT)
+
+ # Compute the maximum aperture size
+ AP_APIX(phot) = NULL
+ for (i = AP_NAPERTS(phot); AP_APIX(phot) == NULL && i >= 1; i = i - 1) {
+ rbuf = 2. * Memr[AP_APERTS(phot)+i-1] * AP_SCALE(ap)
+ AP_APIX(phot) = ap_photpix (im, wx, wy, rbuf, c1, c2, l1, l2)
+ AP_AXC(phot) = wx - c1 + 1
+ AP_AYC(phot) = wy - l1 + 1
+ AP_ANX(phot) = c2 - c1 + 1
+ AP_ANY(phot) = l2 - l1 + 1
+ AP_NMAXAP(phot) = i
+ }
+
+ # Return the appropriate error code.
+ if (AP_APIX(phot) == NULL) {
+ return (AP_APERT_NOAPERT)
+ } else if (AP_NMAXAP(phot) < AP_NAPERTS(phot)) {
+ return (AP_APERT_OUTOFBOUNDS)
+ } else {
+ return (AP_OK)
+ }
+end
+
+
+# AP_PHOTPIX -- Procedure to determine the line and column limits of the
+# required subraster.
+
+int procedure ap_photpix (im, wx, wy, papert, c1, c2, l1, l2)
+
+pointer im # pointer to IRAF image
+real wx, wy # center of centering subraster annulus
+real papert # centering radius
+int c1, c2 # column limits
+int l1, l2 # line limits
+
+int ncols, nlines
+real half_papert, xc1, xc2, xl1, xl2
+
+begin
+ # Check for 0 radius aperture.
+ half_papert = papert / 2.
+ if (half_papert <= 0)
+ return (0)
+ ncols = IM_LEN(im,1)
+ nlines = IM_LEN(im,2)
+
+ # Test for an out of bounds aperture.
+ xc1 = wx - half_papert
+ xc2 = wx + half_papert
+ xl1 = wy - half_papert
+ xl2 = wy + half_papert
+ if ((xc1 < 0.5) || (xc2 > (real (ncols) + 0.5)) ||
+ (xl1 < 0.5) || (xl2 > (real (nlines) + 0.5)))
+ return (0)
+
+ # Get the column and line limits, dimensions and center of the subraster
+ # to be extracted.
+ c1 = max (1.0, min (real (ncols), xc1))
+ c2 = min (real (ncols), max (1.0, xc2 + 0.5))
+ l1 = max (1.0, min (real (nlines), xl1))
+ l2 = min (real (nlines), max (1.0, xl2 + 0.5))
+ return ((c2 - c1 + 1) * (l2 - l1 + 1))
+end
diff --git a/noao/digiphot/apphot/phot/apmeasure.x b/noao/digiphot/apphot/phot/apmeasure.x
new file mode 100644
index 00000000..6d64db5e
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apmeasure.x
@@ -0,0 +1,116 @@
+# APMEASURE -- Procedure to measure the fluxes and effective areas of a set of
+# apertures.
+
+procedure apmeasure (im, wx, wy, c1, c2, l1, l2, aperts, sums, areas, naperts)
+
+pointer im # pointer to image
+real wx, wy # center of subraster
+int c1, c2 # column limits
+int l1, l2 # line limits
+real aperts[ARB] # array of apertures
+double sums[ARB] # array of sums
+double areas[ARB] # aperture areas
+int naperts # number of apertures
+
+int i, j, k, nx, yindex
+double fctn
+pointer buf
+real xc, yc, apmaxsq, dy2, r2, r
+pointer imgs2r()
+
+begin
+ # Initialize.
+ nx = c2 - c1 + 1
+ xc = wx - c1 + 1
+ yc = wy - l1 + 1
+ apmaxsq = (aperts[naperts] + 0.5) ** 2
+ call aclrd (sums, naperts)
+ call aclrd (areas, naperts)
+
+ # Loop over the pixels.
+ do j = l1, l2 {
+ buf = imgs2r (im, c1, c2, j, j)
+ if (buf == NULL)
+ return
+ yindex = j - l1 + 1
+ dy2 = (yindex - yc) ** 2
+ do i = 1, nx {
+ r2 = (i - xc) ** 2 + dy2
+ if (r2 > apmaxsq)
+ next
+ r = sqrt (r2) - 0.5
+ do k = 1, naperts {
+ if (r > aperts[k])
+ next
+ fctn = max (0.0, min (1.0, aperts[k] - r))
+ sums[k] = sums[k] + fctn * Memr[buf+i-1]
+ areas[k] = areas[k] + fctn
+ }
+ }
+ }
+end
+
+
+# APBMEASURE -- Procedure to measure the fluxes and effective areas of a set of
+# apertures.
+
+procedure apbmeasure (im, wx, wy, c1, c2, l1, l2, datamin, datamax, aperts,
+ sums, areas, naperts, minapert)
+
+pointer im # pointer to image
+real wx, wy # center of subraster
+int c1, c2 # column limits
+int l1, l2 # line limits
+real datamin # minimum good data value
+real datamax # maximum good data value
+real aperts[ARB] # array of apertures
+double sums[ARB] # array of sums
+double areas[ARB] # aperture areas
+int naperts # number of apertures
+int minapert # minimum apertures
+
+int i, j, k, nx, yindex, kindex
+double fctn
+pointer buf
+real xc, yc, apmaxsq, dy2, r2, r, pixval
+pointer imgs2r()
+
+begin
+ # Initialize.
+ nx = c2 - c1 + 1
+ xc = wx - c1 + 1
+ yc = wy - l1 + 1
+ apmaxsq = (aperts[naperts] + 0.5) ** 2
+ call aclrd (sums, naperts)
+ call aclrd (areas, naperts)
+ minapert = naperts + 1
+
+ # Loop over the pixels.
+ do j = l1, l2 {
+ buf = imgs2r (im, c1, c2, j, j)
+ if (buf == NULL)
+ return
+ yindex = j - l1 + 1
+ dy2 = (yindex - yc) ** 2
+ do i = 1, nx {
+ r2 = (i - xc) ** 2 + dy2
+ if (r2 > apmaxsq)
+ next
+ r = sqrt (r2) - 0.5
+ pixval = Memr[buf+i-1]
+ kindex = naperts + 1
+ do k = 1, naperts {
+ if (r > aperts[k])
+ next
+ kindex = min (k, kindex)
+ fctn = max (0.0, min (1.0, aperts[k] - r))
+ sums[k] = sums[k] + fctn * pixval
+ areas[k] = areas[k] + fctn
+ }
+ if (kindex < minapert) {
+ if (pixval < datamin || pixval > datamax)
+ minapert = kindex
+ }
+ }
+ }
+end
diff --git a/noao/digiphot/apphot/phot/appconfirm.x b/noao/digiphot/apphot/phot/appconfirm.x
new file mode 100644
index 00000000..53d24034
--- /dev/null
+++ b/noao/digiphot/apphot/phot/appconfirm.x
@@ -0,0 +1,98 @@
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+
+# AP_PCONFIRM -- Procedure to confirm the critical phot parameters.
+
+procedure ap_pconfirm (ap, out, stid)
+
+pointer ap # pointer to the apphot structure
+int out # output file descriptor
+int stid # output file sequence number
+
+pointer sp, cstr, sstr, aperts
+real fwhmpsf, capert, annulus, dannulus, skysigma
+real datamin, datamax
+int apstati()
+real apstatr(), ap_vcapert(), ap_vannulus(), ap_vdannulus(), ap_vsigma()
+real ap_vfwhmpsf(), ap_vdatamin(), ap_vdatamax
+
+begin
+ call smark (sp)
+ call salloc (cstr, SZ_FNAME, TY_CHAR)
+ call salloc (sstr, SZ_FNAME, TY_CHAR)
+ call salloc (aperts, SZ_LINE, TY_CHAR)
+
+ call printf ("\n")
+
+ # Confirm the centering algorithm.
+ call ap_vcstring (ap, Memc[cstr], SZ_FNAME)
+
+ if (apstati (ap, CENTERFUNCTION) != AP_NONE) {
+
+ # Confirm the fwhmpsf.
+ if (apstati (ap, CENTERFUNCTION) != AP_CENTROID1D)
+ fwhmpsf = ap_vfwhmpsf (ap)
+ else
+ fwhmpsf = apstatr (ap, FWHMPSF)
+
+ # Confirm the centering box.
+ capert = 2.0 * ap_vcapert (ap)
+
+ } else {
+
+ fwhmpsf = apstatr (ap, FWHMPSF)
+ capert = 2.0 * apstatr (ap, CAPERT)
+ }
+
+ # Confirm the sky fitting algorithm.
+ call ap_vsstring (ap, Memc[sstr], SZ_FNAME)
+
+ # Confirm the sky annulus.
+ if (apstati (ap, SKYFUNCTION) != AP_CONSTANT &&
+ apstati (ap, SKYFUNCTION) != AP_SKYFILE) {
+ annulus = ap_vannulus (ap)
+ dannulus = ap_vdannulus (ap)
+ } else {
+ annulus = apstatr (ap, ANNULUS)
+ dannulus = apstatr (ap, DANNULUS)
+ }
+
+ # Confirm the aperture radii parameter.
+ call ap_vaperts (ap, Memc[aperts], SZ_LINE)
+
+ # Confirm the datamin and datamax parameters.
+ skysigma = ap_vsigma (ap)
+ datamin = ap_vdatamin (ap)
+ datamax = ap_vdatamax (ap)
+
+ call printf ("\n")
+
+ # Update the database file.
+ if (out != NULL && stid > 1) {
+ call ap_sparam (out, KY_CSTRING, Memc[cstr], UN_CALGORITHM,
+ "centering aperture")
+ call ap_rparam (out, KY_FWHMPSF, fwhmpsf, UN_ASCALEUNIT,
+ "full width half maximum of the psf")
+ call ap_rparam (out, KY_CAPERT, capert, UN_CSCALEUNIT,
+ "centering box width")
+ call ap_sparam (out, KY_SSTRING, Memc[sstr], UN_SALGORITHM,
+ "sky fitting algorithm")
+ call ap_rparam (out, KY_ANNULUS, annulus, UN_SSCALEUNIT,
+ "inner radius of the sky annulus")
+ call ap_rparam (out, KY_DANNULUS, dannulus, UN_SSCALEUNIT,
+ "width of the sky annulus")
+ call ap_rparam (out, KY_SKYSIGMA, skysigma, UN_NCOUNTS,
+ "standard deviation of 1 sky pixel")
+ call ap_sparam (out, KY_APERTS, Memc[aperts], UN_PSCALEUNIT,
+ "list of apertures")
+ call ap_rparam (out, KY_DATAMIN, datamin, UN_ACOUNTS,
+ "minimum good data value")
+ call ap_rparam (out, KY_DATAMAX, datamax, UN_ACOUNTS,
+ "maximum good data value")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/phot/apperrors.x b/noao/digiphot/apphot/phot/apperrors.x
new file mode 100644
index 00000000..ff67e3ee
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apperrors.x
@@ -0,0 +1,48 @@
+include "../lib/phot.h"
+
+# AP_PERRORS -- Print the photometry task errors.
+
+procedure ap_perrors (ap, cier, sier, pier)
+
+pointer ap # apphot structure
+int cier # centering error code
+int sier # sky fitting error code
+int pier # photometry error code
+
+begin
+ # Print the centering error message.
+ call ap_cerrors (ap, cier)
+
+ # Print the sky fitting error message.
+ call ap_serrors (ap, sier)
+
+ # Print the photometry error message.
+ call ap_merrors (ap, pier)
+
+end
+
+
+# AP_MERRORS -- Print the photometry errors.
+
+procedure ap_merrors (ap, pier)
+
+pointer ap # pointer to the apphot structure (unused)
+int pier # photometry error
+
+begin
+ # Print the photometry error message.
+ switch (pier) {
+ case AP_APERT_NOAPERT:
+ call printf ("Photometry apertures are outside of the image.\n")
+ case AP_APERT_OUTOFBOUNDS:
+ call printf ("Photometry apertures are partially outside the image.\n")
+ case AP_APERT_NOSKYMODE:
+ call printf ("The sky value is undefined.\n")
+ case AP_APERT_NEGMAG:
+ call printf ("The total flux inside the aperture is negative.\n")
+ case AP_APERT_BADDATA:
+ call printf ("Bad data in the aperture(s).\n")
+ default:
+ call printf ("")
+ }
+end
diff --git a/noao/digiphot/apphot/phot/appfree.x b/noao/digiphot/apphot/phot/appfree.x
new file mode 100644
index 00000000..6d588f8a
--- /dev/null
+++ b/noao/digiphot/apphot/phot/appfree.x
@@ -0,0 +1,66 @@
+include "../lib/apphotdef.h"
+include "../lib/photdef.h"
+
+# APFREE -- Free the apphot structure.
+
+procedure appfree (ap)
+
+pointer ap # pointer to the apphot structure
+
+begin
+ if (ap == NULL)
+ return
+ if (AP_NOISE(ap) != NULL)
+ call ap_noisecls (ap)
+ if (AP_PCENTER(ap) != NULL)
+ call ap_ctrcls (ap)
+ if (AP_PDISPLAY(ap) != NULL)
+ call ap_dispcls (ap)
+ if (AP_POLY(ap) != NULL)
+ call ap_ycls (ap)
+ if (AP_PPHOT(ap) != NULL)
+ call ap_photcls (ap)
+ if (AP_PPSF(ap) != NULL)
+ call ap_psfcls (ap)
+ if (AP_PSKY(ap) != NULL)
+ call ap_skycls (ap)
+ if (AP_IMBUF(ap) != NULL)
+ call mfree (AP_IMBUF(ap), TY_REAL)
+ if (AP_MW(ap) != NULL)
+ call mw_close (AP_MW(ap))
+ call mfree (ap, TY_STRUCT)
+end
+
+
+# AP_PHOTCLS -- Procedure to close up the photometry structure and arrays.
+
+procedure ap_photcls (ap)
+
+pointer ap # pointer to apphot structure
+
+pointer phot
+
+begin
+ if (AP_PPHOT(ap) == NULL)
+ return
+ phot = AP_PPHOT(ap)
+ if (AP_APERTS(phot) != NULL)
+ call mfree (AP_APERTS(phot), TY_REAL)
+ if (AP_MAGS(phot) != NULL)
+ call mfree (AP_MAGS(phot), TY_REAL)
+ if (AP_MAGERRS(phot) != NULL)
+ call mfree (AP_MAGERRS(phot), TY_REAL)
+ if (AP_SUMS(phot) != NULL)
+ call mfree (AP_SUMS(phot), TY_DOUBLE)
+ if (AP_AREA(phot) != NULL)
+ call mfree (AP_AREA(phot), TY_DOUBLE)
+
+ #if (AP_APIX(phot) != NULL)
+ #call mfree (AP_APIX(phot), TY_REAL)
+ #if (AP_XAPIX(phot) != NULL)
+ #call mfree (AP_XAPIX(phot), TY_REAL)
+ #if (AP_YAPIX(phot) != NULL)
+ #call mfree (AP_YAPIX(phot), TY_REAL)
+
+ call mfree (AP_PPHOT(ap), TY_STRUCT)
+end
diff --git a/noao/digiphot/apphot/phot/apphot.x b/noao/digiphot/apphot/phot/apphot.x
new file mode 100644
index 00000000..1f8b942d
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apphot.x
@@ -0,0 +1,511 @@
+include <ctype.h>
+include <gset.h>
+include <imhdr.h>
+include "../lib/phot.h"
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+
+define HELPFILE "apphot$phot/phot.key"
+
+# APPHOT -- Procedure to compute magnitudes for a list of objects
+
+int procedure apphot (ap, im, cl, sd, gd, mgd, id, out, stid, interactive,
+ cache)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to IRAF image
+int cl # starlist file descriptor
+int sd # the sky file descriptor
+pointer gd # pointer to graphcis descriptor
+pointer mgd # pointer to the metacode file
+pointer id # pointer to image display stream
+int out # output file descriptor
+int stid # output file sequence number
+int interactive # interactive mode
+int cache # cache the input image pixels
+
+real wx, wy, xlist, ylist
+pointer sp, cmd
+int newimage, newskybuf, newsky, newcenterbuf, newcenter, newmagbuf, newmag
+int colonkey, prev_num, req_num, ip, cier, sier, pier, oid, req_size
+int old_size, buf_size, memstat, wcs, key, ltid, newlist
+
+real apstatr()
+int clgcur(), apfitsky(), aprefitsky(), apfitcenter(), aprefitcenter()
+int apmag(), apremag(), apgscur(), ctoi(), apstati(), apgqverify()
+int apgtverify(), apnew(), ap_avsky(), ap_memstat(), sizeof()
+bool fp_equalr()
+
+define endswitch_ 99
+
+begin
+ # Initialize.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Initialize cursor command.
+ key = ' '
+ Memc[cmd] = EOS
+
+ # Initialize the fitting parameters.
+ newimage = NO
+ newcenterbuf = YES
+ newcenter = YES
+ newskybuf = YES
+ newsky = YES
+ newmagbuf = YES
+ newmag = YES
+ cier = AP_OK
+ sier = AP_OK
+ pier = AP_OK
+
+ # Intialize the sequencing.
+ newlist = NO
+ ltid = 0
+
+ # Loop over the coordinate file.
+ while (clgcur ("icommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+
+ # Store the current cursor coordinates.
+ call ap_vtol (im, wx, wy, wx, wy, 1)
+ call apsetr (ap, CWX, wx)
+ call apsetr (ap, CWY, wy)
+
+ # Test to see if the cursor moved.
+ if (apnew (ap, wx, wy, xlist, ylist, newlist) == YES) {
+ newcenterbuf = YES
+ newcenter = YES
+ newskybuf = YES
+ newsky = YES
+ newmagbuf = YES
+ newmag = YES
+ }
+
+ # Store previous cursor coordinates.
+ call apsetr (ap, WX, apstatr (ap, CWX))
+ call apsetr (ap, WY, apstatr (ap, CWY))
+
+ # Loop over the colon keystroke commands.
+ switch (key) {
+
+ # Quit.
+ case 'q':
+ if (interactive == YES) {
+ if (apgqverify ("phot", ap, key) == YES) {
+ call sfree (sp)
+ return (apgtverify (key))
+ }
+ } else {
+ call sfree (sp)
+ return (NO)
+ }
+
+ # Print out error messages.
+ case 'e':
+ if (interactive == YES)
+ call ap_perrors (ap, cier, sier, pier)
+
+ # Print out the help page(s).
+ case '?':
+ if ((id != NULL) && (id == gd))
+ call gpagefile (id, HELPFILE, "")
+ else if (interactive == YES)
+ call pagefile (HELPFILE, "[space=morehelp,q=quit,?=help]")
+
+ # Plot a centered stellar radial profile.
+ case 'd':
+ if (interactive == YES) {
+ call ap_qrad (ap, im, wx, wy, gd)
+ newmagbuf = YES; newmag = YES
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ }
+
+ # Rewind the list.
+ case 'r':
+ if (cl != NULL) {
+ call seek (cl, BOFL)
+ ltid = 0
+ } else if (interactive == YES)
+ call printf ("No coordinate list\n")
+
+ # Get, measure the next object in the coordinate list.
+ case 'm', 'n':
+
+ # No coordinate file.
+ if (cl == NULL) {
+ if (interactive == YES)
+ call printf ("No coordinate list\n")
+ goto endswitch_
+
+ }
+
+ # Need to rewind coordinate file.
+ prev_num = ltid
+ req_num = ltid + 1
+ if (apgscur (cl, id, xlist, ylist, prev_num, req_num,
+ ltid) == EOF) {
+ if (interactive == YES)
+ call printf (
+ "End of coordinate list, use r key to rewind\n")
+ goto endswitch_
+
+ }
+
+ # Convert coordinates if necessary.
+ switch (apstati (ap, WCSIN)) {
+ case WCS_PHYSICAL, WCS_WORLD:
+ call ap_itol (ap, xlist, ylist, xlist, ylist, 1)
+ case WCS_TV:
+ call ap_vtol (im, xlist, ylist, xlist, ylist, 1)
+ default:
+ ;
+ }
+
+ # Move to next object.
+ newlist = YES
+ if (key == 'm') {
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ goto endswitch_
+ }
+
+ # Measure next object.
+ cier = apfitcenter (ap, im, xlist, ylist)
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), sd, gd)
+ pier = apmag (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), apstati (ap, POSITIVE), apstatr (ap, SKY_MODE),
+ apstatr (ap, SKY_SIGMA), apstati (ap, NSKY))
+ if (id != NULL) {
+ call apmark (ap, id, apstati (ap, MKCENTER), apstati (ap,
+ MKSKY), apstati (ap, MKAPERT))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_pplot (ap, im, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qpmag (ap, cier, sier, pier)
+ if (stid == 1)
+ call ap_param (ap, out, "phot")
+ call ap_pmag (ap, out, stid, ltid, cier, sier, pier)
+ call ap_pplot (ap, im, stid, mgd, YES)
+ stid = stid + 1
+ newcenterbuf = NO; newcenter = NO
+ newskybuf = NO; newsky = NO
+ newmagbuf = NO; newmag = NO
+
+ # Process the remainder of the list.
+ case 'l':
+ if (cl != NULL) {
+ ltid = ltid + 1
+ oid = stid
+ call apbphot (ap, im, cl, sd, out, stid, ltid, gd, mgd, id,
+ YES)
+ ltid = ltid + stid - oid + 1
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ } else if (interactive == YES)
+ call printf ("No coordinate list\n")
+
+ # Process apphot colon commands.
+ case ':':
+ for (ip = 1; IS_WHITE(Memc[cmd+ip-1]); ip = ip + 1)
+ ;
+ colonkey = Memc[cmd+ip-1]
+ switch (colonkey) {
+ case 'm', 'n':
+
+ # Show/set a phot parameter.
+ if (Memc[cmd+ip] != EOS && Memc[cmd+ip] != ' ') {
+ call apphotcolon (ap, im, cl, out, stid, ltid,
+ Memc[cmd], newimage, newcenterbuf, newcenter,
+ newskybuf, newsky, newmagbuf, newmag)
+ goto endswitch_
+ }
+
+ # No coordinate list.
+ if (cl == NULL) {
+ if (interactive == YES)
+ call printf ("No coordinate list\n")
+ goto endswitch_
+ }
+
+ # Get next object from the list.
+ ip = ip + 1
+ prev_num = ltid
+ if (ctoi (Memc[cmd], ip, req_num) <= 0)
+ req_num = ltid + 1
+
+ # Fetch the next object from the list.
+ if (apgscur (cl, id, xlist, ylist, prev_num, req_num,
+ ltid) == EOF) {
+ if (interactive == YES)
+ call printf (
+ "End of coordinate list, use r key to rewind\n")
+ goto endswitch_
+ }
+
+ # Convert the coordinates.
+ switch (apstati (ap, WCSIN)) {
+ case WCS_PHYSICAL, WCS_WORLD:
+ call ap_itol (ap, xlist, ylist, xlist, ylist, 1)
+ case WCS_TV:
+ call ap_vtol (im, xlist, ylist, xlist, ylist, 1)
+ default:
+ ;
+ }
+
+ # Move to the next object.
+ newlist = YES
+ if (colonkey == 'm') {
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ goto endswitch_
+ }
+ cier = apfitcenter (ap, im, xlist, ylist)
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER),
+ apstatr (ap, YCENTER), sd, gd)
+ pier = apmag (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), apstati (ap, POSITIVE), apstatr (ap,
+ SKY_MODE), apstatr (ap, SKY_SIGMA), apstati (ap, NSKY))
+ if (id != NULL) {
+ call apmark (ap, id, apstati (ap, MKCENTER),
+ apstati (ap, MKSKY), apstati (ap, MKAPERT))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_pplot (ap, im, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qpmag (ap, cier, sier, pier)
+ if (stid == 1)
+ call ap_param (ap, out, "phot")
+ call ap_pmag (ap, out, stid, ltid, cier, sier, pier)
+ call ap_pplot (ap, im, stid, mgd, YES)
+ stid = stid + 1
+ newcenterbuf = NO; newcenter = NO
+ newskybuf = NO; newsky = NO
+ newmagbuf = NO; newmag = NO
+
+ # Show/set a phot parameter.
+ default:
+ call apphotcolon (ap, im, cl, out, stid, ltid, Memc[cmd],
+ newimage, newcenterbuf, newcenter, newskybuf, newsky,
+ newmagbuf, newmag)
+ }
+
+ # Reestablish the image display viewport if necessary.
+ if (newimage == YES) {
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[cmd], im, 4)
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+ }
+
+ newimage = NO
+
+ # Save the current parameters in the pset files.
+ case 'w':
+ call ap_ppars (ap)
+
+ # Setup phot parameters interactively.
+ case 'i':
+ if (interactive == YES) {
+ call ap_radsetup (ap, im, wx, wy, gd, out, stid)
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ }
+
+ # Verify the critical PHOT parameters.
+ case 'v':
+ call ap_pconfirm (ap, out, stid)
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+
+ # Fit the center around the cursor position.
+ case 'c':
+ if (newcenterbuf == YES)
+ cier = apfitcenter (ap, im, wx, wy)
+ else if (newcenter == YES)
+ cier = aprefitcenter (ap, im, cier)
+ if (id != NULL) {
+ call apmark (ap, id, apstati (ap, MKCENTER), NO, NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_cplot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qcenter (ap, cier)
+ newcenterbuf = NO; newcenter = NO
+
+ # Fit the sky around the cursor position.
+ case 't':
+ if (newskybuf == YES || ! fp_equalr (wx,
+ apstatr (ap, SXCUR)) || ! fp_equalr (wy, apstatr (ap,
+ SYCUR)))
+ sier = apfitsky (ap, im, wx, wy, sd, gd)
+ else if (newsky == YES)
+ sier = aprefitsky (ap, im, gd)
+ if (id != NULL) {
+ call apmark (ap, id, NO, apstati (ap, MKSKY), NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_splot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qspsky (ap, sier)
+ newskybuf = NO; newsky = NO
+
+ # Compute the average of several sky measurements around
+ # different cursor postions.
+ case 'a':
+ sier = ap_avsky (ap, im, stid, sd, id, gd, interactive)
+ if (interactive == YES)
+ call ap_qaspsky (ap, sier)
+ newskybuf = NO; newsky = NO
+
+ # Fit the sky around the current center position.
+ case 's':
+ if (newskybuf == YES || ! fp_equalr (apstatr (ap, XCENTER),
+ apstatr (ap, SXCUR)) || ! fp_equalr (apstatr (ap, SYCUR),
+ apstatr (ap, YCENTER)))
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER),
+ apstatr (ap, YCENTER), sd, gd)
+ else if (newsky == YES)
+ sier = aprefitsky (ap, im, gd)
+ if (id != NULL) {
+ call apmark (ap, id, NO, apstati (ap, MKSKY), NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_splot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qspsky (ap, sier)
+ newskybuf = NO; newsky = NO
+
+ # Compute magnitudes around the current star using the current
+ # sky.
+ case 'p', 'o':
+ if (newcenterbuf == YES)
+ cier = apfitcenter (ap, im, wx, wy)
+ else if (newcenter == YES)
+ cier = aprefitcenter (ap, im, cier)
+ if (newmagbuf == YES || ! fp_equalr (apstatr (ap, XCENTER),
+ apstatr (ap, PXCUR)) || ! fp_equalr (apstatr (ap,
+ PYCUR), apstatr (ap, YCENTER)))
+ pier = apmag (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), apstati (ap, POSITIVE), apstatr (ap,
+ SKY_MODE), apstatr (ap, SKY_SIGMA), apstati (ap, NSKY))
+ else
+ pier = apremag (ap, im, apstati (ap, POSITIVE), apstatr (ap,
+ SKY_MODE), apstatr (ap, SKY_SIGMA), apstati (ap, NSKY))
+ if (id != NULL) {
+ call apmark (ap, id, NO, NO, apstati (ap, MKAPERT))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ if (interactive == YES)
+ call ap_qpmag (ap, cier, sier, pier)
+ newcenterbuf = NO; newcenter = NO
+ newmagbuf = NO; newmag = NO
+
+ if (key == 'o') {
+ if (stid == 1)
+ call ap_param (ap, out, "phot")
+ if (newlist == YES)
+ call ap_pmag (ap, out, stid, ltid, cier, sier, pier)
+ else
+ call ap_pmag (ap, out, stid, 0, cier, sier, pier)
+ call ap_pplot (ap, im, stid, mgd, YES)
+ stid = stid + 1
+ }
+
+ # Compute the center, sky, and magnitudes and save the results.
+ case 'f', ' ':
+ if (newcenterbuf == YES)
+ cier = apfitcenter (ap, im, wx, wy)
+ else if (newcenter == YES)
+ cier = aprefitcenter (ap, im, cier)
+ if (newskybuf == YES || ! fp_equalr (apstatr (ap, XCENTER),
+ apstatr (ap, SXCUR)) || ! fp_equalr (apstatr (ap, YCENTER),
+ apstatr (ap, SYCUR)))
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), sd, gd)
+ else if (newsky == YES)
+ sier = aprefitsky (ap, im, gd)
+ if (newmagbuf == YES || ! fp_equalr (apstatr (ap, XCENTER),
+ apstatr (ap, PXCUR)) || ! fp_equalr (apstatr (ap, YCENTER),
+ apstatr (ap, PYCUR)))
+ pier = apmag (ap, im, apstatr (ap, XCENTER),
+ apstatr (ap, YCENTER), apstati (ap, POSITIVE),
+ apstatr (ap, SKY_MODE), apstatr (ap, SKY_SIGMA),
+ apstati (ap, NSKY))
+ else
+ pier = apremag (ap, im, apstati (ap, POSITIVE), apstatr (ap,
+ SKY_MODE), apstatr (ap, SKY_SIGMA), apstati (ap, NSKY))
+
+ if (id != NULL) {
+ call apmark (ap, id, apstati (ap, MKCENTER), apstati (ap,
+ MKSKY), apstati (ap, MKAPERT))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_pplot (ap, im, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qpmag (ap, cier, sier, pier)
+
+ newcenterbuf = NO; newcenter = NO
+ newskybuf = NO; newsky = NO
+ newmagbuf = NO; newmag = NO
+
+ if (key == ' ') {
+ if (stid == 1)
+ call ap_param (ap, out, "phot")
+ if (newlist == YES)
+ call ap_pmag (ap, out, stid, ltid, cier, sier, pier)
+ else
+ call ap_pmag (ap, out, stid, 0, cier, sier, pier)
+ call ap_pplot (ap, im, stid, mgd, YES)
+ stid = stid + 1
+ }
+
+ default:
+ call printf ("Unknown or ambiguous keystroke command\n")
+ }
+
+endswitch_
+ # Setup for the next object.
+ key = ' '
+ Memc[cmd] = EOS
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/phot/apphotcolon.x b/noao/digiphot/apphot/phot/apphotcolon.x
new file mode 100644
index 00000000..825459b2
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apphotcolon.x
@@ -0,0 +1,209 @@
+include <gset.h>
+include "../lib/apphot.h"
+include "../lib/fitsky.h"
+include "../lib/center.h"
+include "../lib/phot.h"
+include "../lib/display.h"
+include "../lib/noise.h"
+
+# APPHOTCOLON -- Process phot colon commands.
+
+procedure apphotcolon (ap, im, cl, out, stid, ltid, cmdstr, newimage,
+ newcenterbuf, newcenter, newskybuf, newsky, newmagbuf, newmag)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the iraf image
+int cl # coord file descriptor
+int out # output file descriptor
+int stid # output file sequence number
+int ltid # coord list sequence number
+char cmdstr[ARB] # command string
+int newimage # new image ?
+int newcenterbuf, newcenter # new center buffer ? new center fit ?
+int newskybuf, newsky # new sky buffer ? new sky fit ?
+int newmagbuf, newmag # new aperture buffer ? new fit ?
+
+pointer sp, incmd, outcmd
+int strdic()
+
+begin
+ call smark (sp)
+ call salloc (incmd, SZ_LINE, TY_CHAR)
+ call salloc (outcmd, SZ_LINE, TY_CHAR)
+
+ # Get the command.
+ call sscan (cmdstr)
+ call gargwrd (Memc[incmd], SZ_LINE)
+ if (Memc[incmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, CCMDS) != 0)
+ call apccolon (ap, out, stid, cmdstr, newcenterbuf, newcenter)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, SCMDS) != 0)
+ call apscolon (ap, out, stid, cmdstr, newskybuf, newsky)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, PCMDS) != 0)
+ call apmagcolon (ap, out, stid, cmdstr, newmagbuf, newmag)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, APCMDS) != 0)
+ call ap_apcolon (ap, im, cl, out, stid, ltid, cmdstr, newimage,
+ newcenterbuf, newcenter, newskybuf, newsky, newmagbuf, newmag)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, NCMDS) != 0)
+ call apnscolon (ap, im, out, stid, cmdstr, newcenterbuf,
+ newcenter, newskybuf, newsky, newmagbuf, newmag)
+ else
+ call ap_himcolon (ap, cmdstr)
+
+ call sfree (sp)
+end
+
+
+# APMAGCOLON -- Procedure to display and edit the photometry parameters.
+
+procedure apmagcolon (ap, out, stid, cmdstr, newmagbuf, newmag)
+
+pointer ap # pointer to apphot structure
+int out # output file descriptor
+int stid # output number
+char cmdstr[ARB] # command string
+int newmagbuf # new aperture buffers
+int newmag # compute new magnitudes
+
+bool bval
+int ncmd
+pointer sp, cmd
+real rval
+bool itob()
+int btoi(), strdic(), nscan(), apstati()
+real apstatr()
+
+begin
+ # Get the command.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, PCMDS)
+ switch (ncmd) {
+ case PCMD_APERTURES:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, APERTS, Memc[cmd], SZ_LINE)
+ call printf ("%s = %s %s\n")
+ call pargstr (KY_APERTS)
+ call pargstr (Memc[cmd])
+ call pargstr (UN_PSCALEUNIT)
+ } else {
+ call apsets (ap, APERTS, Memc[cmd])
+ if (stid > 1)
+ call ap_sparam (out, KY_APERTS, Memc[cmd], UN_PSCALEUNIT,
+ "list of aperture radii")
+ newmag = YES
+ newmagbuf = YES
+ }
+ case PCMD_ZMAG:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (KY_ZMAG)
+ call pargr (apstatr (ap, ZMAG))
+ } else {
+ call apsetr (ap, ZMAG, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_ZMAG, rval, UN_PZMAG,
+ "zero point of magnitude scale")
+ newmag = YES
+ }
+ case PCMD_MKAPERT:
+ call gargb (bval)
+ if (nscan () == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (KY_MKAPERT)
+ call pargb (itob (apstati (ap, MKAPERT)))
+ } else {
+ call apseti (ap, MKAPERT, btoi (bval))
+ }
+ default:
+ call printf ("Unknown command\7\n")
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_HIMCOLON -- Procedure to process commands which alter the centering, sky
+# fitting and photometry buffers.
+
+procedure ap_himcolon (ap, cmdstr)
+
+pointer ap # pointer to the apphot structure
+char cmdstr[ARB] # command string
+
+bool bval
+int ncmd
+pointer sp, cmd
+bool itob()
+int strdic(), nscan(), btoi(), apstati()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Get the command.
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, MISC)
+ switch (ncmd) {
+ case ACMD_SHOW:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, PSHOWARGS)
+ switch (ncmd) {
+ case PCMD_CENTER:
+ call printf ("\n")
+ call ap_cpshow (ap)
+ call printf ("\n")
+ case PCMD_SKY:
+ call printf ("\n")
+ call ap_spshow (ap)
+ call printf ("\n")
+ case PCMD_PHOT:
+ call printf ("\n")
+ call ap_mpshow (ap)
+ call printf ("\n")
+ case PCMD_DATA:
+ call printf ("\n")
+ call ap_nshow (ap)
+ call printf ("\n")
+ default:
+ call printf ("\n")
+ call ap_pshow (ap)
+ call printf ("\n")
+ }
+ case ACMD_RADPLOTS:
+ call gargb (bval)
+ if (nscan () == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (KY_RADPLOTS)
+ call pargb (itob (apstati (ap, RADPLOTS)))
+ } else
+ call apseti (ap, RADPLOTS, btoi (bval))
+ default:
+ call printf ("Unknown or ambigous colon command\7\n")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/phot/appinit.x b/noao/digiphot/apphot/phot/appinit.x
new file mode 100644
index 00000000..b9f558c2
--- /dev/null
+++ b/noao/digiphot/apphot/phot/appinit.x
@@ -0,0 +1,100 @@
+include "../lib/apphotdef.h"
+include "../lib/photdef.h"
+include "../lib/phot.h"
+
+# APPINIT - Procedure to initialize apphot structure.
+
+procedure appinit (ap, cfunction, cbox, sfunction, annulus, dannulus,
+ aperts, napert, weight, fwhmpsf, noise)
+
+pointer ap # pointer to the apphot structure
+int cfunction # centering algorithm
+real cbox # half width of the centering box
+int sfunction # sky fitting algorithm
+real annulus # radius of sky annulus
+real dannulus # width of sky annulus
+real aperts[ARB] # apertures
+int napert # number of apertures
+int weight # weight for photometry
+real fwhmpsf # FWHM of the PSF
+int noise # noise model
+
+begin
+ # Set the image parameters.
+ call malloc (ap, LEN_APSTRUCT, TY_STRUCT)
+
+ # Set up the apphot package defaults.
+ call ap_defsetup (ap, fwhmpsf)
+
+ # Set up noise structure.
+ call ap_noisesetup (ap, noise)
+
+ # Set up centering structure.
+ call ap_ctrsetup (ap, cfunction, cbox)
+
+ # Set up sky fitting structure.
+ call ap_skysetup (ap, sfunction, annulus, dannulus)
+
+ # Set up photometry structure.
+ call ap_photsetup (ap, aperts, napert, weight)
+
+ # Set the display options.
+ call ap_dispsetup (ap)
+
+ # Unused structures are set to null.
+ AP_PPSF(ap) = NULL
+ AP_POLY(ap) = NULL
+ AP_RPROF(ap) = NULL
+end
+
+
+# AP_PHOTSETUP -- Procedure to set up the photometry parameters.
+
+procedure ap_photsetup (ap, aperts, napert, weight)
+
+pointer ap # pointer to apphot structure
+real aperts[ARB] # array of apertures
+int napert # number of apertures
+int weight # weighting function for photometry
+
+pointer phot
+
+begin
+ # phot structure
+ call malloc (AP_PPHOT(ap), LEN_PHOTSTRUCT, TY_STRUCT)
+ phot = AP_PPHOT(ap)
+
+ # Set the default values forthe photometry parameters.
+ AP_PXCUR(phot) = INDEFR
+ AP_PYCUR(phot) = INDEFR
+ AP_NAPERTS(phot) = napert
+ AP_ZMAG(phot) = DEF_ZMAG
+ AP_PWEIGHTS(phot) = weight
+ AP_APSTRING(phot) = EOS
+ switch (weight) {
+ case AP_PWCONSTANT:
+ call strcpy ("constant", AP_PWSTRING(phot), SZ_FNAME)
+ case AP_PWCONE:
+ call strcpy ("cone", AP_PWSTRING(phot), SZ_FNAME)
+ case AP_PWGAUSS:
+ call strcpy ("gauss", AP_PWSTRING(phot), SZ_FNAME)
+ default:
+ call strcpy ("constant", AP_PWSTRING(phot), SZ_FNAME)
+ }
+
+ # Initialize buffers.
+ AP_LENABUF(phot) = 0
+ AP_NAPIX(phot) = 0
+ AP_APIX(phot) = NULL
+ AP_XAPIX(phot) = NULL
+ AP_YAPIX(phot) = NULL
+
+ # Allocate the buffers to hold the answers.
+ call malloc (AP_APERTS(phot), napert, TY_REAL)
+ call malloc (AP_MAGS(phot), napert, TY_REAL)
+ call malloc (AP_MAGERRS(phot), napert, TY_REAL)
+ call malloc (AP_AREA(phot), napert, TY_DOUBLE)
+ call malloc (AP_SUMS(phot), napert, TY_DOUBLE)
+ call amovr (aperts, Memr[AP_APERTS(phot)], napert)
+ call asrtr (Memr[AP_APERTS(phot)], Memr[AP_APERTS(phot)], napert)
+end
diff --git a/noao/digiphot/apphot/phot/appmag.x b/noao/digiphot/apphot/phot/appmag.x
new file mode 100644
index 00000000..9bc7e43c
--- /dev/null
+++ b/noao/digiphot/apphot/phot/appmag.x
@@ -0,0 +1,120 @@
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/photdef.h"
+include "../lib/phot.h"
+
+# AP_PMAG -- Procedure to write the results of the phot task to the output
+# file.
+
+procedure ap_pmag (ap, fd, id, lid, cier, sier, pier)
+
+pointer ap # pointer to apphot structure
+int fd # output text file
+int id # id number of str
+int lid # list id of star
+int cier # centering error
+int sier # sky fitting error
+int pier # photometric error
+
+int i, naperts
+int apstati()
+real apstatr()
+
+begin
+ # Initialize.
+ if (fd == NULL)
+ return
+
+ # Write out the object id parameters.
+ call ap_wid (ap, fd, apstatr (ap, OXINIT), apstatr(ap, OYINIT),
+ id, lid, '\\')
+
+ # Write out the centering results.
+ call ap_wcres (ap, fd, cier, '\\')
+
+ # Write out the sky fitting results.
+ call ap_wsres (ap, fd, sier, '\\')
+
+ # Write out the photometry results.
+ naperts = apstati (ap, NAPERTS)
+ if (naperts == 0)
+ call ap_wmres (ap, fd, 0, pier, " ")
+ else {
+ do i = 1, naperts {
+ if (naperts == 1)
+ call ap_wmres (ap, fd, i, pier, " ")
+ else if (i == naperts)
+ call ap_wmres (ap, fd, i, pier, "* ")
+ else
+ call ap_wmres (ap, fd, i, pier, "*\\")
+ }
+ }
+end
+
+
+# AP_QPMAG -- Procedure to print a quick summary of the phot output on the
+# standard output.
+
+procedure ap_qpmag (ap, cier, sier, pier)
+
+pointer ap # pointer to apphot structure
+int cier # centering error
+int sier # sky fitting error
+int pier # photometry error
+
+int i
+pointer sp, imname, phot
+real apstatr()
+
+begin
+ # Initialize.
+ call smark (sp)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+ phot = AP_PPHOT(ap)
+
+ # Print the center and sky value.
+ call apstats (ap, IMROOT, Memc[imname], SZ_FNAME)
+ call printf ("%s %8.2f %8.2f %8g ")
+ call pargstr (Memc[imname])
+ call pargr (apstatr (ap, OPXCUR))
+ call pargr (apstatr (ap, OPYCUR))
+ call pargr (apstatr (ap, SKY_MODE))
+
+ # Print out the magnitudes and errors.
+ do i = 1, AP_NAPERTS(phot) {
+ if (i == AP_NAPERTS(phot))
+ call printf ("%7.3f ")
+ else
+ call printf ("%7.3f ")
+ call pargr (Memr[AP_MAGS(phot)+i-1])
+ }
+
+ # Print out the error codes.
+ if (cier != AP_OK || sier != AP_OK || pier != AP_OK) {
+ call printf ("err\n")
+ } else {
+ call printf ("ok\n")
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_MAGHDR -- Procedure to print the banner for the phot task on the
+# standard output.
+
+procedure ap_maghdr (ap, fd)
+
+pointer ap # pointer to apphot strucuture
+int fd # output file descriptor
+
+begin
+ if (fd == NULL)
+ return
+ call ap_idhdr (ap, fd)
+ call ap_chdr (ap, fd)
+ call ap_shdr (ap, fd)
+ call ap_mhdr (ap, fd)
+end
diff --git a/noao/digiphot/apphot/phot/apppars.x b/noao/digiphot/apphot/phot/apppars.x
new file mode 100644
index 00000000..68e08aeb
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apppars.x
@@ -0,0 +1,26 @@
+include "../lib/display.h"
+
+# AP_PPARS -- Procedure to write out the phot task parameters.
+
+procedure ap_ppars (ap)
+
+pointer ap # pointer to apphot structure
+
+bool itob()
+int apstati()
+
+begin
+ # Write the data dependent parameters.
+ call ap_dapars (ap)
+
+ # Write the centering parameters.
+ call ap_cepars (ap)
+
+ # Write the sky fitting paameters.
+ call ap_sapars (ap)
+
+ # Write the photometry parameters.
+ call ap_phpars (ap)
+
+ call clputb ("radplots", itob (apstati (ap, RADPLOTS)))
+end
diff --git a/noao/digiphot/apphot/phot/appplot.x b/noao/digiphot/apphot/phot/appplot.x
new file mode 100644
index 00000000..5172533d
--- /dev/null
+++ b/noao/digiphot/apphot/phot/appplot.x
@@ -0,0 +1,273 @@
+include <pkg/gtools.h>
+include <gset.h>
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+
+# AP_PPLOT -- Procedure to compute radial profile plots for the centering
+# routine.
+
+procedure ap_pplot (ap, im, sid, gd, makeplot)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the iraf image
+int sid # id number of the star
+pointer gd # graphics stream
+int makeplot # make a plot ?
+
+int apert, nx, ny
+pointer buf, sp, str, r, gt
+real xcenter, ycenter, xc, yc, rmin, rmax, imin, imax
+real u1, u2, v1, v2, x1, x2, y1, y2
+int ap_ctrpix()
+pointer ap_gtinit()
+real apstatr()
+
+begin
+ # Initialize
+ if (gd == NULL || makeplot == NO)
+ return
+
+ # Check for defined center and get the pixels.
+ xcenter = apstatr (ap, XCENTER)
+ ycenter = apstatr (ap, YCENTER)
+ if (IS_INDEFR(xcenter) || IS_INDEFR(ycenter))
+ return
+
+ # Fetch the pixels.
+ apert = 2 * int (apstatr (ap, SCALE) * (apstatr (ap, ANNULUS) +
+ apstatr (ap, DANNULUS))) + 1
+ buf = ap_ctrpix (im, xcenter, ycenter, apert, xc, yc, nx, ny)
+ if (buf == NULL)
+ return
+
+ # Reactivate the work station.
+ call greactivate (gd, 0)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (r, nx * ny, TY_REAL)
+
+ # Compute the radii and the plot limits.
+ call ap_ijtor2 (Memr[r], nx, ny, xc, yc)
+ call alimr (Memr[r], nx * ny, rmin, rmax)
+ call alimr (Memr[buf], nx * ny, imin, imax)
+
+ # Store the viewport and window coordinates.
+ call ggview (gd, u1, u2, v1, v2)
+ call ggwind (gd, x1, x2, y1, y2)
+
+ # Initialize the plot.
+ call apstats (ap, IMROOT, Memc[str], SZ_LINE)
+ call sprintf (Memc[str], SZ_LINE, "%s Star %d")
+ call pargstr (Memc[str])
+ call pargi (sid)
+ gt = ap_gtinit (Memc[str], apstatr (ap, OXINIT), apstatr (ap, OYINIT))
+ call gclear (gd)
+
+ # Label and annotate the plot.
+ call ap_ppset (gd, gt, ap, rmin, rmax, imin, imax)
+ call ap_ppannotate (gd, ap, rmin, rmax, imin, imax)
+
+ # Plot the coordinates.
+ call ap_plotrad (gd, gt, Memr[r], Memr[buf], nx * ny, "plus")
+
+ # Store the viewport and window coordinates.
+ call gsview (gd, u1, u2, v1, v2)
+ call gswind (gd, x1, x2, y1, y2)
+
+ call ap_gtfree (gt)
+ call gdeactivate (gd, 0)
+ call sfree (sp)
+end
+
+
+# AP_PPSET -- Procedure to set up the parameters for the phot radial profile
+# plot.
+
+procedure ap_ppset (gd, gt, ap, xmin, xmax, ymin, ymax)
+
+pointer gd # the graphics stream
+pointer gt # the gtools pointer
+pointer ap # the apphot pointer
+real xmin, xmax # the minimum and maximum radial distance
+real ymin, ymax # the minimum and maximum of the y axes
+
+int fd, naperts
+pointer sp, str, title, temp
+real aspect, scale, vx1, vx2, vy1, vy2
+int stropen(), apstati()
+real apstatr(), gstatr()
+
+begin
+ call smark (sp)
+ call salloc (str, 5 * SZ_LINE, TY_CHAR)
+ call salloc (title, SZ_LINE, TY_CHAR)
+ naperts = apstati (ap, NAPERTS)
+ call salloc (temp, naperts, TY_REAL)
+
+ fd = stropen (Memc[str], 5 * SZ_LINE, WRITE_ONLY)
+ call sysid (Memc[title], SZ_LINE)
+ call fprintf (fd, "%s\n")
+ call pargstr (Memc[title])
+
+ # Encode the center parameter string.
+ call fprintf (fd,
+ "Center: xc=%0.2f yc=%0.2f xerr=%0.2f yerr=%0.2f\n")
+ call pargr (apstatr (ap, OXCENTER))
+ call pargr (apstatr (ap, OYCENTER))
+ call pargr (apstatr (ap, XERR))
+ call pargr (apstatr (ap, YERR))
+
+ # Encode the sky fitting parameter string
+ call fprintf (fd,
+ "Sky: value=%0.2f sigma=%0.2f skew=%0.2f nsky=%d nrej=%d\n")
+ call pargr (apstatr (ap, SKY_MODE))
+ call pargr (apstatr (ap, SKY_SIGMA))
+ call pargr (apstatr (ap, SKY_SKEW))
+ call pargi (apstati (ap, NSKY))
+ call pargi (apstati (ap, NSKY_REJECT))
+
+ # Encode the apertures and magnitudes.
+ call ap_arrayr (ap, APERTS, Memr[temp])
+ call amulkr (Memr[temp], apstatr (ap, SCALE), Memr[temp], naperts)
+ call fprintf (fd, "Photometry: maxapert=")
+ call fprintf (fd, "%0.2f mag=")
+ call pargr (Memr[temp+naperts-1])
+ call ap_arrayr (ap, MAGS, Memr[temp])
+ call fprintf (fd, "%0.3f merr=")
+ call pargr (Memr[temp+naperts-1])
+ call ap_arrayr (ap, MAGERRS, Memr[temp])
+ call fprintf (fd, "%0.3f\n")
+ call pargr (Memr[temp+naperts-1])
+
+ # Encode the title.
+ call gt_gets (gt, GTTITLE, Memc[title], SZ_LINE)
+ call fprintf (fd, "%s\n")
+ call pargstr (Memc[title])
+
+ call strclose (fd)
+
+ aspect = gstatr (gd, G_ASPECT)
+ call gsetr (gd, G_ASPECT, 0.70)
+ scale = apstatr (ap, SCALE)
+
+ # Draw three axes.
+ call gseti (gd, G_XDRAWAXES, 2)
+ call gswind (gd, xmin / scale, xmax / scale, ymin, ymax)
+ call glabax (gd, Memc[str], "", "Intensity")
+
+ # Draw the bottom x axis.
+ call gseti (gd, G_YDRAWAXES, 0)
+ call gseti (gd, G_XDRAWAXES, 1)
+ call ggview (gd, vx1, vx2, vy1, vy2)
+ call gsview (gd, vx1, vx2, vy1, vy2)
+ call gswind (gd, xmin, xmax, ymin, ymax)
+ call glabax (gd,
+ "","Radial Distance (lower-pixels, upper-scale units)", "")
+
+ # Restore the default draw axis parameters.
+ call gseti (gd, G_YDRAWAXES, 3)
+ call gseti (gd, G_XDRAWAXES, 3)
+ call gsetr (gd, G_ASPECT, aspect)
+
+ # Set the mark type.
+ call gt_sets (gt, GTTYPE, "mark")
+
+ call sfree (sp)
+end
+
+
+# AP_PPANNOTATE -- Procedure to annotate the radial plot in phot.
+
+procedure ap_ppannotate (gd, ap, xmin, xmax, ymin, ymax)
+
+pointer gd # graphics stream
+pointer ap # apphot structure
+real xmin, xmax # minimum and maximum of the x axis
+real ymin, ymax # minimum and maximum of the y axis
+
+int i, naperts
+pointer sp, str, temp
+real annulus, dannulus, skyval, skysigma
+int apstati()
+real apstatr ()
+
+begin
+ naperts = apstati (ap, NAPERTS)
+ call smark (sp)
+ call salloc (str, SZ_LINE + 1, TY_CHAR)
+ call salloc (temp, naperts, TY_REAL)
+
+ # Define some temporary variables
+ annulus = apstatr (ap, SCALE) * apstatr (ap, ANNULUS)
+ dannulus = annulus + apstatr (ap, SCALE) * apstatr (ap, DANNULUS)
+
+ # Mark the inner sky annulus.
+ if (annulus >= xmin && annulus <= xmax) {
+ call gamove (gd, annulus, ymin)
+ call gadraw (gd, annulus, ymax)
+ call sprintf (Memc[str], SZ_LINE, "inner sky radius = %0.2f")
+ call pargr (annulus)
+ call gtext (gd, annulus, ymax, Memc[str], "q=h;u=180;v=t;p=r")
+ }
+
+ # Mark the outer sky annulus.
+ if (dannulus >= xmin && dannulus <= xmax) {
+ call gamove (gd, dannulus, ymin)
+ call gadraw (gd, dannulus, ymax)
+ call sprintf (Memc[str], SZ_LINE, "outer sky radius = %0.2f")
+ call pargr (dannulus)
+ call gtext (gd, dannulus, ymax, Memc[str], "q=h;u=180;v=t;p=r")
+ }
+
+ # Mark the sky value.
+ call gseti (gd, G_PLTYPE, GL_SOLID)
+ skyval = apstatr (ap, SKY_MODE)
+ if (skyval >= ymin && skyval <= ymax) {
+ call gamove (gd, xmin, skyval)
+ call gadraw (gd, xmax, skyval)
+ }
+
+ # Mark the upper sky sigma.
+ call gseti (gd, G_PLTYPE, GL_DASHED)
+ if (! IS_INDEFR(apstatr (ap, SKY_SIGMA)))
+ skysigma = skyval + apstatr (ap, SHIREJECT) * apstatr (ap,
+ SKY_SIGMA)
+ else
+ skysigma = INDEFR
+ if (! IS_INDEFR(skysigma) && (skysigma >= ymin) && skysigma <= ymax) {
+ call gamove (gd, xmin, skysigma)
+ call gadraw (gd, xmax, skysigma)
+ }
+
+ # Mark the lower sky sigma
+ if (! IS_INDEFR(apstatr (ap, SKY_SIGMA)))
+ skysigma = skyval - apstatr (ap, SLOREJECT) * apstatr (ap,
+ SKY_SIGMA)
+ else
+ skysigma = INDEFR
+ if (! IS_INDEFR(skysigma) && (skysigma >= ymin) && skysigma <= ymax) {
+ call gamove (gd, xmin, skysigma)
+ call gadraw (gd, xmax, skysigma)
+ }
+
+ # Mark the appertures.
+ call gseti (gd, G_PLTYPE, GL_SOLID)
+ call ap_arrayr (ap, APERTS, Memr[temp])
+ call amulkr (Memr[temp], apstatr (ap, SCALE), Memr[temp], naperts)
+ do i = 1, naperts {
+ call gamove (gd, Memr[temp+i-1], ymin)
+ call gadraw (gd, Memr[temp+i-1], ymax)
+ call sprintf (Memc[str], SZ_LINE, "apert[%d] = %0.2f")
+ call pargi (i)
+ call pargr (Memr[temp+i-1])
+ call gtext (gd, Memr[temp+i-1], ymax, Memc[str],
+ "q=h;u=180;v=t;p=r")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/phot/appshow.x b/noao/digiphot/apphot/phot/appshow.x
new file mode 100644
index 00000000..5e52b42d
--- /dev/null
+++ b/noao/digiphot/apphot/phot/appshow.x
@@ -0,0 +1,83 @@
+include "../lib/display.h"
+include "../lib/phot.h"
+
+# AP_PSHOW -- Procedure to print the photometry parameters.
+
+procedure ap_pshow (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+bool itob()
+int apstati()
+
+begin
+ call ap_nshow (ap)
+ call printf ("\n")
+ call ap_cpshow (ap)
+ call printf ("\n")
+ call ap_spshow (ap)
+ call printf ("\n")
+ call ap_mpshow (ap)
+ call printf (" %s = %b\n")
+ call pargstr (KY_RADPLOTS)
+ call pargb (itob (apstati (ap, RADPLOTS)))
+end
+
+
+# AP_MSHOW -- Procedure to print the photometry parameters on the standard
+# output.
+
+procedure ap_mshow (ap)
+
+pointer ap # pointer to apphot structure
+
+bool itob()
+int apstati()
+begin
+ call ap_nshow (ap)
+ call printf ("\n")
+ call ap_mpshow (ap)
+ call printf (" %s = %b\n")
+ call pargstr (KY_RADPLOTS)
+ call pargb (itob (apstati (ap, RADPLOTS)))
+end
+
+
+# AP_MPSHOW -- Procedure to print the photometry parameters on the standard
+# output.
+
+procedure ap_mpshow (ap)
+
+pointer ap # pointer to apphot structure
+
+pointer sp, str
+bool itob()
+int apstati()
+real apstatr()
+
+begin
+ # Write out the image and cursor position.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Write out the phot parameters.
+ call printf ("Photometry Parameters\n")
+ call apstats (ap, PWSTRING, Memc[str], SZ_LINE)
+ call printf (" %s = %s %s\n")
+ call pargstr (KY_PWSTRING)
+ call pargstr (Memc[str])
+ call pargstr (UN_PMODEL)
+ call apstats (ap, APERTS, Memc[str], SZ_LINE)
+ call printf (" %s = %s %s\n")
+ call pargstr (KY_APERTS)
+ call pargstr (Memc[str])
+ call pargstr (UN_PSCALEUNIT)
+ call printf (" %s = %g\n")
+ call pargstr (KY_ZMAG)
+ call pargr (apstatr (ap, ZMAG))
+ call printf (" %s = %b\n")
+ call pargstr (KY_MKAPERT)
+ call pargb (itob (apstati (ap, MKAPERT)))
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/phot/apqcolon.x b/noao/digiphot/apphot/phot/apqcolon.x
new file mode 100644
index 00000000..c3050190
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apqcolon.x
@@ -0,0 +1,331 @@
+include <error.h>
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+
+# APQCOLON -- Procedure to display and edit the quick photometry parameters.
+
+procedure apqcolon (ap, im, cl, out, stid, ltid, cmdstr, newimage, newcbuf,
+ newcenter, newsbuf, newsky, newmagbuf, newmag)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to the iraf image
+int cl # coordinate file descriptor
+int out # output file descriptor
+int stid # output file sequence number
+int ltid # coordinate file sequence number
+char cmdstr[ARB] # command string
+int newimage # new image ?
+int newcbuf # new centering buffers ?
+int newcenter # compute new center ?
+int newsbuf # new sky fitting buffers ?
+int newsky # compute new sky ?
+int newmagbuf # new aperture buffers ?
+int newmag # compute new magnitudes ?
+
+bool bval
+int ip, ncmd
+pointer sp, cmd, str
+real rval
+
+bool streq(), itob()
+int btoi(), strdic(), nscan(), apstati(), ctowrd(), open()
+pointer immap()
+real apstatr()
+errchk immap, open
+
+begin
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Get the command.
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, QCMDS)
+ switch (ncmd) {
+ case QCMD_SHOW:
+ call printf ("\n")
+ call ap_qshow (ap)
+ call printf ("\n")
+
+ case QCMD_CBOXWIDTH:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_CAPERT)
+ call pargr (2.0 * apstatr (ap, CAPERT))
+ call pargstr ("pixels")
+ } else {
+ call apsetr (ap, CAPERT, rval / 2.0)
+ if (stid > 1)
+ call ap_rparam (out, KY_CAPERT, rval, UN_CSCALEUNIT,
+ "width of the centering box")
+ newcbuf = YES
+ newcenter = YES
+ }
+
+ case QCMD_ANNULUS:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_ANNULUS)
+ call pargr (apstatr (ap, ANNULUS))
+ call pargstr ("pixels")
+ } else {
+ call apsetr (ap, ANNULUS, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_ANNULUS, rval, UN_SSCALEUNIT,
+ "inner radius of the sky annulus")
+ newsbuf = YES
+ newsky = YES
+ }
+
+ case QCMD_DANNULUS:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_DANNULUS)
+ call pargr (apstatr (ap, DANNULUS))
+ call pargstr ("pixels")
+ } else {
+ call apsetr (ap, DANNULUS, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_DANNULUS, rval, UN_SSCALEUNIT,
+ "width of the sky annulus")
+ newsbuf = YES
+ newsky = YES
+ }
+
+ case QCMD_APERTURES:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, APERTS, Memc[cmd], SZ_LINE)
+ call printf ("%s = %s %s\n")
+ call pargstr (KY_APERTS)
+ call pargstr (Memc[cmd])
+ call pargstr ("pixels")
+ } else {
+ call apsets (ap, APERTS, Memc[cmd])
+ if (stid > 1)
+ call ap_sparam (out, KY_APERTS, Memc[cmd], UN_PSCALEUNIT,
+ "list of aperture radii")
+ newmag = YES
+ newmagbuf = YES
+ }
+
+ case QCMD_ZMAG:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (KY_ZMAG)
+ call pargr (apstatr (ap, ZMAG))
+ } else {
+ call apsetr (ap, ZMAG, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_ZMAG, rval, UN_PZMAG,
+ "zero point of magnitude scale")
+ newmag = YES
+ }
+
+ case QCMD_EPADU:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (KY_EPADU)
+ call pargr (apstatr (ap, EPADU))
+ } else {
+ call apsetr (ap, EPADU, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_EPADU, rval, UN_NEPADU, "gain")
+ newmag = YES
+ }
+
+ case QCMD_EXPOSURE:
+ call gargstr (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, EXPOSURE, Memc[str], SZ_FNAME)
+ call printf ("%s = %s\n")
+ call pargstr (KY_EXPOSURE)
+ call pargstr (Memc[str])
+ } else {
+ ip = 1
+ if (ctowrd (Memc[cmd], ip, Memc[str], SZ_FNAME) <= 0)
+ Memc[str] = EOS
+ call apsets (ap, EXPOSURE, Memc[str])
+ if (im != NULL)
+ call ap_itime (im, ap)
+ if (stid > 1)
+ call ap_sparam (out, KY_EXPOSURE, Memc[str],
+ UN_AKEYWORD, "exposure time keyword")
+ }
+
+ case QCMD_AIRMASS:
+ call gargstr (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, AIRMASS, Memc[str], SZ_FNAME)
+ call printf ("%s = %s\n")
+ call pargstr (KY_AIRMASS)
+ call pargstr (Memc[str])
+ } else {
+ ip = 1
+ if (ctowrd (Memc[cmd], ip, Memc[str], SZ_FNAME) <= 0)
+ Memc[str] = EOS
+ call apsets (ap, AIRMASS, Memc[str])
+ if (im != NULL)
+ call ap_airmass (im, ap)
+ if (stid > 1)
+ call ap_sparam (out, KY_AIRMASS, Memc[str],
+ UN_AKEYWORD, "airmass keyword")
+ }
+
+ case QCMD_FILTER:
+ call gargstr (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, FILTER, Memc[str], SZ_FNAME)
+ call printf ("%s = %s\n")
+ call pargstr (KY_FILTER)
+ call pargstr (Memc[str])
+ } else {
+ ip = 1
+ if (ctowrd (Memc[cmd], ip, Memc[str], SZ_FNAME) <= 0)
+ Memc[str] = EOS
+ call apsets (ap, FILTER, Memc[str])
+ if (im != NULL)
+ call ap_filter (im, ap)
+ if (stid > 1)
+ call ap_sparam (out, KY_FILTER, Memc[str],
+ UN_AKEYWORD, "filter keyword")
+ }
+
+ case QCMD_OBSTIME:
+ call gargstr (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, OBSTIME, Memc[str], SZ_FNAME)
+ call printf ("%s = %s\n")
+ call pargstr (KY_OBSTIME)
+ call pargstr (Memc[str])
+ } else {
+ ip = 1
+ if (ctowrd (Memc[cmd], ip, Memc[str], SZ_FNAME) <= 0)
+ Memc[str] = EOS
+ call apsets (ap, OBSTIME, Memc[str])
+ if (im != NULL)
+ call ap_otime (im, ap)
+ if (stid > 1)
+ call ap_sparam (out, KY_OBSTIME, Memc[str],
+ UN_AKEYWORD, "filter keyword")
+ }
+
+ case QCMD_RADPLOTS:
+ call gargb (bval)
+ if (nscan () == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (KY_RADPLOTS)
+ call pargb (itob (apstati (ap, RADPLOTS)))
+ } else {
+ call apseti (ap, RADPLOTS, btoi (bval))
+ }
+
+ case QCMD_IMAGE:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ call apstats (ap, IMNAME, Memc[str], SZ_FNAME)
+ if (Memc[cmd] == EOS || streq (Memc[cmd], Memc[str])) {
+ call printf ("%s = %s\n")
+ call pargstr (KY_IMNAME)
+ call pargstr (Memc[str])
+ } else {
+ if (im != NULL) {
+ call imunmap (im)
+ im = NULL
+ }
+ iferr {
+ im = immap (Memc[cmd], READ_ONLY, 0)
+ } then {
+ call erract (EA_WARN)
+ call printf ("Reopening image %s.\n")
+ call pargstr (Memc[str])
+ im = immap (Memc[str], READ_ONLY, 0)
+ } else {
+ call apimkeys (ap, im, Memc[cmd])
+ newimage = YES
+ newcbuf = YES; newcenter = YES
+ newsbuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ }
+ }
+
+ case QCMD_COORDS:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ call apstats (ap, CLNAME, Memc[str], SZ_FNAME)
+ if (Memc[cmd] == EOS || streq (Memc[cmd], Memc[str])) {
+ call printf ("%s: %s\n")
+ call pargstr (KY_CLNAME)
+ call pargstr (Memc[str])
+ } else {
+ if (cl != NULL) {
+ call close( cl)
+ cl = NULL
+ }
+ iferr {
+ cl = open (Memc[cmd], READ_ONLY, TEXT_FILE)
+ } then {
+ cl = NULL
+ call erract (EA_WARN)
+ call apsets (ap, CLNAME, "")
+ call apsets (ap, CLROOT, "")
+ call printf ("Coordinate file is undefined.\n")
+ } else {
+ call apsets (ap, CLNAME, Memc[cmd])
+ call apfroot (Memc[cmd], Memc[str], SZ_FNAME)
+ call apsets (ap, CLROOT, Memc[str])
+ ltid = 0
+ }
+ }
+
+ case QCMD_OUTPUT:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ call apstats (ap, OUTNAME, Memc[str], SZ_FNAME)
+ if (Memc[cmd] == EOS || streq (Memc[cmd], Memc[str])) {
+ call printf ("%s = %s\n")
+ call pargstr (KY_OUTNAME)
+ call pargstr (Memc[str])
+ } else {
+ if (out != NULL) {
+ call close (out)
+ out = NULL
+ if (stid <= 1)
+ call delete (Memc[str])
+ }
+ iferr {
+ out = open (Memc[cmd], READ_ONLY, TEXT_FILE)
+ } then {
+ call erract (EA_WARN)
+ call printf ("Reopening output file: %s\n")
+ call pargstr (Memc[str])
+ if (Memc[str] != EOS)
+ out = open (Memc[str], APPEND, TEXT_FILE)
+ else
+ out = NULL
+ } else {
+ call apsets (ap, OUTNAME, Memc[cmd])
+ stid = 1
+ }
+ }
+
+ default:
+ call printf ("Unknown or ambiguous colon command\7\n")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/phot/apqphot.x b/noao/digiphot/apphot/phot/apqphot.x
new file mode 100644
index 00000000..b3c80b73
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apqphot.x
@@ -0,0 +1,494 @@
+include <ctype.h>
+include <gset.h>
+include <imhdr.h>
+include "../lib/phot.h"
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+
+define HELPFILE "apphot$phot/qphot.key"
+
+# APQPHOT -- Procedure to compute quick magnitudes for a list of objects
+
+int procedure apqphot (ap, im, cl, gd, mgd, id, out, stid, interactive, cache)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to IRAF image
+int cl # the coordinate list descriptor
+pointer gd # pointer to graphcis descriptor
+pointer mgd # pointer to the metacode file
+pointer id # pointer to image display stream
+int out # output file descriptor
+int stid # output file sequence number
+int interactive # interactive mode
+int cache # cache the input image pixels
+
+real wx, wy, xlist, ylist
+pointer sp, cmd
+int newskybuf, newsky, newcenterbuf, newcenter, newmagbuf, newmag
+int newimage, newlist, ip, wcs, key, colonkey, cier, sier, pier
+int ltid, oid, prev_num, req_num, req_size, old_size, buf_size, memstat
+
+real apstatr()
+int clgcur(), apfitsky(), aprefitsky(), apfitcenter(), aprefitcenter()
+int apmag(), apremag(), apstati(), apgqverify(), apnew(), ctoi()
+int apgtverify(), apgscur(), ap_avsky(), ap_memstat(), sizeof()
+bool fp_equalr()
+
+define endswitch_ 99
+
+begin
+ # Initialize.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Initialize cursor command.
+ key = ' '
+ Memc[cmd] = EOS
+
+ # Initialize the fitting parameters.
+ newimage = NO
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ cier = AP_OK; sier = AP_OK; pier = AP_OK
+
+ # Initialize the sequencing.
+ newlist = NO
+ ltid = 0
+
+ # Loop over the coordinate file.
+ while (clgcur ("icommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+
+ # Store the current cursor coordinates.
+ call ap_vtol (im, wx, wy, wx, wy, 1)
+ call apsetr (ap, CWX, wx)
+ call apsetr (ap, CWY, wy)
+
+ if (apnew (ap, wx, wy, xlist, ylist, newlist) == YES) {
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ }
+
+ # Store previous cursor coordinates.
+ call apsetr (ap, WX, apstatr (ap, CWX))
+ call apsetr (ap, WY, apstatr (ap, CWY))
+
+ # Loop over the colon keystroke commands.
+ switch (key) {
+
+ # Quit.
+ case 'q':
+ if (interactive == YES) {
+ if (apgqverify ("qphot", ap, key) == YES) {
+ call sfree (sp)
+ return (apgtverify (key))
+ }
+ } else {
+ call sfree (sp)
+ return (NO)
+ }
+
+ # Print out error messages.
+ case 'e':
+ if (interactive == YES)
+ call ap_perrors (ap, cier, sier, pier)
+
+ # Print out the help page(s).
+ case '?':
+ if ((id != NULL) && (id == gd))
+ call gpagefile (id, HELPFILE, "")
+ else if (gd != NULL)
+ call pagefile (HELPFILE, "[space=morehelp,q=quit,?=help]")
+
+ # Process apphot colon commands.
+ case ':':
+ for (ip = 1; IS_WHITE(Memc[cmd+ip-1]); ip = ip + 1)
+ ;
+ colonkey = Memc[cmd+ip-1]
+ switch (colonkey) {
+ case 'm', 'n':
+
+ # Show/set a qphot parameter.
+ if (Memc[cmd+ip] != EOS && Memc[cmd+ip] != ' ') {
+ call apqcolon (ap, im, cl, out, stid, ltid, Memc[cmd],
+ newimage, newcenterbuf, newcenter, newskybuf,
+ newsky, newmagbuf, newmag)
+ goto endswitch_
+ }
+
+ # No coordinate list.
+ if (cl == NULL) {
+ if (interactive == YES)
+ call printf ("No coordinate list\n")
+ goto endswitch_
+ }
+
+ # Get the next object.
+ ip = ip + 1
+ prev_num = ltid
+ if (ctoi (Memc[cmd], ip, req_num) <= 0)
+ req_num = ltid + 1
+
+ # Fetch the next object from the list.
+ if (apgscur (cl, id, xlist, ylist, prev_num, req_num,
+ ltid) == EOF) {
+ if (interactive == YES)
+ call printf (
+ "End of coordinate list, use r key to rewind\n")
+ goto endswitch_
+ }
+
+ # Convert the coordinates.
+ switch (apstati (ap, WCSIN)) {
+ case WCS_PHYSICAL, WCS_WORLD:
+ call ap_itol (ap, xlist, ylist, xlist, ylist, 1)
+ case WCS_TV:
+ call ap_vtol (im, xlist, ylist, xlist, ylist, 1)
+ default:
+ ;
+ }
+
+ # Move to the next object.
+ newlist = YES
+ if (colonkey == 'm') {
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ goto endswitch_
+ }
+
+ # Measure object.
+ cier = apfitcenter (ap, im, xlist, ylist)
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER),
+ apstatr (ap, YCENTER), NULL, gd)
+ pier = apmag (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), apstati (ap, POSITIVE), apstatr (ap,
+ SKY_MODE), apstatr(ap, SKY_SIGMA), apstati (ap, NSKY))
+ if (id != NULL) {
+ call apmark (ap, id, apstati (ap, MKCENTER),
+ apstati (ap, MKSKY), apstati (ap, MKAPERT))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_pplot (ap, im, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qpmag (ap, cier, sier, pier)
+ if (stid == 1)
+ call ap_param (ap, out, "qphot")
+ call ap_pmag (ap, out, stid, ltid, cier, sier, pier)
+ call ap_pplot (ap, im, stid, mgd, YES)
+ stid = stid + 1
+ newcenterbuf = NO; newcenter = NO
+ newskybuf = NO; newsky = NO
+ newmagbuf = NO; newmag = NO
+
+ default:
+ call apqcolon (ap, im, cl, out, stid, ltid, Memc[cmd],
+ newimage, newcenterbuf, newcenter, newskybuf, newsky,
+ newmagbuf, newmag)
+ }
+
+ # Reestablish the correct viewport.
+ if (newimage == YES) {
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[cmd], im, 4)
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+ }
+
+ newimage = NO
+
+ # Save the current parameters in the pset files.
+ case 'w':
+ call ap_qppars (ap)
+
+ # Plot a centered stellar radial profile.
+ case 'd':
+ if (interactive == YES) {
+ call ap_qrad (ap, im, wx, wy, gd)
+ newmagbuf = YES; newmag = YES
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ }
+
+ # Rewind the list.
+ case 'r':
+ if (cl != NULL) {
+ call seek (cl, BOF)
+ ltid = 0
+ } else if (interactive == YES)
+ call printf ("No coordinate list\n")
+
+ # Process the remainder of the list.
+ case 'l':
+ if (cl != NULL) {
+ ltid = ltid + 1
+ oid = stid
+ call apbphot (ap, im, cl, NULL, out, stid, ltid, gd, mgd,
+ id, YES)
+ ltid = ltid + stid - oid + 1
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ } else if (interactive == YES)
+ call printf ("No coordinate list\n")
+
+ # Get, measure next object in the list
+ case 'm', 'n':
+
+ # No coordinate file.
+ if (cl == NULL) {
+ if (interactive == YES)
+ call printf ("No coordinate list\n")
+ goto endswitch_
+
+ }
+
+ # Need to rewind the coordinate file.
+ prev_num = ltid
+ req_num = ltid + 1
+ if (apgscur (cl, id, xlist, ylist, prev_num, req_num,
+ ltid) == EOF) {
+ if (interactive == YES)
+ call printf (
+ "End of coordinate list, use r key to rewind\n")
+ goto endswitch_
+ }
+
+ # Convert coordinates if necessary.
+ switch (apstati (ap, WCSIN)) {
+ case WCS_PHYSICAL, WCS_WORLD:
+ call ap_itol (ap, xlist, ylist, xlist, ylist, 1)
+ case WCS_TV:
+ call ap_vtol (im, xlist, ylist, xlist, ylist, 1)
+ default:
+ ;
+ }
+
+ # Move to next object.
+ newlist = YES
+ if (key == 'm') {
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ goto endswitch_
+ }
+
+ # Measure next object.
+ cier = apfitcenter (ap, im, xlist, ylist)
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), NULL, gd)
+ pier = apmag (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), apstati (ap, POSITIVE), apstatr (ap, SKY_MODE),
+ apstatr (ap, SKY_SIGMA), apstati (ap, NSKY))
+ if (id != NULL) {
+ call apmark (ap, id, apstati (ap, MKCENTER), apstati (ap,
+ MKSKY), apstati (ap, MKAPERT))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_pplot (ap, im, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qpmag (ap, cier, sier, pier)
+ if (stid == 1)
+ call ap_param (ap, out, "qphot")
+ call ap_pmag (ap, out, stid, ltid, cier, sier, pier)
+ call ap_pplot (ap, im, stid, mgd, YES)
+ stid = stid + 1
+ newcenterbuf = NO; newcenter = NO
+ newskybuf = NO; newsky = NO
+ newmagbuf = NO; newmag = NO
+
+ # Setup phot parameters interactively.
+ case 'i':
+ if (interactive == YES) {
+ call ap_qradsetup (ap, im, wx, wy, gd, out, stid)
+ newmagbuf = YES; newmag = YES
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ }
+
+ # Fit the center around the cursor position.
+ case 'c':
+ if (newcenterbuf == YES)
+ cier = apfitcenter (ap, im, wx, wy)
+ else if (newcenter == YES)
+ cier = aprefitcenter (ap, im, cier)
+ if (id != NULL) {
+ call apmark (ap, id, apstati (ap, MKCENTER), NO, NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_cplot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qcenter (ap, cier)
+ newcenterbuf = NO
+ newcenter = NO
+
+ # Fit the sky around the cursor position.
+ case 't':
+ if (newskybuf == YES || ! fp_equalr (wx,
+ apstatr (ap, SXCUR)) || ! fp_equalr (wy, apstatr (ap,
+ SYCUR)))
+ sier = apfitsky (ap, im, wx, wy, NULL, gd)
+ else if (newsky == YES)
+ sier = aprefitsky (ap, im, gd)
+ if (id != NULL) {
+ call apmark (ap, id, NO, apstati (ap, MKSKY), NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_splot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qspsky (ap, sier)
+ newskybuf = NO; newsky = NO
+
+ # Compute the average of several sky measurements around
+ # different cursor postions.
+ case 'a':
+ sier = ap_avsky (ap, im, stid, NULL, id, gd, interactive)
+ if (interactive == YES)
+ call ap_qaspsky (ap, sier)
+ newskybuf = NO; newsky = NO
+
+ # Fit the sky around the current center position.
+ case 's':
+ if (newskybuf == YES || ! fp_equalr (apstatr (ap, XCENTER),
+ apstatr (ap, SXCUR)) || ! fp_equalr (apstatr (ap, SYCUR),
+ apstatr (ap, YCENTER)))
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER),
+ apstatr (ap, YCENTER), NULL, gd)
+ else if (newsky == YES)
+ sier = aprefitsky (ap, im, gd)
+ if (id != NULL) {
+ call apmark (ap, id, NO, apstati (ap, MKSKY), NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_splot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qspsky (ap, sier)
+ newskybuf = NO
+ newsky = NO
+
+ # Compute magnitudes around the cursor position using the current
+ # sky.
+ case 'p', 'o':
+ if (newcenterbuf == YES)
+ cier = apfitcenter (ap, im, wx, wy)
+ else if (newcenter == YES)
+ cier = aprefitcenter (ap, im, cier)
+ if (newmagbuf == YES || ! fp_equalr (apstatr (ap, XCENTER),
+ apstatr (ap, PXCUR)) || ! fp_equalr (apstatr (ap,
+ PYCUR), apstatr (ap, YCENTER)))
+ pier = apmag (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), apstati (ap, POSITIVE), apstatr (ap,
+ SKY_MODE), apstatr (ap, SKY_SIGMA), apstati (ap, NSKY))
+ else
+ pier = apremag (ap, im, apstati (ap, POSITIVE), apstatr (ap,
+ SKY_MODE), apstatr (ap, SKY_SIGMA), apstati (ap, NSKY))
+ if (id != NULL) {
+ call apmark (ap, id, NO, NO, apstati (ap, MKAPERT))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ if (interactive == YES)
+ call ap_qpmag (ap, cier, sier, pier)
+ newmagbuf = NO; newmag = NO
+
+ if (key == 'o') {
+ if (stid == 1)
+ call ap_param (ap, out, "qphot")
+ if (newlist == YES)
+ call ap_pmag (ap, out, stid, ltid, cier, sier, pier)
+ else
+ call ap_pmag (ap, out, stid, 0, cier, sier, pier)
+ call ap_pplot (ap, im, stid, mgd, YES)
+ stid = stid + 1
+ }
+
+ # Compute the center, sky, and magnitudes and save the results.
+ case 'f', ' ':
+ if (newcenterbuf == YES)
+ cier = apfitcenter (ap, im, wx, wy)
+ else if (newcenter == YES)
+ cier = aprefitcenter (ap, im, cier)
+ if (newskybuf == YES || ! fp_equalr (apstatr (ap, XCENTER),
+ apstatr (ap, SXCUR)) || ! fp_equalr (apstatr (ap, YCENTER),
+ apstatr (ap, SYCUR)))
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), NULL, gd)
+ else if (newsky == YES)
+ sier = aprefitsky (ap, im, gd)
+ if (newmagbuf == YES || ! fp_equalr (apstatr (ap, XCENTER),
+ apstatr (ap, PXCUR)) || ! fp_equalr (apstatr (ap, YCENTER),
+ apstatr (ap, PYCUR)))
+ pier = apmag (ap, im, apstatr (ap, XCENTER),
+ apstatr (ap, YCENTER), apstati (ap, POSITIVE),
+ apstatr (ap, SKY_MODE), apstatr (ap, SKY_SIGMA),
+ apstati (ap, NSKY))
+ else
+ pier = apremag (ap, im, apstati (ap, POSITIVE), apstatr (ap,
+ SKY_MODE), apstatr (ap, SKY_SIGMA), apstati (ap, NSKY))
+
+ if (id != NULL) {
+ call apmark (ap, id, apstati (ap, MKCENTER), apstati (ap,
+ MKSKY), apstati (ap, MKAPERT))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_pplot (ap, im, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qpmag (ap, cier, sier, pier)
+
+ newcenterbuf = NO; newcenter = NO
+ newskybuf = NO; newsky = NO
+ newmagbuf = NO; newmag = NO
+
+ if (key == ' ') {
+ if (stid == 1)
+ call ap_param (ap, out, "qphot")
+ if (newlist == YES)
+ call ap_pmag (ap, out, stid, ltid, cier, sier, pier)
+ else
+ call ap_pmag (ap, out, stid, 0, cier, sier, pier)
+ call ap_pplot (ap, im, stid, mgd, YES)
+ stid = stid + 1
+ }
+
+ default:
+ call printf ("Unknown or ambiguous keystroke command\n")
+ }
+
+endswitch_
+ # Setup for the next object.
+ key = ' '
+ Memc[cmd] = EOS
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/phot/apqppars.x b/noao/digiphot/apphot/phot/apqppars.x
new file mode 100644
index 00000000..cb87383b
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apqppars.x
@@ -0,0 +1,42 @@
+include "../lib/apphot.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+include "../lib/noise.h"
+include "../lib/display.h"
+
+# AP_QPPARS -- Procedure to write out qthe phot task parameters.
+
+procedure ap_qppars (ap)
+
+pointer ap # pointer to apphot structure
+
+pointer mp, str
+bool itob()
+int apstati()
+real apstatr()
+
+begin
+ call smark (mp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ call clputr ("cbox", 2.0 * apstatr (ap, CAPERT))
+ call clputr ("annulus", apstatr (ap, ANNULUS))
+ call clputr ("dannulus", apstatr (ap, DANNULUS))
+ call apstats (ap, APERTS, Memc[str], SZ_LINE)
+ call clpstr ("apertures", Memc[str])
+
+ call apstats (ap, EXPOSURE, Memc[str], SZ_LINE)
+ call clpstr ("exposure", Memc[str])
+ call apstats (ap, AIRMASS, Memc[str], SZ_LINE)
+ call clpstr ("airmass", Memc[str])
+ call apstats (ap, FILTER, Memc[str], SZ_LINE)
+ call clpstr ("filter", Memc[str])
+ call apstats (ap, OBSTIME, Memc[str], SZ_LINE)
+ call clpstr ("obstime", Memc[str])
+ call clputr ("epadu", apstatr (ap, EPADU))
+ call clputr ("zmag", apstatr (ap, ZMAG))
+ call clputb ("radplots", itob (apstati (ap, RADPLOTS)))
+
+ call sfree (mp)
+end
diff --git a/noao/digiphot/apphot/phot/apqradsetup.x b/noao/digiphot/apphot/phot/apqradsetup.x
new file mode 100644
index 00000000..233cd8a7
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apqradsetup.x
@@ -0,0 +1,105 @@
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/fitsky.h"
+include "../lib/center.h"
+
+define HELPFILE "apphot$phot/iqphot.key"
+
+# AP_QRADSETUP -- Procedure to set up phot interactively using a radial profile
+# plot of a bright star.
+
+procedure ap_qradsetup (ap, im, wx, wy, gd, out, stid)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to the IRAF image
+real wx, wy # cursor coordinates
+pointer gd # pointer to graphics stream
+int out # output file descriptor
+int stid # output file sequence number
+
+int cier, sier, pier, wcs, key
+pointer sp, str, cmd
+real xcenter, ycenter, rmin, rmax, imin, imax, xc, yc, rval
+real u1, u2, v1, v2, x1, x2, y1, y2
+
+int apfitcenter(), apfitsky(), ap_wmag(), apstati(), clgcur(), ap_showplot()
+real apstatr(), ap_ccapert(), ap_cannulus(), ap_cdannulus()
+
+begin
+ # Check for open graphics stream
+ if (gd == NULL)
+ return
+ call greactivate (gd, 0)
+
+ # Store the viewport and window coordinates.
+ call ggview (gd, u1, u2, v1, v2)
+ call ggwind (gd, x1, x2, y1, y2)
+
+ # Plot the radial profile.
+ if (ap_showplot (ap, im, wx, wy, gd, xcenter, ycenter, rmin, rmax,
+ imin, imax) == ERR) {
+ call gdeactivate (gd, 0)
+ return
+ }
+
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ call printf (
+ "Waiting for setup menu command (?=help, v=default setup, q=quit):\n")
+ while (clgcur ("gcommands", xc, yc, wcs, key, Memc[cmd],
+ SZ_LINE) != EOF) {
+
+ switch (key) {
+
+ case 'q':
+ break
+ case '?':
+ call gpagefile (gd, HELPFILE, "")
+ case 'c':
+ rval = ap_ccapert (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'a':
+ rval = ap_cannulus (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'd':
+ rval = ap_cdannulus (ap, gd, out, stid, apstatr (ap, ANNULUS),
+ rmin, rmax, imin, imax)
+ case 'r':
+ call ap_caper (ap, gd, out, stid, Memc[str], rmin, rmax,
+ imin, imax)
+ case 'v':
+ rval = ap_ccapert (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_cannulus (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_cdannulus (ap, gd, out, stid, apstatr (ap, ANNULUS),
+ rmin, rmax, imin, imax)
+ call ap_caper (ap, gd, out, stid, Memc[str], rmin, rmax,
+ imin, imax)
+ default:
+ call printf ("Unknown or ambiguous keystroke command\007\n")
+ }
+ call printf (
+ "Waiting for setup menu command (?=help, v=default setup, q=quit):\n")
+ }
+ call printf (
+ "Interactive setup is complete. Type w to save parameters.\n")
+
+ # Restore the viewport and window coordinates.
+ call gsview (gd, u1, u2, v1, v2)
+ call gswind (gd, x1, x2, y1, y2)
+
+ call gdeactivate (gd, 0)
+ call sfree (sp)
+
+ # Print the answer.
+ cier = apfitcenter (ap, im, xcenter, ycenter)
+ if (! IS_INDEFR (apstatr (ap, XCENTER)) &&
+ ! IS_INDEFR (apstatr (ap, YCENTER)))
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), NULL, gd)
+ if (! IS_INDEFR (apstatr (ap, SKY_MODE)))
+ pier = ap_wmag (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), apstati (ap, POSITIVE), apstatr (ap, SKY_MODE),
+ apstatr (ap, SKY_SIGMA), apstati (ap, NSKY))
+ call ap_pplot (ap, im, 0, gd, apstati (ap, RADPLOTS))
+ call ap_qpmag (ap, cier, sier, pier)
+end
diff --git a/noao/digiphot/apphot/phot/apqshow.x b/noao/digiphot/apphot/phot/apqshow.x
new file mode 100644
index 00000000..d8a4b6db
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apqshow.x
@@ -0,0 +1,86 @@
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/display.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+
+# AP_QSHOW -- Procedure to display the current data parameters.
+
+procedure ap_qshow (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+pointer sp, str
+bool itob()
+int apstati()
+real apstatr()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Set the object charactersitics.
+ call printf ("Quick Phot Parameters\n")
+ call printf (" %s: %s (%.2f,%.2f) %s: %s\n")
+ call apstats (ap, IMNAME, Memc[str], SZ_FNAME)
+ call pargstr (KY_IMNAME)
+ call pargstr (Memc[str])
+ call pargr (apstatr (ap, CWX))
+ call pargr (apstatr (ap, CWY))
+ call apstats (ap, OUTNAME, Memc[str], SZ_FNAME)
+ call pargstr (KY_OUTNAME)
+ call pargstr (Memc[str])
+
+ call printf (" %s: %s\n")
+ call apstats (ap, CLNAME, Memc[str], SZ_FNAME)
+ call pargstr (KY_CLNAME)
+ call pargstr (Memc[str])
+
+ call printf (" %s = %g %s\n")
+ call pargstr (KY_CAPERT)
+ call pargr (2.0* apstatr (ap, CAPERT))
+ call pargstr ("pixels")
+
+ call printf (" %s = %g %s %s = %g %s\n")
+ call pargstr (KY_ANNULUS)
+ call pargr (apstatr (ap, ANNULUS))
+ call pargstr ("pixels")
+ call pargstr (KY_DANNULUS)
+ call pargr (apstatr (ap, DANNULUS))
+ call pargstr ("pixels")
+
+ call apstats (ap, APERTS, Memc[str], SZ_FNAME)
+ call printf (" %s = %s %s %s = %g %s\n")
+ call pargstr (KY_APERTS)
+ call pargstr (Memc[str])
+ call pargstr ("pixels")
+ call pargstr (KY_ZMAG)
+ call pargr (apstatr (ap, ZMAG))
+ call pargstr (UN_PZMAG)
+
+ call printf (" %s = %g %s\n")
+ call pargstr (KY_EPADU)
+ call pargr (apstatr (ap, EPADU))
+ call pargstr (UN_NEPADU)
+ call printf (" %s = %s %s = %s\n")
+ call apstats (ap, EXPOSURE, Memc[str], SZ_FNAME)
+ call pargstr (KY_EXPOSURE)
+ call pargstr (Memc[str])
+ call apstats (ap, AIRMASS, Memc[str], SZ_FNAME)
+ call pargstr (KY_AIRMASS)
+ call pargstr (Memc[str])
+ call printf (" %s = %s %s = %s\n")
+ call apstats (ap, FILTER, Memc[str], SZ_FNAME)
+ call pargstr (KY_FILTER)
+ call pargstr (Memc[str])
+ call apstats (ap, OBSTIME, Memc[str], SZ_FNAME)
+ call pargstr (KY_OBSTIME)
+ call pargstr (Memc[str])
+
+ call printf (" %s = %b\n")
+ call pargstr (KY_RADPLOTS)
+ call pargb (itob (apstati (ap, RADPLOTS)))
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/phot/apradsetup.x b/noao/digiphot/apphot/phot/apradsetup.x
new file mode 100644
index 00000000..b7f47f41
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apradsetup.x
@@ -0,0 +1,126 @@
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+
+define HELPFILE "apphot$phot/iphot.key"
+
+# AP_RADSETUP -- Procedure to set up phot interactively using a radial profile
+# plot of a bright star.
+
+procedure ap_radsetup (ap, im, wx, wy, gd, out, stid)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to the IRAF image
+real wx, wy # cursor coordinates
+pointer gd # pointer to graphics stream
+int out # output file descriptor
+int stid # output file sequence number
+
+int cier, sier, pier, key, wcs
+pointer sp, cmd, str
+real xcenter, ycenter, xc, yc, rmin, rmax, imin, imax
+real u1, u2, v1, v2, x1, x2, y1, y2, rval
+
+int apfitcenter(), apfitsky(), ap_wmag(), apstati(), clgcur(), ap_showplot()
+real apstatr(), ap_cfwhmpsf(), ap_ccapert(), ap_cannulus(), ap_cdannulus()
+real ap_csigma(), ap_crgrow(), ap_crclean(), ap_crclip()
+real ap_cdatamin(), ap_cdatamax()
+
+begin
+ # Check for open graphics stream
+ if (gd == NULL)
+ return
+ call greactivate (gd, 0)
+ call gclear (gd)
+
+ # Store the viewport and window coordinates.
+ call ggview (gd, u1, u2, v1, v2)
+ call ggwind (gd, x1, x2, y1, y2)
+
+ # Make the plot.
+ if (ap_showplot (ap, im, wx, wy, gd, xcenter, ycenter, rmin, rmax,
+ imin, imax) == ERR) {
+ call gdeactivate (gd, 0)
+ return
+ }
+
+ # Initialize.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ call printf (
+ "Waiting for setup menu command (?=help, v=default setup, q=quit):\n")
+ while (clgcur ("gcommands", xc, yc, wcs, key, Memc[cmd],
+ SZ_LINE) != EOF) {
+
+ switch (key) {
+
+ case 'q':
+ break
+ case '?':
+ call gpagefile (gd, HELPFILE, "")
+ case 'f':
+ rval = ap_cfwhmpsf (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 's':
+ rval = ap_csigma (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'l':
+ rval = ap_cdatamin (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'u':
+ rval = ap_cdatamax (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'c':
+ rval = ap_ccapert (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'n':
+ rval = ap_crclean (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'p':
+ rval = ap_crclip (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'a':
+ rval = ap_cannulus (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'd':
+ rval = ap_cdannulus (ap, gd, out, stid, apstatr (ap, ANNULUS),
+ rmin, rmax, imin, imax)
+ case 'g':
+ rval = ap_crgrow (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'r':
+ call ap_caper (ap, gd, out, stid, Memc[str], rmin, rmax,
+ imin, imax)
+ case 'v':
+ rval = ap_cfwhmpsf (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_ccapert (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_csigma (ap, gd, out, stid, rmin, rmax, imin, imax)
+ #rval = ap_ccthresh (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_cannulus (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_cdannulus (ap, gd, out, stid, apstatr (ap, ANNULUS),
+ rmin, rmax, imin, imax)
+ call ap_caper (ap, gd, out, stid, Memc[str], rmin, rmax,
+ imin, imax)
+ default:
+ call printf ("Unknown or ambiguous keystroke command\007\n")
+ }
+ call printf (
+ "Waiting for setup menu command (?=help, v=default setup, q=quit):\n")
+ }
+ call printf (
+ "Interactive setup is complete. Type w to save parameters.\n")
+
+ # Restore the viewport and window coordinates.
+ call gsview (gd, u1, u2, v1, v2)
+ call gswind (gd, x1, x2, y1, y2)
+
+ call gdeactivate (gd, 0)
+ call sfree (sp)
+
+ # Compute and print the answer.
+ cier = apfitcenter (ap, im, xcenter, ycenter)
+ if (! IS_INDEFR (apstatr (ap, XCENTER)) &&
+ ! IS_INDEFR (apstatr (ap, YCENTER)))
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), NULL, gd)
+ if (! IS_INDEFR (apstatr (ap, SKY_MODE)))
+ pier = ap_wmag (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), apstati (ap, POSITIVE), apstatr (ap, SKY_MODE),
+ apstatr (ap, SKY_SIGMA), apstati (ap, NSKY))
+ call ap_pplot (ap, im, 0, gd, apstati (ap, RADPLOTS))
+ call ap_qpmag (ap, cier, sier, pier)
+end
diff --git a/noao/digiphot/apphot/phot/apremag.x b/noao/digiphot/apphot/phot/apremag.x
new file mode 100644
index 00000000..9cf705d4
--- /dev/null
+++ b/noao/digiphot/apphot/phot/apremag.x
@@ -0,0 +1,77 @@
+include <mach.h>
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/noisedef.h"
+include "../lib/photdef.h"
+include "../lib/phot.h"
+
+# APREMAG -- Procedure to recompute the magnitudes inside a set of apertures
+# given that the sums and effective areas have already been computed.
+
+int procedure apremag (ap, im, positive, skyval, skysig, nsky)
+
+pointer ap # pointer to the apphot structure
+pointer im # the input image descriptor
+int positive # emission and absorption features
+real skyval # sky value
+real skysig # sigma of sky
+int nsky # number of sky pixels
+
+int nap
+pointer nse, phot
+real zmag
+
+begin
+ # Initalize.
+ phot = AP_PPHOT(ap)
+ nse = AP_NOISE(ap)
+ call amovkr (INDEFR, Memr[AP_MAGS(phot)], AP_NAPERTS(phot))
+ call amovkr (INDEFR, Memr[AP_MAGERRS(phot)], AP_NAPERTS(phot))
+ if (IS_INDEFR(AP_PXCUR(phot)) || IS_INDEFR(AP_PYCUR(phot))) {
+ AP_OPXCUR(phot) = AP_PXCUR(phot)
+ AP_OPYCUR(phot) = AP_PYCUR(phot)
+ } else {
+ switch (AP_WCSOUT(ap)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (ap, AP_PXCUR(phot), AP_PYCUR(phot),
+ AP_OPXCUR(phot), AP_OPYCUR(phot), 1)
+ case WCS_TV:
+ call ap_ltov (im, AP_PXCUR(phot), AP_PYCUR(phot),
+ AP_OPXCUR(phot), AP_OPYCUR(phot), 1)
+ default:
+ AP_OPXCUR(phot) = AP_PXCUR(phot)
+ AP_OPYCUR(phot) = AP_PYCUR(phot)
+ }
+ }
+
+ # Check for errors.
+ if (IS_INDEFR(AP_PXCUR(phot)) || IS_INDEFR(AP_PYCUR(phot)))
+ return (AP_APERT_NOAPERT)
+ if (IS_INDEFR(skyval))
+ return (AP_APERT_NOSKYMODE)
+
+ nap = min (AP_NMINAP(phot) - 1, AP_NMAXAP(phot))
+
+ # Compute the magnitudes and errors.
+ if (positive == YES)
+ call apcopmags (Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)],
+ Memr[AP_MAGS(phot)], Memr[AP_MAGERRS(phot)], nap,
+ skyval, skysig, nsky, AP_ZMAG(phot), AP_NOISEFUNCTION(nse),
+ AP_EPADU(nse))
+ else
+ call apconmags (Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)],
+ Memr[AP_MAGS(phot)], Memr[AP_MAGERRS(phot)], nap,
+ skyval, skysig, nsky, AP_ZMAG(phot), AP_NOISEFUNCTION(nse),
+ AP_EPADU(nse), AP_READNOISE(nse))
+
+ # Correct for itime.
+ zmag = 2.5 * log10 (AP_ITIME(ap))
+ call aaddkr (Memr[AP_MAGS(phot)], zmag, Memr[AP_MAGS(phot)], nap)
+
+ if (AP_NMAXAP(phot) < AP_NAPERTS(phot))
+ return (AP_APERT_OUTOFBOUNDS)
+ else if (AP_NMINAP(phot) <= AP_NMAXAP(phot))
+ return (AP_APERT_BADDATA)
+ else
+ return (AP_OK)
+end
diff --git a/noao/digiphot/apphot/phot/iphot.key b/noao/digiphot/apphot/phot/iphot.key
new file mode 100644
index 00000000..679f2d50
--- /dev/null
+++ b/noao/digiphot/apphot/phot/iphot.key
@@ -0,0 +1,18 @@
+ Interactive Phot Setup Menu
+
+ v Mark and verify the critical parameters (f,s,c,a,d,r)
+
+ f Mark and verify the full-width half-maximum of psf
+ s Mark and verify the standard deviation of the background
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
+
+ c Mark and verify the centering box width
+ n Mark and verify the cleaning radius
+ p Mark and verify the clipping radius
+
+ a Mark and verify the inner radius of the sky annulus
+ d Mark and verify the width of the sky annulus
+ g Mark and verify the region growing radius
+
+ r Mark and verify the aperture radii
diff --git a/noao/digiphot/apphot/phot/iqphot.key b/noao/digiphot/apphot/phot/iqphot.key
new file mode 100644
index 00000000..426bd523
--- /dev/null
+++ b/noao/digiphot/apphot/phot/iqphot.key
@@ -0,0 +1,8 @@
+ Interactive Qphot Setup Menu
+
+ v Mark and verify the critical parameters (c,a,d,r)
+
+ c Mark and verify the centering box width
+ a Mark and verify the inner radius of the sky annulus
+ d Mark and verify the width of the sky annulus
+ r Mark and verify the aperture radii
diff --git a/noao/digiphot/apphot/phot/mkpkg b/noao/digiphot/apphot/phot/mkpkg
new file mode 100644
index 00000000..8ca684f8
--- /dev/null
+++ b/noao/digiphot/apphot/phot/mkpkg
@@ -0,0 +1,81 @@
+# PHOT,QPHOT tasks
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ # general photometry and PHOT task routines
+
+ apbphot.x <fset.h> ../lib/apphot.h \
+ ../lib/center.h ../lib/display.h \
+ ../lib/fitsky.h
+ apcomags.x <mach.h> ../lib/noise.h
+ apgppars.x ../lib/center.h ../lib/fitsky.h \
+ ../lib/phot.h ../lib/display.h \
+ ../lib/noise.h
+ apmag.x <mach.h> ../lib/apphotdef.h \
+ ../lib/noisedef.h ../lib/photdef.h \
+ ../lib/apphot.h ../lib/phot.h
+ apmagbuf.x <imhdr.h> ../lib/apphotdef.h \
+ ../lib/photdef.h ../lib/phot.h
+ apmeasure.x
+ apppars.x ../lib/display.h
+ appconfirm.x ../lib/apphot.h ../lib/noise.h \
+ ../lib/center.h ../lib/fitsky.h \
+ ../lib/phot.h
+ apperrors.x ../lib/phot.h
+ appfree.x ../lib/apphotdef.h ../lib/photdef.h
+ apphot.x <ctype.h> <gset.h> \
+ ../lib/apphot.h ../lib/display.h \
+ ../lib/center.h ../lib/fitsky.h \
+ ../lib/phot.h <imhdr.h>
+ apphotcolon.x ../lib/noise.h ../lib/apphot.h \
+ ../lib/display.h ../lib/fitsky.h \
+ ../lib/center.h ../lib/phot.h \
+ <gset.h>
+ appinit.x ../lib/apphotdef.h ../lib/photdef.h \
+ ../lib/phot.h
+ appplot.x <gset.h> <pkg/gtools.h> \
+ ../lib/apphot.h ../lib/noise.h \
+ ../lib/center.h ../lib/fitsky.h \
+ ../lib/phot.h
+ appmag.x ../lib/apphot.h ../lib/apphotdef.h \
+ ../lib/fitsky.h ../lib/center.h \
+ ../lib/photdef.h ../lib/phot.h
+ appshow.x ../lib/display.h ../lib/phot.h
+ apradsetup.x ../lib/fitsky.h ../lib/center.h \
+ ../lib/display.h ../lib/apphot.h
+ apremag.x <mach.h> ../lib/apphotdef.h \
+ ../lib/noisedef.h ../lib/photdef.h \
+ ../lib/apphot.h ../lib/phot.h
+ t_phot.x <fset.h> <gset.h> \
+ <lexnum.h> ../lib/apphot.h \
+ ../lib/fitsky.h <imhdr.h>
+
+ # QPHOT TASK SPECIFIC ROUTINES
+
+ apgqppars.x "../lib/apphot.h" "../lib/display.h" \
+ "../lib/noise.h" "../lib/center.h" \
+ "../lib/fitsky.h" "../lib/phot.h"
+ apqppars.x "../lib/apphot.h" "../lib/display.h" \
+ "../lib/noise.h" "../lib/center.h" \
+ "../lib/fitsky.h" "../lib/phot.h"
+ apqphot.x <ctype.h> <gset.h> \
+ "../lib/apphot.h" "../lib/display.h" \
+ "../lib/center.h" "../lib/fitsky.h" \
+ "../lib/phot.h" <imhdr.h>
+ apqradsetup.x "../lib/apphot.h" "../lib/display.h" \
+ "../lib/center.h" "../lib/fitsky.h"
+ apqcolon.x "../lib/apphot.h" "../lib/display.h" \
+ "../lib/noise.h" "../lib/center.h" \
+ "../lib/fitsky.h" "../lib/phot.h" \
+ <error.h>
+ apqshow.x "../lib/apphot.h" "../lib/display.h" \
+ "../lib/noise.h" "../lib/center.h" \
+ "../lib/fitsky.h" "../lib/phot.h"
+ t_qphot.x <fset.h> <gset.h> \
+ <lexnum.h> ../lib/apphot.h \
+ ../lib/fitsky.h <imhdr.h>
+ ;
diff --git a/noao/digiphot/apphot/phot/phot.key b/noao/digiphot/apphot/phot/phot.key
new file mode 100644
index 00000000..83e577fd
--- /dev/null
+++ b/noao/digiphot/apphot/phot/phot.key
@@ -0,0 +1,109 @@
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+v Verify the critical parameters
+w Save the current parameters
+d Plot radial profile of current star
+i Interactively set parameters using current star
+c Fit center for current star
+t Fit sky around cursor
+a Average sky values fit around several cursor positions
+s Fit sky around current centered star
+p Do photometry for current star, using current sky
+o Do photometry for current star, using current sky, output results
+f Do photometry for current star
+spbar Do photometry for current star, output results
+m Move to next star in coordinate list
+n Do photometry for next star in coordinate list, output results
+l Do photometry for remaining stars in coordinate list, output results
+e Print error messages
+r Rewind coordinate list
+q Exit task
+
+
+Photometry parameters are listed or set with the following commands.
+
+ Colon commands
+
+:show [data/center/sky/phot] List the parameters
+:m [n] Move to next [nth] star in coordinate list
+:n [n] Do photometry for next [nth] star in coordinate list, output results
+
+ Colon Parameter Editing Commands
+
+# Image and file name parameters
+
+:image [string] Image name
+:coords [string] Coordinate file name
+:output [string] Output file name
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Full width half maximum of PSF (scale units)
+:emission [y/n] Emission feature (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good data value (counts)
+:datamax [value] Maximum good data value (counts)
+
+# Noise parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per adu)
+:readnoise [value] Readout noise (electrons)
+
+# Observations parameters
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Integration time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observation (time units)
+
+# Centering algorithm parameters
+
+:calgorithm [string] Centering algorithm
+:cbox [value] Width of the centering box (scale units)
+:cthreshold [value] Centering intensity threshold (sigma)
+:cmaxiter [value] Maximum number of iterations
+:maxshift [value] Maximum center shift (scale units)
+:minsnratio [value] Minimum S/N ratio for centering
+:clean [y/n] Clean subraster before centering
+:rclean [value] Cleaning radius (scale units)
+:rclip [value] Clipping radius (scale units)
+:kclean [value] Clean K-sigma rejection limit (sigma)
+
+# Sky fitting algorithm parameters
+
+:salgorithm [string] Sky fitting algorithm
+:skyvalue [value] User supplied sky value (counts)
+:annulus [value] Inner radius of sky annulus (scale units)
+:dannulus [value] Width of sky annulus (scale units)
+:khist [value] Sky histogram extent (+/- sky sigma)
+:binsize [value] Resolution of sky histogram (sky sigma)
+:smooth [y/n] Lucy smooth the sky histogram
+:sloclip [value] Low-side clipping factor in percent
+:shiclip [value] High-side clipping factor in percent
+:smaxiter [value] Maximum number of iterations
+:snreject [value] Maximum number of rejection cycles
+:sloreject [value] Low-side pixel rejection limits (sky sigma)
+:shireject [value] High-side pixel rejection limits (sky sigma)
+:rgrow [value] Region growing radius (scale units)
+
+# Photometry parameters
+
+:apertures [string] List of aperture radii (scale units)
+:zmag [value] Zero point of magnitude scale
+
+# Plotting and marking parameters
+
+:mkcenter [y/n] Mark computed centers on display
+:mksky [y/n] Mark the sky annuli on the display
+:mkapert [y/n] Mark apertures on the display
+:radplot [y/n] Plot radial profile of object
diff --git a/noao/digiphot/apphot/phot/qphot.key b/noao/digiphot/apphot/phot/qphot.key
new file mode 100644
index 00000000..ff4dd5b7
--- /dev/null
+++ b/noao/digiphot/apphot/phot/qphot.key
@@ -0,0 +1,48 @@
+ Interactive Photometry Commands
+
+? Print help
+: Colon commands
+w Save the current parameters
+d Plot radial profile of current star
+i Interactively set parameters using current star
+c Fit center of current star
+t Fit sky around cursor
+a Average sky values fit around several cursor positions
+s Fit sky for current centered star
+p Do photometry for current star, using current sky
+o Do photometry for current star, using current sky, output results
+f Do photometry for current star
+spbar Do photometry for current star, output results
+e Print error messages
+m Move to next star in coordinate list
+n Do photometry for next star in coordinate list, output results
+l Do photometry for remaining stars in coordinate list, output results
+r Rewind the coordinate list
+q Exit task
+
+
+ Colon Commands
+
+:show List the parameters
+:m [n] Move to next [nth] star in coordinate list
+:n [n] Do photometry for next [nth] star in coordinate list, output results
+
+ Colon Parameter Editing Commands
+
+:image [string] Image name
+:output [string] Output file name
+:coords [string] Coords file name
+
+:cbox [value] Width of the centering box (pixels)
+:annulus [value] Inner radius of sky annulus (pixels)
+:dannulus [value] Width of sky annulus (pixels)
+:apertures [string] List of aperture radii (pixels)
+:zmag [value] Zero point of magnitude scale (magnitudes)
+:epadu [value] Gain (electrons per adu)
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+
+:radplot [y/n] Plot radial profile of object
diff --git a/noao/digiphot/apphot/phot/t_phot.x b/noao/digiphot/apphot/phot/t_phot.x
new file mode 100644
index 00000000..9d35c994
--- /dev/null
+++ b/noao/digiphot/apphot/phot/t_phot.x
@@ -0,0 +1,341 @@
+include <fset.h>
+include <gset.h>
+include <lexnum.h>
+include <imhdr.h>
+include "../lib/apphot.h"
+include "../lib/fitsky.h"
+
+# T_PHOT -- Procedure to measure magnitudes inside a set of apertures for a list
+# of stars in a list of images.
+
+procedure t_phot ()
+
+pointer image # pointer name of the image
+pointer output # pointer output file name
+pointer coords # pointer to name of coords file
+pointer skyfile # pointer to name of file with sky values
+pointer plotfile # file of plot metacode
+pointer graphics # graphics display device
+pointer display # display device
+int interactive # mode of use
+int cache # cache the input image pixels in memory
+int verify # verify critical parameters in batch mode
+int update # update the critical parameters
+int verbose # type messages on the terminal
+
+pointer sp, cname, outfname, str, ap, im, gd, mgd, id
+int limlist, lclist, lolist, lslist, sid, lid, sd, out, cl, root, stat, pfd
+int imlist, clist, olist, slist, memstat, old_size, wcs, req_size
+int buf_size
+
+pointer immap(), gopen()
+int imtlen(), imtgetim(), clplen(), clgfil(), btoi(), apstati(), strncmp()
+int fnldir(), strlen(), apphot(), imtopenp(), clpopnu(), open(), clgwrd()
+int ap_memstat(), sizeof()
+bool clgetb(), streq()
+errchk gopen
+
+begin
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (coords, SZ_FNAME, TY_CHAR)
+ call salloc (skyfile, SZ_FNAME, TY_CHAR)
+ call salloc (plotfile, SZ_FNAME, TY_CHAR)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+ call salloc (display, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (cname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Set the standard output to flush on newline.
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get the task parameters.
+ imlist = imtopenp ("image")
+ limlist = imtlen (imlist)
+ clist = clpopnu ("coords")
+ lclist = clplen (clist)
+ olist = clpopnu ("output")
+ lolist = clplen (olist)
+
+ # Check that image and coordinate list lengths match.
+ if (limlist < 1 || (lclist > 1 && lclist != limlist)) {
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+ call error (0, "Imcompatible image and coordinate list lengths")
+ }
+
+ # Check that image and output list lengths match.
+ if (lolist > 1 && lolist != limlist) {
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+ call error (0, "Imcompatible image and output list lengths")
+ }
+
+ call clgstr ("icommands.p_filename", Memc[cname], SZ_FNAME)
+ if (Memc[cname] != EOS)
+ interactive = NO
+ #else if (lclist == 0)
+ #interactive = YES
+ else
+ interactive = btoi (clgetb ("interactive"))
+ cache = btoi (clgetb ("cache"))
+ verbose = btoi (clgetb ("verbose"))
+ verify = btoi (clgetb ("verify"))
+ update = btoi (clgetb ("update"))
+
+ # Get the graphics and display devices.
+ call clgstr ("graphics", Memc[graphics], SZ_FNAME)
+ call clgstr ("display", Memc[display], SZ_FNAME)
+
+ # Open the graphics and display devices.
+ if (interactive == YES) {
+ if (Memc[graphics] == EOS)
+ gd = NULL
+ else {
+ iferr {
+ gd = gopen (Memc[graphics], APPEND+AW_DEFER, STDGRAPH)
+ } then {
+ call eprintf (
+ "Warning: Error opening graphics device.\n")
+ gd = NULL
+ }
+ }
+ if (Memc[display] == EOS)
+ id = NULL
+ else if (streq (Memc[graphics], Memc[display]))
+ id = gd
+ else {
+ iferr {
+ id = gopen (Memc[display], APPEND, STDIMAGE)
+ } then {
+ call eprintf (
+ "Warning: Graphics overlay not available for display device.\n")
+ id = NULL
+ }
+ }
+ } else {
+ gd = NULL
+ id = NULL
+ }
+
+ # Open the plot metacode file.
+ call clgstr ("plotfile", Memc[plotfile], SZ_FNAME)
+ if (Memc[plotfile] == EOS)
+ pfd = NULL
+ else
+ pfd = open (Memc[plotfile], APPEND, BINARY_FILE)
+ if (pfd != NULL)
+ mgd = gopen (Memc[graphics], NEW_FILE, pfd)
+ else
+ mgd = NULL
+
+ # Intialize the phot structure.
+ call ap_gppars (ap)
+
+ # Confirm the algorithm parameters.
+ if (verify == YES && interactive == NO) {
+ call ap_pconfirm (ap, NULL, 1)
+ if (update == YES)
+ call ap_ppars (ap)
+ }
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_LINE, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (ap, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_LINE, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (ap, WCSOUT, wcs)
+
+ # Get the file name for the sky values.
+ if (apstati (ap, SKYFUNCTION) == AP_SKYFILE) {
+ slist = clpopnu ("skyfile")
+ lslist = clplen (slist)
+ if (limlist < 1 || (lslist > 1 && lslist != limlist)) {
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+ call clpcls (slist)
+ call error (0, "Imcompatible image and sky file list lengths")
+ }
+ } else
+ sd = NULL
+
+ # Begin looping over the image list.
+ sid = 1
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open the image and store image parameters.
+ im = immap (Memc[image], READ_ONLY, 0)
+ call apimkeys (ap, im, Memc[image])
+
+ # Set the image display viewport.
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[image], im, 4)
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+
+ # Open the coordinate file, where coords is assumed to be a simple
+ # text file in which the x and y positions are in columns 1 and 2
+ # respectively and all remaining fields are ignored.
+
+ if (lclist <= 0) {
+ cl = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (clist, Memc[coords], SZ_FNAME)
+ root = fnldir (Memc[coords], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[coords+root], 7) == 0 || root ==
+ strlen (Memc[coords])) {
+ call ap_inname (Memc[image], Memc[outfname], "coo",
+ Memc[outfname], SZ_FNAME)
+ lclist = limlist
+ cl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else if (stat != EOF) {
+ call strcpy (Memc[coords], Memc[outfname], SZ_FNAME)
+ cl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else {
+ call apstats (ap, CLNAME, Memc[outfname], SZ_FNAME)
+ call seek (cl, BOF)
+ }
+ }
+ call apsets (ap, CLNAME, Memc[outfname])
+ call apfroot (Memc[outfname], Memc[str], SZ_LINE)
+ call apsets (ap, CLROOT, Memc[str])
+
+ # Open the skys file.
+ if (lslist <= 0) {
+ sd = NULL
+ call strcpy ("", Memc[skyfile], SZ_FNAME)
+ } else if (clgfil (slist, Memc[skyfile], SZ_FNAME) != EOF)
+ sd = open (Memc[skyfile], READ_ONLY, TEXT_FILE)
+ else
+ call seek (sd, BOF)
+ #call apsets (ap, SKYNAME, Memc[skyfile])
+
+ # Open the output text file, if output is "default", dir$default or
+ # a directory specification then the extension "mag" is added to the
+ # image name and a suitable version number is appended to the output
+ # name. If output is the null string then no output file is created.
+
+ if (lolist == 0) {
+ out = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (olist, Memc[output], SZ_FNAME)
+ root = fnldir (Memc[output], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[output+root], 7) == 0 || root ==
+ strlen (Memc[output])) {
+ call apoutname (Memc[image], Memc[outfname], "mag",
+ Memc[outfname], SZ_FNAME)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ lolist = limlist
+ } else if (stat != EOF) {
+ call strcpy (Memc[output], Memc[outfname], SZ_FNAME)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ } else
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ }
+ call apsets (ap, OUTNAME, Memc[outfname])
+
+ # Do aperture photometry.
+ if (interactive == NO) {
+ if (Memc[cname] != EOS)
+ stat = apphot (ap, im, cl, sd, NULL, mgd, NULL, out, sid,
+ NO, cache)
+ else if (cl != NULL) {
+ lid = 1
+ call apbphot (ap, im, cl, sd, out, sid, lid, gd, mgd, id,
+ verbose)
+ stat = NO
+ } else
+ stat = NO
+ } else
+ stat = apphot (ap, im, cl, sd, gd, mgd, id, out, sid, YES,
+ cache)
+
+ # Cleanup.
+ call imunmap (im)
+ if (cl != NULL) {
+ if (clplen(clist) > 1)
+ call close (cl)
+ }
+ if (sd != NULL) {
+ if (lslist > 1)
+ call close (sd)
+ }
+ if (out != NULL && lolist != 1) {
+ call close (out)
+ if (sid <= 1) {
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ call delete (Memc[outfname])
+ }
+ sid = 1
+ }
+
+ # Uncache memory.
+ call fixmem (old_size)
+
+ if (stat == YES)
+ break
+ }
+
+
+ # Close the coordinate, sky and output files.
+ if (cl != NULL && lclist == 1)
+ call close (cl)
+ if (sd != NULL && lslist == 1)
+ call close (sd)
+ if (out != NULL && lolist == 1) {
+ call close (out)
+ if (sid <= 1) {
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ call delete (Memc[outfname])
+ }
+ }
+
+ # Close up the plot files.
+ if (id == gd && id != NULL)
+ call gclose (id)
+ else {
+ if (gd != NULL)
+ call gclose (gd)
+ if (id != NULL)
+ call gclose (id)
+ }
+ if (mgd != NULL)
+ call gclose (mgd)
+ if (pfd != NULL)
+ call close (pfd)
+
+ # Free the apphot data structures.
+ call appfree (ap)
+
+ # Close the coord, sky and image lists.
+ call imtclose (imlist)
+ call clpcls (clist)
+ if (sd != NULL)
+ call clpcls (slist)
+ call clpcls (olist)
+
+ # Free working space.
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/phot/t_qphot.x b/noao/digiphot/apphot/phot/t_qphot.x
new file mode 100644
index 00000000..91174e78
--- /dev/null
+++ b/noao/digiphot/apphot/phot/t_qphot.x
@@ -0,0 +1,293 @@
+include <fset.h>
+include <gset.h>
+include <lexnum.h>
+include <imhdr.h>
+include "../lib/apphot.h"
+include "../lib/fitsky.h"
+
+# T_QPHOT -- Procedure to measure magnitudes inside a set of apertures for a
+# list of stars in a list of images.
+
+procedure t_qphot ()
+
+pointer image # pointer name of the image
+pointer output # pointer output file name
+pointer coords # pointer to the coordinate file
+pointer plotfile # file of plot metacode
+pointer graphics # graphics display device
+pointer display # display device
+int cache # cache input image pixels in memory
+int verbose # verbose mode
+
+pointer sp, outfname, cname, ap, im, gd, mgd, id, str
+int limlist, lclist, lolist, cl, sid, lid, out, root, stat, pfd, interactive
+int imlist, olist, clist, memstat, wcs, req_size, old_size, buf_size
+
+pointer immap(), gopen()
+int imtlen(), imtgetim(), clplen(), clgfil(), btoi(), strncmp()
+int fnldir(), strlen(), apqphot(), imtopenp(), clpopnu(), open()
+int clgwrd(), ap_memstat(), sizeof()
+bool clgetb(), streq()
+errchk gopen
+
+begin
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (coords, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (plotfile, SZ_FNAME, TY_CHAR)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+ call salloc (display, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (cname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Set the standard output to flush on newline.
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get the task parameters.
+ imlist = imtopenp ("image")
+ limlist = imtlen (imlist)
+ clist = clpopnu ("coords")
+ lclist = clplen (clist)
+ olist = clpopnu ("output")
+ lolist = clplen (olist)
+
+ # Check that image and coordinate list lengths match.
+ if (limlist < 1 || (lclist > 1 && lclist != limlist)) {
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+ call error (0, "Imcompatible image and coordinate list lengths")
+ }
+
+ # Check that image and output list lengths match.
+ if (lolist > 1 && lolist != limlist) {
+ call imtclose (imlist)
+ call clpcls (olist)
+ call error (0, "Imcompatible image and output list lengths")
+ }
+
+ # Intialize the phot structure.
+ call clgstr ("icommands.p_filename", Memc[cname], SZ_FNAME)
+ if (Memc[cname] != EOS)
+ interactive = NO
+ #else if (lclist == 0)
+ #interactive = YES
+ else
+ interactive = btoi (clgetb ("interactive"))
+ cache = btoi (clgetb ("cache"))
+ verbose = btoi (clgetb ("verbose"))
+
+ # Get the parameters.
+ call ap_gqppars (ap)
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_LINE, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (ap, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_LINE, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (ap, WCSOUT, wcs)
+
+ # Get the graphics and display devices.
+ call clgstr ("graphics", Memc[graphics], SZ_FNAME)
+ call clgstr ("display", Memc[display], SZ_FNAME)
+
+ # Open the plot files.
+ if (interactive == YES) {
+ if (Memc[graphics] == EOS)
+ gd = NULL
+ else {
+ iferr {
+ gd = gopen (Memc[graphics], APPEND+AW_DEFER, STDGRAPH)
+ } then {
+ call eprintf (
+ "Warning: Error opening graphics device.\n")
+ gd = NULL
+ }
+ }
+ if (Memc[display] == EOS)
+ id = NULL
+ else if (streq (Memc[graphics], Memc[display]))
+ id = gd
+ else {
+ iferr {
+ id = gopen (Memc[display], APPEND, STDIMAGE)
+ } then {
+ call eprintf (
+ "Warning: Graphics overlay not available for display device.\n")
+ id = NULL
+ }
+ }
+ } else {
+ gd = NULL
+ id = NULL
+ }
+
+ # Open the plot metacode file.
+ call clgstr ("plotfile", Memc[plotfile], SZ_FNAME)
+ if (Memc[plotfile] == EOS)
+ pfd = NULL
+ else
+ pfd = open (Memc[plotfile], APPEND, BINARY_FILE)
+ if (pfd != NULL)
+ mgd = gopen (Memc[graphics], NEW_FILE, pfd)
+ else
+ mgd = NULL
+
+ # Begin looping over the image list.
+ sid = 1
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open the image and store image parameters.
+ im = immap (Memc[image], READ_ONLY, 0)
+ call apimkeys (ap, im, Memc[image])
+
+ # Set the image display viewport.
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[image], im, 4)
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+
+ # Open the coordinate file, where coords is assumed to be a simple
+ # text file in which the x and y positions are in columns 1 and 2
+ # respectively and all remaining fields are ignored.
+
+ if (lclist <= 0) {
+ cl = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (clist, Memc[coords], SZ_FNAME)
+ root = fnldir (Memc[coords], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[coords+root], 7) == 0 || root ==
+ strlen (Memc[coords])) {
+ call ap_inname (Memc[image], Memc[outfname], "coo",
+ Memc[outfname], SZ_FNAME)
+ lclist = limlist
+ cl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else if (stat != EOF) {
+ call strcpy (Memc[coords], Memc[outfname], SZ_FNAME)
+ cl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else {
+ call apstats (ap, CLNAME, Memc[outfname], SZ_FNAME)
+ call seek (cl, BOF)
+ }
+ }
+ call apsets (ap, CLNAME, Memc[outfname])
+ call apfroot (Memc[outfname], Memc[str], SZ_FNAME)
+ call apsets (ap, CLROOT, Memc[str])
+
+ # Open the output text file, if output is "default", dir$default or
+ # a directory specification then the extension "mag" is added to the
+ # image name and a suitable version number is appended to the output
+ # name. If output is the null string then no output file is created.
+
+ if (lolist == 0) {
+ out = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (olist, Memc[output], SZ_FNAME)
+ root = fnldir (Memc[output], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[output+root], 7) == 0 || root ==
+ strlen (Memc[output])) {
+ call apoutname (Memc[image], Memc[outfname], "mag",
+ Memc[outfname], SZ_FNAME)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ lolist = limlist
+ } else if (stat != EOF) {
+ call strcpy (Memc[output], Memc[outfname], SZ_FNAME)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ } else
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ }
+ call apsets (ap, OUTNAME, Memc[outfname])
+
+ # Do aperture photometry.
+ if (interactive == NO) {
+ if (Memc[cname] != EOS)
+ stat = apqphot (ap, im, cl, NULL, mgd, NULL, out, sid, NO,
+ cache)
+ else if (cl != NULL) {
+ lid = 1
+ call apbphot (ap, im, cl, NULL, out, sid, lid, gd, mgd, id,
+ verbose)
+ stat = NO
+ } else
+ stat = NO
+ } else
+ stat = apqphot (ap, im, cl, gd, mgd, id, out, sid, YES, cache)
+
+ # Cleanup.
+ call imunmap (im)
+ if (cl != NULL) {
+ if (lclist > 1)
+ call close (cl)
+ }
+ if (out != NULL && lolist != 1) {
+ call close (out)
+ if (sid <= 1) {
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ call delete (Memc[outfname])
+ }
+ sid = 1
+ }
+
+ # Uncache memory.
+ call fixmem (old_size)
+
+ if (stat == YES)
+ break
+ }
+
+
+ # Close the coordinate, sky and output files.
+ if (cl != NULL && lclist == 1)
+ call close (cl)
+ if (out != NULL && lolist == 1) {
+ call close (out)
+ if (sid <= 1) {
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ call delete (Memc[outfname])
+ }
+ }
+
+ # Close up the plot files.
+ if (id == gd && id != NULL)
+ call gclose (id)
+ else {
+ if (gd != NULL)
+ call gclose (gd)
+ if (id != NULL)
+ call gclose (id)
+ }
+ if (mgd != NULL)
+ call gclose (mgd)
+ if (pfd != NULL)
+ call close (pfd)
+
+ # Free the apphot data structure.
+ call appfree (ap)
+
+ # Close the coord, sky and image lists.
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+
+ # Free working space.
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/photpars.par b/noao/digiphot/apphot/photpars.par
new file mode 100644
index 00000000..87c7ac9e
--- /dev/null
+++ b/noao/digiphot/apphot/photpars.par
@@ -0,0 +1,7 @@
+# PHOTPARS Parameter File
+
+weighting,s,h,constant,"|constant|cone|gauss|",,Photometric weighting scheme for wphot
+apertures,s,h,"3.",,,List of aperture radii in scale units
+zmag,r,h,25.,,,Zero point of magnitude scale
+mkapert,b,h,no,,,Draw apertures on the display
+mode,s,h,'ql'
diff --git a/noao/digiphot/apphot/polymark.par b/noao/digiphot/apphot/polymark.par
new file mode 100644
index 00000000..6bf303e3
--- /dev/null
+++ b/noao/digiphot/apphot/polymark.par
@@ -0,0 +1,13 @@
+# POLYMARK
+
+image,f,a,,,,"The input image(s)"
+coords,f,h,"default",,,"The output coordinate file(s) (default: image.coo.?)"
+polygons,f,h,"default",,,"The output polygons file(s) (default: image.ver.?)"
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor: [x y wcs] key [cmd]"
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the input image pixels ?"
+graphics,s,h,)_.graphics,,,"Graphics device"
+display,s,h,)_.display,,,"Display device"
+mode,s,h,'ql'
diff --git a/noao/digiphot/apphot/polypars.par b/noao/digiphot/apphot/polypars.par
new file mode 100644
index 00000000..8b6aac6a
--- /dev/null
+++ b/noao/digiphot/apphot/polypars.par
@@ -0,0 +1,4 @@
+# Polyphot photometry parameters
+
+zmag,r,h,25.0,,,Zero point of magnitude scale
+mkpolygon,b,h,no,,,Draw polygon on the image display
diff --git a/noao/digiphot/apphot/polyphot.par b/noao/digiphot/apphot/polyphot.par
new file mode 100644
index 00000000..aefdf6b9
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot.par
@@ -0,0 +1,22 @@
+# POLYPHOT
+
+image,f,a,,,,"The input image(s)"
+polygons,f,h,"",,,"The input polygons file(s) (default: image.ver.?)"
+coords,f,h,"",,,"The input coordinates file(s) (default: image.coo.?)"
+output,f,h,"default",,,"The output photometry file(s) (default: image.mag.?)"
+datapars,pset,h,"",,,"Data dependent parameters"
+centerpars,pset,h,"",,,"Centering parameters"
+fitskypars,pset,h,"",,,"Sky fitting parameters"
+polypars,pset,h,"",,,"Photometry parameters"
+interactive,b,h,yes,,,"Interactive mode ?"
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor: [x y wcs] key [cmd]"
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the input image pixels in memory ?"
+verify,b,h,)_.verify,,,"Verify critical parameters in non-interactive mode ?"
+update,b,h,)_.update,,,"Update critical parameters in non-interactive mode ?"
+verbose,b,h,)_.verbose,,,"Print messages in non-interactive mode ?"
+graphics,s,h,)_.graphics,,,"Graphics device"
+display,s,h,)_.display,,,"Display device"
+mode,s,h,'ql'
diff --git a/noao/digiphot/apphot/polyphot/apgypars.x b/noao/digiphot/apphot/polyphot/apgypars.x
new file mode 100644
index 00000000..960f9cbc
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apgypars.x
@@ -0,0 +1,29 @@
+include "../lib/display.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/polyphot.h"
+
+# AP_GYPARS -- Procedure to fetch the polyphot task parameters.
+
+procedure ap_gypars (ap)
+
+pointer ap # pointer to apphot fitting structure
+
+begin
+ # Open the apphot strucuture.
+ call apyinit (ap, AP_CENTROID1D, 2.5, AP_MODE, 10.0, 10.0, 2.0,
+ AP_NPOISSON)
+
+ # Get the data dependent parameters.
+ call ap_gdapars (ap)
+
+ # Get the centering algorithm parameters.
+ call ap_gcepars (ap)
+
+ # Get the sky fitting parameters.
+ call ap_gsapars (ap)
+
+ # Get the photometry parameters.
+ call ap_gpopars (ap)
+end
diff --git a/noao/digiphot/apphot/polyphot/apmkpylist.x b/noao/digiphot/apphot/polyphot/apmkpylist.x
new file mode 100644
index 00000000..6b9d1ea0
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apmkpylist.x
@@ -0,0 +1,279 @@
+include <ctype.h>
+include <gset.h>
+include "../lib/apphot.h"
+include "../lib/polyphot.h"
+
+define HELPFILE "apphot$polyphot/polymark.key"
+
+# AP_MKPYLIST -- Procedure to make polygon and accompanying coordinate list.
+
+int procedure ap_mkpylist (im, py, pl, cl, id, gd, pid, cid)
+
+pointer im # pointer to IRAF image
+pointer py # pointer to the POLYPHOT structure
+int pl # starlist file descriptor
+int cl # coordinate file list
+pointer id # pointer to image display stream
+pointer gd # pointer to graphics display stream
+int pid # polygon id sequence number
+int cid # coordinate list sequence number
+
+int key, nvertices, wcs, ptid, ltid, prev_num, req_num
+int ip, colonkey, firstpoly, newpoly, delim
+pointer sp, cmd, x, y, xshift, yshift
+real wx, wy, xmean, ymean
+
+int clgcur(), apgqverify(), apgtverify(), ap_ymkpoly(), ctoi()
+int ap_ynextobj()
+real apstatr()
+data delim /';'/
+
+define endswitch_ 99
+
+begin
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (x, MAX_NVERTICES + 1, TY_REAL)
+ call salloc (y, MAX_NVERTICES + 1, TY_REAL)
+ call salloc (xshift, MAX_NVERTICES + 1, TY_REAL)
+ call salloc (yshift, MAX_NVERTICES + 1, TY_REAL)
+
+ # Initialize the cursor read.
+ key = ' '
+ Memc[cmd] = EOS
+
+ # Initialize the sequencing.
+ firstpoly = YES
+ newpoly = NO
+ ptid = 0
+ ltid = 0
+ xmean = INDEFR
+ ymean = INDEFR
+
+ # Loop over the polygon file.
+ nvertices = 0
+ while (clgcur ("icommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+
+ # Set the current cursor coordinates.
+ call ap_vtol (im, wx, wy, wx, wy, 1)
+ call apsetr (py, CWX, wx)
+ call apsetr (py, CWY, wy)
+
+ # Loop over the colon commands.
+ switch (key) {
+
+ # Quit.
+ case 'q':
+ if (apgqverify ("polymark", NULL, key) == YES) {
+ call sfree (sp)
+ return (apgtverify (key))
+ }
+
+ # Plot a centered stellar radial profile.
+ case 'd':
+ call ap_qrad (py, im, wx, wy, gd)
+
+ # Print the help page.
+ case '?':
+ if ((id != NULL) && (id == gd))
+ call gpagefile (id, HELPFILE, "")
+ else
+ call pagefile (HELPFILE, "[space=morehelp,q=quit,?=help]")
+
+ # Colon escape commands.
+ case ':':
+ for (ip = 1; IS_WHITE(Memc[cmd+ip-1]); ip = ip + 1)
+ ;
+ colonkey = Memc[cmd+ip-1]
+
+ switch (colonkey) {
+ case 'm':
+
+ # Decode a polymark colon command.
+ if (Memc[cmd+ip] != EOS && Memc[cmd+ip] != ' ') {
+ call printf (
+ "Unknown or ambigous keystroke command\n")
+ goto endswitch_
+ }
+
+ # The polygon file is undefined.
+ if (pl == NULL) {
+ call printf ("The polygon list is undefined\n")
+ goto endswitch_
+ }
+
+ # Read the next polygon.
+ ip = ip + 1
+ prev_num = ltid
+ if (ctoi (Memc[cmd], ip, req_num) <= 0)
+ req_num = ltid + 1
+ nvertices = ap_ynextobj (py, im, id, pl, cl, delim,
+ Memr[xshift], Memr[yshift], MAX_NVERTICES, prev_num,
+ req_num, ltid, ptid)
+ if (nvertices == EOF) {
+ call printf (
+ "End of polygon list, use r key to rewind\n")
+ goto endswitch_
+ }
+
+ # The polygon is undefined.
+ if (nvertices < 3) {
+ call printf ("The polygon has fewer than 3 vertices\n")
+ goto endswitch_
+ }
+
+ # Mark the polygon.
+ if (id != NULL) {
+ call appymark (py, id, Memr[xshift], Memr[yshift],
+ nvertices + 1, NO, NO, YES)
+ if (gd == id)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ default:
+ call printf ("Unknown or ambigous keystroke command\n")
+ }
+
+ # Draw the next polygon in the list.
+ case 'm':
+
+ # No polygon file.
+ if (pl == NULL) {
+ call printf ("The polygon list is undefined\n")
+ goto endswitch_
+ }
+
+ # Read the next polygon.
+ prev_num = ltid
+ req_num = ltid + 1
+ nvertices = ap_ynextobj (py, im, id, pl, cl, delim,
+ Memr[xshift], Memr[yshift], MAX_NVERTICES, prev_num,
+ req_num, ltid, ptid)
+
+ # The polygon is undefined.
+ if (nvertices == EOF) {
+ call printf ("End of polygon list, use r key to rewind\n")
+ goto endswitch_
+ }
+
+ # The polygon is ill-defined.
+ if (nvertices < 3) {
+ call printf ("The polygon has fewer than 3 vertices\n")
+ goto endswitch_
+ }
+
+ # Mark the polygon.
+ if (id != NULL) {
+ call appymark (py, id, Memr[xshift], Memr[yshift],
+ nvertices + 1, NO, NO, YES)
+ if (gd == id)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ # Rewind the polygon and coordinate lists.
+ case 'r':
+ if (pl != NULL) {
+ call seek (pl, BOF)
+ if (cl != NULL)
+ call seek (cl, BOF)
+ ptid = 0
+ ltid = 0
+ } else
+ call printf ("The polygon list is undefined\n")
+
+ # Draw the remaining polygons on the display.
+ case 'l':
+ if (pl == NULL) {
+ call printf ("The polygon list is undefined\n")
+ } else if (id != NULL) {
+ call ap_ydraw (py, im, cl, pl, ltid, ptid, id)
+ if (gd == id)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ # Define the polygon interactively.
+ case 'g':
+ if (gd == id)
+ nvertices = ap_ymkpoly (py, im, id, Memr[x], Memr[y],
+ MAX_NVERTICES, NO)
+ else
+ nvertices = ap_ymkpoly (py, im, id, Memr[x], Memr[y],
+ MAX_NVERTICES, YES)
+ xmean = apstatr (py, PYXMEAN)
+ ymean = apstatr (py, PYYMEAN)
+ if (nvertices == EOF) {
+ newpoly = NO
+ call printf ("The polygon is undefined\n")
+ } else if (nvertices <= 2) {
+ newpoly = NO
+ call printf (
+ "The polygon has fewer then 3 vertices\n")
+ } else {
+ newpoly = YES
+ if (id != NULL) {
+ if (gd == id)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ }
+
+ # Mark the current polygon on the display.
+ case 'f':
+ if (id != NULL) {
+ if (! IS_INDEFR(xmean) && ! IS_INDEFR(ymean)) {
+ call aaddkr (Memr[x], wx - xmean, Memr[xshift],
+ nvertices + 1)
+ call aaddkr (Memr[y], wy - ymean, Memr[yshift],
+ nvertices + 1)
+ call appymark (py, id, Memr[xshift], Memr[yshift],
+ nvertices + 1, NO, NO, YES)
+ if (gd == id)
+ call gflush (id)
+ else
+ call gframe (id)
+ } else
+ call printf ("The polygon is undefined\n")
+ }
+
+
+ # Mark the current polygon on the display and write to file.
+ case ' ':
+ if (! IS_INDEFR(xmean) && ! IS_INDEFR(ymean)) {
+ call ap_ywrite (py, im, cl, pl, Memr[x], Memr[y], nvertices,
+ cid, pid, firstpoly, newpoly)
+ if (id != NULL) {
+ call aaddkr (Memr[x], wx - xmean, Memr[xshift],
+ nvertices + 1)
+ call aaddkr (Memr[y], wy - ymean, Memr[yshift],
+ nvertices + 1)
+ call appymark (py, id, Memr[xshift], Memr[yshift],
+ nvertices + 1, NO, NO, YES)
+ if (gd == id)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ } else
+ call printf ("The polygon is undefined\n")
+
+ default:
+ call printf ("Unknown or ambigous keystroke command\n")
+ }
+
+endswitch_
+ # Reset the keystroke and command defaults.
+ call apsetr (py, WX, apstatr (py, CWX))
+ call apsetr (py, WY, apstatr (py, CWY))
+ key = ' '
+ Memc[cmd] = EOS
+ }
+end
diff --git a/noao/digiphot/apphot/polyphot/appyerrors.x b/noao/digiphot/apphot/polyphot/appyerrors.x
new file mode 100644
index 00000000..96a7bc93
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/appyerrors.x
@@ -0,0 +1,35 @@
+include "../lib/polyphot.h"
+
+# AP_PYERRORS -- Procedure to print out polyphot error messages when the
+# task is run in interactive mode.
+
+procedure ap_pyerrors (ap, cier, sier, pier)
+
+pointer ap # apphot structure
+int cier # centering error code
+int sier # sky fitting error code
+int pier # polyphot error code
+
+begin
+ # Print centering errors.
+ call ap_cerrors (ap, cier)
+
+ # Print sky fitting errors.
+ call ap_serrors (ap, sier)
+
+ # Print the polyphot errors.
+ switch (pier) {
+ case PY_NOPOLYGON:
+ call printf ("The polygon is undefined or too few vertices.\n")
+ case PY_OUTOFBOUNDS:
+ call printf ("The polygon is partially outside the image.\n")
+ case PY_NOPIX:
+ call printf ("The effective polygon area is 0.0.\n")
+ case PY_NOSKYMODE:
+ call printf ("The sky value is undefined.\n")
+ case PY_BADDATA:
+ call printf ("Bad pixels inside the polygon.\n")
+ default:
+ call printf ("")
+ }
+end
diff --git a/noao/digiphot/apphot/polyphot/apybphot.x b/noao/digiphot/apphot/polyphot/apybphot.x
new file mode 100644
index 00000000..8a4783e8
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apybphot.x
@@ -0,0 +1,94 @@
+include <fset.h>
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/fitsky.h"
+include "../lib/polyphot.h"
+
+# AP_YBPHOT -- Measure the flux inside a list of polygons.
+
+procedure ap_ybphot (py, im, cl, pl, out, id, ld, pd, gid, interactive)
+
+pointer py # pointer to apphot structure
+pointer im # pointer to IRAF image
+int cl # coordinates file descriptor
+int pl # vertices list file descriptor
+int out # output file descriptor
+int id # output file sequence number
+int ld # coordinate list number
+int pd # polygon list number
+pointer gid # pointer to image display stream
+int interactive # interactive or batch mode
+
+real apstatr()
+pointer sp, x, y, xout, yout
+int req_num, prev_num, cier, sier, pier, nvertices, delim
+int ap_ynextobj(), ap_ycenter(), apfitsky(), ap_yfit(), apstati()
+data delim /';'/
+
+begin
+ # Allocate temporary space for arrays.
+ call smark (sp)
+ call salloc (x, MAX_NVERTICES + 1, TY_REAL)
+ call salloc (y, MAX_NVERTICES + 1, TY_REAL)
+ call salloc (xout, MAX_NVERTICES + 1, TY_REAL)
+ call salloc (yout, MAX_NVERTICES + 1, TY_REAL)
+
+ # Initialize
+ if (pl != NULL)
+ call seek (pl, BOF)
+ if (cl != NULL)
+ call seek (cl, BOF)
+
+ # Get the first polygon.
+ pd = 0
+ prev_num = 0
+ req_num = ld + 1
+ nvertices = ap_ynextobj (py, im, gid, pl, cl, delim, Memr[x], Memr[y],
+ MAX_NVERTICES, prev_num, req_num, ld, pd)
+
+ while (nvertices != EOF) {
+
+ # Fit the center, sky and measure the polygon.
+ cier = ap_ycenter (py, im, apstatr (py, PYCX), apstatr (py, PYCY),
+ Memr[x], Memr[y], nvertices + 1)
+ sier = apfitsky (py, im, apstatr (py, PYCX), apstatr (py,
+ PYCY), NULL, NULL)
+ pier = ap_yfit (py, im, Memr[x], Memr[y],
+ nvertices + 1, apstatr (py, SKY_MODE), apstatr (py,
+ SKY_SIGMA), apstati (py, NSKY))
+
+ # Write the output to the standard output.
+ if (interactive == YES) {
+ call ap_qyprint (py, cier, sier, pier)
+ if (gid != NULL)
+ call appymark (py, gid, Memr[x], Memr[y], nvertices + 1,
+ YES, apstati (py, MKSKY), apstati (py, MKPOLYGON))
+ }
+
+ # Write the output to a file.
+ if (id == 1)
+ call ap_param (py, out, "polyphot")
+ switch (apstati(py,WCSOUT)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (py, Memr[x], Memr[y], Memr[xout], Memr[yout],
+ nvertices + 1)
+ case WCS_TV:
+ call ap_ltov (im, Memr[x], Memr[y], Memr[xout], Memr[yout],
+ nvertices + 1)
+ default:
+ call amovr (Memr[x], Memr[xout], nvertices + 1)
+ call amovr (Memr[y], Memr[yout], nvertices + 1)
+ }
+ call ap_yprint (py, out, Memr[xout], Memr[yout], nvertices, id, ld,
+ pd, cier, sier, pier)
+ id = id + 1
+
+ # Setup for next polygon.
+ prev_num = ld
+ req_num = ld + 1
+ nvertices = ap_ynextobj (py, im, gid, pl, cl, delim, Memr[x],
+ Memr[y], MAX_NVERTICES, prev_num, req_num, ld, pd)
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/polyphot/apycenter.x b/noao/digiphot/apphot/polyphot/apycenter.x
new file mode 100644
index 00000000..faa2d884
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apycenter.x
@@ -0,0 +1,59 @@
+include "../lib/center.h"
+include "../lib/polyphot.h"
+
+# AP_YCENTER -- Center the polygon using the centering package routines.
+
+int procedure ap_ycenter (py, im, wx, wy, x, y, nver)
+
+pointer py # pointer to polyphot structure
+pointer im # pointer to the IRAF image
+real wx # initial x center
+real wy # initial y center
+real x[ARB] # x coordinates of the polygon
+real y[ARB] # y coordinates of the polygon
+int nver # number of vertices
+
+int cier
+int apfitcenter()
+real apstatr()
+
+begin
+ if (IS_INDEFR(apstatr (py, PYCX)) || IS_INDEFR(apstatr (py, PYCY)))
+ cier = apfitcenter (py, im, INDEFR, INDEFR)
+ else
+ cier = apfitcenter (py, im, wx, wy)
+
+ if (! IS_INDEFR (apstatr (py, XCENTER)) && ! IS_INDEFR (apstatr (py,
+ YCENTER)) && ! IS_INDEFR (apstatr (py, PYCX)) &&
+ ! IS_INDEFR (apstatr (py, PYCY)))
+ call ap_yshift (py, im, x, y, nver, apstatr (py, XCENTER),
+ apstatr (py, YCENTER))
+
+ return (cier)
+end
+
+
+# AP_YRECENTER -- Recenter the polygon using the existing buffer of pixels
+# and the centering package routines.
+
+int procedure ap_yrecenter (py, im, x, y, nver, cier)
+
+pointer py # pointer to polyphot structure
+pointer im # the input image descriptor
+real x[ARB] # x coordinates of the polygon
+real y[ARB] # y coordinates of the polygon
+int nver # number of vertices
+int cier # original centering error
+
+int aprefitcenter()
+real apstatr()
+
+begin
+ cier = aprefitcenter (py, im, cier)
+ if (! IS_INDEFR (apstatr (py, XCENTER)) && ! IS_INDEFR (apstatr (py,
+ YCENTER)) && ! IS_INDEFR (apstatr (py, PYCX)) && !
+ IS_INDEFR (apstatr (py, PYCY)))
+ call ap_yshift (py, im, x, y, nver, apstatr (py, XCENTER),
+ apstatr (py, YCENTER))
+ return (cier)
+end
diff --git a/noao/digiphot/apphot/polyphot/apycolon.x b/noao/digiphot/apphot/polyphot/apycolon.x
new file mode 100644
index 00000000..9b70199b
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apycolon.x
@@ -0,0 +1,226 @@
+include <error.h>
+include <gset.h>
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/display.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/polyphot.h"
+
+# AP_YCOLON -- Process polyphot task colon commands
+
+procedure ap_ycolon (ap, im, pl, cl, out, stid, ptid, ltid, cmdstr, newimage,
+ newcenterbuf, newcenter, newskybuf, newsky, newmagbuf, newmag)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the iraf image
+int pl # polygon file descriptor
+int cl # coord file descriptor
+int out # output file descriptor
+int stid # output file number
+int ptid # polygon file sequence number
+int ltid # coord file sequence number
+char cmdstr[ARB] # command string
+int newimage # new image ?
+int newcenterbuf, newcenter # new center buffer ?, new center fit ?
+int newskybuf, newsky # new sky buffer ?, new sky fit ?
+int newmagbuf, newmag # new aperture buffer ?, new fit ?
+
+pointer sp, incmd, outcmd
+int strdic()
+
+begin
+ # Fetch the command.
+ call smark (sp)
+ call salloc (incmd, SZ_LINE, TY_CHAR)
+ call salloc (outcmd, SZ_LINE, TY_CHAR)
+
+ call sscan (cmdstr)
+ call gargwrd (Memc[incmd], SZ_LINE)
+ if (Memc[incmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Set the command to the appropriate routine.
+ if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, CCMDS) != 0)
+ call apccolon (ap, out, stid, cmdstr, newcenterbuf, newcenter)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, SCMDS) != 0)
+ call apscolon (ap, out, stid, cmdstr, newskybuf, newsky)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, APCMDS) != 0)
+ call ap_apcolon (ap, im, cl, out, stid, ltid, cmdstr, newimage,
+ newcenterbuf, newcenter, newskybuf, newsky, newmagbuf, newmag)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, NCMDS) != 0)
+ call ap_nscolon (ap, im, out, stid, cmdstr, newcenterbuf,
+ newcenter, newskybuf, newsky, newmagbuf, newmag)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, PYCMDS) != 0)
+ call ap_yycolon (ap, pl, out, stid, ptid, ltid, cmdstr, newmagbuf,
+ newmag)
+ else
+ call ap_yimcolon (ap, cmdstr)
+
+ call sfree (sp)
+end
+
+
+# AP_YIMCOLON -- Procedure to process remaining polyphot commands which
+
+procedure ap_yimcolon (ap, cmdstr)
+
+pointer ap # pointer to the apphot structure
+char cmdstr[ARB] # command string
+
+int ncmd
+pointer sp, cmd
+int strdic()
+
+begin
+ # Fetch the command.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, MISC1)
+ switch (ncmd) {
+ case 1:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, PYSHOWARGS)
+ switch (ncmd) {
+ case 1:
+ call printf ("\n")
+ call ap_cpshow (ap)
+ call printf ("\n")
+ case 2:
+ call printf ("\n")
+ call ap_spshow (ap)
+ call printf ("\n")
+ case 3:
+ call printf ("\n")
+ call ap_ypshow (ap)
+ call printf ("\n")
+ case 4:
+ call printf ("\n")
+ call ap_nshow (ap)
+ call printf ("\n")
+ default:
+ call printf ("\n")
+ call ap_yshow (ap)
+ call printf ("\n")
+ }
+ default:
+ call printf ("Unknown or ambiguous colon command\7\n")
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_YYCOLON -- Procedure to process polyphot commands
+
+procedure ap_yycolon (ap, pl, out, stid, ptid, ltid, cmdstr, newmagbuf, newmag)
+
+pointer ap # pointer to apphot structure
+int pl # polygon file descriptor
+int out # output file descriptor
+int stid # output file sequence number
+int ptid # polygon file sequence number
+int ltid # coords file sequence number
+char cmdstr[ARB] # command string
+int newmagbuf # new aperture buffers ?
+int newmag # compute new magnitudes ?
+
+bool bval
+int ncmd
+pointer sp, cmd, str
+real rval
+string cmds PYCMDS
+
+bool itob(), streq()
+int apstati(), btoi(), strdic(), nscan(), open()
+real apstatr()
+errchk open, close
+
+begin
+ # Allocate the space.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the colon command.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, cmds)
+ switch (ncmd) {
+
+ case PLCMD_ZMAG:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (KY_PYZMAG)
+ call pargr (apstatr (ap, PYZMAG))
+ } else {
+ call apsetr (ap, PYZMAG, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_PYZMAG, rval, UN_PYZMAG,
+ "zero point of magnitude scale")
+ newmag = YES
+ }
+
+ case PLCMD_MKPOLYGON:
+ call gargb (bval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (KY_MKPOLYGON)
+ call pargb (itob (apstati (ap, MKPOLYGON)))
+ } else {
+ call apseti (ap, MKPOLYGON, btoi (bval))
+ }
+
+ case PLCMD_POLYGONS:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ call apstats (ap, PYNAME, Memc[str], SZ_FNAME)
+ if (Memc[cmd] == EOS || streq (Memc[cmd], Memc[str])) {
+ call printf ("%s = %s\n")
+ call pargstr (KY_PYNAME)
+ call pargstr (Memc[str])
+ } else {
+ if (pl != NULL) {
+ call close (pl)
+ pl = NULL
+ }
+ iferr {
+ pl = open (Memc[cmd], READ_ONLY, TEXT_FILE)
+ } then {
+ pl = NULL
+ call erract (EA_WARN)
+ call apsets (ap, PYNAME, "")
+ call apsets (ap, PYROOT, "")
+ ptid = 0
+ ltid = 0
+ } else {
+ call apsets (ap, PYNAME, Memc[cmd])
+ call apfroot (Memc[cmd], Memc[str], SZ_FNAME)
+ call apsets (ap, PYROOT, Memc[str])
+ ptid = 0
+ ltid = 0
+ }
+ }
+
+ default:
+ call printf ("Unknown or ambiguous colon command\n")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/polyphot/apyconfirm.x b/noao/digiphot/apphot/polyphot/apyconfirm.x
new file mode 100644
index 00000000..fb10ad32
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apyconfirm.x
@@ -0,0 +1,99 @@
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+
+# AP_YCONFIRM -- Procedure to confirm the critical polyphot parameters.
+
+procedure ap_yconfirm (ap, out, stid)
+
+pointer ap # pointer to the apphot structure
+int out # output file descriptor
+int stid # output file sequence number
+
+pointer sp, cstr, sstr
+real fwhmpsf, capert, annulus, dannulus, skysigma
+real datamin, datamax
+int apstati()
+real apstatr(), ap_vfwhmpsf(), ap_vcapert(), ap_vsigma()
+real ap_vannulus(), ap_vdannulus(), ap_vdatamin(), ap_vdatamax()
+
+begin
+ call smark (sp)
+ call salloc (cstr, SZ_FNAME, TY_CHAR)
+ call salloc (sstr, SZ_FNAME, TY_CHAR)
+
+ call printf ("\n")
+
+ # Confirm the centering algorithm.
+ call ap_vcstring (ap, Memc[cstr], SZ_FNAME)
+
+ if (apstati (ap, CENTERFUNCTION) != AP_NONE) {
+
+ # Confirm the fwhmpsf.
+ if (apstati (ap, CENTERFUNCTION) != AP_CENTROID1D)
+ fwhmpsf = ap_vfwhmpsf (ap)
+ else
+ fwhmpsf = apstatr (ap, FWHMPSF)
+
+ # Confirm the centering box.
+ capert = 2.0 * ap_vcapert (ap)
+
+ } else {
+ fwhmpsf = apstatr (ap, FWHMPSF)
+ capert = 2.0 * apstatr (ap, CAPERT)
+ }
+
+ # Confirm the sky fitting algorithm.
+ call ap_vsstring (ap, Memc[sstr], SZ_FNAME)
+
+ if (apstati (ap, SKYFUNCTION) != AP_CONSTANT &&
+ apstati (ap, SKYFUNCTION) != AP_SKYFILE) {
+
+ # Confirm the sky annulus parameter.
+ annulus = ap_vannulus (ap)
+
+ # Confirm the width of the sky annulus.
+ dannulus = ap_vdannulus (ap)
+
+ } else {
+ annulus = apstatr (ap, ANNULUS)
+ dannulus = apstatr (ap, DANNULUS)
+ }
+
+ # Confirm the sky sigma parameter.
+ if (apstati (ap, SKYFUNCTION) != AP_SKYFILE)
+ skysigma = ap_vsigma (ap)
+ else
+ skysigma = apstatr (ap, SKYSIGMA)
+
+ # Confirm the datamin and datamax parameters.
+ datamin = ap_vdatamin (ap)
+ datamax = ap_vdatamax (ap)
+
+ call printf ("\n")
+
+ # Update the database file.
+ if (out != NULL && stid > 1) {
+ call ap_sparam (out, KY_CSTRING, Memc[cstr], UN_CALGORITHM,
+ "centering algorithm")
+ call ap_rparam (out, KY_FWHMPSF, fwhmpsf, UN_ASCALEUNIT,
+ "full width half maximum of the psf")
+ call ap_rparam (out, KY_CAPERT, capert, UN_CSCALEUNIT,
+ "width of the centering box")
+ call ap_sparam (out, KY_SSTRING, Memc[sstr], UN_SALGORITHM,
+ "sky fitting algorithm")
+ call ap_rparam (out, KY_ANNULUS, annulus, UN_SSCALEUNIT,
+ "inner radius of the sky annulus")
+ call ap_rparam (out, KY_DANNULUS, dannulus, UN_SSCALEUNIT,
+ "width of the sky annulus")
+ call ap_rparam (out, KY_SKYSIGMA, skysigma, UN_NCOUNTS,
+ "standard deviation of 1 sky pixel")
+ call ap_rparam (out, KY_DATAMIN, datamin, UN_ACOUNTS,
+ "minimum good data value")
+ call ap_rparam (out, KY_DATAMAX, datamax, UN_ACOUNTS,
+ "maximum good data value")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/polyphot/apycoords.x b/noao/digiphot/apphot/polyphot/apycoords.x
new file mode 100644
index 00000000..0298b0f8
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apycoords.x
@@ -0,0 +1,43 @@
+include "../lib/polyphot.h"
+
+# AP_YCOORDS -- Procedure to fetch the next center coordinates for the polygon.
+
+int procedure ap_ycoords (cl, delim, xshift, yshift, stdin)
+
+int cl # coordinates file descriptor
+int delim # delimiter character
+real xshift # new x coordinate
+real yshift # new y coordinate
+int stdin # is cl STDIN?
+
+char marker
+int stat
+int fscan(), nscan()
+
+begin
+ if (stdin == YES) {
+ call printf ("Type object x and y coordinates (^D or^Z to end): ")
+ call flush (STDOUT)
+ }
+
+ stat = fscan (cl)
+ while (stat != EOF) {
+
+ call gargr (xshift)
+ call gargr (yshift)
+
+ if (nscan() != 2) {
+ call reset_scan()
+ call gargc (marker)
+ if (int (marker) == delim)
+ return (NEXT_POLYGON)
+ #else
+ #return (NEXT_OBJECT)
+ } else
+ return (THIS_OBJECT)
+
+ stat = fscan (cl)
+ }
+
+ return (stat)
+end
diff --git a/noao/digiphot/apphot/polyphot/apydraw.x b/noao/digiphot/apphot/polyphot/apydraw.x
new file mode 100644
index 00000000..aadcbed0
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apydraw.x
@@ -0,0 +1,55 @@
+include "../lib/polyphot.h"
+
+# APYDRAW -- Procedure to draw polygons interactively on the display.
+
+procedure ap_ydraw (py, im, cl, pl, ld, pd, id)
+
+pointer py # pointer to apphot structure
+pointer im # theinput image descriptor
+int cl # coordinates file descriptor
+int pl # vertices list file descriptor
+int ld # coordinate list number
+int pd # polygon list number
+pointer id # pointer to image display stream
+
+int req_num, prev_num, nvertices, delim
+pointer sp, x, y
+int ap_ynextobj()
+data delim /';'/
+
+begin
+ # Allocate temporary space for arrays.
+ call smark (sp)
+ call salloc (x, MAX_NVERTICES + 1, TY_REAL)
+ call salloc (y, MAX_NVERTICES + 1, TY_REAL)
+
+ # Rewind the polygon and coordinate files.
+ if (pl != NULL)
+ call seek (pl, BOF)
+ if (cl != NULL)
+ call seek (cl, BOF)
+
+ # Initialize.
+ pd = 0
+ prev_num = 0
+ req_num = ld + 1
+ nvertices = ap_ynextobj (py, im, id, pl, cl, delim, Memr[x], Memr[y],
+ MAX_NVERTICES, prev_num, req_num, ld, pd)
+
+ # Loop over the coordinate and polygon file.
+ while (nvertices != EOF) {
+
+ # Draw the polygon if it has more than three vertices.
+ if (id != NULL && nvertices >= 3)
+ call appymark (py, id, Memr[x], Memr[y], nvertices + 1,
+ NO, NO, YES)
+
+ # Setup for next polygon.
+ prev_num = ld
+ req_num = ld + 1
+ nvertices = ap_ynextobj (py, im, id, pl, cl, delim, Memr[x],
+ Memr[y], MAX_NVERTICES, prev_num, req_num, ld, pd)
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/polyphot/apyfit.x b/noao/digiphot/apphot/polyphot/apyfit.x
new file mode 100644
index 00000000..abb76a6d
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apyfit.x
@@ -0,0 +1,578 @@
+include <imhdr.h>
+include <mach.h>
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/polyphot.h"
+
+# AP_YFIT -- Procedure to compute the magnitude of an object inside a polygonal
+# aperture.
+
+int procedure ap_yfit (py, im, xver, yver, nver, skyval, skysig, nsky)
+
+pointer py # pointer to polyphot strucuture
+pointer im # pointer to IRAF image
+real xver[ARB] # x vertices coords
+real yver[ARB] # y vertices coords
+int nver # number of vertices
+real skyval # sky value
+real skysig # sigma of sky pixels
+int nsky # number of sky pixels
+
+double flux, area
+int noise, badpix, ier
+real datamin, datamax, mag, magerr, zmag, padu, itime, readnoise
+int apstati(), ap_yyfit(), ap_byyfit()
+real apstatr()
+
+begin
+ # Initialize.
+ call apsetd (py, PYFLUX, 0.0d0)
+ call apsetd (py, PYNPIX, 0.0d0)
+ call apsetr (py, PYMAG, INDEFR)
+ call apsetr (py, PYMAGERR, INDEFR)
+
+ # Compute the flux inside the polygon.
+ if (IS_INDEFR(apstatr (py, DATAMIN)) && IS_INDEFR(apstatr(py,
+ DATAMAX))) {
+ ier = ap_yyfit (im, xver, yver, nver, flux, area)
+ badpix = NO
+ } else {
+ if (IS_INDEFR(apstatr (py, DATAMIN)))
+ datamin = -MAX_REAL
+ else
+ datamin = apstatr (py, DATAMIN)
+ if (IS_INDEFR(apstatr (py, DATAMAX)))
+ datamax = MAX_REAL
+ else
+ datamax = apstatr (py, DATAMAX)
+ ier = ap_byyfit (im, xver, yver, nver, datamin, datamax, flux,
+ area, badpix)
+ }
+
+ if (ier == PY_NOPOLYGON)
+ return (PY_NOPOLYGON)
+ else if (ier == PY_NOPIX)
+ return (PY_NOPIX)
+
+ # Store the results.
+ call apsetd (py, PYFLUX, flux)
+ call apsetd (py, PYNPIX, area)
+ call apseti (py, PYBADPIX, badpix)
+
+ if (IS_INDEFR(skyval))
+ return (PY_NOSKYMODE)
+
+ # Get the photometry parameters.
+ zmag = apstatr (py, PYZMAG)
+ itime = apstatr (py, ITIME)
+ noise = apstati (py, NOISEFUNCTION)
+ padu = apstatr (py, EPADU)
+ readnoise = apstatr (py, READNOISE)
+
+ # Compute the magnitude and error.
+ if (badpix == NO) {
+ if (apstati (py, POSITIVE) == YES)
+ call apcopmags (flux, area, mag, magerr, 1, skyval,
+ skysig, nsky, zmag, noise, padu)
+ else
+ call apconmags (flux, area, mag, magerr, 1, skyval,
+ skysig, nsky, zmag, noise, padu, readnoise)
+ mag = mag + 2.5 * log10 (itime)
+
+ call apsetr (py, PYMAG, mag)
+ call apsetr (py, PYMAGERR, magerr)
+ }
+
+ return (ier)
+end
+
+
+# AP_YYFIT -- Measure the total flux inside a polygon.
+
+int procedure ap_yyfit (im, xver, yver, nver, flux, area)
+
+pointer im # pointer to IRAF image
+real xver[ARB] # x coordinates of the vertices
+real yver[ARB] # y coordinates of the vertices:
+int nver # number of vertices
+double flux # flux interior to the polygon
+double area # approximate area of polygon
+
+double fluxx, areax, fctnx, fctny
+real xmin, xmax, ymin, ymax, x1, x2, lx, ld
+pointer sp, work1, work2, xintr, buf
+int i, j, k, linemin, linemax, colmin, colmax, nintr, ier
+int ap_yclip()
+pointer imgl2r()
+
+begin
+ # Check that polygon has at least 3 vertices plus the closing vertex.
+ if (nver < 4) {
+ flux = INDEFD
+ area = 0.0d0
+ return (PY_NOPOLYGON)
+ }
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (work1, nver, TY_REAL)
+ call salloc (work2, nver, TY_REAL)
+ call salloc (xintr, nver, TY_REAL)
+
+ # Find the minimum and maximum x and y values of the polygon
+ # and detemine whether the polygon is partially off the image.
+
+ call alimr (xver, nver, xmin, xmax)
+ call alimr (yver, nver, ymin, ymax)
+ if (xmin < 0.5 || xmax > (IM_LEN(im,1) + 0.5) || ymin < 0.5 || ymax >
+ (IM_LEN(im,2) + 0.5))
+ ier = PY_OUTOFBOUNDS
+ else
+ ier = PY_OK
+
+ # Find the minimum and maximum image line numbers.
+ ymin = max (0.5, min (real (IM_LEN (im,2) + 0.5), ymin))
+ ymax = min (real (IM_LEN(im,2) + 0.5), max (0.5, ymax))
+ linemin = min (int (ymin + 0.5), int (IM_LEN(im,2)))
+ linemax = min (int (ymax + 0.5), int (IM_LEN(im,2)))
+
+ # Set up the line segment parameters and initialize fluxes and areas.
+ x1 = 0.5
+ x2 = IM_LEN(im,1) + 0.5
+ lx = x2 - x1
+ flux = 0.0d0
+ area = 0.0d0
+
+ # Loop over the range of lines of interest.
+ do i = linemin, linemax {
+
+ # Read in image line.
+ buf = imgl2r (im, i)
+ if (buf == EOF)
+ next
+
+ # Find all the x intersection points of image line and polygon.
+ if (ymin > i)
+ ld = min (i + 1, linemax)
+ else if (ymax < i)
+ ld = max (i - 1, linemin)
+ else
+ ld = i
+ nintr = ap_yclip (xver, yver, Memr[work1], Memr[work2],
+ Memr[xintr], nver, lx, ld)
+ if (nintr <= 0)
+ next
+ fctny = min (i + 0.5, ymax) - max (i - 0.5, ymin)
+
+ # Sort the x intersection points
+ call asrtr (Memr[xintr], Memr[xintr], nintr)
+
+ # Integrate the flux in each line segment.
+ fluxx = 0.0d0
+ areax = 0.0d0
+ do j = 1, nintr, 2 {
+
+ # Compute the line segment limits.
+ xmin = min (real (IM_LEN(im,1) + 0.5), max (0.5,
+ Memr[xintr+j-1]))
+ xmax = min (real (IM_LEN(im,1) + 0.5), max (0.5,
+ Memr[xintr+j]))
+ colmin = min (int (xmin + 0.5), int (IM_LEN(im,1)))
+ colmax = min (int (xmax + 0.5), int (IM_LEN(im,1)))
+
+ # Sum the contribution from a particular line segment.
+ do k = colmin, colmax {
+ fctnx = min (k + 0.5, xmax) - max (k - 0.5, xmin)
+ fluxx = fluxx + fctnx * Memr[buf+k-1]
+ areax = areax + fctnx
+ }
+ }
+
+ # Add the line sum to the total.
+ area = area + areax * fctny
+ flux = flux + fluxx * fctny
+ }
+
+ call sfree (sp)
+
+ # Return the appropriate error code.
+ if (area <= 0.0d0)
+ return (PY_NOPIX)
+ else if (ier != PY_OK)
+ return (ier)
+ else
+ return (PY_OK)
+end
+
+
+# AP_BYYFIT -- Measure the total flux inside a polygon while searching for
+# bad pixels at the same time.
+
+int procedure ap_byyfit (im, xver, yver, nver, datamin, datamax, flux, area,
+ badpix)
+
+pointer im # pointer to IRAF image
+real xver[ARB] # x coordinates of the vertices
+real yver[ARB] # y coordinates of the vertices:
+int nver # number of vertices
+real datamin # minimum good data value
+real datamax # maximum good data value
+double flux # flux interior to the polygon
+double area # approximate area of polygon
+int badpix # are there bad pixels
+
+int i, j, k, linemin, linemax, colmin, colmax, nintr, ier
+pointer sp, work1, work2, xintr, buf
+real xmin, xmax, ymin, ymax, x1, x2, lx, ld
+double fluxx, areax, fctnx, fctny
+int ap_yclip()
+pointer imgl2r()
+
+begin
+ # Check that polygon has at least 3 vertices plus a closing vertex.
+ if (nver < 4) {
+ flux = INDEFD
+ area = 0.0d0
+ badpix = NO
+ return (PY_NOPOLYGON)
+ }
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (work1, nver, TY_REAL)
+ call salloc (work2, nver, TY_REAL)
+ call salloc (xintr, nver, TY_REAL)
+
+ # Find minimum and maximum y values of the polygon vertices and
+ # compute the minimum and maximum image line limits.
+
+ call alimr (xver, nver, xmin, xmax)
+ call alimr (yver, nver, ymin, ymax)
+ if (xmin < 0.5 || xmax > (IM_LEN(im,1) + 0.5) || ymin < 0.5 || ymax >
+ (IM_LEN(im,2) + 0.5))
+ ier = PY_OUTOFBOUNDS
+ else
+ ier = PY_OK
+
+ # Find the min and max image line numbers.
+ ymin = max (0.5, min (real (IM_LEN (im,2) + 0.5), ymin))
+ ymax = min (real (IM_LEN(im,2) + 0.5), max (0.5, ymax))
+ linemin = max (1, min (int (ymin + 0.5), int (IM_LEN(im,2))))
+ linemax = max (1, min (int (ymax + 0.5), int (IM_LEN(im,2))))
+
+ # Set up line segment parameters and initialize fluxes.
+ x1 = 0.5
+ x2 = IM_LEN(im,1) + 0.5
+ lx = x2 - x1
+ flux = 0.0d0
+ area = 0.0d0
+
+ # Loop over the range of lines of interest.
+ badpix = NO
+ do i = linemin, linemax {
+
+ # Read in the image line.
+ buf = imgl2r (im, i)
+ if (buf == EOF)
+ next
+
+ # Find all the intersection points.
+ if (ymin > i)
+ ld = min (i + 1, linemax)
+ else if (ymax < i)
+ ld = max (i - 1, linemin)
+ else
+ ld = i
+ nintr = ap_yclip (xver, yver, Memr[work1], Memr[work2],
+ Memr[xintr], nver, lx, ld)
+ if (nintr <= 0)
+ next
+ fctny = min (i + 0.5, ymax) - max (i - 0.5, ymin)
+
+ # Sort the x intersection points
+ call asrtr (Memr[xintr], Memr[xintr], nintr)
+
+ # Integrate the flux in the line segment
+ fluxx = 0.0d0
+ areax = 0.0d0
+ do j = 1, nintr, 2 {
+
+ # Compute the line segment limits.
+ xmin = min (real (IM_LEN(im,1) + 0.5), max (0.5,
+ Memr[xintr+j-1]))
+ xmax = min (real (IM_LEN(im,1) + 0.5), max (0.5, Memr[xintr+j]))
+ colmin = min (int (xmin + 0.5), int (IM_LEN(im,1)))
+ colmax = min (int (xmax + 0.5), int (IM_LEN(im,1)))
+
+ # Sum the contribution from a particular line segment.
+ do k = colmin, colmax {
+ fctnx = min (k + 0.5, xmax) - max (k - 0.5, xmin)
+ fluxx = fluxx + fctnx * Memr[buf+k-1]
+ areax = areax + fctnx
+ if (Memr[buf+k-1] < datamin || Memr[buf+k-1] > datamax)
+ badpix = YES
+ }
+ }
+
+ # Add the line sum to the total.
+ area = area + areax * fctny
+ flux = flux + fluxx * fctny
+ }
+
+ call sfree (sp)
+
+ if (area <= 0.0d0)
+ return (PY_NOPIX)
+ if (badpix == YES)
+ return (PY_BADDATA)
+ else if (ier != PY_OK)
+ return (ier)
+ else
+ return (PY_OK)
+end
+
+
+# AP_YCLIP -- Compute the intersection of an image line with a polygon defined
+# by a list of vertices. The output is a list of ranges stored in the array
+# xranges. Two work additional work arrays xintr and slope are required for
+# the computation.
+
+int procedure ap_yclip (xver, yver, xintr, slope, xranges, nver, lx, ld)
+
+real xver[ARB] # x vertex coords
+real yver[ARB] # y vertex coords
+real xintr[ARB] # work array of x intersection points
+real slope[ARB] # work array of y slopes at intersection points
+real xranges[ARB] # x line segments
+int nver # number of vertices
+real lx, ld # equation of image line
+
+bool collinear
+int i, j, nintr, nplus, nzero, nneg, imin, imax, nadd
+real u1, u2, u1u2, dx, dy, dd, xa, wa
+
+begin
+ # Compute the intersection points of the image line and the polygon.
+ collinear = false
+ nplus = 0
+ nzero = 0
+ nneg = 0
+ nintr = 0
+ #u1 = - lx * yver[1] + ld
+ u1 = lx * (- yver[1] + ld)
+ do i = 2, nver {
+
+ #u2 = - lx * yver[i] + ld
+ u2 = lx * (- yver[i] + ld)
+ u1u2 = u1 * u2
+
+ # Does the polygon side intersect the image line ?
+ if (u1u2 <= 0.0) {
+
+
+ # Compute the x intersection coordinate if the point of
+ # intersection is not a vertex.
+
+ if ((u1 != 0.0) && (u2 != 0.0)) {
+
+ dy = yver[i-1] - yver[i]
+ dx = xver[i-1] - xver[i]
+ dd = xver[i-1] * yver[i] - yver[i-1] * xver[i]
+ #xa = (dx * ld - lx * dd)
+ xa = lx * (dx * ld - dd)
+ wa = dy * lx
+ nintr = nintr + 1
+ xranges[nintr] = xa / wa
+ slope[nintr] = -dy
+ if (slope[nintr] < 0.0)
+ nneg = nneg + 1
+ else if (slope[nintr] > 0.0)
+ nplus = nplus + 1
+ else
+ nzero = nzero + 1
+ collinear = false
+
+ # For each collinear line segment add two intersection
+ # points. Remove interior collinear intersection points.
+
+ } else if (u1 == 0.0 && u2 == 0.0) {
+
+ if (! collinear) {
+ nintr = nintr + 1
+ xranges[nintr] = xver[i-1]
+ if (i == 2)
+ slope[nintr] = yver[1] - yver[nver-1]
+ else
+ slope[nintr] = yver[i-1] - yver[i-2]
+ if (slope[nintr] < 0.0)
+ nneg = nneg + 1
+ else if (slope[nintr] > 0.0)
+ nplus = nplus + 1
+ else
+ nzero = nzero + 1
+ nintr = nintr + 1
+ xranges[nintr] = xver[i]
+ slope[nintr] = 0.0
+ nzero = nzero + 1
+ } else {
+ xranges[nintr] = xver[i]
+ slope[nintr] = 0.0
+ nzero = nzero + 1
+ }
+ collinear = true
+
+ # If the intersection point is a vertex add it to the
+ # list if it is not collinear with the next point. Add
+ # another point to the list if the vertex is at the
+ # apex of an acute angle.
+
+ } else if (u1 != 0.0) {
+
+ if (i == nver) {
+ dx = (xver[2] - xver[nver])
+ dy = (yver[2] - yver[nver])
+ dd = dy * (yver[nver-1] - yver[nver])
+ } else {
+ dx = (xver[i+1] - xver[i])
+ dy = (yver[i+1] - yver[i])
+ dd = dy * (yver[i-1] - yver[i])
+ }
+
+ # Test whether the point is collinear with the point
+ # ahead. If it is not include the intersection point.
+
+ if (dy != 0.0) {
+ nintr = nintr + 1
+ xranges[nintr] = xver[i]
+ slope[nintr] = yver[i] - yver[i-1]
+ if (slope[nintr] < 0.0)
+ nneg = nneg + 1
+ else if (slope[nintr] > 0.0)
+ nplus = nplus + 1
+ else
+ nzero = nzero + 1
+ }
+
+ # If the intersection point is an isolated vertex add
+ # another point to the list.
+
+ if (dd > 0.0) {
+ nintr = nintr + 1
+ xranges[nintr] = xver[i]
+ slope[nintr] = dy
+ if (slope[nintr] < 0.0)
+ nneg = nneg + 1
+ else if (slope[nintr] > 0.0)
+ nplus = nplus + 1
+ else
+ nzero = nzero + 1
+ }
+
+ collinear = false
+
+ } else
+ collinear = false
+ } else
+ collinear = false
+
+ u1 = u2
+ }
+
+ # Join up any split collinear line segments.
+ if (collinear && (slope[1] == 0.0)) {
+ xranges[1] = xranges[nintr-1]
+ slope[1] = slope[nintr-1]
+ nintr = nintr - 2
+ nzero = nzero - 2
+ }
+
+ # Return the number of intersection points if there are no interior
+ # collinear line segments.
+ if (nzero == 0 || nplus == 0 || nneg == 0)
+ return (nintr)
+
+ # Find the minimum and maximum intersection points.
+ call ap_alimr (xranges, nintr, u1, u2, imin, imax)
+
+ # Check for vertices at the ends of the ranges.
+
+ u1 = xranges[min(imin,imax)] - xranges[1]
+ u2 = xranges[nintr] - xranges[max(imin,imax)]
+
+ # Vertices were traversed in order of increasing x.
+ if ((u1 >= 0.0 && u2 > 0.0) || (u1 > 0.0 && u2 >= 0.0) ||
+ (u1 == u2 && imax > imin)) {
+ do i = imax + 1, nintr {
+ if (xranges[i] != xranges[i-1])
+ break
+ imax = i
+ }
+ do i = imin - 1, 1, -1 {
+ if (xranges[i] != xranges[i+1])
+ break
+ imin = i
+ }
+ }
+
+ # Vertices were traversed in order of decreasing x.
+ if ((u1 <= 0.0 && u2 < 0.0) || (u1 < 0.0 && u2 <= 0.0) ||
+ (u1 == u2 && imax < imin)) {
+ do i = imin + 1, nintr {
+ if (xranges[i] != xranges[i-1])
+ break
+ imin = i
+ }
+ do i = imax - 1, 1, -1 {
+ if (xranges[i] != xranges[i+1])
+ break
+ imax = i
+ }
+ }
+
+ # Reorder the x ranges and slopes if necessary.
+ if ((imax < imin) && ! (imin == nintr && imax == 1)) {
+ call amovr (xranges, xintr, nintr)
+ do i = 1, imax
+ xranges[nintr-imax+i] = xintr[i]
+ do i = imin, nintr
+ xranges[i-imax] = xintr[i]
+ call amovr (slope, xintr, nintr)
+ do i = 1, imax
+ slope[nintr-imax+i] = xintr[i]
+ do i = imin, nintr
+ slope[i-imax] = xintr[i]
+ } else if ((imin < imax) && ! (imin == 1 && imax == nintr)) {
+ call amovr (xranges, xintr, nintr)
+ do i = 1, imin
+ xranges[nintr-imin+i] = xintr[i]
+ do i = imax, nintr
+ xranges[i-imin] = xintr[i]
+ call amovr (slope, xintr, nintr)
+ do i = 1, imin
+ slope[nintr-imin+i] = xintr[i]
+ do i = imax, nintr
+ slope[i-imin] = xintr[i]
+ }
+
+ # Add any extra intersection points that are required to deal with
+ # the collinear line segments.
+
+ nadd = 0
+ for (i = 1; i <= nintr-2; ) {
+ if (slope[i] * slope[i+2] > 0.0) {
+ i = i + 2
+ } else {
+ nadd = nadd + 1
+ xranges[nintr+nadd] = xranges[i+1]
+ for (j = i + 3; j <= nintr; j = j + 1) {
+ if (slope[i] * slope[j] > 0)
+ break
+ nadd = nadd + 1
+ xranges[nintr+nadd] = xranges[j-1]
+ }
+ i = j
+ }
+ }
+
+ return (nintr + nadd)
+end
diff --git a/noao/digiphot/apphot/polyphot/apyfree.x b/noao/digiphot/apphot/polyphot/apyfree.x
new file mode 100644
index 00000000..0bede579
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apyfree.x
@@ -0,0 +1,41 @@
+include "../lib/apphotdef.h"
+include "../lib/polyphotdef.h"
+
+# AP_YFREE -- Procedure to free the polyphot structure.
+
+procedure ap_yfree (ap)
+
+pointer ap # pointer to the apphot structure
+
+begin
+ if (ap == NULL)
+ return
+ if (AP_NOISE(ap) != NULL)
+ call ap_noisecls (ap)
+ if (AP_PDISPLAY(ap) != NULL)
+ call ap_dispcls (ap)
+ if (AP_POLY(ap) != NULL)
+ call ap_ycls (ap)
+ if (AP_PSKY(ap) != NULL)
+ call ap_skycls (ap)
+ if (AP_PCENTER(ap) != NULL)
+ call ap_ctrcls (ap)
+ if (AP_IMBUF(ap) != NULL)
+ call mfree (AP_IMBUF(ap), TY_REAL)
+ if (AP_MW(ap) != NULL)
+ call mw_close (AP_MW(ap))
+ call mfree (ap, TY_STRUCT)
+end
+
+
+# AP_YCLS -- Procedure to close up the polyphot structure and arrays.
+
+procedure ap_ycls (ap)
+
+pointer ap # pointer to the apphot structure
+
+begin
+ if (AP_POLY(ap) == NULL)
+ return
+ call mfree (AP_POLY(ap), TY_STRUCT)
+end
diff --git a/noao/digiphot/apphot/polyphot/apyget.x b/noao/digiphot/apphot/polyphot/apyget.x
new file mode 100644
index 00000000..a990b6f8
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apyget.x
@@ -0,0 +1,306 @@
+include <fset.h>
+include "../lib/apphot.h"
+include "../lib/fitsky.h"
+include "../lib/polyphot.h"
+
+# AP_YGET -- Procedure to fetch the coordinates of the vertices of a
+# polygon from a text file.
+
+int procedure ap_yget (py, im, fd, delim, x, y, max_nvertices)
+
+pointer py # polyphot structure
+pointer im # the input image descriptor
+int fd # polygon file descriptor
+int delim # delimiter character
+real x[ARB] # x coords of vertices
+real y[ARB] # y coords of vertices
+int max_nvertices # maximum number of vertices
+
+real xc, yc, r2max, r2, xtemp, ytemp
+pointer sp, str
+int i, nvertices, nreal, stat
+char marker
+real asumr()
+int fscan(), nscan(), strncmp(), apstati()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Print prompts if input file is STDIN.
+ call fstats (fd, F_FILENAME, Memc[str], SZ_LINE)
+ if (strncmp ("STDIN", Memc[str], 5) == 0) {
+ call printf ("Type x and y coordinates of vertex\n")
+ call printf ("\t1 vertex per line\n")
+ call printf ("\t; to end polygon\n")
+ call printf ("\t^Z to end list\n")
+ call flush (STDOUT)
+ }
+
+ # Get the polygon.
+ nvertices = 0
+ stat = fscan (fd)
+ while (stat != EOF) {
+
+ # Read the vertices from the file
+ call gargr (xtemp)
+ call gargr (ytemp)
+ nreal = nscan ()
+ if (nreal != 2) {
+ call reset_scan ()
+ call gargc (marker)
+ if (int (marker) == delim)
+ break
+ nreal = nscan ()
+ }
+
+ # Store the vertices.
+ if (nreal >= 2) {
+ nvertices = nvertices + 1
+ if (nvertices <= max_nvertices) {
+ x[nvertices] = xtemp
+ y[nvertices] = ytemp
+ }
+ }
+
+ stat = fscan (fd)
+ }
+
+ if (nvertices == 0 && stat == EOF) {
+
+ nvertices = EOF
+ call apsetr (py, PYXMEAN, INDEFR)
+ call apsetr (py, PYYMEAN, INDEFR)
+ call apsetr (py, OPYXMEAN, INDEFR)
+ call apsetr (py, OPYYMEAN, INDEFR)
+ call apsetr (py, PYCX, INDEFR)
+ call apsetr (py, PYCY, INDEFR)
+ call apsetr (py, OPYCX, INDEFR)
+ call apsetr (py, OPYCY, INDEFR)
+ call apsetr (py, PYMINRAD, INDEFR)
+ call apseti (py, PYNVER, 0)
+
+ } else if (nvertices <= 2) {
+
+ call apsetr (py, PYXMEAN, INDEFR)
+ call apsetr (py, PYYMEAN, INDEFR)
+ call apsetr (py, OPYXMEAN, INDEFR)
+ call apsetr (py, OPYYMEAN, INDEFR)
+ call apsetr (py, PYCX, INDEFR)
+ call apsetr (py, PYCY, INDEFR)
+ call apsetr (py, OPYCX, INDEFR)
+ call apsetr (py, OPYCY, INDEFR)
+ call apsetr (py, PYMINRAD, INDEFR)
+ call apseti (py, PYNVER, 0)
+ nvertices = 0
+
+ } else {
+
+ # Add in the last vertex.
+ x[nvertices+1] = x[1]
+ y[nvertices+1] = y[1]
+
+ # Transform the input coordinates.
+ switch (apstati(py,WCSIN)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_itol (py, x, y, x, y, nvertices + 1)
+ case WCS_TV:
+ call ap_vtol (im, x, y, x, y, nvertices + 1)
+ default:
+ ;
+ }
+
+ # Compute the mean polygon coordinates.
+ xc = asumr (x, nvertices) / nvertices
+ yc = asumr (y, nvertices) / nvertices
+ call apsetr (py, PYXMEAN, xc)
+ call apsetr (py, PYYMEAN, yc)
+ call apsetr (py, PYCX, xc)
+ call apsetr (py, PYCY, yc)
+
+ # Set the minimum size of the sky annulus.
+ r2max = 0.0
+ do i = 1, nvertices {
+ r2 = (x[i] - xc) ** 2 + (y[i] - yc) ** 2
+ if (r2 > r2max)
+ r2max = r2
+ }
+
+ switch (apstati(py,WCSOUT)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (py, xc, yc, xc, yc, 1)
+ case WCS_TV:
+ call ap_ltov (im, xc, yc, xc, yc, 1)
+ default:
+ ;
+ }
+ call apsetr (py, OPYXMEAN, xc)
+ call apsetr (py, OPYYMEAN, yc)
+ call apsetr (py, OPYCX, xc)
+ call apsetr (py, OPYCY, yc)
+
+ call apsetr (py, PYMINRAD, (sqrt (r2max) + 1.1))
+ call apseti (py, PYNVER, nvertices)
+ }
+
+ call sfree (sp)
+ return (nvertices)
+end
+
+
+# AP_YMKPOLY -- Mark the coordinates of a polygon on the display device.
+
+int procedure ap_ymkpoly (py, im, id, x, y, max_nvertices, idflush)
+
+pointer py # polyphot structure
+pointer im # the input image descriptor
+pointer id # display pointer
+real x[ARB] # x coords of vertices
+real y[ARB] # y coords of vertices
+int max_nvertices # maximum number of vertices
+int idflush # flush the imd interface ?
+
+int i, nvertices, stat, wcs, key
+pointer sp, cmd
+real xtemp, ytemp, xc, yc, r2max, r2
+real apstatr(), asumr()
+int clgcur(), apstati()
+errchk gscur
+
+begin
+ # Reopen the device.
+ if (id != NULL)
+ call greactivate (id, 0)
+
+ # Initialize.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Type prompt.
+ call printf (
+ "Mark polygon vertex [space=mark,q=quit].\n")
+ stat = clgcur ("icommands", xtemp, ytemp, wcs, key, Memc[cmd], SZ_LINE)
+ call ap_vtol (im, xtemp, ytemp, xtemp, ytemp, 1)
+
+
+ # Fetch the polygon and draw it on the display.
+ nvertices = 0
+ while (stat != EOF) {
+
+ if (key == 'q')
+ break
+
+ # Decode and draw vertices.
+ nvertices = nvertices + 1
+ if (nvertices <= max_nvertices) {
+ x[nvertices] = xtemp
+ y[nvertices] = ytemp
+ if (id != NULL) {
+ if (nvertices == 1)
+ call gamove (id, x[1], y[1])
+ else {
+ call gadraw (id, x[nvertices], y[nvertices])
+ if (idflush == YES)
+ call gframe (id)
+ else
+ call gflush (id)
+ }
+ }
+ } else
+ break
+
+ # Type prompt.
+ call printf (
+ "Mark polygon vertex [space=mark,q=quit].\n")
+ stat = clgcur ("icommands", xtemp, ytemp, wcs, key, Memc[cmd],
+ SZ_LINE)
+ call ap_vtol (im, xtemp, ytemp, xtemp, ytemp, 1)
+ }
+ call printf ("\n")
+
+ call sfree (sp)
+
+ # Return EOF or the number of vertices in the polygon.
+ if (stat == EOF) {
+
+ call apsetr (py, PYXMEAN, INDEFR)
+ call apsetr (py, PYYMEAN, INDEFR)
+ call apsetr (py, OPYXMEAN, INDEFR)
+ call apsetr (py, OPYYMEAN, INDEFR)
+ call apsetr (py, PYCX, INDEFR)
+ call apsetr (py, PYCY, INDEFR)
+ call apsetr (py, OPYCX, INDEFR)
+ call apsetr (py, OPYCY, INDEFR)
+ call apsetr (py, PYMINRAD, INDEFR)
+ call apseti (py, PYNVER, 0)
+ nvertices = EOF
+
+ } else if (nvertices <= 2) {
+
+ call apsetr (py, PYXMEAN, INDEFR)
+ call apsetr (py, PYYMEAN, INDEFR)
+ call apsetr (py, OPYXMEAN, INDEFR)
+ call apsetr (py, OPYYMEAN, INDEFR)
+ call apsetr (py, PYCX, INDEFR)
+ call apsetr (py, PYCY, INDEFR)
+ call apsetr (py, OPYCX, INDEFR)
+ call apsetr (py, OPYCY, INDEFR)
+ call apsetr (py, PYMINRAD, INDEFR)
+ call apseti (py, PYNVER, 0)
+ nvertices = 0
+
+ } else {
+
+ # Add the last vertex and close the polygon.
+ x[nvertices+1] = x[1]
+ y[nvertices+1] = y[1]
+ if (id != NULL) {
+ call gadraw (id, x[1], y[1])
+ if (idflush == YES)
+ call gframe (id)
+ else
+ call gflush (id)
+ }
+
+ # Compute and save the mean polygon coords.
+ xc = asumr (x, nvertices) / nvertices
+ yc = asumr (y, nvertices) / nvertices
+ call apsetr (py, PYXMEAN, xc)
+ call apsetr (py, PYYMEAN, yc)
+ call apsetr (py, PYCX, xc)
+ call apsetr (py, PYCY, yc)
+ if (id != NULL)
+ call gscur (id, apstatr (py, PYCX), apstatr (py, PYCY))
+
+ # Compute the mean sky annulus.
+ r2max = 0.0
+ do i = 1, nvertices {
+ r2 = (x[i] - xc) ** 2 + (y[i] - yc) ** 2
+ if (r2 > r2max)
+ r2max = r2
+ }
+
+ # Compute output coordinate centers.
+ switch (apstati(py,WCSOUT)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (py, xc, yc, xc, yc, 1)
+ case WCS_TV:
+ call ap_ltov (im, xc, yc, xc, yc, 1)
+ default:
+ ;
+ }
+ call apsetr (py, OPYXMEAN, xc)
+ call apsetr (py, OPYYMEAN, yc)
+ call apsetr (py, OPYCX, xc)
+ call apsetr (py, OPYCY, yc)
+
+ call apseti (py, PYNVER, nvertices)
+ call apsetr (py, PYMINRAD, (sqrt (r2max) + 1.1))
+
+ }
+
+ if (id != NULL)
+ call gdeactivate (id, 0)
+
+ return (nvertices)
+end
diff --git a/noao/digiphot/apphot/polyphot/apyinit.x b/noao/digiphot/apphot/polyphot/apyinit.x
new file mode 100644
index 00000000..6d9c2fe7
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apyinit.x
@@ -0,0 +1,64 @@
+include "../lib/apphotdef.h"
+include "../lib/polyphotdef.h"
+
+# AP_YINIT - Initialize the polyphot structure.
+
+procedure ap_yinit (ap, cfunction, cbox, sfunction, annulus, dannulus, fwhmpsf,
+ noise)
+
+pointer ap # pointer to the apphot structure
+int cfunction # centering algorithm
+real cbox # centering box half-width
+int sfunction # sky fitting algorithm
+real annulus # inner radius of sky annulus
+real dannulus # width of sky annulus
+real fwhmpsf # fwhmpsf
+int noise # Noise function
+
+begin
+ call malloc (ap, LEN_APSTRUCT, TY_STRUCT)
+
+ # Set the global apphot package parameters.
+ call ap_defsetup (ap, fwhmpsf)
+
+ # Setup noise parameters.
+ call ap_noisesetup (ap, noise)
+
+ # Set display options.
+ call ap_dispsetup (ap)
+
+ # Setup the centering parameters.
+ call ap_ctrsetup (ap, cfunction, cbox)
+
+ # Set up the sky fitting parameters.
+ call ap_skysetup (ap, sfunction, annulus, dannulus)
+
+ # Setup the polyphot parameters.
+ call ap_ysetup (ap)
+
+ # Set unused structure pointers to null.
+ AP_PPSF(ap) = NULL
+ AP_PPHOT(ap) = NULL
+ AP_RPROF(ap) = NULL
+end
+
+
+# AP_YSETUP -- Procedure to set parameters for polygonal aperture photometry.
+
+procedure ap_ysetup (ap)
+
+pointer ap # pointer to apphot strucuture
+
+pointer ply
+
+begin
+ call malloc (AP_POLY(ap), LEN_PYSTRUCT, TY_STRUCT)
+ ply = AP_POLY(ap)
+ AP_PYCX(ply) = INDEFR
+ AP_PYCY(ply) = INDEFR
+ AP_PYX(ply) = INDEFR
+ AP_PYY(ply) = INDEFR
+ AP_PYZMAG(ply) = DEF_PYZMAG
+ AP_PYNAME(ply) = EOS
+ AP_PYROOT(ply) = EOS
+end
diff --git a/noao/digiphot/apphot/polyphot/apymkfree.x b/noao/digiphot/apphot/polyphot/apymkfree.x
new file mode 100644
index 00000000..424b94e3
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apymkfree.x
@@ -0,0 +1,23 @@
+include "../lib/apphotdef.h"
+
+# AP_YMKFREE -- Procedure to free the polyphot structure.
+
+procedure ap_ymkfree (ap)
+
+pointer ap # pointer to the apphot structure
+
+begin
+ if (ap == NULL)
+ return
+ if (AP_NOISE(ap) != NULL)
+ call ap_noisecls (ap)
+ if (AP_PDISPLAY(ap) != NULL)
+ call ap_dispcls (ap)
+ if (AP_POLY(ap) != NULL)
+ call ap_ycls (ap)
+ if (AP_IMBUF(ap) != NULL)
+ call mfree (AP_IMBUF(ap), TY_REAL)
+ if (AP_MW(ap) != NULL)
+ call mw_close (AP_MW(ap))
+ call mfree (ap, TY_STRUCT)
+end
diff --git a/noao/digiphot/apphot/polyphot/apymkinit.x b/noao/digiphot/apphot/polyphot/apymkinit.x
new file mode 100644
index 00000000..215d3e9c
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apymkinit.x
@@ -0,0 +1,31 @@
+include "../lib/apphotdef.h"
+include "../lib/noise.h"
+
+# AP_YMKINIT - Procedure to initialize the polymark structure.
+
+procedure ap_ymkinit (ap)
+
+pointer ap # pointer to the apphot structure
+
+begin
+ call calloc (ap, LEN_APSTRUCT, TY_STRUCT)
+
+ # Set the main structure parameters.
+ call ap_defsetup (ap, 2.5)
+
+ # Set the noise options.
+ call ap_noisesetup (ap, AP_NPOISSON)
+
+ # Set display options.
+ call ap_dispsetup (ap)
+
+ # Setup the polyphot parameters.
+ call ap_ysetup (ap)
+
+ # Set unused structure pointers to null.
+ AP_PCENTER(ap) = NULL
+ AP_PSKY(ap) = NULL
+ AP_PPHOT(ap) = NULL
+ AP_RPROF(ap) = NULL
+ AP_PPSF(ap) = NULL
+end
diff --git a/noao/digiphot/apphot/polyphot/apynextobj.x b/noao/digiphot/apphot/polyphot/apynextobj.x
new file mode 100644
index 00000000..292d84bd
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apynextobj.x
@@ -0,0 +1,190 @@
+include <fset.h>
+include "../lib/apphot.h"
+include "../lib/polyphot.h"
+
+# AP_YNEXTOBJ -- Read the next polygon from the list polygon and/or coordinate
+# list.
+
+int procedure ap_ynextobj (py, im, id, pl, cl, delim, x, y, maxnver, prev_num,
+ req_num, ld, pd)
+
+pointer py # pointer to the apphot structre
+pointer im # the input image descriptor
+pointer id # pointer to image display stream
+int pl # polygons file descriptor
+int cl # coordinates file descriptor
+int delim # delimiter character
+real x[ARB] # x coordinates of the polygon vertices
+real y[ARB] # y coordinates of the polygon vertices
+int maxnver # maximum number of vertices
+int prev_num # previous object
+int req_num # requested object
+int ld # current object
+int pd # current polygon
+
+real xshift, yshift
+pointer sp, fname
+int stdin, nskip, ncount, nver, stat
+real apstatr()
+int strncmp(), ap_yget(), ap_ycoords(), apstati()
+errchk greactivate, gdeactivate, gscur
+
+begin
+ # The coordinate list is undefined.
+ if (cl == NULL) {
+
+ # Get the input file name.
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call fstats (pl, F_FILENAME, Memc[fname], SZ_FNAME)
+
+ # Compute the number of polygons that must be skipped.
+ if (strncmp ("STDIN", Memc[fname], 5) == 0) {
+ stdin = YES
+ nskip = 1
+ } else {
+ stdin = NO
+ if (req_num <= prev_num) {
+ call seek (pl, BOF)
+ nskip = req_num
+ } else
+ nskip = req_num - prev_num
+ }
+
+ # Initialize the polygon search.
+ ncount = 0
+ pd = prev_num
+
+ # Find the correct polygon.
+ repeat {
+
+ call apsetr (py, PYX, apstatr (py, PYCX))
+ call apsetr (py, PYY, apstatr (py, PYCY))
+ nver = ap_yget (py, im, pl, delim, x, y, maxnver)
+
+ if (nver == EOF) {
+ ncount = EOF
+ } else if (nver > 0) {
+ ncount = ncount + 1
+ pd = pd + 1
+ }
+
+ } until (ncount == EOF || ncount == nskip)
+
+ # Return the polygon number.
+ if (req_num <= prev_num)
+ pd = ncount
+ ld = pd
+
+ call sfree (sp)
+
+ if (ncount == EOF) {
+ return (EOF)
+ } else if (id != NULL) {
+ iferr {
+ call greactivate (id, 0)
+ call gscur (id, apstatr (py, PYCX), apstatr (py, PYCY))
+ call gdeactivate (id, 0)
+ } then
+ ;
+ return (nver)
+ } else {
+ return (nver)
+ }
+
+ # Both the polygon and coordinate file are defined.
+ } else {
+
+ # Get the input file name.
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call fstats (cl, F_FILENAME, Memc[fname], SZ_FNAME)
+
+ # Compute the number of objects that must be skipped.
+ if (strncmp ("STDIN", Memc[fname], 5) == 0) {
+ stdin = YES
+ nskip = 1
+ } else {
+ stdin = NO
+ if (req_num <= prev_num) {
+ call seek (cl, BOF)
+ call seek (pl, BOF)
+ pd = 0
+ nskip = req_num
+ } else
+ nskip = req_num - prev_num
+ }
+
+ # Initialize the polygon id.
+ ncount = 0
+ ld = prev_num
+
+ # Find the correct object and shift the coordinates.
+ repeat {
+
+ # Read the coordinates and the polygon.
+ stat = ap_ycoords (cl, delim, xshift, yshift, stdin)
+ if (stat == EOF) {
+ ncount = EOF
+ } else if (stat == NEXT_POLYGON || pd == 0) {
+ call apsetr (py, PYX, apstatr (py, PYCX))
+ call apsetr (py, PYY, apstatr (py, PYCY))
+ nver = ap_yget (py, im, pl, delim, x, y, maxnver)
+ if (nver == EOF)
+ ncount = EOF
+ else if (nver > 0)
+ pd = pd + 1
+ }
+
+ # Shift the polygon coordinates.
+ if (stat == THIS_OBJECT && ncount != EOF && nver > 0) {
+ switch (apstati(py,WCSIN)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_itol (py, xshift, yshift, xshift, yshift, 1)
+ case WCS_TV:
+ call ap_vtol (im, xshift, yshift, xshift, yshift, 1)
+ default:
+ ;
+ }
+ call aaddkr (x, (xshift - apstatr (py, PYCX)), x, nver + 1)
+ call aaddkr (y, (yshift - apstatr (py, PYCY)), y, nver + 1)
+ call apsetr (py, PYCX, xshift)
+ call apsetr (py, PYCY, yshift)
+ switch (apstati(py,WCSOUT)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (py, xshift, yshift, xshift, yshift, 1)
+ case WCS_TV:
+ call ap_ltov (im, xshift, yshift, xshift, yshift, 1)
+ default:
+ ;
+ }
+ call apsetr (py, OPYCX, xshift)
+ call apsetr (py, OPYCY, yshift)
+ ncount = ncount + 1
+ ld = ld + 1
+ }
+
+ } until (ncount == EOF || ncount == nskip)
+
+ # Get the correct id.
+ if (req_num <= prev_num)
+ ld = ncount
+
+ call sfree (sp)
+
+ if (ncount == EOF) {
+ return (EOF)
+ } else if (id != NULL) {
+ iferr {
+ call greactivate (id, 0)
+ call gscur (id, apstatr (py, PYCX), apstatr (py, PYCY))
+ call gdeactivate (id, 0)
+ } then
+ ;
+ return (nver)
+ } else {
+ return (nver)
+ }
+ }
+
+end
diff --git a/noao/digiphot/apphot/polyphot/apypars.x b/noao/digiphot/apphot/polyphot/apypars.x
new file mode 100644
index 00000000..4f988323
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apypars.x
@@ -0,0 +1,20 @@
+# AP_PYPARS -- Procedure to write the current polyphot parameters to the
+# output file.
+
+procedure ap_pypars (ap)
+
+pointer ap # pointer to apphot structure
+
+begin
+ # Write the data dependent parameters.
+ call ap_dapars (ap)
+
+ # Write the centering parameters.
+ call ap_cepars (ap)
+
+ # Write the sky fitting parameters.
+ call ap_sapars (ap)
+
+ # Set the photometry parameters.
+ call ap_popars (ap)
+end
diff --git a/noao/digiphot/apphot/polyphot/apyphot.x b/noao/digiphot/apphot/polyphot/apyphot.x
new file mode 100644
index 00000000..cd7bac0a
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apyphot.x
@@ -0,0 +1,577 @@
+include <ctype.h>
+include <gset.h>
+include <imhdr.h>
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/fitsky.h"
+include "../lib/polyphot.h"
+
+define HELPFILE "apphot$polyphot/polyphot.key"
+
+# AP_YPHOT -- Compute the flux inside polygonal apertures.
+
+int procedure ap_yphot (py, im, cl, pl, gd, id, out, stid, interactive, cache)
+
+pointer py # pointer to apphot structure
+pointer im # pointer to IRAF image
+int cl # coordinate file descriptor
+int pl # starlist file descriptor
+pointer gd # pointer to graphcis stream
+pointer id # pointer to image display stream
+int out # output file descriptor
+int stid # output file sequence number
+int interactive # interactive mode
+int cache # cache the input image pixels
+
+real wx, wy
+pointer sp, x, y, xout, yout, cmd
+int nvertices, cier, sier, pier, wcs, key, ip, colonkey
+int prev_num, req_num, ptid, ltid, delim, newlist, newimage
+int newcenterbuf, newcenter, newskybuf, newsky, newmagbuf, newmag
+int req_size, old_size, buf_size, memstat
+
+real apstatr()
+int ap_ymkpoly(), ap_yfit(), clgcur(), apfitsky(), aprefitsky()
+int apstati(), ctoi(), ap_ynextobj(), ap_ycenter(), ap_yrecenter()
+int apgqverify(), apgtverify(), ap_yradsetup(), apnew(), ap_avsky()
+int ap_memstat(), sizeof()
+bool fp_equalr()
+data delim /';'/
+
+define endswitch_ 99
+
+begin
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (x, MAX_NVERTICES + 1, TY_REAL)
+ call salloc (y, MAX_NVERTICES + 1, TY_REAL)
+ call salloc (xout, MAX_NVERTICES + 1, TY_REAL)
+ call salloc (yout, MAX_NVERTICES + 1, TY_REAL)
+
+ # Initialize the cursor read.
+ key = ' '
+ Memc[cmd] = EOS
+
+ # Initialize the fit.
+ newimage = NO
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ cier = AP_OK; sier = AP_OK; pier = AP_OK
+
+ # Initialize the sequencing.
+ newlist = NO
+ ptid = 0
+ ltid = 0
+
+ # Loop over the polygon file.
+ nvertices = 0
+ while (clgcur ("icommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+
+ # Store the current coordinates.
+ call ap_vtol (im, wx, wy, wx, wy, 1)
+ call apsetr (py, CWX, wx)
+ call apsetr (py, CWY, wy)
+
+ # Has the polygon moved ?
+ if (apnew (py, wx, wy, apstatr (py, PYCX), apstatr (py, PYCY),
+ newlist) == YES) {
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ }
+
+ # Loop over the colon commands.
+ switch (key) {
+
+ # Quit.
+ case 'q':
+ if (interactive == YES) {
+ if (apgqverify ("polyphot", py, key) == YES) {
+ call sfree (sp)
+ return (apgtverify (key))
+ }
+ } else {
+ call sfree (sp)
+ return (NO)
+ }
+
+ # Print the help page.
+ case '?':
+ if ((id != NULL) && (id == gd))
+ call gpagefile (id, HELPFILE, "")
+ else if (interactive == YES)
+ call pagefile (HELPFILE, "[space=morehelp,q=quit,?=help]")
+
+ # Plot a centered stellar radial profile.
+ case 'd':
+ if (interactive == YES)
+ call ap_qrad (py, im, wx, wy, gd)
+
+ # Setup the parameters using a radial profile plot
+ case 'i':
+ if (interactive == YES) {
+ nvertices = ap_yradsetup (py, im, id, gd, out, stid,
+ Memr[x], Memr[y], MAX_NVERTICES)
+ newlist = NO
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ }
+
+ # Verify the critical parameters.
+ case 'v':
+ call ap_yconfirm (py, out, stid)
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+
+ # Define a polygon interactively.
+ case 'g':
+ if (interactive == YES) {
+ if (id == gd)
+ nvertices = ap_ymkpoly (py, im, id, Memr[x], Memr[y],
+ MAX_NVERTICES, NO)
+ else
+ nvertices = ap_ymkpoly (py, im, id, Memr[x], Memr[y],
+ MAX_NVERTICES, YES)
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ newlist = NO
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ }
+
+ # Print error messages.
+ case 'e':
+ if (interactive == YES)
+ call ap_pyerrors (py, cier, sier, pier)
+
+ # Rewind the polygon and coordinate lists.
+ case 'r':
+ if (pl != NULL) {
+ call seek (pl, BOF)
+ if (cl != NULL)
+ call seek (cl, BOF)
+ ptid = 0
+ ltid = 0
+ } else if (interactive == YES)
+ call printf ("No polygon list\n")
+
+ # Show/set polyphot parameters.
+ case ':':
+ for (ip = 1; IS_WHITE(Memc[cmd+ip-1]); ip = ip + 1)
+ ;
+
+ colonkey = Memc[cmd+ip-1]
+ switch (colonkey) {
+ case 'm', 'n':
+
+ # Show/set polyphot parameters
+ if (Memc[cmd+ip] != EOS && Memc[cmd+ip] != ' ') {
+ call ap_ycolon (py, im, pl, cl, out, stid, ptid, ltid,
+ Memc[cmd], newimage, newcenterbuf, newcenter,
+ newskybuf, newsky, newmagbuf, newmag)
+ goto endswitch_
+ }
+
+ # Measure the next object in the list.
+ if (pl != NULL) {
+ if (interactive == YES)
+ call printf ("No polygon list\n")
+ goto endswitch_
+ }
+
+ # Get the next polygon.
+ ip = ip + 1
+ prev_num = ltid
+ if (ctoi (Memc[cmd], ip, req_num) <= 0)
+ req_num = ltid + 1
+ nvertices = ap_ynextobj (py, im, id, pl, cl, delim, Memr[x],
+ Memr[y], MAX_NVERTICES, prev_num, req_num, ltid, ptid)
+ if (nvertices == EOF) {
+ if (interactive == YES)
+ call printf (
+ "End of polygon list, use r key to rewind\n")
+ goto endswitch_
+ }
+
+ # Move to the next object.
+ newlist = YES
+ if (colonkey == 'm') {
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ goto endswitch_
+ }
+
+ # Fit the center, sky and measure polygon.
+ cier = ap_ycenter (py, im, apstatr (py, PYCX), apstatr (py,
+ PYCY), Memr[x], Memr[y], nvertices + 1)
+ sier = apfitsky (py, im, apstatr (py, PYCX), apstatr (py,
+ PYCY), NULL, gd)
+ pier = ap_yfit (py, im, Memr[x], Memr[y], nvertices + 1,
+ apstatr (py, SKY_MODE), apstatr (py, SKY_SIGMA),
+ apstati (py, NSKY))
+ if (interactive == YES)
+ call ap_qyprint (py, cier, sier, pier)
+
+ # Draw the polygon.
+ if (id != NULL) {
+ call appymark (py, id, Memr[x], Memr[y], nvertices + 1,
+ apstati (py, MKCENTER), apstati (py, MKSKY),
+ apstati (py, MKPOLYGON))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ # Write the results to output.
+ if (stid == 1)
+ call ap_param (py, out, "polyphot")
+
+ switch (apstati(py,WCSOUT)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (py, Memr[x], Memr[y], Memr[xout],
+ Memr[yout], nvertices + 1)
+ case WCS_TV:
+ call ap_ltov (im, Memr[x], Memr[y], Memr[xout],
+ Memr[yout], nvertices + 1)
+ default:
+ call amovr (Memr[x], Memr[xout], nvertices + 1)
+ call amovr (Memr[y], Memr[yout], nvertices + 1)
+ }
+ if (newlist == YES)
+ call ap_yprint (py, out, Memr[xout], Memr[yout],
+ nvertices, stid, ltid, ptid, cier, sier, pier)
+ else
+ call ap_yprint (py, out, Memr[xout], Memr[yout],
+ nvertices, stid, 0, ptid, cier, sier, pier)
+
+ # Set up for the next object.
+ stid = stid + 1
+ newcenterbuf = NO; newcenter = NO
+ newskybuf = NO; newsky = NO
+ newmagbuf = NO; newmag = NO
+
+ # Show/set polyphot parameters.
+ default:
+ call ap_ycolon (py, im, pl, cl, out, stid, ptid, ltid,
+ Memc[cmd], newimage, newcenterbuf, newcenter,
+ newskybuf, newsky, newmagbuf, newmag)
+ }
+
+ # Reestablish the image display viewport and window.
+ if (newimage == YES) {
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[cmd], im, 4)
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+ }
+ newimage = NO
+
+ # Get measure next object in the list.
+ case 'm', 'n':
+ if (pl == NULL) {
+ if (interactive == YES)
+ call printf ("No polygon list\n")
+ goto endswitch_
+ }
+
+ # Get the next polygon.
+ prev_num = ltid
+ req_num = ltid + 1
+ nvertices = ap_ynextobj (py, im, id, pl, cl, delim, Memr[x],
+ Memr[y], MAX_NVERTICES, prev_num, req_num, ltid, ptid)
+ if (nvertices == EOF) {
+ if (interactive == YES)
+ call printf (
+ "End of polygon list, use r key to rewind\n")
+ goto endswitch_
+ }
+
+ # Move to next object.
+ newlist = YES
+ if (key == 'm') {
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ goto endswitch_
+ }
+
+ # Measure next object.
+ cier = ap_ycenter (py, im, apstatr (py, PYCX), apstatr (py,
+ PYCY), Memr[x], Memr[y], nvertices + 1)
+ sier = apfitsky (py, im, apstatr (py, PYCX), apstatr (py,
+ PYCY), NULL, gd)
+ pier = ap_yfit (py, im, Memr[x], Memr[y], nvertices + 1,
+ apstatr (py, SKY_MODE), apstatr (py, SKY_SIGMA),
+ apstati (py, NSKY))
+ if (interactive == YES)
+ call ap_qyprint (py, cier, sier, pier)
+
+ # Draw the polygon.
+ if (id != NULL) {
+ call appymark (py, id, Memr[x], Memr[y], nvertices + 1,
+ apstati (py, MKCENTER), apstati (py, MKSKY),
+ apstati (py, MKPOLYGON))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ # Write the results to output.
+ if (stid == 1)
+ call ap_param (py, out, "polyphot")
+ switch (apstati(py,WCSOUT)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (py, Memr[x], Memr[y], Memr[xout], Memr[yout],
+ nvertices + 1)
+ case WCS_TV:
+ call ap_ltov (im, Memr[x], Memr[y], Memr[xout], Memr[yout],
+ nvertices + 1)
+ default:
+ call amovr (Memr[x], Memr[xout], nvertices + 1)
+ call amovr (Memr[y], Memr[yout], nvertices + 1)
+ }
+ if (newlist == YES)
+ call ap_yprint (py, out, Memr[xout], Memr[yout], nvertices,
+ stid, ltid, ptid, cier, sier, pier)
+ else
+ call ap_yprint (py, out, Memr[xout], Memr[yout], nvertices,
+ stid, 0, ptid, cier, sier, pier)
+
+ # Set up for the next object.
+ stid = stid + 1
+ newcenterbuf = NO; newcenter = NO
+ newskybuf = NO; newsky = NO
+ newmagbuf = NO; newmag = NO
+
+ # Process the remainder of the list.
+ case 'l':
+ if (pl != NULL) {
+ call ap_ybphot (py, im, cl, pl, out, stid, ltid, ptid, id,
+ YES)
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ } else if (interactive == YES)
+ call printf ("No polygon list\n")
+
+ # Save current parameters in the pset file.
+ case 'w':
+ call ap_pypars (py)
+
+ # Center the current polygon around the cursor poition.
+ case 'c':
+ if (newcenterbuf == YES)
+ cier = ap_ycenter (py, im, wx, wy, Memr[x], Memr[y],
+ nvertices + 1)
+ else if (newcenter == YES)
+ cier = ap_yrecenter (py, im, Memr[x], Memr[y],
+ nvertices + 1, cier)
+ if (interactive == YES)
+ call ap_qcenter (py, cier)
+ if (id != NULL) {
+ call apmark (py, id, apstati (py, MKCENTER), NO, NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ newcenterbuf = NO; newcenter = NO
+
+ # Fit the sky around the cursor position.
+ case 't':
+ if (newskybuf == YES || ! fp_equalr (wx,
+ apstatr (py, SXCUR)) || ! fp_equalr (wy, apstatr (py,
+ SYCUR)))
+ sier = apfitsky (py, im, wx, wy, NULL, gd)
+ else if (newsky == YES)
+ sier = aprefitsky (py, im, gd)
+ if (interactive == YES)
+ call ap_qspsky (py, sier)
+ if (id != NULL) {
+ call apmark (py, id, NO, apstati (py, MKSKY), NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ newskybuf = NO; newsky = NO
+
+ # Compute the average of several sky measurements around
+ # different cursor postions.
+ case 'a':
+ sier = ap_avsky (py, im, stid, NULL, id, gd, interactive)
+ if (interactive == YES)
+ call ap_qaspsky (py, sier)
+ newskybuf = NO; newsky = NO
+
+ # Fit sky in an annulus around the current polygon.
+ case 's':
+ if (newskybuf == YES || ! fp_equalr (apstatr (py, PYCX),
+ apstatr (py, SXCUR)) || ! fp_equalr (apstatr (py, PYCY),
+ apstatr (py, SYCUR)))
+ sier = apfitsky (py, im, apstatr (py, PYCX), apstatr (py,
+ PYCY), NULL, gd)
+ else if (newsky == YES)
+ sier = aprefitsky (py, im, gd)
+ if (interactive == YES)
+ call ap_qspsky (py, sier)
+ if (id != NULL) {
+ call apmark (py, id, NO, apstati (py, MKSKY), NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ newskybuf = NO; newsky = NO
+
+ # Compute the magnitudes of current polygon using the current sky.
+ case 'p', 'o':
+ if (newcenterbuf == YES)
+ cier = ap_ycenter (py, im, wx, wy, Memr[x], Memr[y],
+ nvertices + 1)
+ else if (newcenter == YES)
+ cier = ap_yrecenter (py, im, Memr[x], Memr[y],
+ nvertices + 1, cier)
+ pier = ap_yfit (py, im, Memr[x], Memr[y], nvertices + 1,
+ apstatr (py, SKY_MODE), apstatr (py, SKY_SIGMA),
+ apstati (py, NSKY))
+ if (interactive == YES)
+ call ap_qyprint (py, cier, sier, pier)
+ if (id != NULL) {
+ call appymark (py, id, Memr[x], Memr[y], nvertices + 1,
+ NO, NO, apstati (py, MKPOLYGON))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ newcenterbuf = NO; newcenter = NO
+ newmagbuf = NO; newmag = NO
+
+ # Write the results.
+ if (key == 'o') {
+ if (stid == 1)
+ call ap_param (py, out, "polyphot")
+ switch (apstati(py,WCSOUT)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (py, Memr[x], Memr[y], Memr[xout],
+ Memr[yout], nvertices + 1)
+ case WCS_TV:
+ call ap_ltov (im, Memr[x], Memr[y], Memr[xout],
+ Memr[yout], nvertices + 1)
+ default:
+ call amovr (Memr[x], Memr[xout], nvertices + 1)
+ call amovr (Memr[y], Memr[yout], nvertices + 1)
+ }
+ if (newlist == YES)
+ call ap_yprint (py, out, Memr[xout], Memr[yout],
+ nvertices, stid, ltid, ptid, cier, sier, pier)
+ else
+ call ap_yprint (py, out, Memr[xout], Memr[yout],
+ nvertices, stid, 0, ptid, cier, sier, pier)
+ stid = stid + 1
+ }
+
+ # Center, compute the sky and the magnitudes and save the results.
+ case 'h', 'j', 'f', ' ':
+
+ # Compute the centers.
+ if (key == 'f' || key == ' ') {
+ if (newcenterbuf == YES)
+ cier = ap_ycenter (py, im, wx, wy, Memr[x], Memr[y],
+ nvertices + 1)
+ else if (newcenter == YES)
+ cier = ap_yrecenter (py, im, Memr[x], Memr[y],
+ nvertices + 1, cier)
+ } else {
+ if (newcenterbuf == YES)
+ cier = ap_ycenter (py, im, apstatr (py, PYCX),
+ apstatr (py, PYCY), Memr[x], Memr[y], nvertices + 1)
+ else if (newcenter == YES)
+ cier = ap_yrecenter (py, im, Memr[x], Memr[y],
+ nvertices + 1, cier)
+ }
+
+ # Compute the sky values and the magnitudes.
+ if (newskybuf == YES || ! fp_equalr (apstatr (py,
+ PYCX), apstatr (py, SXCUR)) || ! fp_equalr (apstatr (py,
+ PYCY), apstatr (py, SYCUR))) sier = apfitsky (py, im,
+ apstatr (py, PYCX), apstatr (py, PYCY), NULL, gd)
+ else if (newsky == YES)
+ sier = aprefitsky (py, im, gd)
+ pier = ap_yfit (py, im, Memr[x], Memr[y], nvertices + 1,
+ apstatr (py, SKY_MODE), apstatr (py, SKY_SIGMA),
+ apstati (py, NSKY))
+
+ if (interactive == YES)
+ call ap_qyprint (py, cier, sier, pier)
+ if (id != NULL) {
+ call appymark (py, id, Memr[x], Memr[y], nvertices + 1,
+ apstati (py, MKCENTER), apstati (py, MKSKY),
+ apstati (py, MKPOLYGON))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ newcenterbuf = NO; newcenter = NO
+ newskybuf = NO; newsky = NO
+ newmagbuf = NO; newmag = NO
+
+ # Write the results to an output file.
+ if (key == ' ' || key == 'j') {
+ if (stid == 1)
+ call ap_param (py, out, "polyphot")
+ switch (apstati(py,WCSOUT)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (py, Memr[x], Memr[y], Memr[xout],
+ Memr[yout], nvertices + 1)
+ case WCS_TV:
+ call ap_ltov (im, Memr[x], Memr[y], Memr[xout],
+ Memr[yout], nvertices + 1)
+ default:
+ call amovr (Memr[x], Memr[xout], nvertices + 1)
+ call amovr (Memr[y], Memr[yout], nvertices + 1)
+ }
+ if (newlist == YES)
+ call ap_yprint (py, out, Memr[xout], Memr[yout],
+ nvertices, stid, ltid, ptid, cier, sier, pier)
+ else
+ call ap_yprint (py, out, Memr[xout], Memr[yout],
+ nvertices, stid, 0, ptid, cier, sier, pier)
+ stid = stid + 1
+ }
+
+ default:
+ call printf ("Unknown or ambigous keystroke command\n")
+ }
+
+endswitch_
+ # Reset the keystroke and command defaults.
+ key = ' '
+ Memc[cmd] = EOS
+ call apsetr (py, WX, apstatr (py, CWX))
+ call apsetr (py, WY, apstatr (py, CWY))
+ }
+
+end
diff --git a/noao/digiphot/apphot/polyphot/apyprint.x b/noao/digiphot/apphot/polyphot/apyprint.x
new file mode 100644
index 00000000..dda24c3f
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apyprint.x
@@ -0,0 +1,94 @@
+include "../lib/apphot.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/polyphot.h"
+
+# AP_YPRINT -- Write the results of the polyphot task to the output file.
+
+procedure ap_yprint (py, fd, xver, yver, nver, id, lid, pid, cier, sier, pier)
+
+pointer py # pointer to apphot structure
+int fd # output file descriptor
+real xver[ARB] # coords of x vertices
+real yver[ARB] # coords of y vertices
+int nver # number of vertices
+int id # id number of str
+int lid # list id number of star
+int pid # polygon number
+int cier # centering error
+int sier # sky fitting error
+int pier # photometric error
+
+real apstatr()
+
+begin
+ if (fd == NULL)
+ return
+
+ # Write object id parameters.
+ call ap_wid (py, fd, apstatr (py, OXINIT), apstatr (py, OYINIT), id,
+ lid, '\\')
+
+ # Write the centering parameters
+ call ap_wcres (py, fd, cier, '\\')
+
+ # Write the fitsky parameters.
+ call ap_wsres (py, fd, sier, '\\')
+
+ # Write the polyphot parameters
+ call ap_wlres (py, fd, xver, yver, nver, pid, pier)
+end
+
+
+# AP_QYPRINT -- Print a quick summary of the polyphot results on the standard
+# output.
+
+procedure ap_qyprint (py, cier, sier, pier)
+
+pointer py # pointer to apphot structure
+int cier # centering error
+int sier # sky fitting error
+int pier # photometry error
+
+pointer sp, imname
+real apstatr()
+
+begin
+ # Allocate space.
+ call smark (sp)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+
+ # Print polyphot magnitudes.
+ #call apstats (py, IMNAME, Memc[imname], SZ_FNAME)
+ call apstats (py, IMROOT, Memc[imname], SZ_FNAME)
+ call printf ("%s %8.2f %8.2f %8g ")
+ call pargstr (Memc[imname])
+ call pargr (apstatr (py, OPYCX))
+ call pargr (apstatr (py, OPYCY))
+ call pargr (apstatr (py, SKY_MODE))
+ call printf ("%7.3f %s\n")
+ call pargr (apstatr (py, PYMAG))
+ if (cier != AP_OK || sier != AP_OK || pier != AP_OK)
+ call pargstr ("err")
+ else
+ call pargstr ("ok")
+
+ call sfree (sp)
+end
+
+
+# AP_YHDR -- Write the polyphot header banner to the output file.
+
+procedure ap_yhdr (ap, fd)
+
+pointer ap # apphot structure
+int fd # output file descriptor
+
+begin
+ if (fd == NULL)
+ return
+ call ap_idhdr (ap, fd)
+ call ap_chdr (ap, fd)
+ call ap_shdr (ap, fd)
+ call ap_plhdr (ap, fd)
+end
diff --git a/noao/digiphot/apphot/polyphot/apyradsetup.x b/noao/digiphot/apphot/polyphot/apyradsetup.x
new file mode 100644
index 00000000..a966110b
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apyradsetup.x
@@ -0,0 +1,135 @@
+include "../lib/fitsky.h"
+include "../lib/polyphot.h"
+
+define HELPFILE "apphot$polyphot/ipolyphot.key"
+
+# AP_YRADSETUP - Set up polyphot interactively using a radial profile
+# plot of a bright star.
+
+int procedure ap_yradsetup (ap, im, id, gd, out, stid, x, y, max_nvertices)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to the IRAF image
+pointer id # pointer to the image display
+pointer gd # pointer to graphics stream
+int out # output file descriptor
+int stid # output file sequence number
+real x[ARB] # array of x vertices
+real y[ARB] # array of y vertices
+int max_nvertices # maximum number of vertices
+
+int nvertices, cier, sier, pier, key, wcs
+pointer sp, str, cmd
+real rmin, rmax, imin, imax, u1, u2, v1, v2, x1, x2, y1, y2
+real xcenter, ycenter, xc, yc, rval
+
+int ap_ycenter(), clgcur(), ap_showplot()
+int apfitsky(), ap_yfit(), apstati(), ap_ymkpoly()
+real apstatr(), ap_cfwhmpsf(), ap_ccapert(), ap_cannulus(), ap_csigma()
+real ap_cdannulus(), ap_cdatamin(), ap_cdatamax()
+real ap_crgrow(), ap_crclean(), ap_crclip()
+
+begin
+ # Mark the polygon interactively.
+ if (id == gd)
+ nvertices = ap_ymkpoly (ap, im, id, x, y, max_nvertices, NO)
+ else
+ nvertices = ap_ymkpoly (ap, im, id, x, y, max_nvertices, YES)
+ if (id != NULL) {
+ if (gd == id)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ if (nvertices <= 0)
+ return (nvertices)
+
+ # Store the viewport and window coordinates.
+ call ggview (gd, u1, u2, v1, v2)
+ call ggwind (gd, x1, x2, y1, y2)
+
+ # Check for open display device and graphics stream.
+ if (gd == NULL)
+ return (0)
+ call greactivate (gd, 0)
+
+ # Show the plot.
+ if (ap_showplot (ap, im, apstatr (ap, PYCX), apstatr (ap, PYCY), gd,
+ xcenter, ycenter, rmin, rmax, imin, imax) == ERR) {
+ call gdeactivate (gd, 0)
+ return (nvertices)
+ }
+
+ # Allocate memory.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ call printf (
+ "Waiting for setup menu command (?=help, v=default setup, q=quit):\n")
+ while (clgcur ("gcommands", xc, yc, wcs, key, Memc[cmd],
+ SZ_LINE) != EOF) {
+
+ switch (key) {
+
+ case 'q':
+ break
+ case '?':
+ call gpagefile (gd, HELPFILE, "")
+ case 'f':
+ rval = ap_cfwhmpsf (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'h':
+ #rval = ap_ccthresh (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'c':
+ rval = ap_ccapert (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 's':
+ rval = ap_csigma (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'n':
+ rval = ap_crclean (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'p':
+ rval = ap_crclip (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'l':
+ rval = ap_cdatamin (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'u':
+ rval = ap_cdatamax (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'a':
+ rval = ap_cannulus (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'd':
+ rval = ap_cdannulus (ap, gd, out, stid, apstatr (ap, ANNULUS),
+ rmin, rmax, imin, imax)
+ case 'g':
+ rval = ap_crgrow (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'v':
+ rval = ap_cfwhmpsf (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_ccapert (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_csigma (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_cannulus (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_cdannulus (ap, gd, out, stid, apstatr (ap, ANNULUS),
+ rmin, rmax, imin, imax)
+ default:
+ call printf ("Unknown or ambiguous keystroke command\007\n")
+ }
+ call printf (
+ "Waiting for setup menu command (?=help, v=default setup, q=quit):\n")
+ }
+ call printf (
+ "Interactive setup is complete. Type w to save parameters.\n")
+
+ # Restore the viewport and window coordinates.
+ call gsview (gd, u1, u2, v1, v2)
+ call gswind (gd, x1, x2, y1, y2)
+
+ # Clean up memory space.
+ call gdeactivate (gd, 0)
+ call sfree (sp)
+
+ # Print the answer.
+ cier = ap_ycenter (ap, im, xcenter, ycenter, x, y, nvertices + 1)
+ sier = apfitsky (ap, im, apstatr (ap, PYCX), apstatr (ap, PYCY),
+ NULL, gd)
+ pier = ap_yfit (ap, im, x, y, nvertices + 1, apstatr (ap, SKY_MODE),
+ apstatr (ap, SKY_SIGMA), apstati (ap, NSKY))
+ call ap_qyprint (ap, cier, sier, pier)
+
+ return (nvertices)
+end
diff --git a/noao/digiphot/apphot/polyphot/apyshift.x b/noao/digiphot/apphot/polyphot/apyshift.x
new file mode 100644
index 00000000..4fd56cbe
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apyshift.x
@@ -0,0 +1,41 @@
+include "../lib/apphot.h"
+include "../lib/polyphot.h"
+
+# AP_YSHIFT -- Shift a polygon to a new center position.
+
+procedure ap_yshift (py, im, x, y, nver, newx, newy)
+
+pointer py # pointer to the polyphot structure
+pointer im # the input image descriptor
+real x[ARB] # x coordinates of the vertices
+real y[ARB] # y coordinates of the vertices
+int nver # number of vertices
+real newx, newy # new x and y coordinates of center
+
+real xshift, yshift
+real apstatr()
+int apstati()
+
+begin
+ call apsetr (py, PYX, apstatr (py, PYCX))
+ call apsetr (py, PYY, apstatr (py, PYCY))
+
+ xshift = newx - apstatr (py, PYCX)
+ yshift = newy - apstatr (py, PYCY)
+ call aaddkr (x, xshift, x, nver)
+ call aaddkr (y, yshift, y, nver)
+ call apsetr (py, PYCX, newx)
+ call apsetr (py, PYCY, newy)
+
+ switch (apstati(py,WCSOUT)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (py, newx, newy, xshift, yshift, 1)
+ case WCS_TV:
+ call ap_ltov (im, newx, newy, xshift, yshift, 1)
+ default:
+ xshift = newx
+ yshift = newy
+ }
+ call apsetr (py, OPYCX, xshift)
+ call apsetr (py, OPYCY, yshift)
+end
diff --git a/noao/digiphot/apphot/polyphot/apywrite.x b/noao/digiphot/apphot/polyphot/apywrite.x
new file mode 100644
index 00000000..b246aac3
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/apywrite.x
@@ -0,0 +1,92 @@
+include "../lib/apphot.h"
+include "../lib/polyphot.h"
+
+# AP_YWRITE -- Procedure to write a polygon to a file.
+
+procedure ap_ywrite (py, im, cl, pl, x, y, nvertices, cid, pid, firstpoly,
+ newpoly)
+
+pointer py # pointer to the apphot structure
+pointer im # the input image descriptor
+int cl # pointer to the coordinate list file
+int pl # pointer to the polygon list file
+real x[ARB] # x coordinates of the vertices
+real y[ARB] # y coordinates of the vertices
+int nvertices # number of vertices
+int cid # coordinate list index
+int pid # polygon list index
+int firstpoly # first polygon measured
+int newpoly # new polygon
+
+real xtemp, ytemp
+int i
+real apstatr()
+int apstati()
+
+begin
+ # Make sure the output files are at EOF.
+ if (pl == NULL)
+ return
+ call seek (pl, EOF)
+ if (cl != NULL)
+ call seek (cl, EOF)
+
+ if (newpoly == YES) {
+
+ # Terminate the coord list that belongs with the first polygon.
+ if (firstpoly == NO && cl != NULL)
+ call fprintf (cl, ";\n")
+
+ # Write out the coordinates.
+ do i = 1, nvertices {
+ switch (apstati(py, WCSOUT)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (py, x[i], y[i], xtemp, ytemp, 1)
+ case WCS_TV:
+ call ap_ltov (im, x[i], y[i], xtemp, ytemp, 1)
+ default:
+ xtemp = x[i]
+ ytemp = y[i]
+ }
+ call fprintf (pl, "%g %g\n")
+ call pargr (xtemp)
+ call pargr (ytemp)
+ }
+ if (nvertices > 0)
+ call fprintf (pl, ";\n")
+
+ pid = pid + 1
+
+ # Reset polygon parameters.
+ newpoly = NO
+ if (firstpoly == YES)
+ firstpoly = NO
+ }
+
+ # Write out the central coordinates of the polygon.
+ if (firstpoly == NO && cl != NULL) {
+
+ switch (apstati(py, WCSOUT)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (py, apstatr(py,CWX), apstatr(py,CWY), xtemp,
+ ytemp, 1)
+ case WCS_TV:
+ call ap_ltov (im, apstatr(py,CWX), apstatr(py,CWY), xtemp,
+ ytemp, 1)
+ default:
+ xtemp = apstatr (py, CWX)
+ ytemp = apstatr (py, CWY)
+ }
+ call fprintf (cl, "%g %g\n")
+ call pargr (xtemp)
+ call pargr (ytemp)
+
+ cid = cid + 1
+ }
+
+ # Flush the output files.
+ if (pl != NULL)
+ call flush (pl)
+ if (cl != NULL)
+ call flush (cl)
+end
diff --git a/noao/digiphot/apphot/polyphot/ipolyphot.key b/noao/digiphot/apphot/polyphot/ipolyphot.key
new file mode 100644
index 00000000..f8ef878c
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/ipolyphot.key
@@ -0,0 +1,16 @@
+ Interactive Photometry Setup Menu
+
+ v Mark and verify the critical parameters (f,c,s,a,d)
+
+ f Mark and verify the psf full-width half-maximum
+ s Mark and verify the standard deviation of the background
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
+
+ c Mark and verify the centering box width
+ n Mark and verify the cleaning radius
+ p Mark and verify the clipping radius
+
+ a Mark and verify the inner radius of the sky annulus
+ d Mark and verify the width of the sky annulus
+ g Mark and verify the region growing radius
diff --git a/noao/digiphot/apphot/polyphot/mkpkg b/noao/digiphot/apphot/polyphot/mkpkg
new file mode 100644
index 00000000..b98b6803
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/mkpkg
@@ -0,0 +1,60 @@
+# POLYPHOT and POLYMARK routines
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ # POLYPHOT routines
+
+ appyerrors.x ../lib/polyphot.h
+ apgypars.x ../lib/display.h ../lib/fitsky.h \
+ ../lib/noise.h ../lib/polyphot.h \
+ ../lib/center.h
+ apycenter.x ../lib/center.h ../lib/polyphot.h
+ apyconfirm.x ../lib/apphot.h ../lib/noise.h \
+ ../lib/center.h ../lib/fitsky.h
+ apycoords.x ../lib/polyphot.h
+ apyfree.x ../lib/apphotdef.h ../lib/polyphotdef.h
+ apyinit.x ../lib/apphotdef.h ../lib/polyphotdef.h
+ apynextobj.x <fset.h> ../lib/apphot.h \
+ ../lib/polyphot.h
+ apypars.x
+ apyradsetup.x ../lib/fitsky.h ../lib/polyphot.h
+ apyshift.x ../lib/apphot.h ../lib/polyphot.h
+ apycolon.x ../lib/polyphot.h ../lib/center.h \
+ ../lib/apphot.h ../lib/fitsky.h \
+ ../lib/noise.h ../lib/display.h \
+ <gset.h> <error.h>
+ apyfit.x ../lib/polyphot.h ../lib/noise.h \
+ ../lib/apphot.h <imhdr.h> \
+ <mach.h>
+ apyget.x <fset.h> ../lib/apphot.h \
+ ../lib/fitsky.h ../lib/polyphot.h
+ polyshow.x ../lib/display.h ../lib/polyphot.h
+ apybphot.x <fset.h> ../lib/display.h \
+ ../lib/polyphot.h ../lib/fitsky.h \
+ ../lib/apphot.h
+ apyphot.x <ctype.h> <gset.h> \
+ ../lib/display.h ../lib/polyphot.h \
+ ../lib/fitsky.h ../lib/apphot.h \
+ <imhdr.h>
+ apyprint.x ../lib/fitsky.h ../lib/center.h \
+ ../lib/apphot.h ../lib/polyphot.h
+ t_polyphot.x <gset.h> <fset.h> \
+ ../lib/apphot.h ../lib/polyphot.h \
+ <imhdr.h>
+
+ # POLYMARK routines
+
+ t_polymark.x <gset.h> <fset.h> \
+ "../lib/apphot.h" "../lib/polyphot.h" \
+ <imhdr.h>
+ apmkpylist.x <gset.h> <ctype.h> \
+ "../lib/apphot.h" "../lib/polyphot.h"
+ apydraw.x "../lib/polyphot.h"
+ apymkinit.x "../lib/apphotdef.h" "../lib/noise.h"
+ apymkfree.x "../lib/apphotdef.h"
+ apywrite.x "../lib/apphot.h" "../lib/polyphot.h"
+ ;
diff --git a/noao/digiphot/apphot/polyphot/polymark.key b/noao/digiphot/apphot/polyphot/polymark.key
new file mode 100644
index 00000000..9e1901a1
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/polymark.key
@@ -0,0 +1,16 @@
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+d Plot radial profile of star near cursor
+g Define the current polygonal aperture
+f Draw the current polygon on the display
+spbar Draw the current polygon on the display, output the polygon
+r Rewind the polygon list
+m Draw the next polygon in the polygon list on the display
+l Draw all the remaining polygons in the list on the display
+q Exit
+
+ Colon commands
+
+:m [n] Draw the next [nth] polygon in the polygon list on the display
diff --git a/noao/digiphot/apphot/polyphot/polyphot.key b/noao/digiphot/apphot/polyphot/polyphot.key
new file mode 100644
index 00000000..e2c92da2
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/polyphot.key
@@ -0,0 +1,110 @@
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+v Verify the critical parameters
+w Store the current parameters
+d Plot radial profile of current object
+i Define current polygon, graphically set parameters using current object
+g Define current polygon
+c Fit center for current object
+t Fit sky around cursor
+a Average sky values fit around several cursor positions
+s Fit sky around current object
+h Do photometry for current polygon
+j Do photometry for current polygon, output results
+p Do photometry for current object using current sky
+o Do photometry for current object using current sky, output results
+f Do photometry for current object
+spbar Do photometry for current object, output results
+m Move to next object in coordinate list
+n Do photometry for next object in coordinate list, output results
+l Do photometry for remaining objects in coordinate list, output results
+r Rewind the the coordinate list
+e Print error messages
+q Exit task
+
+
+ Colon Commands
+
+:show [data/center/sky/phot] List the parameters
+:m [n] Move to next [nth] object in coordinate list
+:n [n] Do photometry for next [nth] object in coordinate list, output results
+
+
+ Colon Parameter Editing Commands
+
+# Image and file name parameters
+
+:image [string] Image name
+:polygon [string] Polygon file
+:coords [string] Coordinate file
+:output [string] Results file
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Full-width half-maximum of PSF (scale units)
+:emission [y/n] Emission feature (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good pixel value (counts)
+:datamax [value] Maximum good pixel value (counts)
+
+# Noise parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per count)
+:epadu [value] Readout noise (electrons)
+
+# Observing parameters
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Integration time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observation (time units)
+
+# Centering algorithm parameters
+
+:calgorithm [string] Centering algorithm
+:cbox [value] Width of centering box (scale units)
+:cthreshold [value] Centering intensity threshold (sigma)
+:cmaxiter [value] Maximum number of iterations
+:maxshift [value] Maximum center shift (scale units)
+:minsnratio [value] Minimum S/N ratio for centering
+:clean [y/n] Clean subraster before centering
+:rclean [value] Cleaning radius (scale units)
+:rclip [value] Clipping radius (scale units)
+:kclean [value] Clean K-sigma rejection limit (sigma)
+
+# Sky fitting algorithm parameters
+
+:salgorithm [string] Sky fitting algorithm
+:skyvalue [value] User supplied sky value (counts)
+:annulus [value] Inner radius of sky annulus (scale units)
+:dannulus [value] Width of sky annulus (scale units)
+:khist [value] Sky histogram extent (+/- sigma)
+:binsize [value] Resolution of sky histogram (sigma)
+:sloclip [value] Low-side clipping factor in percent
+:shiclip [value] High-side clipping factor in percent
+:smooth [y/n] Lucy smooth the sky histogram
+:smaxiter [value] Maximum number of iterations
+:snreject [value] Maximum number of rejection cycles
+:sloreject [value] Low-side pixel rejection limits (sky sigma)
+:shireject [value] High-side pixel rejection limits (sky sigma)
+:rgrow [value] Region growing radius (scale units)
+
+# Photometry parameters
+
+:zmag [value] Zero point of magnitude scale
+
+# Plotting and marking parameters
+
+:mkcenter [y/n] Mark computed centers on the display
+:mksky [y/n] Mark the sky annuli on the display
+:mkpolygon [y/n] Mark the polygon on the display
diff --git a/noao/digiphot/apphot/polyphot/polyshow.x b/noao/digiphot/apphot/polyphot/polyshow.x
new file mode 100644
index 00000000..9e3da070
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/polyshow.x
@@ -0,0 +1,65 @@
+include "../lib/display.h"
+include "../lib/polyphot.h"
+
+# AP_YSHOW -- Print the all the polyphot parameters on the standard output.
+
+procedure ap_yshow (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+begin
+ call ap_nshow (ap)
+ call printf ("\n")
+ call ap_cpshow (ap)
+ call printf ("\n")
+ call ap_spshow (ap)
+ call printf ("\n")
+ call ap_yyshow (ap)
+end
+
+
+# AP_YPSHOW -- Print the noise and polypars parameters on the standard output.
+
+procedure ap_ypshow (ap)
+
+pointer ap # pointer to apphot structure
+
+begin
+ call ap_nshow (ap)
+ call printf ("\n")
+ call ap_yyshow (ap)
+end
+
+
+# AP_YYSHOW -- Print the polypars parameters on the standard output.
+
+procedure ap_yyshow (ap)
+
+pointer ap # pointer to apphot structure
+
+pointer sp, str
+bool itob()
+int apstati()
+real apstatr()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ call printf ("Photometry Parameters\n")
+
+ call apstats (ap, PYNAME, Memc[str], SZ_LINE)
+ call printf (" %s = %s\n")
+ call pargstr (KY_PYNAME)
+ call pargstr (Memc[str])
+
+ call printf (" %s = %g\n")
+ call pargstr (KY_PYZMAG)
+ call pargr (apstatr (ap, PYZMAG))
+
+ call printf (" %s = %b\n")
+ call pargstr (KY_MKPOLYGON)
+ call pargb (itob (apstati (ap, MKPOLYGON)))
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/polyphot/t_polymark.x b/noao/digiphot/apphot/polyphot/t_polymark.x
new file mode 100644
index 00000000..4eea5207
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/t_polymark.x
@@ -0,0 +1,240 @@
+include <gset.h>
+include <fset.h>
+include <imhdr.h>
+include "../lib/apphot.h"
+include "../lib/polyphot.h"
+
+define MAX_NVERTICES 100
+
+# T_POLYMARK -- Create a polygons list file interactively.
+
+procedure t_polymark()
+
+pointer image # pointer to name of image
+pointer polygons # pointer to the polygons file
+pointer coords # pointer to the coords file
+int cache # cache the input image pixels in memory
+pointer display # pointer to display device name
+pointer graphics # pointer to the graphics device
+
+pointer sp, cfname, pfname, im, py, id, gd, str
+int limlist, lplist, lclist, stat, pl, cl, root, pid, cid, wcs
+int imlist, plist, clist, newpy, newcoo, memstat, req_size, old_size
+int buf_size
+
+pointer gopen(), immap()
+int imtlen(), clplen(), imtgetim(), clgfil(), strncmp(), strlen()
+int fnldir(), ap_mkpylist(), imtopenp(), clpopnu(), open(), clgwrd()
+int access(), btoi(), ap_memstat(), sizeof()
+bool clgetb(), streq()
+errchk gopen()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (coords, SZ_FNAME, TY_CHAR)
+ call salloc (polygons, SZ_FNAME, TY_CHAR)
+ call salloc (display, SZ_FNAME, TY_CHAR)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+ call salloc (cfname, SZ_FNAME, TY_CHAR)
+ call salloc (pfname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Set STDOUT.
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get input and output file lists.
+ imlist = imtopenp ("image")
+ limlist = imtlen (imlist)
+ plist = clpopnu ("polygons")
+ lplist = clplen (plist)
+ clist = clpopnu ("coords")
+ lclist = clplen (clist)
+
+ # Check that image input and coords file list lengths match.
+ if (lclist > 0 && lclist != limlist) {
+ call imtclose (imlist)
+ call clpcls (plist)
+ call clpcls (clist)
+ call error (0, "Imcompatible image and coord file list lengths")
+ }
+
+ # Check that image input and polygons file list lengths match.
+ if (lplist != limlist) {
+ call imtclose (imlist)
+ call clpcls (plist)
+ call clpcls (clist)
+ call error (0, "Imcompatible image and polygons file list lengths")
+ }
+
+ cache = btoi (clgetb ("cache"))
+
+ # Open the graphics device.
+ call clgstr ("graphics", Memc[graphics], SZ_FNAME)
+ if (Memc[graphics] == EOS)
+ gd = NULL
+ else {
+ iferr {
+ gd = gopen (Memc[graphics], APPEND+AW_DEFER, STDGRAPH)
+ } then {
+ call eprintf ("Warning: Error opening graphics device.\n")
+ gd = NULL
+ }
+ }
+
+ # Open the display device.
+ call clgstr ("display", Memc[display], SZ_FNAME)
+ if (Memc[display] == EOS)
+ id = NULL
+ else if (streq (Memc[display], Memc[graphics])) {
+ id = gd
+ } else {
+ iferr {
+ id = gopen (Memc[display], APPEND, STDIMAGE)
+ } then {
+ call eprintf (
+ "Warning: Graphics overlay not available for display device.\n")
+ id = NULL
+ }
+ }
+
+ # Open the polymark structure.
+ call ap_ymkinit (py)
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_LINE, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (py, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_LINE, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (py, WCSOUT, wcs)
+
+ # Mark polygons.
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open image.
+ im = immap (Memc[image], READ_ONLY, 0)
+ call apimkeys (py, im, Memc[image])
+
+ # Establish the image display viewport and window.
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[image], im, 4)
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+
+ # Set the polygon file name.
+ if (lplist == 0)
+ pl = NULL
+ else {
+ stat = clgfil (plist, Memc[polygons], SZ_FNAME)
+ root = fnldir (Memc[polygons], Memc[pfname], SZ_FNAME)
+ if (strncmp ("default", Memc[polygons+root], 7) == 0 || root ==
+ strlen (Memc[polygons])) {
+ call apoutname (Memc[image], Memc[pfname], "ver",
+ Memc[pfname], SZ_FNAME)
+ lplist = limlist
+ } else if (stat != EOF)
+ call strcpy (Memc[polygons], Memc[pfname], SZ_FNAME)
+ if (access (Memc[pfname], READ_WRITE, TEXT_FILE) == YES) {
+ newpy = NO
+ pl = open (Memc[pfname], READ_WRITE, TEXT_FILE)
+ } else {
+ newpy = YES
+ pl = open (Memc[pfname], NEW_FILE, TEXT_FILE)
+ call close (pl)
+ pl = open (Memc[pfname], READ_WRITE, TEXT_FILE)
+ }
+ }
+ call apsets (py, PYNAME, Memc[pfname])
+
+ # Set the coord file name.
+ if (lclist == 0)
+ cl = NULL
+ else {
+ stat = clgfil (clist, Memc[coords], SZ_FNAME)
+ root = fnldir (Memc[coords], Memc[cfname], SZ_FNAME)
+ if (strncmp ("default", Memc[coords+root], 7) == 0 || root ==
+ strlen (Memc[coords])) {
+ call apoutname (Memc[image], Memc[cfname], "coo",
+ Memc[cfname], SZ_FNAME)
+ lclist = limlist
+ } else if (stat != EOF)
+ call strcpy (Memc[coords], Memc[cfname], SZ_FNAME)
+ if (access (Memc[cfname], READ_WRITE, TEXT_FILE) == YES) {
+ newcoo = NO
+ cl = open (Memc[cfname], READ_WRITE, TEXT_FILE)
+ } else {
+ newcoo = YES
+ cl = open (Memc[cfname], NEW_FILE, TEXT_FILE)
+ call close (cl)
+ cl = open (Memc[cfname], READ_WRITE, TEXT_FILE)
+ }
+ }
+ call apsets (py, CLNAME, Memc[cfname])
+
+ # Mark polygons on each image.
+ pid = 1
+ cid = 1
+ stat = ap_mkpylist (im, py, pl, cl, id, gd, pid, cid)
+
+ # Unmap the input image.
+ call imunmap (im)
+
+ # Close the polygon file.
+ if (pl != NULL) {
+ call close (pl)
+ if (newpy == YES && pid <= 1)
+ call delete (Memc[pfname])
+ }
+
+ # Close the coordinate file.
+ if (cl != NULL) {
+ if (cid > 1) {
+ call seek (cl, EOF)
+ call fprintf (cl, ";\n")
+ }
+ call close (cl)
+ if (newcoo == YES && cid <= 1)
+ call delete (Memc[cfname])
+ }
+
+ # Uncache memory.
+ call fixmem (old_size)
+
+ if (stat == YES)
+ break
+ }
+
+ # Close the graphics and image display devices.
+ if (id == gd && id != NULL)
+ call gclose (id)
+ else {
+ if (gd != NULL)
+ call gclose (gd)
+ if (id != NULL)
+ call gclose (id)
+ }
+
+ # Free the polymark structure.
+ call ap_ymkfree (py)
+
+ # Close image, polygon, and coordinate lists.
+ call imtclose (imlist)
+ call clpcls (plist)
+ call clpcls (clist)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/polyphot/t_polyphot.x b/noao/digiphot/apphot/polyphot/t_polyphot.x
new file mode 100644
index 00000000..5242d02e
--- /dev/null
+++ b/noao/digiphot/apphot/polyphot/t_polyphot.x
@@ -0,0 +1,329 @@
+include <gset.h>
+include <fset.h>
+include <imhdr.h>
+include "../lib/apphot.h"
+include "../lib/polyphot.h"
+
+# T_POLYPHOT -- Measure the total magnitudes inside a list of polygons.
+
+procedure t_polyphot()
+
+pointer image # pointer to name of image
+pointer output # pointer to the results file
+pointer coords # pointer to file of coordinates
+pointer polygon # pointer to file containing polygon
+pointer graphics # pointer to graphics device name
+pointer display # pointer to display device name
+int interactive # mode of use
+int cache # cache the input image pixels
+int verify # verify critical parameters
+int update # update the critical parameters
+int verbose # print messages
+
+pointer sp, outfname, cname, im, py, id, gd, str
+int limlist, lplist, lolist, lclist, sid, lid, pid, pl, cl, out, root, stat
+int imlist, plist, olist, clist, memstat, wcs, req_size, old_size, buf_size
+
+pointer immap(), gopen()
+int imtlen(), imtgetim(), clplen(), clgfil(), btoi(), strncmp()
+int fnldir(), strlen(), ap_yphot(), open(), imtopenp(), clpopnu()
+int clgwrd(), ap_memstat(), sizeof()
+bool clgetb(), streq()
+errchk gopen
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (coords, SZ_FNAME, TY_CHAR)
+ call salloc (polygon, SZ_FNAME, TY_CHAR)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+ call salloc (display, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (cname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Set STDOUT.
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get input and output file lists.
+ imlist = imtopenp ("image")
+ limlist = imtlen (imlist)
+ plist = clpopnu ("polygons")
+ lplist = clplen (plist)
+ olist = clpopnu ("output")
+ lolist = clplen (olist)
+ clist = clpopnu ("coords")
+ lclist = clplen (clist)
+
+ # Check that image and polygon list lengths match.
+ if (limlist < 1 || (lplist > 1 && lplist != limlist)) {
+ call imtclose (imlist)
+ call clpcls (plist)
+ call clpcls (olist)
+ call clpcls (clist)
+ call error (0, "Imcompatible image and polygon list lengths")
+ }
+
+ # Check that image and coordinates list lengths match.
+ if (limlist < 1 || (lclist > 1 && lclist != limlist)) {
+ call imtclose (imlist)
+ call clpcls (plist)
+ call clpcls (olist)
+ call clpcls (clist)
+ call error (0, "Imcompatible image and coordinate list lengths")
+ }
+
+ # Check that image input and output list lengths match.
+ if (lolist > 1 && lolist != limlist) {
+ call imtclose (imlist)
+ call clpcls (plist)
+ call clpcls (olist)
+ call clpcls (clist)
+ call error (0, "Imcompatible image and output list lengths")
+ }
+
+ call clgstr ("icommands.p_filename", Memc[cname], SZ_FNAME)
+ if (Memc[cname] != EOS)
+ interactive = NO
+ else
+ interactive = btoi (clgetb ("interactive"))
+ cache = btoi (clgetb ("cache"))
+ verify = btoi (clgetb ("verify"))
+ update = btoi (clgetb ("update"))
+ verbose = btoi (clgetb ("verbose"))
+
+ # Get polygon fitting parameters.
+ call ap_gypars (py)
+
+ # Confirm the algorithm parameters.
+ if (verify == YES && interactive == NO) {
+ call ap_yconfirm (py, NULL, 1)
+ if (update == YES)
+ call ap_pypars (py)
+ }
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_LINE, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (py, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_LINE, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (py, WCSOUT, wcs)
+
+ # Get the graphics and display devices.
+ call clgstr ("graphics", Memc[graphics], SZ_FNAME)
+ call clgstr ("display", Memc[display], SZ_FNAME)
+
+ # Open the plot files.
+ if (interactive == YES) {
+ if (Memc[graphics] == EOS)
+ gd = NULL
+ else {
+ iferr {
+ gd = gopen (Memc[graphics], APPEND+AW_DEFER, STDGRAPH)
+ } then {
+ call eprintf (
+ "Warning: Error opening graphics device.\n")
+ gd = NULL
+ }
+ }
+ if (Memc[display] == EOS)
+ id = NULL
+ else if (streq (Memc[graphics], Memc[display]))
+ id = gd
+ else {
+ iferr {
+ id = gopen (Memc[display], APPEND, STDIMAGE)
+ } then {
+ call eprintf (
+ "Warning: Graphics overlay not available for display device.\n")
+ id = NULL
+ }
+ }
+ } else {
+ gd = NULL
+ id = NULL
+ }
+
+ # Measure flux in a polygon.
+ sid = 1
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open image.
+ im = immap (Memc[image], READ_ONLY, 0)
+ call apimkeys (py, im, Memc[image])
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[image], im, 4)
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+
+ # Open the polygons file.
+ if (lplist <= 0) {
+ pl = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (plist, Memc[polygon], SZ_FNAME)
+ root = fnldir (Memc[polygon], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[polygon+root], 7) == 0 || root ==
+ strlen (Memc[polygon])) {
+ call ap_inname (Memc[image], Memc[outfname], "ver",
+ Memc[outfname], SZ_FNAME)
+ lplist = limlist
+ pl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else if (stat != EOF) {
+ call strcpy (Memc[polygon], Memc[outfname], SZ_FNAME)
+ pl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else {
+ call apstats (py, PYNAME, Memc[outfname], SZ_FNAME)
+ call seek (pl, BOF)
+ }
+ }
+ call apsets (py, PYNAME, Memc[outfname])
+ call apfroot (Memc[outfname], Memc[str], SZ_LINE)
+ call apsets (py, PYROOT, Memc[str])
+
+ # Open the coordinates file.
+ if (lclist <= 0) {
+ cl = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (clist, Memc[coords], SZ_FNAME)
+ root = fnldir (Memc[coords], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[coords+root], 7) == 0 || root ==
+ strlen (Memc[coords])) {
+ call ap_inname (Memc[image], Memc[outfname], "coo",
+ Memc[outfname], SZ_FNAME)
+ lclist = limlist
+ cl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else if (stat != EOF) {
+ call strcpy (Memc[coords], Memc[outfname], SZ_FNAME)
+ cl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else {
+ call apstats (py, CLNAME, Memc[outfname], SZ_FNAME)
+ call seek (cl, BOF)
+ }
+ }
+ call apsets (py, CLNAME, Memc[outfname])
+ call apfroot (Memc[outfname], Memc[str], SZ_LINE)
+ call apsets (py, CLROOT, Memc[str])
+
+ # Set output file name.
+ if (lolist == 0) {
+ out = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (olist, Memc[output], SZ_FNAME)
+ root = fnldir (Memc[output], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[output+root], 7) == 0 || root ==
+ strlen (Memc[output])) {
+ call apoutname (Memc[image], Memc[outfname], "ply",
+ Memc[outfname], SZ_FNAME)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ lolist = limlist
+ } else if (stat != EOF) {
+ call strcpy (Memc[output], Memc[outfname], SZ_FNAME)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ } else
+ call apstats (py, OUTNAME, Memc[outfname], SZ_FNAME)
+ }
+ call apsets (py, OUTNAME, Memc[outfname])
+
+ # Do the photometry.
+ if (interactive == NO) {
+ if (Memc[cname] != EOS)
+ stat = ap_yphot (py, im, cl, pl, NULL, NULL, out, sid, NO,
+ cache)
+ else if (pl != NULL) {
+ lid = 0
+ pid = 0
+ call ap_ybphot (py, im, cl, pl, out, sid, lid, pid, NULL,
+ verbose)
+ stat = NO
+ } else
+ stat = NO
+ } else
+ stat = ap_yphot (py, im, cl, pl, gd, id, out, sid, YES, cache)
+
+ # Unmap the input image.
+ call imunmap (im)
+
+ # Close the polygon file.
+ if (pl != NULL) {
+ if (lplist > 1)
+ call close (pl)
+ }
+
+ # Close the coordinate file.
+ if (cl != NULL) {
+ if (lclist > 1)
+ call close (cl)
+ }
+
+ # Close the output file.
+ if (out != NULL && lolist != 1) {
+ call close (out)
+ if (sid <= 1) {
+ call apstats (py, OUTNAME, Memc[outfname], SZ_FNAME)
+ call delete (Memc[outfname])
+ }
+ sid = 1
+ }
+
+ # Uncache memory.
+ call fixmem (old_size)
+
+ if (stat == YES)
+ break
+ }
+
+ # Close plot files.
+ if (id == gd && id != NULL)
+ call gclose (id)
+ else {
+ if (gd != NULL)
+ call gclose (gd)
+ if (id != NULL)
+ call gclose (id)
+ }
+
+ # Close the single coords and polygon file.
+ if (pl != NULL && lplist == 1)
+ call close (pl)
+ if (cl != NULL && lclist == 1)
+ call close (cl)
+
+ # Close the singled output file.
+ if (out != NULL && lolist == 1) {
+ call close (out)
+ if (sid <= 1) {
+ call apstats (py, OUTNAME, Memc[outfname], SZ_FNAME)
+ call delete (Memc[outfname])
+ }
+ }
+
+ # Close up the files.
+ call ap_yfree (py)
+
+ # Close image, coord and shift lists.
+ call imtclose (imlist)
+ call clpcls (plist)
+ call clpcls (clist)
+ call clpcls (olist)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/qphot.par b/noao/digiphot/apphot/qphot.par
new file mode 100644
index 00000000..85b18882
--- /dev/null
+++ b/noao/digiphot/apphot/qphot.par
@@ -0,0 +1,27 @@
+# QPHOT parameters
+
+image,f,a,,,,"The input image(s)"
+cbox,r,a,5.0,,,"The centering box width in pixels"
+annulus,r,a,,0.0,,"The inner radius of sky annulus in pixels"
+dannulus,r,a,,1.0,,"The width of the sky annulus in pixels"
+apertures,s,a,"3.0",,,"The list of photometry apertures"
+coords,s,h,"",,,"The input coordinate file(s) (default: *.coo.?)"
+output,f,h,"default",,,"The output photometry file(s) (default: *.mag.?)"
+plotfile,f,h,"",,,"The output plot metacode file"
+zmag,r,h,25.0,,,"The zero point of the magnitude scale"
+exposure,s,h,"",,,"The exposure time image header keyword"
+airmass,s,h,"",,,"The airmass image header keyword"
+filter,s,h,"",,,"The filter image header keyword"
+obstime,s,h,"",,,"The time of observation image header keyword"
+epadu,r,h,1.0,,,"The instrument gain in e-/ADU"
+interactive,b,h,yes,,,"Interactive mode ?"
+radplots,b,h,no,,,"Plot the radial profiles in interactive mode ?"
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor: [x y wcs] key [cmd]"
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache input image pixels in memory ?"
+verbose,b,h,)_.verbose,,,"Print messages in non-interactive mode ?"
+graphics,s,h,)_.graphics,,,"Graphics device"
+display,s,h,)_.display,,,"Display device"
+mode,s,h,'ql'
diff --git a/noao/digiphot/apphot/radprof.par b/noao/digiphot/apphot/radprof.par
new file mode 100644
index 00000000..c5ce3bb7
--- /dev/null
+++ b/noao/digiphot/apphot/radprof.par
@@ -0,0 +1,28 @@
+# RADPROF
+
+image,f,a,,,,"The input image(s)"
+radius,r,a,,,,"The maximum radial profile radius in scale units"
+step,r,a,,,,"The step size for radial profile in scale units"
+coords,f,h,"",,,"The input coordinate list(s) (default: image.coo.?)"
+output,f,h,"",,,"The output radial profile files (default: image.prf.?)"
+plotfile,f,h,"",,,"The output radial profile plot metacode file"
+datapars,pset,h,"",,,"Data dependent parameters"
+centerpars,pset,h,"",,,"Centering parameters"
+fitskypars,pset,h,"",,,"Sky fitting parameters"
+photpars,pset,h,"",,,"Photometry parameters"
+order,i,h,5,1,,"Order of spline fit"
+kreject,r,h,3.0,,,"K-sigma rejection limit"
+nreject,i,h,1,,,"Maximum number of rejection cycles"
+interactive,b,h,yes,,,"Interactive mode ?"
+radplots,b,h,yes,,,"Plot radial profiles in interactive mode ?"
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor: [x y wcs] key [cmd]"
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the input image pixels ?"
+verify,b,h,)_.verify,,,"Verify critical parameters in non-interactive mode ?"
+update,b,h,)_.update,,,"Update critical parameters in non-interactive mode ?"
+verbose,b,h,)_.verbose,,,"Print messages in non-interactive mode ?"
+graphics,s,h,)_.graphics,,,"Graphics device"
+display,s,h,)_.display,,,"Image display device"
+mode,s,h,'ql'
diff --git a/noao/digiphot/apphot/radprof/apbradprof.x b/noao/digiphot/apphot/radprof/apbradprof.x
new file mode 100644
index 00000000..08e5547b
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/apbradprof.x
@@ -0,0 +1,107 @@
+include <fset.h>
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+
+# AP_BRADPROF -- Procedure to fit the radial profiles of a list of objects
+# in a list of images.
+
+procedure ap_bradprof (ap, im, cl, gid, gd, mgd, out, id, ld, interactive)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to IRAF image
+int cl # starlist file descriptor
+pointer gid # display device stream
+pointer gd # pointer to graphics stream
+pointer mgd # pointer to metacode file
+int out # output file descriptor
+int id, ld # sequence and list numbers
+int interactive # interactive pr batch mode
+
+int stdin, ild, cier, sier, pier, rier
+pointer sp, str
+real wx, wy
+int fscan(), nscan(), apfitsky(), apfitcenter(), ap_frprof(), apstati()
+int strncmp()
+real apstatr()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME + 1, TY_CHAR)
+ call fstats (cl, F_FILENAME, Memc[str], SZ_FNAME)
+
+ # Initialize.
+ ild = ld
+
+ # Print query if coords is equal to STDIN.
+ if (strncmp ("STDIN", Memc[str], 5) == 0) {
+ stdin = YES
+ call printf (
+ "Type x and y coordinates of object (^D or ^Z to end): ")
+ call flush (STDOUT)
+ } else
+ stdin = NO
+
+ # Loop over the coordinate file.
+ while (fscan (cl) != EOF) {
+
+ # Get the coordinates.
+ call gargr (wx)
+ call gargr (wy)
+ if (nscan () != 2) {
+ if (stdin == YES) {
+ call printf (
+ "Type x and y coordinates of object (^D or ^Z to end): ")
+ call flush (STDOUT)
+ }
+ next
+ }
+
+ # Transform the input coordinates.
+ switch (apstati(ap,WCSIN)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_itol (ap, wx, wy, wx, wy, 1)
+ case WCS_TV:
+ call ap_vtol (im, wx, wy, wx, wy, 1)
+ default:
+ ;
+ }
+
+ # Set the current cursor position.
+ call apsetr (ap, CWX, wx)
+ call apsetr (ap, CWY, wy)
+
+ # Fit the center, sky and radial profile.
+ cier = apfitcenter (ap, im, wx, wy)
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), NULL, gd)
+ rier = ap_frprof (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), pier)
+
+ # Output the results.
+ if (interactive == YES) {
+ call ap_qprprof (ap, cier, sier, pier, rier)
+ if (id != NULL)
+ call aprmark (ap, gid, apstati (ap, MKCENTER),
+ apstati (ap, MKSKY), apstati (ap, MKAPERT))
+ }
+ if (id == 1)
+ call ap_param (ap, out, "radprof")
+ call ap_prprof (ap, out, id, ild, cier, sier, pier, rier)
+ call ap_rpplot (ap, id, mgd, YES)
+
+ # Setup for the next object.
+ id = id + 1
+ ild = ild + 1
+ call apsetr (ap, WX, wx)
+ call apsetr (ap, WY, wy)
+ if (stdin == YES) {
+ call printf (
+ "Type x and y coordinates of object (^D or ^Z to end): ")
+ call flush (STDOUT)
+ }
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/radprof/apfrprof.x b/noao/digiphot/apphot/radprof/apfrprof.x
new file mode 100644
index 00000000..093e90bd
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/apfrprof.x
@@ -0,0 +1,417 @@
+include <mach.h>
+include <gset.h>
+include <math.h>
+
+include <math/curfit.h>
+include <math/iminterp.h>
+include "../lib/apphotdef.h"
+include "../lib/noisedef.h"
+include "../lib/fitskydef.h"
+include "../lib/photdef.h"
+include "../lib/radprofdef.h"
+include "../lib/apphot.h"
+include "../lib/phot.h"
+include "../lib/radprof.h"
+
+# AP_FRPROF -- Compute the radial profile of an object.
+
+int procedure ap_frprof (ap, im, wx, wy, pier)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the IRAF image
+real wx, wy # object coordinates
+int pier # photometry error
+
+int i, ier, fier, nxpts, nypts, nrpts, order
+pointer sky, rprof, cv, asi
+real datamin, datamax, step, rmin, rmax, inorm, tinorm
+int ap_rpbuf(), ap_rmag(), ap_rpmeasure(), ap_rpiter()
+real asigrl(), cveval(), ap_rphalf()
+
+errchk cvinit(), cvfit(), cvvector(), cveval(), cvfree()
+errchk asinit(), asifit(), asigrl(), asifree()
+errchk ap_rpmeasure(), ap_rpiter()
+
+begin
+ # Set up some apphot pointers.
+ sky = AP_PSKY(ap)
+ rprof = AP_RPROF(ap)
+
+ # Initialize.
+ AP_RPXCUR(rprof) = wx
+ AP_RPYCUR(rprof) = wy
+ call ap_rpindef (ap)
+ if (IS_INDEFR(wx) || IS_INDEFR(wy)) {
+ AP_ORPXCUR(rprof) = INDEFR
+ AP_ORPYCUR(rprof) = INDEFR
+ } else {
+ switch (AP_WCSOUT(ap)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (ap, wx, wy, AP_ORPXCUR(rprof),
+ AP_ORPYCUR(rprof), 1)
+ case WCS_TV:
+ call ap_ltov (im, wx, wy, AP_ORPXCUR(rprof),
+ AP_ORPYCUR(rprof), 1)
+ default:
+ AP_ORPXCUR(rprof) = wx
+ AP_ORPYCUR(rprof) = wy
+ }
+ }
+
+ # Get the pixels and check for error conditions.
+ if (IS_INDEFR(wx) || IS_INDEFR(wy)) {
+ pier = AP_APERT_NOAPERT
+ return (AP_RP_NOPROFILE)
+ } else if (IS_INDEFR(AP_SKY_MODE(sky))) {
+ pier = AP_APERT_NOSKYMODE
+ return (AP_RP_NOSKYMODE)
+ } else if (ap_rpbuf (ap, im, wx, wy) == AP_RP_NOPROFILE) {
+ pier = AP_APERT_NOAPERT
+ return (AP_RP_NOPROFILE)
+ }
+
+ # Do the photometry.
+ pier = ap_rmag (ap)
+
+ # Initialize some common variables.
+ nxpts = AP_RPNX(rprof)
+ nypts = AP_RPNY(rprof)
+ nrpts = AP_RPNPTS(rprof)
+
+ # Initialize the radial profile curve fitting.
+ step = AP_SCALE(ap) * AP_RPSTEP(rprof)
+ order = max (1, min (AP_RPORDER(rprof), nxpts * nypts - 3))
+ rmin = 0.0
+ rmax = (nrpts - 1) * step
+ if (IS_INDEFR(AP_DATAMIN(ap)))
+ datamin = -MAX_REAL
+ else
+ datamin = AP_DATAMIN(ap) - AP_SKY_MODE(sky)
+ if (IS_INDEFR(AP_DATAMAX(ap)))
+ datamax = MAX_REAL
+ else
+ datamax = AP_DATAMAX(ap) - AP_SKY_MODE(sky)
+
+ # Fit the curve.
+ call cvinit (cv, SPLINE3, order, rmin, rmax)
+ call asubkr (Memr[AP_RPIX(rprof)], AP_SKY_MODE(sky),
+ Memr[AP_RPIX(rprof)], nxpts * nypts)
+ fier = ap_rpmeasure (cv, Memr[AP_RPIX(rprof)], nxpts, nypts,
+ AP_RPXC(rprof), AP_RPYC(rprof), datamin, datamax, rmax,
+ AP_RPNDATA(rprof), AP_RPNBAD(rprof))
+
+ # Perform the rejection cycle.
+ if (fier != NO_DEG_FREEDOM && AP_RPNREJECT(rprof) > 0 &&
+ AP_RPKSIGMA(rprof) > 0.0)
+ AP_RPNDATAREJ(rprof) = ap_rpiter (cv, Memr[AP_RPIX(rprof)], nxpts,
+ nypts, AP_RPXC(rprof), AP_RPYC(rprof), rmax, datamin, datamax,
+ AP_RPNREJECT(rprof), AP_RPKSIGMA(rprof), fier)
+ else
+ AP_RPNDATAREJ(rprof) = 0
+
+ AP_RPNDATA(rprof) = AP_RPNDATA(rprof) - AP_RPNDATAREJ(rprof)
+ AP_RPNDATAREJ(rprof) = AP_RPNDATAREJ(rprof) + AP_RPNBAD(rprof)
+
+ # Evaluate the fit.
+ if (fier != NO_DEG_FREEDOM) {
+
+ # Evaluate the profile.
+ do i = 1, nrpts
+ Memr[AP_RPDIST(rprof)+i-1] = (i - 1) * step
+ call cvvector (cv, Memr[AP_RPDIST(rprof)],
+ Memr[AP_INTENSITY(rprof)], nrpts)
+
+ # Evaluate the integral.
+ call asiinit (asi, II_SPLINE3)
+ call amulr (Memr[AP_RPDIST(rprof)], Memr[AP_INTENSITY(rprof)],
+ Memr[AP_TINTENSITY(rprof)], nrpts)
+ call asifit (asi, Memr[AP_TINTENSITY(rprof)], nrpts)
+ Memr[AP_TINTENSITY(rprof)] = 0.0
+ do i = 2, nrpts
+ Memr[AP_TINTENSITY(rprof)+i-1] = Memr[AP_TINTENSITY(rprof)+
+ i-2] + asigrl (asi, real (i - 1), real (i))
+ call amulkr (Memr[AP_TINTENSITY(rprof)], real (TWOPI) * step,
+ Memr[AP_TINTENSITY(rprof)], nrpts)
+ call asifree (asi)
+
+ # Normalize the radial profile.
+ inorm = cveval (cv, 0.0)
+ if (inorm != 0.0)
+ call adivkr (Memr[AP_INTENSITY(rprof)], inorm,
+ Memr[AP_INTENSITY(rprof)], nrpts)
+ call apsetr (ap, INORM, inorm)
+
+ # Normalize the total intensity.
+ tinorm = Memr[AP_TINTENSITY(rprof)+AP_RPNPTS(rprof)-1]
+ if (tinorm != 0.0)
+ call adivkr (Memr[AP_TINTENSITY(rprof)], tinorm,
+ Memr[AP_TINTENSITY(rprof)], nrpts)
+ call apsetr (ap, TNORM, tinorm)
+
+ # Compute the FWHMPSF.
+ call apsetr (ap, RPFWHM, 2.0 * ap_rphalf (Memr[AP_RPDIST(rprof)],
+ Memr[AP_INTENSITY(rprof)], nrpts))
+ }
+
+ # Set the error code and return.
+ call cvfree (cv)
+ if (fier == NO_DEG_FREEDOM)
+ ier = AP_RP_NPTS_TOO_SMALL
+ else if (fier == SINGULAR)
+ ier = AP_RP_SINGULAR
+
+ # Free space.
+ return (ier)
+end
+
+
+# AP_RMAG -- Compute the magnitudes for the radial profile
+
+int procedure ap_rmag (ap)
+
+pointer ap # pointer to the apphot structure
+
+int pier, nap
+pointer sp, nse, sky, phot, rprof, aperts
+real datamin, datamax, zmag
+
+begin
+ # Initialize some apphot pointers.
+ nse = AP_NOISE(ap)
+ sky = AP_PSKY(ap)
+ phot = AP_PPHOT(ap)
+ rprof = AP_RPROF(ap)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (aperts, AP_NAPERTS(phot), TY_REAL)
+
+ # Check for out of bounds apertures.
+ call ap_maxap (ap, pier)
+
+ # Define the good data minimum and maximum for photometry.
+ if (IS_INDEFR(AP_DATAMIN(ap)))
+ datamin = -MAX_REAL
+ else
+ datamin = AP_DATAMIN(ap)
+ if (IS_INDEFR(AP_DATAMAX(ap)))
+ datamax = MAX_REAL
+ else
+ datamax = AP_DATAMAX(ap)
+
+ # Compute the sums.
+ call ap_arrayr (ap, APERTS, Memr[aperts])
+ call amulkr (Memr[aperts], AP_SCALE(ap), Memr[aperts], AP_NAPERTS(phot))
+ if (IS_INDEFR(AP_DATAMIN(ap)) && IS_INDEFR(AP_DATAMAX(ap))) {
+ call ap_rmmeasure (Memr[AP_RPIX(rprof)], AP_RPNX(rprof),
+ AP_RPNY(rprof), AP_RPXC(rprof), AP_RPYC(rprof), Memr[aperts],
+ Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)], AP_NMAXAP(phot))
+ AP_NMINAP(phot) = AP_NMAXAP(phot) + 1
+ } else
+ call ap_brmmeasure (Memr[AP_RPIX(rprof)], AP_RPNX(rprof),
+ AP_RPNY(rprof), AP_RPXC(rprof), AP_RPYC(rprof), datamin,
+ datamax, Memr[aperts], Memd[AP_SUMS(phot)],
+ Memd[AP_AREA(phot)], AP_NMAXAP(phot), AP_NMINAP(phot))
+
+ # Check for bad pixels.
+ if ((pier == AP_OK) && (AP_NMINAP(phot) <= AP_NMAXAP(phot)))
+ pier = AP_APERT_BADDATA
+ nap = min (AP_NMINAP(phot) - 1, AP_NMAXAP(phot))
+
+ # Compute the magnitudes.
+ zmag = AP_ZMAG(phot) + 2.5 * log10 (AP_ITIME(ap))
+ if (AP_POSITIVE(ap) == YES)
+ call apcopmags (Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)],
+ Memr[AP_MAGS(phot)], Memr[AP_MAGERRS(phot)], nap,
+ AP_SKY_MODE(sky), AP_SKY_SIG(sky), AP_NSKY(sky), zmag,
+ AP_NOISEFUNCTION(nse), AP_EPADU(nse))
+ else
+ call apconmags (Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)],
+ Memr[AP_MAGS(phot)], Memr[AP_MAGERRS(phot)], nap,
+ AP_SKY_MODE(sky), AP_SKY_SIG(sky), AP_NSKY(sky), zmag,
+ AP_NOISEFUNCTION(nse), AP_EPADU(nse), AP_READNOISE(nse))
+
+ call sfree (sp)
+
+ return (pier)
+end
+
+
+# AP_RPMEASURE -- Procedure to measure the flux and effective area in a set of
+# apertures and accumulate the fit to the radial profile.
+
+int procedure ap_rpmeasure (cv, pixels, nx, ny, wx, wy, datamin, datamax,
+ rmax, ndata, nbad)
+
+pointer cv # pointer to curfit structure
+real pixels[nx,ARB] # subraster pixel values
+int nx, ny # dimensions of the subraster
+real wx, wy # center of subraster
+real datamin # minimum good data value
+real datamax # maximum good data value
+real rmax # the maximum radius
+int ndata # the number of ok data points
+int nbad # the number of bad data points
+
+int i, j, ier
+real weight, dy2, r2, rcv
+
+begin
+ # Initialize.
+ ndata = 0
+ nbad = 0
+ call cvzero (cv)
+
+ # Loop over the pixels.
+ do j = 1, ny {
+ dy2 = (j - wy) ** 2
+ do i = 1, nx {
+ r2 = (i - wx) ** 2 + dy2
+ rcv = sqrt (r2)
+ if (rcv > rmax)
+ next
+ if (pixels[i,j] < datamin || pixels[i,j] > datamax) {
+ nbad = nbad + 1
+ } else {
+ call cvaccum (cv, rcv, pixels[i,j], weight, WTS_UNIFORM)
+ ndata = ndata + 1
+ }
+ }
+ }
+
+ call cvsolve (cv, ier)
+ return (ier)
+end
+
+
+# AP_RPITER -- Procedure to reject pixels from the fit.
+
+int procedure ap_rpiter (cv, pixels, nx, ny, wx, wy, rmax, datamin, datamax,
+ niter, ksigma, fier)
+
+pointer cv # pointer to the curfit structure
+real pixels[nx,ARB] # pixel values
+int nx, ny # dimensions of image subraster
+real wx, wy # x and y coordinates of the center
+real rmax # maximum radius value
+real datamin # minimum good data value
+real datamax # maximum good data value
+int niter # maximum number of rejection cycles
+real ksigma # ksigma rejection limit
+int fier # fitting error code
+
+int i, j, k, npts, ntreject, nreject
+pointer sp, rtemp, w, ptr
+real chisqr, diff, locut, hicut
+real cveval()
+errchk cveval, cvrject, cvsolve
+
+begin
+ # Allocate the necessary space.
+ call smark (sp)
+ call salloc (rtemp, nx, TY_REAL)
+ call salloc (w, nx * ny, TY_REAL)
+ call amovkr (1.0, Memr[w], nx * ny)
+
+ # Set the weights of out of range and bad data points to 0.0.
+ ptr = w
+ do j = 1, ny {
+ call ap_ijtor (Memr[rtemp], nx, j, wx, wy)
+ do k = 1, nx {
+ if (Memr[rtemp+k-1] > rmax || pixels[k,j] < datamin ||
+ pixels[k,j] > datamax)
+ Memr[ptr+k-1] = 0.0
+ }
+ ptr = ptr + nx
+ }
+
+ ntreject = 0
+ do i = 1, niter {
+
+ # Compute the chisqr.
+ chisqr = 0.0
+ npts = 0
+ ptr = w
+ do j = 1, ny {
+ call ap_ijtor (Memr[rtemp], nx, j, wx, wy)
+ do k = 1, nx {
+ if (Memr[ptr+k-1] <= 0.0)
+ next
+ chisqr = chisqr + (pixels[k,j] - cveval (cv,
+ Memr[rtemp+k-1])) ** 2
+ npts = npts + 1
+ }
+ ptr = ptr + nx
+ }
+
+ # Compute the new limits.
+ if (npts > 1)
+ chisqr = sqrt (chisqr / (npts - 1))
+ else
+ chisqr = 0.0
+ locut = - ksigma * chisqr
+ hicut = ksigma * chisqr
+
+ # Reject pixels from the fit.
+ nreject = 0
+ ptr = w
+ do j = 1, ny {
+ call ap_ijtor (Memr[rtemp], nx, j, wx, wy)
+ do k = 1, nx {
+ if (Memr[ptr+k-1] <= 0.0)
+ next
+ diff = pixels[k,j] - cveval (cv, Memr[rtemp+k-1])
+ if (diff >= locut && diff <= hicut)
+ next
+ call cvrject (cv, Memr[rtemp+k-1], pixels[k,j], 1.0)
+ nreject = nreject + 1
+ Memr[ptr+k-1] = 0.0
+ }
+ ptr = ptr + nx
+ }
+
+ if (nreject == 0)
+ break
+ ntreject = ntreject + nreject
+
+ # Recompute the fit.
+ call cvsolve (cv, fier)
+ if (fier == NO_DEG_FREEDOM)
+ break
+ }
+
+
+ call sfree (sp)
+
+ return (ntreject)
+end
+
+
+# AP_RPHALF -- Compute the FWHM of the PSF.
+
+real procedure ap_rphalf (radius, intensity, npts)
+
+real radius[ARB] # radius in pixels
+real intensity[ARB] # profile intensity
+int npts # number of points
+
+int i
+real halfp
+
+begin
+ # Seach for the appropriate interval.
+ do i = 1, npts
+ if (intensity[i] < 0.5)
+ break
+
+ # Compute the full width half maximum.
+ if (i == 1)
+ halfp = radius[1]
+ else if (i == npts && intensity[npts] >= 0.5)
+ halfp = radius[npts]
+ else
+ halfp = (radius[i] * (0.5 - intensity[i-1]) + radius[i-1] *
+ (intensity[i] - 0.5)) / (intensity[i] - intensity[i-1])
+
+ return (halfp)
+end
diff --git a/noao/digiphot/apphot/radprof/apgrpars.x b/noao/digiphot/apphot/radprof/apgrpars.x
new file mode 100644
index 00000000..c7442121
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/apgrpars.x
@@ -0,0 +1,46 @@
+include "../lib/display.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+include "../lib/radprof.h"
+
+# AP_GRPPARS -- Procedure to fetch the radprof parameters.
+
+procedure ap_grppars (ap)
+
+pointer ap # pointer to apphot structure
+
+bool clgetb()
+int clgeti(), btoi()
+real clgetr()
+
+begin
+ # Open the apphot strucuture.
+ call ap_rpinit (ap, AP_CENTROID1D, 2.5, AP_MODE, 10.0, 10.0,
+ 3.0, 1, 8.0, 0.5, 2.0, AP_NPOISSON)
+
+ # Get the radial profile parameters.
+ call apsetr (ap, RPRADIUS, clgetr ("radius"))
+ call apsetr (ap, RPSTEP, clgetr ("step"))
+
+ # Get the data dependent parameters.
+ call ap_gdapars (ap)
+
+ # Get the centering algorithm parameters.
+ call ap_gcepars (ap)
+
+ # Get the sky fitting algorithm parameters.
+ call ap_gsapars (ap)
+
+ # Get the photometry parameters.
+ call ap_gphpars (ap)
+
+ # Set remainder of the radprof parameters.
+ call apsetr (ap, RPKSIGMA, clgetr ("kreject"))
+ call apseti (ap, RPNREJECT, clgeti ("nreject"))
+ call apseti (ap, RPORDER, clgeti ("order"))
+
+ # Set the plotting parameters.
+ call apseti (ap, RADPLOTS, btoi (clgetb ("radplots")))
+end
diff --git a/noao/digiphot/apphot/radprof/approfsetup.x b/noao/digiphot/apphot/radprof/approfsetup.x
new file mode 100644
index 00000000..826bdd21
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/approfsetup.x
@@ -0,0 +1,123 @@
+include "../lib/display.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+
+define HELPFILE "apphot$radprof/iradprof.key"
+
+# AP_PROFSETUP -- Procedure to set up radprof interactively using a radial
+# profile plot.
+
+procedure ap_profsetup (ap, im, wx, wy, gd, out, stid)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to the IRAF image
+real wx, wy # cursor coordinates
+pointer gd # pointer to graphics stream
+int out # output file descriptor
+int stid # output file sequence number
+
+int cier, sier, pier, rier, wcs, key
+pointer sp, str, cmd
+real xc, yc, xcenter, ycenter, rmin, rmax, imin, imax, rval
+real u1, u2, v1, v2, x1, x2, y1, y2
+
+int apfitcenter(), clgcur(), apfitsky(), ap_frprof(), apstati()
+int ap_showplot()
+real apstatr(), ap_cfwhmpsf(), ap_ccapert(), ap_cannulus(), ap_cdannulus()
+real ap_crprof(), ap_crpstep(), ap_cdatamin()
+real ap_cdatamax(), ap_crgrow(), ap_crclip(), ap_crclean(), ap_csigma()
+
+begin
+ if (gd == NULL)
+ return
+ call greactivate (gd, 0)
+
+ # Save old viewport and window
+ call ggview (gd, u1, u2, v1, v2)
+ call ggwind (gd, x1, x2, y1, y2)
+
+ # Plot the radial profile.
+ if (ap_showplot (ap, im, wx, wy, gd, xcenter, ycenter, rmin, rmax,
+ imin, imax) == ERR) {
+ call gdeactivate (gd, 0)
+ return
+ }
+
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call printf (
+ "Waiting for setup menu command (?=help, v=default setup, q=quit):\n")
+ while (clgcur ("gcommands", xc, yc, wcs, key, Memc[cmd],
+ SZ_LINE) != EOF) {
+
+ switch (key) {
+
+ case 'q':
+ break
+ case '?':
+ call gpagefile (gd, HELPFILE, "")
+ case 'f':
+ rval = ap_cfwhmpsf (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 's':
+ rval = ap_csigma (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'l':
+ rval = ap_cdatamin (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'u':
+ rval = ap_cdatamax (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'c':
+ rval = ap_ccapert (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'n':
+ rval = ap_crclean (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'p':
+ rval = ap_crclip (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'a':
+ rval = ap_cannulus (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'd':
+ rval = ap_cdannulus (ap, gd, out, stid, apstatr (ap, ANNULUS),
+ rmin, rmax, imin, imax)
+ case 'g':
+ rval = ap_crgrow (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'r':
+ call ap_caper (ap, gd, out, stid, Memc[str], rmin, rmax,
+ imin, imax)
+ case 'w':
+ rval = ap_crprof (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'x':
+ rval = ap_crpstep (ap, gd, out, stid, rmin, rmax, imin, imax)
+ case 'v':
+ rval = ap_cfwhmpsf (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_ccapert (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_cannulus (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_cdannulus (ap, gd, out, stid, apstatr (ap, ANNULUS),
+ rmin, rmax, imin, imax)
+ rval = ap_csigma (ap, gd, out, stid, rmin, rmax, imin, imax)
+ call ap_caper (ap, gd, out, stid, Memc[str], rmin, rmax,
+ imin, imax)
+ rval = ap_crprof (ap, gd, out, stid, rmin, rmax, imin, imax)
+ rval = ap_crpstep (ap, gd, out, stid, rmin, rmax, imin, imax)
+ default:
+ call printf ("Unknown or ambiguous keystroke command\007\n")
+ }
+ call printf (
+ "Waiting for setup menu command (?=help, v=default setup, q=quit):\n")
+ }
+ call printf (
+ "Interactive setup is complete. Type w to save parameters.\n")
+
+ # Restore old view port and window
+ call gsview (gd, u1, u2, v1, v2)
+ call gswind (gd, x1, x2, y1, y2)
+
+ call gdeactivate (gd, 0)
+ call sfree (sp)
+
+ # Compute the answer.
+ cier = apfitcenter (ap, im, xcenter, ycenter)
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER), apstatr (ap, YCENTER),
+ NULL, gd)
+ rier = ap_frprof (ap, im, apstatr (ap, XCENTER), apstatr (ap, YCENTER),
+ pier)
+ call ap_rpplot (ap, 0, gd, apstati (ap, RADPLOTS))
+ call ap_qprprof (ap, cier, sier, pier, rier)
+end
diff --git a/noao/digiphot/apphot/radprof/apprprof.x b/noao/digiphot/apphot/radprof/apprprof.x
new file mode 100644
index 00000000..1d7461ee
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/apprprof.x
@@ -0,0 +1,109 @@
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/photdef.h"
+include "../lib/phot.h"
+include "../lib/radprof.h"
+
+# AP_PRPROF -- Procedure to write the results of radprof to the output file.
+
+procedure ap_prprof (ap, fd, id, lid, cier, sier, pier, rier)
+
+pointer ap # pointer to apphot structure
+int fd # output text file descriptor
+int id # id number of str
+int lid # list id of star
+int cier # centering error
+int sier # sky fitting error
+int pier # photometric error
+int rier # radial profile error
+
+int i, naperts
+int apstati()
+real apstatr()
+
+begin
+ if (fd == NULL)
+ return
+
+ # Print the id parameters.
+ call ap_wid (ap, fd, apstatr (ap, OXINIT), apstatr (ap, OYINIT),
+ id, lid, '\\')
+
+ # Print the center parameters.
+ call ap_wcres (ap, fd, cier, '\\')
+
+ # Print the sky values.
+ call ap_wsres (ap, fd, sier, '\\')
+
+ # Print photometry parameters.
+ naperts = apstati (ap, NAPERTS)
+ do i = 1, naperts {
+ if (naperts == 1)
+ call ap_wmres (ap, fd, i, pier, " \\")
+ else
+ call ap_wmres (ap, fd, i, pier, "*\\")
+ }
+
+ # Print the radprof parameters.
+ call ap_wrres (ap, fd, rier)
+end
+
+
+# AP_RPHDR -- Procedure to write the radprof banner header to the output file.
+
+procedure ap_rphdr (ap, out)
+
+pointer ap # apphot descriptor
+int out # output file descriptor
+
+begin
+ if (out == NULL)
+ return
+
+ # Print out the keywords.
+ call ap_idhdr (ap, out)
+ call ap_chdr (ap, out)
+ call ap_shdr (ap, out)
+ call ap_mhdr (ap, out)
+ call ap_rhdr (ap, out)
+end
+
+
+# AP_QPRPROF -- Procedure to print a short version of the radprof results
+# on the standard output.
+
+procedure ap_qprprof (ap, cier, sier, pier, rier)
+
+pointer ap # pointer to apphot structure
+int cier # centering error
+int sier # sky fitting error
+int pier # phot error
+int rier # radprof error
+
+pointer sp, imname, phot
+real apstatr()
+
+begin
+ call smark (sp)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+ phot = AP_PPHOT(ap)
+
+ # Print quick summary of radprof results on the standard output.
+ call apstats (ap, IMROOT, Memc[imname], SZ_FNAME)
+ call printf ("%s %8.2f %8.2f %8g %5.2f ")
+ call pargstr (Memc[imname])
+ call pargr (apstatr (ap, ORPXCUR))
+ call pargr (apstatr (ap, ORPYCUR))
+ call pargr (apstatr (ap, SKY_MODE))
+ call pargr (apstatr (ap, RPFWHM) / apstatr (ap, SCALE))
+ call printf ("%7.3f %s\n")
+ call pargr (Memr[AP_MAGS(phot)+AP_NAPERTS(phot)-1])
+ if (cier != AP_OK || sier != AP_OK || pier != AP_OK || rier != AP_OK)
+ call pargstr ("err")
+ else
+ call pargstr ("ok")
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/radprof/apradprof.x b/noao/digiphot/apphot/radprof/apradprof.x
new file mode 100644
index 00000000..10448af2
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/apradprof.x
@@ -0,0 +1,500 @@
+include <ctype.h>
+include <gset.h>
+include <imhdr.h>
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/radprof.h"
+
+define HELPFILE "apphot$radprof/radprof.key"
+
+# AP_RADPROF -- Procedure to determine radial profiles for a list of objects
+# in a list of images.
+
+int procedure ap_radprof (ap, im, cl, gd, mgd, id, out, stid, interactive,
+ cache)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to IRAF image
+int cl # starlist file descriptor
+pointer gd # pointer to graphcis descriptor
+pointer mgd # pointer to plot metacode stream
+pointer id # pointer to image display stream
+int out # output file descriptor
+int stid # output file sequence number
+int interactive # interactive mode
+int cache # cache the input image pixels
+
+real wx, wy, xlist, ylist
+pointer sp, cmd
+int wcs, key, oid, ltid, newlist, colonkey, req_size, buf_size, old_size
+int newimage, newskybuf, newsky, newcenterbuf, newcenter, newbuf, newfit
+int ip, prev_num, req_num, cier, sier, pier, rier, memstat
+
+real apstatr()
+int clgcur(), apfitsky(), aprefitsky(), apfitcenter(), aprefitcenter()
+int apstati(), apgscur(), ap_frprof(), ctoi(), apgqverify(), apgtverify()
+int apnew(), ap_avsky(), sizeof(), ap_memstat()
+bool fp_equalr()
+
+define endswitch_ 99
+
+begin
+ # Initialize.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Initialize the cursor command.
+ key = ' '
+ Memc[cmd] = EOS
+
+ # Initialize the fit.
+ newimage = NO
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ cier = AP_OK; sier = AP_OK; pier = AP_OK; rier = AP_OK
+
+ # Initialize the sequencing.
+ newlist = NO
+ ltid = 0
+
+ # Loop over the coordinate file.
+ while (clgcur ("icommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+
+ # Store the cursor coords.
+ call ap_vtol (im, wx, wy, wx, wy, 1)
+ call apsetr (ap, CWX, wx)
+ call apsetr (ap, CWY, wy)
+
+ # Test to see if the cursor has moved.
+ if (apnew (ap, wx, wy, xlist, ylist, newlist) == YES) {
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ }
+
+ # Switch on the keystroke commands.
+ switch (key) {
+
+ # Quit.
+ case 'q':
+ if (interactive == YES) {
+ if (apgqverify ("radprof", ap, key) == YES) {
+ call sfree (sp)
+ return (apgtverify (key))
+ }
+ } else {
+ call sfree (sp)
+ return (NO)
+ }
+
+ # Print the errors.
+ case 'e':
+ if (interactive == YES)
+ call ap_rferrors (ap, cier, sier, pier, rier)
+
+ # Print the help page.
+ case '?':
+ if ((id != NULL) && (id == gd))
+ call gpagefile (id, HELPFILE, "")
+ else if (interactive == YES)
+ call pagefile (HELPFILE, "[space=morehelp,q=quit,?=help]")
+
+ # Rewind the list.
+ case 'r':
+ if (cl != NULL) {
+ call seek (cl, BOF)
+ ltid = 0
+ } else if (interactive == YES)
+ call printf ("No coordinate list\n")
+
+ # Move, measure next object in the coordinate list.
+ case 'm', 'n':
+
+ # No coordinate file.
+ if (cl == NULL) {
+ if (interactive == YES)
+ call printf ("No coordinate list\n")
+ goto endswitch_
+ }
+
+ # Need to rewind the coordinate file.
+ prev_num = ltid
+ req_num = ltid + 1
+ if (apgscur (cl, id, xlist, ylist, prev_num, req_num,
+ ltid) == EOF) {
+ if (interactive == YES)
+ call printf (
+ "End of coordinate list, use r key to rewind\n")
+ goto endswitch_
+ }
+
+ # Convert coordinates if necessary.
+ switch (apstati (ap, WCSIN)) {
+ case WCS_PHYSICAL, WCS_WORLD:
+ call ap_itol (ap, xlist, ylist, xlist, ylist, 1)
+ case WCS_TV:
+ call ap_vtol (im, xlist, ylist, xlist, ylist, 1)
+ default:
+ ;
+ }
+
+ # Move to the next object.
+ newlist = YES
+ if (key == 'm') {
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ goto endswitch_
+ }
+
+ # Measure next object.
+ cier = apfitcenter (ap, im, xlist, ylist)
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), NULL, gd)
+ rier = ap_frprof (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), pier)
+ call aprmark (ap, id, apstati (ap, MKCENTER), apstati (ap,
+ MKSKY), apstati (ap, MKAPERT))
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_rpplot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qprprof (ap, cier, sier, pier, rier)
+ if (stid == 1)
+ call ap_param (ap, out, "radprof")
+ call ap_prprof (ap, out, stid, ltid, cier, sier, pier, rier)
+ call ap_rpplot (ap, stid, mgd, YES)
+ stid = stid + 1
+ newcenterbuf = NO; newcenter = NO
+ newskybuf = NO; newsky = NO
+ newbuf = NO; newfit = NO
+
+ # Process the remainder of the list.
+ case 'l':
+ if (cl != NULL) {
+ oid = stid
+ ltid = ltid + 1
+ call ap_bradprof (ap, im, cl, id, gd, mgd, out, stid, ltid,
+ YES)
+ ltid = ltid + stid - oid + 1
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ } else if (interactive == YES)
+ call printf ("No coordinate list\n")
+
+ # Process radprof colon commands.
+ case ':':
+ for (ip = 1; IS_WHITE(Memc[cmd+ip-1]); ip = ip + 1)
+ ;
+ colonkey = Memc[cmd+ip-1]
+ switch (colonkey) {
+ case 'm', 'n':
+
+ # Show/set radprof parameters.
+ if (Memc[cmd+ip] != EOS && Memc[cmd+ip] != ' ') {
+ call ap_rpcolon (ap, im, cl, out, stid, ltid, Memc[cmd],
+ newimage, newcenterbuf, newcenter, newskybuf,
+ newsky, newbuf, newfit)
+ goto endswitch_
+ }
+
+ # Process the next object.
+ if (cl == NULL) {
+ if (interactive == YES)
+ call printf ("No coordinate list\n")
+ goto endswitch_
+ }
+
+ # Get next object from the list.
+ ip = ip + 1
+ prev_num = ltid
+ if (ctoi (Memc[cmd], ip, req_num) <= 0)
+ req_num = ltid + 1
+
+ # Fetch next object from the list.
+ if (apgscur (cl, id, xlist, ylist, prev_num, req_num,
+ ltid) == EOF) {
+ if (interactive == YES)
+ call printf (
+ "End of coordinate list, use r key to rewind\n")
+ goto endswitch_
+
+ }
+
+ # Convert the coordinates.
+ switch (apstati (ap, WCSIN)) {
+ case WCS_PHYSICAL, WCS_WORLD:
+ call ap_itol (ap, xlist, ylist, xlist, ylist, 1)
+ case WCS_TV:
+ call ap_vtol (im, xlist, ylist, xlist, ylist, 1)
+ default:
+ ;
+ }
+
+ # Move to next object.
+ newlist = YES
+ if (colonkey == 'm') {
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ }
+
+ # Measure the next object.
+ cier = apfitcenter (ap, im, xlist, ylist)
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER),
+ apstatr (ap, YCENTER), NULL, gd)
+ rier = ap_frprof (ap, im, apstatr (ap, XCENTER),
+ apstatr (ap, YCENTER), pier)
+ call aprmark (ap, id, apstati (ap, MKCENTER), apstati (ap,
+ MKSKY), apstati (ap, MKAPERT))
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_rpplot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qprprof (ap, cier, sier, pier, rier)
+
+ if (stid == 1)
+ call ap_param (ap, out, "radprof")
+ call ap_prprof (ap, out, stid, ltid, cier, sier, pier, rier)
+ call ap_rpplot (ap, stid, mgd, YES)
+ stid = stid + 1
+ newcenterbuf = NO; newcenter = NO
+ newskybuf = NO; newsky = NO
+ newbuf = NO; newfit = NO
+
+ default:
+ call ap_rpcolon (ap, im, cl, out, stid, ltid, Memc[cmd],
+ newimage, newcenterbuf, newcenter, newskybuf, newsky,
+ newbuf, newfit)
+ }
+
+ # Reestablish the image viewport and window.
+ if (newimage == YES) {
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[cmd], im, 4)
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+ }
+
+ newimage = NO
+
+ # Save the parameters.
+ case 'w':
+ call ap_rpars (ap)
+
+ # Plot a simple centered radial profile.
+ case 'd':
+ if (interactive == YES) {
+ call ap_qrad (ap, im, wx, wy, gd)
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ }
+
+
+ # Setup the radial profile fitting parameters interactively.
+ case 'i':
+ if (interactive == YES) {
+ call ap_profsetup (ap, im, wx, wy, gd, out, stid)
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+ }
+
+ # Verify the critical radprof parameters.
+ case 'v':
+ call ap_rconfirm (ap, out, stid)
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newbuf = YES; newfit = YES
+
+ # Fit the center around the current cursor value.
+ case 'c':
+ if (newcenterbuf == YES)
+ cier = apfitcenter (ap, im, wx, wy)
+ else if (newcenter == YES)
+ cier = aprefitcenter (ap, im, cier)
+ call aprmark (ap, id, apstati (ap, MKCENTER), NO, NO)
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_cplot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qcenter (ap, cier)
+ newcenterbuf = NO; newcenter = NO
+
+ # Fit the sky around the current cursor value.
+ case 't':
+ if (newskybuf == YES || ! fp_equalr (wx,
+ apstatr (ap, SXCUR)) || ! fp_equalr (wy, apstatr (ap,
+ SYCUR)))
+ sier = apfitsky (ap, im, wx, wy, NULL, gd)
+ else if (newsky == YES)
+ sier = aprefitsky (ap, im, gd)
+ call aprmark (ap, id, NO, apstati (ap, MKSKY), NO)
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_splot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qspsky (ap, sier)
+ newskybuf = NO; newsky = NO
+
+ # Compute the average of several sky measurements around
+ # different cursor postions.
+ case 'a':
+ sier = ap_avsky (ap, im, stid, NULL, id, gd, interactive)
+ if (interactive == YES)
+ call ap_qaspsky (ap, sier)
+ newskybuf = NO; newsky = NO
+
+ # Fit the sky around derived center value.
+ case 's':
+ if (newskybuf == YES || ! fp_equalr (apstatr (ap, XCENTER),
+ apstatr (ap, SXCUR)) || ! fp_equalr (apstatr (ap,
+ SYCUR), apstatr (ap, YCENTER)))
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER),
+ apstatr (ap, YCENTER), NULL, gd)
+ else if (newsky == YES)
+ sier = aprefitsky (ap, im, gd)
+ call aprmark (ap, id, NO, apstati (ap, MKSKY), NO)
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_splot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qspsky (ap, sier)
+ newskybuf = NO; newsky = NO
+
+ # Compute magnitudes around the current cursor position using
+ # the current sky.
+ case 'p', 'o':
+ if (newcenterbuf == YES)
+ cier = apfitcenter (ap, im, wx, wy)
+ else if (newcenter == YES)
+ cier = aprefitcenter (ap, im, cier)
+ call aprmark (ap, id, apstati (ap, MKCENTER), NO,
+ apstati (ap, MKAPERT))
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ if (newfit == YES || newbuf == YES || ! fp_equalr (apstatr (ap,
+ XCENTER), apstatr (ap, RPXCUR)) ||
+ ! fp_equalr (apstatr (ap, RPYCUR), apstatr (ap, YCENTER)))
+ rier = ap_frprof (ap, im, apstatr (ap, XCENTER),
+ apstatr (ap, YCENTER), pier)
+ if (interactive == YES)
+ call ap_qprprof (ap, cier, sier, pier, rier)
+ newcenterbuf = NO; newcenter = NO
+ newbuf = NO; newfit = NO
+
+ if (key == 'o') {
+ if (stid == 1)
+ call ap_param (ap, out, "radprof")
+ if (newlist == YES)
+ call ap_prprof (ap, out, stid, ltid, cier, sier, pier,
+ rier)
+ else
+ call ap_prprof (ap, out, stid, 0, cier, sier, pier,
+ rier)
+ call ap_rpplot (ap, stid, mgd, YES)
+ stid = stid + 1
+ }
+
+ # Center, fit the sky, and compute magnitudes.
+ # Compute the centers, fit the sky, compute the magnitudes
+ # and save the results.
+ case 'f', ' ':
+ if (newcenterbuf == YES)
+ cier = apfitcenter (ap, im, wx, wy)
+ else if (newcenter == YES)
+ cier = aprefitcenter (ap, im, cier)
+ if (newskybuf == YES || ! fp_equalr (apstatr (ap, XCENTER),
+ apstatr (ap, SXCUR)) || ! fp_equalr (apstatr (ap, YCENTER),
+ apstatr (ap, SYCUR)))
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER),
+ apstatr (ap, YCENTER), NULL, gd)
+ else if (newsky == YES)
+ sier = aprefitsky (ap, im, gd)
+
+ if (newfit == YES || newbuf == YES || ! fp_equalr (apstatr (ap,
+ XCENTER), apstatr (ap, RPXCUR)) || ! fp_equalr (apstatr (ap,
+ YCENTER), apstatr (ap, RPYCUR)))
+ rier = ap_frprof (ap, im, apstatr (ap, XCENTER),
+ apstatr (ap, YCENTER), pier)
+ call aprmark (ap, id, apstati (ap, MKCENTER), apstati (ap,
+ MKSKY), apstati (ap, MKAPERT))
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_rpplot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qprprof (ap, cier, sier, pier, rier)
+
+ newcenterbuf = NO; newcenter = NO
+ newskybuf = NO; newsky = NO
+ newbuf = NO; newfit = NO
+
+ if (key == ' ') {
+ if (stid == 1)
+ call ap_param (ap, out, "radprof")
+ if (newlist == YES)
+ call ap_prprof (ap, out, stid, ltid, cier, sier, pier,
+ rier)
+ else
+ call ap_prprof (ap, out, stid, 0, cier, sier, pier,
+ rier)
+ call ap_rpplot (ap, stid, mgd, YES)
+ stid = stid + 1
+ }
+
+ default:
+ # do nothing
+ call printf ("Print unknown or ambiguous colon command\n")
+ }
+
+endswitch_
+ # Prepare for the next object.
+ key = ' '
+ Memc[cmd] = EOS
+ call apsetr (ap, WX, apstatr (ap, CWX))
+ call apsetr (ap, WY, apstatr (ap, CWY))
+
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/radprof/aprconfirm.x b/noao/digiphot/apphot/radprof/aprconfirm.x
new file mode 100644
index 00000000..3c775e79
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/aprconfirm.x
@@ -0,0 +1,118 @@
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+include "../lib/radprof.h"
+
+# AP_RCONFIRM -- Procedure to confirm the critical phot parameters.
+
+procedure ap_rconfirm (ap, out, stid)
+
+pointer ap # pointer to the apphot structure
+int out # output file descriptor
+int stid # output file sequence number
+
+pointer sp, cstr, sstr, aperts
+real fwhmpsf, capert, annulus, dannulus, skysigma
+real datamin, datamax, radius, step
+int apstati()
+real apstatr(), ap_vfwhmpsf(), ap_vcapert()
+real ap_vannulus(), ap_vdannulus(), ap_vsigma(), ap_vstep()
+real ap_vdatamin(), ap_vdatamax(), ap_vrpradius()
+
+begin
+ call smark (sp)
+ call salloc (cstr, SZ_FNAME, TY_CHAR)
+ call salloc (sstr, SZ_FNAME, TY_CHAR)
+ call salloc (aperts, SZ_LINE, TY_CHAR)
+
+ call printf ("\n")
+
+ # Confirm the centering algorithm.
+ call ap_vcstring (ap, Memc[cstr], SZ_FNAME)
+
+ if (apstati (ap, CENTERFUNCTION) != AP_NONE) {
+
+ # Confirm the fwhmpsf.
+ if (apstati (ap, CENTERFUNCTION) != AP_CENTROID1D)
+ fwhmpsf = ap_vfwhmpsf (ap)
+ else
+ fwhmpsf = apstatr (ap, FWHMPSF)
+
+ # Confirm the centering box.
+ capert = 2.0 * ap_vcapert (ap)
+
+ } else {
+ fwhmpsf = apstatr (ap, FWHMPSF)
+ capert = 2.0 * apstatr (ap, CAPERT)
+ }
+
+ # Confirm the sky fitting algorithm.
+ call ap_vsstring (ap, Memc[sstr], SZ_FNAME)
+
+ if (apstati (ap, SKYFUNCTION) != AP_CONSTANT &&
+ apstati (ap, SKYFUNCTION) != AP_SKYFILE) {
+
+ # Confirm the sky annulus parameter.
+ annulus = ap_vannulus (ap)
+
+ # Confirm the width of the sky annulus.
+ dannulus = ap_vdannulus (ap)
+
+ } else {
+ annulus = apstatr (ap, ANNULUS)
+ dannulus = apstatr (ap, DANNULUS)
+ }
+
+ # Confirm the sky sigma parameter.
+ if (apstati (ap, SKYFUNCTION) != AP_SKYFILE)
+ skysigma = ap_vsigma (ap)
+ else
+ skysigma = apstatr (ap, SKYSIGMA)
+
+ # Confirm the aperture radii parameter.
+ call ap_vaperts (ap, Memc[aperts], SZ_LINE)
+
+ # Confirm the radius of profile
+ radius = ap_vrpradius (ap)
+
+ # Confirm the step size of profile
+ step = ap_vstep (ap)
+
+ # Confirm the minimum and maximum good data values.
+ datamin = ap_vdatamin (ap)
+ datamax = ap_vdatamax (ap)
+
+ call printf ("\n")
+
+ # Update the database file.
+ if (out != NULL && stid > 1) {
+ call ap_sparam (out, KY_CSTRING, Memc[cstr], UN_CALGORITHM,
+ "centering algorithm")
+ call ap_rparam (out, KY_FWHMPSF, fwhmpsf, UN_ASCALEUNIT,
+ "full width half maximum of the psf")
+ call ap_rparam (out, KY_CAPERT, capert, UN_CSCALEUNIT,
+ "centering box width")
+ call ap_sparam (out, KY_SSTRING, Memc[sstr], UN_SALGORITHM,
+ "sky fitting algorithm")
+ call ap_rparam (out, KY_ANNULUS, annulus, UN_SSCALEUNIT,
+ "inner radius of the sky annulus")
+ call ap_rparam (out, KY_DANNULUS, dannulus, UN_SSCALEUNIT,
+ "width of the sky annulus")
+ call ap_rparam (out, KY_SKYSIGMA, skysigma, UN_NCOUNTS,
+ "standard deviation of 1 sky pixel")
+ call ap_sparam (out, KY_APERTS, Memc[aperts], UN_PSCALEUNIT,
+ "list of apertures")
+ call ap_rparam (out, KY_DATAMIN, datamin, UN_ACOUNTS,
+ "minimum good data value")
+ call ap_rparam (out, KY_DATAMAX, datamax, UN_ACOUNTS,
+ "maximum good data value")
+ call ap_rparam (out, KY_RPRADIUS, radius, UN_RSCALEUNIT,
+ "fitting radius")
+ call ap_rparam (out, KY_RPSTEP, step, UN_RSCALEUNIT,
+ "step size in radius")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/radprof/aprferrors.x b/noao/digiphot/apphot/radprof/aprferrors.x
new file mode 100644
index 00000000..f72586f3
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/aprferrors.x
@@ -0,0 +1,40 @@
+include "../lib/phot.h"
+include "../lib/radprof.h"
+
+# AP_RFERRORS -- Procedure to print a short form of the output of radprof on
+# the standard output.
+
+procedure ap_rferrors (ap, cier, sier, pier, rier)
+
+pointer ap # pointer to apphot structure
+int cier # centering error
+int sier # sky fitting error
+int pier # photmetry error
+int rier # photometric error
+
+begin
+ # Print the centering errors.
+ call ap_cerrors (ap, cier)
+
+ # Print the sky fitting errors.
+ call ap_serrors (ap, sier)
+
+ # Print the photometry errors.
+ call ap_merrors (ap, pier)
+
+ # Print the radial profile fitting errors.
+ switch (rier) {
+ case AP_RP_NOPROFILE:
+ call printf ("The profile fitting region is outside the image.\n")
+ case AP_RP_OUTOFBOUNDS:
+ call printf (
+ "The profile fitting region is partially outside the image.\n")
+ case AP_RP_NPTS_TOO_SMALL:
+ call printf (
+ "There are too few points in the profile fitting region.\n")
+ case AP_RP_SINGULAR:
+ call printf ("The profile fit is singular.\n")
+ default:
+ call printf ("")
+ }
+end
diff --git a/noao/digiphot/apphot/radprof/aprmmeasure.x b/noao/digiphot/apphot/radprof/aprmmeasure.x
new file mode 100644
index 00000000..fe455008
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/aprmmeasure.x
@@ -0,0 +1,96 @@
+include <math/curfit.h>
+
+# AP_RMMEASURE -- Procedure to compute the sums and areas inside the apertures.
+
+procedure ap_rmmeasure (pixels, nx, ny, wx, wy, aperts, sums, areas, naperts)
+
+real pixels[nx,ARB] # subraster pixel values
+int nx, ny # dimensions of the subraster
+real wx, wy # center of subraster
+real aperts[ARB] # array of apertures
+double sums[ARB] # array of sums
+double areas[ARB] # aperture areas
+int naperts # number of apertures
+
+int i, j, k
+double fctn
+real apmaxsq, dy2, r2, r
+
+begin
+ # Initialize.
+ apmaxsq = (aperts[naperts] + 0.5) ** 2
+ call aclrd (sums, naperts)
+ call aclrd (areas, naperts)
+
+ # Loop over the pixels.
+ do j = 1, ny {
+ dy2 = (j - wy) ** 2
+ do i = 1, nx {
+ r2 = (i - wx) ** 2 + dy2
+ if (r2 > apmaxsq)
+ next
+ r = sqrt (r2) - 0.5
+ do k = 1, naperts {
+ if (r > aperts[k])
+ next
+ fctn = max (0.0, min (1.0, aperts[k] - r))
+ sums[k] = sums[k] + fctn * pixels[i,j]
+ areas[k] = areas[k] + fctn
+ }
+ }
+ }
+end
+
+
+# AP_BRMMEASURE -- Procedure to compute the sums and areas inside the apertures.
+
+procedure ap_brmmeasure (pixels, nx, ny, wx, wy, datamin, datamax, aperts,
+ sums, areas, naperts, minapert)
+
+real pixels[nx,ARB] # subraster pixel values
+int nx, ny # dimensions of the subraster
+real wx, wy # center of subraster
+real datamin # minimum good data value
+real datamax # maximum good data value
+real aperts[ARB] # array of apertures
+double sums[ARB] # array of sums
+double areas[ARB] # aperture areas
+int naperts # number of apertures
+int minapert # minimum number of apertures
+
+int i, j, k, kindex
+double fctn
+real apmaxsq, dy2, r2, r, pixval
+
+begin
+ # Initialize.
+ apmaxsq = (aperts[naperts] + 0.5) ** 2
+ call aclrd (sums, naperts)
+ call aclrd (areas, naperts)
+ minapert = naperts + 1
+
+ # Loop over the pixels.
+ do j = 1, ny {
+ dy2 = (j - wy) ** 2
+ do i = 1, nx {
+ r2 = (i - wx) ** 2 + dy2
+ if (r2 > apmaxsq)
+ next
+ r = sqrt (r2) - 0.5
+ kindex = naperts + 1
+ pixval = pixels[i,j]
+ do k = 1, naperts {
+ if (r > aperts[k])
+ next
+ kindex = min (k, kindex)
+ fctn = max (0.0, min (1.0, aperts[k] - r))
+ sums[k] = sums[k] + fctn * pixval
+ areas[k] = areas[k] + fctn
+ }
+ if (kindex < minapert) {
+ if (pixval < datamin || pixval > datamax)
+ minapert = kindex
+ }
+ }
+ }
+end
diff --git a/noao/digiphot/apphot/radprof/aprpars.x b/noao/digiphot/apphot/radprof/aprpars.x
new file mode 100644
index 00000000..fb4ed401
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/aprpars.x
@@ -0,0 +1,37 @@
+include "../lib/display.h"
+include "../lib/radprof.h"
+
+# AP_RPARS -- Procedure to write the radprof parameters to the parameter
+# file.
+
+procedure ap_rpars (ap)
+
+pointer ap # pointer to apphot structure
+
+bool itob()
+int apstati()
+real apstatr()
+
+begin
+ # Write the data dependent parameters.
+ call ap_dapars (ap)
+
+ # Write the centering parameters.
+ call ap_cepars (ap)
+
+ # Write the sky fitting parameters.
+ call ap_sapars (ap)
+
+ # Write out the photometry parameters.
+ call ap_phpars (ap)
+
+ # Set the radphot parameters
+ call clputr ("radius", apstatr (ap, RPRADIUS))
+ call clputr ("step", apstatr (ap, RPSTEP))
+ call clputi ("order", apstati (ap, RPORDER))
+ call clputr ("kreject", apstatr (ap, RPKSIGMA))
+ call clputi ("nreject", apstati (ap, RPNREJECT))
+
+ # Set radial profile plots
+ call clputb ("radplots", itob (apstati (ap, RADPLOTS)))
+end
diff --git a/noao/digiphot/apphot/radprof/aprpbuf.x b/noao/digiphot/apphot/radprof/aprpbuf.x
new file mode 100644
index 00000000..3a2f73ed
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/aprpbuf.x
@@ -0,0 +1,82 @@
+include <imhdr.h>
+include "../lib/apphotdef.h"
+include "../lib/radprofdef.h"
+include "../lib/radprof.h"
+
+# AP_RPBUF -- Procedure to determine the mapping of the of the radial
+# profile size into the apertures.
+
+int procedure ap_rpbuf (ap, im, wx, wy)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to the IRAF image
+real wx, wy # center coordinates
+
+int c1, c2, l1, l2
+pointer rprof
+real rbuf
+pointer ap_rppix()
+
+begin
+ # Check for 0 radius aperture.
+ rprof = AP_RPROF(ap)
+ if (AP_RPRADIUS(rprof) <= 0.0)
+ return (AP_RP_NOPROFILE)
+
+ # Compute the maximum aperture size
+ rbuf = 2. * AP_RPRADIUS(rprof) * AP_SCALE(ap) + 1.
+ AP_RPIX(rprof) = ap_rppix (im, wx, wy, rbuf, c1, c2, l1, l2)
+ AP_RPXC(rprof) = wx - c1 + 1
+ AP_RPYC(rprof) = wy - l1 + 1
+ AP_RPNX(rprof) = c2 - c1 + 1
+ AP_RPNY(rprof) = l2 - l1 + 1
+
+ # Return the appropriate error code.
+ if (AP_RPIX(rprof) == NULL) {
+ return (AP_RP_NOPROFILE)
+ } else if (AP_RPNX(rprof) < rbuf || AP_RPNY(rprof) < rbuf) {
+ return (AP_RP_OUTOFBOUNDS)
+ } else {
+ return (AP_OK)
+ }
+end
+
+
+# AP_RPPIX -- Procedure to read in the aperture pixels
+
+pointer procedure ap_rppix (im, wx, wy, papert, c1, c2, l1, l2)
+
+pointer im # pointer to IRAF image
+real wx, wy # center of centering subraster annulus
+real papert # centering radius
+int c1, c2 # column limits
+int l1, l2 # line limits
+
+int ncols, nlines
+real half_papert, xc1, xc2, xl1, xl2
+pointer imgs2r()
+
+begin
+ # Check for 0 radius aperture.
+ half_papert = papert / 2.
+ if (half_papert <= 0.)
+ return (NULL)
+ ncols = IM_LEN(im,1)
+ nlines = IM_LEN(im,2)
+
+ # Test for an out of bounds aperture.
+ xc1 = wx - half_papert
+ xc2 = wx + half_papert
+ xl1 = wy - half_papert
+ xl2 = wy + half_papert
+ if (xc1 > real (ncols) || xc2 < 1.0 || xl1 > real (nlines) || xl2 < 1.0)
+ return (NULL)
+
+ # Get the column and line limits, dimensions and center of the subraster
+ # to be extracted.
+ c1 = max (1.0, min (real (ncols), xc1))
+ c2 = min (real (ncols), max (1.0, xc2))
+ l1 = max (1.0, min (real (nlines), xl1))
+ l2 = min (real (nlines), max (1.0, xl2))
+ return (imgs2r (im, c1, c2, l1, l2))
+end
diff --git a/noao/digiphot/apphot/radprof/aprpcolon.x b/noao/digiphot/apphot/radprof/aprpcolon.x
new file mode 100644
index 00000000..a5bf0eab
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/aprpcolon.x
@@ -0,0 +1,241 @@
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+include "../lib/radprof.h"
+include "../lib/display.h"
+
+# AP_RPCOLON -- Show/set radprof parameters.
+
+procedure ap_rpcolon (ap, im, cl, out, stid, ltid, cmdstr, newimage,
+ newcenterbuf, newcenter, newskybuf, newsky, newbuf, newfit)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to iraf image
+int cl # coord file descriptor
+int out # output file descriptor
+int stid # output file sequence number
+int ltid # coord list sequence number
+char cmdstr[ARB] # command string
+int newimage # new image
+int newcenterbuf, newcenter # new sky fit
+int newskybuf, newsky # new sky buffer
+int newbuf, newfit # new aperture
+
+pointer sp, incmd, outcmd
+int strdic()
+
+begin
+ call smark (sp)
+ call salloc (incmd, SZ_LINE, TY_CHAR)
+ call salloc (outcmd, SZ_LINE, TY_CHAR)
+
+ # Get the commands.
+ call sscan (cmdstr)
+ call gargwrd (Memc[incmd], SZ_LINE)
+ if (Memc[incmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, CCMDS) != 0)
+ call apccolon (ap, out, stid, cmdstr, newcenterbuf, newcenter)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, SCMDS) != 0)
+ call apscolon (ap, out, stid, cmdstr, newskybuf, newsky)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, RPCMDS) != 0)
+ call ap_profcolon (ap, out, stid, cmdstr, newbuf, newfit)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, PCMDS) != 0)
+ call apmagcolon (ap, out, stid, cmdstr, newbuf, newfit)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, APCMDS) != 0)
+ call ap_apcolon (ap, im, cl, out, stid, ltid, cmdstr, newimage,
+ newcenterbuf, newcenter, newskybuf, newsky, newbuf, newfit)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, NCMDS) != 0)
+ call ap_nscolon (ap, im, out, stid, cmdstr, newcenterbuf,
+ newcenter, newskybuf, newsky, newbuf, newfit)
+ else
+ call ap_rpimcolon (ap, cmdstr)
+
+ call sfree (sp)
+end
+
+
+# AP_PROFCOLON -- Procedure to display and modify radprof parameters.
+
+procedure ap_profcolon (ap, out, stid, cmdstr, newbuf, newfit)
+
+pointer ap # pointer to apphot structure
+int out # output file descriptor
+int stid # output file number
+char cmdstr[ARB] # command string
+int newbuf # new aperture buffers
+int newfit # compute new magnitudes
+
+int ival, ncmd
+pointer sp, cmd
+real rval
+int strdic(), nscan(), apstati()
+real apstatr()
+
+begin
+ # Get the command.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the colon command.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, RPCMDS)
+ switch (ncmd) {
+ case RCMD_RADIUS:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_RPRADIUS)
+ call pargr (apstatr (ap, RPRADIUS))
+ call pargstr (UN_RSCALEUNIT)
+ } else {
+ call apsetr (ap, RPRADIUS, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_RPRADIUS, rval, UN_RSCALEUNIT,
+ "fitting radius")
+ newbuf = YES; newfit = YES
+ }
+ case RCMD_STEPSIZE:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_RPSTEP)
+ call pargr (apstatr (ap, RPSTEP))
+ call pargstr (UN_RSCALEUNIT)
+ } else {
+ call apsetr (ap, RPSTEP, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_RPSTEP, rval, UN_RSCALEUNIT,
+ "step size in radius")
+ newfit = YES
+ }
+ case RCMD_ORDER:
+ call gargi (ival)
+ if (nscan() == 1) {
+ call printf ("%s = %d\n")
+ call pargstr (KY_RPORDER)
+ call pargi (apstati (ap, RPORDER))
+ } else {
+ call apseti (ap, RPORDER, ival)
+ if (stid > 1)
+ call ap_iparam (out, KY_RPORDER, ival, UN_RNUMBER,
+ "maximum number of rejection cycels")
+ newfit = YES
+ }
+ case RCMD_KREJECT:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g %s\n")
+ call pargstr (KY_RPKSIGMA)
+ call pargr (apstatr (ap, RPKSIGMA))
+ call pargstr (UN_RSIGMA)
+ } else {
+ call apsetr (ap, RPKSIGMA, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_RPKSIGMA, rval, UN_RSIGMA,
+ "k-sigma rejection criteron")
+ newfit = YES
+ }
+ case RCMD_NREJECT:
+ call gargi (ival)
+ if (nscan() == 1) {
+ call printf ("%s = %d\n")
+ call pargstr (KY_RPNREJECT)
+ call pargi (apstati (ap, RPNREJECT))
+ } else {
+ call apseti (ap, RPNREJECT, ival)
+ if (stid > 1)
+ call ap_iparam (out, KY_RPNREJECT, ival, UN_RNUMBER,
+ "maximum number of rejection cycles")
+ newfit = YES
+ }
+ default:
+ call printf ("Unknown or ambiguous colon command\7\n")
+ }
+ call sfree (sp)
+end
+
+
+# AP_RPIMCOLON -- Show/set quantities which are not radprof parameters.
+
+procedure ap_rpimcolon (ap, cmdstr)
+
+pointer ap # pointer to the apphot structure
+char cmdstr[ARB] # command string
+
+bool bval
+int ncmd
+pointer sp, cmd
+bool itob()
+int apstati(), strdic(), nscan(), btoi()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Get the command.
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, MISC)
+ switch (ncmd) {
+ case ACMD_SHOW:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, RPSHOWARGS)
+ switch (ncmd) {
+ case RCMD_CENTER:
+ call printf ("\n")
+ call ap_cpshow (ap)
+ call printf ("\n")
+ case RCMD_SKY:
+ call printf ("\n")
+ call ap_spshow (ap)
+ call printf ("\n")
+ case RCMD_PHOT:
+ call printf ("\n")
+ call ap_mpshow (ap)
+ call printf ("\n")
+ case RCMD_FIT:
+ call printf ("\n")
+ call ap_rppshow (ap)
+ call printf ("\n")
+ case RCMD_DATA:
+ call printf ("\n")
+ call ap_nshow (ap)
+ call printf ("\n")
+ default:
+ call printf ("\n")
+ call ap_rprofshow (ap)
+ call printf ("\n")
+ }
+ case ACMD_RADPLOTS:
+ call gargb (bval)
+ if (nscan() == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (KY_RADPLOTS)
+ call pargb (itob (apstati (ap, RADPLOTS)))
+ } else
+ call apseti (ap, RADPLOTS, btoi (bval))
+ default:
+ call printf ("Unknown or ambiguous colon command\7\n")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/radprof/aprpfree.x b/noao/digiphot/apphot/radprof/aprpfree.x
new file mode 100644
index 00000000..2f16e03a
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/aprpfree.x
@@ -0,0 +1,60 @@
+include "../lib/apphotdef.h"
+include "../lib/radprofdef.h"
+
+# AP_RPFREE -- Procedure to free the radial profile fitting structure.
+
+procedure ap_rpfree (ap)
+
+pointer ap # pointer to the apphot structure
+
+begin
+ if (ap == NULL)
+ return
+ if (AP_NOISE(ap) != NULL)
+ call ap_noisecls (ap)
+ if (AP_PCENTER(ap) != NULL)
+ call ap_ctrcls (ap)
+ if (AP_PDISPLAY(ap) != NULL)
+ call ap_dispcls (ap)
+ if (AP_POLY(ap) != NULL)
+ call ap_ycls (ap)
+ if (AP_PPHOT(ap) != NULL)
+ call ap_photcls (ap)
+ if (AP_PPSF(ap) != NULL)
+ call ap_psfcls (ap)
+ if (AP_RPROF(ap) != NULL)
+ call ap_rpcls (ap)
+ if (AP_PSKY(ap) != NULL)
+ call ap_skycls (ap)
+ if (AP_IMBUF(ap) != NULL)
+ call mfree (AP_IMBUF(ap), TY_REAL)
+ if (AP_MW(ap) != NULL)
+ call mw_close (AP_MW(ap))
+ call mfree (ap, TY_STRUCT)
+end
+
+
+# AP_RPCLS -- Procedure to closee up the radial profile fitting arrays.
+
+procedure ap_rpcls (ap)
+
+pointer ap # pointer to apphot structure
+
+pointer rprof
+
+begin
+ rprof = AP_RPROF(ap)
+ if (rprof == NULL)
+ return
+ #if (AP_RPIX(rprof) != NULL)
+ #call mfree (AP_RPIX(rprof), TY_REAL)
+ if (AP_RPDIST(rprof) != NULL)
+ call mfree (AP_RPDIST(rprof), TY_REAL)
+ if (AP_INTENSITY(rprof) != NULL)
+ call mfree (AP_INTENSITY(rprof), TY_REAL)
+ if (AP_DINTENSITY(rprof) != NULL)
+ call mfree (AP_DINTENSITY(rprof), TY_REAL)
+ if (AP_TINTENSITY(rprof) != NULL)
+ call mfree (AP_TINTENSITY(rprof), TY_REAL)
+ call mfree (rprof, TY_STRUCT)
+end
diff --git a/noao/digiphot/apphot/radprof/aprpindef.x b/noao/digiphot/apphot/radprof/aprpindef.x
new file mode 100644
index 00000000..4d92d615
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/aprpindef.x
@@ -0,0 +1,69 @@
+include "../lib/apphotdef.h"
+include "../lib/radprofdef.h"
+include "../lib/photdef.h"
+include "../lib/phot.h"
+include "../lib/radprof.h"
+
+# AP_RPINDEF -- Routine to return INDEF valued photometry and radial profile
+# buffers.
+
+procedure ap_rpindef (ap)
+
+pointer ap # pointer to the apphot structure
+
+pointer phot, rprof
+
+begin
+ phot = AP_PPHOT(ap)
+ rprof = AP_RPROF(ap)
+
+ AP_RPFWHM(rprof) = INDEFR
+ AP_INORM(rprof) = INDEFR
+ AP_TINORM(rprof) = INDEFR
+
+ call amovkr (INDEFR, Memr[AP_INTENSITY(rprof)], AP_RPNPTS(rprof))
+ call amovkr (INDEFR, Memr[AP_TINTENSITY(rprof)], AP_RPNPTS(rprof))
+ call amovkd (0.0d0, Memd[AP_AREA(phot)], AP_NAPERTS(phot))
+ call amovkd (0.0d0, Memd[AP_SUMS(phot)], AP_NAPERTS(phot))
+ call amovkr (INDEFR, Memr[AP_MAGS(phot)], AP_NAPERTS(phot))
+ call amovkr (INDEFR, Memr[AP_MAGERRS(phot)], AP_NAPERTS(phot))
+end
+
+
+# AP_MAXAP -- Procedure to setup the maximum number of apertures for phot.
+
+procedure ap_maxap (ap, pier)
+
+pointer ap # pointer to the apphot structure
+int pier # photometric error
+
+int i
+pointer phot, rprof
+real dxc1, dxc2, dyc1, dyc2, rdist, rapert
+
+begin
+ phot = AP_PPHOT(ap)
+ rprof = AP_RPROF(ap)
+
+ dxc1 = AP_RPXC(rprof) - 0.5
+ dxc2 = AP_RPNX(rprof) - AP_RPXC(rprof) + 0.5
+ dyc1 = AP_RPYC(rprof) - 0.5
+ dyc2 = AP_RPNY(rprof) - AP_RPYC(rprof) + 0.5
+
+ # Compute the maximum aperture.
+ AP_NMAXAP(phot) = 0
+ rdist = min (abs (dxc1), abs (dxc2), abs (dyc1), abs (dyc2))
+ do i = 1, AP_NAPERTS(phot) {
+ rapert = AP_SCALE(ap) * Memr[AP_APERTS(phot)+i-1]
+ if (rapert <= rdist) {
+ AP_NMAXAP(phot) = i
+ } else {
+ break
+ }
+ }
+
+ if (AP_NMAXAP(phot) < AP_NAPERTS(phot))
+ pier = AP_APERT_OUTOFBOUNDS
+ else
+ pier = AP_OK
+end
diff --git a/noao/digiphot/apphot/radprof/aprpinit.x b/noao/digiphot/apphot/radprof/aprpinit.x
new file mode 100644
index 00000000..49bea62c
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/aprpinit.x
@@ -0,0 +1,77 @@
+include "../lib/apphotdef.h"
+include "../lib/radprofdef.h"
+include "../lib/phot.h"
+
+# AP_RPINIT - Procedure to initialize the radial profile fitting structure.
+
+procedure ap_rpinit (ap, cfunction, cbox, sfunction, annulus, dannulus,
+ aperts, napert, radius, step, fwhmpsf, noise)
+
+pointer ap # pointer to the apphot structure
+int cfunction # centering algorithm
+real cbox # half width of the centering box
+int sfunction # sky fitting algorithm
+real annulus # radius of sky annulus
+real dannulus # width of sky annulus
+real aperts[ARB] # array of apertures
+int napert # number of apertures
+real radius # radius of fitting region
+real step # step size of output
+real fwhmpsf # FWHM of the PSF
+int noise # Noise model
+
+begin
+ # Set the image dependent parameters.
+ call malloc (ap, LEN_APSTRUCT, TY_STRUCT)
+
+ # Set up the global apphot package defaults.
+ call ap_defsetup (ap, fwhmpsf)
+
+ # Set up the noise model parameters.
+ call ap_noisesetup (ap, noise)
+
+ # Set up the centering algorithm parameters.
+ call ap_ctrsetup (ap, cfunction, cbox)
+
+ # Set up the sky fitting parameters.
+ call ap_skysetup (ap, sfunction, annulus, dannulus)
+
+ # Set up the photometry parameters.
+ call ap_photsetup (ap, aperts, napert, AP_PWCONSTANT)
+
+ # Set up the radial profile fitting parameters.
+ call ap_rpsetup (ap, radius, step)
+
+ # Set up the display options.
+ call ap_dispsetup (ap)
+
+ # Set psf fitting and polyphot structures to null.
+ AP_PPSF(ap) = NULL
+ AP_POLY(ap) = NULL
+end
+
+
+# AP_RPSETUP -- Procedure to set up the radial profle fitting parameters.
+
+procedure ap_rpsetup (ap, radius, step)
+
+pointer ap # pointer to apphot structure
+real radius # radius of psf to be fit
+real step # step size
+
+pointer rprof
+
+begin
+ call malloc (AP_RPROF(ap), LEN_RPSTRUCT, TY_STRUCT)
+ rprof = AP_RPROF(ap)
+ AP_RPXCUR(rprof) = INDEFR
+ AP_RPYCUR(rprof) = INDEFR
+ AP_RPRADIUS(rprof) = radius
+ AP_RPSTEP(rprof) = step
+ AP_RPIX(rprof) = NULL
+ AP_RPNPTS(rprof) = int (AP_RPRADIUS(rprof) / AP_RPSTEP(rprof)) + 1
+ call malloc (AP_RPDIST(rprof), AP_RPNPTS(rprof), TY_REAL)
+ call malloc (AP_INTENSITY(rprof), AP_RPNPTS(rprof), TY_REAL)
+ call malloc (AP_DINTENSITY(rprof), AP_RPNPTS(rprof), TY_REAL)
+ call malloc (AP_TINTENSITY(rprof), AP_RPNPTS(rprof), TY_REAL)
+end
diff --git a/noao/digiphot/apphot/radprof/aprpplot.x b/noao/digiphot/apphot/radprof/aprpplot.x
new file mode 100644
index 00000000..dee441f1
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/aprpplot.x
@@ -0,0 +1,307 @@
+include <gset.h>
+include <pkg/gtools.h>
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/photdef.h"
+include "../lib/phot.h"
+include "../lib/radprofdef.h"
+include "../lib/radprof.h"
+
+define IMIN -0.1 # Minimum intensity value for plot
+define IMAX 1.1 # Maximum intensity value for plot
+
+# AP_RPPLOT -- Procedure to plot the radial profile.
+
+procedure ap_rpplot (ap, sid, gd, makeplots)
+
+pointer ap # pointer to the apphot structure
+int sid # output file id number (not used)
+pointer gd # pointer to the plot stream
+int makeplots # make plots on the screen ?
+
+int nxpts, nypts, nrpts
+pointer rprof, gt
+real rmin, rmax, inorm, x1, x2, y1, y2, u1, u2, v1, v2
+int apstati()
+pointer ap_gtinit()
+real apstatr()
+
+begin
+ # Return if no graphics stream.
+ if (gd == NULL || makeplots == NO)
+ return
+
+ # Return if the center or sky is undefined.
+ if (IS_INDEFR(apstatr (ap, XCENTER)) || IS_INDEFR(apstatr (ap,
+ YCENTER)) || IS_INDEFR (apstatr (ap, SKY_MODE)))
+ return
+
+ # Return if there are no pixels.
+ rprof = AP_RPROF(ap)
+ if (AP_RPIX(rprof) == NULL)
+ return
+
+ # Set up some useful constants.
+ rmin = 0.0
+ rmax = apstatr (ap, SCALE) * apstatr (ap, RPRADIUS)
+ nxpts = AP_RPNX(rprof)
+ nypts = AP_RPNY(rprof)
+ nrpts = apstati (ap, RPNPTS)
+ inorm = apstatr (ap, INORM)
+
+ # Reopen the work station.
+ call greactivate (gd, 0)
+
+ # Save old viewport and coordinates.
+ call ggwind (gd, x1, x2, y1, y2)
+ call ggview (gd, u1, u2, v1, v2)
+
+ # Set up the labels and annotate the plot.
+ gt = ap_gtinit (AP_IMROOT(ap), apstatr (ap, OXINIT), apstatr (ap,
+ OYINIT))
+ call gclear (gd)
+ call ap_rpset (gd, gt, ap, rmin, rmax, IMIN, IMAX)
+ call ap_rpannotate (gd, ap, rmin, rmax, IMIN, IMAX)
+
+ # Plot the intensity and total intensity.
+ call ap_plothist (gd, gt, Memr[AP_RPDIST(rprof)],
+ Memr[AP_INTENSITY(rprof)], nrpts, "line", GL_SOLID)
+ call ap_plothist (gd, gt, Memr[AP_RPDIST(rprof)],
+ Memr[AP_TINTENSITY(rprof)], nrpts, "line", GL_DOTDASH)
+
+ # Plot the points.
+ call gswind (gd, rmin, rmax, (IMIN * inorm), (IMAX * inorm))
+ call rp_ptsplot (gd, gt, Memr[AP_RPIX(rprof)], nxpts, nypts,
+ AP_RPXC(rprof), AP_RPYC(rprof))
+
+ # Restore old viewport and world coordinates.
+ call gsview (gd, u1, u2, v1, v2)
+ call gswind (gd, x1, x2, y1, y2)
+
+ call ap_gtfree (gt)
+ call gdeactivate (gd, 0)
+end
+
+
+# AP_RPSET -- Procedure to set up the parameters for the radial profile
+# plot.
+
+procedure ap_rpset (gd, gt, ap, xmin, xmax, ymin, ymax)
+
+pointer gd # graphics stream
+pointer gt # gtools pointer
+pointer ap # apphot pointer
+real xmin, xmax # minimum and maximum radial distance
+real ymin, ymax # minimum and maximum of the y axis
+
+int fd, naperts
+pointer sp, str, tstr, temp
+real scale, aspect, vx1, vx2, vy1, vy2
+int stropen(), apstati()
+real apstatr(), gstatr()
+
+begin
+ call smark (sp)
+ call salloc (str, 6 * SZ_LINE, TY_CHAR)
+ call salloc (tstr, SZ_LINE, TY_CHAR)
+ naperts = apstati (ap, NAPERTS)
+ call salloc (temp, naperts, TY_REAL)
+
+ # Open the title string.
+ fd = stropen (Memc[str], 6 * SZ_LINE, WRITE_ONLY)
+
+ # Encode the sysid.
+ call sysid (Memc[tstr], SZ_LINE)
+ call fprintf (fd, "%s\n")
+ call pargstr (Memc[tstr])
+
+ # Encode the center string
+ call fprintf (fd,
+ "Center: xc=%0.2f yc=%0.2f xerr=%0.2f yerr=%0.2f\n")
+ call pargr (apstatr (ap, OXCENTER))
+ call pargr (apstatr (ap, OYCENTER))
+ call pargr (apstatr (ap, XERR))
+ call pargr (apstatr (ap, YERR))
+
+ # Encode the sky string
+ call fprintf (fd,
+ "Sky: value=%0.2f sigma=%0.2f skew=%0.2f nsky=%d nreject=%d\n")
+ call pargr (apstatr (ap, SKY_MODE))
+ call pargr (apstatr (ap, SKY_SIGMA))
+ call pargr (apstatr (ap, SKY_SKEW))
+ call pargi (apstati (ap, NSKY))
+ call pargi (apstati (ap, NSKY_REJECT))
+
+ # Encode the value of the magnitude at the maximum aperture.
+ call fprintf (fd, "Photometry: fwhmpsf=%0.3f maxapert=")
+ call pargr (apstatr (ap, RPFWHM))
+ call ap_arrayr (ap, APERTS, Memr[temp])
+ call amulkr (Memr[temp], apstatr (ap, SCALE), Memr[temp], naperts)
+ call fprintf (fd, "%0.2f mags=")
+ call pargr (Memr[temp+naperts-1])
+ call ap_arrayr (ap, MAGS, Memr[temp])
+ call fprintf (fd, "%0.3f\n")
+ call pargr (Memr[temp+naperts-1])
+
+ # Encode the parameter string.
+ call fprintf (fd,
+ "Fit: spline3 order=%d krej=%0.1f sigma np=%d nprej=%d\n")
+ call pargi (apstati (ap, RPORDER))
+ call pargr (apstatr (ap, RPKSIGMA))
+ call pargi (apstati (ap, RPNDATA))
+ call pargi (apstati (ap, RPNDATAREJ))
+
+ # Encode the title.
+ call gt_gets (gt, GTTITLE, Memc[tstr], SZ_LINE)
+ call fprintf (fd, "%s\n\n")
+ call pargstr (Memc[tstr])
+
+ call strclose (fd)
+
+ aspect = gstatr (gd, G_ASPECT)
+ scale = apstatr (ap, SCALE)
+ call gsetr (gd, G_ASPECT, 0.70)
+ call gseti (gd, G_WCS, 2)
+
+ # Draw and label the axes.
+ call gseti (gd, G_XDRAWAXES, 2)
+ call gswind (gd, xmin / scale, xmax / scale, ymin, ymax)
+ call glabax (gd, Memc[str], "", "Intensity")
+ call gseti (gd, G_YDRAWAXES, 0)
+ call gseti (gd, G_XDRAWAXES, 1)
+ call ggview (gd, vx1, vx2, vy1, vy2)
+ call gsview (gd, vx1, vx2, vy1, vy2)
+ call gswind (gd, xmin, xmax, ymin, ymax)
+ call glabax (gd, "",
+ "Radial Distance (lower-pixels, upper-scale units)", "")
+
+ # Reset the axes parameters.
+ call gseti (gd, G_YDRAWAXES, 3)
+ call gseti (gd, G_XDRAWAXES, 3)
+ call gsetr (gd, G_ASPECT, aspect)
+
+ # Set the plot type.
+ call gt_sets (gt, GTTYPE, "line")
+
+ call sfree (sp)
+end
+
+
+# AP_RPANNOTATE -- Procedure to annotate the radial plot in radprof.
+
+procedure ap_rpannotate (gd, ap, xmin, xmax, ymin, ymax)
+
+pointer gd # graphics stream
+pointer ap # apphot structure
+real xmin, xmax # min and max of x axis
+real ymin, ymax # min and max of y axis
+
+int naperts
+pointer sp, str, temp
+real scale, rpfwhm, annulus, dannulus, inorm, tinorm
+int apstati()
+real apstatr()
+
+begin
+ # Allocate working space.
+ naperts = apstati (ap, NAPERTS)
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (temp, naperts, TY_REAL)
+ call gseti (gd, G_PLTYPE, GL_DASHED)
+
+ # Draw the zero level line.
+ call gamove (gd, xmin, 0.0)
+ call gadraw (gd, xmax, 0.0)
+
+ # Draw the half power point.
+ call gamove (gd, xmin, 0.5)
+ call gadraw (gd, xmax, 0.5)
+
+ # Draw the unit normalization value.
+ call gamove (gd, xmin, 1.0)
+ call gadraw (gd, xmax, 1.0)
+
+ # Plot the full width half maximum of the radial profile.
+ scale = apstatr (ap, SCALE)
+ rpfwhm = apstatr (ap, RPFWHM) / 2.0
+ if (rpfwhm >= xmin && rpfwhm <= xmax) {
+ call gamove (gd, rpfwhm, ymin)
+ call gadraw (gd, rpfwhm, ymax)
+ call sprintf (Memc[str], SZ_LINE, "hwhm = %0.2f")
+ call pargr (rpfwhm)
+ call gtext (gd, rpfwhm, 0.0, Memc[str], "q=h;u=180;p=r")
+ }
+
+ # Mark the sky annuli.
+ annulus = scale * apstatr (ap, ANNULUS)
+ dannulus = scale * (apstatr (ap, ANNULUS) + apstatr (ap, DANNULUS))
+ if (annulus >= xmin && annulus <= xmax) {
+ call gamove (gd, annulus, ymin)
+ call gadraw (gd, annulus, ymax)
+ call sprintf (Memc[str], SZ_LINE, "inner sky radius = %0.2f")
+ call pargr (annulus)
+ call gtext (gd, annulus, 0.0, Memc[str], "q=h;u=180;p=r")
+ }
+ if (dannulus >= xmin && dannulus <= xmax) {
+ call gamove (gd, dannulus, ymin)
+ call gadraw (gd, dannulus, ymax)
+ call sprintf (Memc[str], SZ_LINE, "outer sky radius = %0.2f")
+ call pargr (dannulus)
+ call gtext (gd, dannulus, 0.0, Memc[str], "q=h;u=180;p=r")
+ }
+
+ # Plot the aperture value.
+ call ap_arrayr (ap, APERTS, Memr[temp])
+ call amulkr (Memr[temp], scale, Memr[temp], naperts)
+ call gseti (gd, G_PLTYPE, GL_SOLID)
+ if (Memr[temp+naperts-1] >= xmin && Memr[temp+naperts-1] <= xmax) {
+ call gamove (gd, Memr[temp+naperts-1], ymin)
+ call gadraw (gd, Memr[temp+naperts-1], ymax)
+ call sprintf (Memc[str], SZ_LINE, "maxapert = %0.2f")
+ call pargr (Memr[temp+naperts-1])
+ call gtext (gd, Memr[temp+naperts-1], 0.0, Memc[str],
+ "q=h;u=180;p=r")
+ }
+ call gseti (gd, G_PLTYPE, GL_DASHED)
+
+ # Plot the inorm value.
+ inorm = apstatr (ap, INORM)
+ call sprintf (Memc[str], SZ_LINE, "inorm = %0.2f")
+ call pargr (inorm)
+ call gtext (gd, 0.0, 1.0, Memc[str], "q=h")
+
+ # Plot the tinorm value.
+ tinorm = apstatr (ap, TNORM)
+ call sprintf (Memc[str], SZ_LINE, "tinorm = %0.2f")
+ call pargr (tinorm)
+ call gtext (gd, xmax, 1.0, Memc[str], "q=h;h=r")
+
+ call sfree (sp)
+end
+
+
+# RP_PTSPLOT -- Plot the radial profile plots.
+
+procedure rp_ptsplot (gd, gt, pixels, nx, ny, wx, wy)
+
+pointer gd # pointer to the graphics stream
+pointer gt # pointer to the gtools structure
+real pixels[nx,ARB] # subraster of pixel values
+int nx, ny # dimensions of the pixel subraster
+real wx, wy # x and y coordinates of the center
+
+int i
+pointer sp, rtemp
+
+begin
+ call smark (sp)
+ call salloc (rtemp, nx, TY_REAL)
+ do i = 1, ny {
+ call ap_ijtor (Memr[rtemp], nx, i, wx, wy)
+ call ap_plotrad (gd, gt, Memr[rtemp], pixels[1,i], nx, "plus")
+ }
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/radprof/iradprof.key b/noao/digiphot/apphot/radprof/iradprof.key
new file mode 100644
index 00000000..1c5a8974
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/iradprof.key
@@ -0,0 +1,20 @@
+ Interactive Radprof Setup Menu
+
+ v Mark and verify the critical parameters (f,c,s,a,d,r,w,x)
+
+ f Mark and verify the psf full-width half-maximum
+ s Mark and verify the standard deviation of the background
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
+
+ c Mark and verify the centering box width
+ n Mark and verify the cleaning radius
+ p Mark and verify the clipping radius
+
+ a Mark and verify the inner radius of the sky annulus
+ d Mark and verify the width of the sky annulus
+ g Mark and verify the region growing radius
+
+ r Mark and verify the photometry aperture radii
+ w Mark and verify the radius of the radial profile
+ x Mark and verify the step size of radial profile
diff --git a/noao/digiphot/apphot/radprof/mkpkg b/noao/digiphot/apphot/radprof/mkpkg
new file mode 100644
index 00000000..8ef786bc
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/mkpkg
@@ -0,0 +1,58 @@
+RADPROF Fitting Task Routines
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ apbradprof.x <fset.h> ../lib/apphot.h \
+ ../lib/center.h ../lib/fitsky.h \
+ ../lib/display.h
+ apgrpars.x ../lib/center.h ../lib/fitsky.h \
+ ../lib/phot.h ../lib/display.h \
+ ../lib/noise.h ../lib/radprof.h
+ approfsetup.x ../lib/center.h ../lib/fitsky.h \
+ ../lib/display.h
+ apprprof.x ../lib/apphotdef.h ../lib/apphot.h \
+ ../lib/center.h ../lib/fitsky.h \
+ ../lib/photdef.h ../lib/phot.h \
+ ../lib/radprof.h
+ apradprof.x <ctype.h> <gset.h> \
+ ../lib/apphot.h ../lib/center.h \
+ ../lib/fitsky.h ../lib/radprof.h \
+ ../lib/display.h <imhdr.h>
+ aprconfirm.x ../lib/apphot.h ../lib/noise.h \
+ ../lib/center.h ../lib/fitsky.h \
+ ../lib/phot.h ../lib/radprof.h
+ aprferrors.x ../lib/phot.h ../lib/radprof.h
+ aprmmeasure.x <math/curfit.h>
+ aprpars.x ../lib/radprof.h ../lib/display.h
+ aprpbuf.x <imhdr.h> ../lib/apphotdef.h \
+ ../lib/radprofdef.h ../lib/radprof.h
+ aprpcolon.x ../lib/apphot.h ../lib/fitsky.h \
+ ../lib/center.h ../lib/phot.h \
+ ../lib/radprof.h ../lib/noise.h \
+ ../lib/display.h
+ aprpfree.x ../lib/apphotdef.h ../lib/radprofdef.h
+ aprpindef.x ../lib/apphotdef.h ../lib/radprofdef.h \
+ ../lib/radprof.h ../lib/photdef.h \
+ ../lib/phot.h
+ aprpinit.x ../lib/apphotdef.h ../lib/radprofdef.h \
+ ../lib/phot.h
+ aprpplot.x <gset.h> <pkg/gtools.h> \
+ ../lib/apphotdef.h ../lib/photdef.h \
+ ../lib/radprof.h ../lib/phot.h \
+ ../lib/fitsky.h ../lib/radprofdef.h \
+ ../lib/center.h ../lib/apphot.h
+ apfrprof.x <math/curfit.h> <math/iminterp.h> \
+ <gset.h> ../lib/fitskydef.h \
+ ../lib/apphotdef.h ../lib/radprofdef.h \
+ ../lib/phot.h ../lib/photdef.h \
+ ../lib/radprof.h <math.h> \
+ <mach.h> "../lib/noisedef.h" \
+ ../lib/apphot.h
+ rprofshow.x ../lib/display.h ../lib/radprof.h
+ t_radprof.x <fset.h> <gset.h> \
+ ../lib/apphot.h <imhdr.h>
+ ;
diff --git a/noao/digiphot/apphot/radprof/radprof.key b/noao/digiphot/apphot/radprof/radprof.key
new file mode 100644
index 00000000..4204743f
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/radprof.key
@@ -0,0 +1,116 @@
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+v Verify the critical parameters
+w Store the current parameters
+d Plot radial profile of current star
+i Interactively set parameters using current star
+c Fit center of current star
+t Fit sky around cursor
+a Average sky values fit around several cursor positions
+s Fit sky around the current star
+p Fit star using current sky
+o Fit star using current sky, output results
+f Fit current star
+spbar Fit current star, output results
+m Move to next star in coordinate list
+n Fit next star in coordinate list, output results
+l Fit remaining stars in coordinate list, output results
+r Rewind the coordinate list
+e Print error messages
+q Exit task
+
+
+ Colon Commands
+
+:show [data/center/sky/fit] List the parameters
+:m [n] Move to next [nth] object in coordinate list
+:n [n] Fit next [nth] object in coordinate list, output results
+
+
+ Colon Parameter Editing Commands
+
+# Image and file name parameters
+
+:image [string] Image name
+:coords [string] Coordinate file name
+:output [string] Output file name
+
+# Data dependent parameters
+
+:scale [vlaue] Image scale (units per pixel)
+:fwhmpsf [value] Full-width half-maximum of psf (scale units)
+:emission [y/n] Emission features (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good pixel value (counts)
+:datamax [value] Maximum good pixel value (counts)
+
+# Noise parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per adu)
+:readnoise [value] Readout noise (electrons)
+
+# Observing parameters
+
+:exposure [value] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Integration time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observation (time units)
+
+# Centering algorithm parameters
+
+:calgorithm [string] Centering algorithm
+:cbox [value] Width of the centering box (scale units)
+:cthreshold [value] Centering intensity threshold (sigma)
+:cmaxiter [value] Maximum number of iterations
+:maxshift [value] Maximum center shift (scale units)
+:minsnratio [value] Minimum S/N ratio for centering
+:clean [y/n] Clean subraster before centering
+:rclean [value] Cleaning radius (scale units)
+:rclip [value] Clipping radius (scale units)
+:kclean [value] Clean K-sigma rejection limit (sigma)
+
+# Sky fitting algorithm parameters
+
+:salgorithm [string] Sky fitting algorithm
+:skyvalue [value] User supplied sky value (counts)
+:annulus [value] Inner radius of sky annulus (scale units)
+:dannulus [value] Width of sky annulus (scale units)
+:khist [value] Sky histogram extent (+/- sigma)
+:binsize [value] Resolution of sky histogram (sigma)
+:sloclip [value] Low-side clipping factor in percent
+:shiclip [value] High-side clipping factor in percent
+:smaxiter [value] Maximum number of iterations
+:smooth [y/n] Lucy smooth the sky histogram
+:snreject [value] Maximum number of rejection cycles
+:sloreject [value] Low-side pixel rejection limits (sky sigma)
+:shireject [value] High-side pixel rejection limits (sky sigma)
+:rgrow [value] Region growing radius (scale units)
+
+# Photometry parameters
+
+:apertures [string] List of apertures (scale units)
+:zmag [value] Zero point of magnitude scale
+
+# Profile fitting parameters
+
+:radius [value] Maximum profile radius (scale units)
+:step [value] Step size for computed profile (scale units)
+:order [value] Number of spline pieces in fit
+:kreject [value] K-sigma rejection for fit (fit sigma)
+:nreject [value] Maximum number of rejection cycles
+
+# Marking and plotting parameters
+
+:mkcenter [y/n] Mark computed centers on display
+:mksky [y/n] Mark the sky annuli on the display
+:mkapert [y/n] Mark apertures on the display
+:radplot [y/n] Plot the radial profile
diff --git a/noao/digiphot/apphot/radprof/rprofshow.x b/noao/digiphot/apphot/radprof/rprofshow.x
new file mode 100644
index 00000000..c4264ede
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/rprofshow.x
@@ -0,0 +1,75 @@
+include "../lib/display.h"
+include "../lib/radprof.h"
+
+# AP_RPROFSHOW -- Procedure to display all the radprof parameters.
+
+procedure ap_rprofshow (ap)
+
+pointer ap # pointer to the apphot strucuture
+
+bool itob()
+int apstati()
+
+begin
+ call ap_nshow (ap)
+ call printf ("\n")
+ call ap_cpshow (ap)
+ call printf ("\n")
+ call ap_spshow (ap)
+ call printf ("\n")
+ call ap_mpshow (ap)
+ call printf ("\n")
+ call ap_rppshow (ap)
+ call printf (" %s = %b\n")
+ call pargstr (KY_RADPLOTS)
+ call pargb (itob (apstati (ap, RADPLOTS)))
+end
+
+
+# AP_RPSHOW -- Procedure to display radprof parameters.
+
+procedure ap_rpshow (ap)
+
+pointer ap # pointer to apphot structure
+
+bool itob()
+int apstati()
+
+begin
+ call ap_nshow (ap)
+ call ap_rppshow (ap)
+ call printf (" %s = %b\n")
+ call pargstr (KY_RADPLOTS)
+ call pargb (itob (apstati (ap, RADPLOTS)))
+end
+
+
+# AP_RPPSHOW -- Procedure to display radprof parameters.
+
+procedure ap_rppshow (ap)
+
+pointer ap # pointer to apphot structure
+
+int apstati()
+real apstatr()
+
+begin
+ # Print the radial profile characteristics.
+ call printf ("Radial Profile Fitting Parameters\n")
+ call printf (" %s = %g %s %s = %g %s\n")
+ call pargstr (KY_RPRADIUS)
+ call pargr (apstatr (ap, RPRADIUS))
+ call pargstr (UN_RSCALEUNIT)
+ call pargstr (KY_RPSTEP)
+ call pargr (apstatr (ap, RPSTEP))
+ call pargstr (UN_RSCALEUNIT)
+
+ call printf (" %s = %d %s = %g %s %s = %d\n")
+ call pargstr (KY_RPORDER)
+ call pargi (apstati (ap, RPORDER))
+ call pargstr (KY_RPKSIGMA)
+ call pargr (apstatr (ap, RPKSIGMA))
+ call pargstr (UN_RSIGMA)
+ call pargstr (KY_RPNREJECT)
+ call pargi (apstati (ap, RPNREJECT))
+end
diff --git a/noao/digiphot/apphot/radprof/t_radprof.x b/noao/digiphot/apphot/radprof/t_radprof.x
new file mode 100644
index 00000000..fda4c459
--- /dev/null
+++ b/noao/digiphot/apphot/radprof/t_radprof.x
@@ -0,0 +1,306 @@
+include <fset.h>
+include <gset.h>
+include <imhdr.h>
+include "../lib/apphot.h"
+
+# T_RADPROF -- Procedure to compute the radial profiles of a list of
+# objects.
+
+procedure t_radprof ()
+
+pointer image # pointer to the name of the image
+pointer output # pointer to the output file name
+pointer coords # pointer to the coordinate file
+pointer plotfile # pointer to the metacode plot file
+pointer graphics # pointer to the graphics device
+pointer display # pointer to the display device
+int interactive # interactive mode
+int cache # cache the input image
+int verify # verify the critical parameters
+int update # update the critical parameters
+int verbose # verbose mode
+
+pointer sp, cname, outfname, ap, im, id, gd, mgd, str
+int limlist, lclist, lolist, sid, lid, cl, out, pfd, root, stat
+int imlist, clist, olist, wcs, memstat, req_size, old_size, buf_size
+
+pointer immap(), gopen()
+int imtlen(), imtgetim(), clplen(), clgfil(), btoi(), fnldir(), strncmp()
+int strlen(), ap_radprof(), imtopenp(), clpopnu(), open(), clgwrd()
+int ap_memstat(), sizeof()
+bool clgetb(), streq()
+errchk gopen
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (coords, SZ_FNAME, TY_CHAR)
+ call salloc (plotfile, SZ_FNAME, TY_CHAR)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+ call salloc (display, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (cname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Set standard output to flush on newline.
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get input and output file names.
+ imlist = imtopenp ("image")
+ limlist = imtlen (imlist)
+ clist = clpopnu ("coords")
+ lclist = clplen (clist)
+ olist = clpopnu ("output")
+ lolist = clplen (olist)
+
+ # Check that the image and coordinate list lengths match.
+ if (limlist < 1 || (lclist > 1 && lclist != limlist)) {
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+ call error (0, "Imcompatible image and coordinate list lengths")
+ }
+
+ # Check that image and output list lengths match.
+ if (lolist > 1 && lolist != limlist) {
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+ call error (0, "Imcompatible image and output list lengths")
+ }
+
+ call clgstr ("icommands.p_filename", Memc[cname], SZ_FNAME)
+ if (Memc[cname] != EOS)
+ interactive = NO
+ #else if (lclist == 0)
+ #interactive = YES
+ else
+ interactive = btoi (clgetb ("interactive"))
+ cache = btoi (clgetb ("cache"))
+ verify = btoi (clgetb ("verify"))
+ update = btoi (clgetb ("update"))
+ verbose = btoi (clgetb ("verbose"))
+
+ # Get the radial profile fitting parameters.
+ call ap_grppars (ap)
+
+ # Verify the radial profile fitting parameters.
+ if (verify == YES && interactive == NO) {
+ call ap_rconfirm (ap, NULL, 1)
+ if (update == YES)
+ call ap_rpars (ap)
+ }
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_LINE, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (ap, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_LINE, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (ap, WCSOUT, wcs)
+
+ # Get the graphics and display devices.
+ call clgstr ("graphics", Memc[graphics], SZ_FNAME)
+ call clgstr ("display", Memc[display], SZ_FNAME)
+
+ # Open the plot files.
+ if (interactive == YES) {
+ if (Memc[graphics] == EOS)
+ gd = NULL
+ else {
+ iferr {
+ gd = gopen (Memc[graphics], APPEND+AW_DEFER, STDGRAPH)
+ } then {
+ call eprintf (
+ "Warning: Error opening graphics device.\n")
+ gd = NULL
+ }
+ }
+ if (Memc[display] == EOS)
+ id = NULL
+ else if (streq (Memc[graphics], Memc[display]))
+ id = gd
+ else {
+ iferr {
+ id = gopen (Memc[display], APPEND, STDIMAGE)
+ } then {
+ call eprintf (
+ "Warning: Graphics overlay not available for display device.\n")
+ id = NULL
+ }
+ }
+ } else {
+ gd = NULL
+ id = NULL
+ }
+
+ # Open the plot metacode file.
+ call clgstr ("plotfile", Memc[plotfile], SZ_FNAME)
+ if (Memc[plotfile] == EOS)
+ pfd = NULL
+ else
+ pfd = open (Memc[plotfile], APPEND, BINARY_FILE)
+ if (pfd != NULL)
+ mgd = gopen (Memc[graphics], NEW_FILE, pfd)
+ else
+ mgd = NULL
+
+ # Begin looping over the image list.
+ sid = 1
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open the image.
+ im = immap (Memc[image], READ_ONLY, 0)
+
+ # Set the image display viewport.
+ call apimkeys (ap, im, Memc[image])
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[image], im, 4)
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+
+ # Open the coordinate file, where coords is assumed to be a simple
+ # text file in which the x and y positions are in columns 1 and 2
+ # respectively and all remaining fields are ignored.
+
+ if (lclist <= 0) {
+ cl = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (clist, Memc[coords], SZ_FNAME)
+ root = fnldir (Memc[coords], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[coords+root], 7) == 0 || root ==
+ strlen (Memc[coords])) {
+ call ap_inname (Memc[image], Memc[outfname], "coo",
+ Memc[outfname], SZ_FNAME)
+ lclist = limlist
+ cl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else if (stat != EOF) {
+ call strcpy (Memc[coords], Memc[outfname], SZ_FNAME)
+ cl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else {
+ call apstats (ap, CLNAME, Memc[outfname], SZ_FNAME)
+ call seek (cl, BOF)
+ }
+ }
+ call apsets (ap, CLNAME, Memc[outfname])
+ call apfroot (Memc[outfname], Memc[str], SZ_FNAME)
+ call apsets (ap, CLROOT, Memc[str])
+
+ # Open output text file, if output is "default", dir$default,
+ # or a directory specification then the extension "prf" is added
+ # to the image name and a suitable version number is appended to
+ # the output name. If the output name is null then no output
+ # file is created.
+
+ if (lolist == 0) {
+ out = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (olist, Memc[output], SZ_FNAME)
+ root = fnldir (Memc[output], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[output+root], 7) == 0 || root ==
+ strlen (Memc[output])) {
+ call apoutname (Memc[image], Memc[outfname], "prf",
+ Memc[outfname], SZ_FNAME)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ lolist = limlist
+ } else if (stat != EOF) {
+ call strcpy (Memc[output], Memc[outfname], SZ_FNAME)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ } else
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ }
+ call apsets (ap, OUTNAME, Memc[outfname])
+
+ # Fit the radial profiles.
+ if (interactive == NO) {
+ if (Memc[cname] != EOS)
+ stat = ap_radprof (ap, im, cl, NULL, mgd, NULL, out,
+ sid, NO, cache)
+ else if (cl != NULL) {
+ lid = 1
+ call ap_bradprof (ap, im, cl, id, gd, mgd, out, sid, lid,
+ verbose)
+ stat = NO
+ } else
+ stat = NO
+ } else
+ stat = ap_radprof (ap, im, cl, gd, mgd, id, out, sid, YES,
+ cache)
+
+ # Cleanup.
+ call imunmap (im)
+ if (cl != NULL) {
+ if (lclist > 1)
+ call close (cl)
+ }
+ if (out != NULL && lolist != 1) {
+ call close (out)
+ if (sid <= 1) {
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ call delete (Memc[outfname])
+ }
+ sid = 1
+ }
+
+ # Uncache memory.
+ call fixmem (old_size)
+
+ if (stat == YES)
+ break
+
+ }
+
+ # If only one coordinate file for a list of images close list.
+ if (cl != NULL && lclist == 1)
+ call close (cl)
+
+ # If only one output file for a list of images close list.
+ if (out != NULL && lolist == 1) {
+ call close (out)
+ if (sid <= 1) {
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ call delete (Memc[outfname])
+ }
+ }
+
+ # Close up plot files.
+ if (id == gd && id != NULL)
+ call gclose (id)
+ else {
+ if (gd != NULL)
+ call gclose (gd)
+ if (id != NULL)
+ call gclose (id)
+ }
+ if (mgd != NULL)
+ call gclose (mgd)
+ if (pfd != NULL)
+ call close (pfd)
+
+ # Free the radial profile fitting structure.
+ call ap_rpfree (ap)
+
+ # Close up the lists.
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/temp b/noao/digiphot/apphot/temp
new file mode 100644
index 00000000..afb44322
--- /dev/null
+++ b/noao/digiphot/apphot/temp
@@ -0,0 +1,8 @@
+-rw-rw-r-- 1 davis 8974 Sep 30 15:53 t_center.x
+-rw-rw-r-- 1 davis 8366 Sep 30 15:53 t_fitpsf.x
+-rw-rw-r-- 1 davis 8829 Sep 30 15:54 t_fitsky.x
+-rw-rw-r-- 1 davis 9968 Sep 30 15:57 t_phot.x
+-rw-rw-r-- 1 davis 8526 Sep 30 15:57 t_qphot.x
+-rw-rw-r-- 1 davis 9430 Sep 30 15:55 t_polyphot.x
+-rw-rw-r-- 1 davis 8936 Sep 30 15:58 t_radprof.x
+-rw-rw-r-- 1 davis 9933 Sep 30 15:56 t_wphot.x
diff --git a/noao/digiphot/apphot/test/README b/noao/digiphot/apphot/test/README
new file mode 100644
index 00000000..006e6988
--- /dev/null
+++ b/noao/digiphot/apphot/test/README
@@ -0,0 +1,5 @@
+This subdirectory contains test data for the installer/maintainer of
+the apphot package. The files beginning with fits contain test images
+of both real and artificial data. There are also some coordinate files
+supplied for these images. Eventually there will be some apphot demos
+which can be run to automatically test new releases of the software etc.
diff --git a/noao/digiphot/apphot/test/coords.dat b/noao/digiphot/apphot/test/coords.dat
new file mode 100644
index 00000000..f6458223
--- /dev/null
+++ b/noao/digiphot/apphot/test/coords.dat
@@ -0,0 +1,10 @@
+36 22 1 \40
+26 22 1 \40
+36 42 1 \40
+31 25 1 \40
+29 34 1 \40
+18 8 1 \40
+21 26 1 \40
+23 7 1 \40
+8 23 1 \40
+41 4 1 \40
diff --git a/noao/digiphot/apphot/test/fits1.fits b/noao/digiphot/apphot/test/fits1.fits
new file mode 100644
index 00000000..85105ec8
--- /dev/null
+++ b/noao/digiphot/apphot/test/fits1.fits
Binary files differ
diff --git a/noao/digiphot/apphot/test/fits2.fits b/noao/digiphot/apphot/test/fits2.fits
new file mode 100644
index 00000000..212a0c12
--- /dev/null
+++ b/noao/digiphot/apphot/test/fits2.fits
Binary files differ
diff --git a/noao/digiphot/apphot/test/fits3.fits b/noao/digiphot/apphot/test/fits3.fits
new file mode 100644
index 00000000..ff7938e7
--- /dev/null
+++ b/noao/digiphot/apphot/test/fits3.fits
Binary files differ
diff --git a/noao/digiphot/apphot/test/fits4.fits b/noao/digiphot/apphot/test/fits4.fits
new file mode 100644
index 00000000..5f9ca811
--- /dev/null
+++ b/noao/digiphot/apphot/test/fits4.fits
Binary files differ
diff --git a/noao/digiphot/apphot/test/fits5.fits b/noao/digiphot/apphot/test/fits5.fits
new file mode 100644
index 00000000..3542fe3e
--- /dev/null
+++ b/noao/digiphot/apphot/test/fits5.fits
Binary files differ
diff --git a/noao/digiphot/apphot/test/polygons.dat b/noao/digiphot/apphot/test/polygons.dat
new file mode 100644
index 00000000..666b9df7
--- /dev/null
+++ b/noao/digiphot/apphot/test/polygons.dat
@@ -0,0 +1,6 @@
+36 22 1 \40
+26 22 1 \40
+36 42 1 \40
+31 25 1 \40
+29 34 1 \40
+;
diff --git a/noao/digiphot/apphot/wphot.par b/noao/digiphot/apphot/wphot.par
new file mode 100644
index 00000000..126d52ce
--- /dev/null
+++ b/noao/digiphot/apphot/wphot.par
@@ -0,0 +1,24 @@
+# WPHOT parameters
+
+image,f,a,,,,"The input image(s)"
+skyfile,f,a,"",,,"The input sky file(s)"
+coords,f,h,"",,,"The input coordinate file(s) (default: image.coo.?)"
+output,f,h,"default",,,The output photometry file(s) (default: image.omag.?)"
+plotfile,f,h,"",,,"The output plot metacode file"
+datapars,pset,h,"",,,"Data dependent parameters"
+centerpars,pset,h,"",,,"Centering parameters"
+fitskypars,pset,h,"",,,"Sky fitting parameters"
+photpars,pset,h,,,,"Photometry parameters"
+interactive,b,h,yes,,,"Interactive mode ?"
+radplots,b,h,no,,,"Plot radial profiles in interactive mode ?"
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor: [x y wcs] key [cmd]"
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the input image pixels ?"
+verify,b,h,)_.verify,,,"Confirm critical parameters in non-interactive mode ?"
+update,b,h,)_.update,,,"Update critical parameters in non-interactive mode ?"
+verbose,b,h,)_.verbose,,,"Print messages in non-interactive mode ?"
+graphics,s,h,)_.graphics,,,"Graphics device"
+display,s,h,)_.display,,,"Display device"
+mode,s,h,'ql'
diff --git a/noao/digiphot/apphot/wphot/apbwphot.x b/noao/digiphot/apphot/wphot/apbwphot.x
new file mode 100644
index 00000000..b684abb7
--- /dev/null
+++ b/noao/digiphot/apphot/wphot/apbwphot.x
@@ -0,0 +1,108 @@
+include <fset.h>
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+
+# AP_BWPHOT -- Procedure to compute the magnitudes for a list of objects
+# interactively.
+
+procedure ap_bwphot (ap, im, cl, sd, out, id, ld, gd, mgd, gid, interactive)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to IRAF image
+int cl # starlist file descriptor
+int sd # sky file descriptor
+int out # output file descriptor
+int id, ld # sequence and list numbers
+pointer gd # pointer to stdgraph stream
+pointer mgd # pointer to the plot metacode stream
+pointer gid # pointer to image display stream
+int interactive # interactive pr batch mode
+
+int stdin, ild, cier, sier, pier
+pointer sp, str
+real wx, wy
+int fscan(), nscan(), apfitsky(), apfitcenter(), ap_wmag(), strncmp()
+int apstati()
+real apstatr()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+ call fstats (cl, F_FILENAME, Memc[str], SZ_FNAME)
+
+ # Initialize
+ ild = ld
+
+ # Print query.
+ if (strncmp ("STDIN", Memc[str], 5) == 0)
+ stdin = YES
+ else
+ stdin = NO
+ if (stdin == YES) {
+ call printf ("Type object x and y coordinates (^D or ^Z to end): ")
+ call flush (STDOUT)
+ }
+
+ # Loop over the coordinate file.
+ while (fscan (cl) != EOF) {
+
+ # Get and store the coordinates.
+ call gargr (wx)
+ call gargr (wy)
+ if (nscan () != 2) {
+ if (stdin == YES) {
+ call printf (
+ "Type object x and y coordinates (^D or ^Z to end): ")
+ call flush (STDOUT)
+ }
+ next
+ }
+
+ # Transform the input coordinates.
+ switch (apstati(ap,WCSIN)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_itol (ap, wx, wy, wx, wy, 1)
+ case WCS_TV:
+ call ap_vtol (im, wx, wy, wx, wy, 1)
+ default:
+ ;
+ }
+ call apsetr (ap, CWX, wx)
+ call apsetr (ap, CWY, wy)
+
+ # Center the coordinatess, fit the sky and compute magnitudes.
+ cier = apfitcenter (ap, im, wx, wy)
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), sd, gd)
+ pier = ap_wmag (ap, im, apstatr (ap, XCENTER), apstatr(ap, YCENTER),
+ apstati (ap, POSITIVE), apstatr (ap, SKY_MODE),
+ apstatr (ap, SKY_SIGMA), apstati (ap, NSKY))
+
+ # Write the results.
+ if (interactive == YES) {
+ call ap_qpmag (ap, cier, sier, pier)
+ if (gid != NULL)
+ call apmark (ap, gid, apstati (ap, MKCENTER), apstati (ap,
+ MKSKY), apstati (ap, MKAPERT))
+ }
+ if (id == 1)
+ call ap_param (ap, out, "wphot")
+ call ap_pmag (ap, out, id, ild, cier, sier, pier)
+ call ap_pplot (ap, im, id, mgd, YES)
+
+ # Prepare for the next object.
+ id = id + 1
+ ild = ild + 1
+ call apsetr (ap, WX, wx)
+ call apsetr (ap, WY, wy)
+ if (stdin == YES) {
+ call printf (
+ "Type object x and y coordinates (^Z or ^D to end): ")
+ call flush (STDOUT)
+ }
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/wphot/apgmeasure.x b/noao/digiphot/apphot/wphot/apgmeasure.x
new file mode 100644
index 00000000..738630f2
--- /dev/null
+++ b/noao/digiphot/apphot/wphot/apgmeasure.x
@@ -0,0 +1,190 @@
+# AP_GMEASURE -- Procedure to measure the fluxes and effective areas of a set of
+# apertures assuming a Gaussian weighting function.
+
+procedure ap_gmeasure (im, wx, wy, c1, c2, l1, l2, aperts, sums, areas,
+ naperts, sigsq, gain, varsky)
+
+pointer im # pointer to image
+real wx, wy # center of subraster
+int c1, c2 # column limits
+int l1, l2 # line limits
+real aperts[ARB] # array of apertures
+double sums[ARB] # array of sums
+double areas[ARB] # aperture areas
+int naperts # number of apertures
+real sigsq # the profile widht squared
+real gain # the sky value
+real varsky # the sky variance
+
+int i, j, k, nx, yindex
+double fctn, weight, norm
+pointer sp, buf, sump, sumpw
+real xc, yc, apmaxsq, dy2, r2, r, prof, var
+pointer imgs2r()
+
+begin
+ # Initialize.
+ call smark (sp)
+ call salloc (sump, naperts, TY_DOUBLE)
+ call salloc (sumpw, naperts, TY_DOUBLE)
+ call aclrd (Memd[sump], naperts)
+ call aclrd (Memd[sumpw], naperts)
+
+ # Get array boundary parameters.
+ nx = c2 - c1 + 1
+ xc = wx - c1 + 1
+ yc = wy - l1 + 1
+ apmaxsq = (aperts[naperts] + 0.5) ** 2
+
+ # Clear out the accumulaters
+ call aclrd (sums, naperts)
+ call aclrd (areas, naperts)
+
+ # Loop over the pixels.
+ do j = l1, l2 {
+ buf = imgs2r (im, c1, c2, j, j)
+ if (buf == EOF) {
+ call sfree (sp)
+ return
+ }
+ yindex = j - l1 + 1
+ dy2 = (yindex - yc) ** 2
+ do i = 1, nx {
+ r2 = (i - xc) ** 2 + dy2
+ if (r2 > apmaxsq)
+ next
+ prof = max (exp (-r2 / sigsq), 0.0)
+ if (prof <= 0.0)
+ next
+ var = max (0.0, Memr[buf+i-1])
+ var = var / gain + varsky
+ if (var <= 0.0)
+ next
+ weight = prof / var
+ r = sqrt (r2) - 0.5
+ do k = 1, naperts {
+ if (r > aperts[k])
+ next
+ fctn = max (0.0, min (1.0, aperts[k] - r))
+ sums[k] = sums[k] + weight * fctn * Memr[buf+i-1]
+ areas[k] = areas[k] + weight * fctn
+ Memd[sump+k-1] = Memd[sump+k-1] + prof
+ Memd[sumpw+k-1] = Memd[sumpw+k-1] + weight * prof
+ }
+ }
+ }
+
+ # Normalize.
+ do k = 1, naperts {
+ if (Memd[sumpw+k-1] <= 0.0d0)
+ norm = 0.0d0
+ else
+ norm = Memd[sump+k-1] / Memd[sumpw+k-1]
+ sums[k] = sums[k] * norm
+ areas[k] = areas[k] * norm
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_BGMEASURE -- Procedure to measure the fluxes and effective areas of a set
+# of apertures assuming a Gaussian weighting function.
+
+procedure ap_bgmeasure (im, wx, wy, c1, c2, l1, l2, datamin, datamax,
+ aperts, sums, areas, naperts, minapert, sigsq, gain, varsky)
+
+pointer im # pointer to image
+real wx, wy # center of subraster
+int c1, c2 # column limits
+int l1, l2 # line limits
+real datamin # minimum good data
+real datamax # maximum good data
+real aperts[ARB] # array of apertures
+double sums[ARB] # array of sums
+double areas[ARB] # aperture areas
+int naperts # number of apertures
+int minapert # minimum aperture fo bad pixels
+real sigsq # the profile widht squared
+real gain # the image gain value
+real varsky # the sky variance
+
+int i, j, k, nx, yindex, kindex
+double fctn, weight, norm
+pointer sp, buf, sump, sumpw
+real xc, yc, apmaxsq, dy2, r2, r
+real pixval, prof, var
+pointer imgs2r()
+
+begin
+ # Initialize.
+ call smark (sp)
+ call salloc (sump, naperts, TY_DOUBLE)
+ call salloc (sumpw, naperts, TY_DOUBLE)
+ call aclrd (Memd[sump], naperts)
+ call aclrd (Memd[sumpw], naperts)
+ minapert = naperts + 1
+
+ # Get array boundary parameters.
+ nx = c2 - c1 + 1
+ xc = wx - c1 + 1
+ yc = wy - l1 + 1
+ apmaxsq = (aperts[naperts] + 0.5) ** 2
+
+ # Clear out the accumulaters
+ call aclrd (sums, naperts)
+ call aclrd (areas, naperts)
+
+ # Loop over the pixels.
+ do j = l1, l2 {
+ buf = imgs2r (im, c1, c2, j, j)
+ if (buf == EOF) {
+ call sfree (sp)
+ return
+ }
+ yindex = j - l1 + 1
+ dy2 = (yindex - yc) ** 2
+ do i = 1, nx {
+ r2 = (i - xc) ** 2 + dy2
+ if (r2 > apmaxsq)
+ next
+ prof = max (exp (-r2 / sigsq), 0.0)
+ if (prof <= 0.0)
+ next
+ pixval = Memr[buf+i-1]
+ var = max (0.0, pixval)
+ var = pixval / gain + varsky
+ if (var <= 0.0)
+ next
+ weight = prof / var
+ r = sqrt (r2) - 0.5
+ kindex = naperts + 1
+ do k = 1, naperts {
+ if (r > aperts[k])
+ next
+ kindex = min (k, kindex)
+ fctn = max (0.0, min (1.0, aperts[k] - r))
+ sums[k] = sums[k] + weight * fctn * pixval
+ areas[k] = areas[k] + weight * fctn
+ Memd[sump+k-1] = Memd[sump+k-1] + prof
+ Memd[sumpw+k-1] = Memd[sumpw+k-1] + weight * prof
+ }
+ if (kindex < minapert) {
+ if (pixval < datamin || pixval > datamax)
+ minapert = kindex
+ }
+ }
+ }
+
+ # Normalize.
+ do k = 1, naperts {
+ if (Memd[sumpw+k-1] <= 0.0d0)
+ norm = 0.0d0
+ else
+ norm = Memd[sump+k-1] / Memd[sumpw+k-1]
+ sums[k] = sums[k] * norm
+ areas[k] = areas[k] * norm
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/wphot/apgwppars.x b/noao/digiphot/apphot/wphot/apgwppars.x
new file mode 100644
index 00000000..91383169
--- /dev/null
+++ b/noao/digiphot/apphot/wphot/apgwppars.x
@@ -0,0 +1,35 @@
+include "../lib/display.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+
+# AP_GWPPARS -- Procedure to fetch the phot task parameters.
+
+procedure ap_gwppars (ap)
+
+pointer ap # pointer to apphot structure
+
+bool clgetb()
+int btoi()
+
+begin
+ # Initialize the photometry structure.
+ call appinit (ap, AP_CENTROID1D, 2.5, AP_MODE, 10.0, 10.0, 3.0, 1,
+ AP_PWCONSTANT, 2.0, AP_NPOISSON)
+
+ # Get the data dependent parameters.
+ call ap_gdapars (ap)
+
+ # Get the centering parameters.
+ call ap_gcepars (ap)
+
+ # Get the sky fitting parameters.
+ call ap_gsapars (ap)
+
+ # Get the photometry parameters.
+ call ap_gwhpars (ap)
+
+ # Set the radplot parameters.
+ call apseti (ap, RADPLOTS, btoi (clgetb ("radplots")))
+end
diff --git a/noao/digiphot/apphot/wphot/aptmeasure.x b/noao/digiphot/apphot/wphot/aptmeasure.x
new file mode 100644
index 00000000..8ba7b650
--- /dev/null
+++ b/noao/digiphot/apphot/wphot/aptmeasure.x
@@ -0,0 +1,192 @@
+# AP_TMEASURE -- Procedure to measure the fluxes and effective areas of a set of
+# apertures assuming a conical weighting function.
+
+procedure ap_tmeasure (im, wx, wy, c1, c2, l1, l2, aperts, sums, areas,
+ naperts, fwhmpsf, gain, varsky)
+
+pointer im # pointer to image
+real wx, wy # center of subraster
+int c1, c2 # column limits
+int l1, l2 # line limits
+real aperts[ARB] # array of apertures
+double sums[ARB] # array of sums
+double areas[ARB] # aperture areas
+int naperts # number of apertures
+real fwhmpsf # width of the profile
+real gain # the image gain
+real varsky # the sky variance
+
+int i, j, k, yindex, nx
+double fctn, weight, norm
+pointer buf, sp, sump, sumpw
+real xc, yc, apmaxsq, dy2, r2, r, pixval, prof, var
+pointer imgs2r()
+
+begin
+ # Initialize.
+ call smark (sp)
+ call salloc (sump, naperts, TY_DOUBLE)
+ call salloc (sumpw, naperts, TY_DOUBLE)
+ call aclrd (Memd[sump], naperts)
+ call aclrd (Memd[sumpw], naperts)
+
+ # Set up some array boundary parameters.
+ nx = c2 - c1 + 1
+ xc = wx - c1 + 1
+ yc = wy - l1 + 1
+ apmaxsq = (aperts[naperts] + 0.5) ** 2
+
+ # Clear out the accumulaters
+ call aclrd (sums, naperts)
+ call aclrd (areas, naperts)
+
+ # Loop over the pixels.
+ do j = l1, l2 {
+ buf = imgs2r (im, c1, c2, j, j)
+ if (buf == NULL) {
+ call sfree (sp)
+ return
+ }
+ yindex = j - l1 + 1
+ dy2 = (yindex - yc) ** 2
+ do i = 1, nx {
+ r2 = (i - xc) ** 2 + dy2
+ if (r2 > apmaxsq)
+ next
+ r = sqrt (r2)
+ prof = max (1.0 - r / fwhmpsf, 0.0)
+ if (prof <= 0.0)
+ next
+ pixval = Memr[buf+i-1]
+ var = max (0.0, pixval)
+ var = var / gain + varsky
+ if (var <= 0.0)
+ next
+ weight = prof / var
+ r = r - 0.5
+ do k = 1, naperts {
+ if (r > aperts[k])
+ next
+ fctn = max (0.0, min (1.0, aperts[k] - r))
+ Memd[sump+k-1] = Memd[sump+k-1] + prof
+ Memd[sumpw+k-1] = Memd[sumpw+k-1] + prof * weight
+ sums[k] = sums[k] + weight * fctn * pixval
+ areas[k] = areas[k] + weight * fctn
+ }
+ }
+ }
+
+ # Normalize.
+ do k = 1, naperts {
+ if (Memd[sumpw+k-1] <= 0.0d0)
+ norm = 0.0d0
+ else
+ norm = Memd[sump+k-1] / Memd[sumpw+k-1]
+ sums[k] = sums[k] * norm
+ areas[k] = areas[k] * norm
+ }
+
+ call sfree (sp)
+end
+
+
+# AP_BTMEASURE -- Procedure to measure the fluxes and effective areas of a
+# set of apertures assuming a conical weighting function.
+
+procedure ap_btmeasure (im, wx, wy, c1, c2, l1, l2, datamin, datamax,
+ aperts, sums, areas, naperts, minapert, fwhmpsf, gain, varsky)
+
+pointer im # pointer to image
+real wx, wy # center of subraster
+int c1, c2 # column limits
+int l1, l2 # line limits
+real datamin # minimum good data value
+real datamax # maximum good data value
+real aperts[ARB] # array of apertures
+double sums[ARB] # array of sums
+double areas[ARB] # aperture areas
+int naperts # number of apertures
+int minapert # minimum aperture
+real fwhmpsf # width of the profile
+real gain # the image gain
+real varsky # the sky variance
+
+int i, j, k, yindex, kindex, nx
+double fctn, weight, norm
+pointer buf, sp, sump, sumpw
+real xc, yc, apmaxsq, dy2, r2, r, pixval, prof, var
+pointer imgs2r()
+
+begin
+ # Initialize.
+ call smark (sp)
+ call salloc (sump, naperts, TY_DOUBLE)
+ call salloc (sumpw, naperts, TY_DOUBLE)
+ call aclrd (Memd[sump], naperts)
+ call aclrd (Memd[sumpw], naperts)
+ minapert = naperts + 1
+
+ # Set up some array boundary parameters.
+ nx = c2 - c1 + 1
+ xc = wx - c1 + 1
+ yc = wy - l1 + 1
+ apmaxsq = (aperts[naperts] + 0.5) ** 2
+
+ # Clear out the accumulaters
+ call aclrd (sums, naperts)
+ call aclrd (areas, naperts)
+
+ # Loop over the pixels.
+ do j = l1, l2 {
+ buf = imgs2r (im, c1, c2, j, j)
+ if (buf == NULL) {
+ call sfree (sp)
+ return
+ }
+ yindex = j - l1 + 1
+ dy2 = (yindex - yc) ** 2
+ do i = 1, nx {
+ r2 = (i - xc) ** 2 + dy2
+ if (r2 > apmaxsq)
+ next
+ r = sqrt (r2)
+ prof = max (1.0 - r / fwhmpsf, 0.0)
+ if (prof <= 0.0)
+ next
+ pixval = Memr[buf+i-1]
+ var = max (0.0, pixval)
+ var = var / gain + varsky
+ if (var <= 0.0)
+ next
+ weight = prof / var
+ r = r - 0.5
+ kindex = naperts + 1
+ do k = 1, naperts {
+ if (r > aperts[k])
+ next
+ kindex = min (k, kindex)
+ fctn = max (0.0, min (1.0, aperts[k] - r))
+ Memd[sump+k-1] = Memd[sump+k-1] + prof
+ Memd[sumpw+k-1] = Memd[sumpw+k-1] + prof * weight
+ sums[k] = sums[k] + weight * fctn * pixval
+ areas[k] = areas[k] + weight * fctn
+ }
+ if (kindex < minapert) {
+ if (pixval < datamin || pixval > datamax)
+ minapert = kindex
+ }
+ }
+ }
+
+ # Normalize.
+ do k = 1, naperts {
+ if (Memd[sumpw+k-1] <= 0.0d0)
+ norm = 0.0d0
+ else
+ norm = Memd[sump+k-1] / Memd[sumpw+k-1]
+ sums[k] = sums[k] * norm
+ areas[k] = areas[k] * norm
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/wphot/apwconfirm.x b/noao/digiphot/apphot/wphot/apwconfirm.x
new file mode 100644
index 00000000..53222388
--- /dev/null
+++ b/noao/digiphot/apphot/wphot/apwconfirm.x
@@ -0,0 +1,110 @@
+include "../lib/apphot.h"
+include "../lib/noise.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+include "../lib/phot.h"
+
+# AP_WCONFIRM -- Procedure to confirm the critical phot parameters.
+
+procedure ap_wconfirm (ap, out, stid)
+
+pointer ap # pointer to the apphot structure
+int out # pointer to the output file descriptor
+int stid # output file sequence number
+
+pointer sp, cstr, sstr, pwstr, aperts
+real fwhmpsf, capert, annulus, dannulus, skysigma
+real datamin, datamax
+int apstati()
+real apstatr(), ap_vfwhmpsf(), ap_vcapert(), ap_vsigma()
+real ap_vannulus(), ap_vdannulus(), ap_vdatamin(), ap_vdatamax()
+
+begin
+ call smark (sp)
+ call salloc (cstr, SZ_FNAME, TY_CHAR)
+ call salloc (sstr, SZ_FNAME, TY_CHAR)
+ call salloc (pwstr, SZ_FNAME, TY_CHAR)
+ call salloc (aperts, SZ_LINE, TY_CHAR)
+
+ call printf ("\n")
+
+ # Confirm the centering algorithm.
+ call ap_vcstring (ap, Memc[cstr], SZ_FNAME)
+
+ if (apstati (ap, CENTERFUNCTION) != AP_NONE) {
+
+ # Confirm the fwhmpsf.
+ if (apstati (ap, CENTERFUNCTION) != AP_CENTROID1D)
+ fwhmpsf = ap_vfwhmpsf (ap)
+ else
+ fwhmpsf = apstatr (ap, FWHMPSF)
+
+ # Confirm the centering box.
+ capert = 2.0 * ap_vcapert (ap)
+
+ } else {
+
+ fwhmpsf = apstatr (ap, FWHMPSF)
+ capert = 2.0 * apstatr (ap, CAPERT)
+ }
+
+ # Confirm the sky fitting algorithm.
+ call ap_vsstring (ap, Memc[sstr], SZ_FNAME)
+
+ if (apstati (ap, SKYFUNCTION) != AP_CONSTANT &&
+ apstati (ap, SKYFUNCTION) != AP_SKYFILE) {
+
+ # Confirm the sky annulus parameter.
+ annulus = ap_vannulus (ap)
+
+ # Confirm the width of the sky annulus.
+ dannulus = ap_vdannulus (ap)
+
+ } else {
+ annulus = apstatr (ap, ANNULUS)
+ dannulus = apstatr (ap, DANNULUS)
+ }
+
+ # Confirm the sky sigma parameter.
+ skysigma = ap_vsigma (ap)
+
+ # Confirm the weighting scheme algorithm.
+ call ap_vpwstring (ap, Memc[pwstr], SZ_FNAME)
+
+ # Confirm the aperture radii parameter.
+ call ap_vaperts (ap, Memc[aperts], SZ_LINE)
+
+ # Verify the datamin and datamax parameters.
+ datamin = ap_vdatamin (ap)
+ datamax = ap_vdatamax (ap)
+
+ call printf ("\n")
+
+ # Update the database file.
+ if (out != NULL && stid > 1) {
+ call ap_sparam (out, KY_CSTRING, Memc[cstr], UN_CALGORITHM,
+ "centering algorithm")
+ call ap_rparam (out, KY_FWHMPSF, fwhmpsf, UN_ASCALEUNIT,
+ "full width half maximum of the psf")
+ call ap_rparam (out, KY_CAPERT, capert, UN_CSCALEUNIT,
+ "centering box width")
+ call ap_sparam (out, KY_SSTRING, Memc[sstr], UN_SALGORITHM,
+ "sky fitting algorithm")
+ call ap_rparam (out, KY_ANNULUS, annulus, UN_SSCALEUNIT,
+ "inner radius of the sky annulus")
+ call ap_rparam (out, KY_DANNULUS, dannulus, UN_SSCALEUNIT,
+ "width of the sky annulus")
+ call ap_rparam (out, KY_SKYSIGMA, skysigma, UN_NCOUNTS,
+ "standard deviation of 1 sky pixel")
+ call ap_sparam (out, KY_PWSTRING, Memc[pwstr], UN_PMODEL,
+ "photometric weighting function")
+ call ap_sparam (out, KY_APERTS, Memc[aperts], UN_PSCALEUNIT,
+ "list of apertures")
+ call ap_rparam (out, KY_DATAMIN, datamin, UN_ACOUNTS,
+ "minimum good data value")
+ call ap_rparam (out, KY_DATAMAX, datamax, UN_ACOUNTS,
+ "maximum good data value")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/wphot/apwmag.x b/noao/digiphot/apphot/wphot/apwmag.x
new file mode 100644
index 00000000..0818bf3f
--- /dev/null
+++ b/noao/digiphot/apphot/wphot/apwmag.x
@@ -0,0 +1,157 @@
+include <mach.h>
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/noisedef.h"
+include "../lib/photdef.h"
+include "../lib/phot.h"
+
+define CONVERSION 2.772588
+
+# AP_WMAG -- Procedure to compute the magnitudes inside a set of apertures for
+# a single of object.
+
+int procedure ap_wmag (ap, im, wx, wy, positive, skyval, skysig, nsky)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the IRAF image
+real wx, wy # object coordinates
+int positive # emission or absorption features
+real skyval # sky value
+real skysig # sky sigma
+int nsky # number of sky pixels
+
+int c1, c2, l1, l2, ier, nap
+pointer sp, nse, phot, temp
+real datamin, datamax, zmag, wsigsq, wvarsky
+int apmagbuf()
+
+begin
+ # Initalize.
+ phot = AP_PPHOT(ap)
+ nse = AP_NOISE(ap)
+ AP_PXCUR(phot) = wx
+ AP_PYCUR(phot) = wy
+ if (IS_INDEFR(wx) || IS_INDEFR(wy)) {
+ AP_OPXCUR(phot) = INDEFR
+ AP_OPYCUR(phot) = INDEFR
+ } else {
+ switch (AP_WCSOUT(ap)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (ap, wx, wy, AP_OPXCUR(phot), AP_OPYCUR(phot), 1)
+ case WCS_TV:
+ call ap_ltov (im, wx, wy, AP_OPXCUR(phot), AP_OPYCUR(phot), 1)
+ default:
+ AP_OPXCUR(phot) = wx
+ AP_OPYCUR(phot) = wy
+ }
+ }
+ call amovkd (0.0d0, Memd[AP_SUMS(phot)], AP_NAPERTS(phot))
+ call amovkd (0.0d0, Memd[AP_AREA(phot)], AP_NAPERTS(phot))
+ call amovkr (INDEFR, Memr[AP_MAGS(phot)], AP_NAPERTS(phot))
+ call amovkr (INDEFR, Memr[AP_MAGERRS(phot)], AP_NAPERTS(phot))
+
+ # Make sure the center is defined.
+ if (IS_INDEFR(wx) || IS_INDEFR(wy))
+ return (AP_APERT_NOAPERT)
+
+ # Fetch the aperture pixels.
+ ier = apmagbuf (ap, im, wx, wy, c1, c2, l1, l2)
+ if (ier == AP_APERT_NOAPERT)
+ return (AP_APERT_NOAPERT)
+
+ call smark (sp)
+ call salloc (temp, AP_NAPERTS(phot), TY_REAL)
+
+ # Compute the min and max.
+ if (IS_INDEFR(AP_DATAMIN(ap)))
+ datamin = -MAX_REAL
+ else
+ datamin = AP_DATAMIN(ap)
+ if (IS_INDEFR(AP_DATAMAX(ap)))
+ datamax = MAX_REAL
+ else
+ datamax = AP_DATAMAX(ap)
+
+ # Do photometry for all the apertures.
+ AP_NMINAP(phot) = AP_NMAXAP(phot) + 1
+ call amulkr (Memr[AP_APERTS(phot)], AP_SCALE(ap), Memr[temp],
+ AP_NAPERTS(phot))
+
+ switch (AP_PWEIGHTS(phot)) {
+ case AP_PWCONSTANT:
+ if (IS_INDEFR(AP_DATAMIN(ap)) && IS_INDEFR(AP_DATAMAX(ap)))
+ call apmeasure (im, wx, wy, c1, c2, l1, l2, Memr[temp],
+ Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)], AP_NMAXAP(phot))
+ else
+ call apbmeasure (im, wx, wy, c1, c2, l1, l2, datamin,
+ datamax, Memr[temp], Memd[AP_SUMS(phot)],
+ Memd[AP_AREA(phot)], AP_NMAXAP(phot), AP_NMINAP(phot))
+ case AP_PWCONE:
+ wsigsq = AP_FWHMPSF(ap) * AP_SCALE(ap)
+ wvarsky = (AP_READNOISE(nse) / AP_EPADU(nse)) ** 2
+ if (IS_INDEFR(AP_DATAMIN(ap)) && IS_INDEFR(AP_DATAMAX(ap)))
+ call ap_tmeasure (im, wx, wy, c1, c2, l1, l2, Memr[temp],
+ Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)], AP_NMAXAP(phot),
+ wsigsq, AP_EPADU(nse), wvarsky)
+ else
+ call ap_btmeasure (im, wx, wy, c1, c2, l1, l2, datamin,
+ datamax, Memr[temp], Memd[AP_SUMS(phot)],
+ Memd[AP_AREA(phot)], AP_NMAXAP(phot), AP_NMINAP(phot),
+ wsigsq, AP_EPADU(nse), wvarsky)
+ case AP_PWGAUSS:
+ wsigsq = (AP_FWHMPSF(ap) * AP_SCALE(ap)) ** 2 / CONVERSION
+ wvarsky = (AP_READNOISE(nse) / AP_EPADU(nse)) ** 2
+ if (IS_INDEFR(AP_DATAMIN(ap)) && IS_INDEFR(AP_DATAMAX(ap)))
+ call ap_gmeasure (im, wx, wy, c1, c2, l1, l2, Memr[temp],
+ Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)], AP_NMAXAP(phot),
+ wsigsq, AP_EPADU(nse), wvarsky)
+ else
+ call ap_bgmeasure (im, wx, wy, c1, c2, l1, l2,
+ datamin, datamax, Memr[temp], Memd[AP_SUMS(phot)],
+ Memd[AP_AREA(phot)], AP_NMAXAP(phot), AP_NMINAP(phot),
+ wsigsq, AP_EPADU(nse), wvarsky)
+ default:
+ if (IS_INDEFR(AP_DATAMIN(ap)) && IS_INDEFR(AP_DATAMAX(ap)))
+ call apmeasure (im, wx, wy, c1, c2, l1, l2, Memr[temp],
+ Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)], AP_NMAXAP(phot))
+ else
+ call apbmeasure (im, wx, wy, c1, c2, l1, l2, datamin,
+ datamax, Memr[temp], Memd[AP_SUMS(phot)],
+ Memd[AP_AREA(phot)], AP_NMAXAP(phot), AP_NMINAP(phot))
+ }
+
+ # Make sure that the sky value has been defined.
+ if (IS_INDEFR(skyval))
+ ier = AP_APERT_NOSKYMODE
+
+ else {
+
+ # Check for bad pixels.
+ if ((ier == AP_OK) && (AP_NMINAP(phot) <= AP_NMAXAP(phot)))
+ ier = AP_APERT_BADDATA
+
+ nap = min (AP_NMINAP(phot) - 1, AP_NMAXAP(phot))
+
+ # Compute the magnitudes and errors.
+ if (positive == YES)
+ call apcopmags (Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)],
+ Memr[AP_MAGS(phot)], Memr[AP_MAGERRS(phot)], nap, skyval,
+ skysig, nsky, AP_ZMAG(phot), AP_NOISEFUNCTION(nse),
+ AP_EPADU(nse))
+ else
+ call apconmags (Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)],
+ Memr[AP_MAGS(phot)], Memr[AP_MAGERRS(phot)], nap, skyval,
+ skysig, nsky, AP_ZMAG(phot), AP_NOISEFUNCTION(nse),
+ AP_EPADU(nse), AP_READNOISE(nse))
+
+ # Compute correction for itime.
+ zmag = 2.5 * log10 (AP_ITIME(ap))
+ call aaddkr (Memr[AP_MAGS(phot)], zmag, Memr[AP_MAGS(phot)], nap)
+ }
+
+ call sfree (sp)
+ if (ier != AP_OK)
+ return (ier)
+ else
+ return (AP_OK)
+end
diff --git a/noao/digiphot/apphot/wphot/apwpars.x b/noao/digiphot/apphot/wphot/apwpars.x
new file mode 100644
index 00000000..88406a8f
--- /dev/null
+++ b/noao/digiphot/apphot/wphot/apwpars.x
@@ -0,0 +1,27 @@
+include "../lib/display.h"
+
+# AP_WPARS -- Procedure to write out the wphot task parameters.
+
+procedure ap_wpars (ap)
+
+pointer ap # pointer to apphot structure
+
+bool itob()
+int apstati()
+
+begin
+ # Write out the data dependent parameters.
+ call ap_dapars (ap)
+
+ # Write the centering parameters.
+ call ap_cepars (ap)
+
+ # Write out the sky fitting parameters.
+ call ap_sapars (ap)
+
+ # Write out the photometry parameters.
+ call ap_phpars (ap)
+
+ # Set the radplots parameter.
+ call clputb ("radplots", itob (apstati (ap, RADPLOTS)))
+end
diff --git a/noao/digiphot/apphot/wphot/apwpcolon.x b/noao/digiphot/apphot/wphot/apwpcolon.x
new file mode 100644
index 00000000..6f6e1f5c
--- /dev/null
+++ b/noao/digiphot/apphot/wphot/apwpcolon.x
@@ -0,0 +1,157 @@
+include <gset.h>
+include "../lib/apphot.h"
+include "../lib/fitsky.h"
+include "../lib/center.h"
+include "../lib/phot.h"
+include "../lib/display.h"
+include "../lib/noise.h"
+
+# AP_WPCOLON -- Process wphot colon commands.
+
+procedure ap_wpcolon (ap, im, cl, out, stid, ltid, cmdstr, newimage,
+ newcenterbuf, newcenter, newskybuf, newsky, newmagbuf, newmag)
+
+pointer ap # pointer to the apphot structure
+pointer im # pointer to the iraf image
+int cl # coord file descriptor
+int out # output file descriptor
+int stid # output file sequence number
+int ltid # coord file sequence number
+char cmdstr[ARB] # command string
+int newimage # new image ?
+int newcenterbuf, newcenter # new center buffer ? new center fit ?
+int newskybuf, newsky # new sky buffer ? new sky fit ?
+int newmagbuf, newmag # new aperture buffer ? new fit ?
+
+pointer sp, incmd, outcmd
+int strdic()
+
+begin
+ # Get the command.
+ call smark (sp)
+ call salloc (incmd, SZ_LINE, TY_CHAR)
+ call salloc (outcmd, SZ_LINE, TY_CHAR)
+
+ call sscan (cmdstr)
+ call gargwrd (Memc[incmd], SZ_LINE)
+ if (Memc[incmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, CCMDS) != 0)
+ call apccolon (ap, out, stid, cmdstr, newcenterbuf, newcenter)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, SCMDS) != 0)
+ call apscolon (ap, out, stid, cmdstr, newskybuf, newsky)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, PCMDS) != 0)
+ call ap_wmagcolon (ap, out, stid, cmdstr, newmagbuf, newmag)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, APCMDS) != 0)
+ call ap_apcolon (ap, im, cl, out, stid, ltid, cmdstr, newimage,
+ newcenterbuf, newcenter, newskybuf, newsky, newmagbuf, newmag)
+ else if (strdic (Memc[incmd], Memc[outcmd], SZ_LINE, NCMDS) != 0)
+ call ap_nscolon (ap, im, out, stid, cmdstr, newcenterbuf,
+ newcenter, newskybuf, newsky, newmagbuf, newmag)
+ else
+ call ap_himcolon (ap, cmdstr)
+
+ call sfree (sp)
+end
+
+
+# AP_WMAGCOLON -- Procedure to display and edit the photometry parameters.
+
+procedure ap_wmagcolon (ap, out, stid, cmdstr, newmagbuf, newmag)
+
+pointer ap # pointer to apphot structure
+int out # output file descriptor
+int stid # output number
+char cmdstr[ARB] # command string
+int newmagbuf # new aperture buffers
+int newmag # compute new magnitudes
+
+bool bval
+int ncmd, stat
+pointer sp, cmd
+real rval
+bool itob()
+int btoi(), strdic(), nscan(), apstati()
+real apstatr()
+
+begin
+ # Get the command.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, PCMDS)
+ switch (ncmd) {
+ case PCMD_APERTURES:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, APERTS, Memc[cmd], SZ_LINE)
+ call printf ("%s = %s %s\n")
+ call pargstr (KY_APERTS)
+ call pargstr (Memc[cmd])
+ call pargstr (UN_PSCALEUNIT)
+ } else {
+ call apsets (ap, APERTS, Memc[cmd])
+ if (stid > 1)
+ call ap_sparam (out, KY_APERTS, Memc[cmd], UN_PSCALEUNIT,
+ "list of aperture radii")
+ newmag = YES
+ newmagbuf = YES
+ }
+ case PCMD_ZMAG:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (KY_ZMAG)
+ call pargr (apstatr (ap, ZMAG))
+ } else {
+ call apsetr (ap, ZMAG, rval)
+ if (stid > 1)
+ call ap_rparam (out, KY_ZMAG, rval, UN_PZMAG,
+ "zero point of magnitude scale")
+ newmag = YES
+ }
+ case PCMD_MKAPERT:
+ call gargb (bval)
+ if (nscan () == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (KY_MKAPERT)
+ call pargb (itob (apstati (ap, MKAPERT)))
+ } else {
+ call apseti (ap, MKAPERT, btoi (bval))
+ }
+ case PCMD_WEIGHTING:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call apstats (ap, PWSTRING, Memc[cmd], SZ_LINE)
+ call printf ("%s = %s\n")
+ call pargstr (KY_PWSTRING)
+ call pargstr (Memc[cmd])
+ } else {
+ stat = strdic (Memc[cmd], Memc[cmd], SZ_LINE, PWFUNCS)
+ if (stat > 0) {
+ call apseti (ap, PWEIGHTS, stat)
+ call apsets (ap, PWSTRING, Memc[cmd])
+ if (stid > 1)
+ call ap_sparam (out, KY_PWSTRING, Memc[cmd],
+ UN_PMODEL, "photometric weighting model")
+ newmagbuf = YES
+ newmag = YES
+ }
+ }
+ default:
+ call printf ("Unknown or ambiguous colon command\7\n")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/wphot/apwphot.x b/noao/digiphot/apphot/wphot/apwphot.x
new file mode 100644
index 00000000..07849c0e
--- /dev/null
+++ b/noao/digiphot/apphot/wphot/apwphot.x
@@ -0,0 +1,509 @@
+include <ctype.h>
+include <gset.h>
+include <imhdr.h>
+include "../lib/phot.h"
+include "../lib/apphot.h"
+include "../lib/display.h"
+include "../lib/center.h"
+include "../lib/fitsky.h"
+
+define HELPFILE "apphot$wphot/wphot.key"
+
+# APWPHOT -- Procedure to compute magnitudes for a list of objects
+
+int procedure ap_wphot (ap, im, cl, sd, gd, mgd, id, out, stid, interactive,
+ cache)
+
+pointer ap # pointer to apphot structure
+pointer im # pointer to IRAF image
+int cl # starlist file descriptor
+int sd # the sky file descriptor
+pointer gd # pointer to graphcis descriptor
+pointer mgd # pointer to graphics metacode file
+pointer id # pointer to image display stream
+int out # output file descriptor
+int stid # output file sequence number
+int interactive # interactive mode
+int cache # cache the input image pixels
+
+real wx, wy, xlist, ylist
+pointer sp, cmd
+int wcs, key, ltid, newlist, req_size, old_size, buf_size, memstat
+int newimage, newskybuf, newsky, newcenterbuf, newcenter, newmagbuf, newmag
+int colonkey, prev_num, req_num, ip, oid
+int cier, sier, pier
+
+real apstatr()
+int clgcur(), apfitsky(), aprefitsky(), apfitcenter(), aprefitcenter()
+int ap_wmag(), ap_wremag(), apgscur(), ctoi(), apstati(), apgqverify()
+int apgtverify(), apnew(), ap_avsky(), ap_memstat(), sizeof()
+bool fp_equalr()
+
+define endswitch_ 99
+
+begin
+ # Initialize.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Initialize the cursor command.
+ key = ' '
+ Memc[cmd] = EOS
+
+ # Initialize the fitting parameters.
+ newimage = NO
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ cier = AP_OK; sier = AP_OK; pier = AP_OK
+
+ # Initialize the sequence numbering.
+ newlist = NO
+ ltid = 0
+
+ # Loop over the coordinate file.
+ while (clgcur ("icommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+
+ # Store the current cursor coordinates.
+ call ap_vtol (im, wx, wy, wx, wy, 1)
+ call apsetr (ap, CWX, wx)
+ call apsetr (ap, CWY, wy)
+
+ # Test to see if the cursor moved.
+ if (apnew (ap, wx, wy, xlist, ylist, newlist) == YES) {
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ }
+
+ # Store previous cursor coordinates.
+ call apsetr (ap, WX, apstatr (ap, CWX))
+ call apsetr (ap, WY, apstatr (ap, CWY))
+
+ # Loop over the colon keystroke commands.
+ switch (key) {
+
+ # Quit.
+ case 'q':
+ if (interactive == YES) {
+ if (apgqverify ("wphot", ap, key) == YES) {
+ call sfree (sp)
+ return (apgtverify (key))
+ }
+ } else {
+ call sfree (sp)
+ return (NO)
+ }
+
+ # Print out error messages.
+ case 'e':
+ if (interactive == YES)
+ call ap_perrors (ap, cier, sier, pier)
+
+ # Print out the help page(s).
+ case '?':
+ if ((id != NULL) && (id == gd))
+ call gpagefile (id, HELPFILE, "")
+ else if (interactive == YES)
+ call pagefile (HELPFILE, "[space=morehelp,q=quit,?=help]")
+
+ # Rewind the list.
+ case 'r':
+ if (cl != NULL) {
+ call seek (cl, BOFL)
+ ltid = 0
+ } else if (interactive == YES)
+ call printf ("No coordinate list\n")
+
+ # Get, measure next object from the list.
+ case 'm', 'n':
+
+ # No coordinate file.
+ if (cl == NULL) {
+ if (interactive == YES)
+ call printf ("No coordinate list\n")
+ goto endswitch_
+
+ }
+
+ # Need to rewind coordinate list.
+ prev_num = ltid
+ req_num = ltid + 1
+ if (apgscur (cl, id, xlist, ylist, prev_num, req_num,
+ ltid) == EOF) {
+ if (interactive == YES)
+ call printf (
+ "End of coordinate list, use r key to rewind\n")
+ goto endswitch_
+ }
+
+ # Convert coordinates if necessary.
+ switch (apstati (ap, WCSIN)) {
+ case WCS_PHYSICAL, WCS_WORLD:
+ call ap_itol (ap, xlist, ylist, xlist, ylist, 1)
+ case WCS_TV:
+ call ap_vtol (im, xlist, ylist, xlist, ylist, 1)
+ default:
+ ;
+ }
+
+ # Move to next object.
+ newlist = YES
+ if (key == 'm') {
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ goto endswitch_
+ }
+
+ # Measure the object.
+ cier = apfitcenter (ap, im, xlist, ylist)
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), sd, gd)
+ pier = ap_wmag (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), apstati (ap, POSITIVE), apstatr (ap, SKY_MODE),
+ apstatr (ap, SKY_SIGMA), apstati (ap, NSKY))
+ if (id != NULL) {
+ call apmark (ap, id, apstati (ap, MKCENTER), apstati (ap,
+ MKSKY), apstati (ap, MKAPERT))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_pplot (ap, im, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qpmag (ap, cier, sier, pier)
+ if (stid == 1)
+ call ap_param (ap, out, "wphot")
+ call ap_pmag (ap, out, stid, ltid, cier, sier, pier)
+ call ap_pplot (ap, im, stid, mgd, YES)
+ stid = stid + 1
+ newcenterbuf = NO; newcenter = NO
+ newskybuf = NO; newsky = NO
+ newmagbuf = NO; newmag = NO
+
+ # Process the remainder of the list.
+ case 'l':
+ if (cl != NULL) {
+ oid = stid
+ ltid = ltid + 1
+ call ap_bwphot (ap, im, cl, sd, out, stid, ltid, gd, mgd,
+ id, YES)
+ ltid = ltid + stid - oid + 1
+ if (id != NULL) {
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ } else if (interactive == YES)
+ call printf ("No coordinate list\n")
+
+ # Process apphot colon commands.
+ case ':':
+ for (ip = 1; IS_WHITE(Memc[cmd+ip-1]); ip = ip + 1)
+ ;
+ colonkey = Memc[cmd+ip-1]
+ switch (colonkey) {
+ case 'm', 'n':
+
+ # Show/set a wphot parameter.
+ if (Memc[cmd+ip] != EOS && Memc[cmd+ip] != ' ') {
+ call ap_wpcolon (ap, im, cl, out, stid, ltid, Memc[cmd],
+ newimage, newcenterbuf, newcenter, newskybuf,
+ newsky, newmagbuf, newmag)
+ goto endswitch_
+ }
+
+ # No coordinate list.
+ if (cl == NULL) {
+ if (interactive == YES)
+ call printf ("No coordinate list\n")
+ goto endswitch_
+
+ }
+
+ # Get next object from list.
+ ip = ip + 1
+ prev_num = ltid
+ if (ctoi (Memc[cmd], ip, req_num) <= 0)
+ req_num = ltid + 1
+
+ # Fetch the next object from the list.
+ if (apgscur (cl, id, xlist, ylist, prev_num, req_num,
+ ltid) == EOF) {
+ if (interactive == YES)
+ call printf (
+ "End of coordinate list, use r key to rewind\n")
+ goto endswitch_
+
+ }
+
+ # Convert the coordinates.
+ switch (apstati (ap, WCSIN)) {
+ case WCS_PHYSICAL, WCS_WORLD:
+ call ap_itol (ap, xlist, ylist, xlist, ylist, 1)
+ case WCS_TV:
+ call ap_vtol (im, xlist, ylist, xlist, ylist, 1)
+ default:
+ ;
+ }
+
+ # Move to the next object.
+ newlist = YES
+ if (colonkey == 'm') {
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ newmagbuf = YES; newmag = YES
+ goto endswitch_
+ }
+
+ # Measure the next object.
+ cier = apfitcenter (ap, im, xlist, ylist)
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER),
+ apstatr (ap, YCENTER), sd, gd)
+ pier = ap_wmag (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), apstati (ap, POSITIVE), apstatr (ap,
+ SKY_MODE), apstatr (ap, SKY_SIGMA), apstati (ap, NSKY))
+ if (id != NULL) {
+ call apmark (ap, id, apstati (ap, MKCENTER),
+ apstati (ap, MKSKY), apstati (ap, MKAPERT))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_pplot (ap, im, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qpmag (ap, cier, sier, pier)
+ if (stid == 1)
+ call ap_param (ap, out, "wphot")
+ call ap_pmag (ap, out, stid, ltid, cier, sier, pier)
+ call ap_pplot (ap, im, stid, mgd, YES)
+ stid = stid + 1
+ newcenterbuf = NO; newcenter = NO
+ newskybuf = NO; newsky = NO
+ newmagbuf = NO; newmag = NO
+
+ # Show/set a phot parameter.
+ default:
+ call ap_wpcolon (ap, im, cl, out, stid, ltid, Memc[cmd],
+ newimage, newcenterbuf, newcenter, newskybuf, newsky,
+ newmagbuf, newmag)
+ }
+
+ # Reestablish the image viewport and window.
+ if (newimage == YES) {
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[cmd], im, 4)
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+ }
+
+ newimage = NO
+
+ # Save the current parameters in the pset files.
+ case 'w':
+ call ap_wpars (ap)
+
+ # Plot centered radial profile.
+ case 'd':
+ if (interactive == YES) {
+ call ap_qrad (ap, im, wx, wy, gd)
+ newmagbuf = YES; newmag = YES
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ }
+
+ # Setup phot parameters interactively.
+ case 'i':
+ if (interactive == YES) {
+ call ap_radsetup (ap, im, wx, wy, gd, out, stid)
+ newmagbuf = YES; newmag = YES
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+ }
+
+ # Verify critical parameters.
+ case 'v':
+ call ap_wconfirm (ap, out, stid)
+ newmagbuf = YES; newmag = YES
+ newcenterbuf = YES; newcenter = YES
+ newskybuf = YES; newsky = YES
+
+ # Fit the center around the cursor position.
+ case 'c':
+ if (newcenterbuf == YES)
+ cier = apfitcenter (ap, im, wx, wy)
+ else if (newcenter == YES)
+ cier = aprefitcenter (ap, im, cier)
+ if (id != NULL) {
+ call apmark (ap, id, apstati (ap, MKCENTER), NO, NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_cplot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qcenter (ap, cier)
+ newcenterbuf = NO; newcenter = NO
+
+ # Fit the sky around the cursor position.
+ case 't':
+ if (newskybuf == YES || ! fp_equalr (wx,
+ apstatr (ap, SXCUR)) || ! fp_equalr (wy, apstatr (ap,
+ SYCUR)))
+ sier = apfitsky (ap, im, wx, wy, sd, gd)
+ else if (newsky == YES)
+ sier = aprefitsky (ap, im, gd)
+ if (id != NULL) {
+ call apmark (ap, id, NO, apstati (ap, MKSKY), NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_splot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qspsky (ap, sier)
+ newskybuf = NO; newsky = NO
+
+ # Compute the average of several sky measurements around
+ # different cursor postions.
+ case 'a':
+ sier = ap_avsky (ap, im, stid, sd, id, gd, interactive)
+ if (interactive == YES)
+ call ap_qaspsky (ap, sier)
+ newskybuf = NO; newsky = NO
+
+ # Fit the sky around the current center position.
+ case 's':
+ if (newskybuf == YES || ! fp_equalr (apstatr (ap, XCENTER),
+ apstatr (ap, SXCUR)) || ! fp_equalr (apstatr (ap, SYCUR),
+ apstatr (ap, YCENTER)))
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER),
+ apstatr (ap, YCENTER), sd, gd)
+ else if (newsky == YES)
+ sier = aprefitsky (ap, im, gd)
+ if (id != NULL) {
+ call apmark (ap, id, NO, apstati (ap, MKSKY), NO)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_splot (ap, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qspsky (ap, sier)
+ newskybuf = NO; newsky = NO
+
+ # Compute magnitudes around the cursor position using the current
+ # sky.
+ case 'p':
+ if (newcenterbuf == YES)
+ cier = apfitcenter (ap, im, wx, wy)
+ else if (newcenter == YES)
+ cier = aprefitcenter (ap, im, cier)
+ if (newmagbuf == YES || ! fp_equalr (apstatr (ap, XCENTER),
+ apstatr (ap, PXCUR)) || ! fp_equalr (apstatr (ap,
+ PYCUR), apstatr (ap, YCENTER)))
+ pier = ap_wmag (ap, im, apstatr (ap, XCENTER),
+ apstatr (ap, YCENTER), apstati (ap, POSITIVE),
+ apstatr (ap, SKY_MODE), apstatr (ap, SKY_SIGMA),
+ apstati (ap, NSKY))
+ else
+ pier = ap_wremag (ap, im, apstati (ap, POSITIVE),
+ apstatr (ap, SKY_MODE), apstatr (ap, SKY_SIGMA),
+ apstati (ap, NSKY))
+ if (id != NULL) {
+ call apmark (ap, id, NO, NO, apstati (ap, MKAPERT))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ if (interactive == YES)
+ call ap_qpmag (ap, cier, sier, pier)
+ newcenterbuf = NO; newcenter = NO
+ newmagbuf = NO; newmag = NO
+ if (key == 'o') {
+ if (stid == 1)
+ call ap_param (ap, out, "wphot")
+ if (newlist == YES)
+ call ap_pmag (ap, out, stid, ltid, cier, sier, pier)
+ else
+ call ap_pmag (ap, out, stid, 0, cier, sier, pier)
+ call ap_pplot (ap, im, stid, mgd, YES)
+ stid = stid + 1
+ }
+
+ # Compute the center, sky, and magnitudes and save the results.
+ case 'f', ' ':
+ if (newcenterbuf == YES)
+ cier = apfitcenter (ap, im, wx, wy)
+ else if (newcenter == YES)
+ cier = aprefitcenter (ap, im, cier)
+ if (newskybuf == YES || ! fp_equalr (apstatr (ap, XCENTER),
+ apstatr (ap, SXCUR)) || ! fp_equalr (apstatr (ap, YCENTER),
+ apstatr (ap, SYCUR)))
+ sier = apfitsky (ap, im, apstatr (ap, XCENTER), apstatr (ap,
+ YCENTER), sd, gd)
+ else if (newsky == YES)
+ sier = aprefitsky (ap, im, gd)
+ if (newmagbuf == YES || ! fp_equalr (apstatr (ap, XCENTER),
+ apstatr (ap, PXCUR)) || ! fp_equalr (apstatr (ap, YCENTER),
+ apstatr (ap, PYCUR)))
+ pier = ap_wmag (ap, im, apstatr (ap, XCENTER),
+ apstatr (ap, YCENTER), apstati (ap, POSITIVE),
+ apstatr (ap, SKY_MODE), apstatr (ap, SKY_SIGMA),
+ apstati (ap, NSKY))
+ else
+ pier = ap_wremag (ap, im, apstati (ap, POSITIVE),
+ apstatr (ap, SKY_MODE), apstatr (ap, SKY_SIGMA),
+ apstati (ap, NSKY))
+
+ if (id != NULL) {
+ call apmark (ap, id, apstati (ap, MKCENTER), apstati (ap,
+ MKSKY), apstati (ap, MKAPERT))
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ call ap_pplot (ap, im, stid, gd, apstati (ap, RADPLOTS))
+ if (interactive == YES)
+ call ap_qpmag (ap, cier, sier, pier)
+
+ newcenterbuf = NO; newcenter = NO
+ newskybuf = NO; newsky = NO
+ newmagbuf = NO; newmag = NO
+
+ if (key == ' ') {
+ if (stid == 1)
+ call ap_param (ap, out, "wphot")
+ if (newlist == YES)
+ call ap_pmag (ap, out, stid, ltid, cier, sier, pier)
+ else
+ call ap_pmag (ap, out, stid, 0, cier, sier, pier)
+ call ap_pplot (ap, im, stid, mgd, YES)
+ stid = stid + 1
+ }
+
+ default:
+ call printf ("Unknown or ambiguous keystroke command\n")
+ }
+
+endswitch_
+ # Setup for the next object.
+ key = ' '
+ Memc[cmd] = EOS
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/wphot/apwremag.x b/noao/digiphot/apphot/wphot/apwremag.x
new file mode 100644
index 00000000..5f611ec8
--- /dev/null
+++ b/noao/digiphot/apphot/wphot/apwremag.x
@@ -0,0 +1,76 @@
+include <mach.h>
+include "../lib/apphotdef.h"
+include "../lib/apphot.h"
+include "../lib/noisedef.h"
+include "../lib/photdef.h"
+include "../lib/phot.h"
+
+# AP_WREMAG -- Procedure to recompute the magnitudes inside a set of apertures
+# given that the sums and effective areas have already been computed.
+
+int procedure ap_wremag (ap, im, positive, skyval, skysig, nsky)
+
+pointer ap # pointer to the apphot structure
+pointer im # the input image descriptor
+int positive # emission or absorption features
+real skyval # sky value
+real skysig # sigma of sky
+int nsky # number of sky pixels
+
+int nap
+pointer nse, phot
+real zmag
+
+begin
+ # Initalize.
+ phot = AP_PPHOT(ap)
+ nse = AP_NOISE(ap)
+ call amovkr (INDEFR, Memr[AP_MAGS(phot)], AP_NAPERTS(phot))
+ call amovkr (INDEFR, Memr[AP_MAGERRS(phot)], AP_NAPERTS(phot))
+ if (IS_INDEFR(AP_PXCUR(phot)) || IS_INDEFR(AP_PYCUR(phot))) {
+ AP_OPXCUR(phot) = AP_PXCUR(phot)
+ AP_OPYCUR(phot) = AP_PYCUR(phot)
+ } else {
+ switch (AP_WCSOUT(ap)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call ap_ltoo (ap, AP_PXCUR(phot), AP_PYCUR(phot),
+ AP_OPXCUR(phot), AP_OPYCUR(phot), 1)
+ case WCS_TV:
+ call ap_ltov (im, AP_PXCUR(phot), AP_PYCUR(phot),
+ AP_OPXCUR(phot), AP_OPYCUR(phot), 1)
+ default:
+ AP_OPXCUR(phot) = AP_PXCUR(phot)
+ AP_OPYCUR(phot) = AP_PYCUR(phot)
+ }
+ }
+
+ if (IS_INDEFR(AP_PXCUR(phot)) || IS_INDEFR(AP_PYCUR(phot)))
+ return (AP_APERT_NOAPERT)
+ if (IS_INDEFR(skyval))
+ return (AP_APERT_NOSKYMODE)
+
+ nap = min (AP_NMINAP(phot) - 1, AP_NMAXAP(phot))
+
+ # Compute the magnitudes and errors.
+ if (positive == YES)
+ call apcopmags (Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)],
+ Memr[AP_MAGS(phot)], Memr[AP_MAGERRS(phot)], nap,
+ skyval, skysig, nsky, AP_ZMAG(phot), AP_NOISEFUNCTION(nse),
+ AP_EPADU(nse))
+ else
+ call apconmags (Memd[AP_SUMS(phot)], Memd[AP_AREA(phot)],
+ Memr[AP_MAGS(phot)], Memr[AP_MAGERRS(phot)], nap,
+ skyval, skysig, nsky, AP_ZMAG(phot), AP_NOISEFUNCTION(nse),
+ AP_EPADU(nse), AP_READNOISE(nse))
+
+ # Correct for itime.
+ zmag = 2.5 * log10 (AP_ITIME(ap))
+ call aaddkr (Memr[AP_MAGS(phot)], zmag, Memr[AP_MAGS(phot)], nap)
+
+ if (AP_NMINAP(phot) <= AP_NMAXAP(phot))
+ return (AP_APERT_BADDATA)
+ else if (AP_NMAXAP(phot) < AP_NAPERTS(phot))
+ return (AP_APERT_OUTOFBOUNDS)
+ else
+ return (AP_OK)
+end
diff --git a/noao/digiphot/apphot/wphot/mkpkg b/noao/digiphot/apphot/wphot/mkpkg
new file mode 100644
index 00000000..ac69a00d
--- /dev/null
+++ b/noao/digiphot/apphot/wphot/mkpkg
@@ -0,0 +1,38 @@
+# WPHOT task
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ apbwphot.x <fset.h> ../lib/apphot.h \
+ ../lib/center.h ../lib/display.h \
+ ../lib/fitsky.h
+ apgwppars.x ../lib/center.h ../lib/fitsky.h \
+ ../lib/phot.h ../lib/display.h \
+ ../lib/noise.h
+ apwconfirm.x ../lib/apphot.h ../lib/noise.h \
+ ../lib/center.h ../lib/fitsky.h \
+ ../lib/phot.h
+ apwmag.x <mach.h> ../lib/apphotdef.h \
+ ../lib/noisedef.h ../lib/photdef.h \
+ ../lib/apphot.h ../lib/phot.h
+ apgmeasure.x
+ aptmeasure.x
+ apwpars.x ../lib/display.h
+ apwphot.x <ctype.h> <gset.h> \
+ ../lib/apphot.h ../lib/display.h \
+ ../lib/center.h ../lib/fitsky.h \
+ ../lib/phot.h <imhdr.h>
+ apwpcolon.x ../lib/noise.h ../lib/apphot.h \
+ ../lib/display.h ../lib/fitsky.h \
+ ../lib/center.h ../lib/phot.h \
+ <gset.h>
+ apwremag.x <mach.h> ../lib/apphotdef.h \
+ ../lib/noisedef.h ../lib/photdef.h \
+ ../lib/apphot.h ../lib/phot.h
+ t_wphot.x <fset.h> <gset.h> \
+ <lexnum.h> ../lib/apphot.h \
+ ../lib/fitsky.h <imhdr.h>
+ ;
diff --git a/noao/digiphot/apphot/wphot/t_wphot.x b/noao/digiphot/apphot/wphot/t_wphot.x
new file mode 100644
index 00000000..14a82a3e
--- /dev/null
+++ b/noao/digiphot/apphot/wphot/t_wphot.x
@@ -0,0 +1,339 @@
+include <fset.h>
+include <gset.h>
+include <lexnum.h>
+include <imhdr.h>
+include "../lib/apphot.h"
+include "../lib/fitsky.h"
+
+# T_WPHOT -- Procedure to measure magnitudes inside a set of apertures for a
+# list of stars in a list of images.
+
+procedure t_wphot ()
+
+pointer image # pointer to name of the image
+pointer output # pointer to output file name
+pointer coords # pointer to name of coords file
+pointer skyfile # pointer to name of file with sky values
+pointer plotfile # pointer to name of plot metacode file
+pointer graphics # pointer to graphics display device
+pointer display # pointer to display device
+int interactive # mode of use
+int cache # cache the input image pixels
+int verify # verify critical parameters
+int update # update the critical parameters
+int verbose # print messages in verbose mode
+
+pointer sp, outfname, cname, ap, im, gd, mgd, id, str
+int limlist, lclist, lolist, lslist, sid, lid, sd, out, cl, root, stat, pfd
+int imlist, clist, olist, slist, wcs, memstat, req_size, old_size, buf_size
+
+pointer immap(), gopen()
+int imtlen(), imtgetim(), clplen(), clgfil(), btoi(), apstati(), clgwrd()
+int strncmp(), strlen(), fnldir(), ap_wphot(), imtopenp(), clpopnu(), open()
+int ap_memstat(), sizeof()
+bool clgetb(), streq()
+errchk gopen
+
+begin
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (coords, SZ_FNAME, TY_CHAR)
+ call salloc (skyfile, SZ_FNAME, TY_CHAR)
+ call salloc (plotfile, SZ_FNAME, TY_CHAR)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+ call salloc (display, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (cname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Set the standard output to flush on newline.
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get the task parameters.
+ imlist = imtopenp ("image")
+ limlist = imtlen (imlist)
+ clist = clpopnu ("coords")
+ lclist = clplen (clist)
+ olist = clpopnu ("output")
+ lolist = clplen (olist)
+
+ # Check that image and coordinate list lengths match.
+ if (limlist < 1 || (lclist > 1 && lclist != limlist)) {
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+ call error (0, "Imcompatible image and coordinate list lengths")
+ }
+
+ # Check that image and output list lengths match.
+ if (lolist > 1 && lolist != limlist) {
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+ call error (0, "Imcompatible image and output list lengths")
+ }
+
+ call clgstr ("icommands.p_filename", Memc[cname], SZ_FNAME)
+ if (Memc[cname] != EOS)
+ interactive = NO
+ #else if (lclist == 0)
+ #interactive = YES
+ else
+ interactive = btoi (clgetb ("interactive"))
+ cache = btoi (clgetb ("cache"))
+ verify = btoi (clgetb ("verify"))
+ update = btoi (clgetb ("update"))
+ verbose = btoi (clgetb ("verbose"))
+
+ # Intialize the phot structure.
+ call ap_gwppars (ap)
+
+ # Confirm the algorithm parameters.
+ if (verify == YES && interactive == NO) {
+ call ap_wconfirm (ap, NULL, 1)
+ if (update == YES)
+ call ap_wpars (ap)
+ }
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_LINE, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (ap, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_LINE, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call apseti (ap, WCSOUT, wcs)
+
+ # Get the graphics and display devices.
+ call clgstr ("graphics", Memc[graphics], SZ_FNAME)
+ call clgstr ("display", Memc[display], SZ_FNAME)
+
+ # Open the plot files.
+ if (interactive == YES) {
+ if (Memc[graphics] == EOS)
+ gd = NULL
+ else {
+ iferr {
+ gd = gopen (Memc[graphics], APPEND+AW_DEFER, STDGRAPH)
+ } then {
+ call eprintf (
+ "Warning: Error opening graphics device.\n")
+ gd = NULL
+ }
+ }
+ if (Memc[display] == EOS)
+ id = NULL
+ else if (streq (Memc[graphics], Memc[display]))
+ id = gd
+ else {
+ iferr {
+ id = gopen (Memc[display], APPEND, STDIMAGE)
+ } then {
+ call eprintf (
+ "Warning: Graphics overlay not available for display device.\n")
+ id = NULL
+ }
+ }
+ } else {
+ gd = NULL
+ id = NULL
+ }
+
+ # Open the plot metacode file.
+ call clgstr ("plotfile", Memc[plotfile], SZ_FNAME)
+ if (Memc[plotfile] == EOS)
+ pfd = NULL
+ else
+ pfd = open (Memc[plotfile], APPEND, BINARY_FILE)
+ if (pfd != NULL)
+ mgd = gopen (Memc[graphics], NEW_FILE, pfd)
+ else
+ mgd = NULL
+
+ # Get the file name for the sky values.
+ if (apstati (ap, SKYFUNCTION) == AP_SKYFILE) {
+ slist = clpopnu ("skyfile")
+ lslist = clplen (slist)
+ if (limlist < 1 || (lslist > 1 && lslist != limlist)) {
+ call imtclose (imlist)
+ call clpcls (clist)
+ call clpcls (olist)
+ call clpcls (slist)
+ call error (0, "Imcompatible image and sky file list lengths")
+ }
+ } else
+ sd = NULL
+
+ # Begin looping over the image list.
+ sid = 1
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open the image and store image parameters.
+ im = immap (Memc[image], READ_ONLY, 0)
+ call apimkeys (ap, im, Memc[image])
+
+ # Set the image display viewport.
+ if ((id != NULL) && (id != gd))
+ call ap_gswv (id, Memc[image], im, 4)
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = ap_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call ap_pcache (im, INDEFI, buf_size)
+
+ # Open the coordinate file, where coords is assumed to be a simple
+ # text file in which the x and y positions are in columns 1 and 2
+ # respectively and all remaining fields are ignored.
+
+ if (lclist <= 0) {
+ cl = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (clist, Memc[coords], SZ_FNAME)
+ root = fnldir (Memc[coords], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[coords+root], 7) == 0 || root ==
+ strlen (Memc[coords])) {
+ call ap_inname (Memc[image], Memc[outfname], "coo",
+ Memc[outfname], SZ_FNAME)
+ lclist = limlist
+ cl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else if (stat != EOF) {
+ call strcpy (Memc[coords], Memc[outfname], SZ_FNAME)
+ cl = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ } else {
+ call apstats (ap, CLNAME, Memc[outfname], SZ_FNAME)
+ call seek (cl, BOF)
+ }
+ }
+ call apsets (ap, CLNAME, Memc[outfname])
+ call apfroot (Memc[outfname], Memc[str], SZ_LINE)
+ call apsets (ap, CLROOT, Memc[str])
+
+ # Open the skys file.
+ if (lslist <= 0) {
+ sd = NULL
+ call strcpy ("", Memc[skyfile], SZ_FNAME)
+ } else if (clgfil (slist, Memc[skyfile], SZ_FNAME) != EOF)
+ sd = open (Memc[skyfile], READ_ONLY, TEXT_FILE)
+ else
+ call seek (sd, BOF)
+ #call apsets (ap, SKYNAME, Memc[skyfile])
+
+ # Open the output text file, if output is "default", dir$default
+ # or a directory specification then the extension "mag" is added
+ # to the image name and a suitable version number is appended to
+ # the output name. If the output name is null then no output
+ # file is created.
+
+ if (lolist == 0) {
+ out = NULL
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ } else {
+ stat = clgfil (olist, Memc[output], SZ_FNAME)
+ root = fnldir (Memc[output], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[output+root], 7) == 0 || root ==
+ strlen (Memc[output])) {
+ call apoutname (Memc[image], Memc[outfname], "omag",
+ Memc[outfname], SZ_FNAME)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ lolist = limlist
+ } else if (stat != EOF) {
+ call strcpy (Memc[output], Memc[outfname], SZ_FNAME)
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ } else
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ }
+ call apsets (ap, OUTNAME, Memc[outfname])
+
+ # Do aperture photometry.
+ if (interactive == NO) {
+ if (Memc[cname] != EOS)
+ stat = ap_wphot (ap, im, cl, sd, NULL, mgd, NULL, out,
+ sid, NO, cache)
+ else if (cl != NULL) {
+ lid = 1
+ call ap_bwphot (ap, im, cl, sd, out, sid, lid, gd, mgd, id,
+ verbose)
+ stat = NO
+ } else
+ stat = NO
+ } else
+ stat = ap_wphot (ap, im, cl, sd, gd, mgd, id, out, sid, YES,
+ cache)
+
+ # Cleanup.
+ call imunmap (im)
+ if (cl != NULL) {
+ if (lclist > 1)
+ call close (cl)
+ }
+ if (sd != NULL) {
+ if (lslist > 1)
+ call close (sd)
+ }
+ if (out != NULL && lolist != 1) {
+ call close (out)
+ if (sid <= 1) {
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ call delete (Memc[outfname])
+ }
+ sid = 1
+ }
+
+ # Uncache memory.
+ call fixmem (old_size)
+
+ if (stat == YES)
+ break
+ }
+
+
+ # Close the coordinate, sky and output files.
+ if (cl != NULL && lclist == 1)
+ call close (cl)
+ if (sd != NULL && lslist == 1)
+ call close (sd)
+ if (out != NULL && lolist == 1) {
+ call close (out)
+ if (sid <= 1) {
+ call apstats (ap, OUTNAME, Memc[outfname], SZ_FNAME)
+ call delete (Memc[outfname])
+ }
+ }
+
+ # Close up plot files
+ if (id == gd && id != NULL)
+ call gclose (id)
+ else {
+ if (gd != NULL)
+ call gclose (gd)
+ if (id != NULL)
+ call gclose (id)
+ }
+ if (mgd != NULL)
+ call gclose (mgd)
+ if (pfd != NULL)
+ call close (pfd)
+
+ # Free the photometry structures.
+ call appfree (ap)
+
+ # Close the coord, sky and image lists.
+ call imtclose (imlist)
+ call clpcls (clist)
+ if (sd != NULL)
+ call clpcls (slist)
+ call clpcls (olist)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/apphot/wphot/wphot.key b/noao/digiphot/apphot/wphot/wphot.key
new file mode 100644
index 00000000..808bf923
--- /dev/null
+++ b/noao/digiphot/apphot/wphot/wphot.key
@@ -0,0 +1,109 @@
+ Interactive Photometry Commands
+
+? Print help
+: Colon commands
+v Verify the critical parameters
+w Store the current parameters
+d Plot radial profile of current star
+i Interactively set parameters using current star
+c Fit center of current star
+t Fit sky around cursor
+a Average sky values fit around several cursor positions
+s Fit sky around the current star
+p Do photometry for current star, using current sky
+o Do photometry for current star, using current sky, output results
+f Do photometry for current star
+spbar Do photometry for current star, output results
+m Move to next star in coordinate list
+n Do photometry for next star in coordinate list, output results
+l Do photometry for remaining stars in coordinate list, output results
+r Rewind the coordinate list
+e Print error messages
+q Exit task
+
+
+ Colon Commands
+
+:show [data/center/sky/fit] Show parameters
+:m [n] Move to next [nth] star in the coordinate list
+:n [n] Do photometry for next [nth] star in coordinate list, output results
+
+
+ Colon Parameter Editing Commands
+
+# Image and file parameters
+
+:image [string] Image name
+:coords [string] Coordinate file name
+:output [string] Output file name
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Full-width half-maximum of PSF (scale units)
+:emission [y/n] Emission features (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good pixel value (counts)
+:datamax [value] Maximum good pixel value (counts)
+
+# Noise parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per adu)
+:readnoise [value] Readout noise (electrons)
+
+# Observations parameters
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Integration time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observations (time units)
+
+# Centering algorithm parameters
+
+:calgorithm [string] Centering algorithm
+:cbox [value] Width of the centering box (scale units)
+:cthreshold [value] Centering intensity threshold (sigma)
+:cmaxiter [value] Maximum number of iterations
+:maxshift [value] Maximum center shift (scale units)
+:minsnratio [value] Minimum S/N ratio for centering
+:clean [y/n] Clean subraster before centering
+:rclean [value] Cleaning radius (scale units)
+:rclip [value] Clipping radius (scale units)
+:kclean [value] Clean K-sigma rejection limit (sigma)
+
+# Sky fitting algorithm parameters
+
+:salgorithm [string] Sky fitting algorithm
+:skyvalue [value] User supplied sky value (counts)
+:annulus [value] Inner radius of sky annulus (scale units)
+:dannulus [value] Width of sky annulus (scale units)
+:khist [value] Sky histogram extent (+/- sigma)
+:binsize [value] Resolution of sky histogram (sigma)
+:smooth [y/n] Lucy smooth the sky histogram
+:sloclip [value] Low-side clipping factor in percent
+:shiclip [value] High-side clipping factor in percent
+:smaxiter [value] Maximum number of iterations
+:snreject [value] Maximum number of rejection cycles
+:sloreject [value] Low-side pixel rejection limits (sky sigma)
+:shireject [value] High-side pixel rejection limits (sky sigma)
+:rgrow [value] Region growing radius (scale units)
+
+# Photometry parameters
+
+:weighting [string] Weighting function (constant|cone|gauss)
+:apertures [string] List of aperture radii (scale units)
+:zmag [value] Zero point of magnitude scale
+
+# Plotting and marking parameters
+
+:mkcenter [y/n] Mark computed centers on display
+:mksky [y/n] Mark the sky annuli on the display
+:mkapert [y/n] Mark apertures on the display
+:radplot [y/n] Plot radial profile of object
diff --git a/noao/digiphot/apphot/x_apphot.x b/noao/digiphot/apphot/x_apphot.x
new file mode 100644
index 00000000..33c73ed1
--- /dev/null
+++ b/noao/digiphot/apphot/x_apphot.x
@@ -0,0 +1,12 @@
+# Task statements for the apphot package
+
+task center = t_center,
+ daofind = t_daofind,
+ fitpsf = t_fitpsf,
+ fitsky = t_fitsky,
+ wphot = t_wphot,
+ phot = t_phot,
+ polymark = t_polymark,
+ polyphot = t_polyphot,
+ qphot = t_qphot,
+ radprof = t_radprof
diff --git a/noao/digiphot/daophot/README b/noao/digiphot/daophot/README
new file mode 100644
index 00000000..1ae04629
--- /dev/null
+++ b/noao/digiphot/daophot/README
@@ -0,0 +1,32 @@
+ The Daophot Photometry Package
+ ----------------------------------
+
+The daophot package contains routines which perform crowded-filed
+photometry using point spread functions fitting techniques.
+The aperture photometry package routines are used to provide initial
+estimates for the magnitudes of these objects.
+
+The daophot directory structure is listed below. The package organization
+is by task, for example the nstar subdirectory contains routines
+specific to the nstar task or by function.
+The .h files are all in lib as many of them are shared by several tasks.
+
+ |-addstar-------routines specific to the addstar task
+ |-allstar-------routines specific to the allstar task
+ |-daoedit-------routines specific to the daoedit task
+ |-daolib--------routines common to many daophot tasks
+ |-doc-----------daophot documentation
+ |-group---------routines specific to the group task
+|-daophot----|-lib-----------daophot definitions or .h files
+ |-nstar---------routines specific to the nstar task
+ |-peak----------routines specific to the peak task
+ |-psf-----------routines specific to the psf/pstselect tasks
+ |-seepsf--------routines specific to the seepsf task
+ |-select--------routines specific to the grpselect/psfmerge tasks
+ |-substar-------routines specific to the substar task
+ |-test----------directory of test data
+
+
+Lindsey Davis
+NOAO IRAF GROUP
+May 1993
diff --git a/noao/digiphot/daophot/Revisions b/noao/digiphot/daophot/Revisions
new file mode 100644
index 00000000..7e88e82c
--- /dev/null
+++ b/noao/digiphot/daophot/Revisions
@@ -0,0 +1,918 @@
+.help revisions Jan90 noao.digiphot.daophot
+.nf
+
+daophot/psf/dpfitpsf.x
+ The ":function <func>" command was not saving the new functon when
+ refitting with the 'f' keystroke. In dp_fitpsf() the parameters are
+ reinitialized and the startup function was being reused. (4/13/10, MJF)
+
+daophot/psf/dpfitpsf.x
+ An amovi() call referenced a Memr[] array that was declared as
+ int, changed to Memi[] (8/28/09, MJF)
+
+daophot/*.par
+ Minor changes for readability suggested by Jason Quinn, i.e. made
+ consistent use of space before question marks (12/23/08, MJF)
+
+daophot/lib/warning.dat
+ Added some blank lines for readability before the package menu
+ (12/11/08, MJF)
+
+=======
+V2.14.1
+=======
+
+daophot/psf/dppwselmer.x
+ PSTSELECT was showing the IMAGE param as 'name' instead of 'imagename'
+ (7/8/08)
+
+daophot/daophot.hd
+ The source directories for pstselect and allstar were wrong.
+ (5/27/08, Valdes)
+
+=======
+V2.14
+=======
+
+daophot/allstar/dpcache.x
+ Fixed some procedure calls being closed with a ']' instead of a ')'
+ (2/17/08, MJF)
+
+daophot/psf.par
+ Fixed a type in the 'pstfile' prompt (11/24/07)
+
+========
+V2.12.3
+========
+
+daophot/allstar/dpalwrite.x
+ In dl_alxaccum there are conditions where the loop skips a star which
+ are not checked in the write routines when they compute the sharp
+ parameter. When the loop is not completed the denom value is not
+ computed and defaults to zero which caused a divide by zero error
+ in computing the sharpness. (11/18/04, Valdes)
+
+daophot/daolib/invers2.x
+daophot/daolib/mkpkg
+daophot/allstar/t_allstar.x
+daophot/allstar/dpalphot.x
+daophot/allstar/dpastar.x
+daophot/allstar.par
+ Made a small change to the matrix inversion code to avoid problems with
+ very small numbers. This was done by translating the original fortran
+ version to SPP and then replacing small numbers by zero. In order to
+ allow users to reproduces earlier results or if there is a problem
+ a version parameter was added to ALLSTAR. Setting the version to 1
+ will use the old version of the inversion routine and the default of
+ 2 will use the new version. (6/18/04, Valdes)
+
+=======
+V2.12.2
+=======
+
+daophot/daoedit/dpeconfirm.x
+daophot/daoedit/dperprofile.x
+ Added some missing sfree statements to the daophot package routines.
+
+ (19/02/02, Davis)
+
+daophot/daolib/dpppcache.x
+ Added a call setting IM_BUFFRAC to 0 to the memory caching code in the
+ daophot package tasks in order to force the imio buffer to be the size of
+ the input image.
+
+daophot/substar/dprestars.x
+ There were 3 missing arguments in the dp_tptread call which cause
+ trouble for people trying to read an input exclude file in tables
+ format.
+
+ (19/09/01, Davis)
+
+daophot/psf/dppwselmer.x
+ Changed an incorrect smark call to salloc. This bug was introduced by
+ recent output file mods. Should not have been a problem in released code.
+
+ (19/09/01, Davis)
+
+daophot/psf/t_psf.x
+ Changed the type declaration for the clgwrd function from bool to int.
+ This bug was introduced by the wcs mods. Should not have been a problem
+ in realeased code.
+
+ (19/09/01, Davis)
+
+daophot/addstar/t_addstar.x
+ Modifed the addstar task to add a ".art" suffix to the output artificial
+ star coordinate files when the user supplies the output root name. This
+ avoids file and image name conflicts when the user includes the image
+ suffix, e.g. ".imh" in the output root name.
+
+ Davis, September 17, 2001
+
+daophot/
+ Modified all the apphot tasks to accept input coordinates in logical, tv,
+ physical, or world coordinates and to write the output coordinates in
+ logical, tv, or physical coordinates. One consequence of this is that
+ the apphot tasks will now work correctly off image sections in interactive
+ mode. Another is that users can work on image sections while preserving
+ the coordinate system of the entire image.
+
+ Davis, June 8, 2000
+
+daophot/
+ Modified all the daophot tasks to strip the directory information from
+ the input image and coordinate file names written to the output files,
+ to the terminal, and to the plot headers. The colon commands will still
+ read and write full image and coordinate file path names. This change
+ improves the likelyhood that the full root image name will be written
+ to the output. This root image name is used by the photometric calibration
+ code to construct images sets.
+
+ Davis, June 8, 2000
+
+daophot/mkpkg
+ Modified the make procedure to pick up user compile and link flags.
+
+ Davis, June 17, 1999
+
+daophot/daolib/dpotime.x
+ Modified the code which reads the time of observation value from the image
+ header to extract the time field from the date-obs keyword if it is
+ present.
+
+ Davis, May 11, 1999
+
+daophot/daolib/dpdate.x
+ Modified the date and time photometry file keyword encoding tasks to
+ write the date and time in the proper fits format and in units of GMT.
+ Note that GMT is deactivated in digiphotx because the necessary routine
+ is not yet in the system.
+
+ Davis, May 11, 1999
+
+
+daophot/psf/dppwrtgrp.x
+ The row number in the psf star group file writing code was not being
+ correctly initialized results in an "invalid row number error" if
+ the psf task was run with daophot.text = no.
+
+ Davis May 10, 1999
+
+daophot/psf/dpgetapert.x
+daophot/allstar/dpalwrite.x
+daophot/group/dpwrtgroup.x
+daophot/doc/daopars.hlp
+ Removed the restriction on the number of stars imposed by the maxnstars
+ parameter and in the process fixed a segmentation violation that occurred
+ when the number for stars in the files was > maxnstars. Maxnstars is
+ now used only for setting the initial buffer size.
+
+ Removed the code which writes MAXNSTARS to the output photometry files.
+
+ Davis May 8, 1999
+
+daophot/psf/t_pstselect.x
+ Added a missing imtclose statement.
+
+ Davis, May 4, 1999
+
+daophot/psf/dpfitpsf.x
+ Changed the test for the radial weighting function from wt >= 1.0 to
+ wt >= 0.999998 to avoid floating point errors (division by a very small
+ number) under Linux and possibly other systems as well.
+
+ Davis, April 19, 1999
+
+daophot/peak/dppkfit.x
+daophot/nstar/dpnstarfit.x
+daophot/allstar/dpalphot.x
+ Added a check to make sure that the predicted error computation can
+ never be <= 0.0 This can happen in rare circumstances if the model
+ prediction is exactly 0, the rdnoise is 0.0 and flaterr and proferr are
+ 0.0.
+
+ Davis, April 12, 1999
+
+daophot/daolib/dpnames.x
+ Modified the automatic input and output image and file naming code
+ to behave more gracefully in the case where the input images have
+ kernel sections and cluster indices and sizes.
+
+ Davis, January 17, 1999
+
+daophot/daolib/dpdate.x
+daophot/addstar/dpnaddstar.x
+daophot/addstar/dpalwrite.x
+daophot/group/dpwrtgroup.x
+daophot/nstar/dpntwrite.x
+daophot/peak/dppkwrite.x
+daophot/psf/dppwrtgrp.x
+ Modified the daophot output file writing routines to write the DATE
+ header keyword in the new Y2k format even though the output files
+ are not FITS files.
+
+ Davis, Dec 29, 1998
+
+daophot/allstar/t_allstar.x
+daophot/allstar/dpcache.x
+daophot/allstar/dpalinit.x
+ Modified the allstar task to ensure that all the output and scratch
+ images and scratch space are 2D even if the input image is greater than
+ 2D to avoid a non-obvious memory error.
+
+ Davis, Aug 3, 1998
+
+
+daophot/daophot.cl
+ Modified the package cl script to check whether the tables package is
+ already loaded before checking whether it is defined and then loading it.
+
+ Davis, Aug 1, 1998
+
+daophot/psf/t_psf.x
+ The psf task psf image list reading code was using the fntgfnb routine
+ instead of the imtgetim routine to read image names from the psf image list.
+ Although the code functioned correctly, if the input psf image list was
+ an @ file, a control character (^P) was being written into the PSFIMAGE
+ keyword value in the output *.psg.* and *.pst.* files. This caused an error
+ in the nstar, allstar, etc task photometry file reading code.
+
+ Davis, Apr 1, 1998
+
+daophot/addstar/t_addstar.x
+daophot/allstar/t_allstar.x
+daophot/group/t_group.x
+daophot/nstar/t_nstar.x
+daophot/nstar/t_peak.x
+daophot/psf/t_pstselect.x
+daophot/psf/t_psf.x
+daophot/substar/t_substar.x
+ Modified the addstar, allstar, group, nstar, peak, pstselect, psf,
+ and substar tasks to be able to read and write default images and files
+ from and to directories other than the current directory just as the
+ daophot tasks daofind and phot do.
+
+ Davis, Feb 14, 1998
+
+daophot/seepsf/t_seepsf.x
+daophot/seepsf/dpmkimage.x
+ Modified the seepsf task so it explicity sets the pixel type of the
+ output psf image to real to avoid a problem with stf image kernel
+ and dataless stf images.
+
+ Davis, Jan 20, 1998
+
+daophot/allstar/dpalinit.x
+ Fixed an uninitialized memory problem that was occurring on the Dec
+ ALPHA if cache=no and readnoise=0.0. This part of memory was never
+ used by the code, but was being written to a scratch image of type real,
+ which could result in an FPE if the affected memory was not a valid
+ FP number. A similar problem was fixed for the cache=yes situtation
+ awhile back.
+
+ Davis, Nov 12, 1997
+
+
+daophot/psf/dpfitpsf.x
+ Fixed a bug in the psf task that was causing the fits image kernel to
+ crash when opening a new image, but apparently did not affect the oif
+ or stf kernels in any way.
+
+ Davis, June 23, 1997
+
+daophot/daotest.cl
+ Modified the rfits calling sequence so that the code will work
+ correctly with the new version of rfits.
+
+ Davis, May 29, 1997
+
+daophot$psf/mkpkg
+daophot$psf/dprstars.x
+daophot$psf/dpspstars.x
+daophot$psf/dpispstars.x
+ The pstselect and psf tasks were not reinitializing the psf star list
+ correctly when more than one image was being processed, resulting in
+ psf stars on successive images which have the same ids as psf stars
+ in previous images being incorrectly rejected or include in the psf star
+ list.
+
+ Davis, Feb 21, 1997
+
+daophot$psf/dpmkpsf.x
+ The id number and magnitude arguments were reversed in the 'f' keystroke
+ command call to the routine dp_addstar. This should only cause trouble
+ if the psf star list need to be reread.
+
+ Davis, July 18, 1996
+
+daophot$doc/phot.hlp
+ Fixed a type in the ERRORS section of the phot help page.
+
+ Davis, April 11, 1996
+
+daophot$daolib/dpinit.x
+daophot$psf/dpfitpsf.x
+daophot$psf/dppsfutil.x
+ The psf task was not restoring the fit for the moffat25 and moffat15
+ functions correctly, in the event that they were chosen as the best
+ fitting analytic function. This was occurring because the constant
+ beta parameter was not being copied into and out of the save array
+ resulting in a totally incorrect look-up table being computed.
+
+ Davis, March 20, 1996
+
+daophot$psf/dpfitpsf.x
+ Modified the code which computes the analytic component of the psf
+ model to start from the same initial state in auto mode as it does
+ if a single function is specified. Peviously the initial state
+ in the auto case was the state computed by the previous function.
+ Because the convergence criteria have a specified tolerance, the
+ resulting computed values of the analytic component functions and the
+ look-up table elements can be slightly different in the two cases.
+
+ Davis, March 18, 1996
+
+daophot$allstar/dpcache.x
+daophot$allstar/dpalmemstar.x
+
+ Modified the malloc calls to calloc calls in the dpcache routine to
+ avoid an unititialized memory FPE error than can occur if the readout
+ noise is exactly 0. As far as I am aware this has only caused a problem
+ on the Dec Alpha, but 0 readout noise situation does occur in the
+ daophot test script. Removed an extra fixmem call from the allstar
+ cleanup routine.
+
+ Davis, February 20, 1996
+
+daophot$daolib/dpgetapert.x
+daophot$nstar/dpggroup.x
+ Fixed a bug in the code which parses the input photometry or group files.
+ If the numerical field to be extracted is adjacent to another numerical
+ field and there is no white space between them, then the number
+ extracted may be a combination of the two fields, rather than the desired
+ individual field. This is most likely to occur when the id numbers are
+ large, e.g. 10003, and the image name is a number, e.g. 8649.imh.
+
+ Davis, February 20, 1996
+
+daophot$daopars.par
+daophot$daotest.cl
+daophot$lib/daophotdef.h
+daophot$lib/nstardef.h
+daophot$daolib/dpgppars.x
+daophot$daolib/dppppars.x
+daophot$daolib/dpset.x
+daophot$daolib/dpstat.x
+daophot$daolib/dpverify.x
+daophot$group/dpgconfirm.x
+daophot$group/dpmkgroup.x
+daophot$group/dpwrtgroup.x
+daophot$nstar/dpnstarfit.x
+daophot$nstar/dpntwrite.x
+daophot$allstar/dpastar.x
+daophot$allstar/dpalwrite.x
+daophot$doc/daopars.hlp
+daophot$doc/group.hlp
+ Added a new parameter mergerad to the daopars parameter set. Mergerad
+ permits the user to control the merging process. If mergerad is 0
+ object merging is turned off altogether. If mergerad is INDEF to default
+ mergeing radius is used. Otherwise the user can set the merging radius
+ to a specific value.
+
+ Changed the name of the critoverlap parameter to critsnratio to avoid
+ user confusion over the meaning to the parameter.
+
+ Davis, February 15, 1996
+
+daophot$nstar/dpnmemstar.x
+daophot$nstar/dpnstar.x
+daophot$allstar/dpalmemstar.x
+daophot$allstar/dpalphot.x
+ Modified the nstar and allstar tasks so that they allocate less memory for
+ the fitting matrices and vectors if object recentering is turned off. This
+ can make a big difference if the the maximum group size is large.
+
+ Davis, February 14, 1996
+
+daophot$nstar/dpnstarfit.x
+ Added a singular matrix check to avoid floating point operand errors
+ in the nstar task.
+
+ Davis, January 5, 1996
+
+daophot$nstar/dpggroup.x
+ The integer code array size was not being reallocated correctly in the
+ case that the size of a group is greater the the value of the maxgroup
+ parameter, causing nstar to die with a memory allocation parameter,
+
+ Davis, January 3, 1996
+
+daophot$doc/centerpars.hlp
+ Edited the centerpars help page to include a description of the new
+ INDEF-valued cthreshold option.
+
+ Davis, Sept 29, 1995
+
+daophot$lib/psfdef.h
+daophot$psf/dpfitpsf.x
+daophot$psf/dpmempsf.x
+daophot$psf/dppsfutil.x
+daophot$psf/dprstars.x
+daophot$psf/dpispstars.x
+daophot$psf/dpspstars.x
+daophot$psf/dpmkpsf.x
+daophot$psf/dpaddstar.x
+daophot$doc/psf.hlp
+ Modifed the way the magnitude of the psf is set. If matchbyid is
+ yes (the default) the magnitude of the first psf star in the psf
+ star list if any will be used; other wise the magnitude of the first
+ psf star in the input photometry file will be used as before. This
+ should help minimize photometric drift problems derived from repeated
+ iterations.
+
+ Davis, Sept 21, 1995
+
+daophot$psf/dpdelstar.x
+daophot$psf/dpsubpsf.x
+ Added a missing mfree to the dpsubpsf routine. This was not causing
+ a problem but might in a large script.
+
+ In dpdelstar the routine dp_psubrast was being called with an input
+ output variable that was never used being set to a constant. This was
+ causing a segvio on Solaris but not on SunOS.
+
+ Davis, Aug 25, 1995
+
+daophot$seepsf/dpmkimage.x
+ Seepsf was dying with an FPE error on the Dec Alpha. This was caused
+ by an array out-of-bounds error which was not detected on the Sun
+ machines.
+
+ Davis, July 18, 1995
+
+daophot$seepsf/t_seepsf.x
+daophot$seepsf/dpmkimage.x
+ The fix made to cure the previous seepsf problem broke the code for
+ pure analytic psf images.
+
+ Davis, July 3, 1995
+
+daophot$psf/dpfitpsf.x
+ Changed the illegal construct "} until (redo == false)" to
+ "} until (! redo)". This was causing problems on the IBM/RISC6000
+ compilers but was not caught by the Sun compilers.
+
+ Davis, November 16, 1994
+
+daophot$seepsf/t_seepsf.x
+daophot$seepsf/dpmkimage.x
+ The code that was computing the default size of the output psf image
+ was incorrectly using the size of psf requested by the user (default
+ radius = 11.0 pixesl) instead of the actual size of the input psf image.
+
+ Davis, October 3, 1994
+
+daophot$daoedit/t_daoedit.x
+daophot$daoedit/dpeconfirm.x
+ Made some minor modifications to the daoedit task which change the
+ image cursor mode and graphics cursor mode interact.
+
+ Davis, June 21, 1994
+
+daophot$addstar/dpnaddstar.x
+ Corrected an error in the format string for the output file.
+
+ Davis, June 20, 1994
+
+daophot$psf.par
+daophot$lib/psfdef.h
+daophot$psf/t_psf.x
+daophot$psf/t_dprstars.x
+daophot$doc/psf.hlp
+ Added a new parameter, matchbyid, to the psf task so that stars in the
+ psf star list can be matched to stars in the input photometry file
+ by id or by position.
+
+ Davis, June 20, 1994
+
+daophot$psf/dpspstars.
+ In non-interactive mode the pstselect task was writing a minimum
+ of two stars to the output file even if the requested number of
+ psf stars was one.
+
+ Davis, June 18, 1994
+
+daophot$addstar/dpartstar.x
+daophot$addstar/dpartstar.x
+ If the nimages parameter was greater than 1 and the addimage parameter
+ was set to other than the default value, the task would terminate
+ prematurely with a "Cannot close file error" after the first output
+ image was written. The problem was caused by addstar failing to append
+ the appropriate sequence number to the output star list.
+
+ Davis, June 13, 1994
+
+daophot$allstar/dpalwrite.x
+daophot$group/dpwrtgroup.x
+daophot$nstar/dpntwrite.x
+daophot$peak/dppkwrite.x
+daophot$psf/dppwrtgrp.x
+daophot$psf/dppwselmer.x
+daophot$select/dpgwselect.x
+ Modified all the daophot package tasks which output sky values (pstselect,
+ psf, peak, group, grpselect, nstar, allstar, pfmerge) to write the
+ values with format -%15.7g like the apphot package tasks do, instead
+ of %-12.3f/%-14.3f, to avoid precision problems with images that
+ have been "flux calibrated".
+
+ Davis, May 27, 1994
+
+daophot$nstar/dpntwrite.x
+daophot$nstar/dpalwrite.x
+ Changed the output GROUPSKY parameter name in the phot files to GRPSKY
+ to avoid a name matching conflict with the GROUP column. This was causing
+ problems in reading nstar output.
+
+ Davis, May 5, 1994
+
+daophot$daopars.par
+daophot$lib/daophotdef.h
+daophot$allstar/dpaconfirm.x
+daophot$allstar/dpalphot.x
+daophot$allstar/dpalwrite.x
+daophot$daoedit/daoedit.h
+daophot$daoedit/dpecolon.x
+daophot$daolib/dpgppars.x
+daophot$daolib/dpppars.x
+daophot$daolib/dpinit.x
+daophot$daolib/dpset.x
+daophot$daolib/dpstat.x
+daophot$daolib/dpverify.x
+daophot$nstar/dpnconfirm.x
+daophot$nstar/dpnstar.x
+daophot$nstar/dpnstarfit.x
+daophot$nstar/dpntwrite.x
+daophot$doc/allstar.hlp
+daophot$doc/daopars.hlp
+daophot$doc/nstar.hlp
+ Added a new boolean parameter, groupsky, to the daopars parameter set.
+ Groupsky determines whether the sky value for each pixel used in the fit
+ is set to, the mean of ALL the individual sky values of the stars in the
+ group (groupsky = yes), or, to the mean of the individual sky values of
+ only those stars for which the pixel in question is inside the fitting
+ radius.
+
+ Davis, Dec 20, 1993
+
+daophot II installed
+ Davis, May 31, 1993
+
+ Daophot II installed.
+
+daophot$phot.par
+ Added a leading quote to the prompt string for the daophot.phot task
+ output parameter.
+
+ Davis, Mar 24, 1993
+
+daophot$daolib/dpppars.x
+ The psfrad, fitrad, and matchrad were being written to the parameter
+ set in pixel units instead of scale units when update was set to
+ yes.
+
+ Davis, Feb 16, 1993
+
+daophot$allstar/dpalinit.x
+ In crowded regions allstar would occasionally refuse to 1) fit a group
+ of bright stars or 2) fail to converge to reasonable values for a group
+ of bright stars by the time the number of iterations equaled maxiter,
+ resulting in a group of stars with very poor subtractions.
+ The problem was caused by a bug in the code which steps through the
+ stellar groups subtracting off the current best fit to produce a residuals
+ image. Occasioanally stars which should have been subtracted from the
+ residuals image were not being subtracted. Since the residuals image is
+ used to determine the relative errors and weights,
+ which in turn control the bad data rejection algorithm, allstar sometimes
+ refused to fit stars because the residuals were too big, or was unable
+ to converge to a reasonable fit. The bug is data dependent but is
+ more likely to be a problem if 1) the stellar detection threshold is low
+ 2) the fitting radius is high producing very large groups.
+
+ Davis, Dec 23, 1992
+
+daophot$allstar/dpalphot.x
+ If 1) cache=no, or cache=yes and memory allocation failed for one of the
+ three arrays scratch, weight, or data, 2) one or more the the groups has >
+ maxgroup stars, 3) regrouping was performed and 4) the position of next
+ non-regrouped group was just right, allstar could fail with an "attempt to
+ access the scratch, weight or data pixels randomly" error. This error
+ occurrs because the regrouping process could produce groups which were out
+ of y-order with with succeeding groups which had not been regrouped,
+ forcing an illegal non-sequential image access. The solution was to buffer
+ enough data to fit original large group.
+
+ Davis, Sept 16, 1992
+
+apphot$datapars.par
+apphot$centerpars.par
+apphot$doc/datapars.hlp
+apphot$doc/centerpars.hlp
+ Changed the units of the cthreshold parameter to sigma and moved it
+ to the centerpars parameter set.
+
+ Davis, July 7, 1992
+
+daophot$daophot.par
+ The verbose, verify, update, graphics, and display parameters were
+ added to the package parameters and the corresponding individual
+ task parameters were redirected there by default.
+
+ Davis, June 20, 1992
+
+daophot$daopars.par
+daophot$lib/warning.dat
+ Fixed errors in the definition of the psfrad and fitrad parameters in
+ the daopars parameter set. These parameters are now defined in units
+ of scale not pixels as before.
+
+ Fixed some bugs in the message printed by the daophot package if the
+ tables package is not present.
+
+ Davis, May 29, 1992
+
+daophot$daophot.men
+ Changed the entries for append, convert, dump, renumber, select, and
+ sort to entries for pappend, pconvert, pdump, prenumber, pselect,
+ and psort.
+
+ Davis, Feb 28, 1992
+
+daophot$psf/dpmkpsf.x
+ Added missing fset declaration to the mkpkg line for this routine.
+
+ Davis, Nov 20, 1991
+
+daophot$
+ Renamed the append, convert, dump, renumber, select, and sort tasks to
+ pappend, pconvert, pdump, prenumber, pselect, and psort.
+
+ Davis, Nov 11, 1991
+
+ *** Ran spplint on the daophot package.
+
+daophot$allstar/dpastar.x
+ The routines dp_gst, dp_gwt, and dp_gdc were being called as subroutines
+ instead of functions inside dp_astar. This was a recent change which
+ would not affect the old testphot.
+
+daophot/psf/dpcontpsf.x
+ Changed the last argument in the call to dp_map_viewport from NO to false
+ to fix a type mismatch. This could affect the old testphot.
+
+daophot/psf/dpnewpsf.x
+ Removed extra status argument from the call to dp_gaussfit. This could
+ have caused a problem in the old daophot.
+
+daophot/peak/dppkfit.x
+ Removed an extra argument from the mfree call. This would not cause a
+ problem in the old testphot.
+
+ Davis, Oct 3, 1991
+
+daophot$daophot.cl
+daophot$daophot.men
+daophot$daophot.hd
+daophot$daotest.cl
+ At the autotmatic package test task daotest to the daophot package.
+
+ Davis, Oct 3, 1991
+
+daophot$psf/dpsurfpsf.x
+ Removed non-required variables mode, xres, yres from this routine.
+
+ Davis, Oct 1, 1991
+
+daophot$test/fits3.fits
+ Added the fits test image to the daophot test subdirectory in preparation
+ for making a test script.
+
+ Added a test cursor input file for the psf task in preparation for
+ making the test script.
+
+ Davis, Aug 13, 1991
+
+daophot$daolib/dpgetapert.x
+daophot$nstar/dpggroup.x
+ Modified the i/o routines which read aperture photometry and group
+ photometry format text files in order to take account of new additions
+ to the text database routines.
+
+ Davis, Aug 13, 1991
+
+daophot$
+ 1. All the DAOPHOT tasks except PSF have been modified to accept lists of
+ input and output files.
+
+ 2. Moved the text parameter from DAOPARS to the DAOPHOT package parameter
+ file.
+
+ 3. Modified all the DAOPHOT routines so that psfrad, fitrad and matchrad
+ are defined in terms of scale.
+
+ Davis, Aug 5, 1991
+
+daophot$
+ 1. Added support for a time of observation parameter to all the appropriate
+ daophot tasks.
+
+ 2. Changed all the daophot file header parameters to be 23 characters long
+ instead of 15 characters.
+
+ 3. Modified all the daophot tasks to strip whitespace from the filter id
+ keywords and the iraf version environment variable string.
+
+ 4. Wrote an spp version of the error function routine which was originally
+ in fortran.
+
+ Davis, Aug 2, 1991
+
+daophot$allstar/
+ 1. Redid the i/o of the ALLSTAR task to make the cache=no option run in
+ a finite period of time for large images.
+
+ Davis, Jun 24, 1991
+
+daophot$group/
+ 1. Changed GROUP so that the groups are output in y order instead of in
+ order of the size of the group. This will help make i/o more efficient
+ in NSTAR.
+
+ Davis, Jun 18, 1991
+
+daophot$allstar/
+ 1. Changed the boolean arrays inside ALLSTAR to integer arrays. These
+ use the same amount of space and are probably safer.
+
+ 2. Added protection in the code for the case that the x and y position
+ of a star is INDEF or the sky value is INDEF.
+
+ 3. Changed the format of the output of the verbose option in several places
+ in the code.
+
+ Davis, Jun 17, 1991
+
+daophot$nstar/
+ 1. Changed the boolean arrays inside NSTAR to integer arrays. Thought
+ this was probably safer.
+
+ 2. Fixed a potential problem in NSTAR wherein for groups greater than
+ the maxgroup parameter in size the old_size variable was not being
+ correctly set. This would mean that some group members could get
+ truncated from the output file.
+
+ 3. Fixed a bug in verbose mode wherein stars would not be fit, their
+ magnitude would be set to INDEF, but no error message would be generated.
+ This was occurring when the new center of a star moved too close to the
+ edge of the image.
+
+ 4. Also took the opportunity to do some code cleanup.
+
+ Davis, Jun 5, 1991
+
+daophot$psf/
+ 1. Modified the PSF task so that potential psf stars are rejected if their
+ sky or magnitude values are INDEF.
+
+ 2. Added a check so that stars with INDEF valued positions are treated as
+ stars that were not found.
+
+ 3. Added a check in the code so that the same star could not be added to
+ the psf twice.
+
+ 4. Found a code construct in the dp_friends() routine that
+ could trigger an optimizer bug and removed it.
+
+ 5. Finally changed the code which deletes an empty psf image and group
+ file so that it would handle an output ST table correctly.
+
+ 6. Did some minor code cleanup.
+
+ Davis, Jun 3, 1991
+
+daophot$peak/
+ 1. Found that the main fitting task in PEAK, dp_pkfit(), was missing an
+ sfree statement. This may account for the problems with TESTPHOT on the
+ mountain. Took the opportunity afforded by this bug to do a little
+ code cleanup in peak.
+
+ 2. Had to do a couple of modifications in PSF because of the mod to the
+ fitting code in PEAK. The two tasks share code. Found an extra sfree
+ statement in the main PSF loop and removed it.
+
+ 3. Changed the size of the extractions box in PEAK from psfrad to
+ (psfrad + fitrad + 1). This removes any problems in the unlikely
+ event that the fitting radius is bigger than the psf radius.
+
+ Davis, Jun 1, 1991
+
+daophot$group/
+ Modified GROUP so that any stars with INDEF valued centers are not
+ written to the output file. Various code modifications were made
+ to clean up the logic of the task and make it more structured.
+
+ Davis, May 31, 1991
+
+daophot$peak/
+ Modified PEAK so that stars with undefined sky values don't cause a
+ floating operand error. Also modified PEAK so that any stars with
+ INDEF centers in the input file are not written to the output file.
+
+ Davis, May 30, 1991
+
+daophot$addstar/
+ Addstar was not incrementing the row numbers correctly when writing
+ the output star list if the output file was an ST table, resulting
+ in an output file that was missing some rows. The output image was being
+ computed correctly.
+
+ Davis, May 26, 1991
+
+daophot$
+ Added the PEXAMINE task to the daophot package.
+
+ Davis, May 24, 1991
+
+daophot$allstar/
+daophot$addstar/
+ Modified the peak and allstar tasks so that they were writing the
+ keyword IMAGE instead of IMNAME in the header. IMNAME was causing
+ problems for the preprocessors.
+
+ Davis, Apr 5, 1991
+
+daophot$
+daophot$psf/
+ 1. Modified the dpppars() routine in daolib to the datamin and datamax
+ in the datapars pset are updated when the daophot fitting parameters are
+ updated.
+
+ 2. Update the psf task so that the default psf image header will hold more
+ than 22 stars. The current default will be three times that. Psf will
+ still pack up on the min_lenuserarea parameter if it is the default.
+
+ Davis, Apr 1, 1991
+
+daophot$
+ 1. The tasks allstar, group, nstar, peak, psf and substar were all modified
+ to include datamin and datamax in their verify routines.
+ As part of this a set of general utility routines were written and
+ stored in the file daolib/dpverify.x.
+
+ 2. The io routines were consolidated into a single file for output and/or
+ another for input as appropriate. This means several files in the
+ addstar, allstar, nstar, and peak routines have disappeared.
+
+ 3. The nstar text file input routine was made for efficient by changing
+ the strmatch calls to strncmp.
+
+ Davis, Mar 30, 1991
+
+daophot$psf/
+ The psf task was writing the incorrect value of xpsf and ypsf into the
+ psf image header causing the variable psf to be evaluated at the
+ wrong position. Any task which evaluated the variable psf including
+ seepsf, group, peak, nstar, and allstar would be in error. The
+ bug was located in the file dp_writepsf.x in testphot$daophot/psf/.
+
+ Davis, Feb 1, 1991
+
+daophot$psf/
+
+ The celling for surface plots was being set to 20000 in the routine
+ dp_psfsetup in file daolib/dpinit.x causing floating point divide
+ errors in images with pixels not in the usual CCD range.
+
+ Davis, Jan 21, 1991
+
+daophot$allstar/
+ A call to dp_talwrite() was missing the chigrp argument.
+
+ Davis, March 1, 1989
+
+daophot$allstar/
+ A data dependent error could occur in allstar if the user tried to
+ write to an output ST table and the computed magnitude error was
+ less than or equal to zero.
+
+ Davis, February 28, 1989
+
+daophot$
+ All task except DAOFIND and PHOT were affected by an error in the
+ ptools$pttables/pthdrs.x file. The tasks sometimes crash on input files
+ created with append task with a memory corruption error.
+ See the ptools Revisions file for a description of the error.
+
+ Davis, January 4, 1990
+
+December 21, 1989 -- Beta Daophot Release
+.endhelp
diff --git a/noao/digiphot/daophot/addstar.par b/noao/digiphot/daophot/addstar.par
new file mode 100644
index 00000000..a8b6787f
--- /dev/null
+++ b/noao/digiphot/daophot/addstar.par
@@ -0,0 +1,23 @@
+# Parameters for the ADDSTAR task
+
+image,f,a,,,,"Image to which stars are to be added"
+photfile,f,a,,,,"Input photometry file"
+psfimage,f,a,default,,,"Input PSF image (default: image.psf.?)"
+addimage,f,a,"default",,,"Output artificial image (default: image.add.?)"
+minmag,r,a,,,,Minimum magnitude of artificial stars to add
+maxmag,r,a,,,,Maximum magnitude of artificial stars to add
+nstar,i,a,100,1,,Number of artifical stars to add
+datapars,pset,h,"",,,Data dependent parameters
+daopars,pset,h,"",,,Psf fitting parameters
+simple_text,b,h,no,,,"Input is in simple text format?"
+seed,r,h,0.0,,,Seed for the random number generator
+nimage,i,h,1,1,,Number of new images per input image
+idoffset,i,h,0,,,Id numbering offset
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+wcspsf,s,h,)_.wcspsf,,,"The psf coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the output image pixels in memory?"
+verify,b,h,)_.verify,,,Verify critical addstar parameters?
+update,b,h,)_.update,,,Update critical addstar parameters?
+verbose,b,h,)_.verbose,,,Print addstar messages?
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/addstar/dpadconfirm.x b/noao/digiphot/daophot/addstar/dpadconfirm.x
new file mode 100644
index 00000000..bff2ca93
--- /dev/null
+++ b/noao/digiphot/daophot/addstar/dpadconfirm.x
@@ -0,0 +1,14 @@
+# DP_ADCONFIRM -- Confirm the critical ADDSTAR parameters.
+
+procedure dp_adconfirm (dao)
+
+pointer dao # pointer to the daophot structure
+
+begin
+ call printf ("\n")
+
+ # Confirm the psf radius.
+ call dp_vpsfrad (dao)
+
+ call printf ("\n")
+end
diff --git a/noao/digiphot/daophot/addstar/dpaddrd.x b/noao/digiphot/daophot/addstar/dpaddrd.x
new file mode 100644
index 00000000..108448ee
--- /dev/null
+++ b/noao/digiphot/daophot/addstar/dpaddrd.x
@@ -0,0 +1,89 @@
+include "../lib/apseldef.h"
+
+# DP_TADINIT -- Initializie the column descriptors for the input ST photometry
+# table.
+
+procedure dp_tadinit (tp, column)
+
+pointer tp # table descriptor
+int column[ARB] # column pointer array
+
+begin
+ # Find the column pointers
+ call tbcfnd (tp, ID, column[1], 1)
+ if (column[1] == NULL)
+ call tbcfnd (tp, "ID", column[1], 1)
+ if (column[1] == NULL)
+ call printf ("Error reading ID.\n")
+
+ call tbcfnd (tp, XCENTER, column[2], 1)
+ if (column[2] == NULL)
+ call tbcfnd (tp, "XCENTER", column[2], 1)
+ if (column[2] == NULL)
+ call printf ("Error reading XCENTER.\n")
+
+ call tbcfnd (tp, YCENTER, column[3], 1)
+ if (column[3] == NULL)
+ call tbcfnd (tp, "YCENTER", column[3], 1)
+ if (column[3] == NULL)
+ call printf ("Error reading YCENTER.\n")
+
+ call tbcfnd (tp, MAG, column[4], 1)
+ if (column[4] == NULL)
+ call tbcfnd (tp, APMAG, column[4], 1)
+ if (column[4] == NULL)
+ call printf ("Error reading MAG.\n")
+end
+
+
+# DP_TADREAD -- Read a record from the input ST photometry table.
+
+procedure dp_tadread (tp, column, id, x, y, mag, row)
+
+pointer tp # table descriptor
+int column[ARB] # column pointer array
+int id # output id
+real x # output x value
+real y # output y value
+real mag # output magnitude
+int row # integer row
+
+bool nullflag
+
+begin
+ call tbrgti (tp, column[1], id, nullflag, 1, row)
+ if (nullflag)
+ id = 0
+ call tbrgtr (tp, column[2], x, nullflag, 1, row)
+ call tbrgtr (tp, column[3], y, nullflag, 1, row)
+ call tbrgtr (tp, column[4], mag, nullflag, 1, row)
+end
+
+
+# DP_GCOORDS -- Read the coordinates and magnitudes from a simple text file.
+
+int procedure dp_gcoords (cl, x, y, mag, id)
+
+int cl # file descriptor
+real x # x coordinate centers
+real y # y coordinate centers
+real mag # magnitudes
+int id # id of the star
+
+int fscan(), nscan()
+
+begin
+ while (fscan (cl) != EOF) {
+ call gargr (x)
+ call gargr (y)
+ call gargr (mag)
+ if (nscan () < 3)
+ next
+ call gargi (id)
+ if (nscan() < 4)
+ id = 0
+ return (1)
+ }
+
+ return (EOF)
+end
diff --git a/noao/digiphot/daophot/addstar/dpartstar.x b/noao/digiphot/daophot/addstar/dpartstar.x
new file mode 100644
index 00000000..9f464812
--- /dev/null
+++ b/noao/digiphot/daophot/addstar/dpartstar.x
@@ -0,0 +1,303 @@
+include <imhdr.h>
+include <tbset.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+
+define ADD_NINCOLUMN 4
+
+# DP_ARTSTAR -- Add artificial stars to the data frames.
+
+procedure dp_artstar (dao, iim, oim, cl, ofd, nstar, minmag, maxmag, iseed,
+ coo_text, simple, offset, cache)
+
+pointer dao # pointer to DAOPHOT structure
+pointer iim # the input image descriptor
+pointer oim # image to add stars to
+int cl # fd of input photometry file
+int ofd # fd of output photometry file
+int nstar # number of stars to be added
+real minmag, maxmag # min. and max. magnitudes to add
+int iseed[ARB] # the random number generator array
+bool coo_text # coordinate text file ?
+int simple # simple text file ?
+int offset # id offset for output photometry file
+int cache # cache the output pixels
+
+real xmin, ymin, xwide, ywide, mwide, x, y, dxfrom_psf, dyfrom_psf, mag
+real radius, psfradsq, rel_bright, sky, tx, ty
+pointer sp, colpoint, psffit, subim, subim_new, indices, fields, key
+int i, iid, id, lowx, lowy, nxpix, nypix, nrow
+
+pointer dp_gsubrast(), imps2r(), tbpsta()
+int dp_gcoords(), dp_apsel()
+
+begin
+ # Get some memory.
+ call smark (sp)
+ call salloc (fields, SZ_LINE, TY_CHAR)
+ call salloc (indices, ADD_NINCOLUMN, TY_INT)
+ call salloc (colpoint, ADD_NINCOLUMN, TY_INT)
+
+ # Initialize the input photometry file.
+ key = NULL
+ if (cl != NULL) {
+ if (! coo_text) {
+ call dp_tadinit (cl, Memi[indices])
+ nrow = tbpsta (cl, TBL_NROWS)
+ #} else if (coo_text && simple == NO) {
+ } else if (simple == NO) {
+ call pt_kyinit (key)
+ Memi[indices] = DP_PAPID
+ Memi[indices+1] = DP_PAPXCEN
+ Memi[indices+2] = DP_PAPYCEN
+ Memi[indices+3] = DP_PAPMAG1
+ call dp_gappsf (Memi[indices], Memc[fields], ADD_NINCOLUMN)
+ }
+ }
+
+ # Initialize the output table.
+ if (DP_TEXT(dao) == YES)
+ call dp_xnaddstar (dao, ofd)
+ else
+ call dp_tnaddstar (dao, ofd, Memi[colpoint])
+
+ # Get some daophot pointers.
+ psffit = DP_PSFFIT (dao)
+
+ # Get the psf radius
+ if (DP_PSFSIZE(psffit) == 0)
+ radius = DP_PSFRAD(dao)
+ else
+ radius = min (DP_PSFRAD(dao), (real (DP_PSFSIZE(psffit) - 1) /
+ 2.0 - 1.0) / 2.0)
+ psfradsq = radius * radius
+
+ # Get the x and y limits for the random number generator. The
+ # magnitude limits are input by the user.
+ xmin = 1.0
+ xwide = real(IM_LEN(oim,1)) - 1.0
+ ymin = 1.0
+ ywide = real (IM_LEN(oim,2)) - 1.0
+ mwide = maxmag - minmag
+
+ if (DP_VERBOSE (dao) == YES) {
+ call printf ("OUTPUT IMAGE: %s\n")
+ call pargstr (IM_HDRFILE(oim))
+ }
+
+ # Add the stars.
+ i = 1
+ repeat {
+
+ # Get the coords and magnitudes of the star.
+ if (cl == NULL) {
+ call dp_mkcoords (x, y, mag, xmin, xwide, ymin, ywide, minmag,
+ mwide, iseed)
+ id = i + offset
+ if (i > nstar)
+ break
+ } else if (! coo_text) {
+ if (i > nrow)
+ break
+ call dp_tadread (cl, Memi[indices], iid, x, y, mag, i)
+ call dp_win (dao, iim, x, y, x, y, 1)
+ if (iid == 0)
+ iid = i + offset
+ else
+ id = iid
+ } else {
+ if (simple == YES) {
+ if (dp_gcoords (cl, x, y, mag, iid) == EOF)
+ break
+ if (iid == 0)
+ id = i + offset
+ else
+ id = iid
+ } else {
+ if (dp_apsel (key, cl, Memc[fields], Memi[indices], iid, x,
+ y, sky, mag) == EOF)
+ break
+ if (iid == 0)
+ id = i + offset
+ else
+ id = iid
+ }
+ call dp_win (dao, iim, x, y, x, y, 1)
+ }
+
+ # Increment the counter
+ i = i + 1
+
+ # Compute the psf coordinates.
+ call dp_wpsf (dao, iim, x, y, dxfrom_psf, dyfrom_psf, 1)
+ dxfrom_psf = (dxfrom_psf - 1.0) / DP_PSFX(psffit) - 1.0
+ dyfrom_psf = (dyfrom_psf - 1.0) / DP_PSFY(psffit) - 1.0
+
+ # Compute output coordinates.
+ call dp_wout (dao, iim, x, y, tx, ty, 1)
+
+ # Read in the subraster and compute the relative x-y position.
+ subim = dp_gsubrast (oim, x, y, radius, lowx, lowy, nxpix, nypix)
+ if (subim == NULL) {
+ call printf (
+ " Star: %d - X: %6.2f Y: %6.2f Mag: %7.3f off image\n")
+ call pargi (id)
+ call pargr (tx)
+ call pargr (ty)
+ call pargr (mag)
+ next
+ } else if (DP_VERBOSE (dao) == YES) {
+ call printf (
+ " Added Star: %d - X: %6.2f Y: %6.2f Mag: %7.3f\n")
+ call pargi (id)
+ call pargr (tx)
+ call pargr (ty)
+ call pargr (mag)
+ }
+
+ if (DP_TEXT(dao) == YES)
+ call dp_xwadd (ofd, id, tx, ty, mag)
+ else
+ call dp_twadd (ofd, Memi[colpoint], id, tx, ty, mag, id)
+
+ # Get the relative brightness
+ rel_bright = DAO_RELBRIGHT (psffit, mag)
+
+ # Get the output buffer.
+ subim_new = imps2r (oim, lowx, lowx + nxpix - 1, lowy,
+ lowy + nypix - 1)
+
+ # Evaluate the PSF for a single star.
+ x = x - lowx + 1.0
+ y = y - lowy + 1.0
+ call dp_artone (dao, Memr[subim], nxpix, nypix, x, y, rel_bright,
+ dxfrom_psf, dyfrom_psf, psfradsq, DP_PHOTADU(dao), iseed)
+
+ # Make sure the image buffer is flushed. Currently this is a
+ # very inefficient way to do the image i/o.
+ call amovr (Memr[subim], Memr[subim_new], nxpix * nypix)
+ if (cache == NO)
+ call imflush (oim)
+
+ }
+
+ # Release the text file structure.
+ if (key != NULL)
+ call pt_kyfree (key)
+
+ call sfree (sp)
+end
+
+
+# DP_ARTONE -- Add a single star to the image.
+
+procedure dp_artone (dao, subin, nxpix, nypix, x, y, rel_bright, xfrom_psf,
+ yfrom_psf, psfradsq, gain, iseed)
+
+pointer dao # pointer to the daophot structure
+real subin[nxpix,nypix] # input subraster
+int nxpix, nypix # dimensions of subrasters
+real x, y # input position
+real rel_bright # relative brightness
+real xfrom_psf # x distance from the psf
+real yfrom_psf # y distance from the psf
+real psfradsq # psf radius squared
+real gain # gain
+int iseed[ARB] # random number seed array
+
+int ix, iy
+pointer psffit
+real dx, dy, dxsq, dysq, radsq, dvdx, dvdy, value, err
+real dp_usepsf(), dp_nrml(), daoran()
+
+begin
+ psffit = DP_PSFFIT(dao)
+
+ do iy = 1, nypix {
+ dy = real (iy) - y
+ dysq = dy * dy
+ do ix = 1, nxpix {
+ dx = real (ix) - x
+ dxsq = dx * dx
+ radsq = dxsq + dysq
+ if (radsq < psfradsq) {
+ value = rel_bright * dp_usepsf (DP_PSFUNCTION(psffit),
+ dx, dy, DP_PSFHEIGHT(psffit), Memr[DP_PSFPARS(psffit)],
+ Memr[DP_PSFLUT(psffit)], DP_PSFSIZE(psffit),
+ DP_NVLTABLE(psffit), DP_NFEXTABLE(psffit),
+ xfrom_psf, yfrom_psf, dvdx, dvdy)
+ err = daoran (iseed[mod(ix+iy,3)+1])
+ err = sqrt (max (0.0, value / gain)) * dp_nrml (err)
+ subin[ix,iy] = subin[ix,iy] + value + err
+ }
+ }
+ }
+end
+
+
+# DP_MKCOORDS -- Construct a list of coordinates using a random number
+# generator.
+
+procedure dp_mkcoords (x, y, mag, xmin, xwide, ymin, ywide, minmag, mwide,
+ iseed)
+
+real x # x array
+real y # y array
+real mag # magnitude array
+real xmin # xmin value
+real xwide # x coordinate range
+real ymin # ymin value
+real ywide # y coordinate range
+real minmag # minimum magnitude
+real mwide # the magnitude range
+int iseed[ARB] # seed array for random number genrator
+
+real daoran()
+
+begin
+ x = xmin + daoran (iseed[1]) * xwide
+ y = ymin + daoran (iseed[2]) * ywide
+ mag = minmag + daoran (iseed[3]) * mwide
+end
+
+
+# DP_SEED3 -- Seed the random number generator.
+
+procedure dp_seed3 (seed, iseed)
+
+int seed # initial seed value
+int iseed[ARB] # the seed array
+
+int idum
+real daoran()
+
+begin
+ idum = seed
+ iseed[1] = int (524288.* daoran (idum)) + 1
+ iseed[2] = int (524288.* daoran (idum)) + 1
+ iseed[3] = int (524288.* daoran (idum)) + 1
+end
+
+
+# DP_NRML -- Convert a uniform probability distribution to a Gaussian
+# distribution with mean zero and standard deviation of unity.
+
+real procedure dp_nrml (random)
+
+real random # input random number
+
+real p, sign, t
+
+begin
+ p = random
+ sign = -1.0
+ if (p > 0.5) {
+ p = p - 0.5
+ sign = 1.0
+ } else if (p <= 0.0)
+ return (-1.0e20)
+
+ t = sqrt (log (1.0 / (p * p)))
+ return (sign * (t - (2.30753 + 0.27061 * t) /
+ (1.0 + t * (0.99229 + t * 0.04481))))
+end
diff --git a/noao/digiphot/daophot/addstar/dpnaddstar.x b/noao/digiphot/daophot/addstar/dpnaddstar.x
new file mode 100644
index 00000000..b08dd813
--- /dev/null
+++ b/noao/digiphot/daophot/addstar/dpnaddstar.x
@@ -0,0 +1,265 @@
+include <time.h>
+include <tbset.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+
+define ADD_NOUTCOLUMN 4
+
+# DP_TNADDSTAR -- Create an output ADDSTAR table.
+
+procedure dp_tnaddstar (dao, tp, columns)
+
+pointer dao # pointer to daophot structure
+pointer tp # output table decscriptor
+int columns[ARB] # pointer to columns
+
+int i
+pointer sp, colnames, colunits, colformat, col_dtype, col_len
+
+begin
+ # Allocate space for table definition.
+ call smark (sp)
+ call salloc (colnames, ADD_NOUTCOLUMN * (SZ_COLNAME + 1), TY_CHAR)
+ call salloc (colunits, ADD_NOUTCOLUMN * (SZ_COLUNITS + 1), TY_CHAR)
+ call salloc (colformat, ADD_NOUTCOLUMN * (SZ_COLFMT + 1), TY_CHAR)
+ call salloc (col_dtype, ADD_NOUTCOLUMN, TY_INT)
+ call salloc (col_len, ADD_NOUTCOLUMN, TY_INT)
+
+ # Set up the column definitions.
+ call strcpy (ID, Memc[colnames], SZ_COLNAME)
+ call strcpy (XCENTER, Memc[colnames+SZ_COLNAME+1], SZ_COLNAME)
+ call strcpy (YCENTER, Memc[colnames+2*SZ_COLNAME+2], SZ_COLNAME)
+ call strcpy (MAG, Memc[colnames+3*SZ_COLNAME+3], SZ_COLNAME)
+
+ # Set up the column formats.
+ call strcpy ("%5d", Memc[colformat], SZ_COLFMT)
+ call strcpy ("%10.3f", Memc[colformat+SZ_COLFMT+1], SZ_COLFMT)
+ call strcpy ("%10.3f", Memc[colformat+2*SZ_COLFMT+2], SZ_COLFMT)
+ call strcpy ("%12.3f", Memc[colformat+3*SZ_COLFMT+3], SZ_COLFMT)
+
+ # Set up the units definitions.
+ call strcpy ("NUMBER", Memc[colunits], SZ_COLUNITS)
+ call strcpy ("PIXELS", Memc[colunits+SZ_COLUNITS+1], SZ_COLUNITS)
+ call strcpy ("PIXELS", Memc[colunits+2*SZ_COLUNITS+2], SZ_COLUNITS)
+ call strcpy ("MAGNITIDES", Memc[colunits+3*SZ_COLUNITS+3],
+ SZ_COLUNITS)
+
+ # Set up the data types.
+ Memi[col_dtype] = TY_INT
+ Memi[col_dtype+1] = TY_REAL
+ Memi[col_dtype+2] = TY_REAL
+ Memi[col_dtype+3] = TY_REAL
+
+ do i = 1, ADD_NOUTCOLUMN
+ Memi[col_len+i-1] = 1
+
+ call tbcdef (tp, columns, Memc[colnames], Memc[colunits],
+ Memc[colformat], Memi[col_dtype], Memi[col_len], ADD_NOUTCOLUMN)
+ call tbtcre (tp)
+
+ # Write out the header parameters.
+ call dp_tgadppars (dao, tp)
+
+ call sfree (sp)
+
+end
+
+
+define ADD_NAMESTR "#N%4tID%10tXCENTER%20tYCENTER%30tMAG%80t\\\n"
+define ADD_UNITSTR "#U%4t##%10tpixels%20tpixels%30tmagnitudes%80t\\\n"
+define ADD_FORMATSTR "#F%4t%%-9d%10t%%-10.3f%20t%%-10.3f%30t%%-12.3f%80t \n"
+define ADD_DATASTR "%4t%-6d%10t%-10.3f%20t%-10.3f%30t%-12.3f%80t \n"
+
+
+# DP_XNADDSTAR -- Write out the ADDSTAR header parameters into a text file.
+
+procedure dp_xnaddstar (dao, tp)
+
+pointer dao # pointer to the daophot structure
+int tp # group output file descriptor
+
+begin
+ # Add header parameters to the table.
+ call dp_xgadppars (dao, tp)
+
+ # Write out the banner.
+ call fprintf (tp, "#\n")
+ call fprintf (tp, ADD_NAMESTR)
+ call fprintf (tp, ADD_UNITSTR)
+ call fprintf (tp, ADD_FORMATSTR)
+ call fprintf (tp, "#\n")
+end
+
+
+# DP_XWADD -- Procedure to write out the new star to the ADDSTAR output
+# text file.
+
+procedure dp_xwadd (tp, id, x, y, mag)
+
+int tp # output file descriptor
+int id # id number
+real x # x value
+real y # y value
+real mag # magnitude
+
+begin
+ call fprintf (tp, ADD_DATASTR)
+ call pargi (id)
+ call pargr (x)
+ call pargr (y)
+ call pargr (mag)
+end
+
+
+# DP_TWADD -- Procedure to write out the new star to the ADDSTAR output
+# table.
+
+procedure dp_twadd (tp, colpoint, id, x, y, mag, row)
+
+int tp # pointer to group output table
+int colpoint[ARB] # column pointers
+int id # id number
+real x # x value
+real y # y value
+real mag # magnitude
+int row # row number to be added
+
+begin
+ call tbrpti (tp, colpoint[1], id, 1, row)
+ call tbrptr (tp, colpoint[2], x, 1, row)
+ call tbrptr (tp, colpoint[3], y, 1, row)
+ call tbrptr (tp, colpoint[4], mag, 1, row)
+end
+
+
+# DP_XGADPPARS -- Add various parameters to the header of the ADDSTAR text
+# output file.
+
+procedure dp_xgadppars (dao, tp)
+
+pointer dao # pointer to the DAOPHOT structure
+int tp # output file descriptor
+
+pointer sp, outstr, date, time
+int envfind()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+ call salloc (date, SZ_DATE, TY_CHAR)
+ call salloc (time, SZ_DATE, TY_CHAR)
+
+ # Write the id.
+ if (envfind ("version", Memc[outstr], SZ_LINE) <= 0)
+ call strcpy ("NOAO/IRAF", Memc[outstr], SZ_LINE)
+ call dp_rmwhite (Memc[outstr], Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "IRAF", Memc[outstr], "version", "")
+
+ if (envfind ("userid", Memc[outstr], SZ_LINE) > 0)
+ call dp_sparam (tp, "USER", Memc[outstr], "name", "")
+ call gethost (Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "HOST", Memc[outstr], "computer", "")
+ call dp_date (Memc[date], Memc[time], SZ_DATE)
+ call dp_sparam (tp, "DATE", Memc[date], "yyyy-mm-dd", "")
+ call dp_sparam (tp, "TIME", Memc[time], "hh:mm:ss", "")
+ call dp_sparam (tp, "PACKAGE", "daophot", "name", "")
+ call dp_sparam (tp, "TASK", "addstar", "name", "")
+
+ # Write the file name parameters.
+ call dp_imroot (DP_INIMAGE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "IMAGE", Memc[outstr], "imagename", "")
+ call dp_froot (DP_INPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "PHOTFILE", Memc[outstr], "filename", "")
+ call dp_imroot (DP_PSFIMAGE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "PSFIMAGE", Memc[outstr], "imagename", "")
+ call dp_imroot (DP_OUTIMAGE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "ADDIMAGE", Memc[outstr], "imagename", "")
+ call dp_froot (DP_OUTPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "ADDFILE", Memc[outstr], "filename", "")
+
+ # Write out relevant data parameters.
+ call dp_rparam (tp, "SCALE", DP_SCALE(dao), "units/pix", "")
+ call dp_rparam (tp, "DATAMIN", DP_MINGDATA(dao), "counts", "")
+ call dp_rparam (tp, "DATAMAX", DP_MAXGDATA(dao), "counts", "")
+ call dp_rparam (tp, "GAIN", DP_PHOTADU(dao), "number", "")
+ call dp_rparam (tp, "READNOISE", DP_READNOISE(dao), "electrons", "")
+
+ # Write out the observing parameters.
+ call dp_sparam (tp, "OTIME", DP_OTIME(dao), "timeunit", "")
+ call dp_rparam (tp, "XAIRMASS", DP_XAIRMASS(dao), "number", "")
+ call dp_sparam (tp, "IFILTER", DP_IFILTER(dao), "filter", "")
+
+ # Write out the daopars parameters.
+ call dp_rparam (tp, "PSFRAD", DP_SPSFRAD(dao), "scaleunit", "")
+ call dp_rparam (tp, "FITRAD", DP_SFITRAD(dao), "scaleunit", "")
+
+ call sfree(sp)
+end
+
+
+# DP_TGADPPARS -- Add various parameters to the header of the ADDSTAR output
+# table.
+
+procedure dp_tgadppars (dao, tp)
+
+pointer dao # pointer to the DAOPHOT structure
+pointer tp # pointer to the output table
+
+pointer sp, outstr, date, time
+int envfind()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+ call salloc (date, SZ_DATE, TY_CHAR)
+ call salloc (time, SZ_DATE, TY_CHAR)
+
+ # Write the id.
+
+ if (envfind ("version", Memc[outstr], SZ_LINE) <= 0)
+ call strcpy ("NOAO/IRAF", Memc[outstr], SZ_LINE)
+ call dp_rmwhite (Memc[outstr], Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "IRAF", Memc[outstr])
+
+ if (envfind ("userid", Memc[outstr], SZ_LINE) > 0)
+ call tbhadt (tp, "USER", Memc[outstr])
+ call gethost (Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "HOST", Memc[outstr])
+ call dp_date (Memc[date], Memc[time], SZ_DATE)
+ call tbhadt (tp, "DATE", Memc[date])
+ call tbhadt (tp, "TIME", Memc[time])
+ call tbhadt (tp, "PACKAGE", "daophot")
+ call tbhadt (tp, "TASK", "group")
+
+ # Write the file name parameters.
+ call dp_imroot (DP_INIMAGE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "IMAGE", Memc[outstr])
+ call dp_froot (DP_INPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "PHOTFILE", Memc[outstr])
+ call dp_imroot (DP_PSFIMAGE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "PSFIMAGE", Memc[outstr])
+ call dp_imroot (DP_OUTIMAGE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "ADDIMAGE", Memc[outstr])
+ call dp_froot (DP_OUTPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "ADDFILE", Memc[outstr])
+
+ # Write out relevant data parameters.
+ call tbhadr (tp, "SCALE", DP_SCALE(dao))
+ call tbhadr (tp, "DATAMIN", DP_MINGDATA(dao))
+ call tbhadr (tp, "DATAMAX", DP_MAXGDATA(dao))
+ call tbhadr (tp, "GAIN", DP_PHOTADU(dao))
+ call tbhadr (tp, "READNOISE", DP_READNOISE(dao))
+
+ # Write out the observing parameters.
+ call tbhadt (tp, "OTIME", DP_OTIME(dao))
+ call tbhadr (tp, "XAIRMASS", DP_XAIRMASS(dao))
+ call tbhadt (tp, "IFILTER", DP_IFILTER(dao))
+
+ # Write out the daophot parameters.
+ call tbhadr (tp, "PSFRAD", DP_SPSFRAD(dao))
+ call tbhadr (tp, "FITRAD", DP_SFITRAD(dao))
+
+ call sfree(sp)
+end
diff --git a/noao/digiphot/daophot/addstar/mkpkg b/noao/digiphot/daophot/addstar/mkpkg
new file mode 100644
index 00000000..9092f186
--- /dev/null
+++ b/noao/digiphot/daophot/addstar/mkpkg
@@ -0,0 +1,17 @@
+# ADDSTAR task
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ dpaddrd.x ../lib/apseldef.h
+ dpadconfirm.x
+ dpartstar.x <tbset.h> <imhdr.h> \
+ ../lib/daophotdef.h ../lib/apseldef.h
+ dpnaddstar.x <tbset.h> <time.h> \
+ ../lib/daophotdef.h ../lib/apseldef.h
+ t_addstar.x <fset.h> <imhdr.h> \
+ ../lib/daophotdef.h
+ ;
diff --git a/noao/digiphot/daophot/addstar/t_addstar.x b/noao/digiphot/daophot/addstar/t_addstar.x
new file mode 100644
index 00000000..479188c0
--- /dev/null
+++ b/noao/digiphot/daophot/addstar/t_addstar.x
@@ -0,0 +1,331 @@
+include <fset.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+
+define NSEED 3
+
+# T_ADDSTAR -- Add artificial stars to a list of images.
+
+procedure t_addstar ()
+
+pointer image # the input image
+pointer psfimage # the input PSF image
+pointer photfile # the input photometry file
+pointer addimage # root name for output image and file
+real minmag, maxmag # magnitude range of artificial stars
+int nstar # number of artificial stars
+int nimage # number of new images
+int cache # cache the output image pixels
+
+pointer sp, outfname, im, psffd, oim, dao, str
+int imlist, limlist, plist, lplist, pimlist, lpimlist, oimlist, loimlist
+int ifd, ofd, j, simple, idoffset, root, verbose, verify, update, wcs
+int req_size, old_size, buf_size, memstat
+int seed, iseed[NSEED]
+bool coo_text
+
+real clgetr()
+pointer immap(), tbtopn()
+int clgeti(), fstati(), btoi(), fnldir(), strlen(), strncmp()
+int access(), open(), imtopen(), imtlen(), imtgetim(), fntopnb(), fntlenb()
+int fntgfnb(), clgwrd(), sizeof(), dp_memstat()
+bool itob(), clgetb()
+
+begin
+ # Set the standard output to flush on newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Allocate some memory.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (psfimage, SZ_FNAME, TY_CHAR)
+ call salloc (photfile, SZ_FNAME, TY_CHAR)
+ call salloc (addimage, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Get the file names.
+ call clgstr ("image", Memc[image], SZ_FNAME)
+ call clgstr ("photfile", Memc[photfile], SZ_FNAME)
+ call clgstr ("psfimage", Memc[psfimage], SZ_FNAME)
+ call clgstr ("addimage", Memc[addimage], SZ_FNAME)
+
+ # Open the file/image lists.
+ imlist = imtopen (Memc[image])
+ limlist = imtlen (imlist)
+ plist = fntopnb (Memc[photfile], NO)
+ lplist = fntlenb (plist)
+ pimlist = imtopen (Memc[psfimage])
+ lpimlist = imtlen (pimlist)
+ oimlist = imtopen (Memc[addimage])
+ loimlist = imtlen (oimlist)
+
+ # Check that the image and input photometry list lengths match.
+ if ((lplist > 1) && (lplist != limlist)) {
+ call imtclose (imlist)
+ call fntclsb (plist)
+ call imtclose (pimlist)
+ call imtclose (oimlist)
+ call sfree (sp)
+ call error (0, "Incompatible image and photometry list lengths")
+ }
+
+ # Check that the image and psf image list lengths match.
+ if ((limlist != lpimlist) && (strncmp (Memc[psfimage], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (plist)
+ call imtclose (pimlist)
+ call imtclose (oimlist)
+ call sfree (sp)
+ call error (0, "Incompatible image and psf image list lengths")
+ }
+
+ # Check that image and output image list lengths match.
+ if ((loimlist != limlist) && (strncmp (Memc[addimage], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (plist)
+ call imtclose (pimlist)
+ call imtclose (oimlist)
+ call sfree (sp)
+ call error (0, "Incompatible input and output image list lengths")
+ }
+
+ # Set the type of input text file.
+ simple = btoi (clgetb ("simple_text"))
+
+ # Get the articial star parameters.
+ nimage = clgeti ("nimage")
+ if (lplist <= 0) {
+ nstar = clgeti ("nstar")
+ minmag = clgetr ("minmag")
+ maxmag = clgetr ("maxmag")
+ }
+ seed = clgeti ("seed")
+ idoffset = clgeti ("idoffset")
+
+ verbose = btoi (clgetb ("verbose"))
+ verify = btoi (clgetb ("verify"))
+ update = btoi (clgetb ("update"))
+ cache = btoi (clgetb("cache"))
+
+ # Initialize the daophot structure.
+ call dp_gppars (dao)
+ call dp_seti (dao, VERBOSE, verbose)
+
+ # Verify, confirm, update the parameters.
+ if (verify == YES) {
+ call dp_adconfirm (dao)
+ if (update == YES)
+ call dp_pppars (dao)
+ }
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_FNAME, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_FNAME, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSOUT, wcs)
+ wcs = clgwrd ("wcspsf", Memc[str], SZ_FNAME, WCSPSFSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the psf coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSPSF, wcs)
+
+
+ # Open the PSF structure
+ call dp_fitsetup (dao)
+
+ # Initialize the random number generator.
+ call dp_seed3 (seed, iseed)
+
+ # Now loop over the input image list
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open the input image.
+ im = immap (Memc[image], READ_ONLY, 0)
+ call dp_imkeys (dao, im)
+ call dp_sets (dao, INIMAGE, Memc[image])
+
+ # Cache the output image pixels.
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = dp_memstat (cache, req_size, old_size)
+ #if (memstat == YES)
+ #call dp_pcache (im, INDEFI, buf_size)
+
+ # Read the PSF image.
+ if (imtgetim (pimlist, Memc[psfimage], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[psfimage], SZ_FNAME)
+ root = fnldir (Memc[psfimage], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[psfimage+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[psfimage]))
+ call dp_iimname (Memc[image], Memc[outfname], "psf",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[psfimage], Memc[outfname], SZ_FNAME)
+ psffd = immap (Memc[outfname], READ_ONLY, 0)
+ call dp_sets (dao, PSFIMAGE, Memc[outfname])
+ call dp_readpsf (dao, psffd)
+
+ # Open the input photometry file.
+ if (lplist <= 0 ) {
+ ifd = NULL
+ call strcpy ("", Memc[photfile], SZ_FNAME)
+ } else if (fntgfnb (plist, Memc[photfile], SZ_FNAME) != EOF) {
+ coo_text = itob (access (Memc[photfile], 0, TEXT_FILE))
+ if (coo_text)
+ ifd = open (Memc[photfile], READ_ONLY, TEXT_FILE)
+ else
+ ifd = tbtopn (Memc[photfile], READ_ONLY, 0)
+ } else
+ call seek (ifd, BOF)
+ call dp_sets (dao, INPHOTFILE, Memc[photfile])
+
+ # Get the output image and file root name.
+ if (imtgetim (oimlist, Memc[addimage], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[addimage], SZ_FNAME)
+
+ # Now loop over the number of output images per input image.
+ do j = 1, nimage {
+
+ # Open the output image.
+ root = fnldir (Memc[addimage], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[addimage+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[addimage])) {
+ call dp_oimname (Memc[image], Memc[outfname], "add",
+ Memc[outfname], SZ_FNAME)
+ oim = immap (Memc[outfname], NEW_COPY, im)
+ } else {
+ call strcpy (Memc[addimage], Memc[outfname], SZ_FNAME)
+ if (nimage > 1) {
+ call sprintf (Memc[outfname+
+ strlen(Memc[outfname])], SZ_FNAME, "%03d")
+ call pargi (j)
+ }
+ oim = immap (Memc[outfname], NEW_COPY, im)
+ }
+ call dp_sets (dao, OUTIMAGE, Memc[outfname])
+ if (memstat == YES)
+ call dp_pcache (oim, INDEFI, buf_size)
+
+ # Copy the input image to the new output image.
+ call dp_imcopy (im, oim)
+ if (memstat == NO)
+ call imflush (oim)
+
+ # Open the output photometry file.
+ root = fnldir (Memc[addimage], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[addimage+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[addimage])) {
+ call dp_outname (Memc[image], Memc[outfname], "art",
+ Memc[outfname], SZ_FNAME)
+ if (DP_TEXT(dao) == YES)
+ ofd = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ else
+ ofd = tbtopn (Memc[outfname], NEW_FILE, 0)
+ } else {
+ call strcpy (Memc[addimage], Memc[outfname], SZ_FNAME)
+ if (nimage > 1) {
+ call sprintf (Memc[outfname+
+ strlen(Memc[outfname])], SZ_FNAME, "%03d")
+ call pargi (j)
+ }
+ call strcat (".art", Memc[outfname], SZ_FNAME)
+ if (DP_TEXT(dao) == YES)
+ ofd = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ else
+ ofd = tbtopn (Memc[outfname], NEW_FILE, 0)
+ }
+ call dp_sets (dao, OUTPHOTFILE, Memc[outfname])
+
+ # Now go and actually add the stars.
+ call dp_artstar (dao, im, oim, ifd, ofd, nstar, minmag,
+ maxmag, iseed, coo_text, simple, idoffset, memstat)
+
+ # Close the output image and output table.
+ call imunmap (oim)
+ if (DP_TEXT(dao) == YES)
+ call close (ofd)
+ else
+ call tbtclo (ofd)
+ }
+
+ # Close the input image
+ call imunmap (im)
+
+ # Close the PSF image.
+ call imunmap (psffd)
+
+ # Close the input photometry file if there is more than one.
+ if ((ifd != NULL) && (lplist > 1)) {
+ if (coo_text)
+ call close (ifd)
+ else
+ call tbtclo (ifd)
+ ifd = NULL
+ }
+
+ # Uncache memory.
+ call fixmem (old_size)
+ }
+
+ # If there was only a single photometry file close it.
+ if (ifd != NULL && lplist == 1) {
+ if (coo_text)
+ call close (ifd)
+ else
+ call tbtclo (ifd)
+ }
+
+ # Close the image/file lists.
+ call imtclose (imlist)
+ call fntclsb (plist)
+ call imtclose (pimlist)
+ call imtclose (oimlist)
+
+ # Close the PSF structure.
+ call dp_fitclose (dao)
+
+ # Close the daophot structure.
+ call dp_free (dao)
+
+ call sfree (sp)
+end
+
+
+# DP_IMCOPY -- Make a copy of an image.
+
+procedure dp_imcopy (in, out)
+
+pointer in # the input image
+pointer out # input and output descriptors
+
+int npix
+long v1[IM_MAXDIM], v2[IM_MAXDIM]
+pointer l1, l2
+pointer imgnlr(), impnlr()
+
+begin
+ # Initialize position vectors.
+ call amovkl (long(1), v1, IM_MAXDIM)
+ call amovkl (long(1), v2, IM_MAXDIM)
+ npix = IM_LEN(in, 1)
+
+ # Copy the image.
+ while (imgnlr (in, l1, v1) != EOF && impnlr (out, l2, v2) != EOF)
+ call amovr (Memr[l1], Memr[l2], npix)
+end
diff --git a/noao/digiphot/daophot/allstar.par b/noao/digiphot/daophot/allstar.par
new file mode 100644
index 00000000..e8d52d28
--- /dev/null
+++ b/noao/digiphot/daophot/allstar.par
@@ -0,0 +1,19 @@
+# Parameters for the ALLSTAR task
+
+image,f,a,,,,"Image corresponding to photometry"
+photfile,f,a,default,,,"Input photometry file (default: image.mag.?)"
+psfimage,f,a,default,,,"PSF image (default: image.psf.?)"
+allstarfile,f,a,"default",,,"Output photometry file (default: image.als.?)"
+rejfile,f,a,"default",,,"Output rejections file (default: image.arj.?)"
+subimage,f,a,"default",,,"Subtracted image (default: image.sub.?)"
+datapars,pset,h,"",,, Data dependent parameters
+daopars,pset,h,"",,,Psf fitting parameters
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+wcspsf,s,h,)_.wcspsf,,,"The psf coordinate system (logical,tv,physical)"
+cache,b,h,yes,,,Cache the data in memory?
+verify,b,h,)_.verify,,,Verify critical allstar parameters?
+update,b,h,)_.update,,,Update critical allstar parameters?
+verbose,b,h,)_.verbose,,,Print allstar messages?
+version,i,h,2,1,2,Version
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/allstar/dpabuf.x b/noao/digiphot/daophot/allstar/dpabuf.x
new file mode 100644
index 00000000..13aac109
--- /dev/null
+++ b/noao/digiphot/daophot/allstar/dpabuf.x
@@ -0,0 +1,495 @@
+include <imhdr.h>
+include "../lib/daophotdef.h"
+include "../lib/allstardef.h"
+
+# DP_GWT -- Return a pointer to the desired weights pixels. The weights buffer
+# pointer is assumed to be NULL on the initial all. If the new line limits
+# are totally contained within the old line limits no action is taken and
+# the old line limits are returned. If the weights pixels are stored in a
+# scratch image the pixels must be accessed sequentially, otherwise an
+# error is returned.
+
+pointer procedure dp_gwt (dao, im, line1, line2, mode, flush)
+
+pointer dao # pointer to the daophot strucuture
+pointer im # pointer to the input image
+int line1 # the lower line limit
+int line2 # the upper line limit
+int mode # input / output mode
+int flush # flush the output
+
+int nx, ny, xoff, yoff, llast1, llast2
+pointer allstar
+
+begin
+ allstar = DP_ALLSTAR(dao)
+ if (DP_WBUF(allstar) == NULL) {
+ llast1 = 0
+ llast2 = 0
+ } else if (flush == YES) {
+ line1 = llast1
+ line2 = llast2
+ } else if ((line1 >= llast1) && (line2 <= llast2)) {
+ line1 = llast1
+ line2 = llast2
+ return (DP_WBUF(allstar))
+ } else if (line1 < llast1)
+ call error (0,
+ "ERROR: Attempting to access the weights pixels randomly")
+
+ # All the data is cached.
+ if (DP_CACHE (allstar, A_WEIGHT) == YES) {
+
+ nx = IM_LEN(im,1)
+ ny = IM_LEN(im,2)
+ xoff = 1
+ yoff = 1
+ DP_WBUF(allstar) = DP_WEIGHTS(allstar)
+
+ # Read in some new data.
+ } else if (mode == READ_ONLY) {
+
+ call dp_albufl2r (DP_WEIGHTS(allstar), DP_WBUF(allstar),
+ llast1, llast2, line1, line2, flush)
+
+ if (flush == NO) {
+ nx = IM_LEN(im,1)
+ ny = line2 - line1 + 1
+ xoff = 1
+ yoff = line1
+ } else {
+ nx = 0
+ ny = 0
+ xoff = 0
+ yoff = 0
+ }
+
+ # Write out the old data and read in some new data.
+ } else if (mode == READ_WRITE) {
+
+ call dp_albufl2rw (DP_WEIGHTS(allstar), DP_WEIGHTS(allstar),
+ DP_WBUF(allstar), llast1, llast2, line1, line2, flush)
+
+ if (flush == NO) {
+ nx = IM_LEN(im,1)
+ ny = line2 - line1 + 1
+ xoff = 1
+ yoff = line1
+ } else {
+ nx = 0
+ ny = 0
+ xoff = 0
+ yoff = 0
+ }
+ }
+
+ # Update the required buffer parameters.
+ DP_WNX(allstar) = nx
+ DP_WNY(allstar) = ny
+ DP_WXOFF(allstar) = xoff
+ DP_WYOFF(allstar) = yoff
+
+ # Update the buffer definition which is currently not used.
+ DP_WLX(allstar) = xoff
+ DP_WMX(allstar) = max (xoff + nx - 1, 0)
+ DP_WLY(allstar) = yoff
+ DP_WMY(allstar) = max (yoff + ny - 1, 0)
+
+ return (DP_WBUF(allstar))
+end
+
+
+# DP_GST -- Return a pointer to the scratch image pixels. The scratch image
+# pointer is assumed to be NULL on the initial all. If the new line limits
+# are totally contained within the old line limits no action is taken and
+# the old line limits are returned. If the scratch image pixels are stored in a
+# scratch image the pixels must be accessed sequentially, otherwise an
+# error is returned.
+
+pointer procedure dp_gst (dao, im, line1, line2, mode, flush)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+int line1 # the lower line limit
+int line2 # the upper line limit
+int mode # input / output mode
+int flush # flush the buffer
+
+int nx, ny, xoff, yoff, llast1, llast2
+pointer allstar
+
+begin
+ allstar = DP_ALLSTAR(dao)
+ if (DP_SBUF(allstar) == NULL) {
+ llast1 = 0
+ llast2 = 0
+ } else if (flush == YES) {
+ line1 = llast1
+ line2 = llast2
+ } else if ((line1 >= llast1) && (line2 <= llast2)) {
+ line1 = llast1
+ line2 = llast2
+ return (DP_SBUF(allstar))
+ } else if (line1 < llast1)
+ call error (0,
+ "ERROR: Attempting to access scratch image pixels randomly")
+
+ # All the data is cached.
+ if (DP_CACHE (allstar, A_SUBT) == YES) {
+
+ nx = IM_LEN(im,1)
+ ny = IM_LEN(im,2)
+ xoff = 1
+ yoff = 1
+ DP_SBUF(allstar) = DP_SUBT(allstar)
+
+ # Read in some new data.
+ } else if (mode == READ_ONLY) {
+
+ call dp_albufl2r (DP_SUBT(allstar), DP_SBUF(allstar),
+ llast1, llast2, line1, line2, flush)
+
+ if (flush == NO) {
+ nx = IM_LEN(im,1)
+ ny = line2 - line1 + 1
+ xoff = 1
+ yoff = line1
+ } else {
+ nx = 0
+ ny = 0
+ xoff = 0
+ yoff = 0
+ }
+
+ # Write out the old data and read in some new data.
+ } else if (mode == READ_WRITE) {
+
+ call dp_albufl2rw (DP_SUBT(allstar), DP_SUBT(allstar),
+ DP_SBUF(allstar), llast1, llast2, line1, line2, flush)
+
+ if (flush == NO) {
+ nx = IM_LEN(im,1)
+ ny = line2 - line1 + 1
+ xoff = 1
+ yoff = line1
+ } else {
+ nx = 0
+ ny = 0
+ xoff = 0
+ yoff = 0
+ }
+ }
+
+ # Update the required buffer parameters.
+ DP_SNX(allstar) = nx
+ DP_SNY(allstar) = ny
+ DP_SXOFF(allstar) = xoff
+ DP_SYOFF(allstar) = yoff
+
+ # Update the buffer description which is not currently used.
+ DP_SLX(allstar) = xoff
+ DP_SMX(allstar) = max (xoff + nx - 1, 0)
+ DP_SLY(allstar) = yoff
+ DP_SMY(allstar) = max (yoff + ny - 1, 0)
+
+ return (DP_SBUF(allstar))
+end
+
+
+# DP_GDC -- Return a pointer to the subtracted image pixels. The subtracted
+# image pixels pointer is assumed to be NULL on the initial all. If the new
+# line limits are totally contained within the old line limits no action is
+# taken and the old line limits are returned. If the subtracted image pixels are
+# stored in a scratch image the pixels must be accessed sequentially,
+# otherwise an error is returned.
+
+pointer procedure dp_gdc (dao, im, line1, line2, mode, flush)
+
+pointer dao # pointer to the daophot strucuture
+pointer im # pointer to the input image
+int line1, line2 # the upper and lower line limits
+int mode # input / output mode
+int flush # flush the input data
+
+int nx, ny, xoff, yoff, llast1, llast2
+pointer allstar
+
+begin
+ allstar = DP_ALLSTAR(dao)
+ if (DP_DBUF(allstar) == NULL) {
+ llast1 = 0
+ llast2 = 0
+ } else if (flush == YES) {
+ line1 = llast1
+ line2 = llast2
+ } else if ((line1 >= llast1) && (line2 <= llast2)) {
+ line1 = llast1
+ line2 = llast2
+ return (DP_DBUF(allstar))
+ } else if (line1 < llast1)
+ call error (0,
+ "ERROR: Attempting to access subtracted image pixels randomly")
+
+ # All the data is cached.
+ if (DP_CACHE (allstar, A_DCOPY) == YES) {
+
+ nx = IM_LEN(im,1)
+ ny = IM_LEN(im,2)
+ xoff = 1
+ yoff = 1
+ DP_DBUF(allstar) = DP_DATA(allstar)
+
+ # Read in some new data.
+ } else if (mode == READ_ONLY) {
+
+ call dp_albufl2r (DP_DATA(allstar), DP_DBUF(allstar),
+ llast1, llast2, line1, line2, flush)
+
+ if (flush == NO) {
+ nx = IM_LEN(im,1)
+ ny = line2 - line1 + 1
+ xoff = 1
+ yoff = line1
+ } else {
+ nx = 0
+ ny = 0
+ xoff = 0
+ yoff = 0
+ }
+
+ # Write out the old data and read in some new data.
+ } else if (mode == READ_WRITE) {
+
+ call dp_albufl2rw (DP_DATA(allstar), DP_DATA(allstar),
+ DP_DBUF(allstar), llast1, llast2, line1, line2, flush)
+
+ if (flush == NO) {
+ nx = IM_LEN(im,1)
+ ny = line2 - line1 + 1
+ xoff = 1
+ yoff = line1
+ } else {
+ nx = 0
+ ny = 0
+ xoff = 0
+ yoff = 0
+ }
+ }
+
+ # Update the required buffer parameters.
+ DP_DNX(allstar) = nx
+ DP_DNY(allstar) = ny
+ DP_DXOFF(allstar) = xoff
+ DP_DYOFF(allstar) = yoff
+
+ # Update the buffer definition which is currently not used.
+ DP_DLX(allstar) = xoff
+ DP_DMX(allstar) = max (xoff + nx - 1, 0)
+ DP_DLY(allstar) = yoff
+ DP_DMY(allstar) = max (yoff + ny - 1, 0)
+
+ return (DP_DBUF(allstar))
+end
+
+
+# DP_ALBUFL2RW -- Maintain a buffer of image lines and which can be read from
+# an input image and written to an output image. The input and output images
+# may be the same but must have the same dimensions. A new buffer is created
+# when the buffer pointer is null and reallocated when the buffer changes size.
+
+procedure dp_albufl2rw (inim, outim, buf, llast1, llast2, line1, line2, flush)
+
+pointer inim # the input image pointer
+pointer outim # the output image pointer
+pointer buf # pointer to the internal buffer
+int llast1, llast2 # the line limits of the previous buffer
+int line1, line2 # the line limits of the requested buffer
+int flush # flush the output buffer
+
+int i, ncols, nlines, nllast, lout, nmove
+pointer buf1, buf2
+pointer imgl2r(), impl2r()
+
+define flush_ 11
+
+begin
+ # Write the data in the buffer to the output image and free
+ # the buffer.
+
+ if (flush == YES)
+ go to flush_
+
+ # Define the size of the current buffer.
+ ncols = IM_LEN(inim,1)
+ nlines = line2 - line1 + 1
+
+ # If the buffer pointer is undefined then allocate memory for the
+ # buffer.
+
+ if (buf == NULL) {
+ call malloc (buf, ncols * nlines, TY_REAL)
+ llast1 = 0
+ llast2 = 0
+ nllast = 0
+ } else
+ nllast = llast2 - llast1 + 1
+
+ # Write out the lines that are not needed any more.
+
+ if ((line1 > llast1) && (llast1 > 0)) {
+ buf2 = buf
+ lout = min (llast2, line1 - 1)
+ do i = llast1, lout {
+ buf1 = impl2r (outim, i)
+ call amovr (Memr[buf2], Memr[buf1], ncols)
+ buf2 = buf2 + ncols
+ }
+ }
+
+ # Now move the remaining lines to the beginning of the buffer.
+
+ nmove = 0
+ if (llast2 >= line1) {
+ buf1 = buf
+ buf2 = buf + ncols * (line1 - llast1)
+ do i = line1, llast2 {
+ if (buf1 != buf2)
+ call amovr (Memr[buf2], Memr[buf1], ncols)
+ nmove = nmove + 1
+ buf2 = buf2 + ncols
+ buf1 = buf1 + ncols
+ }
+ }
+
+ # Resize the buffer if necessary.
+
+ if (nlines > nllast)
+ call realloc (buf, ncols * nlines, TY_REAL)
+
+ # Read only the image lines with are different from the last buffer.
+
+ if (line2 > llast2) {
+ buf1 = buf + ncols * nmove
+ lout = max (line1, llast2 + 1)
+ do i = lout, line2 {
+ buf2 = imgl2r (inim, i)
+ call amovr (Memr[buf2], Memr[buf1], ncols)
+ buf1 = buf1 + ncols
+ }
+ }
+
+ # Save the buffer parameters.
+ llast1 = line1
+ llast2 = line2
+
+ if (flush == NO)
+ return
+flush_
+ # Flush the remaining portion of the buffer to the output image
+ # and free the buffer space.
+
+ if (buf != NULL) {
+
+ buf2 = buf
+ do i = llast1, llast2 {
+ buf1 = impl2r (outim, i)
+ call amovr (Memr[buf2], Memr[buf1], ncols)
+ buf2 = buf2 + ncols
+ }
+ call imflush (outim)
+
+ call mfree (buf, TY_REAL)
+ }
+
+ buf = NULL
+end
+
+
+# DP_ALBUFL2R -- Maintain a buffer of image lines which can be read
+# sequentially from an input image. The buffer pointer must be initialized
+# to NULL. A new buffer is created when the buffer pointer is null and
+# reallocated when the buffer increases in size.
+
+procedure dp_albufl2r (inim, buf, llast1, llast2, line1, line2, flush)
+
+pointer inim # pointer to the input image
+pointer buf # pointer to the internal buffer
+int llast1, llast2 # the line limits of the previous buffer
+int line1, line2 # the line limits of the requested buffer
+int flush # flush the output buffer
+
+int i, ncols, nlines, nllast, lout, nmove
+pointer buf1, buf2
+pointer imgl2r()
+
+define flush_ 11
+
+begin
+
+ # Write the data in the buffer to the output image and free
+ # the buffer.
+
+ if (flush == YES)
+ go to flush_
+
+ # Define the size parameters for the new buffer.
+
+ ncols = IM_LEN(inim,1)
+ nlines = line2 - line1 + 1
+
+ # If the buffer pointer is undefined then allocate memory for the
+ # buffer.
+
+ if (buf == NULL) {
+ call malloc (buf, ncols * nlines, TY_REAL)
+ llast1 = 0
+ llast2 = 0
+ nllast = 0
+ } else
+ nllast = llast2 - llast1 + 1
+
+ # Now move the remaining lines to the beginning of the buffer.
+
+ nmove = 0
+ if (llast2 >= line1) {
+ buf1 = buf
+ buf2 = buf + ncols * (line1 - llast1)
+ do i = line1, llast2 {
+ if (buf1 != buf2)
+ call amovr (Memr[buf2], Memr[buf1], ncols)
+ nmove = nmove + 1
+ buf2 = buf2 + ncols
+ buf1 = buf1 + ncols
+ }
+ }
+
+ # Resize the buffer if necessary.
+
+ if (nlines > nllast)
+ call realloc (buf, ncols * nlines, TY_REAL)
+
+ # Read only the image lines with are different from the last buffer.
+
+ if (line2 > llast2) {
+ buf1 = buf + ncols * nmove
+ lout = max (line1, llast2 + 1)
+ do i = lout, line2 {
+ buf2 = imgl2r (inim, i)
+ call amovr (Memr[buf2], Memr[buf1], ncols)
+ buf1 = buf1 + ncols
+ }
+ }
+
+ # Save the buffer parameters.
+ llast1 = line1
+ llast2 = line2
+
+ if (flush == NO)
+ return
+flush_
+
+ # Free the buffer space.
+ if (buf != NULL)
+ call mfree (buf, TY_REAL)
+ buf = NULL
+end
diff --git a/noao/digiphot/daophot/allstar/dpaconfirm.x b/noao/digiphot/daophot/allstar/dpaconfirm.x
new file mode 100644
index 00000000..76e24798
--- /dev/null
+++ b/noao/digiphot/daophot/allstar/dpaconfirm.x
@@ -0,0 +1,37 @@
+include "../lib/daophotdef.h"
+
+# DP_ACONFIRM -- Procedure to confirm the critical allstar parameters.
+
+procedure dp_aconfirm (dao)
+
+pointer dao # pointer to the group structure
+
+int dp_stati()
+
+begin
+ call printf ("\n")
+
+ # Confirm the recentering and sky fitting parameters.
+ call dp_vrecenter (dao)
+ call dp_vgroupsky (dao)
+ call dp_vfitsky (dao)
+ if (dp_stati (dao, FITSKY) == YES) {
+ call dp_vsannulus (dao)
+ call dp_vwsannulus (dao)
+ }
+
+ # Confirm the psf radius.
+ call dp_vpsfrad (dao)
+
+ # Confirm the fitting radius.
+ call dp_vfitrad (dao)
+
+ # Confirm the maximum group size.
+ call dp_vmaxgroup (dao)
+
+ # Confirm the minimum and maximum good data values.
+ call dp_vdatamin (dao)
+ call dp_vdatamax (dao)
+
+ call printf ("\n")
+end
diff --git a/noao/digiphot/daophot/allstar/dpalinit.x b/noao/digiphot/daophot/allstar/dpalinit.x
new file mode 100644
index 00000000..4f1afb89
--- /dev/null
+++ b/noao/digiphot/daophot/allstar/dpalinit.x
@@ -0,0 +1,665 @@
+include <mach.h>
+include <imhdr.h>
+include <math.h>
+include "../lib/daophotdef.h"
+include "../lib/allstardef.h"
+
+# DP_SETWT -- Initialize the subtracted image and compute the initial weights
+# image from the input image.
+
+procedure dp_setwt (dao, im)
+
+pointer dao # pointer to daophot structure
+pointer im # input image decriptor
+
+int i, ncol, nline
+pointer sp, v1, v2, v3, v4, line1, line2, line3, line4
+pointer allstar, wtim, dataim, subtim
+real rdnoise, mingdata, maxgdata
+int imgnlr(), impnlr()
+
+begin
+ # Allocate some working space.
+ call smark (sp)
+ call salloc (v1, IM_MAXDIM, TY_LONG)
+ call salloc (v2, IM_MAXDIM, TY_LONG)
+ call salloc (v3, IM_MAXDIM, TY_LONG)
+ call salloc (v4, IM_MAXDIM, TY_LONG)
+
+ # Define the allstar pointer.
+ allstar = DP_ALLSTAR (dao)
+
+ # Define some useful constants.
+ rdnoise = (DP_READNOISE(dao) / DP_PHOTADU(dao)) ** 2
+ if (IS_INDEFR(DP_MINGDATA(dao)))
+ mingdata = -MAX_REAL
+ else
+ mingdata = DP_MINGDATA(dao)
+ if (IS_INDEFR(DP_MAXGDATA(dao)))
+ maxgdata = MAX_REAL
+ else
+ maxgdata = DP_MAXGDATA(dao)
+
+ wtim = DP_WEIGHTS (allstar)
+ dataim = DP_DATA(allstar)
+ subtim = DP_SUBT(allstar)
+ ncol = IM_LEN (im,1)
+ nline = IM_LEN(im,2)
+
+ call amovkl (long(1), Meml[v1], IM_MAXDIM)
+ call amovkl (long(1), Meml[v2], IM_MAXDIM)
+ call amovkl (long(1), Meml[v3], IM_MAXDIM)
+ call amovkl (long(1), Meml[v4], IM_MAXDIM)
+ do i = 1, nline {
+
+ # Get the next line
+ if (imgnlr (im, line1, Meml[v1]) == EOF)
+ break
+
+ # Initialize the subtracted image.
+ if (DP_CACHE(allstar, A_DCOPY) == YES) {
+ call amovr (Memr[line1], Memr[dataim], ncol)
+ dataim = dataim + ncol
+ } else if (impnlr (dataim, line2, Meml[v2]) != EOF) {
+ call amovr (Memr[line1], Memr[line2], ncol)
+ }
+
+ # Initialize the weights image.
+ if (DP_CACHE(allstar, A_WEIGHT) == YES) {
+ call dp_wtvector (Memr[line1], Memr[wtim], ncol, mingdata,
+ maxgdata, rdnoise)
+ wtim = wtim + ncol
+ } else if (impnlr (wtim, line3, Meml[v3]) != EOF) {
+ call dp_wtvector (Memr[line1], Memr[line3], ncol, mingdata,
+ maxgdata, rdnoise)
+ }
+
+ # Initilize the subtracted image.
+ if (DP_CACHE(allstar, A_WEIGHT) == YES) {
+ ;
+ } else if (impnlr (subtim, line4, Meml[v4]) != EOF) {
+ call amovkr (0.0, Memr[line4], ncol)
+ }
+
+ }
+
+ # Make sure all the changes are written to disk.
+ if (DP_CACHE(allstar, A_WEIGHT) == NO)
+ call imflush (DP_WEIGHTS(allstar))
+ if (DP_CACHE(allstar, A_DCOPY) == NO)
+ call imflush (DP_DATA(allstar))
+ if (DP_CACHE(allstar, A_SUBT) == NO)
+ call imflush (DP_SUBT(allstar))
+
+ call sfree (sp)
+end
+
+
+# DP_WTVECTOR -- Compute the initial weights for a vector of input data.
+
+procedure dp_wtvector (a, b, ncols, mingdata, maxgdata, rnoisesq)
+
+real a[ARB] # input array
+real b[ARB] # output array
+int ncols # number of points
+real mingdata # minimum good data value
+real maxgdata # maximum good data value
+real rnoisesq # read noise squared in adu
+
+int i
+
+begin
+ do i = 1, ncols {
+ if (a[i] < mingdata || a[i] > maxgdata)
+ b[i] = -MAX_REAL
+ else
+ b[i] = rnoisesq
+ }
+end
+
+
+define DELTA_MAG 12.5
+define INIT_REL_BRIGHT 0.003
+
+# DP_ALZERO -- Convert from magnitudes to relative brightnesses before
+# fitting the stars. If the star's magnitude is undefined or more than
+# 12.5 magnitudes fainter than the PSF magnitude, a default relative
+# brightness is defined.
+
+procedure dp_alzero (dao, mag, nstars)
+
+pointer dao # pointer to the daophot strucuture
+real mag[ARB] # the magnitude array
+int nstars # number of stars
+
+int i
+pointer psffit
+real faint
+
+begin
+ psffit = DP_PSFFIT (dao)
+ faint = DP_PSFMAG(psffit) + DELTA_MAG
+
+ do i = 1, nstars {
+ if (IS_INDEFR(mag[i])) {
+ mag[i] = INIT_REL_BRIGHT
+ } else if (mag[i] >= faint) {
+ mag[i] = INIT_REL_BRIGHT
+ } else {
+ mag[i] = DAO_RELBRIGHT (psffit, mag[i])
+ }
+ }
+end
+
+
+# DP_STRIP -- Remove stars with undefined centers, stars with centers that
+# are off the input image, and duplicate stars from the input photometry
+# list, where duplicate stars are defined as those within a distance of
+# radius pixels of each other. The duplicate stars are moved to the end of
+# the star list and the number of stars is recomputed.
+
+procedure dp_strip (id, x, y, mag, sky, skip, aier, nstar, sepradsq, ncol,
+ nline, fitradius, verbose)
+
+int id[ARB] # array of star ids
+real x[ARB] # array of star x values
+real y[ARB] # array of star y values
+real mag[ARB] # array of star magnitudes
+real sky[ARB] # array of star sky values
+int skip[ARB] # array of fit/nofit indicators
+int aier[ARB] # array of error codes
+int nstar # number of stars (may change)
+real sepradsq # separation radius squared
+int ncol # number of columns in the image
+int nline # number of columns in the image
+real fitradius # the fitting radius
+int verbose # print error messages ?
+
+int i, j, ier, ahold
+pointer sp, index, idhold
+real seprad, dx, dy, xhold, yhold, maghold, skyhold
+
+begin
+ # Duplicate stars are impossible.
+ if (nstar <= 1)
+ return
+
+ # Allocate some working space.
+ call smark (sp)
+ call salloc (index, nstar, TY_INT)
+
+ # Sort the data in y.
+ call quick (y, nstar, Memi[index], ier)
+
+ # Rectify the remaining arrays.
+ call dp_irectify (id, Memi[index], nstar)
+ call dp_rectify (x, Memi[index], nstar)
+ call dp_rectify (mag, Memi[index], nstar)
+ call dp_rectify (sky, Memi[index], nstar)
+
+ # Determine whether any stars are close to star i.
+ seprad = sqrt (sepradsq)
+ do i = 1, nstar - 1 {
+
+ # This star was rejected on a previous loop.
+ if (skip[i] == YES)
+ next
+
+ # Reject if star has an INDEF valued position or is off image.
+ if (IS_INDEFR(x[i]) || IS_INDEFR(y[i])) {
+ mag[i] = INDEFR
+ skip[i] = YES
+ aier[i] = ALLERR_OFFIMAGE
+ if (verbose == YES)
+ call printf (
+ "REJECTING: Star %d has an undefined x or y value\n")
+ call pargi (id[i])
+ } else if ((int (x[i] - fitradius) + 1) > ncol) {
+ mag[i] = INDEFR
+ skip[i] = YES
+ aier[i] = ALLERR_OFFIMAGE
+ if (verbose == YES)
+ call printf ("REJECTING: Star %d is outside the image\n")
+ call pargi (id[i])
+ } else if (int (x[i] + fitradius) < 1) {
+ mag[i] = INDEFR
+ skip[i] = YES
+ aier[i] = ALLERR_OFFIMAGE
+ if (verbose == YES)
+ call printf ("REJECTING: Star %d is outside the image\n")
+ call pargi (id[i])
+ } else if ((int (y[i] - fitradius) + 1) > nline) {
+ mag[i] = INDEFR
+ skip[i] = YES
+ aier[i] = ALLERR_OFFIMAGE
+ if (verbose == YES)
+ call printf ("REJECTING: Star %d is outside the image\n")
+ call pargi (id[i])
+ } else if (int (y[i] + fitradius) < 1) {
+ mag[i] = INDEFR
+ skip[i] = YES
+ aier[i] = ALLERR_OFFIMAGE
+ if (verbose == YES)
+ call printf ("REJECTING: Star %d is outside the image\n")
+ call pargi (id[i])
+ }
+
+ # This star was rejected on this loop.
+ if (skip[i] == YES)
+ next
+
+ # Loop over the remaining stars.
+ do j = i + 1, nstar {
+
+ # Star has already been rejected on previous loop.
+ if (skip[j] == YES)
+ next
+
+ # Test for INDEF.
+ if (IS_INDEFR(x[j]) || IS_INDEFR(y[j])) {
+ mag[j] = INDEFR
+ skip[j] = YES
+ aier[j] = ALLERR_OFFIMAGE
+ if (verbose == YES)
+ call printf (
+ "REJECTING: Star %d has an undefined x or y value\n")
+ call pargi (id[j])
+ } else if ((int (x[j] - fitradius) + 1) > ncol) {
+ mag[j] = INDEFR
+ skip[j] = YES
+ aier[j] = ALLERR_OFFIMAGE
+ if (verbose == YES)
+ call printf (
+ "REJECTING: Star %d is outside the image\n")
+ call pargi (id[j])
+ } else if (int (x[j] + fitradius) < 1) {
+ mag[j] = INDEFR
+ skip[j] = YES
+ aier[j] = ALLERR_OFFIMAGE
+ if (verbose == YES)
+ call printf (
+ "REJECTING: Star %d is outside the image\n")
+ call pargi (id[j])
+ } else if ((int (y[j] - fitradius) + 1) > nline) {
+ mag[j] = INDEFR
+ skip[j] = YES
+ aier[j] = ALLERR_OFFIMAGE
+ if (verbose == YES)
+ call printf (
+ "REJECTING: Star %d is outside the image\n")
+ call pargi (id[j])
+ } else if (int (y[j] + fitradius) < 1) {
+ mag[j] = INDEFR
+ skip[j] = YES
+ aier[j] = ALLERR_OFFIMAGE
+ if (verbose == YES)
+ call printf (
+ "REJECTING: Star %d is outside the image\n")
+ call pargi (id[j])
+ }
+
+ # Star was rejected.
+ if (skip[j] == YES)
+ next
+
+ # Test for proximity.
+ dy = y[j] - y[i]
+ if (dy > seprad)
+ break
+ dx = x[j] - x[i]
+ if (abs (dx) > seprad)
+ next
+ if ((dx * dx + dy * dy) > sepradsq)
+ next
+
+ # Set the magnitude of the star to INDEF and skip.
+ if (mag[j] <= mag[i]) {
+ mag[j] = INDEFR
+ skip[j] = YES
+ aier[j] = ALLERR_MERGE
+ if (verbose == YES) {
+ call printf (
+ "REJECTING: Star %d has merged with star %d\n")
+ call pargi (id[j])
+ call pargi (id[i])
+ }
+ } else {
+ mag[i] = INDEFR
+ skip[i] = YES
+ aier[i] = ALLERR_MERGE
+ if (verbose == YES) {
+ call printf (
+ "REJECTING: Star %d has merged with star %d\n")
+ call pargi (id[i])
+ call pargi (id[j])
+ }
+ break
+ }
+ }
+ }
+
+ # Remove the duplicate stars.
+ for (i = 1; i <= nstar; i = i + 1) {
+
+ # Redefine the number of stars by removing skipped stars from
+ # the end of the star list.
+ while (nstar >= 1) {
+ if (skip[nstar] == NO)
+ break
+ nstar = nstar - 1
+ }
+ if (i > nstar)
+ break
+ if (skip[i] == NO)
+ next
+
+ # Switch the rejected star with the one at the end of the list.
+ idhold = id[i]
+ xhold = x[i]
+ yhold = y[i]
+ maghold = mag[i]
+ skyhold = sky[i]
+ ahold = aier[i]
+
+ id[i] = id[nstar]
+ x[i] = x[nstar]
+ y[i] = y[nstar]
+ mag[i] = mag[nstar]
+ sky[i] = sky[nstar]
+ skip[i] = NO
+ aier[i] = aier[nstar]
+
+ id[nstar] = idhold
+ x[nstar] = xhold
+ y[nstar] = yhold
+ mag[nstar] = maghold
+ sky[nstar] = skyhold
+ skip[nstar] = YES
+ aier[nstar] = ahold
+
+ nstar = nstar - 1
+ }
+
+ call sfree (sp)
+end
+
+
+# DP_WSTINIT -- Initialize the weight and scratch arrays / images.
+
+procedure dp_wstinit (dao, im, xcen, ycen, mag, nstar, radius, x1, x2, y1, y2)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+real xcen[ARB] # the x centers array
+real ycen[ARB] # the y centers array
+real mag[ARB] # the magnitude array
+int nstar # the number of stars
+real radius # radius for subraction
+int x1, x2 # column limits
+int y1, y2 # line limits
+
+int j, l, ncol, npix, nl, ns, lx, mx
+pointer psffit, allstar, databuf, wtbuf, owtbuf, subtbuf
+real rsq, psfradius, psfradsq, x, y, dy, dysq, deltax, deltay
+pointer imgs2r(), imps2r()
+
+begin
+ # Set up some pointers.
+ psffit = DP_PSFFIT(dao)
+ allstar = DP_ALLSTAR(dao)
+
+ # Set up some constants.
+ ncol = IM_LEN(im,1)
+ npix = x2 - x1 + 1
+ rsq = radius ** 2
+ if (DP_PSFSIZE(psffit) == 0)
+ psfradius = DP_PSFRAD(dao)
+ else
+ psfradius = (real (DP_PSFSIZE(psffit) - 1) / 2.0 - 1.0) / 2.0
+ psfradsq = psfradius * psfradius
+
+ # Begin the search of the groups at the first group.
+ ns = 0
+ nl = 0
+
+ ns = 0
+ do j = y1, y2 {
+
+ # Get the data.
+ if (DP_CACHE(allstar,A_DCOPY) == YES)
+ databuf = DP_DATA(allstar) + (j - 1) * ncol + x1 - 1
+ else
+ databuf = imgs2r (DP_DATA(allstar), x1, x2, j, j)
+ if (DP_CACHE(allstar,A_WEIGHT) == YES) {
+ wtbuf = DP_WEIGHTS(allstar) + (j - 1) * ncol + x1 - 1
+ owtbuf = wtbuf
+ } else {
+ owtbuf = imps2r (DP_WEIGHTS(allstar), x1, x2, j, j)
+ wtbuf = imgs2r (DP_WEIGHTS(allstar), x1, x2, j, j)
+ }
+ if (DP_CACHE(allstar,A_SUBT) == YES)
+ subtbuf = DP_SUBT(allstar) + (j - 1) * ncol + x1 - 1
+ else
+ subtbuf = imps2r (DP_SUBT(allstar), x1, x2, j, j)
+
+ # Set all the weights in the working array negative.
+ call aabsr (Memr[wtbuf], Memr[owtbuf], npix)
+ call anegr (Memr[owtbuf], Memr[owtbuf], npix)
+ call amovkr (0.0, Memr[subtbuf], npix)
+
+ # Set the y coordinate.
+ y = real (j)
+
+ # Initialize the weight and scratch arrays.
+
+ # Find all the points within one working radius of each star.
+ # Set all the sigmas positive again and copy them from DATA
+ # to SUBT.
+ do l = ns + 1, nstar {
+ dy = y - ycen[l]
+ if (dy > radius) {
+ ns = l
+ next
+ } else if (dy < -radius)
+ break
+ dysq = dy ** 2
+ lx = max (x1, min (x2, int (xcen[l] - radius) + 1))
+ mx = max (x1, min (x2, int (xcen[l] + radius)))
+ x = xcen[l] - lx + 1.0
+ lx = lx - x1 + 1
+ mx = mx - x1 + 1
+ call dp_wstvector (x, Memr[databuf+lx-1], Memr[owtbuf+lx-1],
+ Memr[subtbuf+lx-1], mx - lx + 1, dysq, rsq, -MAX_REAL)
+ }
+
+ do l = nl + 1, nstar {
+ dy = y - ycen[l]
+ if (dy > psfradius) {
+ nl = l
+ next
+ } else if (dy < -psfradius)
+ break
+ dysq = dy ** 2
+ lx = max (x1, min (x2, int (xcen[l] - psfradius) + 1))
+ mx = max (x1, min (x2, int (xcen[l] + psfradius)))
+ x = xcen[l] - lx + 1.0
+ lx = lx - x1 + 1
+ mx = mx - x1 + 1
+ call dp_wpsf (dao, im, xcen[l], ycen[l], deltax, deltay, 1)
+ deltax = (deltax - 1.0) / DP_PSFX(psffit) - 1.0
+ deltay = (deltay - 1.0) / DP_PSFY(psffit) - 1.0
+ call dp_alsubstar (psffit, x, dy, deltax, deltay, mag[l],
+ Memr[subtbuf+lx-1], Memr[owtbuf+lx-1], mx - lx + 1, dysq,
+ psfradsq)
+ }
+ }
+
+ if (DP_CACHE(allstar,A_WEIGHT) == NO)
+ call imflush (DP_WEIGHTS(allstar))
+ if (DP_CACHE(allstar,A_SUBT) == NO)
+ call imflush (DP_SUBT(allstar))
+end
+
+
+# DP_WSTVECTOR -- Set the weight and scratch vector
+
+procedure dp_wstvector (xcen, data, weight, subt, npix, dysq, rsq, badwt)
+
+real xcen # x coordinate of center
+real data[ARB] # the data array
+real weight[ARB] # the weight array
+real subt[ARB] # the subtracted array array
+int npix # the number of pixels
+real dysq # the y distance squared
+real rsq # the inclusion radius squared
+real badwt # badwt value
+
+int i
+real dx
+
+begin
+ do i = 1, npix {
+ dx = (real (i) - xcen)
+ if ((dx ** 2 + dysq) <= rsq) {
+ if (weight[i] <= badwt)
+ next
+ weight[i] = abs (weight[i])
+ subt[i] = data[i]
+ } else if (dx >= 0.0)
+ break
+ }
+end
+
+
+# DP_ALSUBSTAR -- The subtraction vector.
+
+procedure dp_alsubstar (psffit, xcen, dy, deltax, deltay, mag, subt, weight,
+ npix, dysq, psfradsq)
+
+pointer psffit # pointer to the psf fitting structure
+real xcen # x coordinate of center
+real dy # y offset from psf center
+real deltax # x distance from psf position
+real deltay # y distance from psf position
+real mag # the magnitude of the star
+real subt[ARB] # the subtracted array array
+real weight[ARB] # the weight array
+int npix # the number of pixels
+real dysq # the y distance squared
+real psfradsq # the inclusion radius squared
+
+int i
+real dx, dvdxc, dvdyc
+real dp_usepsf()
+
+begin
+ do i = 1, npix {
+ if (weight[i] < 0.0)
+ next
+ dx = real (i) - xcen
+ if ((dx ** 2 + dysq) < psfradsq) {
+ subt[i] = subt[i] - mag * dp_usepsf (DP_PSFUNCTION(psffit),
+ dx, dy, DP_PSFHEIGHT(psffit), Memr[DP_PSFPARS(psffit)],
+ Memr[DP_PSFLUT(psffit)], DP_PSFSIZE(psffit),
+ DP_NVLTABLE(psffit), DP_NFEXTABLE(psffit), deltax, deltay,
+ dvdxc, dvdyc)
+ } else if (dx > 0.0)
+ break
+ }
+end
+
+
+# DP_ALSKY -- Recompute the sky values.
+
+procedure dp_alsky (dao, im, xcen, ycen, sky, nstar, x1, x2, y1, y2, rinsky,
+ routsky, minnsky, badwt)
+
+pointer dao # pointer to the daophot structure
+int im # the input image pointer
+real xcen[ARB] # x coordinates
+real ycen[ARB] # y coordinates
+real sky[ARB] # sky values
+int nstar # number of stars
+int x1, x2 # coordinate limits
+int y1, y2 # coordinate limits
+real rinsky # inner radius of the sky annulus
+real routsky # outer radius of the sky annulus
+int minnsky # minimum number of sky pixels
+real badwt # the bad weight value
+
+int istar, i, j, ncols, lenskybuf, lx, mx, ly, my, line1, line2, nsky, ier
+pointer allstar, sub, psub, wgt, pwgt, skyvals, index
+real risq, rosq, dannulus, dysq, dx, rsq
+pointer dp_gst(), dp_gwt()
+
+begin
+ # Get the allstar pointer.
+ allstar = DP_ALLSTAR(dao)
+
+ # Define some constants
+ ncols = IM_LEN(im,1)
+ risq = rinsky ** 2
+ rosq = routsky ** 2
+ dannulus = routsky - rinsky
+
+ # Allcoate some working memory.
+ lenskybuf = PI * (2.0 * rinsky + dannulus + 1.0) * (dannulus + 0.5)
+ call malloc (skyvals, lenskybuf, TY_REAL)
+ call malloc (index, lenskybuf, TY_INT)
+
+ # Accumulate the sky buffer.
+ do istar = 1, nstar {
+
+ # Get the data.
+ lx = max (x1, min (x2, int (xcen[istar] - routsky) + 1))
+ mx = max (x1, min (x2, int (xcen[istar] + routsky)))
+ ly = max (y1, min (y2, int (ycen[istar] - routsky) + 1))
+ my = max (y1, min (y2, int (ycen[istar] + routsky)))
+ line1 = ly
+ line2 = my
+ sub = dp_gst (dao, im, line1, line2, READ_ONLY, NO)
+ wgt = dp_gwt (dao, im, line1, line2, READ_ONLY, NO)
+
+ nsky = 0
+ psub = sub + (ly - DP_SYOFF(allstar)) * ncols
+ pwgt = wgt + (ly - DP_WYOFF(allstar)) * ncols
+ do j = ly, my {
+ dysq = (real (j) - ycen[istar]) ** 2
+ do i = lx, mx {
+ dx = (real (i) - xcen[istar])
+ rsq = dx ** 2 + dysq
+ if (rsq > rosq) {
+ if (dx > 0.0)
+ break
+ else
+ next
+ }
+ if (rsq < risq)
+ next
+ if (Memr[pwgt+i-1] <= badwt)
+ next
+ Memr[skyvals+nsky] = Memr[psub+i-1]
+ nsky = nsky + 1
+ }
+ psub = psub + ncols
+ pwgt = pwgt + ncols
+ }
+
+ # Compute the new sky value.
+ if (nsky > minnsky) {
+ call quick (Memr[skyvals], nsky, Memi[index], ier)
+ j = nint (0.2 * nsky)
+ dx = 0.0
+ do i = (nsky + 1) / 2 - j, (nsky / 2) + j + 1
+ dx = dx + Memr[skyvals+i-1]
+ sky[istar] = dx / real ((nsky / 2) + 2 * j + 2 -
+ (nsky + 1) / 2)
+ }
+ }
+
+
+ call mfree (skyvals, TY_REAL)
+ call mfree (index, TY_INT)
+ sub = dp_gst (dao, im, line1, line2, READ_ONLY, YES)
+ wgt = dp_gwt (dao, im, line1, line2, READ_ONLY, YES)
+end
diff --git a/noao/digiphot/daophot/allstar/dpalmemstar.x b/noao/digiphot/daophot/allstar/dpalmemstar.x
new file mode 100644
index 00000000..fd9ee80e
--- /dev/null
+++ b/noao/digiphot/daophot/allstar/dpalmemstar.x
@@ -0,0 +1,182 @@
+include "../lib/daophotdef.h"
+include "../lib/allstardef.h"
+
+# DP_ALLSTARSETUP -- Procedure to set up the ALLSTAR parameters.
+
+procedure dp_allstarsetup (dp)
+
+pointer dp # pointer to daophot structure
+
+pointer allstar
+
+begin
+ # Allocate memory.
+ call malloc (DP_ALLSTAR(dp), LEN_ALLSTARSTRUCT, TY_STRUCT)
+ allstar = DP_ALLSTAR(dp)
+
+ DP_DATA(allstar) = NULL
+ DP_SUBT(allstar) = NULL
+ DP_WEIGHTS(allstar) = NULL
+ DP_DBUF(allstar) = NULL
+ DP_SBUF(allstar) = NULL
+ DP_WBUF(allstar) = NULL
+
+ DP_ANUMER(allstar) = NULL
+ DP_ADENOM(allstar) = NULL
+ DP_ASUMWT(allstar) = NULL
+ DP_ARPIXSQ(allstar) = NULL
+ DP_ASKIP(allstar) = NULL
+ DP_AXCLAMP(allstar) = NULL
+ DP_AYCLAMP(allstar) = NULL
+ DP_AXOLD(allstar) = NULL
+ DP_AYOLD(allstar) = NULL
+ DP_AX(allstar) = NULL
+ DP_AV(allstar) = NULL
+ DP_AC(allstar) = NULL
+ DP_ALAST(allstar) = NULL
+ DP_ANPIX(allstar) = NULL
+ DP_AIER(allstar) = NULL
+end
+
+
+# DP_ALMEMSTAR -- Procedure to allocate sufficient memory for ALLSTAR.
+
+procedure dp_almemstar (dao, max_star, max_group)
+
+pointer dao # pointer to daophot structure
+int max_star # maximum number of stars
+int max_group # maximum group size
+
+pointer allstar
+
+begin
+ allstar = DP_ALLSTAR(dao)
+
+ if (DP_ANUMER (allstar) != NULL)
+ call mfree (DP_ANUMER (allstar), TY_REAL)
+ call malloc (DP_ANUMER (allstar), max_star, TY_REAL)
+
+ if (DP_ADENOM (allstar) != NULL)
+ call mfree (DP_ADENOM (allstar), TY_REAL)
+ call malloc (DP_ADENOM (allstar), max_star, TY_REAL)
+
+ if (DP_ARPIXSQ (allstar) != NULL)
+ call mfree (DP_ARPIXSQ (allstar), TY_REAL)
+ call malloc (DP_ARPIXSQ (allstar), max_star, TY_REAL)
+
+ if (DP_ASUMWT (allstar) != NULL)
+ call mfree (DP_ASUMWT (allstar), TY_REAL)
+ call malloc (DP_ASUMWT (allstar), max_star, TY_REAL)
+
+ if (DP_ANPIX (allstar) != NULL)
+ call mfree (DP_ANPIX (allstar), TY_INT)
+ call malloc (DP_ANPIX (allstar), max_star, TY_INT)
+
+ if (DP_AIER (allstar) != NULL)
+ call mfree (DP_AIER (allstar), TY_INT)
+ call malloc (DP_AIER (allstar), max_star, TY_INT)
+
+ if (DP_ASKIP (allstar) != NULL)
+ call mfree (DP_ASKIP (allstar), TY_INT)
+ call malloc (DP_ASKIP (allstar), max_star, TY_INT)
+
+ if (DP_ALAST (allstar) != NULL)
+ call mfree (DP_ALAST (allstar), TY_INT)
+ call malloc (DP_ALAST (allstar), max_star, TY_INT)
+
+ if (DP_AXCLAMP (allstar) != NULL)
+ call mfree (DP_AXCLAMP (allstar), TY_REAL)
+ call malloc (DP_AXCLAMP (allstar), max_star, TY_REAL)
+
+ if (DP_AYCLAMP (allstar) != NULL)
+ call mfree (DP_AYCLAMP (allstar), TY_REAL)
+ call malloc (DP_AYCLAMP (allstar), max_star, TY_REAL)
+
+ if (DP_AXOLD (allstar) != NULL)
+ call mfree (DP_AXOLD (allstar), TY_REAL)
+ call malloc (DP_AXOLD (allstar), max_star, TY_REAL)
+
+ if (DP_AYOLD (allstar) != NULL)
+ call mfree (DP_AYOLD (allstar), TY_REAL)
+ call malloc (DP_AYOLD (allstar), max_star, TY_REAL)
+
+ # Allocate space for the fitting matrices. Note that nine
+ # times less space is required if recentering is turned
+ # off.
+ if (DP_RECENTER(dao) == YES) {
+
+ if (DP_AX (allstar) != NULL)
+ call mfree (DP_AX (allstar), TY_REAL)
+ call malloc (DP_AX (allstar), 3 * max_group + 1, TY_REAL)
+
+ if (DP_AV (allstar) != NULL)
+ call mfree (DP_AV (allstar), TY_REAL)
+ call malloc (DP_AV (allstar), 3 * max_group + 1, TY_REAL)
+
+ if (DP_AC (allstar) != NULL)
+ call mfree (DP_AC (allstar), TY_REAL)
+ call malloc (DP_AC (allstar), (3 * max_group + 1) *
+ (3 * max_group + 1), TY_REAL)
+
+ } else {
+
+ if (DP_AX (allstar) != NULL)
+ call mfree (DP_AX (allstar), TY_REAL)
+ call malloc (DP_AX (allstar), max_group + 1, TY_REAL)
+
+ if (DP_AV (allstar) != NULL)
+ call mfree (DP_AV (allstar), TY_REAL)
+ call malloc (DP_AV (allstar), max_group + 1, TY_REAL)
+
+ if (DP_AC (allstar) != NULL)
+ call mfree (DP_AC (allstar), TY_REAL)
+ call malloc (DP_AC (allstar), (max_group + 1) * (max_group + 1),
+ TY_REAL)
+ }
+end
+
+
+# DP_ALCLOSE -- Procedure to close up the ALLSTAR parameters.
+
+procedure dp_alclose (dp)
+
+pointer dp # pointer to daophot structure
+
+pointer allstar
+
+begin
+ allstar = DP_ALLSTAR(dp)
+
+ if (DP_ANUMER (allstar) != NULL)
+ call mfree (DP_ANUMER (allstar), TY_REAL)
+ if (DP_ADENOM (allstar) != NULL)
+ call mfree (DP_ADENOM (allstar), TY_REAL)
+ if (DP_ARPIXSQ (allstar) != NULL)
+ call mfree (DP_ARPIXSQ (allstar), TY_REAL)
+ if (DP_ASUMWT (allstar) != NULL)
+ call mfree (DP_ASUMWT (allstar), TY_REAL)
+ if (DP_ASKIP (allstar) != NULL)
+ call mfree (DP_ASKIP (allstar), TY_INT)
+ if (DP_ALAST (allstar) != NULL)
+ call mfree (DP_ALAST (allstar), TY_INT)
+ if (DP_AXCLAMP (allstar) != NULL)
+ call mfree (DP_AXCLAMP (allstar), TY_REAL)
+ if (DP_AYCLAMP (allstar) != NULL)
+ call mfree (DP_AYCLAMP (allstar), TY_REAL)
+ if (DP_AXOLD (allstar) != NULL)
+ call mfree (DP_AXOLD (allstar), TY_REAL)
+ if (DP_AYOLD (allstar) != NULL)
+ call mfree (DP_AYOLD (allstar), TY_REAL)
+ if (DP_AX (allstar) != NULL)
+ call mfree (DP_AX (allstar), TY_REAL)
+ if (DP_AV (allstar) != NULL)
+ call mfree (DP_AV (allstar), TY_REAL)
+ if (DP_AC (allstar) != NULL)
+ call mfree (DP_AC (allstar), TY_REAL)
+ if (DP_ANPIX (allstar) != NULL)
+ call mfree (DP_ANPIX (allstar), TY_INT)
+ if (DP_AIER (allstar) != NULL)
+ call mfree (DP_AIER (allstar), TY_INT)
+
+ call mfree (allstar, TY_STRUCT)
+end
diff --git a/noao/digiphot/daophot/allstar/dpalphot.x b/noao/digiphot/daophot/allstar/dpalphot.x
new file mode 100644
index 00000000..74741958
--- /dev/null
+++ b/noao/digiphot/daophot/allstar/dpalphot.x
@@ -0,0 +1,1438 @@
+include <mach.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/allstardef.h"
+
+# DP_ALPHOT -- Perform one iteration on each group of stars.
+
+int procedure dp_alphot (dao, im, ntot, istar, niter, sepcrit, sepmin, wcrit,
+ clip, clampmax, version)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+int ntot # the total number of stars left unfit
+int istar # first star in the current group
+int niter # the current iteration
+real sepcrit # critical separation for merging
+real sepmin # minimum separation for merging
+real wcrit # the critical error for merging
+bool clip # clip the data
+real clampmax # maximum clamping factor
+int version # version number
+
+bool regroup
+int cdimen, lstar, nstar, fstar, nterm, ixmin, ixmax, iymin, iymax
+int fixmin, fixmax, fiymin, fiymax, nxpix, nypix, flag, i, j, k, ifaint
+pointer apsel, psffit, allstar, data, subt, weights
+real radius, totradius, mean_sky, pererr, peakerr, faint
+real xmin, xmax, ymin, ymax, sumres, grpwt, chigrp
+
+bool dp_alredo(), dp_checkc(), dp_almerge(), dp_alclamp(), dp_alfaint()
+int dp_laststar(), dp_delfaintest()
+pointer dp_gwt(), dp_gst(), dp_gdc()
+real dp_almsky(), asumr()
+
+begin
+ # Get some daophot pointers.
+ psffit = DP_PSFFIT (dao)
+ apsel = DP_APSEL(dao)
+ allstar = DP_ALLSTAR (dao)
+
+ # Define some constants. At some point these should be stored
+ # in the allstar structure at task initialization. When the final
+ # rewrite gets done this will occur.
+
+ radius = DP_FITRAD(dao)
+ totradius = DP_FITRAD(dao) + DP_PSFRAD(dao) + 1
+ if (DP_RECENTER(dao) == YES)
+ cdimen = 3 * DP_MAXGROUP(dao) + 1
+ else
+ cdimen = DP_MAXGROUP(dao) + 1
+ pererr = 0.01 * DP_FLATERR(dao)
+ peakerr = 0.01 * DP_PROFERR(dao) / (Memr[DP_PSFPARS(psffit)] *
+ Memr[DP_PSFPARS(psffit)+1])
+ regroup = false
+
+ repeat {
+
+ # Given the last star arrary as computed by dp_regroup, the first
+ # star in the current group, and the total number of stars,
+ # find the last star in the current group and compute the
+ # total number of stars in the group.
+
+ lstar = dp_laststar (Memi[DP_ALAST(allstar)], istar, ntot)
+ nstar = lstar - istar + 1
+
+ # Don't compute the subraster limits if no regroup has been
+ # performed.
+ if (! regroup) {
+ call alimr (Memr[DP_APXCEN(apsel)+istar-1], nstar, xmin, xmax)
+ call alimr (Memr[DP_APYCEN(apsel)+istar-1], nstar, ymin, ymax)
+ }
+
+ # Determine whether the group is too large to be fit.
+
+ if (nstar > DP_MAXGROUP (dao)) {
+
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (
+ "Group too large: %5d Fitting Radius: %5.2f Regrouping\n")
+ call pargi (nstar)
+ call pargr (radius)
+ }
+
+ # If size of group too small go to next group.
+ radius = RADIUS_FRACTION * radius
+ if ((DP_RECENTER(dao) == YES) && (niter >= 2)) {
+ if (radius < DENSE_RADIUS1) {
+ fstar = dp_delfaintest (Memr[DP_APMAG(apsel)], istar,
+ lstar)
+ Memr[DP_APMAG(apsel)+fstar-1] = INDEFR
+ Memi[DP_ASKIP(allstar)+fstar-1] = YES
+ Memi[DP_AIER(allstar)+fstar-1] = ALLERR_BIGGROUP
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (
+ "REJECTING: Star ID: %d Group too dense to reduce\n")
+ call pargi (Memi[DP_APID(apsel)+fstar-1])
+ }
+ return (lstar)
+ }
+ } else {
+ if (radius < DENSE_RADIUS2) {
+ fstar = dp_delfaintest (Memr[DP_APMAG(apsel)], istar,
+ lstar)
+ Memr[DP_APMAG(apsel)+fstar-1] = INDEFR
+ Memi[DP_ASKIP(allstar)+fstar-1] = YES
+ Memi[DP_AIER(allstar)+fstar-1] = ALLERR_BIGGROUP
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (
+ "REJECTING: Star ID: %d Group too dense to reduce\n")
+ call pargi (Memi[DP_APID(apsel)+fstar-1])
+ }
+ return (lstar)
+ }
+ }
+
+ # Regroup the stars.
+ call dp_regroup (Memi[DP_APID(apsel)+istar-1],
+ Memr[DP_APXCEN(apsel)+istar-1], Memr[DP_APYCEN(apsel)+
+ istar-1], Memr[DP_APMAG(apsel)+istar-1],
+ Memr[DP_APMSKY(apsel)+istar-1],
+ Memr[DP_ASUMWT(allstar)+istar-1],
+ Memr[DP_AXOLD(allstar)+ istar-1],
+ Memr[DP_AYOLD(allstar)+istar-1],
+ Memr[DP_AXCLAMP(allstar)+istar-1],
+ Memr[DP_AYCLAMP(allstar)+istar-1], nstar, radius,
+ Memi[DP_ALAST(allstar)+istar-1])
+ regroup = true
+ next
+ }
+
+ # Compute the mean sky for the group. If the sky is undefined
+ # reject the group.
+ mean_sky = dp_almsky (Memr[DP_APMSKY(apsel)+istar-1], nstar)
+ if (IS_INDEFR(mean_sky)) {
+ call amovkr (INDEFR, Memr[DP_APMAG(apsel)+istar-1], nstar)
+ call amovki (YES, Memi[DP_ASKIP(allstar)+istar-1], nstar)
+ call amovki (ALLERR_INDEFSKY, Memi[DP_AIER(allstar)+istar-1],
+ nstar)
+ if (DP_VERBOSE(dao) == YES) {
+ do i = istar, lstar {
+ call printf (
+ "REJECTING: Star ID: %d Group sky value is undefined\n")
+ call pargi (Memi[DP_APID(apsel)+i-1])
+ }
+ }
+ return (lstar)
+ }
+
+ # Re-compute the number of terms in the fitting equation.
+ if ((DP_RECENTER(dao) == YES) && (niter >= 2))
+ nterm = 3 * nstar
+ else
+ nterm = nstar
+
+ # Zero the fitting arrays.
+ chigrp = asumr (Memr[DP_ASUMWT(allstar)+istar-1], nstar) / nstar
+ call aclrr (Memr[DP_APCHI(apsel)+istar-1], nstar)
+ call aclrr (Memr[DP_ASUMWT(allstar)+istar-1], nstar)
+ call aclrr (Memr[DP_ANUMER(allstar)+istar-1], nstar)
+ call aclrr (Memr[DP_ADENOM(allstar)+istar-1], nstar)
+ call aclri (Memi[DP_ANPIX(allstar)+istar-1], nstar)
+ call aclrr (Memr[DP_AV(allstar)], nterm)
+ call aclrr (Memr[DP_AC(allstar)], cdimen * cdimen)
+
+ # Compute the subraster limits.
+
+ ixmin = min (IM_LEN (im,1), max (1, int (xmin - totradius) + 1))
+ ixmax = min (IM_LEN (im,1), max (1,int (xmax + totradius)))
+ iymin = min (IM_LEN (im,2), max (1, int (ymin - totradius) + 1))
+ iymax = min (IM_LEN (im,2), max (1, int (ymax + totradius)))
+
+ # Get pointer to the required weight, scratch image and
+ # subtracted image pixels. Need to modify this so writing
+ # is only enabled if iter >= MIN_ITER.
+
+ subt = dp_gst (dao, im, iymin, iymax, READ_ONLY, NO)
+ weights = dp_gwt (dao, im, iymin, iymax, READ_WRITE, NO)
+ data = dp_gdc (dao, im, iymin, iymax, READ_WRITE, NO)
+
+ # Compute the fitting limits in the subraster.
+
+ fixmin = min (ixmax, max (ixmin, int (xmin - DP_FITRAD(dao)) + 1))
+ fixmax = min (ixmax, max (ixmin, int (xmax + DP_FITRAD(dao))))
+ fiymin = min (iymax, max (iymin, int (ymin - DP_FITRAD(dao)) + 1))
+ fiymax = min (iymax, max (iymin, int (ymax + DP_FITRAD(dao))))
+ nypix = fiymax - fiymin + 1
+ nxpix = fixmax - fixmin + 1
+
+ # Now we deal with the pixels one by one.
+ sumres = 0.0
+ grpwt = 0.0
+
+ # Accumulate the data into the matrix.
+ call dp_alaccum (dao, im, Memr[data], DP_DNX(allstar),
+ DP_DNY(allstar), DP_DXOFF(allstar), DP_DYOFF(allstar),
+ Memr[subt], DP_SNX(allstar), DP_SNY(allstar), DP_SXOFF(allstar),
+ DP_SYOFF(allstar), Memr[weights], DP_WNX(allstar),
+ DP_WNY(allstar), DP_WXOFF(allstar), DP_WYOFF(allstar), nxpix,
+ nypix, fixmin, fiymin, mean_sky, istar, lstar, niter, clip,
+ pererr, peakerr, sumres, grpwt, chigrp, cdimen, nterm)
+
+ # Reflect the normal matrix across the diagonal.
+
+ call dp_mreflect (Memr[DP_AC(allstar)], cdimen, nterm)
+
+ # Compute the estimate of the standard deviation of the residuals
+ # for the group as a whole, and for each star. This estimate starts
+ # out as SQRT (PI / 2) * [sum [weight * ABS (residual / sigma)] /
+ # sum [weight] # and then gets corrected for bias by SQRT (# of
+ # pixels / [# of pixel - # degrees of freedom]).
+ #
+ # But now we drive the value toward unity, depending upon exactly
+ # how many pixels were involved. If CHI is based on exactly a total
+ # weight of 3, then it is extremely poorly determined, and we just
+ # want to keep CHI = 1. The larger the GRPWT is, the better
+ # determined CHI is, and the less we want to force it toward unity.
+ # So, just take the weighted average of CHI and unity, with weights
+ # GRPWT = 3, and 1, respectively.
+
+ if (grpwt > nterm) {
+ chigrp = CHI_NORM * sumres / sqrt (grpwt * (grpwt - nterm))
+ chigrp = ((grpwt - 3.0) * chigrp + 3.0) / grpwt
+ } else {
+ chigrp = 1.0
+ }
+
+ # CHIGRP has been pulled towards its expected value of unity to
+ # keep the statistics of a small number of pixels from completely
+ # dominating the error analysis. Similarly, the photometric errors
+ # for the individual stars will be pulled toward unity now. Later
+ # on, if the number of stars in the group is greater than one,
+ # CHI(I) will nudged toward the group average. In order to work
+ # optimally this requires that the gain and read noise and any
+ # other parameters which represent the noise sources have been
+ # properly specified.
+ #
+ # At the same time, make sure that every star in the group contains
+ # at least MIN_FIT_PIXEL valid pixels if re-centroiding is being
+ # performed, 1 valid pixel if not. If any star in the group fails
+ # to meet this criterion, mark that star for deletion and skip
+ # ahead to the next group.
+
+ if (dp_alredo (Memi[DP_APID(apsel)], Memr[DP_APMAG(apsel)],
+ Memr[DP_APCHI(apsel)], Memr[DP_ASUMWT(allstar)],
+ Memi[DP_ANPIX(allstar)], Memi[DP_ASKIP(allstar)],
+ Memi[DP_AIER(allstar)], istar, lstar, niter, chigrp,
+ DP_RECENTER(dao), DP_VERBOSE(dao)))
+ return (lstar)
+
+ # Invert the matrix.
+ if (version == 1)
+ call invers (Memr[DP_AC(allstar)], cdimen, nterm, flag)
+ else
+ call invers2 (Memr[DP_AC(allstar)], cdimen, nterm, flag)
+
+ if (dp_checkc (Memr[DP_AC(allstar)], cdimen, nterm,
+ Memi[DP_APID(apsel)], Memr[DP_APMAG(apsel)],
+ Memi[DP_ASKIP(allstar)], Memi[DP_AIER(allstar)], istar, niter,
+ DP_RECENTER(dao), DP_VERBOSE(dao)))
+ return (lstar)
+
+ # Compute the coefficients.
+ call mvmul (Memr[DP_AC(allstar)], cdimen, nterm,
+ Memr[DP_AV(allstar)], Memr[DP_AX(allstar)])
+
+ # In the beginning, the brightness of each star will be permitted
+ # to change by no more than 2 magnitudes per iteration, and the
+ # x,y coordinates of each centroid will be permitted to change by
+ # no more than 0.4 pixel per iteration. Any time that the
+ # parameter correction changes sign from one iteration to the next
+ # the maximum permissable change will be reduced by a factor of
+ # two. These clamps are released any time a star in the group
+ # disappears.
+
+ if (dp_alclamp (dao, im, Memi[DP_APID(apsel)],
+ Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[DP_APMAG(apsel)], Memr[DP_APERR(apsel)],
+ Memr[DP_ASUMWT(allstar)], Memi[DP_ASKIP(allstar)],
+ Memr[DP_AXOLD(allstar)], Memr[DP_AXCLAMP(allstar)],
+ Memr[DP_AYOLD(allstar)], Memr[DP_AYCLAMP(allstar)], istar,
+ lstar, Memr[DP_AC(allstar)], Memr[DP_AX(allstar)], cdimen,
+ niter, clampmax, pererr, peakerr)) {
+
+ # Flush the new data to the output buffers. Actually
+ # only data which fits this criterion need be written.
+ # However this makes sequential i/o management tricky.
+ # Leave this alone for the moment. Note only the cache-
+ # state is affected.
+ }
+
+ # If there is more than one star, check to see whether any two
+ # stars have merged.
+
+ if (nstar > 1) {
+
+ if (dp_almerge (Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[DP_APMAG(apsel)], Memr[DP_APERR(apsel)],
+ Memi[DP_ASKIP(allstar)], istar, lstar, sepcrit, sepmin,
+ wcrit, j, k)) {
+
+ call dp_alcentroid (Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMAG(apsel)], j, k)
+
+ # Remove the k-th star from this group.
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (
+ "REJECTING: Star ID: %d has merged with star ID: %d\n")
+ call pargi (Memi[DP_APID(apsel)+j-1])
+ call pargi (Memi[DP_APID(apsel)+k-1])
+ }
+ Memr[DP_APMAG(apsel)+j-1] = INDEFR
+ Memi[DP_ASKIP(allstar)+j-1] = YES
+ Memi[DP_AIER(allstar)+j-1] = ALLERR_MERGE
+
+ # Loosen the clamps of every star in the group
+ call aclrr (Memr[DP_AXOLD(allstar)+istar-1], nstar)
+ call aclrr (Memr[DP_AYOLD(allstar)+istar-1], nstar)
+ call amaxkr (Memr[DP_AXCLAMP(allstar)+istar-1], 0.5 *
+ clampmax, Memr[DP_AXCLAMP(allstar)+istar-1], nstar)
+ call amaxkr (Memr[DP_AYCLAMP(allstar)+istar-1], 0.5 *
+ clampmax, Memr[DP_AYCLAMP(allstar)+istar-1], nstar)
+
+ }
+ }
+
+ # If the number of iterations completed is less than or equal
+ # to 3, perform another iteration no questions asked.
+
+ if (niter <= (MIN_ITER - 1))
+ return (lstar)
+
+ # If not star has been removed from the group in the previous
+ # iteration, check to see if any of the stars is too faint (more
+ # than 12.5 magnitudes fainter thanthe PSF star). If several stars
+ # are too faint, delete the faintest one, and set the
+ # brightnesses of the other faint ones exactly to 12.5
+ # magnitudes below the PSF star. That way on the next iteration
+ # we will see whether these stars want to grow or disappear.
+
+ if (dp_alfaint (Memr[DP_APMAG(apsel)], Memi[DP_ASKIP(allstar)],
+ istar, lstar, faint, ifaint))
+ return (lstar)
+
+ # If at least one star is more than 12.5 magnitudes fainter
+ # than the PSF, then IFAINT is the index of the faintest of them
+ # and faint is the relative brightness of the faintest of them.
+
+ if (ifaint > 0) {
+
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("REJECTING: Star ID: %d is too faint\n")
+ call pargi (Memi[DP_APID(apsel)+ifaint-1])
+ }
+ Memr[DP_APMAG(apsel)+ifaint-1] = INDEFR
+ Memi[DP_ASKIP(allstar)+ifaint-1] = YES
+ Memi[DP_AIER(allstar)+ifaint-1] = ALLERR_FAINT
+
+ call aclrr (Memr[DP_AXOLD(allstar)+istar-1], nstar)
+ call aclrr (Memr[DP_AYOLD(allstar)+istar-1], nstar)
+ call amaxkr (Memr[DP_AXCLAMP(allstar)+istar-1], 0.5 *
+ clampmax, Memr[DP_AXCLAMP(allstar)+istar-1], nstar)
+ call amaxkr (Memr[DP_AYCLAMP(allstar)+istar-1], 0.5 *
+ clampmax, Memr[DP_AYCLAMP(allstar)+istar-1], nstar)
+
+ # If no star is more than 12.5 magnitudes fainter than the PSF
+ # then after the 50th iteration delete the least certain star i
+ # if it is less than a one sigma detection; after the 100th
+ # iteration delete the least certain star if it is less than a
+ # two sigma detection; after the 150th delete the least certain
+ # star if it is less than a 3 sigma detection.
+
+ } else if (niter >= 5) {
+
+ call dp_almfaint (Memr[DP_APMAG(apsel)], Memr[DP_APERR(apsel)],
+ istar, lstar, faint, ifaint)
+
+ if (faint < wcrit) {
+
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("REJECTING: Star ID: %d is too faint\n")
+ call pargi (Memi[DP_APID(apsel)+ifaint-1])
+ }
+ Memr[DP_APMAG(apsel)+ifaint-1] = INDEFR
+ Memi[DP_ASKIP(allstar)+ifaint-1] = YES
+ Memi[DP_AIER(allstar)+ifaint-1] = ALLERR_FAINT
+
+ # Loosen the clamps of every star in the group.
+ call aclrr (Memr[DP_AXOLD(allstar)+istar-1], nstar)
+ call aclrr (Memr[DP_AYOLD(allstar)+istar-1], nstar)
+ call amaxkr (Memr[DP_AXCLAMP(allstar)+istar-1], 0.5 *
+ clampmax, Memr[DP_AXCLAMP(allstar)+istar-1], nstar)
+ call amaxkr (Memr[DP_AYCLAMP(allstar)+istar-1], 0.5 *
+ clampmax, Memr[DP_AYCLAMP(allstar)+istar-1], nstar)
+ }
+ }
+
+ break
+ }
+
+ return (lstar)
+end
+
+
+# DP_LASTSTAR -- Find the last star in the current group.
+
+int procedure dp_laststar (last, istar, ntot)
+
+int last[ARB] # the grouping information array
+int istar # index of the first star in the group
+int ntot # total number of stars
+
+int lstar
+
+begin
+ do lstar = istar, ntot, 1 {
+ if (last[lstar] == YES)
+ break
+ }
+
+ return (lstar)
+end
+
+
+# DP_DELFAINTEST -- Delete the faintest star in the group.
+
+int procedure dp_delfaintest (mag, istar, lstar)
+
+real mag[ARB] # the array of magnitudes
+int istar # the first star in the group
+int lstar # the last star in the group
+
+int i, starno
+real faint
+
+begin
+ starno = 0
+ faint = MAX_REAL
+ do i = istar, lstar {
+ if (mag[i] >= faint)
+ next
+ faint = mag[i]
+ starno = i
+ }
+
+ return (starno)
+end
+
+
+# DP_ALMSKY -- Determine the mean sky value for the current group of stars.
+
+real procedure dp_almsky (sky, nstar)
+
+real sky[ARB] # array of sky values
+int nstar # number of stars in the group
+
+int i, nsky
+real sky_sum
+
+begin
+ sky_sum = 0.0
+ nsky = 0
+
+ do i = 1, nstar {
+ if (IS_INDEFR(sky[i]))
+ next
+ sky_sum = sky_sum + sky[i]
+ nsky = nsky + 1
+ }
+
+ if (nsky <= 0)
+ return (INDEFR)
+ else
+ return (sky_sum / nsky)
+end
+
+
+# DP_ALACCUM -- Accumulate the data into the matrix.
+
+procedure dp_alaccum (dao, im, data, dnx, dny, dxoff, dyoff, subt, snx, sny,
+ sxoff, syoff, weights, wnx, wny, wxoff, wyoff, nxpix, nypix, ixmin,
+ iymin, mean_sky, istar, lstar, niter, clip, pererr, peakerr, sumres,
+ grpwt, chigrp, cdimen, nterm)
+
+pointer dao # pointer to the daophot structure
+pointer im # the input image descriptor
+real data[dnx,dny] # the subtracted data array
+int dnx, dny # dimenions of the data array
+int dxoff, dyoff # lower left corner of the data array
+real subt[snx,sny] # the scratch array
+int snx, sny # dimensions of the scratch array
+int sxoff, syoff # lower left corner of the scratch array
+real weights[wnx,wny] # the weight array
+int wnx, wny # dimensions of the weight array
+int wxoff, wyoff # lower left corner of the weight array
+int nxpix, nypix # the dimensions of the area of interest
+int ixmin,iymin # lower left corner of area of interest
+real mean_sky # the group sky value
+int istar # the index of the first star in current group
+int lstar # the index of the last star in current group
+int niter # the current interation
+bool clip # clip the errors ?
+real pererr # flat fielding error factor
+real peakerr # profile error factor
+real sumres # sum of the residuals
+real grpwt # the group weight
+real chigrp # the group chi value
+int cdimen # maximum number of maxtrix dimensions
+int nterm # number of terms in the matrix to fit
+
+real fitradsq, maxgdata, fix, fiy, d, delta, sigmasq, relerr, wt, dwt
+pointer psffit, apsel, allstar
+int dix, diy, sxdiff, sydiff, wxdiff, wydiff
+real sky_value, dp_alskyval()
+bool dp_alomit()
+
+begin
+ # Set up some pointers.
+ apsel = DP_APSEL(dao)
+ psffit = DP_PSFFIT(dao)
+ allstar = DP_ALLSTAR(dao)
+
+ # These constants need to be stored more permanently in the
+ # allstar structure at some point. They should all be defined
+ # once and for all at task startup. Leave for next phase
+ # of code cleanup.
+
+ fitradsq = DP_FITRAD(dao) ** 2
+ if (IS_INDEFR(DP_MAXGDATA(dao)))
+ maxgdata = MAX_REAL
+ else
+ maxgdata = DP_MAXGDATA(dao)
+
+ # Compute the array offsets.
+ sxdiff = dxoff - sxoff
+ sydiff = dyoff - syoff
+ wxdiff = dxoff - wxoff
+ wydiff = dyoff - wyoff
+
+ do diy = iymin - dyoff + 1, iymin - dyoff + nypix, 1 {
+ fiy = real (diy + dyoff - 1)
+ do dix = ixmin - dxoff + 1, ixmin - dxoff + nxpix, 1 {
+
+ # Skip data with negative weights.
+ if (weights[dix+wxdiff,diy+wydiff] < 0.0)
+ next
+ fix = real (dix + dxoff - 1)
+
+ # If this current pixel is within one fitting radius of
+ # at least one star in the current group, include it in the
+ # calculation. Otherwise skip it. While figuring this out,
+ # compute the squared distance of this pixel from the
+ # centroid of each star in the group.
+
+ if (dp_alomit (Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[DP_ARPIXSQ(allstar)], istar, lstar, fix, fiy,
+ fitradsq))
+ next
+
+ call dp_alsetskip (Memr[DP_ARPIXSQ(allstar)],
+ Memi[DP_ASKIP(allstar)], istar, lstar, fitradsq)
+
+ if (DP_GROUPSKY(dao) == NO) {
+ sky_value = dp_alskyval (Memr[DP_APMSKY(apsel)],
+ Memi[DP_ASKIP(allstar)], istar, lstar)
+ if (IS_INDEFR(sky_value))
+ sky_value = mean_sky
+ } else
+ sky_value = mean_sky
+
+ # The expected random error in the pixel is the quadratic
+ # sum of the Poisson statistics, plus the readout noise,
+ # plus an estimated error of 0.75% of the total brightness
+ # for the difficulty of flat-fielding and bias-correcting
+ # the chip, plus an estimated error of some fraction of the
+ # of the fourth derivative at the peak of the profile, to
+ # account for the difficulty of accurately interpolating
+ # within the PSF. The fourth derivative of the PSF is
+ # proportional to H/hwhm ** 4 (hwhm is the width of the
+ # stellar core); using the geometric mean of hwhmx and
+ # hwhmy, this becomes H/(hwhmx * hwhmy) ** 2. The ratio of
+ # the fitting error to this quantity is estimated from a
+ # good-seeing CTIO frame to be approimxately 0.027.
+
+ #d = subt[dix+sxdiff,diy+sydiff] - mean_sky
+ d = subt[dix+sxdiff,diy+sydiff] - sky_value
+ delta = max (0.0, data[dix,diy] - d)
+ if ((delta > maxgdata) && (niter >= MIN_ITER))
+ next
+
+ # Dpos = raw data - residual
+ # = model-predicted brightness in this pixel consisting
+ # of sky plus all stellar profiles, which is
+ # presumably non-negative
+ #
+ # The four noise sources in the model are
+ # readout noise
+ # poisson noise
+ # flat-field errors
+ # profile errors
+ #
+ # Numerically the squares of these quantities are
+ # ronoise = sigma[i,j]
+ # poisson noise = delta / gain
+ # flat-field error = constant * delta ** 2
+ # profile error = constant * sum of profile ** 2
+
+ #sigmasq = weights[dix+wxdiff,diy+wydiff] + delta /
+ #DP_PHOTADU(dao) + (pererr * delta) ** 2 +
+ #(peakerr * (delta - mean_sky)) ** 2
+ sigmasq = weights[dix+wxdiff,diy+wydiff] + delta /
+ DP_PHOTADU(dao) + (pererr * delta) ** 2 +
+ (peakerr * (delta - sky_value)) ** 2
+ if (sigmasq <= 0.0)
+ next
+ relerr = abs (d) / sqrt (sigmasq)
+
+ if (clip && (relerr > MAX_RELERR))
+ next
+
+ # Now include this pixel in the fitting equation for the
+ # group.
+
+ wt = 0.0
+ call dp_alxaccum (dao, im, Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMAG(apsel)],
+ Memr[DP_ARPIXSQ(allstar)], Memi[DP_ASKIP(allstar)],
+ Memr[DP_AX(allstar)], Memr[DP_ANUMER(allstar)],
+ Memr[DP_ADENOM(allstar)], istar, lstar, fix, fiy, d,
+ wt, sigmasq, nterm, fitradsq)
+
+ # At this point the vector X contains the first
+ # derivative of the condition equation for pixel (I,J)
+ # with respect to each of the fitting parameters for
+ # all of the stars. Now these derivatives will be added
+ # into the normal matrix and the vector of residuals.
+ # Add this residual into the weighted sum of the absolute
+ # relative residuals
+
+ dwt = wt * relerr
+ sumres = sumres + dwt
+ grpwt = grpwt + wt
+
+ # SUMRES is the weighted sum for all the pixels in the group.
+ # Now also add the weigghted value of the residuals into the
+ # accumulating sum for each of the stars.
+
+ call dp_alchi (Memi[DP_ASKIP(allstar)], Memr[DP_APCHI(apsel)],
+ Memr[DP_ASUMWT(allstar)], Memi[DP_ANPIX(allstar)], istar,
+ lstar, wt, dwt)
+
+ # Up until now, WT represents only the radial weighting
+ # profile. Now figure in the anticipated standard error
+ # of the pixel.
+
+ wt = wt / sigmasq
+
+ # After the third iteration, reduce the weight of a bad pixel
+ # Note that for the first iteration, only the stellar magnitude
+ # is being solved for, which is a problem in LINEAR least
+ # squares, and so should be solved exactly the first time.
+ # After that, the star is given two iterations to adjust it's
+ # centroid before the clipping is turned on. After that a
+ # pixel having a residual of DP_CLIPRANGE times sigma gets
+ # reduced to half weight; a pixel having a residual of n
+ # sigma gets a weight of 1 / [1 + (n/DP_CLIPRANGE) **
+ # DP_CLIPEXP].
+
+ if (clip)
+ wt = wt / (1.0 + (relerr / (chigrp * DP_CLIPRANGE (dao))) **
+ DP_CLIPEXP (dao))
+
+ # Now work this pixel into the normal matrix
+ dwt = d * wt
+ call dp_alcaccum (Memr[DP_AX(allstar)], Memr[DP_AC(allstar)],
+ Memr[DP_AV(allstar)], Memi[DP_ASKIP(allstar)], cdimen,
+ nterm, istar, lstar, wt, dwt)
+ }
+ }
+end
+
+
+# DP_ALOMIT - Omit pixels which are too far from the center of any star
+# in the group.
+
+bool procedure dp_alomit (xcen, ycen, rpixsq, istar, lstar, fix, fiy,
+ fitradsq)
+
+real xcen[ARB] # array of x centers
+real ycen[ARB] # array of y centers
+real rpixsq[ARB] # array of pixel differences
+int istar, lstar # first and last star
+real fix, fiy # current star position
+real fitradsq # fit radius squared
+
+bool omit
+int i
+
+begin
+ omit = true
+ do i = istar, lstar {
+ rpixsq[i] = (fix - xcen[i]) ** 2 + (fiy - ycen[i]) ** 2
+ if (rpixsq[i] < fitradsq)
+ omit = false
+ }
+
+ return (omit)
+end
+
+
+# DP_ALSETSKIP -- Initialize the skip array.
+
+procedure dp_alsetskip (rpixsq, skip, istar, lstar, fitradsq)
+
+real rpixsq[ARB] # pixel distance squared
+int skip[ARB] # skip array
+int istar # the index of the first star
+int lstar # the index of the last star
+real fitradsq # the fitting radius squared
+
+int i
+
+begin
+ do i = istar, lstar {
+ if (rpixsq[i] < fitradsq)
+ skip[i] = NO
+ else
+ skip[i] = YES
+ }
+end
+
+
+# DP_ALSKYVAL -- Compute the sky value to be subtracted from a given pixel
+# by averaging the sky values of all the the stars for which the pixel in
+# question is within one fitting radius.
+
+real procedure dp_alskyval (sky, skip, istar, lstar)
+
+real sky[ARB] # the array of sky values
+int skip[ARB] # the array of skip values
+int istar # the index of the first star
+int lstar # the index of the last star
+
+int i, npts
+real sum
+
+begin
+ sum = 0.0
+ npts = 0
+ do i = istar, lstar {
+ if (skip[i] == YES)
+ next
+ sum = sum + sky[i]
+ npts = npts + 1
+ }
+
+ if (npts <= 0)
+ return (INDEFR)
+ else
+ return (sum / npts)
+end
+
+
+# DP_ALXACCUM - Accumulate the x vector.
+
+procedure dp_alxaccum (dao, im, xcen, ycen, mag, rpixsq, skip, x, numer1,
+ denom1, istar, lstar, fix, fiy, resid, wt, sigmasq, nterm, fitradsq)
+
+pointer dao # pointer to the daopot structure
+pointer im # pointer to the input image
+real xcen[ARB] # array of x centers
+real ycen[ARB] # array of y centers
+real mag[ARB] # array of relative brightnesses
+real rpixsq[ARB] # array of pixel distances squared
+int skip[ARB] # the include / exclude array
+real x[ARB] # the x vector to be accumulated
+real numer1[ARB] # first numerator array
+real denom1[ARB] # first denominator array
+int istar # index of the first star in group
+int lstar # index of the last star in group
+real fix # the x position of the current pixel
+real fiy # the y position of the current pixel
+real resid # the input data residual
+real wt # the output weight value
+real sigmasq # the sigma squared value
+int nterm # number of terms in the matrix
+real fitradsq # fitting radius squared
+
+real psfsigsqx, psfsigsqy, dx, dy, deltax, deltay, value, radsq, rhosq
+real dvdx, dvdy, dfdsig
+pointer psffit
+int nstar, i, i3, k
+real dp_usepsf()
+
+begin
+ psffit = DP_PSFFIT(dao)
+
+ nstar = lstar - istar + 1
+ psfsigsqx = Memr[DP_PSFPARS(psffit)]
+ psfsigsqy = Memr[DP_PSFPARS(psffit)+1]
+
+ do i = istar, lstar {
+
+ if (skip[i] == YES)
+ next
+ radsq = rpixsq[i] / fitradsq
+ if (radsq >= MAX_RSQ)
+ next
+ wt = max (wt, 5.0 / (5.0 + radsq / (1.0 - radsq)))
+
+ # The condition equation for pixel[I,J] is the following.
+ #
+ # data[I,J] - sum [scale * psf[I,J]] - mean_sky = residual
+ #
+ # Then we will adjust the scale factors, x centers and ycenters
+ # such that sum [weight * residual ** 2] is minimized.
+ # WT will be a function (1) of the distance of this pixel from
+ # the center of the nearest star, (2) of the model predicted
+ # brightness of the pixel (taking into consideration the
+ # readout noise, the photons/ADU, and the interpolation error
+ # of the PSF), and (3) of the size of the residual itself. (1) is
+ # necessary to prevent the non-linear least-squares from
+ # fit from oscillating. (2) is simply sensible weighting and (3)
+ # is a crude attempt at making the solution more robust
+ # against bad pixels.
+
+ dx = fix - xcen[i]
+ dy = fiy - ycen[i]
+ call dp_wpsf (dao, im, xcen[i], ycen[i], deltax, deltay, 1)
+ deltax = (deltax - 1.0) / DP_PSFX(psffit) - 1.0
+ deltay = (deltay - 1.0) / DP_PSFY(psffit) - 1.0
+ value = dp_usepsf (DP_PSFUNCTION(psffit), dx, dy,
+ DP_PSFHEIGHT(psffit), Memr[DP_PSFPARS(psffit)],
+ Memr[DP_PSFLUT(psffit)], DP_PSFSIZE(psffit),
+ DP_NVLTABLE(psffit), DP_NFEXTABLE(psffit), deltax, deltay,
+ dvdx, dvdy)
+
+ if (nterm > nstar) {
+ i3 = (i - istar + 1) * 3
+ k = i3 - 2
+ x[k] = -value
+ k = i3 - 1
+ x[k] = -mag[i] * dvdx
+ x[i3] = -mag[i] * dvdy
+ } else {
+ k = i - istar + 1
+ x[k] = -value
+ }
+
+ rhosq = (dx / psfsigsqx) ** 2 + (dy / psfsigsqy) ** 2
+ if (rhosq > MAX_RHOSQ)
+ next
+ rhosq = 0.6931472 * rhosq
+ dfdsig = exp (-rhosq) * (rhosq - 1.)
+ numer1[i] = numer1[i] + dfdsig * resid / sigmasq
+ denom1[i] = denom1[i] + dfdsig ** 2 / sigmasq
+ }
+end
+
+
+# DP_ALCHI -- Compute the weights and chis.
+
+procedure dp_alchi (skip, chi, sumwt, npix, istar, lstar, wt, dwt)
+
+int skip[ARB] # include / exclude array for the stars
+real chi[ARB] # array of chi values
+real sumwt[ARB] # array of weight sums
+int npix[ARB] # array of pixel counts
+int istar # index of first star
+int lstar # index of last star
+real wt # input weight
+real dwt # weighted residual
+
+int i
+
+begin
+ do i = istar, lstar {
+ if (skip[i] == YES)
+ next
+ chi[i] = chi[i] + dwt
+ sumwt[i] = sumwt[i] + wt
+ npix[i] = npix[i] + 1
+ }
+end
+
+
+# DP_ALCACCUM -- Accumulate the main matrix.
+
+procedure dp_alcaccum (x, c, v, skip, cdimen, nterm, istar, lstar, wt, dwt)
+
+
+real x[ARB] # x array
+real c[cdimen,ARB] # maxtrix array
+real v[ARB] # v vector
+int skip[ARB] # include / exclude array
+int cdimen # maximum size of c matrix
+int nterm # number of terms to be fit
+int istar # index of the first star
+int lstar # index of the last star
+real wt # input weight
+real dwt # input residual weight
+
+int nstar, i, j, k, l, i3, i3m2, j3
+real xkwt
+
+begin
+ nstar = lstar - istar + 1
+ do i = istar, lstar {
+ if (skip[i] == YES)
+ next
+ if (nterm > nstar) {
+ i3 = (i - istar + 1) * 3
+ i3m2 = i3 - 2
+ do k = i3m2, i3
+ v[k] = v[k] + x[k] * dwt
+ do j = istar, i {
+ if (skip[j] == YES)
+ next
+ j3 = (j - istar + 1) * 3
+ do k = i3m2, i3 {
+ xkwt = x[k] * wt
+ do l = j3 - 2, min (k, j3)
+ c[k,l] = c[k,l] + x[l] * xkwt
+ }
+ }
+ } else {
+ k = i - istar + 1
+ v[k] = v[k] + x[k] * dwt
+ xkwt = x[k] * wt
+ do j = istar, i {
+ if (skip[j] == YES)
+ next
+ l = j - istar + 1
+ c[k,l] = c[k,l] + x[l] * xkwt
+ }
+ }
+ }
+end
+
+
+# DP_ALREDO -- Check to see that there are enough good pixels to fit the
+# star and compute the individual chi values.
+
+bool procedure dp_alredo (id, mag, chi, sumwt, npix, skip, aier, istar, lstar,
+ niter, chigrp, center, verbose)
+
+int id[ARB] # the array of star ids
+real mag[ARB] # the array of relative brightnesses
+real chi[ARB] # the array of chi values
+real sumwt[ARB] # the array of weight values
+int npix[ARB] # the array of pixel counts
+int skip[ARB] # the include / exclude array
+int aier[ARB] # the array of error codes
+int istar # index of the first star
+int lstar # index of the last star
+int niter # the current iteration
+real chigrp # chi value of the group
+int center # recenter the values ?
+int verbose # verbose mode ?
+
+bool redo
+int i
+
+begin
+ redo = false
+ do i = istar, lstar {
+ if (center == YES && (niter >= 2)) {
+ if (npix[i] < MIN_NPIX) {
+ redo = true
+ skip[i] = YES
+ if (verbose == YES) {
+ call printf (
+ "REJECTING: Star ID: %d has too few good pixels\n")
+ call pargi (id[i])
+ }
+ aier[i] = ALLERR_NOPIX
+ mag[i] = INDEFR
+ } else {
+ skip[i] = NO
+ if (sumwt[i] > MIN_SUMWT) {
+ chi[i] = CHI_NORM * chi[i] / sqrt (sumwt[i] *
+ (sumwt[i] - MIN_SUMWT))
+ sumwt[i] = ((sumwt[i] - MIN_SUMWT) * chi[i] +
+ MIN_SUMWT) / sumwt[i]
+ } else
+ chi[i] = chigrp
+ }
+ } else {
+ if (npix[i] < MIN_NPIX) {
+ redo = true
+ skip[i] = YES
+ if (verbose == YES) {
+ call printf (
+ "REJECTING: Star ID: %d has too few good pixels\n")
+ call pargi (id[i])
+ }
+ aier[i] = ALLERR_NOPIX
+ mag[i] = INDEFR
+ } else {
+ skip[i] = NO
+ if (sumwt[i] > 1.0) {
+ chi[i] = CHI_NORM * chi[i] / sqrt (sumwt[i] *
+ (sumwt[i] - 1.0))
+ sumwt[i] = ((sumwt[i] - MIN_SUMWT) * chi[i] +
+ MIN_SUMWT) / sumwt[i]
+ } else
+ chi[i] = chigrp
+ }
+ }
+ }
+
+ return (redo)
+end
+
+
+# DP_CHECKC - Check the c matrix for valid diagonal elements.
+
+bool procedure dp_checkc (c, cdimen, nterm, id, mag, skip, aier, istar, niter,
+ recenter, verbose)
+
+real c[cdimen,ARB] # the c matrix
+int cdimen # maximum size of the c matrix
+int nterm # number of terms to be fit
+int id[ARB] # the array of ids
+real mag[ARB] # the array of relative brightnesses
+int skip[ARB] # the include / exclude array
+int aier[ARB] # the array of error codes
+int istar # index of the first star
+int niter # the iteration number
+int recenter # recenter ?
+int verbose # verbose mode ?
+
+bool redo
+int j, starno
+
+begin
+ redo = false
+ do j = 1, nterm {
+ if (c[j,j] > 0.0)
+ next
+ if ((recenter == YES) && (niter >= 2))
+ starno = (j + 2) / 3
+ else
+ starno = j
+ starno = starno + istar - 1
+ skip[starno] = YES
+ if (verbose == YES) {
+ call printf (
+ "REJECTING: Star ID: %d generated a fitting error\n")
+ call pargi (id[starno])
+ }
+ aier[starno] = ALLERR_SINGULAR
+ mag[starno] = INDEFR
+ redo = true
+ break
+ }
+
+ return (redo)
+end
+
+
+# DP_ALCLAMP -- Get the answers.
+
+bool procedure dp_alclamp (dao, im, id, xcen, ycen, mag, magerr, sumwt,
+ skip, xold, xclamp, yold, yclamp, istar, lstar, c, x,
+ cdimen, niter, clampmax, pererr, peakerr)
+
+pointer dao # pointer to the daophot structure
+pointer im # the input image descriptor
+int id[ARB] # array of star ids
+real xcen[ARB] # array of star x centers
+real ycen[ARB] # array of star y centers
+real mag[ARB] # array of relative brightnesses
+real magerr[ARB] # array of relative brightness errors
+real sumwt[ARB] # array of pixel distance squared values
+int skip[ARB] # include / exclude array
+real xold[ARB] # xold array
+real xclamp[ARB] # xclamp array
+real yold[ARB] # yold array
+real yclamp[ARB] # yclamp array
+int istar # the index of the first star
+int lstar # the index of the last star
+real c[cdimen,ARB] # c matrix
+real x[ARB] # x vector
+int cdimen # the maximum size of c matrix
+int niter # the current iteration
+real clampmax # the maximum clamp value
+real pererr # flat field error
+real peakerr # the profile error
+
+bool redo, bufwrite
+int i, l, k, j, lx, mx, ly, my, nx, ny
+pointer psffit, allstar
+real dwt, psfrad, psfradsq, df
+
+begin
+ # Get some daophot pointers.
+ allstar = DP_ALLSTAR(dao)
+ psffit = DP_PSFFIT(dao)
+
+ # Get some constants.
+ if (DP_PSFSIZE(psffit) == 0)
+ psfrad = DP_PSFRAD(dao)
+ else
+ psfrad = (real (DP_PSFSIZE(psffit) - 1) / 2.0 - 1.0) / 2.0
+ psfradsq = psfrad * psfrad
+
+ # Initialize.
+ bufwrite = false
+
+ do i = istar, lstar {
+
+ if ((DP_RECENTER(dao) == YES) && (niter >= 2)) {
+
+ l = 3 * (i - istar + 1)
+ k = l - 1
+ j = l - 2
+
+ # Note that the sign of the correction is such that it must be
+ # SUBTRACTED from the current value of the parameter to get the
+ # improved parameter value. This being the case, if the
+ # correction to the brightness is negative a change of one
+ # magnitude is a change of factor of 2.5; if the brightness
+ # correction is positive a change of one magnitude is a change
+ # of 60%.
+
+ dwt = xold[i] * x[k]
+ if (dwt < 0.0)
+ xclamp[i] = max (MIN_XYCLAMP, MIN_XYCLAMP_FRACTION *
+ xclamp[i])
+ else
+ xclamp[i] = min (clampmax, MAX_XYCLAMP_FRACTION * xclamp[i])
+ xcen[i] = xcen[i] - x[k] / (1.0 + abs (x[k] / xclamp[i]))
+ xold[i] = x[k]
+
+ dwt = yold[i] * x[l]
+ if (dwt < 0.0)
+ yclamp[i] = max (MIN_XYCLAMP, MIN_XYCLAMP_FRACTION *
+ yclamp[i])
+ else
+ yclamp[i] = min (clampmax, MAX_XYCLAMP_FRACTION * yclamp[i])
+ ycen[i] = ycen[i] - x[l] / (1.0 + abs (x[l] / yclamp[i]))
+ yold[i] = x[l]
+
+ mag[i] = mag[i] - x[j] / (1.0 + max (x[j] / (MAX_DELTA_FAINTER *
+ mag[i]), -x[j] / (MAX_DELTA_BRIGHTER * mag[i])))
+ magerr[i] = sumwt[i] * sqrt (c[j,j])
+
+ if (niter >= MIN_ITER) {
+ redo = false
+ if (abs(x[j]) > max (MAX_NEW_ERRMAG * magerr[i],
+ MAX_NEW_RELBRIGHT2 * mag[i]))
+ redo = true
+ else {
+ df = (MAX_NEW_ERRMAG * sumwt[i]) ** 2
+ if ((x[k] ** 2) > max (df * c[k,k], MAX_PIXERR2))
+ redo = true
+ else if ((x[l] ** 2) > max (df * c[l,l], MAX_PIXERR2))
+ redo = true
+ }
+ } else
+ redo = true
+
+ } else {
+ j = i - istar + 1
+ mag[i] = mag[i] - x[j] / (1.0 + 1.2 * abs (x[j] / mag[i]))
+ magerr[i] = sumwt[i] * sqrt (c[j,j])
+ if (niter >= 2) {
+ redo = false
+ if (abs(x[j]) > max (MAX_NEW_ERRMAG * magerr[i],
+ MAX_NEW_RELBRIGHT2 * mag[i]))
+ redo = true
+ } else
+ redo = true
+ }
+
+ if (mag[i] < 2.0 * magerr[i])
+ redo = true
+ if (niter >= DP_MAXITER(dao))
+ redo = false
+ if (redo && (niter < DP_MAXITER(dao)))
+ next
+
+ # If this star converged, write out the results for it,
+ # flag it for deletion from the star list and subtract it
+ # from the reference copy of the image.
+
+ call dp_glim (xcen[i], ycen[i], psfrad, DP_DLX(allstar),
+ DP_DMX(allstar), DP_DLY(allstar), DP_DMY(allstar),
+ lx, mx, ly, my)
+ nx = mx - lx + 1
+ ny = my - ly + 1
+
+ call dp_swstar (dao, im, Memr[DP_DBUF(allstar)], DP_DNX(allstar),
+ DP_DNY(allstar), DP_DXOFF(allstar), DP_DYOFF(allstar),
+ Memr[DP_WBUF(allstar)], DP_WNX(allstar), DP_WNY(allstar),
+ DP_WXOFF(allstar), DP_WYOFF(allstar), xcen[i], ycen[i],
+ mag[i], lx, ly, nx, ny, psfradsq, DP_PHOTADU(dao), pererr,
+ peakerr)
+
+ skip[i] = YES
+
+ if (DP_VERBOSE(dao) == YES) {
+ call dp_wout (dao, im, xcen[i], ycen[i], xcen[i], ycen[i], 1)
+ call printf (
+ "FITTING: ID: %5d XCEN: %8.2f YCEN: %8.2f MAG: %8.2f\n")
+ call pargi (id[i])
+ call pargr (xcen[i])
+ call pargr (ycen[i])
+ if (mag[i] <= 0.0)
+ call pargr (INDEFR)
+ else
+ call pargr (DP_PSFMAG(psffit) - 2.5 * log10 (mag[i]))
+
+ }
+ bufwrite = true
+ }
+
+ return (bufwrite)
+end
+
+
+# DP_SWSTAR -- Subtract the fitted star for the data and adjust the
+# weights.
+
+procedure dp_swstar (dao, im, data, dnx, dny, dxoff, dyoff, weights, wnx, wny,
+ wxoff, wyoff, xcen, ycen, mag, lx, ly, nx, ny, psfradsq, gain,
+ pererr, peakerr)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+real data[dnx,dny] # the data array
+int dnx, dny # dimensions of the data array
+int dxoff, dyoff # lower left corner of data array
+real weights[wnx,wny] # the weights array
+int wnx, wny # dimensions of the weights array
+int wxoff, wyoff # lower left corner of weights array
+real xcen, ycen # the position of the star
+real mag # relative brightness of the star
+int lx, ly # lower left corner region of interest
+int nx, ny # size of region of interest
+real psfradsq # the psf radius squared
+real gain # the gain in photons per adu
+real pererr # the flat field error factor
+real peakerr # the peak error factor
+
+real deltax, deltay, dx, dy, dysq, diff, dvdx, dvdy
+pointer psffit
+int di, dj, wxdiff, wydiff
+real dp_usepsf()
+
+begin
+ psffit = DP_PSFFIT(dao)
+
+ wxdiff = dxoff - wxoff
+ wydiff = dyoff - wyoff
+ call dp_wpsf (dao, im, xcen, ycen, deltax, deltay, 1)
+ deltax = (deltax - 1.0) / DP_PSFX(psffit) - 1.0
+ deltay = (deltay - 1.0) / DP_PSFY(psffit) - 1.0
+
+ do dj = ly - dyoff + 1, ly - dyoff + ny {
+ dy = (dj + dyoff - 1) - ycen
+ dysq = dy * dy
+ do di = lx - dxoff + 1, lx - dxoff + nx {
+ if (weights[di+wxdiff,dj+wydiff] <= -MAX_REAL)
+ next
+ dx = (di + dxoff - 1) - xcen
+ if ((dx * dx + dysq) >= psfradsq)
+ next
+ diff = mag * dp_usepsf (DP_PSFUNCTION(psffit), dx, dy,
+ DP_PSFHEIGHT(psffit), Memr[DP_PSFPARS(psffit)],
+ Memr[DP_PSFLUT(psffit)], DP_PSFSIZE(psffit),
+ DP_NVLTABLE(psffit), DP_NFEXTABLE(psffit), deltax, deltay,
+ dvdx, dvdy)
+ data[di,dj] = data[di,dj] - diff
+ if (diff > 0.0) {
+ diff = diff / gain + pererr *
+ 2.0 * max (0.0, data[di,dj]) * diff +
+ (peakerr * diff) ** 2
+ if (weights[di+wxdiff,dj+wydiff] >= 0.0)
+ weights[di+wxdiff,dj+wydiff] = weights[di+wxdiff,
+ dj+wydiff] + diff
+ else
+ weights[di+wxdiff,dj+wydiff] = - (abs (weights[di+
+ wxdiff,dj+wydiff]) + diff)
+ }
+ }
+ }
+end
+
+
+# DP_ALMERGE -- Determine whether or not two stars should merge.
+
+bool procedure dp_almerge (xcen, ycen, mag, magerr, skip, istar, lstar,
+ sepcrit, sepmin, wcrit, k, l)
+
+real xcen[ARB] # array of x centers
+real ycen[ARB] # array of y centers
+real mag[ARB] # array of relative brightnesses
+real magerr[ARB] # array of relative brightness errors
+int skip[ARB] # the include / exclude array
+int istar # index to the first star
+int lstar # index to the last star
+real sepcrit # the critical separation
+real sepmin # the minimum separation
+real wcrit # the critical error
+int k, l # indices of stars to be merged
+
+bool merge
+int i, j
+real rsq, sep
+
+begin
+ # Initialize.
+ rsq = sepcrit
+ merge = false
+ k = 0
+ l = 0
+
+ # Find the closest two stars within the critical separation.
+ do i = istar + 1, lstar {
+
+ if (skip[i] == YES)
+ next
+
+ do j = istar, i - 1 {
+ if (skip[j] == YES)
+ next
+ sep = (xcen[i] - xcen[j]) ** 2 + (ycen[i] - ycen[j]) ** 2
+ if (sep >= rsq)
+ next
+
+ # Two stars are overlapping. Identify the fainter of the two.
+ rsq = sep
+ if (mag[i] < mag[j]) {
+ k = i
+ l = j
+ } else {
+ k = j
+ l = i
+ }
+
+ merge = true
+ }
+ }
+
+ # No stars overlap.
+ if (! merge)
+ return (merge)
+
+ # The stars are not close enough.
+ if ((rsq > sepmin) && (mag[k] > wcrit * magerr[k]))
+ merge = false
+
+ return (merge)
+end
+
+
+# DP_ALCENTROID -- Merge two stars by adding their relative brightnesses
+# and replacing their individual positions with the relative brightness
+# weighted mean position.
+
+procedure dp_alcentroid (xcen, ycen, mag, k, l)
+
+real xcen[ARB] # array of x centers
+real ycen[ARB] # array of y centers
+real mag[ARB] # array of magnitudes
+int k, l # input indices, k is fainter
+
+begin
+ xcen[l] = xcen[l] * mag[l] + xcen[k] * mag[k]
+ ycen[l] = ycen[l] * mag[l] + ycen[k] * mag[k]
+ mag[l] = mag[l] + mag[k]
+ xcen[l] = xcen[l] / mag[l]
+ ycen[l] = ycen[l] / mag[l]
+end
+
+
+# DP_ALFAINT -- Find all the stars with realtive brightnesss less than
+# a given number and set their magnitudes to a given minimum relative
+# brightness.
+
+bool procedure dp_alfaint (mag, skip, istar, lstar, faint, ifaint)
+
+real mag[ARB] # array of magnitudes
+int skip[ARB] # skip array
+int istar, lstar # first and last stars
+real faint # faintest star
+int ifaint # index of faintest star
+
+int i
+
+begin
+ # Initialize
+ faint = MIN_REL_BRIGHT
+ ifaint = 0
+
+ do i = istar, lstar {
+ if (skip[i] == YES)
+ return (true)
+ if (mag[i] < faint) {
+ faint = mag[i]
+ ifaint = i
+ }
+ if (mag[i] < MIN_REL_BRIGHT)
+ mag[i] = MIN_REL_BRIGHT
+ }
+
+ return (false)
+end
+
+
+# DP_ALMFAINT -- Find the star with the greatest error in its relative
+# brightness.
+
+procedure dp_almfaint (mag, magerr, istar, lstar, faint, ifaint)
+
+real mag[ARB] # array of relative brightnesses
+real magerr[ARB] # array of relative brightness errors
+int istar # index of first star
+int lstar # index of last star
+real faint # computed faintness limit
+int ifaint # index of faintest star
+
+int i
+real wt
+
+begin
+ faint = MAX_REAL
+ ifaint = 0
+ do i = istar, lstar {
+ wt = mag[i] / magerr[i]
+ if (wt < faint) {
+ faint = wt
+ ifaint = i
+ }
+ }
+end
diff --git a/noao/digiphot/daophot/allstar/dpalwrite.x b/noao/digiphot/daophot/allstar/dpalwrite.x
new file mode 100644
index 00000000..c4688924
--- /dev/null
+++ b/noao/digiphot/daophot/allstar/dpalwrite.x
@@ -0,0 +1,556 @@
+include <tbset.h>
+include <time.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/allstardef.h"
+
+# DP_TNEWAL -- Create an new ALLSTAR output ST table.
+
+procedure dp_tnewal (dao, tp, colpoint)
+
+pointer dao # pointer to the daophot strucuture
+pointer tp # pointer to the output table
+int colpoint[ARB] # array of column pointers
+
+int i
+pointer sp, colnames, colunits, colformat, col_dtype, col_len
+
+begin
+ # Allocate space for table definition.
+ call smark (sp)
+ call salloc (colnames, ALL_NOUTCOLUMN * (SZ_COLNAME + 1), TY_CHAR)
+ call salloc (colunits, ALL_NOUTCOLUMN * (SZ_COLUNITS + 1), TY_CHAR)
+ call salloc (colformat, ALL_NOUTCOLUMN * (SZ_COLFMT + 1), TY_CHAR)
+ call salloc (col_dtype, ALL_NOUTCOLUMN, TY_INT)
+ call salloc (col_len, ALL_NOUTCOLUMN, TY_INT)
+
+ # Set up the column definitions.
+ call strcpy (ID, Memc[colnames], SZ_COLNAME)
+ call strcpy (XCENTER, Memc[colnames+SZ_COLNAME+1], SZ_COLNAME)
+ call strcpy (YCENTER, Memc[colnames+2*SZ_COLNAME+2], SZ_COLNAME)
+ call strcpy (MAG, Memc[colnames+3*SZ_COLNAME+3], SZ_COLNAME)
+ call strcpy (MAGERR, Memc[colnames+4*SZ_COLNAME+4], SZ_COLNAME)
+ call strcpy (SKY, Memc[colnames+5*SZ_COLNAME+5], SZ_COLNAME)
+ call strcpy (NITER, Memc[colnames+6*SZ_COLNAME+6], SZ_COLNAME)
+ call strcpy (SHARP, Memc[colnames+7*SZ_COLNAME+7], SZ_COLNAME)
+ call strcpy (CHI, Memc[colnames+8*SZ_COLNAME+8], SZ_COLNAME)
+ call strcpy (PIER, Memc[colnames+9*SZ_COLNAME+9], SZ_COLNAME)
+ call strcpy (PERROR, Memc[colnames+10*SZ_COLNAME+10], SZ_COLNAME)
+
+ # Define the column formats.
+ call strcpy ("%6d", Memc[colformat], SZ_COLFMT)
+ call strcpy ("%10.3f", Memc[colformat+SZ_COLFMT+1], SZ_COLFMT)
+ call strcpy ("%10.3f", Memc[colformat+2*SZ_COLFMT+2], SZ_COLFMT)
+ call strcpy ("%12.3f", Memc[colformat+3*SZ_COLFMT+3], SZ_COLFMT)
+ call strcpy ("%14.3f", Memc[colformat+4*SZ_COLFMT+4], SZ_COLFMT)
+ call strcpy ("%15.7g", Memc[colformat+5*SZ_COLFMT+5], SZ_COLFMT)
+ call strcpy ("%6d", Memc[colformat+6*SZ_COLFMT+6], SZ_COLFMT)
+ call strcpy ("%12.3f", Memc[colformat+7*SZ_COLFMT+7], SZ_COLFMT)
+ call strcpy ("%12.3f", Memc[colformat+8*SZ_COLFMT+8], SZ_COLFMT)
+ call strcpy ("%6d", Memc[colformat+9*SZ_COLFMT+9], SZ_COLFMT)
+ call strcpy ("%13s", Memc[colformat+10*SZ_COLFMT+10], SZ_COLFMT)
+
+ # Define the column units.
+ call strcpy ("NUMBER", Memc[colunits], SZ_COLUNITS)
+ call strcpy ("PIXELS", Memc[colunits+SZ_COLUNITS+1], SZ_COLUNITS)
+ call strcpy ("PIXELS", Memc[colunits+2*SZ_COLUNITS+2], SZ_COLUNITS)
+ call strcpy ("MAGNITUDES", Memc[colunits+3*SZ_COLUNITS+3], SZ_COLUNITS)
+ call strcpy ("MAGNITUDES", Memc[colunits+4*SZ_COLUNITS+4], SZ_COLUNITS)
+ call strcpy ("ADC", Memc[colunits+5*SZ_COLUNITS+5], SZ_COLUNITS)
+ call strcpy ("NUMBER", Memc[colunits+6*SZ_COLUNITS+6], SZ_COLUNITS)
+ call strcpy ("NUMBER", Memc[colunits+7*SZ_COLUNITS+7], SZ_COLUNITS)
+ call strcpy ("NUMBER", Memc[colunits+8*SZ_COLUNITS+8], SZ_COLUNITS)
+ call strcpy ("NUMBER", Memc[colunits+9*SZ_COLUNITS+9], SZ_COLUNITS)
+ call strcpy ("PERRORS", Memc[colunits+10*SZ_COLUNITS+10], SZ_COLUNITS)
+
+ # Define the column types.
+ Memi[col_dtype] = TY_INT
+ Memi[col_dtype+1] = TY_REAL
+ Memi[col_dtype+2] = TY_REAL
+ Memi[col_dtype+3] = TY_REAL
+ Memi[col_dtype+4] = TY_REAL
+ Memi[col_dtype+5] = TY_REAL
+ Memi[col_dtype+6] = TY_INT
+ Memi[col_dtype+7] = TY_REAL
+ Memi[col_dtype+8] = TY_REAL
+ Memi[col_dtype+9] = TY_INT
+ Memi[col_dtype+10] = -13
+
+ # Define the column lengths.
+ do i = 1, ALL_NOUTCOLUMN
+ Memi[col_len+i-1] = 1
+
+ # Define and create the table.
+ call tbcdef (tp, colpoint, Memc[colnames], Memc[colunits],
+ Memc[colformat], Memi[col_dtype], Memi[col_len], ALL_NOUTCOLUMN)
+ call tbtcre (tp)
+
+ # Write out the header parameters.
+ call dp_talpars (dao, tp)
+
+ call sfree (sp)
+
+end
+
+
+define AL_NAME1STR "#N%4tID%10tXCENTER%20tYCENTER%30tMAG%42tMERR%56tMSKY%71t\
+NITER%80t\\\n"
+define AL_UNIT1STR "#U%4t##%10tpixels%20tpixels%30tmagnitudes%42tmagnitudes%56t\
+counts%71t##%80t\\\n"
+define AL_FORMAT1STR "#F%4t%%-9d%10t%%-10.3f%20t%%-10.3f%30t%%-12.3f%42t\
+%%-14.3f%56t%%-15.7g%71t%%-6d%80t \n"
+
+define AL_NAME2STR "#N%12tSHARPNESS%24tCHI%36tPIER%42tPERROR%80t\\\n"
+define AL_UNIT2STR "#U%12t##%24t##%36t##%42tperrors%80t\\\n"
+define AL_FORMAT2STR "#F%12t%%-23.3f%24t%%-12.3f%36t%%-6d%42t%%-13s%80t \n"
+
+
+# DP_XNEWAL -- Initialize a new output ALLSTAR text file.
+
+procedure dp_xnewal (dao, tp)
+
+pointer dao # pointer to the daophot structure
+int tp # the output file descriptor
+
+begin
+ # Write out the header parameters.
+ call dp_xalpars (dao, tp)
+
+ # Write out the banner.
+ call fprintf (tp, "#\n")
+ call fprintf (tp, AL_NAME1STR)
+ call fprintf (tp, AL_UNIT1STR)
+ call fprintf (tp, AL_FORMAT1STR)
+ call fprintf (tp, "#\n")
+ call fprintf (tp, AL_NAME2STR)
+ call fprintf (tp, AL_UNIT2STR)
+ call fprintf (tp, AL_FORMAT2STR)
+ call fprintf (tp, "#\n")
+end
+
+
+# DP_TALPARS -- Add various parameters to the header of the ALLSTAR table.
+
+procedure dp_talpars (dao, tp)
+
+pointer dao # pointer to the daophot structure
+pointer tp # pointer to the output table
+
+pointer sp, psffit, outstr, date, time
+bool itob()
+int envfind()
+
+begin
+ # Define some daophot pointers.
+ psffit = DP_PSFFIT(dao)
+
+ # Allocate workin space.
+ call smark (sp)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+ call salloc (date, SZ_DATE, TY_CHAR)
+ call salloc (time, SZ_DATE, TY_CHAR)
+
+ # Write the id.
+ if (envfind ("version", Memc[outstr], SZ_LINE) <= 0)
+ call strcpy ("NOAO/IRAF", Memc[outstr], SZ_LINE)
+ call dp_rmwhite (Memc[outstr], Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "IRAF", Memc[outstr])
+ if (envfind ("userid", Memc[outstr], SZ_LINE) <= 0)
+ call tbhadt (tp, "USER", Memc[outstr])
+ call gethost (Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "HOST", Memc[outstr])
+ call dp_date (Memc[date], Memc[time], SZ_DATE)
+ call tbhadt (tp, "DATE", Memc[date])
+ call tbhadt (tp, "TIME", Memc[time])
+ call tbhadt (tp, "PACKAGE", "daophot")
+ call tbhadt (tp, "TASK", "allstar")
+
+ # Write out the files names.
+ call dp_imroot (DP_INIMAGE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "IMAGE", Memc[outstr])
+ call dp_froot (DP_INPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "PHOTFILE", Memc[outstr])
+ call dp_imroot (DP_PSFIMAGE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "PSFIMAGE", Memc[outstr])
+ call dp_froot (DP_OUTPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "ALLSTARFILE", Memc[outstr])
+ if (DP_OUTREJFILE(dao) == EOS) {
+ call tbhadt (tp, "REJFILE", "\"\"")
+ } else {
+ call dp_froot (DP_OUTREJFILE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "REJFILE", Memc[outstr])
+ }
+ call dp_imroot (DP_OUTIMAGE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "SUBIMAGE", Memc[outstr])
+
+ # Define the data characteristics.
+ call tbhadr (tp, "SCALE", DP_SCALE(dao))
+ call tbhadr (tp, "DATAMIN", DP_MINGDATA(dao))
+ call tbhadr (tp, "DATAMAX", DP_MAXGDATA(dao))
+ call tbhadr (tp, "GAIN", DP_PHOTADU(dao))
+ call tbhadr (tp, "READNOISE", DP_READNOISE(dao))
+
+ # Define the observing parameters.
+ call tbhadt (tp, "OTIME", DP_OTIME(dao))
+ call tbhadr (tp, "XAIRMASS", DP_XAIRMASS(dao))
+ call tbhadt (tp, "IFILTER", DP_IFILTER(dao))
+
+ # Define the fitting parameters.
+ call tbhadb (tp, "RECENTER", itob (DP_RECENTER(dao)))
+ call tbhadb (tp, "GRPSKY", itob (DP_GROUPSKY(dao)))
+ call tbhadb (tp, "FITSKY", itob (DP_FITSKY(dao)))
+ call tbhadr (tp, "PSFMAG", DP_PSFMAG(psffit))
+ call tbhadr (tp, "PSFRAD", DP_SPSFRAD(dao))
+ call tbhadr (tp, "FITRAD", DP_SFITRAD(dao))
+ call tbhadr (tp, "ANNULUS", DP_SANNULUS(dao))
+ call tbhadr (tp, "DANNULUS", DP_SDANNULUS(dao))
+ call tbhadi (tp, "MAXITER", DP_MAXITER(dao))
+ call tbhadi (tp, "MAXGROUP", DP_MAXGROUP(dao))
+ #call tbhadi (tp, "MAXNSTAR", DP_MAXNSTAR(dao))
+ call tbhadr (tp, "FLATERROR", DP_FLATERR(dao))
+ call tbhadr (tp, "PROFERROR", DP_PROFERR(dao))
+ call tbhadi (tp, "CLIPEXP", DP_CLIPEXP(dao))
+ call tbhadr (tp, "CLIPRANGE", DP_CLIPRANGE(dao))
+ call tbhadr (tp, "MERGERAD", DP_SMERGERAD(dao))
+
+ call sfree(sp)
+end
+
+
+# DP_XALPARS -- Add various parameters to the header of the PEAK table
+
+procedure dp_xalpars (dao, tp)
+
+pointer dao # pointer to the daophot structure
+int tp # the output file descriptor
+
+pointer sp, psffit, outstr, date, time, dummy
+bool itob()
+int envfind()
+
+begin
+ # Define some daophot pointers.
+ psffit = DP_PSFFIT(dao)
+
+ # Allocate workin space.
+ call smark (sp)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+ call salloc (date, SZ_DATE, TY_CHAR)
+ call salloc (time, SZ_DATE, TY_CHAR)
+ call salloc (dummy, 2, TY_CHAR)
+ Memc[dummy] = EOS
+
+ # Write the id.
+ if (envfind ("version", Memc[outstr], SZ_LINE) <= 0)
+ call strcpy ("NOAO/IRAF", Memc[outstr], SZ_LINE)
+ call dp_rmwhite (Memc[outstr], Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "IRAF", Memc[outstr], "version", Memc[dummy])
+ if (envfind ("userid", Memc[outstr], SZ_LINE) <= 0)
+ call dp_sparam (tp, "USER", Memc[outstr], "name", Memc[dummy])
+ call gethost (Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "HOST", Memc[outstr], "computer", Memc[dummy])
+ call dp_date (Memc[date], Memc[time], SZ_DATE)
+ call dp_sparam (tp, "DATE", Memc[date], "yyyy-mm-dd", Memc[dummy])
+ call dp_sparam (tp, "TIME", Memc[time], "hh:mm:ss", Memc[dummy])
+ call dp_sparam (tp, "PACKAGE", "daophot", "name", Memc[dummy])
+ call dp_sparam (tp, "TASK", "allstar", "name", Memc[dummy])
+
+ # Write out the files names.
+ call dp_imroot (DP_INIMAGE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "IMAGE", Memc[outstr], "imagename", Memc[dummy])
+ call dp_froot (DP_INPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "PHOTFILE", Memc[outstr], "filename", Memc[dummy])
+ call dp_imroot (DP_PSFIMAGE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "PSFIMAGE", Memc[outstr], "imagename", Memc[dummy])
+ call dp_froot (DP_OUTPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "ALLSTARFILE", Memc[outstr], "filename",
+ Memc[dummy])
+ if (DP_OUTREJFILE(dao) == EOS)
+ call dp_sparam (tp, "REJFILE", "\"\"", "filename", Memc[dummy])
+ else {
+ call dp_froot (DP_OUTREJFILE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "REJFILE", Memc[outstr], "filename",
+ Memc[dummy])
+ }
+ call dp_imroot (DP_OUTIMAGE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "SUBIMAGE", Memc[outstr], "imagename",
+ Memc[dummy])
+
+ # Define the data characteristics.
+ call dp_rparam (tp, "SCALE", DP_SCALE(dao), "units/pix", Memc[dummy])
+ call dp_rparam (tp, "DATAMIN", DP_MINGDATA(dao), "counts", Memc[dummy])
+ call dp_rparam (tp, "DATAMAX", DP_MAXGDATA(dao), "counts", Memc[dummy])
+ call dp_rparam (tp, "GAIN", DP_PHOTADU(dao), "e-/adu", Memc[dummy])
+ call dp_rparam (tp, "READNOISE", DP_READNOISE(dao), "electrons",
+ Memc[dummy])
+
+ # Define the observing parameters.
+ call dp_sparam (tp, "OTIME", DP_OTIME(dao), "timeunit", Memc[dummy])
+ call dp_rparam (tp, "XAIRMASS", DP_XAIRMASS(dao), "number", Memc[dummy])
+ call dp_sparam (tp, "IFILTER", DP_IFILTER(dao), "filter", Memc[dummy])
+
+ # Define the fitting parameters.
+ call dp_bparam (tp, "RECENTER", itob (DP_RECENTER(dao)), "switch",
+ Memc[dummy])
+ call dp_bparam (tp, "GRPSKY", itob (DP_GROUPSKY(dao)), "switch",
+ Memc[dummy])
+ call dp_bparam (tp, "FITSKY", itob (DP_FITSKY(dao)), "switch",
+ Memc[dummy])
+ call dp_rparam (tp, "PSFMAG", DP_PSFMAG(psffit), "magnitude",
+ Memc[dummy])
+ call dp_rparam (tp, "PSFRAD", DP_SPSFRAD(dao), "scaleunit", Memc[dummy])
+ call dp_rparam (tp, "FITRAD", DP_SFITRAD(dao), "scaleunit", Memc[dummy])
+ call dp_rparam (tp, "ANNULUS", DP_SANNULUS(dao), "scaleunit",
+ Memc[dummy])
+ call dp_rparam (tp, "DANNULUS", DP_SDANNULUS(dao), "scaleunit",
+ Memc[dummy])
+ call dp_iparam (tp, "MAXITER", DP_MAXITER(dao), "number", Memc[dummy])
+ call dp_iparam (tp, "MAXGROUP", DP_MAXGROUP(dao), "number", Memc[dummy])
+ #call dp_iparam (tp, "MAXNSTAR", DP_MAXNSTAR(dao), "number",
+ #Memc[dummy])
+ call dp_rparam (tp, "FLATERROR", DP_FLATERR(dao), "percentage",
+ Memc[dummy])
+ call dp_rparam (tp, "PROFERROR", DP_PROFERR(dao), "percentage",
+ Memc[dummy])
+ call dp_iparam (tp, "CLIPEXP", DP_CLIPEXP(dao), "number", Memc[dummy])
+ call dp_rparam (tp, "CLIPRANGE", DP_CLIPRANGE(dao), "sigma",
+ Memc[dummy])
+ call dp_rparam (tp, "MERGERAD", DP_SMERGERAD(dao), "scaleunit",
+ Memc[dummy])
+
+ call sfree (sp)
+end
+
+
+# DP_TALWRITE -- Write out a photometry record to an ALLSTAR ST table.
+
+procedure dp_talwrite (tpout, tprout, colpoint, id, x, y, mag, magerr, sky,
+ chi, numer, denom, skip, aier, niter, istar, lstar, star, rstar,
+ psfmag, csharp)
+
+pointer tpout # the output photometry file descriptor
+pointer tprout # the output rejections file descriptor
+int colpoint[ARB] # array of column pointers
+int id[ARB] # array of ids
+real x[ARB] # array of xpositions
+real y[ARB] # array of y positions
+real mag[ARB] # array of magnitude values
+real magerr[ARB] # array of mangitudes
+real sky[ARB] # array of sky values
+real chi[ARB] # array of chi values
+real numer[ARB] # array of first numerator values
+real denom[ARB] # array of first denominator values
+int skip[ARB] # array of skipped stars
+int aier[ARB] # array of error codes
+int niter # number of iterations
+int istar, lstar # first and last stars
+int star # photometry file row number
+int rstar # rejections file row number
+real psfmag # magnitude of the psf
+real csharp # the sharpness constant
+
+int i, iter, pier, plen
+pointer sp, perror
+real err, sharp
+int dp_gallerr()
+
+begin
+ call smark (sp)
+ call salloc (perror, SZ_FNAME, TY_CHAR)
+
+ do i = istar, lstar {
+
+ # Skip the star ?
+ if (skip[i] == NO)
+ next
+ if (IS_INDEFR(x[i]) || IS_INDEFR(y[i]))
+ next
+
+ # Get the results.
+ if (IS_INDEFR(mag[i]) || mag[i] <= 0.0 || denom[i] == 0.) {
+ mag[i] = INDEFR
+ iter = 0
+ err = INDEFR
+ sharp = INDEFR
+ chi[i] = INDEFR
+ } else {
+ if (magerr[i] <= 0.0)
+ err = 0.0
+ else
+ err = 1.085736 * magerr[i] / mag[i]
+ sharp = csharp * numer[i] / (mag[i] * denom[i])
+ sharp = max (MIN_SHARP, min (sharp, MAX_SHARP))
+ mag[i] = psfmag - 2.5 * log10 (mag[i])
+ iter = niter
+ }
+ pier = aier[i]
+ plen = dp_gallerr (pier, Memc[perror], SZ_FNAME)
+
+ # Write the output row.
+ if ((tprout != NULL) && (pier != ALLERR_OK)) {
+ rstar = rstar + 1
+ call tbrpti (tprout, colpoint[1], id[i], 1, rstar)
+ call tbrptr (tprout, colpoint[2], x[i], 1, rstar)
+ call tbrptr (tprout, colpoint[3], y[i], 1, rstar)
+ call tbrptr (tprout, colpoint[4], mag[i], 1, rstar)
+ call tbrptr (tprout, colpoint[5], err, 1, rstar)
+ call tbrptr (tprout, colpoint[6], sky[i], 1, rstar)
+ call tbrpti (tprout, colpoint[7], iter, 1, rstar)
+ call tbrptr (tprout, colpoint[8], sharp, 1, rstar)
+ call tbrptr (tprout, colpoint[9], chi[i], 1, rstar)
+ call tbrpti (tprout, colpoint[10], pier, 1, rstar)
+ call tbrptt (tprout, colpoint[11], Memc[perror], plen,
+ 1, rstar)
+ } else {
+ star = star + 1
+ call tbrpti (tpout, colpoint[1], id[i], 1, star)
+ call tbrptr (tpout, colpoint[2], x[i], 1, star)
+ call tbrptr (tpout, colpoint[3], y[i], 1, star)
+ call tbrptr (tpout, colpoint[4], mag[i], 1, star)
+ call tbrptr (tpout, colpoint[5], err, 1, star)
+ call tbrptr (tpout, colpoint[6], sky[i], 1, star)
+ call tbrpti (tpout, colpoint[7], iter, 1, star)
+ call tbrptr (tpout, colpoint[8], sharp, 1, star)
+ call tbrptr (tpout, colpoint[9], chi[i], 1, star)
+ call tbrpti (tpout, colpoint[10], pier, 1, star)
+ call tbrptt (tpout, colpoint[11], Memc[perror], plen,
+ 1, star)
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+define AL_DATA1STR "%-9d%10t%-10.3f%20t%-10.3f%30t%-12.3f%42t%-14.3f%56t%-15.7g%71t%-6d%80t\\\n"
+define AL_DATA2STR "%12t%-12.3f%24t%-12.3f%36t%-6d%42t%-13.13s%80t \n"
+
+# DP_XALWRITE -- Write out photometry record to an ALLSTAR text file.
+
+procedure dp_xalwrite (tpout, tprout, id, x, y, mag, magerr, sky, chi, numer,
+ denom, skip, aier, niter, istar, lstar, psfmag, csharp)
+
+int tpout # the output photometry file descriptor
+int tprout # the output rejections file descriptor
+int id[ARB] # array of ids
+real x[ARB] # array of xpositions
+real y[ARB] # array of y positions
+real mag[ARB] # array of magnitude values
+real magerr[ARB] # array of magnitudes
+real sky[ARB] # array of sky values
+real chi[ARB] # array of chi values
+real numer[ARB] # array of first numerator values
+real denom[ARB] # array of first denominator values
+int skip[ARB] # array of skipped stars
+int aier[ARB] # array of error codes
+int niter # number of iterations
+int istar, lstar # first and last stars
+real psfmag # magnitude of the psf
+real csharp # sharpness constant
+
+int i, iter, pier, plen
+pointer sp, perror
+real err, sharp
+int dp_gallerr()
+
+begin
+ call smark (sp)
+ call salloc (perror, SZ_FNAME, TY_CHAR)
+
+ do i = istar, lstar {
+
+ # Skip the star ?
+ if (skip[i] == NO)
+ next
+ if (IS_INDEFR(x[i]) || IS_INDEFR(y[i]))
+ next
+
+ if (IS_INDEFR(mag[i]) || mag[i] <= 0.0 || denom[i] == 0.) {
+ mag[i] = INDEFR
+ iter = 0
+ err = INDEFR
+ sharp = INDEFR
+ chi[i] = INDEFR
+ } else {
+ if (magerr[i] <= 0.0)
+ err = 0.0
+ else
+ err = 1.085736 * magerr[i] / mag[i]
+ sharp = csharp * numer[i] / (mag[i] * denom[i])
+ sharp = max (MIN_SHARP, min (sharp, MAX_SHARP))
+ mag[i] = psfmag - 2.5 * log10 (mag[i])
+ iter = niter
+ }
+ pier = aier[i]
+ plen = dp_gallerr (pier, Memc[perror], SZ_FNAME)
+
+ if ((tprout != NULL) && (pier != ALLERR_OK)) {
+ call fprintf (tprout, AL_DATA1STR)
+ call pargi (id[i])
+ call pargr (x[i])
+ call pargr (y[i])
+ call pargr (mag[i])
+ call pargr (err)
+ call pargr (sky[i])
+ call pargi (iter)
+ call fprintf (tprout, AL_DATA2STR)
+ call pargr (sharp)
+ call pargr (chi[i])
+ call pargi (pier)
+ call pargstr (Memc[perror])
+ } else {
+ call fprintf (tpout, AL_DATA1STR)
+ call pargi (id[i])
+ call pargr (x[i])
+ call pargr (y[i])
+ call pargr (mag[i])
+ call pargr (err)
+ call pargr (sky[i])
+ call pargi (iter)
+ call fprintf (tpout, AL_DATA2STR)
+ call pargr (sharp)
+ call pargr (chi[i])
+ call pargi (pier)
+ call pargstr (Memc[perror])
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# DP_GALLERR -- Set the ALLSTAR task error code string.
+
+int procedure dp_gallerr (ier, perror, maxch)
+
+int ier # the integer error code
+char perror # the output error code string
+int maxch # the maximum size of the error code string
+
+int plen
+int gstrcpy()
+
+begin
+ switch (ier) {
+ case ALLERR_OK:
+ plen = gstrcpy ("No_error", perror, maxch)
+ case ALLERR_BIGGROUP:
+ plen = gstrcpy ("Big_group", perror, maxch)
+ case ALLERR_INDEFSKY:
+ plen = gstrcpy ("Bad_sky", perror, maxch)
+ case ALLERR_NOPIX:
+ plen = gstrcpy ("Npix_too_few", perror, maxch)
+ case ALLERR_SINGULAR:
+ plen = gstrcpy ("Singular", perror, maxch)
+ case ALLERR_FAINT:
+ plen = gstrcpy ("Too_faint", perror, maxch)
+ case ALLERR_MERGE:
+ plen = gstrcpy ("Merged", perror, maxch)
+ case ALLERR_OFFIMAGE:
+ plen = gstrcpy ("Off_image", perror, maxch)
+ default:
+ plen = gstrcpy ("No_error", perror, maxch)
+ }
+
+ return (plen)
+end
diff --git a/noao/digiphot/daophot/allstar/dpastar.x b/noao/digiphot/daophot/allstar/dpastar.x
new file mode 100644
index 00000000..c8004f6d
--- /dev/null
+++ b/noao/digiphot/daophot/allstar/dpastar.x
@@ -0,0 +1,327 @@
+include <mach.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/allstardef.h"
+
+
+# DP_ASTAR -- Begin doing the photometry.
+
+procedure dp_astar (dao, im, subim, allfd, rejfd, cache, savesub, version)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+pointer subim # pointer to the subtracted image
+int allfd # file descriptor for the output photometry file
+int rejfd # file descriptor for rejections files
+int cache # cache the data ?
+int savesub # save the subtracted image ?
+int version # version number
+
+bool clip
+int nstar, row1_number, row2_number, niter, itsky, x1, x2, y1, y2, istar
+int lstar, ldummy, newsky
+pointer apsel, psffit, allstar, sp, indices, colpoints
+real fradius, sepcrt, sepmin, clmpmx, wcrit, radius, xmin, xmax, ymin, ymax
+real csharp, rdummy
+
+int dp_alphot(), dp_alnstar()
+pointer dp_gst(), dp_gwt(), dp_gdc()
+real dp_usepsf()
+
+begin
+ # Define some daophot structure pointers.
+ apsel = DP_APSEL(dao)
+ psffit = DP_PSFFIT (dao)
+ allstar = DP_ALLSTAR (dao)
+
+ # Store the original fitting radius
+ fradius = DP_FITRAD(dao)
+ DP_FITRAD(dao) = min (DP_FITRAD(dao), DP_PSFRAD(dao))
+ DP_SFITRAD(dao) = DP_FITRAD(dao) * DP_SCALE(dao)
+
+ # Get some working memory.
+ call smark (sp)
+ call salloc (indices, NAPPAR, TY_INT)
+ call salloc (colpoints, ALL_NOUTCOLUMN, TY_INT)
+
+ # Define some daophot constants.
+ nstar = DP_APNUM(apsel)
+ csharp = 1.4427 * Memr[DP_PSFPARS(psffit)] *
+ Memr[DP_PSFPARS(psffit)+1] / dp_usepsf (DP_PSFUNCTION(psffit), 0.0,
+ 0.0, DP_PSFHEIGHT(psffit), Memr[DP_PSFPARS(psffit)],
+ Memr[DP_PSFLUT(psffit)], DP_PSFSIZE(psffit), DP_NVLTABLE(psffit),
+ DP_NFEXTABLE(psffit), 0.0, 0.0, rdummy, rdummy)
+ if (IS_INDEFR(DP_MERGERAD(dao)))
+ sepcrt = 2.0 * (Memr[DP_PSFPARS(psffit)] ** 2 +
+ Memr[DP_PSFPARS(psffit)+1] ** 2)
+ else
+ sepcrt = DP_MERGERAD(dao) ** 2
+ sepmin = min (1.0, FRACTION_MINSEP * sepcrt)
+ itsky = 3
+
+ # Initialize the output photometry file for writing.
+ row1_number = 0
+ row2_number = 0
+ if (DP_TEXT(dao) == YES) {
+ call dp_xnewal (dao, allfd)
+ if (rejfd != NULL)
+ call dp_xnewal (dao, rejfd)
+ } else {
+ call dp_tnewal (dao, allfd, Memi[colpoints])
+ if (rejfd != NULL)
+ call dp_tnewal (dao, rejfd, Memi[colpoints])
+ }
+
+ # Allocate memory for the input, output and fitting arrays.
+ call dp_gnindices (Memi[indices])
+ call dp_rmemapsel (dao, Memi[indices], NAPPAR, nstar)
+ call dp_almemstar (dao, nstar, DP_MAXGROUP(dao))
+ call dp_cache (dao, im, subim, cache)
+
+ # Read in the input data and assign the initial weights.
+ call dp_setwt (dao, im)
+
+ # Convert the magnitudes to relative brightnesses.
+ call dp_alzero (dao, Memr[DP_APMAG(apsel)], nstar)
+
+ # Initialize all the fit/nofit indices and the error codes.
+ call amovki (NO, Memi[DP_ASKIP(allstar)], nstar)
+ call amovki (ALLERR_OK, Memi[DP_AIER(allstar)], nstar)
+
+ # Remove stars that have INDEF centers, are off the image altogether,
+ # or are too close to another star before beginning to fit.
+ call dp_strip (Memi[DP_APID(apsel)], Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMAG(apsel)],
+ Memr[DP_APMSKY(apsel)], Memi[DP_ASKIP(allstar)],
+ Memi[DP_AIER(allstar)], nstar, sepmin, int(IM_LEN(im,1)),
+ int(IM_LEN(im,2)), DP_FITRAD(dao), DP_VERBOSE(dao))
+
+ # Write out results for the rejected stars.
+ call dp_wout (dao, im, Memr[DP_APXCEN(apsel)+nstar],
+ Memr[DP_APYCEN(apsel)+nstar], Memr[DP_APXCEN(apsel)+nstar],
+ Memr[DP_APYCEN(apsel)+nstar], DP_APNUM(apsel) - nstar)
+ if (DP_TEXT(dao) == YES) {
+ call dp_xalwrite (allfd, rejfd, Memi[DP_APID(apsel)],
+ Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[DP_APMAG(apsel)], Memr[DP_APERR(apsel)],
+ Memr[DP_APMSKY(apsel)], Memr[DP_APCHI(apsel)],
+ Memr[DP_ANUMER(allstar)], Memr[DP_ADENOM(allstar)],
+ Memi[DP_ASKIP(allstar)], Memi[DP_AIER(allstar)], niter,
+ nstar + 1, DP_APNUM(apsel), DP_PSFMAG(psffit), csharp)
+ } else {
+ call dp_talwrite (allfd, rejfd, Memi[colpoints],
+ Memi[DP_APID(apsel)], Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMAG(apsel)],
+ Memr[DP_APERR(apsel)], Memr[DP_APMSKY(apsel)],
+ Memr[DP_APCHI(apsel)], Memr[DP_ANUMER(allstar)],
+ Memr[DP_ADENOM(allstar)], Memi[DP_ASKIP(allstar)],
+ Memi[DP_AIER(allstar)], niter, nstar + 1, DP_APNUM(apsel),
+ row1_number, row2_number, DP_PSFMAG(psffit), csharp)
+ }
+
+ # Do some initialization for the fit.
+ clmpmx = CLAMP_FRACTION * DP_FITRAD(dao)
+ call aclrr (Memr[DP_AXOLD(allstar)], nstar)
+ call aclrr (Memr[DP_AYOLD(allstar)], nstar)
+ call amovkr (clmpmx, Memr[DP_AXCLAMP(allstar)], nstar)
+ call amovkr (clmpmx, Memr[DP_AYCLAMP(allstar)], nstar)
+ call amovkr (1.0, Memr[DP_ASUMWT(allstar)], nstar)
+
+ # Begin iterating.
+ for (niter = 1; (nstar > 0) && (niter <= DP_MAXITER (dao));
+ niter = niter + 1) {
+
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("NITER = %d\n")
+ call pargi (niter)
+ }
+
+ if ((DP_CLIPEXP(dao) != 0) && (niter >= 4))
+ clip = true
+ else
+ clip = false
+
+ # Define the critical errors.
+ if (niter >= 15)
+ wcrit = WCRIT15
+ else if (niter >= 10)
+ wcrit = WCRIT10
+ else if (niter >= 5)
+ wcrit = WCRIT5
+ else
+ wcrit = WCRIT0
+
+ # Sort the data on y.
+ call dp_alsort (Memi[DP_APID(apsel)], Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMAG(apsel)],
+ Memr[DP_APMSKY(apsel)], Memr[DP_ASUMWT(allstar)],
+ Memr[DP_AXOLD(allstar)], Memr[DP_AYOLD(allstar)],
+ Memr[DP_AXCLAMP(allstar)], Memr[DP_AYCLAMP(allstar)], nstar)
+
+ # Compute the working radius. This is either the fitting radius
+ # or the outer sky radius if this is an iteration during which
+ # sky is to be determined whichever is larger.
+ if ((DP_FITSKY(dao) == YES) && (mod (niter, itsky) == 0)) {
+ newsky = YES
+ if ((DP_ANNULUS(dao) + DP_DANNULUS(dao)) > DP_FITRAD(dao))
+ radius = DP_ANNULUS(dao) + DP_DANNULUS(dao)
+ else
+ radius = DP_FITRAD(dao)
+ } else {
+ newsky = NO
+ radius = DP_FITRAD(dao)
+ }
+
+ # Define region of the image used to fit the remaining stars.
+ call alimr (Memr[DP_APXCEN(apsel)], nstar, xmin, xmax)
+ call alimr (Memr[DP_APYCEN(apsel)], nstar, ymin, ymax)
+ x1 = max (1, min (IM_LEN(im,1), int (xmin-radius)+1))
+ x2 = max (1, min (IM_LEN(im,1), int (xmax+radius)))
+ y1 = max (1, min (IM_LEN(im,2), int (ymin-radius)+1))
+ y2 = max (1, min (IM_LEN (im,2), int (ymax+radius)))
+
+ # Reinitialize the weight and scratch arrays / images .
+ call dp_wstinit (dao, im, Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMAG(apsel)],
+ nstar, radius, x1, x2, y1, y2)
+
+ # Recompute the initial sky estimates if that switch is enabled.
+ if (newsky == YES)
+ call dp_alsky (dao, im, Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMSKY(apsel)], nstar,
+ x1, x2, y1, y2, DP_ANNULUS(dao), DP_ANNULUS(dao) +
+ DP_DANNULUS(dao), 100, -MAX_REAL)
+
+ # Group the remaining stars.
+ call dp_regroup (Memi[DP_APID(apsel)], Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMAG(apsel)],
+ Memr[DP_APMSKY(apsel)], Memr[DP_ASUMWT(allstar)],
+ Memr[DP_AXOLD(allstar)], Memr[DP_AYOLD(allstar)],
+ Memr[DP_AXCLAMP(allstar)], Memr[DP_AYCLAMP(allstar)], nstar,
+ DP_FITRAD(dao), Memi[DP_ALAST(allstar)])
+
+ # Reset the error codes.
+ call amovki (ALLERR_OK, Memi[DP_AIER(allstar)], nstar)
+
+ # Do the serious fitting one group at a time.
+ for (istar = 1; istar <= nstar; istar = lstar + 1) {
+
+ # Do the fitting a group at a time.
+ lstar = dp_alphot (dao, im, nstar, istar, niter, sepcrt,
+ sepmin, wcrit, clip, clmpmx, version)
+
+ # Write the results.
+ if (DP_TEXT(dao) == YES) {
+ call dp_xalwrite (allfd, rejfd, Memi[DP_APID(apsel)],
+ Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[DP_APMAG(apsel)], Memr[DP_APERR(apsel)],
+ Memr[DP_APMSKY(apsel)], Memr[DP_APCHI(apsel)],
+ Memr[DP_ANUMER(allstar)], Memr[DP_ADENOM(allstar)],
+ Memi[DP_ASKIP(allstar)], Memi[DP_AIER(allstar)],
+ niter, istar, lstar, DP_PSFMAG(psffit), csharp)
+ } else {
+ call dp_talwrite (allfd, rejfd, Memi[colpoints],
+ Memi[DP_APID(apsel)], Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMAG(apsel)],
+ Memr[DP_APERR(apsel)], Memr[DP_APMSKY(apsel)],
+ Memr[DP_APCHI(apsel)], Memr[DP_ANUMER(allstar)],
+ Memr[DP_ADENOM(allstar)], Memi[DP_ASKIP(allstar)],
+ Memi[DP_AIER(allstar)], niter, istar, lstar, row1_number,
+ row2_number, DP_PSFMAG(psffit), csharp)
+ }
+
+ }
+
+ # Find the last star in the list that still needs more work.
+ nstar = dp_alnstar (Memi[DP_ASKIP(allstar)], nstar)
+
+ # Remove the fitted stars from the list.
+ for (istar = 1; (istar < nstar) && nstar > 0; istar = istar + 1) {
+ call dp_alswitch (Memi[DP_APID(apsel)],
+ Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[DP_APMAG(apsel)], Memr[DP_APERR(apsel)],
+ Memr[DP_APMSKY(apsel)], Memr[DP_ASUMWT(allstar)],
+ Memr[DP_AXOLD(allstar)], Memr[DP_AYOLD(allstar)],
+ Memr[DP_AXCLAMP(allstar)], Memr[DP_AYCLAMP(allstar)],
+ Memi[DP_ASKIP(allstar)], istar, nstar)
+ }
+
+ # Flush the output buffers.
+ if (dp_gwt (dao, im, ldummy, ldummy, READ_WRITE, YES) == NULL)
+ ;
+ if (dp_gst (dao, im, ldummy, ldummy, READ_ONLY, YES) == NULL)
+ ;
+ if (dp_gdc (dao, im, ldummy, ldummy, READ_WRITE, YES) == NULL)
+ ;
+ }
+
+ # Release cached memory.
+ call dp_uncache (dao, subim, savesub)
+
+ call sfree (sp)
+
+ # Restore the original fitting radius
+ DP_FITRAD(dao) = fradius
+ DP_SFITRAD(dao) = DP_FITRAD(dao) * DP_SCALE(dao)
+end
+
+
+# DP_ALNSTAR -- Compute the number of stars left
+
+int procedure dp_alnstar (skip, nstar)
+
+int skip[ARB] # skip array
+int nstar # number of stars
+
+begin
+ while (nstar > 0) {
+ if (skip[nstar] == NO)
+ break
+ nstar = nstar - 1
+ }
+
+ return (nstar)
+end
+
+
+# DP_ALSWITCH -- Switch array elements.
+
+procedure dp_alswitch (id, xcen, ycen, mag, magerr, sky, chi, xold, yold,
+ xclamp, yclamp, skip, istar, nstar)
+
+int id[ARB] # array of ids
+real xcen[ARB] # array of x centers
+real ycen[ARB] # array of y centers
+real mag[ARB] # array of magnitudes
+real magerr[ARB] # array of magnitude errors
+real sky[ARB] # array of sky values
+real chi[ARB] # array of chi values
+real xold[ARB] # old x array
+real yold[ARB] # old y array
+real xclamp[ARB] # array of x clamps
+real yclamp[ARB] # array of y clamps
+int skip[ARB] # skip array
+int istar # next star
+int nstar # total number of stars
+
+int dp_alnstar()
+
+begin
+ if (skip[istar] == YES) {
+ id[istar] = id[nstar]
+ xcen[istar] = xcen[nstar]
+ ycen[istar] = ycen[nstar]
+ mag[istar] = mag[nstar]
+ magerr[istar] = magerr[nstar]
+ sky[istar] = sky[nstar]
+ chi[istar] = chi[nstar]
+ xold[istar] = xold[nstar]
+ yold[istar] = yold[nstar]
+ xclamp[istar] = xclamp[nstar]
+ yclamp[istar] = yclamp[nstar]
+ skip[istar] = NO
+ nstar = nstar - 1
+ nstar = dp_alnstar (skip, nstar)
+ }
+end
diff --git a/noao/digiphot/daophot/allstar/dpcache.x b/noao/digiphot/daophot/allstar/dpcache.x
new file mode 100644
index 00000000..0782b98f
--- /dev/null
+++ b/noao/digiphot/daophot/allstar/dpcache.x
@@ -0,0 +1,244 @@
+include <imhdr.h>
+include <mach.h>
+include "../lib/allstardef.h"
+include "../lib/daophotdef.h"
+
+define FUDGE 1.2 # fudge factor for memory allocation
+
+# DP_CACHE -- Determine whether it is possible to store all the data
+# in memory or not.
+
+procedure dp_cache (dao, im, subim, cache)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+pointer subim # pointer to the output subtracted image
+int cache # cache the data ?
+
+int npix, req_mem1, req_mem2, req_mem3, old_mem, max_mem
+pointer sp, temp, allstar, data, weights, subt
+int sizeof(), begmem()
+pointer immap()
+errchk begmem(), calloc()
+
+begin
+ # Allocate some working memory.
+ call smark (sp)
+ call salloc (temp, SZ_FNAME, TY_CHAR)
+
+ # Define the allstar pointer.
+ allstar = DP_ALLSTAR(dao)
+
+ # Store the old working set size.
+ DP_SZOLDCACHE(allstar) = begmem (0, old_mem, max_mem)
+
+ # Figure out the memory requirements.
+ npix = IM_LEN(im,1) * IM_LEN(im,2)
+ req_mem1 = FUDGE * npix * sizeof (TY_REAL)
+ req_mem2 = req_mem1 + req_mem1
+ req_mem3 = req_mem2 + req_mem1
+
+ # Initialize.
+ DP_CACHE (allstar,A_DCOPY) = NO
+ DP_CACHE (allstar,A_SUBT) = NO
+ DP_CACHE (allstar,A_WEIGHT) = NO
+
+ DP_DBUF(allstar) = NULL
+ DP_SBUF(allstar) = NULL
+ DP_WBUF(allstar) = NULL
+
+ # Use IRAF images as temporary storage space.
+ if (cache == NO) {
+
+ # The output subtracted image.
+ DP_DATA (allstar) = subim
+
+ # The scratch image.
+ call mktemp ("subt", Memc[temp], SZ_FNAME)
+ DP_SUBT (allstar) = immap (Memc[temp], NEW_COPY, im)
+ IM_NDIM(DP_SUBT(allstar)) = 2
+ IM_PIXTYPE(DP_SUBT(allstar)) = TY_REAL
+
+ # The weights image.
+ call mktemp ("wt", Memc[temp], SZ_FNAME)
+ DP_WEIGHTS (allstar) = immap (Memc[temp], NEW_COPY, im)
+ IM_NDIM(DP_WEIGHTS(allstar)) = 2
+ IM_PIXTYPE(DP_WEIGHTS(allstar)) = TY_REAL
+
+ # Set the type of caching to be used.
+ DP_ISCACHE(allstar) = NO
+ DP_ALLCACHE(allstar) = NO
+
+ } else {
+
+ # Is the memory available.
+ if (old_mem >= req_mem3) {
+ DP_CACHE(allstar,A_DCOPY) = YES
+ DP_CACHE(allstar,A_WEIGHT) = YES
+ DP_CACHE (allstar,A_SUBT) = YES
+ } else {
+ if (begmem (req_mem1, old_mem, max_mem) >= req_mem1)
+ DP_CACHE(allstar,A_SUBT) = YES
+ if (begmem (req_mem2, old_mem, max_mem) >= req_mem2)
+ DP_CACHE(allstar,A_WEIGHT) = YES
+ if (begmem (req_mem3, old_mem, max_mem) >= req_mem3)
+ DP_CACHE(allstar,A_DCOPY) = YES
+ }
+
+ # Allocate space for the scratch image.
+ subt = NULL
+ if (DP_CACHE(allstar, A_SUBT) == YES) {
+ iferr {
+ call calloc (subt, npix, TY_REAL)
+ } then {
+ if (subt != NULL)
+ call mfree (subt, TY_REAL)
+ call mktemp ("subt", Memc[temp], SZ_FNAME)
+ subt = immap (Memc[temp], NEW_COPY, im)
+ IM_NDIM(subt) = 2
+ IM_PIXTYPE(subt) = TY_REAL
+ DP_SUBT(allstar) = subt
+ DP_CACHE(allstar,A_SUBT) = NO
+ } else
+ DP_SUBT(allstar) = subt
+ } else {
+ call mktemp ("subt", Memc[temp], SZ_FNAME)
+ subt = immap (Memc[temp], NEW_COPY, im)
+ IM_NDIM(subt) = 2
+ IM_PIXTYPE(subt) = TY_REAL
+ DP_SUBT(allstar) = subt
+ }
+
+ # Allocate space for the weights image.
+ weights = NULL
+ if (DP_CACHE(allstar, A_WEIGHT) == YES) {
+ iferr {
+ call calloc (weights, npix, TY_REAL)
+ } then {
+ if (weights != NULL)
+ call mfree (weights, TY_REAL)
+ call mktemp ("wt", Memc[temp], SZ_FNAME)
+ weights = immap (Memc[temp], NEW_COPY, im)
+ IM_NDIM(weights) = 2
+ IM_PIXTYPE(weights) = TY_REAL
+ DP_WEIGHTS(allstar) = weights
+ DP_CACHE(allstar,A_WEIGHT) = NO
+ } else
+ DP_WEIGHTS(allstar) = weights
+ } else {
+ call mktemp ("wt", Memc[temp], SZ_FNAME)
+ weights = immap (Memc[temp], NEW_COPY, im)
+ IM_NDIM(weights) = 2
+ IM_PIXTYPE(weights) = TY_REAL
+ DP_WEIGHTS(allstar) = weights
+ }
+
+ # Allocate space for the output subtracted image.
+ data = NULL
+ if (DP_CACHE(allstar, A_DCOPY) == YES) {
+ iferr {
+ call calloc (data, npix, TY_REAL)
+ } then {
+ if (data != NULL)
+ call mfree (data, TY_REAL)
+ DP_DATA(allstar) = subim
+ DP_CACHE(allstar,A_DCOPY) = NO
+ } else {
+ DP_DATA(allstar) = data
+ }
+ } else
+ DP_DATA(allstar) = subim
+
+ # Set the type of caching to be used.
+ if (DP_CACHE(allstar,A_DCOPY) == NO && DP_CACHE(allstar,A_SUBT) ==
+ NO && DP_CACHE(allstar,A_WEIGHT) == NO) {
+ DP_ISCACHE(allstar) = NO
+ DP_ALLCACHE(allstar) = NO
+ } else if (DP_CACHE(allstar,A_DCOPY) == YES && DP_CACHE(allstar,
+ A_SUBT) == YES && DP_CACHE(allstar,A_WEIGHT) == YES) {
+ DP_ISCACHE(allstar) = YES
+ DP_ALLCACHE(allstar) = YES
+ } else {
+ DP_ISCACHE(allstar) = YES
+ DP_ALLCACHE(allstar) = NO
+ }
+
+ }
+
+ call sfree (sp)
+end
+
+
+# DP_UNCACHE -- Release all the stored memory.
+
+procedure dp_uncache (dao, subim, savesub)
+
+pointer dao # pointer to the daophot strucuture
+pointer subim # pointer to the output subtracted image
+int savesub # save the subtracted image ?
+
+int j, ncol, nline
+pointer sp, imname, v, data, buf, allstar
+pointer impnlr()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+ call salloc (v, IM_MAXDIM, TY_LONG)
+
+ # Define the allstar pointer.
+ allstar = DP_ALLSTAR(dao)
+
+ ncol = IM_LEN(subim,1)
+ nline = IM_LEN(subim,2)
+
+ # Write out the subtracted image.
+ if (DP_CACHE(allstar,A_DCOPY) == YES && savesub == YES) {
+ data = DP_DBUF(allstar)
+ call amovkl (long(1), Meml[v], IM_MAXDIM)
+ do j = 1, nline {
+ if (impnlr (subim, buf, Meml[v]) != EOF)
+ call amovr (Memr[data], Memr[buf], ncol)
+ data = data + ncol
+ }
+ }
+ DP_DATA(allstar) = NULL
+
+ # Release any memory used by the subtracted image.
+ if (DP_DBUF(allstar) != NULL)
+ call mfree (DP_DBUF(allstar), TY_REAL)
+ DP_DBUF(allstar) = NULL
+
+ # Delete the scratch image if any.
+ if (DP_CACHE(allstar,A_SUBT) == NO) {
+ call strcpy (IM_HDRFILE(DP_SUBT(allstar)), Memc[imname], SZ_FNAME)
+ call imunmap (DP_SUBT(allstar))
+ call imdelete (Memc[imname])
+ }
+ DP_SUBT(allstar) = NULL
+
+ # Release any memory used by the scratch image.
+ if (DP_SBUF(allstar) != NULL)
+ call mfree (DP_SBUF(allstar), TY_REAL)
+ DP_SBUF(allstar) = NULL
+
+ # Delete the weights image if any.
+ if (DP_CACHE(allstar,A_WEIGHT) == NO) {
+ call strcpy (IM_HDRFILE(DP_WEIGHTS(allstar)), Memc[imname],
+ SZ_FNAME)
+ call imunmap (DP_WEIGHTS(allstar))
+ call imdelete (Memc[imname])
+ }
+ DP_WEIGHTS(allstar) = NULL
+
+ # Release any memory used by the weights buffer.
+ if (DP_WBUF(allstar) != NULL)
+ call mfree (DP_WBUF(allstar), TY_REAL)
+ DP_WBUF(allstar) = NULL
+
+ # Reset the working set size to the previous value.
+ call fixmem (DP_SZOLDCACHE(allstar))
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/allstar/dpglim.x b/noao/digiphot/daophot/allstar/dpglim.x
new file mode 100644
index 00000000..d5f1fedb
--- /dev/null
+++ b/noao/digiphot/daophot/allstar/dpglim.x
@@ -0,0 +1,17 @@
+# DP_GLIM -- Get the lower and upper limits of a section around a specified
+# center.
+
+procedure dp_glim (xc, yc, radius, ixmin, ixmax, iymin, iymax, lx, mx, ly, my)
+
+real xc, yc # the x and y center points
+real radius # the radial distance
+int ixmin, ixmax # absolute x boundaries
+int iymin, iymax # absolute y boundaries
+int lx, mx, ly, my # the returned limits
+
+begin
+ lx = max (ixmin - 1, min (ixmax, int (xc - radius))) + 1
+ mx = max (ixmin, min (ixmax, int (xc + radius)))
+ ly = max (iymin - 1, min (iymax, int (yc - radius))) + 1
+ my = max (iymin, min (iymax, int (yc + radius)))
+end
diff --git a/noao/digiphot/daophot/allstar/dprectify.x b/noao/digiphot/daophot/allstar/dprectify.x
new file mode 100644
index 00000000..5fd7c0db
--- /dev/null
+++ b/noao/digiphot/daophot/allstar/dprectify.x
@@ -0,0 +1,74 @@
+# DP_RECTIFY -- Shuffle a real vector based upon an input index vector using
+# dynamic memory.
+
+procedure dp_rectify (x, index, nitem)
+
+real x[ARB]
+int index[ARB]
+int nitem
+
+pointer sp, hold
+
+begin
+ call smark (sp)
+ call salloc (hold, nitem, TY_REAL)
+ call dp_dorect (x, Memr[hold], index, nitem)
+ call sfree (sp)
+end
+
+
+# DP_IRECTIFY -- Shuffle an integer vector based upon an input index vector
+# using dynamic memory.
+
+procedure dp_irectify (x, index, nitem)
+
+int x[ARB]
+int index[ARB]
+int nitem
+
+pointer sp, hold
+
+begin
+ call smark (sp)
+ call salloc (hold, nitem, TY_INT)
+ call dp_idorect (x, Memi[hold], index, nitem)
+ call sfree (sp)
+end
+
+
+# DP_DORECT -- Shuffle a vector based upon an input index vector using
+# a preallocated dummy array.
+
+procedure dp_dorect (x, hold, index, nitem)
+
+real x[ARB]
+real hold[ARB]
+int index[ARB]
+int nitem
+
+int i
+
+begin
+ call amovr (x, hold, nitem)
+ do i = 1, nitem
+ x[i] = hold[index[i]]
+end
+
+
+# DP_IDORECT -- Shuffle an integer vector based upon an input index vector
+# using a preallocated dummy array.
+
+procedure dp_idorect (x, hold, index, nitem)
+
+int x[ARB]
+int hold[ARB]
+int index[ARB]
+int nitem
+
+int i
+
+begin
+ call amovi (x, hold, nitem)
+ do i = 1, nitem
+ x[i] = hold[index[i]]
+end
diff --git a/noao/digiphot/daophot/allstar/dpregroup.x b/noao/digiphot/daophot/allstar/dpregroup.x
new file mode 100644
index 00000000..a7561fb8
--- /dev/null
+++ b/noao/digiphot/daophot/allstar/dpregroup.x
@@ -0,0 +1,219 @@
+# DP_ALSORT -- Sort the stars on the y coordinate.
+
+procedure dp_alsort (id, x, y, mag, sky, sumwt, dxold, dyold, xclamp, yclamp,
+ nstar)
+
+int id[ARB] # array if star ids
+real x[ARB] # array of star x values
+real y[ARB] # array of y values
+real mag[ARB] # array of star magnitudes
+real sky[ARB] # array of star sky values
+real sumwt[ARB] # array of weighted sums
+real dxold[ARB] # the previous star x array
+real dyold[ARB] # the previous star y array
+real xclamp[ARB] # the x array clamps
+real yclamp[ARB] # the y array clamps
+int nstar # the number of stars
+
+int ier
+pointer sp, index
+
+begin
+ # Allocate some working memory.
+ call smark (sp)
+ call salloc (index, nstar, TY_INT)
+
+ # Sort the star list on y.
+ call quick (y, nstar, Memi[index], ier)
+
+ # Recitfy the remaining arrays.
+ call dp_irectify (id, Memi[index], nstar)
+ call dp_rectify (x, Memi[index], nstar)
+ call dp_rectify (mag, Memi[index], nstar)
+ call dp_rectify (sky, Memi[index], nstar)
+ call dp_rectify (sumwt, Memi[index], nstar)
+ call dp_rectify (dxold, Memi[index], nstar)
+ call dp_rectify (dyold, Memi[index], nstar)
+ call dp_rectify (xclamp, Memi[index], nstar)
+ call dp_rectify (yclamp, Memi[index], nstar)
+
+ # Release memory.
+ call sfree (sp)
+end
+
+
+# DP_REGROUP -- Group stars into physical associations based on proximity.
+
+procedure dp_regroup (id, x, y, mag, sky, chi, dxold, dyold, xclamp, yclamp,
+ nstar, radius, last)
+
+int id[ARB] # array if star ids
+real x[ARB] # array of star x values
+real y[ARB] # array of y values
+real mag[ARB] # array of star magnitudes
+real sky[ARB] # array of star sky values
+real chi[ARB] # array of chis
+real dxold[ARB] # the previous star x array
+real dyold[ARB] # the previous star y array
+real xclamp[ARB] # the x array clamps
+real yclamp[ARB] # the y array clamps
+int nstar # the number of stars
+real radius # the fitting radius
+int last[ARB] # the last array (NO or YES for last star)
+
+int itop, itest, j, k, i, ier
+pointer sp, index
+real critrad, critradsq, xtest, ytest, dx, dy
+
+begin
+ # If there is only one stars its value of last is YES.
+ if (nstar <= 1) {
+ last[1] = YES
+ return
+ }
+
+ # Allocate some working memory.
+ call smark (sp)
+ call salloc (index, nstar, TY_INT)
+
+ # Compute the critical radius.
+ critrad = 2.0 * radius
+ critradsq = critrad * critrad
+
+ # Sort the star list on y and rectify the accompanying x array.
+ call quick (y, nstar, Memi[index], ier)
+ call dp_rectify (x, Memi[index], nstar)
+
+ # At this point the stars are in a stack NSTAR stars long. The
+ # variable ITEST will point to the position in the stack
+ # occupied by the star which is currently the center of a
+ # circle of the CRITRAD pixels, within which we are
+ # looking for other stars. ITEST starts out with a value of one.
+ # ITOP points to the top position in the stack of the
+ # stars which have not yet been assigned to groups. ITOP starts
+ # out with the value of 2. Each time through, the program goes
+ # down through the stack from ITOP and looks for stars within
+ # the critrad pixels from the star at stack position ITEST.
+ # When such a star is found, it changes places in the
+ # stack with the star at ITOP and ITOP is incremented by one.
+ # When the search reaches a star J such that Y(J) - Y(ITEST)
+ # > CRITRAD we know that no further stars will be found
+ # within the CRITRAD pixels, the pointer ITEST is incremented
+ # by one, and the search proceeds again from the new
+ # value of ITOP. If the pointer ITEST catches up with the
+ # pointer ITOP, then the current group is complete
+ # with the star at the position ITEST-1, and
+ # ITOP is incremented by one. If ITOP catches up with NSTAR
+ # the grouping process is complete.
+
+ itop = 2
+ do itest = 1, nstar {
+
+ # Initialize the last array.
+ last[itest] = NO
+
+ # ITEST has reached ITOP; so no other unassigned stars are
+ # within CRITRADIUS pixels of any member of the current
+ # group. The group is therefore complete. Signify this by
+ # setting LAST[ITEST-1] = YES, and incrementing the value of
+ # ITOP by one. If ITOP is greater than NSTAR at this point
+ # list is finished.
+
+ if (itest == itop) {
+ j = itest - 1
+ if (j > 0)
+ last[j] = YES
+ itop = itop + 1
+ if (itop > nstar) {
+ last[itest] = YES
+ break
+ }
+ }
+
+ # Now go through the list of unassigned stars, occupying
+ # positions ITOP through NSTAR in the stack, to look for
+ # stars within CRITRADIUS pixels of the star at
+ # position ITEST inthe stack. If one is found, move it
+ # up to stack position ITOP and increment ITOP by one.
+
+ xtest = x[itest]
+ ytest = y[itest]
+ j = itop
+
+ do i = j, nstar {
+
+ # Check the distance between the stars.
+ dy = y[i] - ytest
+ if (dy > critrad)
+ break
+ dx = x[i] - xtest
+ if (abs (dx) > critrad)
+ next
+ if ((dx * dx + dy * dy) > critradsq)
+ next
+
+ # This star is within CRITRAD pixels of the
+ # star at stack position ITEST. Therefore it is
+ # added to the current group by moving it up to position
+ # ITOP in the stack, where the pointer ITEST may reach it.
+
+ call dp_rgswap (itop, i, x, y, Memi[index])
+
+ # Now increment ITOP by 1 to point at the top most
+ # unassigned star in the stack.
+ itop = itop + 1
+ if (itop > nstar) {
+ do k = itest, nstar - 1
+ last[k] = NO
+ last[nstar] = YES
+ break
+ }
+ }
+
+ if (itop > nstar)
+ break
+ }
+
+ # Reorder the remaining arrays to match the x and y arrays.
+ call dp_irectify (id, Memi[index], nstar)
+ call dp_rectify (mag, Memi[index], nstar)
+ call dp_rectify (sky, Memi[index], nstar)
+ call dp_rectify (chi, Memi[index], nstar)
+ call dp_rectify (dxold, Memi[index], nstar)
+ call dp_rectify (dyold, Memi[index], nstar)
+ call dp_rectify (xclamp, Memi[index], nstar)
+ call dp_rectify (yclamp, Memi[index], nstar)
+
+ call sfree (sp)
+end
+
+
+# DP_RGSWAP -- Swap the i-th and j-th stars in the stack without otherwise
+# altering the order of the stars..
+
+procedure dp_rgswap (i, j, x, y, index)
+
+int i, j # indices of the two stars to be swapped
+real x[ARB] # the array of x values
+real y[ARB] # the array of y values
+int index[ARB] # the index array
+
+int ihold, k,l
+real xhold, yhold
+
+begin
+ xhold = x[j]
+ yhold = y[j]
+ ihold = index[j]
+
+ do k = j, i + 1, -1 {
+ l = k - 1
+ x[k] = x[l]
+ y[k] = y[l]
+ index[k] = index[l]
+ }
+
+ x[i] = xhold
+ y[i] = yhold
+ index[i] = ihold
+end
diff --git a/noao/digiphot/daophot/allstar/mkpkg b/noao/digiphot/daophot/allstar/mkpkg
new file mode 100644
index 00000000..d607592b
--- /dev/null
+++ b/noao/digiphot/daophot/allstar/mkpkg
@@ -0,0 +1,32 @@
+# ALLSTAR task
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ dpabuf.x <imhdr.h> ../lib/daophotdef.h \
+ ../lib/allstardef.h
+ dpaconfirm.x ../lib/daophotdef.h
+ dpcache.x <imhdr.h> <mach.h> \
+ ../lib/daophotdef.h ../lib/allstardef.h
+ dpregroup.x
+ dprectify.x
+ dpalwrite.x <tbset.h> <time.h> \
+ ../lib/daophotdef.h ../lib/apseldef.h \
+ ../lib/allstardef.h
+ dpastar.x <mach.h> <imhdr.h> \
+ ../lib/daophotdef.h ../lib/allstardef.h \
+ ../lib/apseldef.h
+ dpalphot.x <mach.h> <imhdr.h> \
+ ../lib/daophotdef.h ../lib/apseldef.h \
+ ../lib/allstardef.h
+ dpalinit.x <imhdr.h> <mach.h> \
+ <math.h> ../lib/daophotdef.h \
+ ../lib/allstardef.h
+ dpglim.x
+ dpalmemstar.x ../lib/daophotdef.h ../lib/allstardef.h
+ t_allstar.x <fset.h> ../lib/daophotdef.h \
+ <imhdr.h>
+ ;
diff --git a/noao/digiphot/daophot/allstar/t_allstar.x b/noao/digiphot/daophot/allstar/t_allstar.x
new file mode 100644
index 00000000..b3991179
--- /dev/null
+++ b/noao/digiphot/daophot/allstar/t_allstar.x
@@ -0,0 +1,355 @@
+include <imhdr.h>
+include <fset.h>
+include "../lib/daophotdef.h"
+
+# T_ALLSTAR -- Group a list of stars into physical associations, fit the PSF
+# to the stars in each group simultaneously, and produce an output subtracted
+# image.
+
+procedure t_allstar ()
+
+pointer image # the input image
+pointer psfimage # the input psf image
+pointer photfile # the input photometry file
+pointer allstarfile # the output photometry file
+pointer subimage # the output subtracted image
+pointer rejfile # the output rejections file
+int cache # cache the data in memory
+int verbose # verbose mode ?
+int verify # verify critical task parameters ?
+int update # update the task parameters ?
+int version # version number
+
+pointer sp, outfname, im, subim, dao, str
+int imlist, limlist, alist, lalist, pimlist, lpimlist, olist, lolist
+int simlist, lsimlist, rlist, lrlist, photfd, psffd, allfd, root, savesub
+int rejfd, wcs
+bool ap_text
+
+pointer immap(), tbtopn()
+int clgwrd(), clgeti()
+int open(), fnldir(), strncmp(), strlen(), btoi(), access()
+int fstati(), imtopen, imtlen(), imtgetim(), fntopnb(), fntlenb()
+int fntgfnb()
+bool itob(), clgetb()
+
+begin
+ # Set the standard output to flush on newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get some working memory.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (psfimage, SZ_FNAME, TY_CHAR)
+ call salloc (photfile, SZ_FNAME, TY_CHAR)
+ call salloc (allstarfile, SZ_FNAME, TY_CHAR)
+ call salloc (rejfile, SZ_FNAME, TY_CHAR)
+ call salloc (subimage, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Get the task input and output file names.
+ call clgstr ("image", Memc[image], SZ_FNAME)
+ call clgstr ("photfile", Memc[photfile], SZ_FNAME)
+ call clgstr ("psfimage", Memc[psfimage], SZ_FNAME)
+ call clgstr ("allstarfile", Memc[allstarfile], SZ_FNAME)
+ call clgstr ("subimage", Memc[subimage], SZ_FNAME)
+ call clgstr ("rejfile", Memc[rejfile], SZ_FNAME)
+
+ # Get the task mode parameters.
+ verbose = btoi (clgetb ("verbose"))
+ verify = btoi (clgetb ("verify"))
+ update = btoi (clgetb ("update"))
+ cache = btoi (clgetb ("cache"))
+ version = clgeti ("version")
+ version = 2
+
+ # Get the lists.
+ imlist = imtopen (Memc[image])
+ limlist = imtlen (imlist)
+ alist = fntopnb (Memc[photfile], NO)
+ lalist = fntlenb (alist)
+ pimlist = imtopen (Memc[psfimage])
+ lpimlist = imtlen (pimlist)
+ olist = fntopnb (Memc[allstarfile], NO)
+ lolist = fntlenb (olist)
+ simlist = imtopen (Memc[subimage])
+ lsimlist = imtlen (simlist)
+ rlist = fntopnb (Memc[rejfile], NO)
+ lrlist = fntlenb (rlist)
+
+ # Test the lengths of the photometry file, psf image and subtracted
+ # image lists are the same as the length of the input image.
+
+ if ((limlist != lalist) && (strncmp (Memc[photfile], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (rlist)
+ call imtclose (simlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatible image and photometry file list lengths")
+ }
+
+ if ((limlist != lpimlist) && (strncmp (Memc[psfimage], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (rlist)
+ call imtclose (simlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatible image and psf file list lengths")
+ }
+
+ if ((limlist != lsimlist) && (strncmp (Memc[subimage], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (rlist)
+ call imtclose (simlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatible image and subtracted image list lengths")
+ }
+
+ if ((limlist != lolist) && (strncmp (Memc[allstarfile], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (rlist)
+ call imtclose (simlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatible image and subtracted image list lengths")
+ }
+
+ if ((lrlist > 0) && (limlist != lrlist) && (strncmp (Memc[rejfile],
+ DEF_DEFNAME, DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (rlist)
+ call imtclose (simlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatible image and subtracted image list lengths")
+ }
+
+ # Open the input image, initialize the daophot structure, get the
+ # pset parameters
+
+ call dp_gppars (dao)
+
+ # Set some parameters.
+ call dp_seti (dao, VERBOSE, verbose)
+
+ # Verify and update the parameters as appropriate.
+ if (verify == YES) {
+ call dp_aconfirm (dao)
+ if (update == YES)
+ call dp_pppars (dao)
+ }
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_FNAME, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_FNAME, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSOUT, wcs)
+ wcs = clgwrd ("wcspsf", Memc[str], SZ_FNAME, WCSPSFSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the psf coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSPSF, wcs)
+
+ # Initialize the PSF structure.
+ call dp_fitsetup (dao)
+
+ # Initialize the daophot fitting structure.
+ call dp_apsetup (dao)
+
+ # Initialize the allstar structure.
+ call dp_allstarsetup (dao)
+
+ # Loop over the images.
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open the image and store some header parameters.
+ im = immap (Memc[image], READ_ONLY, 0)
+ call dp_imkeys (dao, im)
+ call dp_sets (dao, INIMAGE, Memc[image])
+
+ # Open the input photometry file.
+ if (fntgfnb (alist, Memc[photfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[photfile], SZ_FNAME)
+ root = fnldir (Memc[photfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[photfile+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[photfile]))
+ call dp_inname (Memc[image], Memc[outfname], "mag",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[photfile], Memc[outfname], SZ_FNAME)
+ ap_text = itob (access (Memc[outfname], 0, TEXT_FILE))
+ if (ap_text)
+ photfd = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ else
+ photfd = tbtopn (Memc[outfname], READ_ONLY, 0)
+ call dp_sets (dao, INPHOTFILE, Memc[outfname])
+ call dp_wgetapert (dao, im, photfd, DP_MAXNSTAR(dao), ap_text)
+
+ # Open the PSF image and read in the PSF.
+ if (imtgetim (pimlist, Memc[psfimage], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[psfimage], SZ_FNAME)
+ root = fnldir (Memc[psfimage], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[psfimage+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[psfimage]))
+ call dp_iimname (Memc[image], Memc[outfname], "psf",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[psfimage], Memc[outfname], SZ_FNAME)
+ psffd = immap (Memc[outfname], READ_ONLY, 0)
+ call dp_sets (dao, PSFIMAGE, Memc[outfname])
+ call dp_readpsf (dao, psffd)
+
+ # Open the output ALLSTAR file. If the output is DEF_DEFNAME,
+ # dir$default or a directory specification then the extension
+ # "als" is added to the image name and a suitable version
+ # number if appended to the output name.
+
+ if (fntgfnb (olist, Memc[allstarfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[allstarfile], SZ_FNAME)
+ root = fnldir (Memc[allstarfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[allstarfile+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[allstarfile]))
+ call dp_outname (Memc[image], Memc[outfname], "als",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[allstarfile], Memc[outfname], SZ_FNAME)
+ if (DP_TEXT(dao) == YES)
+ allfd = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ else
+ allfd = tbtopn (Memc[outfname], NEW_FILE, 0)
+ call dp_sets (dao, OUTPHOTFILE, Memc[outfname])
+
+ if (lrlist <= 0) {
+ rejfd = NULL
+ Memc[outfname] = EOS
+ } else {
+ if (fntgfnb (rlist, Memc[rejfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[rejfile], SZ_FNAME)
+ root = fnldir (Memc[rejfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[rejfile+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[rejfile]))
+ call dp_outname (Memc[image], Memc[outfname], "arj",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[rejfile], Memc[outfname], SZ_FNAME)
+ if (DP_TEXT(dao) == YES)
+ rejfd = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ else
+ rejfd = tbtopn (Memc[outfname], NEW_FILE, 0)
+ }
+ call dp_sets (dao, OUTREJFILE, Memc[outfname])
+
+ # Open the subtracted image.
+ savesub = YES
+ if (imtgetim (simlist, Memc[subimage], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[subimage], SZ_FNAME)
+ root = fnldir (Memc[subimage], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[subimage+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[subimage])) {
+ call dp_oimname (Memc[image], Memc[outfname], "sub",
+ Memc[outfname], SZ_FNAME)
+ subim = immap (Memc[outfname], NEW_COPY, im)
+ IM_NDIM(subim) = 2
+ IM_PIXTYPE(subim) = TY_REAL
+ } else {
+ call strcpy (Memc[subimage], Memc[outfname], SZ_FNAME)
+ subim = immap (Memc[outfname], NEW_COPY, im)
+ IM_NDIM(subim) = 2
+ IM_PIXTYPE(subim) = TY_REAL
+ }
+ call dp_sets (dao, OUTIMAGE, Memc[outfname])
+
+ # Fit the stars.
+ call dp_astar (dao, im, subim, allfd, rejfd, cache, savesub,
+ version)
+
+ # Close the input image.
+ call imunmap (im)
+
+ # Close the input photometry file.
+ if (ap_text)
+ call close (photfd)
+ else
+ call tbtclo (photfd)
+
+ # Close PSF image.
+ call imunmap (psffd)
+
+ # Close the output photometry file.
+ if (DP_TEXT(dao) == YES)
+ call close (allfd)
+ else
+ call tbtclo (allfd)
+
+ # Close the output rejections files.
+ if (rejfd != NULL) {
+ if (DP_TEXT(dao) == YES)
+ call close (rejfd)
+ else
+ call tbtclo (rejfd)
+ }
+
+ # Close the output subtracted image.
+ call strcpy (IM_HDRFILE(subim), Memc[subimage], SZ_FNAME)
+ call imunmap (subim)
+ if (savesub == NO)
+ call imdelete (Memc[subimage])
+ }
+
+ # Close the file/image lists.
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (rlist)
+ call imtclose (simlist)
+
+ # Close the allstar structure.
+ call dp_alclose (dao)
+
+ # Close the photometry structure.
+ call dp_apclose (dao)
+
+ # Close the PSF structure.
+ call dp_fitclose (dao)
+
+ # Close up the daophot structure.
+ call dp_free (dao)
+
+ call sfree(sp)
+end
diff --git a/noao/digiphot/daophot/centerpars.par b/noao/digiphot/daophot/centerpars.par
new file mode 100644
index 00000000..b7ff737a
--- /dev/null
+++ b/noao/digiphot/daophot/centerpars.par
@@ -0,0 +1,12 @@
+calgorithm,s,h,"none","|centroid|gauss|none|ofilter|",,Centering algorithm
+cbox,r,h,5.0,,,Centering box width in scale units
+cthreshold,r,h,0.0,,,Centering threshold in sigma above background
+minsnratio,r,h,1.0,0.0,,Minimum signal-to-noise ratio for centering algorithim
+cmaxiter,i,h,10,,,Maximum iterations for centering algorithm
+maxshift,r,h,1.0,,,Maximum center shift in scale units
+clean,b,h,no,,,Symmetry clean before centering
+rclean,r,h,1.0,,,Cleaning radius in scale units
+rclip,r,h,2.0,,,Clipping radius in scale units
+kclean,r,h,3.0,,,K-sigma rejection criterion in skysigma
+mkcenter,b,h,no,,,Mark the computed center
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/daoedit.par b/noao/digiphot/daophot/daoedit.par
new file mode 100644
index 00000000..52723991
--- /dev/null
+++ b/noao/digiphot/daophot/daoedit.par
@@ -0,0 +1,9 @@
+# DAOEDIT parameters
+
+image,f,a,,,,Input image
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor: [x y wcs] key [cmd]"
+cache,b,h,)_.cache,,,"Cache the image pixels?"
+graphics,s,h,)_.graphics,,,Graphics device
+display,s,h,)_.display,,,Display device
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/daoedit/daoedit.h b/noao/digiphot/daophot/daoedit/daoedit.h
new file mode 100644
index 00000000..c373f7c8
--- /dev/null
+++ b/noao/digiphot/daophot/daoedit/daoedit.h
@@ -0,0 +1,123 @@
+# The definitions file for the DAOEDIT task
+# At some point this should become paert of daophotdef.h
+
+define PSET_LIST "|datapars|centerpars|fitskypars|photpars|daopars|\
+findpars|"
+
+define PSET_DATAPARS 1
+define PSET_CENTERPARS 2
+define PSET_FITSKYPARS 3
+define PSET_PHOTPARS 4
+define PSET_DAOPARS 5
+define PSET_FINDPARS 6
+
+define CMD_LIST "|lpar|epar|unlearn|scale|fwhmpsf|emission|sigma|datamin|\
+datamax|noise|ccdread|gain|readnoise|epadu|exposure|airmass|filter|obstime|\
+itime|xairmass|ifilter|otime|calgorithm|cbox|cthreshold|maxshift|minsnratio|\
+cmaxiter|clean|rclean|rclip|kclean|mkcenter|salgorithm|annulus|\
+dannulus|skyvalue|smaxiter|sloclip|shiclip|snreject|sloreject|shireject|\
+khist|binsize|smooth|rgrow|mksky|weighting|apertures|zmag|mkapert|\
+function|varorder|nclean|saturated|matchrad|psfrad|fitrad|recenter|fitsky|\
+groupsky|sannulus|wsannulus|flaterr|proferr|maxiter|clipexp|cliprange|\
+critoverlap|maxnstar|maxgroup|threshold|nsigma|ratio|theta|sharplo|sharphi|\
+roundlo|roundhi|mkdetections|"
+
+define CMD_LPAR 1
+define CMD_EPAR 2
+define CMD_UNLEARN 3
+
+define CMD_SCALE 4
+define CMD_FWHMPSF 5
+define CMD_EMISSION 6
+define CMD_SIGMA 7
+define CMD_DATAMIN 8
+define CMD_DATAMAX 9
+define CMD_NOISE 10
+define CMD_CCDREAD 11
+define CMD_GAIN 12
+define CMD_READNOISE 13
+define CMD_EPADU 14
+define CMD_EXPOSURE 15
+define CMD_AIRMASS 16
+define CMD_FILTER 17
+define CMD_OBSTIME 18
+define CMD_ITIME 19
+define CMD_XAIRMASS 20
+define CMD_IFILTER 21
+define CMD_OTIME 22
+
+define CMD_CALGORITHM 23
+define CMD_CBOX 24
+define CMD_CTHRESHOLD 25
+define CMD_MAXSHIFT 26
+define CMD_MINSNRATIO 27
+define CMD_CMAXITER 28
+define CMD_CLEAN 29
+define CMD_RCLEAN 30
+define CMD_RCLIP 31
+define CMD_KCLEAN 32
+define CMD_MKCENTER 33
+
+define CMD_SALGORITHM 34
+define CMD_ANNULUS 35
+define CMD_DANNULUS 36
+define CMD_SKYVALUE 37
+define CMD_SMAXITER 38
+define CMD_SLOCLIP 39
+define CMD_SHICLIP 40
+define CMD_SNREJECT 41
+define CMD_SLOREJECT 42
+define CMD_SHIREJECT 43
+define CMD_KHIST 44
+define CMD_BINSIZE 45
+define CMD_SMOOTH 46
+define CMD_RGROW 47
+define CMD_MKSKY 48
+
+define CMD_WEIGHTING 49
+define CMD_APERTURES 50
+define CMD_ZMAG 51
+define CMD_MKAPERT 52
+
+define CMD_FUNCTION 53
+define CMD_VARORDER 54
+define CMD_NCLEAN 55
+define CMD_SATURATED 56
+define CMD_MATCHRAD 57
+define CMD_PSFRAD 58
+define CMD_FITRAD 59
+define CMD_RECENTER 60
+define CMD_FITSKY 61
+define CMD_GROUPSKY 62
+define CMD_SANNULUS 63
+define CMD_WSANNULUS 64
+define CMD_FLATERR 65
+define CMD_PROFERR 66
+define CMD_MAXITER 67
+define CMD_CLIPEXP 68
+define CMD_CLIPRANGE 69
+define CMD_CRITOVERLAP 70
+define CMD_MAXNSTAR 71
+define CMD_MAXGROUP 72
+
+define CMD_THRESHOLD 73
+define CMD_NSIGMA 74
+define CMD_RATIO 75
+define CMD_THETA 76
+define CMD_SHARPLO 77
+define CMD_SHARPHI 78
+define CMD_ROUNDLO 79
+define CMD_ROUNDHI 80
+define CMD_MKDETECTIONS 81
+
+# define the different WCSS for the radial profile plots
+
+define WCS_XPIX 1
+define WCS_XSCALE 2
+
+define WCS_YCOUNT 1
+define WCS_YNORM 2
+
+# miscellaneous definitions
+
+define MAX_NAPERTS 100
diff --git a/noao/digiphot/daophot/daoedit/daoedit.key b/noao/digiphot/daophot/daoedit/daoedit.key
new file mode 100644
index 00000000..bd2f6b95
--- /dev/null
+++ b/noao/digiphot/daophot/daoedit/daoedit.key
@@ -0,0 +1,26 @@
+ Daoedit Commands
+
+? Print help
+: Colon commands
+i Interactive parameter setup menu
+a Estimate center, sky, skysigma, fwhmpsf and magnitude of a star
+r Plot the radial profile of an object and its integral
+g Toggle between image and graphics cursor
+x Toggle radial profile plot between pixel and scale units
+y Toggle radial profile plot between counts and normal units
+q Quit task
+
+ Colon Commands
+
+:lparam/eparam/unlearn pset List/edit/unlearn the named pset
+:parameter [value] List or set an individual pset parameter
+
+
+ Named Parameter Sets
+
+datapars The data dependent parameters
+findpars The daofind task object detection parameters
+centerpars The phot task centering algorithm parameters
+fitskypars The phot task sky fitting algorithm parameters
+photpars The phot task photometry algroithm parameters
+daopars The psf fitting algorithm parameters
diff --git a/noao/digiphot/daophot/daoedit/dpecolon.x b/noao/digiphot/daophot/daoedit/dpecolon.x
new file mode 100644
index 00000000..36bccdf9
--- /dev/null
+++ b/noao/digiphot/daophot/daoedit/dpecolon.x
@@ -0,0 +1,441 @@
+include <error.h>
+include "daoedit.h"
+
+# DP_ECOLON -- Show/set the DAOPHOT algorithm parameters.
+
+procedure dp_ecolon (cmdstr, gd, redraw)
+
+char cmdstr[ARB] # input colon command
+int gd # pointer to the graphics stream
+int redraw # redraw the radial profile plot
+
+bool bval
+int cmd, pset, ival
+pointer sp, incmd, param, value
+real rval
+bool clgetb()
+int strdic(), nscan(), clgeti()
+real clgetr()
+string datapars "datapars"
+string centerpars "centerpars"
+string fitskypars "fitskypars"
+string photpars "photpars"
+string daopars "daopars"
+string findpars "findpars"
+
+begin
+ call smark (sp)
+ call salloc (incmd, SZ_LINE, TY_CHAR)
+ call salloc (param, SZ_LINE, TY_CHAR)
+ call salloc (value, SZ_LINE, TY_CHAR)
+
+ # Get the command.
+ call sscan (cmdstr)
+ call gargwrd (Memc[incmd], SZ_LINE)
+ if (Memc[incmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ cmd = strdic (Memc[incmd], Memc[incmd], SZ_LINE, CMD_LIST)
+ switch (cmd) {
+ case CMD_LPAR:
+ call gargwrd (Memc[incmd], SZ_LINE)
+ pset = strdic (Memc[incmd], Memc[incmd], SZ_LINE, PSET_LIST)
+ if (pset != 0)
+ call gdeactivate (gd, 0)
+ switch (pset) {
+ case PSET_DATAPARS:
+ call clcmdw ("lparam datapars")
+ case PSET_CENTERPARS:
+ call clcmdw ("lparam centerpars")
+ case PSET_FITSKYPARS:
+ call clcmdw ("lparam fitskypars")
+ case PSET_PHOTPARS:
+ call clcmdw ("lparam photpars")
+ case PSET_DAOPARS:
+ call clcmdw ("lparam daopars")
+ case PSET_FINDPARS:
+ call clcmdw ("lparam findpars")
+ default:
+ call printf ("Unknown parameter set\7\n")
+ }
+
+ case CMD_EPAR:
+ call gargwrd (Memc[incmd], SZ_LINE)
+ pset = strdic (Memc[incmd], Memc[incmd], SZ_LINE, PSET_LIST)
+ if (pset != 0)
+ call gdeactivate (gd, 0)
+ switch (pset) {
+ case PSET_DATAPARS:
+ call clcmdw ("eparam datapars")
+ case PSET_CENTERPARS:
+ call clcmdw ("eparam centerpars")
+ case PSET_FITSKYPARS:
+ call clcmdw ("eparam fitskypars")
+ case PSET_PHOTPARS:
+ call clcmdw ("eparam photpars")
+ case PSET_DAOPARS:
+ call clcmdw ("eparam daopars")
+ case PSET_FINDPARS:
+ call clcmdw ("eparam findpars")
+ default:
+ call printf ("Unknown parameter set\7\n")
+ }
+ if (pset != 0)
+ redraw = YES
+
+ case CMD_UNLEARN:
+ call gargwrd (Memc[incmd], SZ_LINE)
+ pset = strdic (Memc[incmd], Memc[incmd], SZ_LINE, PSET_LIST)
+ switch (pset) {
+ case PSET_DATAPARS:
+ call clcmdw ("unlearn datapars")
+ case PSET_CENTERPARS:
+ call clcmdw ("unlearn centerpars")
+ case PSET_FITSKYPARS:
+ call clcmdw ("unlearn fitskypars")
+ case PSET_PHOTPARS:
+ call clcmdw ("unlearn photpars")
+ case PSET_DAOPARS:
+ call clcmdw ("unlearn daopars")
+ case PSET_FINDPARS:
+ call clcmdw ("unlearn findpars")
+ default:
+ call printf ("Unknown parameter set\7\n")
+ }
+ if (pset != 0)
+ redraw = YES
+
+ case CMD_SCALE:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (datapars)
+ call pargstr (Memc[incmd])
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (Memc[incmd])
+ call pargr (clgetr (Memc[param]))
+ } else {
+ call clputr (Memc[param], rval)
+ redraw = YES
+ }
+
+ case CMD_FWHMPSF, CMD_SIGMA, CMD_DATAMIN, CMD_DATAMAX,
+ CMD_READNOISE, CMD_EPADU, CMD_ITIME, CMD_XAIRMASS:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (datapars)
+ call pargstr (Memc[incmd])
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (Memc[incmd])
+ call pargr (clgetr (Memc[param]))
+ } else
+ call clputr (Memc[param], rval)
+
+ case CMD_EMISSION:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (datapars)
+ call pargstr (Memc[incmd])
+ call gargb (bval)
+ if (nscan() == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (Memc[incmd])
+ call pargb (clgetb (Memc[param]))
+ } else
+ call clputb (Memc[param], bval)
+
+ case CMD_NOISE:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (datapars)
+ call pargstr (Memc[incmd])
+ call clgstr (Memc[param], Memc[value], SZ_LINE)
+ call printf ("%s = %s\n")
+ call pargstr (Memc[incmd])
+ call pargstr (Memc[value])
+
+ case CMD_CCDREAD, CMD_GAIN, CMD_EXPOSURE, CMD_AIRMASS, CMD_FILTER,
+ CMD_OBSTIME, CMD_IFILTER, CMD_OTIME:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (datapars)
+ call pargstr (Memc[incmd])
+ call gargwrd (Memc[value], SZ_LINE)
+ if (nscan() == 1) {
+ call clgstr (Memc[param], Memc[value], SZ_LINE)
+ call printf ("%s = \"%s\"\n")
+ call pargstr (Memc[incmd])
+ call pargstr (Memc[value])
+ } else
+ call clpstr (Memc[param], Memc[value])
+
+ case CMD_CALGORITHM:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (centerpars)
+ call pargstr (Memc[incmd])
+ call gargwrd (Memc[value], SZ_LINE)
+ if (nscan() == 1) {
+ call clgstr (Memc[param], Memc[value], SZ_LINE)
+ call printf ("%s = \"%s\"\n")
+ call pargstr (Memc[incmd])
+ call pargstr (Memc[value])
+ } else {
+ call clpstr (Memc[param], Memc[value])
+ }
+
+ case CMD_CBOX:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (centerpars)
+ call pargstr (Memc[incmd])
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (Memc[incmd])
+ call pargr (clgetr (Memc[param]))
+ } else {
+ call clputr (Memc[param], rval)
+ redraw = YES
+ }
+
+ case CMD_CTHRESHOLD, CMD_MAXSHIFT, CMD_MINSNRATIO, CMD_RCLEAN,
+ CMD_RCLIP, CMD_KCLEAN:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (centerpars)
+ call pargstr (Memc[incmd])
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (Memc[incmd])
+ call pargr (clgetr (Memc[param]))
+ } else
+ call clputr (Memc[param], rval)
+
+ case CMD_CMAXITER:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (centerpars)
+ call pargstr (Memc[incmd])
+ call gargi (ival)
+ if (nscan() == 1) {
+ call printf ("%s = %d\n")
+ call pargstr (Memc[incmd])
+ call pargi (clgeti (Memc[param]))
+ } else
+ call clputi (Memc[param], ival)
+
+ case CMD_CLEAN, CMD_MKCENTER:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (centerpars)
+ call pargstr (Memc[incmd])
+ call gargb (bval)
+ if (nscan() == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (Memc[incmd])
+ call pargb (clgetb (Memc[param]))
+ } else
+ call clputb (Memc[param], bval)
+
+ case CMD_SALGORITHM:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (fitskypars)
+ call pargstr (Memc[incmd])
+ call gargwrd (Memc[value], SZ_LINE)
+ if (nscan() == 1) {
+ call clgstr (Memc[param], Memc[value], SZ_LINE)
+ call printf ("%s = \"%s\"\n")
+ call pargstr (Memc[incmd])
+ call pargstr (Memc[value])
+ } else {
+ call clpstr (Memc[param], Memc[value])
+ call clgstr (Memc[param], Memc[value], SZ_LINE)
+ }
+
+ case CMD_ANNULUS, CMD_DANNULUS:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (fitskypars)
+ call pargstr (Memc[incmd])
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (Memc[incmd])
+ call pargr (clgetr (Memc[param]))
+ } else {
+ call clputr (Memc[param], rval)
+ redraw = YES
+ }
+
+ case CMD_SLOCLIP, CMD_SHICLIP, CMD_SLOREJECT, CMD_SHIREJECT,
+ CMD_KHIST, CMD_BINSIZE, CMD_SKYVALUE, CMD_RGROW:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (fitskypars)
+ call pargstr (Memc[incmd])
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (Memc[incmd])
+ call pargr (clgetr (Memc[param]))
+ } else
+ call clputr (Memc[param], rval)
+
+ case CMD_SMAXITER, CMD_SNREJECT:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (fitskypars)
+ call pargstr (Memc[incmd])
+ call gargi (ival)
+ if (nscan() == 1) {
+ call printf ("%s = %d\n")
+ call pargstr (Memc[incmd])
+ call pargi (clgeti (Memc[param]))
+ } else
+ call clputi (Memc[param], ival)
+
+ case CMD_SMOOTH, CMD_MKSKY:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (fitskypars)
+ call pargstr (Memc[incmd])
+ call gargb (bval)
+ if (nscan() == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (Memc[incmd])
+ call pargb (clgetb (Memc[param]))
+ } else
+ call clputb (Memc[param], bval)
+
+ case CMD_WEIGHTING:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (photpars)
+ call pargstr (Memc[incmd])
+ call clgstr (Memc[param], Memc[value], SZ_LINE)
+ call printf ("%s = %s\n")
+ call pargstr (Memc[incmd])
+ call pargstr (Memc[value])
+
+ case CMD_APERTURES:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (photpars)
+ call pargstr (Memc[incmd])
+ call gargwrd (Memc[value], SZ_LINE)
+ if (nscan() == 1) {
+ call clgstr (Memc[param], Memc[value], SZ_LINE)
+ call printf ("%s = \"%s\"\n")
+ call pargstr (Memc[incmd])
+ call pargstr (Memc[value])
+ } else {
+ call clpstr (Memc[param], Memc[value])
+ redraw = YES
+ }
+
+ case CMD_ZMAG:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (photpars)
+ call pargstr (Memc[incmd])
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (Memc[incmd])
+ call pargr (clgetr (Memc[param]))
+ } else {
+ call clputr (Memc[param], rval)
+ }
+
+ case CMD_MKAPERT:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (photpars)
+ call pargstr (Memc[incmd])
+ call gargb (bval)
+ if (nscan() == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (Memc[incmd])
+ call pargb (clgetb (Memc[param]))
+ } else
+ call clputb (Memc[param], bval)
+
+ case CMD_FUNCTION:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (daopars)
+ call pargstr (Memc[incmd])
+ call clgstr (Memc[param], Memc[value], SZ_LINE)
+ call printf ("%s = %s\n")
+ call pargstr (Memc[incmd])
+ call pargstr (Memc[value])
+
+ case CMD_RECENTER, CMD_FITSKY, CMD_GROUPSKY, CMD_SATURATED:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (daopars)
+ call pargstr (Memc[incmd])
+ call gargb (bval)
+ if (nscan() == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (Memc[incmd])
+ call pargb (clgetb (Memc[param]))
+ } else
+ call clputb (Memc[param], bval)
+
+ case CMD_PSFRAD, CMD_FITRAD:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (daopars)
+ call pargstr (Memc[incmd])
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (Memc[incmd])
+ call pargr (clgetr (Memc[param]))
+ } else
+ call clputr (Memc[param], rval)
+
+ case CMD_MATCHRAD, CMD_SANNULUS, CMD_WSANNULUS, CMD_FLATERR,
+ CMD_PROFERR, CMD_CRITOVERLAP, CMD_CLIPRANGE:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (daopars)
+ call pargstr (Memc[incmd])
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (Memc[incmd])
+ call pargr (clgetr (Memc[param]))
+ } else
+ call clputr (Memc[param], rval)
+
+ case CMD_VARORDER, CMD_NCLEAN, CMD_MAXITER, CMD_MAXGROUP,
+ CMD_MAXNSTAR, CMD_CLIPEXP:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (daopars)
+ call pargstr (Memc[incmd])
+ call gargi (ival)
+ if (nscan() == 1) {
+ call printf ("%s = %d\n")
+ call pargstr (Memc[incmd])
+ call pargi (clgeti (Memc[param]))
+ } else
+ call clputi (Memc[param], ival)
+
+ case CMD_THRESHOLD, CMD_NSIGMA, CMD_RATIO, CMD_THETA, CMD_SHARPLO,
+ CMD_SHARPHI, CMD_ROUNDLO, CMD_ROUNDHI:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (findpars)
+ call pargstr (Memc[incmd])
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (Memc[incmd])
+ call pargr (clgetr (Memc[param]))
+ } else
+ call clputr (Memc[param], rval)
+
+ case CMD_MKDETECTIONS:
+ call sprintf (Memc[param], SZ_LINE, "%s.%s")
+ call pargstr (findpars)
+ call pargstr (Memc[incmd])
+ call gargb (bval)
+ if (nscan() == 1) {
+ call printf ("%s = %b\n")
+ call pargstr (Memc[incmd])
+ call pargb (clgetb (Memc[param]))
+ } else
+ call clputb (Memc[param], bval)
+
+ default:
+ call printf ("Unknown or ambiguous colon command\7\n")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/daoedit/dpeconfirm.x b/noao/digiphot/daophot/daoedit/dpeconfirm.x
new file mode 100644
index 00000000..31aa359f
--- /dev/null
+++ b/noao/digiphot/daophot/daoedit/dpeconfirm.x
@@ -0,0 +1,433 @@
+include "daoedit.h"
+
+# DP_CBANNER -- Pritnt the confirm banner.
+
+procedure dp_cbanner ()
+
+begin
+ call printf ("\nVERIFY THE NEW VALUES\n")
+end
+
+
+# DP_CFWHMPSF -- Confirm the new value of fwhmpsf.
+
+procedure dp_cfwhmpsf()
+
+real fwhmpsf, scale, rval
+int scan(), nscan()
+real clgetr()
+
+begin
+ # Get the current values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ fwhmpsf = clgetr ("datapars.fwhmpsf")
+
+ # Confirm the fwhmpsf.
+ call printf ("FWHM of features (%g scale units) (CR or value): ")
+ call pargr (fwhmpsf)
+ call flush (STDOUT)
+ if (scan() != EOF) {
+ call gargr (rval)
+ if (nscan() == 1)
+ fwhmpsf = rval
+ }
+ call printf ("\tNew FWHM of features: %g scale units %g pixels\n")
+ call pargr (fwhmpsf)
+ call pargr (scale * fwhmpsf)
+
+ # Store the new fwhmpsf.
+ call clputr ("datapars.fwhmpsf", fwhmpsf)
+end
+
+
+# DP_CSIGMA -- Confirm the sigma parameters.
+
+procedure dp_csigma()
+
+real sigma, rval
+int scan(), nscan()
+real clgetr()
+
+begin
+ # Get the current value.
+ sigma = clgetr ("datapars.sigma")
+
+ # Confirm the sky sigma.
+ call printf (
+ "Standard deviation of background (%g counts) (CR or value): ")
+ call pargr (sigma)
+ call flush (STDOUT)
+ if (scan() != EOF) {
+ call gargr (rval)
+ if (nscan () == 1)
+ sigma = rval
+ }
+ call printf ("\tNew standard deviation of background: %g counts\n")
+ call pargr (sigma)
+
+ # Store the new sky sigma.
+ call clputr ("datapars.sigma", sigma)
+end
+
+
+# DP_CDMIN -- Confirm the good data minimum value.
+
+procedure dp_cdmin ()
+
+real datamin, rval
+int scan(), nscan()
+real clgetr()
+
+begin
+ # Get the current value.
+ datamin = clgetr ("datapars.datamin")
+
+ # Confirm the new minimum good data value.
+ call printf (
+ "Minimum good data value (%g counts) (CR or value): ")
+ call pargr (datamin)
+ call flush (STDOUT)
+ if (scan() != EOF) {
+ call gargr (rval)
+ if (nscan () == 1)
+ datamin = rval
+ }
+ call printf ("\tNew good data minimum: %g counts\n")
+ call pargr (datamin)
+
+ # Store the new good data minimum.
+ call clputr ("datapars.datamin", datamin)
+end
+
+
+# DP_CDMAX -- Confirm the good data maximum value.
+
+procedure dp_cdmax ()
+
+real datamax, rval
+int scan(), nscan()
+real clgetr()
+
+begin
+ # Get the current value.
+ datamax = clgetr ("datapars.datamax")
+
+ # Confirm the new maximum good data value.
+ call printf (
+ "Maximum good data value (%g counts) (CR or value): ")
+ call pargr (datamax)
+ call flush (STDOUT)
+ if (scan() != EOF) {
+ call gargr (rval)
+ if (nscan () == 1)
+ datamax = rval
+ }
+ call printf ("\tNew good data maximum: %g counts\n")
+ call pargr (datamax)
+
+ # Store the new maximum good data value.
+ call clputr ("datapars.datamax", datamax)
+end
+
+
+# DP_CCBOX -- Confirm the cbox parameter.
+
+procedure dp_ccbox()
+
+real scale, cbox, rval
+int scan(), nscan()
+real clgetr()
+
+begin
+ # Get the current values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ cbox = clgetr ("centerpars.cbox")
+
+ # Confirm the centering box value.
+ call printf ("Centering box width (%g scale units) (CR or value): ")
+ call pargr (cbox)
+ call flush (STDOUT)
+ if (scan() != EOF) {
+ call gargr (rval)
+ if (nscan () == 1)
+ cbox = rval
+ }
+ call printf ("\tNew centering box width: %g scale units %g pixels\n")
+ call pargr (cbox)
+ call pargr (scale * cbox)
+
+ # Store the new centering box.
+ call clputr ("centerpars.cbox", cbox)
+end
+
+
+# DP_CRCLEAN -- Confirm the cleaning radius.
+
+procedure dp_crclean()
+
+real scale, rclean, rval
+int scan(), nscan()
+real clgetr()
+
+begin
+ # Get the current values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ rclean = clgetr ("centerpars.rclean")
+
+ # Confirm the cleaning radius..
+ call printf ("Cleaning radius (%g scale units) (CR or value): ")
+ call pargr (rclean)
+ call flush (STDOUT)
+ if (scan() != EOF) {
+ call gargr (rval)
+ if (nscan () == 1)
+ rclean = rval
+ }
+ call printf ("\tNew cleaning radius: %g scale units %g pixels\n")
+ call pargr (rclean)
+ call pargr (scale * rclean)
+
+ # Store the new cleaning radius.
+ call clputr ("centerpars.rclean", rclean)
+end
+
+
+# DP_CRCLIP -- Confirm the clipping radius.
+
+procedure dp_crclip()
+
+real scale, rclip, rval
+int scan(), nscan()
+real clgetr()
+
+begin
+ # Get the current values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ rclip = clgetr ("centerpars.rclip")
+
+ # Confirm the cleaning radius..
+ call printf ("Clipping radius (%g scale units) (CR or value): ")
+ call pargr (rclip)
+ call flush (STDOUT)
+ if (scan() != EOF) {
+ call gargr (rval)
+ if (nscan () == 1)
+ rclip = rval
+ }
+ call printf ("\tNew clipping radius: %g scale units %g pixels\n")
+ call pargr (rclip)
+ call pargr (scale * rclip)
+
+ # Store the new clipping radius.
+ call clputr ("centerpars.rclip", rclip)
+end
+
+
+# DP_CANNULUS -- Confirm the inner radius of the sky annulus.
+
+procedure dp_cannulus()
+
+real scale, annulus, rval
+int scan(), nscan()
+real clgetr()
+
+begin
+ # Get the current values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ annulus = clgetr ("fitskypars.annulus")
+
+ # Confirm the sky annulus.
+ call printf (
+ "Inner radius of sky annulus (%g scale units) (CR or value): ")
+ call pargr (annulus)
+ call flush (STDOUT)
+ if (scan () != EOF) {
+ call gargr (rval)
+ if (nscan () == 1)
+ annulus = rval
+ }
+ call printf (
+ "\tNew inner radius of sky annulus: %g scale units %g pixels\n")
+ call pargr (annulus)
+ call pargr (scale * annulus)
+
+ # Store the new sky annulus.
+ call clputr ("fitskypars.annulus", annulus)
+end
+
+
+# DP_CDANNULUS -- Confirm the annulus width parameter.
+
+procedure dp_cdannulus()
+
+real scale, dannulus, rval
+int scan(), nscan()
+real clgetr()
+
+begin
+ # Get the current values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ dannulus = clgetr ("fitskypars.dannulus")
+
+ # Confirm the sky annulus width.
+ call printf (
+ "Width of the sky annulus (%g scale units) (CR or value): ")
+ call pargr (dannulus)
+ call flush (STDOUT)
+ if (scan() != EOF) {
+ call gargr (rval)
+ if (nscan () == 1)
+ dannulus = rval
+ }
+ call printf (
+ "\tNew width of the sky annulus: %g scale units %g pixels\n")
+ call pargr (dannulus)
+ call pargr (scale * dannulus)
+
+ # Save the new sky annulus width.
+ call clputr ("fitskypars.dannulus", dannulus)
+end
+
+
+# DP_CRGROW -- Confirm the region growing radius.
+
+procedure dp_crgrow()
+
+real scale, rgrow, rval
+int scan(), nscan()
+real clgetr()
+
+begin
+ # Mark the region growing radius.
+ scale = 1.0 / clgetr ("datapars.scale")
+ rgrow = clgetr ("fitskypars.rgrow")
+
+ # Confirm the new region growing radius.
+ call printf (
+ "Region growing radius (%g scale units) (CR or value): ")
+ call pargr (rgrow)
+ call flush (STDOUT)
+ if (scan() != EOF) {
+ call gargr (rval)
+ if (nscan () == 1)
+ rgrow = rval
+ }
+ call printf (
+ "\tNew region growing radius: %g scale units %g pixels\n")
+ call pargr (rgrow)
+ call pargr (scale * rgrow)
+
+ # Save the new region growing radius.
+ call clputr ("fitskypars.rgrow", rgrow)
+end
+
+
+# DP_CAPER -- Confirm the aperture string.
+
+procedure dp_caper()
+
+int i, naperts
+pointer sp, apstr, newapstr, aperts
+real scale
+int scan(), nscan(), dp_gaperts()
+real clgetr()
+
+begin
+ call smark (sp)
+ call salloc (apstr, SZ_LINE, TY_CHAR)
+ call salloc (newapstr, SZ_LINE, TY_CHAR)
+ call salloc (aperts, MAX_NAPERTS, TY_REAL)
+
+ # Get the current values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ call clgstr ("photpars.apertures", Memc[apstr], SZ_LINE)
+
+ # Confirm the aperture string.
+ call printf (
+ "File/list of aperture radii (%s scale units) (CR or value): ")
+ call pargstr (Memc[apstr])
+ call flush (STDOUT)
+
+ # Get the new apertures.
+ if (scan() != EOF) {
+ call gargwrd (Memc[newapstr], SZ_LINE)
+ if (nscan () == 1)
+ call strcpy (Memc[newapstr], Memc[apstr], SZ_LINE)
+ }
+
+ # Print the new apertures.
+ naperts = dp_gaperts (Memc[apstr], Memr[aperts], MAX_NAPERTS)
+ do i = 1, naperts {
+ call printf ("\tAperture radius %d: %g scale units %g pixels\n")
+ call pargi (i)
+ call pargr (Memr[aperts+i-1])
+ call pargr (scale * Memr[aperts+i-1])
+ }
+
+ # Save the new aperture string.
+ call clpstr ("photpars.apertures", Memc[apstr])
+
+ call sfree (sp)
+end
+
+
+# DP_CPSFRAD -- Confirm the psf radius.
+
+procedure dp_cpsfrad()
+
+real scale, psfrad, rval
+int scan(), nscan()
+real clgetr()
+
+begin
+ # Get the current values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ psfrad = clgetr ("daopars.psfrad")
+
+ # Confirm the new PSF radius.
+ call printf ("PSF radius (%g scale units) (CR or value): ")
+ call pargr (psfrad)
+ call flush (STDOUT)
+ if (scan() != EOF) {
+ call gargr (rval)
+ if (nscan () == 1)
+ psfrad = rval
+ }
+ call printf ("\tNew PSF radius: %g scale units %g pixels\n")
+ call pargr (psfrad)
+ call pargr (scale * psfrad)
+
+ # Store the new PSF radius.
+ call clputr ("daopars.psfrad", psfrad)
+end
+
+
+# DP_CFITRAD -- Confirm the fitting radius.
+
+procedure dp_cfitrad ()
+
+real scale, fitrad, rval
+int scan(), nscan()
+real clgetr()
+
+begin
+ # Get the current values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ fitrad = clgetr ("daopars.fitrad")
+
+ # Confirm the new fitting radius.
+ call printf ("Fitting radius (%g scale units) (CR or value): ")
+ call pargr (fitrad)
+ call flush (STDOUT)
+ if (scan() != EOF) {
+ call gargr (rval)
+ if (nscan () == 1)
+ fitrad = rval
+ }
+ call printf ("\tNew fitting radius: %g scale units %g pixels\n")
+ call pargr (fitrad)
+ call pargr (scale * fitrad)
+
+ # Store the new fitting radius.
+ call clputr ("daopars.fitrad", fitrad)
+end
diff --git a/noao/digiphot/daophot/daoedit/dpemark.x b/noao/digiphot/daophot/daoedit/dpemark.x
new file mode 100644
index 00000000..de72fc2c
--- /dev/null
+++ b/noao/digiphot/daophot/daoedit/dpemark.x
@@ -0,0 +1,734 @@
+include <ctype.h>
+include "daoedit.h"
+
+# DP_MFWHMPSF -- Mark the fwhmpsf on the radial profile plot and confirm.
+
+procedure dp_mfwhmpsf (gd)
+
+pointer gd # pointer to the graphics stream
+
+int wcs, key, stat
+pointer sp, cmd
+real rmin, rmax, imin, imax, scale, fwhmpsf, wx, wy
+int clgcur()
+real clgetr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Determine the x and y limits of the current plot.
+ call ggwind (gd, rmin, rmax, imin, imax)
+
+ # Get the current parameters.
+ scale = 1.0 / clgetr ("datapars.scale")
+ fwhmpsf = clgetr ("datapars.fwhmpsf") / 2.0
+
+ # Mark the FWHM of the PSF on the radial profile plot.
+ call printf ("Mark HWHM of the psf (%g pixels):")
+ call pargr (fwhmpsf * scale)
+ call gscur (gd, fwhmpsf * scale, (imin + imax) / 2.0)
+ stat = clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || wx <= 0.0 || wx > rmax)
+ ;
+ else
+ fwhmpsf = wx / scale
+
+ # Store the new fwhmpsf.
+ call clputr ("datapars.fwhmpsf", 2.0 * fwhmpsf)
+
+ call sfree (sp)
+end
+
+
+# DP_MSIGMA -- Mark the sky sigma on the radial profile plot and confirm.
+
+procedure dp_msigma (gd)
+
+pointer gd # pointer to the grapics stream
+
+int wcs, key, stat
+pointer sp, cmd
+real rmin, rmax, imin, imax, mean, sigma, wx, wy
+int clgcur()
+real clgetr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Determine the range of the plot
+ call ggwind (gd, rmin, rmax, imin, imax)
+
+ # Mark the mean sky on the radial profile plot.
+ call printf ("Mark mean sky background level:")
+ call gscur (gd, (rmin + rmax) / 2.0, imin)
+ stat = clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || wy < imin || wy > imax)
+ mean = imin
+ else
+ mean = wy
+
+ # Get the current value.
+ sigma = clgetr ("datapars.sigma")
+ if (! IS_INDEFR (sigma))
+ sigma = 3.0 * sigma
+
+ # Mark the sky sigma on the radial profile plot.
+ call printf ("Mark 3 sigma sky level (%g counts):")
+ call pargr (sigma)
+ if (IS_INDEFR(sigma))
+ call gscur (gd, (rmin + rmax) / 2.0, imax)
+ else
+ call gscur (gd, (rmin + rmax) / 2.0, mean + sigma)
+ stat = clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || wy < imin || wy > imax)
+ ;
+ else
+ sigma = abs (wy - mean) / 3.0
+
+ # Store the new sky sigma.
+ call clputr ("datapars.sigma", sigma)
+
+ call sfree (sp)
+end
+
+
+# DP_MDMIN -- Mark the minimum good data value on the radial profile plot
+# and confirm.
+
+procedure dp_mdmin (gd)
+
+pointer gd # pointer to the grapics stream
+
+int wcs, key, stat
+pointer sp, cmd
+real rmin, rmax, imin, imax, datamin, wx, wy
+int clgcur()
+real clgetr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Determine the limits of the plot.
+ call ggwind (gd, rmin, rmax, imin, imax)
+
+ # Get the current value.
+ datamin = clgetr ("datapars.datamin")
+
+ # Mark the threshold on the radial profile plot.
+ call printf ("Mark the minimum good data level (%g counts):")
+ call pargr (datamin)
+
+ if (IS_INDEFR(datamin) || datamin < imin)
+ call gscur (gd, (rmin + rmax) / 2.0, imin)
+ else
+ call gscur (gd, (rmin + rmax) / 2.0, datamin)
+ stat = clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || wy < imin || wy > imax)
+ ;
+ else
+ datamin = wy
+
+ # Store the new good data minimum.
+ call clputr ("datapars.datamin", datamin)
+
+ call sfree (sp)
+end
+
+
+# DP_MDMAX -- Mark the maximum good data value on the radial profile plot
+# and confirm.
+
+procedure dp_mdmax (gd)
+
+pointer gd # pointer to the grapics stream
+
+int wcs, key, stat
+pointer sp, cmd
+real rmin, rmax, imin, imax, datamax, wx, wy
+int clgcur()
+real clgetr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Determine the limits of the plot.
+ call ggwind (gd, rmin, rmax, imin, imax)
+
+ # Get the current value.
+ datamax = clgetr ("datapars.datamax")
+
+ # Mark the threshold on the radial profile plot.
+ call printf ("Mark the maximum good data level (%g counts):")
+ call pargr (datamax)
+
+ if (IS_INDEFR(datamax) || datamax > imax)
+ call gscur (gd, (rmin + rmax) / 2.0, imax)
+ else
+ call gscur (gd, (rmin + rmax) / 2.0, datamax)
+ stat = clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || wy < imin || wy > imax)
+ ;
+ else
+ datamax = wy
+
+ # Store the new maximum good data value.
+ call clputr ("datapars.datamax", datamax)
+
+ call sfree (sp)
+end
+
+
+# DP_MCBOX -- Mark the centering aperture on the radial profile plot and
+# confirm.
+
+procedure dp_mcbox (gd)
+
+pointer gd # pointer to the grapics stream
+
+int wcs, key, stat
+pointer sp, cmd
+real rmin, rmax, imin, imax, scale, capert, wx, wy
+int clgcur()
+real clgetr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Determine the x and y limits of the current plot.
+ call ggwind (gd, rmin, rmax, imin, imax)
+
+ # Get the current values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ capert = clgetr ("centerpars.cbox") / 2.0
+
+ # Mark the centering aperture on the radial profile plot.
+ call printf ("Mark centering box half width (%g pixels):")
+ call pargr (capert * scale)
+ call gscur (gd, capert * scale, (imin + imax) / 2.0)
+ stat = clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || wx <= 0.0 || wx > rmax)
+ ;
+ else
+ capert = wx / scale
+
+ # Store the new centering box.
+ call clputr ("centerpars.cbox", 2.0 * capert)
+
+ call sfree (sp)
+end
+
+
+# DP_MRCLEAN -- Mark the cleaning radius on the radial profile plot and
+# confirm.
+
+procedure dp_mrclean (gd)
+
+pointer gd # pointer to the graphics stream
+
+int wcs, key, stat
+pointer sp, cmd
+real rmin, rmax, imin, imax, scale, rclean, wx, wy
+int clgcur()
+real clgetr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Get the current plot window.
+ call ggwind (gd, rmin, rmax, imin, imax)
+
+ # Get the current values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ rclean = clgetr ("centerpars.rclean")
+
+ # Mark the cleaning radius on the plot.
+ call printf (
+ "Mark the centering algorithm cleaning radius (%g pixels):")
+ call pargr (scale * rclean)
+ call gscur (gd, scale * rclean, (imin + imax) / 2.0)
+ stat = clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || wx <= 0.0 || wx > rmax)
+ ;
+ else
+ rclean = wx / scale
+
+ # Store the new cleaning radius.
+ call clputr ("centerpars.rclean", rclean)
+
+ call sfree (sp)
+end
+
+
+# DP_MRCLIP -- Mark the clipping radius on the radial profile plot and.
+# confirm.
+
+procedure dp_mrclip (gd)
+
+pointer gd # pointer to the grapics stream
+
+int wcs, key, stat
+pointer sp, cmd
+real rmin, rmax, imin, imax, scale, rclip, wx, wy
+int clgcur()
+real clgetr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Get the current plot window.
+ call ggwind (gd, rmin, rmax, imin, imax)
+
+ # Get the clipping radius values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ rclip = clgetr ("centerpars.rclip")
+
+ # Mark clipping radius on the plot.
+ call printf (
+ "Mark the centering algorithm clipping radius (%g pixels):")
+ call pargr (scale * rclip)
+ call gscur (gd, scale * rclip, (imin + imax) / 2.0)
+ stat = clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || wx <= 0.0 || wx > rmax)
+ ;
+ else
+ rclip = wx / scale
+
+ # Store the new clipping radius.
+ call clputr ("centerpars.rclip", rclip)
+
+ call sfree (sp)
+end
+
+
+# DP_MANNULUS -- Mark the sky annulus on the radial profile plot and confirm.
+
+procedure dp_mannulus (gd)
+
+pointer gd # pointer to the grapics stream
+
+int wcs, key, stat
+pointer sp, cmd
+real rmin, rmax, imin, imax, scale, annulus, wx, wy
+int clgcur()
+real clgetr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Get the current plot window.
+ call ggwind (gd, rmin, rmax, imin, imax)
+
+ # Get the current values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ annulus = clgetr ("fitskypars.annulus")
+
+ # Mark the inner sky radius.
+ call printf ("Mark inner sky radius (%g pixels):")
+ call pargr (annulus * scale)
+ call gscur (gd, annulus * scale, (imin + imax) / 2.0)
+ stat = clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || wx < 0.0 || wx > rmax)
+ ;
+ else
+ annulus = wx / scale
+
+ # Store the new sky annulus.
+ call clputr ("fitskypars.annulus", annulus)
+
+ call sfree (sp)
+
+end
+
+
+# DP_MDANNULUS -- Mark the sky annulus width on the radial profile plot and
+# confirm.
+
+procedure dp_mdannulus (gd)
+
+pointer gd # pointer to the grapics stream
+
+int wcs, key, stat
+pointer sp, cmd
+real rmin, rmax, imin, imax, scale, annulus, dannulus, wx, wy
+int clgcur()
+real clgetr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Get the current plot window.
+ call ggwind (gd, rmin, rmax, imin, imax)
+
+ # Get the current values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ annulus = clgetr ("fitskypars.annulus")
+ dannulus = clgetr ("fitskypars.dannulus")
+
+ # Mark the outer sky radius.
+ call printf ("Mark outer sky radius (%g pixels):")
+ call pargr (scale * (annulus + dannulus))
+ call gscur (gd, scale * (annulus + dannulus), (imin + imax) / 2.0)
+ stat = clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || (wx / scale < annulus) || wx > rmax)
+ ;
+ else
+ dannulus = (wx / scale - annulus)
+
+ # Save the new sky annulus width.
+ call clputr ("fitskypars.dannulus", dannulus)
+
+ call sfree (sp)
+end
+
+
+# DP_MRGROW -- Mark the regions growing radius the radial profile plot.
+
+procedure dp_mrgrow (gd)
+
+pointer gd # pointer to the grapics stream
+
+int wcs, key, stat
+pointer sp, cmd
+real rmin, rmax, imin, imax, scale, rgrow, wx, wy
+int clgcur()
+real clgetr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Get the current plot window.
+ call ggwind (gd, rmin, rmax, imin, imax)
+
+ # Get the current values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ rgrow = clgetr ("fitskypars.rgrow")
+
+ # Mark the inner sky radius.
+ call printf ("Mark region growing radius (%g pixels):")
+ call pargr (rgrow * scale)
+ call gscur (gd, rgrow * scale, (imin + imax) / 2.0)
+ stat = clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || wx < 0.0 || wx > rmax)
+ ;
+ else
+ rgrow = wx / scale
+
+ # Store the new sky annulus.
+ call clputr ("fitskypars.rgrow", rgrow)
+
+ call sfree (sp)
+
+end
+
+
+# DP_MAPER -- Mark the photometry apertures on the radial profile plot and
+# confirm.
+
+procedure dp_maper (gd)
+
+pointer gd # pointer to the grapics stream
+
+int wcs, key, naperts
+pointer sp, oapstr, aperts, tapstr, apstr, cmd
+real rmin, rmax, imin, imax, scale, wx, wy
+int dp_gaperts(), clgcur(), strlen()
+real clgetr()
+
+begin
+ call smark (sp)
+ call salloc (oapstr, SZ_LINE, TY_CHAR)
+ call salloc (aperts, MAX_NAPERTS, TY_REAL)
+ call salloc (apstr, SZ_LINE, TY_CHAR)
+ call salloc (tapstr, SZ_LINE, TY_CHAR)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Determine the current plot window.
+ call ggwind (gd, rmin, rmax, imin, imax)
+
+ # Decode the apertures.
+ scale = 1.0 / clgetr ("datapars.scale")
+ call clgstr ("photpars.apertures", Memc[oapstr], SZ_LINE)
+ naperts = dp_gaperts (Memc[oapstr], Memr[aperts], MAX_NAPERTS)
+
+ # Type prompt string.
+ call printf ("Mark apertures (%s pixels) [q=quit]:")
+ call pargstr (Memc[oapstr])
+ call gscur (gd, Memr[aperts] * scale, (imin + imax) / 2.0)
+
+ # Mark the apertures.
+ Memc[apstr] = EOS
+ Memc[tapstr] = EOS
+ while (clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd],
+ SZ_LINE) != EOF) {
+ if (key == 'q')
+ break
+ if (wx <= 0.0 || wx > rmax)
+ next
+ call sprintf (Memc[apstr+strlen(Memc[apstr])], SZ_FNAME,"%.2f,")
+ call pargr (wx / scale)
+ call sprintf (Memc[tapstr+strlen(Memc[tapstr])], SZ_FNAME,"%.2f,")
+ call pargr (wx)
+ call printf ("Mark apertures (%s pixels) [q=quit]:")
+ call pargstr (Memc[tapstr])
+ }
+ Memc[apstr+strlen(Memc[apstr])-1] = EOS
+
+ # Save the new aperture string.
+ call clpstr ("photpars.apertures", Memc[apstr])
+
+ call sfree (sp)
+end
+
+
+# DP_MPSFRAD -- Mark the psf radius on the radial profile plot and confirm.
+
+procedure dp_mpsfrad (gd)
+
+pointer gd # pointer to the graphics stream
+
+int wcs, key, stat
+pointer sp, cmd
+real rmin, rmax, imin, imax, scale, psfrad, wx, wy
+int clgcur()
+real clgetr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Determine the x and y limits of the current plot.
+ call ggwind (gd, rmin, rmax, imin, imax)
+
+ # Get the current values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ psfrad = clgetr ("daopars.psfrad")
+
+ # Mark the FWHM of the PSF on the radial profile plot.
+ call printf ("Mark the PSF radius (%g pixels):")
+ call pargr (psfrad * scale)
+ call gscur (gd, psfrad * scale, (imin + imax) / 2.0)
+ stat = clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || wx <= 0.0 || wx > rmax)
+ ;
+ else
+ psfrad = wx / scale
+
+ # Store the new PSF radius.
+ call clputr ("daopars.psfrad", psfrad)
+
+ call sfree (sp)
+end
+
+
+# DP_MFITRAD -- Mark the fitting radius on the radial profile plot and confirm.
+
+procedure dp_mfitrad (gd)
+
+pointer gd # pointer to the graphics stream
+
+int wcs, key, stat
+pointer sp, cmd
+real rmin, rmax, imin, imax, scale, fitrad, wx, wy
+int clgcur()
+real clgetr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Determine the x and y limits of the current plot.
+ call ggwind (gd, rmin, rmax, imin, imax)
+
+ # Get the current values.
+ scale = 1.0 / clgetr ("datapars.scale")
+ fitrad = clgetr ("daopars.fitrad")
+
+ # Mark the FWHM of the PSF on the radial profile plot.
+ call printf ("Mark the fitting radius (%g pixels):")
+ call pargr (fitrad * scale)
+ call gscur (gd, fitrad * scale, (imin + imax) / 2.0)
+ stat = clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE)
+ if (stat == EOF || wx <= 0.0 || wx > rmax)
+ ;
+ else
+ fitrad = wx / scale
+
+ # Store the new fitting radius.
+ call clputr ("daopars.fitrad", fitrad)
+
+ call sfree (sp)
+end
+
+
+# DP_GAPERTS -- Decode the aperture string.
+
+int procedure dp_gaperts (str, aperts, max_naperts)
+
+char str[ARB] # aperture string
+real aperts[ARB] # aperture array
+int max_naperts # maximum number of apertures
+
+int naperts, ip, op, ndecode, nap
+pointer sp, outstr
+real apstart, apend, apstep
+bool fp_equalr()
+int dp_gctor()
+
+begin
+ call smark (sp)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+
+ naperts = 0
+ for (ip = 1; str[ip] != EOS && naperts < max_naperts;) {
+
+ # Initialize.
+ apstart = 0.0
+ apend = 0.0
+ apstep = 0.0
+ ndecode = 0
+
+ # Skip past white space and commas.
+ while (IS_WHITE(str[ip]))
+ ip = ip + 1
+ if (str[ip] == ',')
+ ip = ip + 1
+
+ # Get the starting aperture number.
+ op = 1
+ while (IS_DIGIT(str[ip]) || str[ip] == '.') {
+ Memc[outstr+op-1] = str[ip]
+ ip = ip + 1
+ op = op + 1
+ }
+ Memc[outstr+op-1] = EOS
+
+ # Decode the starting aperture.
+ op = 1
+ if (dp_gctor (Memc[outstr], op, apstart) > 0) {
+ apend = apstart
+ ndecode = 1
+ } else
+ apstart = 0.0
+
+ # Skip past white space and commas.
+ while (IS_WHITE(str[ip]))
+ ip = ip + 1
+ if (str[ip] == ',')
+ ip = ip + 1
+
+ # Search for the ending aperture.
+ if (str[ip] == ':') {
+ ip = ip + 1
+
+ # Get the ending aperture.
+ op = 1
+ while (IS_DIGIT(str[ip]) || str[ip] == '.') {
+ Memc[outstr+op-1] = str[ip]
+ ip = ip + 1
+ op = op + 1
+ }
+ Memc[outstr+op-1] = EOS
+
+ # Decode the ending aperture.
+ op = 1
+ if (dp_gctor (Memc[outstr], op, apend) > 0) {
+ ndecode = 2
+ apstep = apend - apstart
+ }
+ }
+
+ # Skip past the white space.
+ while (IS_WHITE(str[ip]))
+ ip = ip + 1
+
+ # Skip past the commas.
+ if (str[ip] == ',')
+ ip = ip + 1
+
+ # Get the step size.
+ if (str[ip] == ':') {
+ ip = ip + 1
+
+ # Get the step size.
+ op = 1
+ while (IS_DIGIT(str[ip]) || str[ip] == '.') {
+ Memc[outstr+op-1] = str[ip]
+ ip = ip + 1
+ op = op + 1
+ }
+ Memc[outstr+op-1] = EOS
+
+ # Decode the step size.
+ op = 1
+ if (dp_gctor (Memc[outstr], op, apstep) > 0) {
+ if (fp_equalr (apstep, 0.0))
+ apstep = apend - apstart
+ else
+ ndecode = (apend - apstart) / apstep + 1
+ if (ndecode < 0) {
+ ndecode = -ndecode
+ apstep = - apstep
+ }
+ }
+ }
+
+ # Negative apertures are not permitted.
+ if (apstart <= 0.0 || apend <= 0.0)
+ break
+
+ # Fill in the apertures.
+ if (ndecode == 0) {
+ ;
+ } else if (ndecode == 1) {
+ naperts = naperts + 1
+ aperts[naperts] = apstart
+ } else if (ndecode == 2) {
+ naperts = naperts + 1
+ aperts[naperts] = apstart
+ if (naperts >= max_naperts)
+ break
+ naperts = naperts + 1
+ aperts[naperts] = apend
+ } else {
+ for (nap = 1; nap <= ndecode && naperts < max_naperts;
+ nap = nap + 1) {
+ naperts = naperts + 1
+ aperts[naperts] = apstart + (nap - 1) * apstep
+ }
+ }
+ }
+
+ call sfree (sp)
+
+ return (naperts)
+end
+
+
+# DP_GCTOR -- Procedure to convert a character variable to a real number.
+# This routine is just an interface routine to the IRAF procedure gctod.
+
+int procedure dp_gctor (str, ip, rval)
+
+char str[ARB] # string to be converted
+int ip # pointer to the string
+real rval # real value
+
+double dval
+int nchars
+int gctod()
+
+begin
+ nchars = gctod (str, ip, dval)
+ rval = dval
+ return (nchars)
+end
diff --git a/noao/digiphot/daophot/daoedit/dpeomark.x b/noao/digiphot/daophot/daoedit/dpeomark.x
new file mode 100644
index 00000000..d635c31a
--- /dev/null
+++ b/noao/digiphot/daophot/daoedit/dpeomark.x
@@ -0,0 +1,68 @@
+include <gset.h>
+
+# DP_EOMARK -- Procedure to mark center, fitsky and phot parameters on the
+# display.
+
+procedure dp_eomark (id, xcenter, ycenter, srin, srout, apr, mkcenter, mksky,
+ mkapert)
+
+pointer id # pointer to image display stream
+real xcenter # the center x coordinate
+real ycenter # the center y coordinate
+real srin # the inner radius of the sky annulus
+real srout # the outer radius of the sky annulus
+real apr # the maximum photometry aperture radius
+int mkcenter # mark the computed center
+int mksky # mark the sky annulus
+int mkapert # mark the aperture(s)
+
+real rad
+int marktype
+int gstati()
+
+errchk greactivate, gdeactivate
+
+begin
+ if (id == NULL)
+ return
+ if (mkcenter == NO && mksky == NO && mkapert == NO)
+ return
+ iferr {
+ call greactivate (id, 0)
+ } then {
+ return
+ }
+
+ # Save old mark type.
+ marktype = gstati (id, G_PMLTYPE)
+
+ # Mark the center and shift on the display.
+ if (mkcenter == YES) {
+ call gseti (id, G_PMLTYPE, GL_SOLID)
+ call gmark (id, xcenter, xcenter, GM_PLUS, -2.0, -2.0)
+ }
+
+ # Draw the sky annuli on the display.
+ if (mksky == YES) {
+ call gseti (id, G_PMLTYPE, GL_DASHED)
+ rad = 2.0 * srin
+ call gmark (id, xcenter, ycenter, GM_CIRCLE, -rad, -rad)
+ rad = 2.0 * srout
+ call gmark (id, xcenter, ycenter, GM_CIRCLE, -rad, -rad)
+ }
+
+ # Draw the apertures on the display.
+ if (mkapert == YES) {
+ call gseti (id, G_PMLTYPE, GL_DASHED)
+ rad = 2.0 * apr
+ call gmark (id, xcenter, ycenter, GM_CIRCLE, -rad, -rad)
+ }
+
+ # Restore the mark type.
+ call gseti (id, G_PMLTYPE, marktype)
+
+ iferr {
+ call gdeactivate (id, 0)
+ } then
+ return
+end
diff --git a/noao/digiphot/daophot/daoedit/dperplot.x b/noao/digiphot/daophot/daoedit/dperplot.x
new file mode 100644
index 00000000..95a78848
--- /dev/null
+++ b/noao/digiphot/daophot/daoedit/dperplot.x
@@ -0,0 +1,172 @@
+include <gset.h>
+include "daoedit.h"
+
+define FRACTION 0.10
+
+# DP_ERPLOT -- Plot the radial profile.
+
+procedure dp_erplot (gd, title, xwcs, ywcs, radius, intensity, npts,
+ rcentroid, pmean, integral, nbins, rmin, rmax, iannulus, oannulus,
+ apradius, skyval, skysigma, rscale, pnorm)
+
+pointer gd # pointer to the graphics stream
+char title[ARB] # the plot title
+int xwcs # the x wcs type of the final plot
+int ywcs # the y wcs type of the final plot
+real radius[ARB] # the radius vector
+real intensity[ARB] # the intensity vector
+int npts # number of points in the profile
+real rcentroid[ARB] # the radius centroid vector
+real pmean[ARB] # the mean intensity vector
+real integral[ARB] # the integral of the profile
+int nbins # the number of bins
+real rmin, rmax # min and max radius
+real iannulus # the inner radius of the sky annulus
+real oannulus # the outer radius of the sky annulus
+real apradius # the aperture radius
+real skyval # the sky value
+real skysigma # the sigma of the sky value
+real rscale # the image scale
+real pnorm # the profile normalization factor
+
+int i, j
+pointer sp, pxlabel, pylabel, sxlabel, sylabel
+real r1, r2, rp1, rp2, rs1, rs2, i1, i2, ip1, ip2, is1, is2, dr, fraction
+
+begin
+ # Get space for the x and y labels.
+ call smark (sp)
+ call salloc (pxlabel, SZ_FNAME, TY_CHAR)
+ call salloc (pylabel, SZ_FNAME, TY_CHAR)
+ call salloc (sxlabel, SZ_FNAME, TY_CHAR)
+ call salloc (sylabel, SZ_FNAME, TY_CHAR)
+
+ # Clear the plot.
+ call gclear (gd)
+
+ # Determine the data range of the x and y axes.
+
+ r1 = rmin - FRACTION * (rmax - rmin)
+ r2 = rmax + FRACTION * (rmax - rmin)
+ switch (xwcs) {
+ case WCS_XPIX:
+ rp1 = r1
+ rp2 = r2
+ rs1 = r1 / rscale
+ rs2 = r2 / rscale
+ case WCS_XSCALE:
+ rp1 = r1 / rscale
+ rp2 = r2 / rscale
+ rs1 = r1
+ rs2 = r2
+ default:
+ rp1 = r1
+ rp2 = r2
+ rs1 = r1 / rscale
+ rs2 = r2 / rscale
+ }
+ fraction = max (FRACTION, 5.0 * skysigma / pnorm)
+ i1 = -pnorm * fraction
+ i2 = pnorm * (1.0 + fraction)
+ switch (ywcs) {
+ case WCS_YNORM:
+ ip1 = i1 / pnorm
+ ip2 = i2 / pnorm
+ is1 = i1 + skyval
+ is2 = i2 + skyval
+ case WCS_YCOUNT:
+ ip1 = i1 + skyval
+ ip2 = i2 + skyval
+ is1 = i1 / pnorm
+ is2 = i2 / pnorm
+ default:
+ ip1 = i1 / pnorm
+ ip2 = i2 / pnorm
+ is1 = i1 + skyval
+ is2 = i2 + skyval
+ }
+
+ # Draw the axes and axis labels.
+ call gsetr (gd, G_ASPECT, 0.0)
+ switch (xwcs) {
+ case WCS_XPIX:
+ call strcpy ("Radius (b=pixels, t=scale units)", Memc[pxlabel],
+ SZ_FNAME)
+ call strcpy ("", Memc[sxlabel], SZ_FNAME)
+ case WCS_XSCALE:
+ call strcpy ("Radius (b=scale units, t=pixels)", Memc[pxlabel],
+ SZ_FNAME)
+ call strcpy ("", Memc[sxlabel], SZ_FNAME)
+ default:
+ call strcpy ("Radius (b=pixels, t=scale units)", Memc[pxlabel],
+ SZ_FNAME)
+ call strcpy ("", Memc[sxlabel], SZ_FNAME)
+ }
+ switch (ywcs) {
+ case WCS_YCOUNT:
+ call strcpy ("Counts", Memc[pylabel], SZ_FNAME)
+ call strcpy ("Norm Counts", Memc[sylabel], SZ_FNAME)
+ case WCS_YNORM:
+ call strcpy ("Norm Counts", Memc[pylabel], SZ_FNAME)
+ call strcpy ("Counts", Memc[sylabel], SZ_FNAME)
+ default:
+ call strcpy ("Counts", Memc[pylabel], SZ_FNAME)
+ call strcpy ("Norm Counts", Memc[sylabel], SZ_FNAME)
+ }
+
+ call gseti (gd, G_XDRAWAXES, 1)
+ call gseti (gd, G_YDRAWAXES, 1)
+ call gswind (gd, rp1, rp2, ip1, ip2)
+ call glabax (gd, title, Memc[pxlabel], Memc[pylabel])
+ call gseti (gd, G_XDRAWAXES, 2)
+ call gseti (gd, G_YDRAWAXES, 2)
+ call gswind (gd, rs1, rs2, is1, is2)
+ call glabax (gd, title, Memc[sxlabel], Memc[sylabel])
+
+ # Plot the data points.
+ call gswind (gd, r1, r2, i1, i2)
+ call gpmark (gd, radius, intensity, npts, GM_PLUS, 1.0, 1.0)
+
+ # Plot the smoothed radial profile skipping any points with no data.
+ call gswind (gd, r1, r2, -fraction, 1.0 + fraction)
+ for (i = 1; i <= nbins && rcentroid[i] <= 0.0; i = i + 1)
+ ;
+ call gamove (gd, rcentroid[i], pmean[i])
+ do j = i, nbins {
+ if (pmean[j] == 0.0)
+ next
+ call gadraw (gd, rcentroid[j], pmean[j])
+ }
+
+ # Plot the integral.
+ call gswind (gd, r1, r2, -fraction, 1.0 + fraction)
+ call gamove (gd, 0.0, 0.0)
+ dr = (rmax - rmin) / real (nbins - 1)
+ do j = 2, nbins {
+ call gadraw (gd, real (j - 1) * dr, integral[j])
+ }
+
+ # Plot the sky annuli and the aperture radius.
+ call gamove (gd, iannulus, -fraction)
+ call gadraw (gd, iannulus, 1.0 + fraction)
+ call gamove (gd, oannulus, -fraction)
+ call gadraw (gd, oannulus, 1.0 + fraction)
+ call gamove (gd, apradius, -fraction)
+ call gadraw (gd, apradius, 1.0 + fraction)
+
+ # Plot the zero level.
+ call gswind (gd, rp1, rp2, ip1, ip2)
+ switch (ywcs) {
+ case WCS_YCOUNT:
+ call gamove (gd, rp1, skyval)
+ call gadraw (gd, rp2, skyval)
+ case WCS_YNORM:
+ call gamove (gd, rp1, 0.0)
+ call gadraw (gd, rp2, 0.0)
+ default:
+ call gamove (gd, rp1, 0.0)
+ call gadraw (gd, rp2, 0.0)
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/daoedit/dperprofile.x b/noao/digiphot/daophot/daoedit/dperprofile.x
new file mode 100644
index 00000000..37cccf97
--- /dev/null
+++ b/noao/digiphot/daophot/daoedit/dperprofile.x
@@ -0,0 +1,590 @@
+include <mach.h>
+include <imhdr.h>
+include "daoedit.h"
+
+
+# DP_ERPROFILE -- Compute and optionally plot the radial profile of the
+# selected star.
+
+procedure dp_erprofile (gd, id, banner, xwcs, ywcs, im, xinit, yinit)
+
+pointer gd # pointer to the graphics descriptor
+pointer id # pointer to the display descriptor
+int banner # print banner for photometry results
+int xwcs # the x wcs type
+int ywcs # the y wcs type
+pointer im # pointer to the input image
+real xinit # initial x position
+real yinit # initial y position
+
+int cboxsize, rboxsize, npts, naperts, nbins, nr
+pointer sp, radius, intensity, apstr, aperts, rcentroid, pmean, integral, title
+real scale, pradius, iannulus, oannulus, mean, median, sigma, pnorm, inorm
+real fwhmpsf, xcenter, ycenter, apradius, counts
+real clgetr(), dp_aprcounts()
+int dp_rprofile(), strlen(), dp_gaperts(), btoi()
+bool clgetb()
+
+begin
+ # Return if the initial x and y centers are undefined.
+ if (IS_INDEFR(xinit) || IS_INDEFR(yinit))
+ return
+
+ # Get the scale of the image from the datapars pset.
+ scale = clgetr ("datapars.scale")
+ if (scale <= 0.0)
+ scale = 1.0
+ else
+ scale = 1.0 / scale
+
+ # Estimate the center of the star using the datapars parameter
+ # scale and the centerpars parameter cbox and an initial center.
+ # Force the centering box to be an odd number of pixels.
+ cboxsize = scale * clgetr ("centerpars.cbox") + 1.0
+ if (mod (cboxsize, 2) == 0)
+ cboxsize = cboxsize + 1
+ call dp_rcenter (im, xinit, yinit, cboxsize, xcenter, ycenter)
+
+ # Allocate working memory for the radial profile data.
+ pradius = scale * (clgetr ("fitskypars.annulus") +
+ clgetr ("fitskypars.dannulus") + 1.0)
+ rboxsize = 2 * nint (pradius + 1.0) + 1
+ call smark (sp)
+ call salloc (radius, rboxsize * rboxsize, TY_REAL)
+ call salloc (intensity, rboxsize * rboxsize, TY_REAL)
+
+ # Compute the radial profile.
+ npts = dp_rprofile (im, xcenter, ycenter, rboxsize, pradius,
+ Memr[radius], Memr[intensity])
+ if (npts <= 0) {
+ call printf ("No data for computing radial profile\n")
+ call sfree (sp)
+ return
+ }
+
+ # Estimate the sky level and subtract it from the profile.
+ iannulus = scale * clgetr ("fitskypars.annulus")
+ oannulus = iannulus + scale * clgetr ("fitskypars.dannulus")
+ call dp_rskyval (Memr[radius], Memr[intensity], npts,
+ iannulus, oannulus, mean, median, sigma)
+ call asubkr (Memr[intensity], median, Memr[intensity], npts)
+
+ # Get the last photometry aperture and sum up the pixels inside it.
+ call salloc (apstr, SZ_LINE, TY_CHAR)
+ call salloc (aperts, MAX_NAPERTS, TY_REAL)
+ call clgstr ("photpars.apertures", Memc[apstr], SZ_LINE)
+ naperts = dp_gaperts (Memc[apstr], Memr[aperts], MAX_NAPERTS)
+ apradius = scale * Memr[aperts+naperts-1]
+ counts = dp_aprcounts (Memr[radius], Memr[intensity], npts, apradius)
+
+ # Compute the normalized mean intensity as a function of radius
+ # and the normalized integral of the intensity as a function of
+ # radius.
+ nbins = int (pradius / 0.5 + 0.5)
+ call salloc (nr, nbins, TY_INT)
+ call salloc (rcentroid, nbins, TY_REAL)
+ call salloc (pmean, nbins, TY_REAL)
+ call salloc (integral, nbins, TY_REAL)
+ call dp_crprofile (Memr[radius], Memr[intensity], npts, Memi[nr],
+ Memr[rcentroid], Memr[pmean], Memr[integral], nbins, 0.0,
+ pradius, real ((cboxsize-1)/ 2), iannulus, fwhmpsf, pnorm, inorm)
+
+ # Mark the objects on the display.
+ if (id != NULL) {
+ call dp_eomark (id, xcenter, ycenter, iannulus, oannulus,
+ apradius, btoi (clgetb ("centerpars.mkcenter")),
+ btoi (clgetb ("fitskypars.mksky")),
+ btoi (clgetb ("photpars.mkapert")))
+ if (gd == id)
+ call gflush (gd)
+ else
+ call gframe (id)
+ }
+ # Convert the center coordinates if appropriate.
+ call dp_ltov (im, xcenter, ycenter, xcenter, ycenter, 1)
+
+ # Draw the plot.
+ if (gd != NULL) {
+ call salloc (title, 3 * SZ_LINE, TY_CHAR)
+ call sprintf (Memc[title], 3 * SZ_LINE,
+ "%s: Radial profile at %0.2f %0.2f\n")
+ call pargstr (IM_HDRFILE(im))
+ call pargr (xcenter)
+ call pargr (ycenter)
+ call sprintf (Memc[title+strlen(Memc[title])], 3 * SZ_LINE,
+ "Sky: mean %g median %g sigma %g\n")
+ call pargr (mean)
+ call pargr (median)
+ call pargr (sigma)
+ call sprintf (Memc[title+strlen(Memc[title])], 3 * SZ_LINE,
+ "Fwhmpsf: %0.2f Counts: %g Mag: %0.3f\n\n")
+ call pargr (fwhmpsf)
+ call pargr (counts)
+ if (counts <= 0.0)
+ call pargr (INDEFR)
+ else
+ call pargr (-2.5 * log10 (counts))
+ call dp_erplot (gd, Memc[title], xwcs, ywcs, Memr[radius],
+ Memr[intensity], npts, Memr[rcentroid], Memr[pmean],
+ Memr[integral], nbins, 0.0, pradius, iannulus, oannulus,
+ apradius, median, sigma, scale, pnorm)
+ }
+
+ # Print the results.
+ if (gd == NULL) {
+ if (banner == YES)
+ call dp_bprint (STDOUT)
+ call dp_aprint (STDOUT, xcenter, ycenter, median, sigma, fwhmpsf,
+ counts)
+ }
+
+ # Free memory.
+ call sfree (sp)
+end
+
+
+# DP_RCENTER -- Compute the star center using a simple 1D centroiding
+# algorithm on the x and y marginals, after thresholding at the mean.
+
+procedure dp_rcenter (im, xstart, ystart, boxsize, xcntr, ycntr)
+
+pointer im # pointer to the input image
+real xstart, ystart # starting coordinates
+int boxsize # width of the centering box
+real xcntr, ycntr # centered coordinates
+
+int half_box, x1, x2, y1, y2, ncols, nrows, nx, ny, try
+pointer bufptr, sp, x_vect, y_vect
+real xinit, yinit
+pointer imgs2r()
+
+begin
+ # Initialize.
+ half_box = (boxsize - 1) / 2
+ xinit = xstart
+ yinit = ystart
+ ncols = IM_LEN (im,1)
+ nrows = IM_LEN (im,2)
+
+ try = 0
+ repeat {
+
+ # Compute the parameters of the extraction region.
+ x1 = max (xinit - half_box, 1.0) + 0.5
+ x2 = min (xinit + half_box, real (ncols)) + 0.5
+ y1 = max (yinit - half_box, 1.0) + 0.5
+ y2 = min (yinit + half_box, real (nrows)) + 0.5
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+
+ # Get the data.
+ bufptr = imgs2r (im, x1, x2, y1, y2)
+
+ # Allocate space for the marginals.
+ call smark (sp)
+ call salloc (x_vect, nx, TY_REAL)
+ call salloc (y_vect, ny, TY_REAL)
+
+ # Compute the marginals.
+ call aclrr (Memr[x_vect], nx)
+ call aclrr (Memr[y_vect], ny)
+ call dp_rowsum (Memr[bufptr], Memr[x_vect], nx, ny)
+ call dp_colsum (Memr[bufptr], Memr[y_vect], nx, ny)
+
+ # Compute the centers.
+ call dp_vcentroid (Memr[x_vect], nx, xcntr)
+ call dp_vcentroid (Memr[y_vect], ny, ycntr)
+
+ # Add in offsets to image coordinate system.
+ xcntr = xcntr + x1
+ ycntr = ycntr + y1
+
+ call sfree (sp)
+
+ # If the shifts are greater than 1 pixel in either direction
+ # do 1 more iteration.
+ try = try + 1
+ if (try == 1) {
+ if ((abs (xcntr - xinit) > 1.0) || (abs (ycntr - yinit) >
+ 1.0)) {
+ xinit = xcntr
+ yinit = ycntr
+ }
+ } else
+ break
+ }
+end
+
+
+# DP_RPROFILE -- Get the data and compute the radius and intensity vectors.
+
+int procedure dp_rprofile (im, xcntr, ycntr, rboxsize, pradius, radius,
+ intensity)
+
+pointer im # pointer to the input image
+real xcntr, ycntr # the center of the extraction box
+int rboxsize # the width of the extraction box
+real pradius # the plotting radius
+real radius[ARB] # the output radius vector
+real intensity[ARB] # the output intensity vector
+
+int half_box, ncols, nrows, x1, x2, y1, y2, nx, ny, npts
+pointer bufptr
+real xinit, yinit
+int dp_rivectors()
+pointer imgs2r()
+
+begin
+ # Initialize.
+ half_box = (rboxsize - 1) / 2
+ xinit = xcntr
+ yinit = ycntr
+ ncols = IM_LEN(im,1)
+ nrows = IM_LEN(im,2)
+
+ # Get the data.
+ x1 = max (xinit - half_box, 1.0) + 0.5
+ x2 = min (xinit + half_box, real (ncols)) + 0.5
+ y1 = max (yinit - half_box, 1.0) + 0.5
+ y2 = min (yinit + half_box, real (nrows)) + 0.5
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ bufptr = imgs2r (im, x1, x2, y1, y2)
+
+ # Compute the radius and intensity vectors.
+ npts = dp_rivectors (Memr[bufptr], nx, ny, x1, y1, xcntr, ycntr,
+ pradius, radius, intensity)
+
+ return (npts)
+end
+
+
+# DP_RSKYVAL -- Compute the mean, median and sigma of the pixels in the
+# sky annulus.
+
+procedure dp_rskyval (radius, intensity, npts, iannulus, oannulus, mean,
+ median, sigma)
+
+real radius[ARB] # the output radius vector
+real intensity[ARB] # the output intensity vector
+int npts # number of points in the profile
+real iannulus # inner radius of sky annulus
+real oannulus # outer radius of sky annulus
+real mean # mean sky value
+real median # median sky value
+real sigma # standard deviation of sky values
+
+int i, nsky, il, ih, ngood
+pointer skypix
+real slocut, shicut
+
+begin
+ call malloc (skypix, npts, TY_REAL)
+
+ nsky = 0
+ do i = 1, npts {
+ if (radius[i] < iannulus || radius[i] > oannulus)
+ next
+ nsky = nsky + 1
+ Memr[skypix+nsky-1] = intensity[i]
+ }
+ call asrtr (Memr[skypix], Memr[skypix], nsky)
+
+ if (nsky == 0) {
+ mean = 0.0
+ median = 0.0
+ sigma = 0.0
+ } else {
+ call aavgr (Memr[skypix], nsky, mean, sigma)
+ if (mod (nsky, 2) == 0)
+ median = 0.5 * (Memr[skypix+(nsky+1)/2-1] +
+ Memr[skypix+(nsky+1)/2])
+ else
+ median = Memr[skypix+(nsky+1)/2-1]
+ }
+
+ # Detect pixels to be rejected.
+ slocut = median - min (median - Memr[skypix], Memr[skypix+nsky-1] -
+ median, 3.0 * sigma)
+ shicut = median + min (median - Memr[skypix], Memr[skypix+nsky-1] -
+ median, 3.0 * sigma)
+ for (il = 1; il <= nsky; il = il + 1) {
+ if (Memr[skypix+il-1] >= slocut)
+ break
+ }
+ for (ih = nsky; ih >= 1; ih = ih - 1) {
+ if (Memr[skypix+ih-1] <= shicut)
+ break
+ }
+ ngood = ih - il + 1
+ if (ngood < nsky) {
+ if (ngood == 0) {
+ mean = 0.0
+ median = 0.0
+ sigma = 0.0
+ } else {
+ call aavgr (Memr[skypix+il-1], ngood, mean, sigma)
+ if (mod (ngood, 2) == 0)
+ median = 0.5 * (Memr[skypix+il-1+(ngood+1)/2-1] +
+ Memr[skypix+il-1+(ngood+1)/2])
+ else
+ median = Memr[skypix+il-1+(ngood+1)/2-1]
+ }
+ }
+
+
+ call mfree (skypix, TY_REAL)
+end
+
+
+# DP_APRCOUNTS -- Sumup the counts inside the aperture.
+
+real procedure dp_aprcounts (radius, intensity, npts, apradius)
+
+real radius[ARB] # the output radius vector
+real intensity[ARB] # the output intensity vector
+int npts # number of points in the profile
+real apradius # the aperture radius
+
+int i
+real counts
+
+begin
+ counts = 0.0
+ do i = 1, npts {
+ if (radius[i] > apradius)
+ next
+ counts = counts + intensity[i]
+ }
+ return (counts)
+end
+
+
+# DP_CRPROFILE -- Compute the smoothed radial profile and its integral at half
+# pixel intervals.
+
+procedure dp_crprofile (radius, intensity, npts, nr, rcentroid, pmean,
+ integral, nbins, rmin, rmax, prad, irad, fwhmpsf, pnorm, inorm)
+
+real radius[ARB] # the output radius vector
+real intensity[ARB] # the output intensity vector
+int npts # number of points in the profile
+int nr[ARB] # the number of points in each interval
+real rcentroid[ARB] # the centroid of the radius values
+real pmean[ARB] # the mean of the intensity values
+real integral[ARB] # the integral of the curve
+int nbins # the number of radius bins
+real rmin, rmax # the radius min and max values
+real prad # the normalization radius for the profile
+real irad # the normalization radius for the integral
+real fwhmpsf # computed full width halfmax psf
+real pnorm # the maximum profile value
+real inorm # the maximum count value
+
+int i, bin
+real dr, r
+
+begin
+ # Initialize the arrays.
+ call aclri (nr, nbins)
+ call aclrr (rcentroid, nbins)
+ call aclrr (pmean, nbins)
+ call aclrr (integral, nbins)
+
+ # Accumulate the data.
+ dr = real (nbins - 1) / real (rmax - rmin)
+ do i = 1, npts {
+ r = radius[i]
+ if (r < rmin || r > rmax)
+ next
+ bin = int ((r - rmin) * dr) + 1
+ nr[bin] = nr[bin] + 1
+ pmean[bin] = pmean[bin] + intensity[i]
+ rcentroid[bin] = rcentroid[bin] + r
+ }
+
+ # Compute the integral of the radial profile and normalize it
+ # to 1.0 at the radius irad.
+ do i = 2, nbins
+ integral[i] = integral[i-1] + pmean[i-1]
+ bin = int ((irad - rmin) * dr) + 1
+ inorm = integral[min (bin, nbins)]
+ call adivkr (integral, inorm, integral, nbins)
+
+ # Compute the smoothed radial profile and normalize to the
+ # maximum data point inside the radius prad.
+ pnorm = -MAX_REAL
+ do i = 1, npts {
+ if (radius[i] > prad)
+ next
+ if (intensity[i] > pnorm)
+ pnorm = intensity[i]
+ }
+ do i = 1, nbins {
+ if (nr[i] <= 0) {
+ rcentroid[i] = (i - 1.0 + 0.5) / dr
+ if (rcentroid[i] < rmin || rcentroid[i] > rmax)
+ pmean[i] = 0.0
+ else
+ pmean[i] = pnorm
+ } else {
+ rcentroid[i] = rcentroid[i] / nr[i]
+ pmean[i] = pmean[i] / nr[i]
+ }
+ }
+ call adivkr (pmean, pnorm, pmean, nbins)
+
+ # Estimate the full width half max of the psf in pixels.
+ do i = 1, nbins {
+ if (pmean[i] == 0.0)
+ next
+ if (pmean[i] < 0.5)
+ break
+ }
+ if (i == 1)
+ fwhmpsf = 2.0 * rcentroid[1]
+ else if (i == nbins && pmean[nbins] >= 0.5)
+ fwhmpsf = 2.0 * rcentroid[nbins]
+ else if (pmean[i-1] == pmean[i])
+ fwhmpsf = rcentroid[i-1] + rcentroid[i]
+ else
+ fwhmpsf = 2.0 * ((rcentroid[i] * (0.5 - pmean[i-1]) +
+ rcentroid[i-1] * (pmean[i] - 0.5)) / (pmean[i] - pmean[i-1]))
+end
+
+
+# DP_ROWSUM -- Sum all the rows in a raster.
+
+procedure dp_rowsum (raster, row, nx, ny)
+
+real raster[nx,ny] # the input subraster
+real row[ARB] # the output summed row
+int nx, ny # the dimensions of the input subraster
+
+int i, j
+
+begin
+ do i = 1, ny
+ do j = 1, nx
+ row[j] = row[j] + raster[j,i]
+end
+
+
+# DP_COLSUM -- Sum all the columns in a raster.
+
+procedure dp_colsum (raster, col, nx, ny)
+
+real raster[nx,ny] # the input subraster
+real col[ARB] # the output summed column
+int nx, ny # the dimensions of the input subraster
+
+int i, j
+
+begin
+ do i = 1, ny
+ do j = 1, nx
+ col[j] = col[j] + raster[i,j]
+end
+
+
+# DP_VCENTROID -- Compute the centroid of a vector.
+
+procedure dp_vcentroid (vector, nv, vc)
+
+real vector[ARB] # the input vector
+int nv # length of the input array
+real vc # the output centroid
+
+int i
+real sum1, sum2, sigma, cont
+
+begin
+ sum1 = 0.0
+ sum2 = 0.0
+
+ call aavgr (vector, nv, cont, sigma)
+ do i = 1, nv
+ if (vector[i] > cont) {
+ sum1 = sum1 + (i - 1) * (vector[i] - cont)
+ sum2 = sum2 + (vector[i] - cont)
+ }
+
+ vc = sum1 / sum2
+end
+
+
+# DP_RIVECTORS -- Compute the radius and intensity vectors.
+
+int procedure dp_rivectors (a, nx, ny, x1, y1, xcntr, ycntr, pradius,
+ radius, intensity)
+
+real a[nx,ny] # the input data array
+int nx, ny # dimensions of the input array
+int x1, y1 # lower left corner of input array
+real xcntr, ycntr # coordinates of center pixel
+real pradius # the plotting radius
+real radius[ARB] # the output radius vector
+real intensity[ARB] # the output intensity vector
+
+int i, j, npts
+real pr2, r2, dy2
+
+begin
+ pr2 = pradius * pradius
+
+ npts = 0
+ do i = 1, ny {
+ dy2 = (ycntr - y1 + 1 - i) ** 2
+ do j = 1, nx {
+ r2 = (xcntr - x1 + 1 - j) ** 2 + dy2
+ if (r2 > pr2)
+ next
+ npts = npts + 1
+ radius[npts] = sqrt (r2)
+ intensity[npts] = a[j,i]
+ }
+ }
+
+ return (npts)
+end
+
+
+# DP_BPRINT -- Print the photometry banner.
+
+procedure dp_bprint (fd)
+
+int fd # output file descriptor
+
+string banner "# XCENTER YCENTER SKY SKYSIGMA FWHM COUNTS MAG"
+
+begin
+ call fprintf (fd, "\n%s\n")
+ call pargstr (banner)
+end
+
+
+# DP_APRINT -- Print the photometry results.
+
+procedure dp_aprint (fd, xcenter, ycenter, skyval, sigma, fwhmpsf, inorm)
+
+int fd # output file descriptor
+real xcenter # x coordinate of profile
+real ycenter # y coordinate of profile
+real skyval # the sky value
+real sigma # the standard deviation of the sky pixels
+real fwhmpsf # the estimated fwhmpsf
+real inorm # the total counts
+
+begin
+ call fprintf (fd, " %7.2f %7.2f %8.1f %8.2f %6.2f %8.1f %7.3f\n")
+ call pargr (xcenter)
+ call pargr (ycenter)
+ call pargr (skyval)
+ call pargr (sigma)
+ call pargr (fwhmpsf)
+ call pargr (inorm)
+ if (inorm <= 0.0)
+ call pargr (INDEFR)
+ else
+ call pargr (-2.5 * log10 (inorm))
+end
diff --git a/noao/digiphot/daophot/daoedit/idaoedit.key b/noao/digiphot/daophot/daoedit/idaoedit.key
new file mode 100644
index 00000000..5967d1e8
--- /dev/null
+++ b/noao/digiphot/daophot/daoedit/idaoedit.key
@@ -0,0 +1,22 @@
+ Interactive Daoedit Parameter Setup Menu
+
+? Print help
+spbar Mark/verify critical parameters (f, t, a, d, r, w, b)
+q Quit
+
+f Mark/verify the fwhm of the psf on the radial profile plot
+s Mark/verify the sky sigma on the radial profile plot
+l Mark/verify the minimum good data value on the radial profile plot
+u Mark/verify the maximum good data value on the radial profile plot
+
+c Mark/verify the centering box on the radial profile plot
+n Mark/verify the cleaning radius on the radial profile plot
+p Mark/verify the clipping radius on the radial profile plot
+
+a Mark/verify the inner sky annulus radius on the radial profile plot
+d Mark/verify the width of the sky annulus on the radial profile plot
+g Mark/verify the sky region growing radius on the radial profile plot
+
+r Mark/verify the photometry aperture(s) on the radial profile plot
+w Mark/verify the psf function radius on the radial profile plot
+b Mark/verify the psf fitting radius on the radial profile plot
diff --git a/noao/digiphot/daophot/daoedit/mkpkg b/noao/digiphot/daophot/daoedit/mkpkg
new file mode 100644
index 00000000..0fc962d1
--- /dev/null
+++ b/noao/digiphot/daophot/daoedit/mkpkg
@@ -0,0 +1,16 @@
+# DAOEDIT task
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ t_daoedit.x <imhdr.h> <gset.h> ../lib/daophotdef.h daoedit.h
+ dpecolon.x <error.h> daoedit.h
+ dpemark.x <ctype.h> daoedit.h
+ dpeomark.x <gset.h>
+ dpeconfirm.x daoedit.h
+ dperprofile.x <mach.h> <imhdr.h> daoedit.h
+ dperplot.x <gset.h> daoedit.h
+ ;
diff --git a/noao/digiphot/daophot/daoedit/t_daoedit.x b/noao/digiphot/daophot/daoedit/t_daoedit.x
new file mode 100644
index 00000000..8c92e969
--- /dev/null
+++ b/noao/digiphot/daophot/daoedit/t_daoedit.x
@@ -0,0 +1,317 @@
+include <imhdr.h>
+include <gset.h>
+include "../lib/daophotdef.h"
+include "daoedit.h"
+
+define HELPFILE "daophot$daoedit/daoedit.key"
+define IHELPFILE "daophot$daoedit/daoedit.key"
+
+# T_DAOEDIT -- Edit the DAOPHOT parameters interactively using the image
+# display and a radial profile plot.
+
+procedure t_daoedit ()
+
+pointer image # the name of the input image
+int cache # cache the image pixels
+pointer graphics # the graphics device
+pointer display # the image display
+
+real wx, wy, xlast, ylast
+pointer sp, cmd, im, gd, id
+int wcs, key, redraw, gcurtype, curtype, xwcs, ywcs, lastkey
+int req_size, memstat, old_size, buf_size
+
+pointer immap(), gopen()
+int dp_gcur(), btoi(), sizeof(), dp_memstat()
+bool clgetb(), streq()
+errchk gopen()
+
+data gcurtype /'g'/
+
+begin
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+ call salloc (display, SZ_FNAME, TY_CHAR)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ call clgstr ("image", Memc[image], SZ_FNAME)
+ im = immap (Memc[image], READ_ONLY, 0)
+
+ call clgstr ("graphics", Memc[graphics], SZ_FNAME)
+ iferr (gd = gopen (Memc[graphics], AW_DEFER+NEW_FILE, STDGRAPH))
+ gd = NULL
+ call clgstr ("display", Memc[display], SZ_FNAME)
+ if (Memc[display] == EOS)
+ id = NULL
+ else if (streq (Memc[graphics], Memc[display]))
+ id = gd
+ else {
+ iferr {
+ id = gopen (Memc[display], APPEND, STDIMAGE)
+ } then {
+ call eprintf (
+ "Warning: Graphics overlay not available for display device.\n")
+ id = NULL
+ }
+ }
+ cache = btoi (clgetb ("cache"))
+
+ # Set up the display coordinate system.
+ if ((id != NULL) && (id != gd))
+ call dp_gswv (id, Memc[image], im, 4)
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = dp_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call dp_pcache (im, INDEFI, buf_size)
+
+ xlast = INDEFR
+ ylast = INDEFR
+ lastkey = INDEFI
+ xwcs = WCS_XPIX
+ ywcs = WCS_YCOUNT
+ curtype = 'i'
+ redraw = NO
+
+ while (dp_gcur (curtype, wx, wy, wcs, key, Memc[cmd], SZ_LINE) != EOF) {
+
+ # Convert the cursor coordinates if necessary.
+ if (curtype == 'i')
+ call dp_vtol (im, wx, wy, wx, wy, 1)
+
+ switch (key) {
+
+ # Print help page.
+ case '?':
+ if (curtype == 'i') {
+ call pagefile (HELPFILE, "[space=cmhelp,q=quit,?=help]")
+ } else if (curtype == 'g') {
+ #call greactivate (gd, 0)
+ call gpagefile (gd, HELPFILE, "")
+ }
+
+
+ # Quit the program.
+ case 'q':
+ break
+
+ # Toggle between the image display and graphics cursor.
+ case 'g':
+ if (curtype == 'i') {
+ call greactivate (gd, 0)
+ curtype = 'g'
+ } else {
+ call gdeactivate (gd, 0)
+ curtype = 'i'
+ }
+
+ # Toggle between the pixel and scale units plot scale in x.
+ case 'x':
+ if (xwcs == WCS_XPIX)
+ xwcs = WCS_XSCALE
+ else if (xwcs == WCS_XSCALE)
+ xwcs = WCS_XPIX
+ redraw = YES
+
+ # Toggle between the counts and norm plot scale in y.
+ case 'y':
+ if (ywcs == WCS_YCOUNT)
+ ywcs = WCS_YNORM
+ else if (ywcs == WCS_YNORM)
+ ywcs = WCS_YCOUNT
+ redraw = YES
+
+ case 'a':
+ if (curtype == 'i') {
+ if (lastkey == 'a')
+ call dp_erprofile (NULL, id, NO, xwcs, ywcs, im, wx, wy)
+ else
+ call dp_erprofile (NULL, id, YES, xwcs, ywcs, im,
+ wx, wy)
+ } else {
+ call dp_erprofile (NULL, id, NO, xwcs, ywcs, im,
+ xlast, ylast)
+ }
+
+ case 'r':
+ if (curtype == 'i') {
+ xlast = wx
+ ylast = wy
+ }
+ redraw = YES
+
+ case 'i':
+ if (curtype == 'i') {
+ xlast = wx
+ ylast = wy
+ }
+ xwcs = WCS_XPIX
+ ywcs = WCS_YCOUNT
+ redraw = YES
+
+ case ':':
+ call dp_ecolon (Memc[cmd], gd, redraw)
+
+ default:
+ call printf ("Unknown or ambiguous keystroke command\7\n")
+ }
+
+ # Draw the plot.
+ if (redraw == YES) {
+ call dp_erprofile (gd, id, NO, xwcs, ywcs, im, xlast, ylast)
+ if (key == 'i')
+ call dp_isetup (gcurtype, gd)
+ redraw = NO
+ if (curtype == 'i')
+ call gdeactivate (gd, 0)
+ }
+
+ lastkey = key
+ }
+
+ if (id == gd && gd != NULL) {
+ call gclose (gd)
+ } else {
+ if (gd != NULL)
+ call gclose (gd)
+ if (id != NULL)
+ call gclose (id)
+ }
+
+ call imunmap (im)
+
+ # Uncache memory.
+ call fixmem (old_size)
+
+ call sfree (sp)
+end
+
+
+# DP_GCUR --Get a SETPARS cursor value.
+
+int procedure dp_gcur (curtype, x, y, wcs, key, strval, maxch)
+
+int curtype # cursor type
+real x, y # cursor position
+int wcs # cursor wcs
+int key # keystroke value of cursor event
+char strval[ARB] # string value, if any
+int maxch # max chars out
+
+int nitems
+int clgcur()
+
+begin
+ # Initialize.
+ strval[1] = EOS
+
+ # Get a cursor values from the desired cursor parameter.
+ switch (curtype) {
+ case 'i':
+ nitems = clgcur ("icommands", x, y, wcs, key, strval, maxch)
+ case 'g':
+ nitems = clgcur ("gcommands", x, y, wcs, key, strval, maxch)
+ }
+
+ return (nitems)
+end
+
+
+# DP_ISETUP -- Setup the daophot parameters interactively using a
+# radial profile plot.
+
+procedure dp_isetup (curtype, gd)
+
+int curtype # the cursor type graphics or display
+pointer gd # pointer to the graphics stream
+
+int wcs, key
+pointer sp, cmd
+real wx, wy
+int dp_gcur()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ call printf (
+ "Interactive setup menu (?=help, spbar=default, q=quit):\n")
+ while (dp_gcur (curtype, wx, wy, wcs, key, Memc[cmd],
+ SZ_LINE) != EOF) {
+ switch (key) {
+ case '?':
+ call gpagefile (gd, IHELPFILE, "")
+ case 'q':
+ break
+ case 'f':
+ call dp_mfwhmpsf(gd)
+ call dp_cfwhmpsf()
+ case 's':
+ call dp_msigma(gd)
+ call dp_csigma()
+ case 'u':
+ call dp_mdmax(gd)
+ call dp_cdmax()
+ case 'l':
+ call dp_mdmin(gd)
+ call dp_cdmin()
+ case 'c':
+ call dp_mcbox(gd)
+ call dp_ccbox()
+ case 'n':
+ call dp_mrclean(gd)
+ call dp_crclean()
+ case 'p':
+ call dp_mrclip(gd)
+ call dp_crclip()
+ case 'a':
+ call dp_mannulus(gd)
+ call dp_cannulus()
+ case 'd':
+ call dp_mdannulus(gd)
+ call dp_cdannulus()
+ case 'g':
+ call dp_mrgrow(gd)
+ call dp_crgrow()
+ case 'r':
+ call dp_maper(gd)
+ call dp_caper()
+ case 'w':
+ call dp_mpsfrad(gd)
+ call dp_cpsfrad()
+ case 'b':
+ call dp_mfitrad(gd)
+ call dp_cfitrad()
+ case ' ':
+ call dp_mfwhmpsf(gd)
+ call dp_mcbox(gd)
+ call dp_mannulus(gd)
+ call dp_mdannulus(gd)
+ call dp_maper(gd)
+ call dp_mpsfrad(gd)
+ call dp_mfitrad(gd)
+ call gdeactivate(gd, 0)
+ call dp_cbanner()
+ call dp_cfwhmpsf()
+ call dp_ccbox()
+ call dp_cannulus()
+ call dp_cdannulus()
+ call dp_caper()
+ call dp_cpsfrad()
+ call dp_cfitrad()
+ call greactivate(gd, 0)
+ default:
+ call printf (
+ "Interactive setup menu (?=help, spbar=default, q=quit):\n")
+ }
+ call printf (
+ "Interactive setup menu (?=help, spbar=default, q=quit):\n")
+ }
+
+ if (curtype == 'i')
+ call gdeactivate (gd, 0)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/daofind.par b/noao/digiphot/daophot/daofind.par
new file mode 100644
index 00000000..3dbe1b34
--- /dev/null
+++ b/noao/digiphot/daophot/daofind.par
@@ -0,0 +1,21 @@
+# DAOFIND
+
+image,s,a,,,,"Input image(s)"
+output,f,a,"default",,,"Output coordinate file(s) (default: image.coo.?)"
+starmap,s,h,"",,,"Output density enhancement image(s)"
+skymap,s,h,"",,,"Output sky image(s)"
+datapars,pset,h,"",,,"Data dependent parameters"
+findpars,pset,h,"",,,"Object detection parameters"
+boundary,s,h,nearest,,,"Boundary extension (constant|nearest|reflect|wrap)"
+constant,r,h,0.0,,,"Constant for boundary extension"
+interactive,b,h,no,,,"Interactive mode?"
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor: [x y wcs] key [cmd]"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the image pixels?"
+verify,b,h,)_.verify,,,"Verify critical daofind parameters?"
+update,b,h,)_.update,,,"Update critical daofind parameters?"
+verbose,b,h,)_.verbose,,,"Print daofind messages?"
+graphics,s,h,)_.graphics,,,"Graphics device"
+display,s,h,)_.display,,,"Display device"
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/daolib/bicubic.x b/noao/digiphot/daophot/daolib/bicubic.x
new file mode 100644
index 00000000..50bec983
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/bicubic.x
@@ -0,0 +1,47 @@
+# BICUBIC -- Perform bicubic interpolation on an array. The point at which
+# the function is to be estimated lies between the second and third columns
+# and second and third rows of f, at a distance of (dx, dy), from the (2,2)
+# element of f.
+
+real procedure bicubic (f, nbox, dx, dy, dfdx, dfdy)
+
+real f[nbox,nbox] # input real array to be interpolated
+int nbox # size of the input array
+real dx, dy # point at which array is to be interpolated
+real dfdx, dfdy # output derivative of the interpolant
+
+int jy
+real c1, c2, c3, c4, temp[4], dfdxt[4], interp
+
+begin
+ # Interpolate first in x.
+ do jy = 1, 4 {
+ c1 = 0.5 * (f[3,jy] - f[1,jy])
+ c4 = f[3,jy] - f[2,jy] - c1
+ c2 = 3.0 * c4 - 0.5 * (f[4,jy] - f[2,jy]) + c1
+ c3 = c4 - c2
+ c4 = dx * c3
+ temp[jy] = dx * (dx * (c4 + c2) + c1) + f[2,jy]
+ dfdxt[jy] = dx * (c4 * 3.0 + 2.0 * c2) + c1
+ }
+
+ # Interpolate next in y.
+ c1 = 0.5 * (temp[3] - temp[1])
+ c4 = temp[3] - temp[2] - c1
+ c2 = 3.0 * c4 - 0.5 * (temp[4] - temp[2]) + c1
+ c3 = c4 - c2
+ c4 = dy * c3
+
+ # Get the result.
+ interp = dy * (dy * (c4 + c2) + c1) + temp[2]
+
+ # Compute the derivatives.
+ dfdy = dy * (c4 * 3.0 + 2.0 * c2) + c1
+ c1 = 0.5 * (dfdxt[3] - dfdxt[1])
+ c4 = dfdxt[3] - dfdxt[2] - c1
+ c2 = 3.0 * c4 - 0.5 * (dfdxt[4] - dfdxt[2]) + c1
+ c3 = c4 - c2
+ dfdx = dy * (dy * (dy * c3 + c2) + c1) + dfdxt[2]
+
+ return (interp)
+end
diff --git a/noao/digiphot/daophot/daolib/daoran.x b/noao/digiphot/daophot/daolib/daoran.x
new file mode 100644
index 00000000..a63b8b39
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/daoran.x
@@ -0,0 +1,43 @@
+define LEN_IR 97
+define IC 150889
+define M 714025
+define IA 1366
+define RM 1.400511e-6
+
+# DAORAN -- The random number generator RAN2 from Numerical Recipes.
+
+real procedure daoran (idum)
+
+int idum # seed for the random number generator
+
+int j, iff, iy, ir[LEN_IR]
+real rnum2
+data iff /0/
+
+begin
+ repeat {
+
+ # Initialize the random number generator.
+ if ((idum < 0) || (iff == 0)) {
+ iff = 1
+ idum = mod (abs (IC - idum), M)
+ do j = 1, LEN_IR {
+ idum = mod (IA * idum + IC, M)
+ ir[j] = idum
+ }
+ idum = mod (IA * idum + IC, M)
+ iy = idum
+ }
+
+ # Get the random number
+ j = 1 + (LEN_IR * iy) / M
+ j = max (1, min (LEN_IR, j))
+ iy = ir[j]
+ rnum2 = iy * RM
+ idum = mod (IA * idum + IC, M)
+ ir[j] = idum
+
+ } until (rnum2 > 0.0)
+
+ return (rnum2)
+end
diff --git a/noao/digiphot/daophot/daolib/dpairmass.x b/noao/digiphot/daophot/daolib/dpairmass.x
new file mode 100644
index 00000000..bad13607
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpairmass.x
@@ -0,0 +1,42 @@
+include <imhdr.h>
+include "../lib/daophotdef.h"
+
+# DP_AIRMASS -- Set the image airmass.
+
+procedure dp_airmass (im, dao)
+
+pointer im # pointer to IRAF image
+pointer dao # pointer to the daophot structure
+
+pointer sp, key
+real xair
+real imgetr(), dp_statr()
+
+begin
+ # Get the airmass keyword.
+ call smark (sp)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ call dp_stats (dao, AIRMASS, Memc[key], SZ_FNAME)
+
+ # Get the value.
+ if (Memc[key] == EOS)
+ xair = dp_statr (dao, XAIRMASS)
+ else {
+ iferr {
+ xair = imgetr (im, Memc[key])
+ } then {
+ xair = dp_statr (dao, XAIRMASS)
+ call eprintf ("Warning: Image %s Keyword: %s not found\n")
+ call pargstr (IM_HDRFILE(im))
+ call pargstr (Memc[key])
+ }
+ }
+
+ # Store the value.
+ if (IS_INDEFR(xair) || xair <= 0.0)
+ call dp_setr (dao, XAIRMASS, INDEFR)
+ else
+ call dp_setr (dao, XAIRMASS, xair)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/daolib/dpapheader.x b/noao/digiphot/daophot/daolib/dpapheader.x
new file mode 100644
index 00000000..898f9dab
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpapheader.x
@@ -0,0 +1,56 @@
+# DP_APHEADER -- Copy the text database column headers to another file.
+# Consider placing this simple routine in the pttables library at some point.
+
+procedure dp_apheader (in, out)
+
+int in # input file descriptor
+int out # output file descriptor
+
+pointer sp, line
+int getline()
+
+begin
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+
+ while (getline (in, Memc[line]) != EOF) {
+ if (Memc[line] != '#')
+ break
+ if (Memc[line+1] == 'N')
+ break
+ call putline (out, Memc[line])
+ }
+
+ call seek (in, BOF)
+
+ call sfree (sp)
+end
+
+
+# DP_APBANNER -- Copy the text database keyword definitions to another file.
+# Consider placing this simple routine in the pttables library at some point.
+
+
+procedure dp_apbanner (in, out)
+
+int in # input file descriptor
+int out # output file descriptor
+
+pointer sp, line
+int getline()
+
+begin
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+
+ while (getline (in, Memc[line]) != EOF) {
+ if (Memc[line] != '#')
+ break
+ if (Memc[line+1] == 'K')
+ next
+ call putline (out, Memc[line])
+ }
+ call seek (in, BOF)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/daolib/dpdate.x b/noao/digiphot/daophot/daolib/dpdate.x
new file mode 100644
index 00000000..70bf8f41
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpdate.x
@@ -0,0 +1,28 @@
+include <time.h>
+
+# DP_DATE -- Create the date and time strings for the daophot output files.
+
+procedure dp_date (date, time, maxch)
+
+char date[ARB] # the date string
+char time[ARB] # the time string
+int maxch # the maximum number of character in the string
+
+int tm[LEN_TMSTRUCT]
+long ctime
+long clktime()
+#long lsttogmt()
+
+begin
+ ctime = clktime (long(0))
+ #ctime = lsttogmt (ctime)
+ call brktime (ctime, tm)
+ call sprintf (date, maxch, "%04d-%02d-%02d")
+ call pargi (TM_YEAR(tm))
+ call pargi (TM_MONTH(tm))
+ call pargi (TM_MDAY(tm))
+ call sprintf (time, maxch, "%02d:%02d:%02d")
+ call pargi (TM_HOUR(tm))
+ call pargi (TM_MIN(tm))
+ call pargi (TM_SEC(tm))
+end
diff --git a/noao/digiphot/daophot/daolib/dpfilter.x b/noao/digiphot/daophot/daolib/dpfilter.x
new file mode 100644
index 00000000..b6932aa1
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpfilter.x
@@ -0,0 +1,41 @@
+include <imhdr.h>
+include "../lib/daophotdef.h"
+
+# DP_FILTER -- Procedure to set the image airmass.
+
+procedure dp_filter (im, dao)
+
+pointer im # pointer to IRAF image
+pointer dao # pointer to the daophot structure
+
+pointer sp, key, filt
+
+begin
+ call smark (sp)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ call salloc (filt, SZ_FNAME, TY_CHAR)
+
+ call dp_stats (dao, FILTER, Memc[key], SZ_FNAME)
+ Memc[filt] = EOS
+ if (Memc[key] == EOS)
+ call dp_stats (dao, IFILTER, Memc[filt], SZ_FNAME)
+ else {
+ iferr {
+ call imgstr (im, Memc[key], Memc[filt], SZ_FNAME)
+ } then {
+ call dp_stats (dao, IFILTER, Memc[filt], SZ_FNAME)
+ call eprintf ("Warning: Image %s Keyword: %s not found\n")
+ call pargstr (IM_HDRFILE(im))
+ call pargstr (Memc[key])
+ }
+ }
+
+ if (Memc[filt] == EOS) {
+ call dp_sets (dao, IFILTER, "INDEF")
+ } else {
+ call dp_rmwhite (Memc[filt], Memc[filt], SZ_FNAME)
+ call dp_sets (dao, IFILTER, Memc[filt])
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/daolib/dpfree.x b/noao/digiphot/daophot/daolib/dpfree.x
new file mode 100644
index 00000000..fa7c954d
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpfree.x
@@ -0,0 +1,71 @@
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/allstardef.h"
+
+# DP_FREE - Procedure to free the the daophot structure.
+
+procedure dp_free (dp)
+
+pointer dp # pointer to the daophot structure
+
+begin
+ if (DP_MW(dp) != NULL)
+ call mw_close (DP_MW(dp))
+ call mfree (dp, TY_STRUCT)
+end
+
+
+# DP_FITCLOSE -- Procedure to close up the psf fitting structure.
+
+procedure dp_fitclose (dp)
+
+pointer dp # pointer to the daophot structure
+
+pointer psffit
+
+begin
+ psffit = DP_PSFFIT(dp)
+ if (DP_PSFLUT(psffit) != NULL)
+ call mfree (DP_PSFLUT(psffit), TY_REAL)
+ if (DP_PSFPARS(psffit) != NULL)
+ call mfree (DP_PSFPARS(psffit), TY_REAL)
+ call mfree (psffit, TY_STRUCT)
+end
+
+
+# DP_APCLOSE -- Procedure to close up the APSEL parameters.
+
+procedure dp_apclose (dp)
+
+pointer dp # pointer to daophot structure
+
+pointer apsel
+
+begin
+ apsel = DP_APSEL(dp)
+
+ if (DP_APRESULT(apsel) != NULL)
+ call mfree (DP_APRESULT(apsel), TY_INT)
+ if (DP_APID(apsel) != NULL)
+ call mfree (DP_APID(apsel), TY_INT)
+ if (DP_APXCEN(apsel) != NULL)
+ call mfree (DP_APXCEN(apsel), TY_REAL)
+ if (DP_APYCEN(apsel) != NULL)
+ call mfree (DP_APYCEN(apsel), TY_REAL)
+ if (DP_APMAG(apsel) != NULL)
+ call mfree (DP_APMAG(apsel), TY_REAL)
+ if (DP_APERR(apsel) != NULL)
+ call mfree (DP_APERR(apsel), TY_REAL)
+ if (DP_APMSKY(apsel) != NULL)
+ call mfree (DP_APMSKY(apsel), TY_REAL)
+ if (DP_APGROUP(apsel) != NULL)
+ call mfree (DP_APGROUP(apsel), TY_INT)
+ if (DP_APNITER(apsel) != NULL)
+ call mfree (DP_APNITER(apsel), TY_INT)
+ if (DP_APSHARP(apsel) != NULL)
+ call mfree (DP_APSHARP(apsel), TY_REAL)
+ if (DP_APCHI(apsel) != NULL)
+ call mfree (DP_APCHI(apsel), TY_REAL)
+
+ call mfree (apsel, TY_STRUCT)
+end
diff --git a/noao/digiphot/daophot/daolib/dpgetapert.x b/noao/digiphot/daophot/daolib/dpgetapert.x
new file mode 100644
index 00000000..8268373f
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpgetapert.x
@@ -0,0 +1,530 @@
+include <tbset.h>
+include "../../lib/ptkeysdef.h"
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+
+# DP_WGETAPERT -- Read the aperture photometry results and transform the
+# input coordinates to the appropriate coordinate system. Works with
+# either the "old" APPHOT files or the new ST Tables.
+
+procedure dp_wgetapert (dao, im, apd, max_nstars, old_ap)
+
+pointer dao # pointer to the DAOPHOT structure
+pointer im # the input image descriptor
+int apd # input photometry file descriptor
+int max_nstars # maximum number of stars
+bool old_ap # YES indicates old APPHOT file
+
+pointer apsel
+int dp_stati()
+
+begin
+ # Get the stars.
+ call dp_getapert (dao, apd, max_nstars, old_ap)
+
+ # Transform the coordinates if necessary.
+ apsel = DP_APSEL (dao)
+ if (dp_stati (dao, WCSIN) != WCS_LOGICAL)
+ call dp_win (dao, im, Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], DP_APNUM(apsel))
+end
+
+
+# DP_GETAPERT -- Read the aperture photometry results. Works with
+# either the "old" APPHOT files or the new ST Tables.
+
+procedure dp_getapert (dao, apd, max_nstars, old_ap)
+
+pointer dao # pointer to the DAOPHOT structure
+int apd # input Photometry file descriptor
+int max_nstars # maximum number of stars
+bool old_ap # YES indicates old APPHOT file
+
+int nstars
+pointer apsel
+int tbpsta(), dp_goldap(), dp_gtabphot()
+
+begin
+ # Get APSEL pointer.
+ apsel = DP_APSEL (dao)
+
+ # Get the required memory.
+ Memi[DP_APRESULT(apsel)] = DP_PAPID
+ Memi[DP_APRESULT(apsel)+1] = DP_PAPXCEN
+ Memi[DP_APRESULT(apsel)+2] = DP_PAPYCEN
+ Memi[DP_APRESULT(apsel)+3] = DP_PAPMAG1
+ Memi[DP_APRESULT(apsel)+4] = DP_PAPSKY
+
+ # Get the results.
+ if (old_ap) {
+ call dp_memapsel (dao, Memi[DP_APRESULT(apsel)], NAPRESULT,
+ max_nstars)
+ nstars = dp_goldap (apd, dao, max_nstars)
+ } else {
+ call dp_memapsel (dao, Memi[DP_APRESULT(apsel)], NAPRESULT,
+ tbpsta (apd, TBL_NROWS))
+ nstars = dp_gtabphot (apd, dao, tbpsta (apd, TBL_NROWS))
+ }
+
+ # Reallocate to save space if appropopriate.
+ if (nstars < max_nstars)
+ call dp_rmemapsel (dao, Memi[DP_APRESULT(apsel)], NAPRESULT,
+ nstars)
+end
+
+
+# DP_MEMAPSEL -- Procedure to allocate memory for the apselect strucuture.
+
+procedure dp_memapsel (dao, fields, nfields, max_nstars)
+
+pointer dao # pointer to the daophot strucuture
+int fields[ARB] # array of fields
+int nfields # number of fields to allocate space for
+int max_nstars # maximum number of stars
+
+int i
+pointer apsel
+
+begin
+ apsel = DP_APSEL(dao)
+
+ # Allocate space for results.
+ do i = 1, nfields {
+ switch (fields[i]) {
+ case DP_PAPID:
+ if (DP_APID(apsel) != NULL)
+ call mfree (DP_APID(apsel), TY_INT)
+ call malloc (DP_APID(apsel), max_nstars, TY_INT)
+
+ case DP_PAPXCEN:
+ if (DP_APXCEN(apsel) != NULL)
+ call mfree (DP_APXCEN(apsel), TY_REAL)
+ call malloc (DP_APXCEN(apsel), max_nstars, TY_REAL)
+
+ case DP_PAPYCEN:
+ if (DP_APYCEN(apsel) != NULL)
+ call mfree (DP_APYCEN(apsel), TY_REAL)
+ call malloc (DP_APYCEN(apsel), max_nstars, TY_REAL)
+
+ case DP_PAPSKY:
+ if (DP_APMSKY(apsel) != NULL)
+ call mfree (DP_APMSKY(apsel), TY_REAL)
+ call malloc (DP_APMSKY(apsel), max_nstars, TY_REAL)
+
+ case DP_PAPMAG1:
+ if (DP_APMAG(apsel) != NULL)
+ call mfree (DP_APMAG(apsel), TY_REAL)
+ call malloc (DP_APMAG(apsel), max_nstars, TY_REAL)
+
+ case DP_PAPGROUP:
+ if (DP_APGROUP(apsel) != NULL)
+ call mfree (DP_APGROUP(apsel), TY_INT)
+ #call malloc (DP_APGROUP(apsel), max_nstars, TY_INT)
+
+ case DP_PAPMERR1:
+ if (DP_APERR(apsel) != NULL)
+ call mfree (DP_APERR(apsel), TY_REAL)
+ call malloc (DP_APERR(apsel), max_nstars, TY_REAL)
+
+ case DP_PAPNITER:
+ if (DP_APNITER(apsel) != NULL)
+ call mfree (DP_APNITER(apsel), TY_INT)
+ #call malloc (DP_APNITER(apsel), max_nstars, TY_INT)
+
+ case DP_PAPCHI:
+ if (DP_APCHI(apsel) != NULL)
+ call mfree (DP_APCHI(apsel), TY_REAL)
+ call malloc (DP_APCHI(apsel), max_nstars, TY_REAL)
+
+ case DP_PAPSHARP:
+ if (DP_APSHARP(apsel) != NULL)
+ call mfree (DP_APSHARP(apsel), TY_REAL)
+ call malloc (DP_APSHARP(apsel), max_nstars, TY_REAL)
+ }
+ }
+end
+
+
+# DP_GOLDAP -- Read in the photometry from an old style APPHOT file
+
+int procedure dp_goldap (apd, dao, max_nstars)
+
+int apd # the input file descriptor
+pointer dao # pointer to the daophot structure
+int max_nstars # maximum number of stars
+
+int nstars, bufsize, stat
+pointer apsel, apkey, sp, fields
+int dp_apsel()
+
+begin
+ # Define the point to the apselect structure.
+ apsel = DP_APSEL (dao)
+
+ # Allocate some temporary space.
+ call smark (sp)
+ call salloc (fields, SZ_LINE, TY_CHAR)
+
+ # Initialize the keyword structure.
+ call pt_kyinit (apkey)
+
+ # Set up the fields to be retrieved.
+ call dp_gappsf (Memi[DP_APRESULT(apsel)], Memc[fields], NAPRESULT)
+
+ # Now read in the results.
+ nstars = 0
+ bufsize = max_nstars
+ repeat {
+
+ # Read in a group of stars.
+ while (nstars < bufsize) {
+ stat = dp_apsel (apkey, apd, Memc[fields],
+ Memi[DP_APRESULT(apsel)], Memi[DP_APID(apsel)+nstars],
+ Memr[DP_APXCEN(apsel)+nstars],
+ Memr[DP_APYCEN(apsel)+nstars],
+ Memr[DP_APMSKY(apsel)+nstars],
+ Memr[DP_APMAG(apsel)+nstars])
+ if (stat == EOF)
+ break
+ nstars = nstars + 1
+ }
+
+ # Check the buffer size.
+ if (stat == EOF)
+ break
+ bufsize = bufsize + max_nstars
+ call dp_rmemapsel (dao, Memi[DP_APRESULT(apsel)], NAPRESULT,
+ bufsize)
+
+ }
+ DP_APNUM(apsel) = nstars
+
+ # Free the keyword structure.
+ call pt_kyfree (apkey)
+ call sfree (sp)
+
+ return (nstars)
+end
+
+
+# DP_GTABPHOT -- Read in the complete photometry from an ST table.
+
+int procedure dp_gtabphot (tp, dao, max_nstars)
+
+pointer tp # table descriptor
+pointer dao # pointer to daophot structure
+int max_nstars # maximum number of stars
+
+bool nullflag
+int record, index, nrow
+pointer apsel, idpt, xcenpt, ycenpt, magpt, skypt
+int tbpsta()
+
+begin
+ # Define the point to the apselect structure.
+ apsel = DP_APSEL (dao)
+
+ # Find the column pointers
+ call tbcfnd (tp, ID, idpt, 1)
+ if (idpt == NULL)
+ call tbcfnd (tp, "ID", idpt, 1)
+ if (idpt == NULL)
+ call printf ("Error reading ID.\n")
+
+ call tbcfnd (tp, XCENTER, xcenpt, 1)
+ if (xcenpt == NULL)
+ call tbcfnd (tp, "XCENTER", xcenpt, 1)
+ if (xcenpt == NULL)
+ call printf ("Error reading XCENTER.\n")
+
+ call tbcfnd (tp, YCENTER, ycenpt, 1)
+ if (ycenpt == NULL)
+ call tbcfnd (tp, "YCENTER", ycenpt, 1)
+ if (ycenpt == NULL)
+ call printf ("Error reading YCENTER.\n")
+
+ call tbcfnd (tp, MAG, magpt, 1)
+ if (magpt == NULL)
+ call tbcfnd (tp, APMAG, magpt, 1)
+ if (magpt == NULL)
+ call printf ("Error reading MAG.\n")
+
+ call tbcfnd (tp, SKY, skypt, 1)
+ if (skypt == NULL)
+ call tbcfnd (tp, SKY, skypt, 1)
+ if (skypt == NULL)
+ call printf ("Error reading SKY.\n")
+
+
+ # Get the results ignoring any record with ID = NULL.
+ nrow = min (tbpsta (tp, TBL_NROWS), max_nstars)
+ index = 0
+ do record = 1, nrow {
+
+ # Check the ID record.
+ call tbrgti (tp, idpt, Memi[DP_APID(apsel)+index], nullflag, 1,
+ record)
+ if (nullflag)
+ next
+
+ # Read the remaining records.
+ call tbrgtr (tp, xcenpt, Memr[DP_APXCEN(apsel)+index], nullflag, 1,
+ record)
+ call tbrgtr (tp, ycenpt, Memr[DP_APYCEN(apsel)+index], nullflag, 1,
+ record)
+ call tbrgtr (tp, magpt, Memr[DP_APMAG(apsel)+index], nullflag, 1,
+ record)
+ call tbrgtr (tp, skypt, Memr[DP_APMSKY(apsel)+index], nullflag, 1,
+ record)
+ index = index + 1
+ }
+
+ DP_APNUM(apsel) = index
+
+ return (index)
+end
+
+
+# DP_RMEMAPSEL -- Procedure to reallocate memory for the apselect strucuture.
+
+procedure dp_rmemapsel (dao, fields, nfields, max_nstars)
+
+pointer dao # pointer to the daophot strucuture
+int fields[ARB] # integer fields
+int nfields # number of fields
+int max_nstars # maximum number of stars
+
+int i
+pointer apsel
+
+begin
+ # Reallocate space for results.
+ apsel = DP_APSEL(dao)
+
+ do i = 1, nfields {
+ switch (fields[i]) {
+ case DP_PAPID:
+ call realloc (DP_APID(apsel), max_nstars, TY_INT)
+ case DP_PAPXCEN:
+ call realloc (DP_APXCEN(apsel), max_nstars, TY_REAL)
+ case DP_PAPYCEN:
+ call realloc (DP_APYCEN(apsel), max_nstars, TY_REAL)
+ case DP_PAPSKY:
+ call realloc (DP_APMSKY(apsel), max_nstars, TY_REAL)
+ case DP_PAPGROUP:
+ #call realloc (DP_APGROUP(apsel), max_nstars, TY_INT)
+ case DP_PAPMAG1:
+ call realloc (DP_APMAG(apsel), max_nstars, TY_REAL)
+ case DP_PAPMERR1:
+ call realloc (DP_APERR(apsel), max_nstars, TY_REAL)
+ case DP_PAPNITER:
+ #call realloc (DP_APNITER(apsel), max_nstars, TY_INT)
+ case DP_PAPSHARP:
+ call realloc (DP_APSHARP(apsel), max_nstars, TY_REAL)
+ case DP_PAPCHI:
+ call realloc (DP_APCHI(apsel), max_nstars, TY_REAL)
+ }
+ }
+end
+
+
+# DP_GAPPSF -- Set up the structures necessary for retrieving the
+# aperture phtometery results needed for the PSF task.
+
+procedure dp_gappsf (fields, sel_fields, max_nfields)
+
+int fields[ARB] # array of selected fields
+char sel_fields[ARB] # names of selected containing fields
+int max_nfields # maximum number of fields selected
+
+int i
+int strlen()
+
+begin
+ sel_fields[1] = EOS
+
+ do i = 1, max_nfields {
+ switch (fields[i]) {
+ case DP_PAPID:
+ call sprintf (sel_fields[strlen(sel_fields)+1], SZ_LINE, "%s ")
+ call pargstr (ID)
+ case DP_PAPXCEN:
+ call sprintf (sel_fields[strlen(sel_fields)+1], SZ_LINE, "%s ")
+ call pargstr (XCENTER)
+ case DP_PAPYCEN:
+ call sprintf (sel_fields[strlen(sel_fields)+1], SZ_LINE, "%s ")
+ call pargstr (YCENTER)
+ case DP_PAPSKY:
+ call sprintf (sel_fields[strlen(sel_fields)+1], SZ_LINE, "%s ")
+ call pargstr (SKY)
+ case DP_PAPMAG1:
+ call sprintf (sel_fields[strlen(sel_fields)+1], SZ_LINE, "%s ")
+ call pargstr (APMAG)
+ }
+ }
+
+ if (sel_fields[1] != EOS)
+ sel_fields[strlen(sel_fields)] = EOS
+end
+
+
+# DP_APSEL -- Select records from an apphot/daophot text file.
+
+int procedure dp_apsel (key, fd, fields, indices, id, x, y, sky, mag)
+
+pointer key # pointer to key structure
+int fd # text file descriptor
+char fields[ARB] # fields to be output
+int indices[ARB] # indices of fields
+int id # star id number
+real x # x center
+real y # y center
+real sky # sky value
+real mag # magnitude
+
+int nchars, nunique, uunique, funique, ncontinue, recptr
+int first_rec, nselect, record
+pointer line
+int getline(), strncmp(), pt_choose()
+
+data first_rec /YES/
+
+begin
+ # Initialize the file read.
+ if (first_rec == YES) {
+ nunique = 0
+ uunique = 0
+ funique = 0
+ nselect = 0
+ record = 0
+ call malloc (line, SZ_LINE, TY_CHAR)
+ }
+
+ ncontinue = 0
+ recptr = 1
+
+ # Loop over the text file records.
+ repeat {
+
+ # Read in a line of the text file.
+ nchars = getline (fd, Memc[line])
+ if (nchars == EOF)
+ break
+
+ # Determine the type of record.
+ if (Memc[line] == KY_CHAR_POUND) {
+
+ if (strncmp (Memc[line], KY_CHAR_KEYWORD, KY_LEN_STR) == 0) {
+ call pt_kyadd (key, Memc[line], nchars)
+ } else if (strncmp (Memc[line], KY_CHAR_NAME,
+ KY_LEN_STR) == 0) {
+ nunique = nunique + 1
+ call pt_kname (key, Memc[line], nchars, nunique)
+ } else if (strncmp (Memc[line], KY_CHAR_UNITS,
+ KY_LEN_STR) == 0) {
+ uunique = uunique + 1
+ call pt_knunits (key, Memc[line], nchars, uunique)
+ } else if (strncmp (Memc[line], KY_CHAR_FORMAT,
+ KY_LEN_STR) == 0) {
+ funique = funique + 1
+ call pt_knformats (key, Memc[line], nchars, funique)
+ }
+ } else if (Memc[line] == KY_CHAR_NEWLINE) {
+ # skip blank lines
+
+ } else {
+
+ # Construct the table record.
+ call pt_mkrec (key, Memc[line], nchars, first_rec, recptr,
+ ncontinue)
+
+ # Construct output record when there is no continuation char.
+ if (Memc[line+nchars-2] != KY_CHAR_CONT) {
+
+ # Select the appropriate records.
+ if (nselect <= 0) {
+ nselect = pt_choose (key, fields)
+ if (nselect <= 0)
+ break
+ }
+
+ # Construct the output record by moving selected fields
+ # into data structures.
+ call dp_getap (key, indices, id, x, y, sky, mag)
+ record = record + 1
+ first_rec = NO
+
+ # Record is complete so exist the loop.
+ break
+ }
+ }
+
+ }
+
+ if (nchars == EOF || nselect <= 0) {
+ first_rec = YES
+ nunique = 0
+ uunique = 0
+ funique = 0
+ nselect = 0
+ call mfree (line, TY_CHAR)
+ return (EOF)
+ } else
+ return (record)
+end
+
+
+# DP_GETAP -- Decode the selected daophot/apphot values.
+
+procedure dp_getap (key, indices, id, x, y, sky, mag)
+
+pointer key # pointer to keys strucuture
+int indices[ARB] # index array
+int id # star id
+real x # x position
+real y # y position
+real sky # sky value
+real mag # magnitude
+
+int i, index, elem, maxch, kip, ip
+int ctoi(), ctor()
+char buffer[SZ_LINE]
+
+begin
+ do i = 1, KY_NSELECT(key) {
+
+ # Find the key.
+ index = Memi[KY_SELECT(key)+i-1]
+ elem = Memi[KY_ELEM_SELECT(key)+i-1]
+ maxch = Memi[KY_LEN_SELECT(key)+i-1]
+ kip = Memi[KY_PTRS(key)+index-1] + (elem - 1) * maxch
+
+ # Extract the appropriate field.
+ call amovc (Memc[kip], buffer, maxch)
+ buffer[maxch+1] = EOS
+
+ # Decode the output value.
+ ip = 1
+ switch (indices[i]) {
+ case DP_PAPID:
+ if (ctoi (buffer, ip, id) <= 0)
+ id = 0
+ case DP_PAPXCEN:
+ if (ctor (buffer, ip, x) <= 0)
+ x = INDEFR
+ case DP_PAPYCEN:
+ if (ctor (buffer, ip, y) <= 0)
+ y = INDEFR
+ case DP_PAPSKY:
+ if (ctor (buffer, ip, sky) <= 0)
+ sky = INDEFR
+ case DP_PAPMAG1:
+ if (ctor (buffer, ip, mag) <= 0)
+ mag = INDEFR
+ default:
+ call printf ("Error reading the APPHOT results.\n")
+ }
+
+ }
+end
diff --git a/noao/digiphot/daophot/daolib/dpgppars.x b/noao/digiphot/daophot/daolib/dpgppars.x
new file mode 100644
index 00000000..f16fc59e
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpgppars.x
@@ -0,0 +1,227 @@
+include <ctotok.h>
+include "../lib/daophotdef.h"
+
+# DP_GPPARS -- Procedure to fetch the daophot task parameters.
+
+procedure dp_gppars (dao)
+
+pointer dao # pointer to daophot structure
+
+int dp, dap
+pointer mp, str, tstr
+real scale, fwhmpsf, psfrad, matchrad, fitrad, annulus, dannulus, mergerad
+
+bool clgetb(), clgpsetb()
+int clgpseti(), btoi(), dp_fctdecode(), dp_strwrd()
+pointer clopset()
+real clgpsetr()
+
+begin
+ # Allocate working space.
+ call smark (mp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+ call salloc (tstr, SZ_FNAME, TY_CHAR)
+
+ # Open the daophot structure.
+ call dp_init (dao)
+
+ # Set the package parameter text and initialize the verbose switch.
+ call dp_seti (dao, TEXT, btoi (clgetb ("text")))
+ call dp_seti (dao, VERBOSE, btoi (false))
+
+ # Open the datapars parameter set.
+ dp = clopset ("datapars")
+
+ # Set the datapars parameters.
+ scale = clgpsetr (dp, "scale")
+ call dp_setr (dao, SCALE, scale)
+ fwhmpsf = clgpsetr (dp, "fwhmpsf")
+ call dp_setr (dao, SFWHMPSF, fwhmpsf)
+ call dp_setr (dao, MAXGDATA, clgpsetr (dp, "datamax"))
+ call dp_setr (dao, MINGDATA, clgpsetr (dp, "datamin"))
+
+ # Initialize the noise parameters.
+ call clgpset (dp, "ccdread", Memc[str], SZ_FNAME)
+ call dp_sets (dao, CCDREAD, Memc[str])
+ call dp_setr (dao, READNOISE, clgpsetr (dp, "readnoise"))
+ call clgpset (dp, "gain", Memc[str], SZ_FNAME)
+ call dp_sets (dao, CCDGAIN, Memc[str])
+ call dp_setr (dao, PHOTADU, clgpsetr (dp, "epadu"))
+
+ # Initialize the observing parameters. Note that whitespace
+ # is removed from the filter id.
+ call clgpset (dp, "exposure", Memc[str], SZ_FNAME)
+ call dp_sets (dao, EXPTIME, Memc[str])
+ call dp_setr (dao, ITIME, 1.0)
+ call clgpset (dp, "airmass", Memc[str], SZ_FNAME)
+ call dp_sets (dao, AIRMASS, Memc[str])
+ call dp_setr (dao, XAIRMASS, clgpsetr (dp, "xairmass"))
+ call clgpset (dp, "filter", Memc[str], SZ_FNAME)
+ call dp_sets (dao, FILTER, Memc[str])
+ call clgpset (dp, "ifilter", Memc[str], SZ_FNAME)
+ call dp_rmwhite (Memc[str], Memc[str], SZ_FNAME)
+ call dp_sets (dao, IFILTER, Memc[str])
+ call clgpset (dp, "obstime", Memc[str], SZ_FNAME)
+ call dp_sets (dao, OBSTIME, Memc[str])
+ call clgpset (dp, "otime", Memc[str], SZ_FNAME)
+ call dp_sets (dao, OTIME, Memc[str])
+
+ # Close the datapars parameter set.
+ call clcpset (dp)
+
+ # Open the daopars parameter set.
+ dap = clopset ("daopars")
+
+ # Set the psf fitting parameters.
+ call clgpset (dap, "function", Memc[tstr], SZ_FNAME)
+ if (dp_fctdecode (Memc[tstr], Memc[str], SZ_FNAME) <= 0)
+ call strcpy (",gauss,", Memc[str], SZ_FNAME)
+ call dp_sets (dao, FUNCLIST, Memc[str])
+ if (dp_strwrd (1, Memc[tstr], SZ_FNAME, Memc[str]) <= 0)
+ call strcpy ("gauss", Memc[tstr], SZ_FNAME)
+ call dp_sets (dao, FUNCTION, Memc[tstr])
+ call dp_seti (dao, VARORDER, clgpseti (dap, "varorder"))
+ #call dp_seti (dao, FEXPAND, btoi (clgpsetb (dap, "fexpand")))
+ call dp_seti (dao, FEXPAND, NO)
+ call dp_seti (dao, NCLEAN, clgpseti (dap, "nclean"))
+ call dp_seti (dao, SATURATED, btoi (clgpsetb (dap, "saturated")))
+ psfrad = clgpsetr (dap, "psfrad")
+ call dp_setr (dao, RPSFRAD, psfrad)
+ call dp_setr (dao, SPSFRAD, psfrad)
+ matchrad = clgpsetr (dap, "matchrad")
+ call dp_setr (dao, SMATCHRAD, matchrad)
+
+ # Set the fitting parameters.
+ fitrad = clgpsetr (dap, "fitrad")
+ call dp_setr (dao, SFITRAD, fitrad)
+ annulus = clgpsetr (dap, "sannulus")
+ call dp_setr (dao, SANNULUS, annulus)
+ dannulus = clgpsetr (dap, "wsannulus")
+ call dp_setr (dao, SDANNULUS, dannulus)
+ call dp_setr (dao, CRITSNRATIO, clgpsetr (dap, "critsnratio"))
+ call dp_seti (dao, MAXITER, clgpseti (dap, "maxiter"))
+ call dp_seti (dao, MAXGROUP, clgpseti (dap, "maxgroup"))
+ call dp_seti (dao, MAXNSTAR, clgpseti (dap, "maxnstar"))
+ call dp_seti (dao, RECENTER, btoi (clgpsetb (dap, "recenter")))
+ call dp_seti (dao, FITSKY, btoi (clgpsetb (dap, "fitsky")))
+ call dp_seti (dao, GROUPSKY, btoi (clgpsetb (dap, "groupsky")))
+ call dp_setr (dao, FLATERR, clgpsetr (dap, "flaterr"))
+ call dp_setr (dao, PROFERR, clgpsetr (dap, "proferr"))
+ call dp_setr (dao, CLIPRANGE, clgpsetr (dap, "cliprange"))
+ call dp_seti (dao, CLIPEXP, clgpseti (dap, "clipexp"))
+ mergerad = clgpsetr (dap, "mergerad")
+ call dp_setr (dao, SMERGERAD, mergerad)
+
+ # Close the daopars pset file.
+ call clcpset (dap)
+
+ # Compute the fwhmpsf, psf radius, fitting radius and matching radius
+ # in pixels and store.
+
+ call dp_setr (dao, FWHMPSF, fwhmpsf / scale)
+ call dp_setr (dao, PSFRAD, psfrad / scale)
+ call dp_setr (dao, MATCHRAD, matchrad / scale)
+ call dp_setr (dao, FITRAD, fitrad / scale)
+ call dp_setr (dao, ANNULUS, annulus / scale)
+ call dp_setr (dao, DANNULUS, dannulus / scale)
+ if (IS_INDEFR(mergerad))
+ call dp_setr (dao, MERGERAD, INDEFR)
+ else
+ call dp_setr (dao, MERGERAD, mergerad / scale)
+
+ call sfree (mp)
+end
+
+
+# DP_FCTDECODE -- Decode and re-encode the list of analytic functions to be
+# fit in a from suitable for use by strdic. If no valid psf types are included
+# in the list set the dictionary to the gaussian function.
+
+int procedure dp_fctdecode (instr, outstr, maxch)
+
+char instr[ARB] # the input list of functions
+char outstr[ARB] # the output list of functions
+int maxch # maximum size of the output string
+
+int ip, op, ntok, tok
+pointer sp, token
+int ctotok(), strdic(), gstrcpy, gstrcat()
+
+begin
+ call smark (sp)
+ call salloc (token, maxch, TY_CHAR)
+
+ outstr[1] = ','
+ outstr[2] = EOS
+ op = 2
+
+ ntok = 0
+ ip = 1
+ while (instr[ip] != EOS) {
+ tok = ctotok (instr, ip, Memc[token], maxch)
+ if (tok != TOK_IDENTIFIER)
+ next
+ if (strdic (Memc[token], Memc[token], maxch, FCTN_FTYPES) <= 0)
+ next
+ ntok = ntok + 1
+ op = op + gstrcpy (Memc[token], outstr[op], maxch - op + 1)
+ op = op + gstrcat (",", outstr[op], maxch - op + 1)
+ }
+
+ call sfree (sp)
+
+ return (ntok)
+end
+
+
+# DP_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 dp_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/daophot/daolib/dpgsubrast.x b/noao/digiphot/daophot/daolib/dpgsubrast.x
new file mode 100644
index 00000000..6794824b
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpgsubrast.x
@@ -0,0 +1,32 @@
+include <imhdr.h>
+
+# DP_GSUBRAST -- Extract a sub-raster around a specified position such that
+# all pixels within the specified radius are included.
+
+pointer procedure dp_gsubrast (im, x, y, radius, lowx, lowy, nxpix, nypix)
+
+pointer im # image descriptor
+real x,y # position
+real radius # radius
+int lowx, lowy # lower boundaries of subraster
+int nxpix, nypix # number of pixels in subraster
+
+pointer imgs2r()
+
+begin
+ # Determine the boundaries of the area.
+ lowx = int (x - radius) + 1
+ lowy = int (y - radius) + 1
+ lowx = max (1, lowx)
+ lowy = max (1, lowy)
+
+ # Compute the size of the area.
+ nxpix = min (int (x + radius), IM_LEN(im, 1)) - lowx + 1
+ nypix = min (int (y + radius), IM_LEN(im, 2)) - lowy + 1
+
+ # Return a pointer to the pixel buffer.
+ if ((nxpix < 1) || (nypix < 1))
+ return (NULL)
+ else
+ return (imgs2r (im, lowx, lowx + nxpix - 1, lowy, lowy + nypix - 1))
+end
diff --git a/noao/digiphot/daophot/daolib/dpgsvw.x b/noao/digiphot/daophot/daolib/dpgsvw.x
new file mode 100644
index 00000000..289b7d15
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpgsvw.x
@@ -0,0 +1,162 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imio.h>
+include <imhdr.h>
+include <math.h>
+
+# DP_GSWV -- Set the data window and viewport for the image display.
+
+procedure dp_gswv (id, image, im, max_nframes)
+
+pointer id # pointer to the image display graphics stream
+char image # the input image name
+pointer im # pointer to the input image
+int max_nframes # the maximum number of display frames
+
+real vx1, vx2, vy1, vy2
+
+begin
+ if (id == NULL)
+ return
+ call dp_gsview (image, im, max_nframes, vx1, vx2, vy1, vy2)
+ call gsview (id, vx1, vx2, vy1, vy2)
+ call gswind (id, 1.0, real (IM_LEN(im,1)), 1.0, real (IM_LEN(im,2)))
+end
+
+
+# DP_GSVIEW -- Map the viewport and window of the image display.
+
+procedure dp_gsview (image, im, max_nframes, vx1, vx2, vy1, vy2)
+
+char image # the input image name
+pointer im # pointer to the input image
+int max_nframes # the maximum number of display frames
+real vx1, vx2, vy1, vy2 # the output viewport
+
+int i, frame, wcs_status, dim1, dim2, step1, step2
+pointer sp, rimname, frimage, frimname, frim, iw
+real x1, x2, y1, y2, fx1, fx2, fy1, fy2, junkx, junky
+bool streq()
+pointer imd_mapframe(), iw_open()
+
+begin
+ # Allocate some memory.
+ call smark (sp)
+ call salloc (rimname, SZ_FNAME, TY_CHAR)
+ call salloc (frimage, SZ_FNAME, TY_CHAR)
+ call salloc (frimname, SZ_FNAME, TY_CHAR)
+
+ # Get the root image name.
+ call imgimage (image, Memc[rimname], SZ_FNAME)
+
+ # Loop through the defined image frames searching for the one
+ # which has the image loaded.
+
+ frame = 0
+ do i = 1, max_nframes {
+ frim = imd_mapframe (i, READ_ONLY, NO)
+ iw = iw_open (frim, i, Memc[frimage], SZ_FNAME, wcs_status)
+ call imgimage (Memc[frimage], Memc[frimname], SZ_FNAME)
+ if (streq (Memc[rimname], Memc[frimname])) {
+ frame = i
+ break
+ } else {
+ call iw_close (iw)
+ call imunmap (frim)
+ }
+ }
+
+ # Default to current frame if the image has not been displayes?
+ if (frame == 0) {
+ call eprintf ("Warning: image %s is not loaded in the display\n")
+ call pargstr (Memc[rimname])
+ vx1 = 0.0
+ vx2 = 1.0
+ vy1 = 0.0
+ vy2 = 1.0
+ call sfree (sp)
+ return
+ }
+
+ # Find the beginning and end points of the requested image section.
+ # We already know at this point that the input logical image is
+ # 2-dimensional. However this 2-dimensional section may be part of
+ # n-dimensional image.
+
+ # X dimension.
+ dim1 = IM_VMAP(im,1)
+ step1 = IM_VSTEP(im,dim1)
+ if (step1 >= 0) {
+ x1 = IM_VOFF(im,dim1) + 1
+ x2 = x1 + IM_LEN(im,1) - 1
+ } else {
+ x1 = IM_VOFF(im,dim1) - 1
+ x2 = x1 - IM_LEN(im,1) + 1
+ }
+
+ # Y dimension.
+ dim2 = IM_VMAP(im,2)
+ step2 = IM_VSTEP(im,dim2)
+ if (step2 >= 0) {
+ y1 = IM_VOFF(im,dim2) + 1
+ y2 = y1 + IM_LEN(im,2) - 1
+ } else {
+ y1 = IM_VOFF(im,dim2) - 1
+ y2 = y1 - IM_LEN(im,2) + 1
+ }
+
+ # Get the frame buffer coordinates corresponding to the lower left
+ # and upper right corners of the image section.
+
+ call iw_im2fb (iw, x1, y1, fx1, fy1)
+ call iw_im2fb (iw, x2, y2, fx2, fy2)
+ if (fx1 > fx2) {
+ junkx = fx1
+ fx1 = fx2
+ fx2 = junkx
+ }
+ if (fy1 > fy2) {
+ junky = fy1
+ fy1 = fy2
+ fy2 = junky
+ }
+
+ # Check that some portion of the input image is in the display.
+ # If not select the default viewport and window coordinates.
+ if (fx1 > IM_LEN(frim,1) || fx2 < 1.0 || fy1 > IM_LEN(frim,2) ||
+ fy2 < 1.0) {
+ vx1 = 0.0
+ vx2 = 1.0
+ vy1 = 0.0
+ vy2 = 1.0
+ call iw_close (iw)
+ call imunmap (frim)
+ call sfree (sp)
+ return
+ }
+
+ # Compute a new viewport and window for X.
+ if (fx1 >= 1.0)
+ vx1 = max (0.0, min (1.0, (fx1 - 0.5) / IM_LEN(frim,1)))
+ else
+ vx1 = 0.0
+ if (fx2 <= IM_LEN(frim,1))
+ vx2 = max (0.0, min (1.0, (fx2 + 0.5) / IM_LEN(frim,1)))
+ else
+ vx2 = 1.0
+
+ # Compute a new viewport and window for Y.
+ if (fy1 >= 1.0)
+ vy1 = max (0.0, min (1.0, (fy1 - 0.5) / IM_LEN(frim,2)))
+ else
+ vy1 = 0.0
+ if (fy2 <= IM_LEN(frim,2))
+ vy2 = max (0.0, min (1.0, (fy2 + 0.5) / IM_LEN(frim,2)))
+ else
+ vy2 = 1.0
+
+ # Clean up.
+ call iw_close (iw)
+ call imunmap (frim)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/daolib/dpimkeys.x b/noao/digiphot/daophot/daolib/dpimkeys.x
new file mode 100644
index 00000000..9cfd1943
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpimkeys.x
@@ -0,0 +1,71 @@
+include "../lib/daophotdef.h"
+
+# DP_IMKEYS - Set the image name and keyword parameters after an image
+# is mapped.
+
+procedure dp_imkeys (dp, im)
+
+pointer dp # pointer to the daophot structure
+pointer im # the image descriptor
+
+pointer mw, ct
+int dp_stati()
+pointer mw_openim(), mw_sctran()
+errchk mw_openim(), mw_sctran()
+
+begin
+ # Set the wcs descriptors.
+ mw = dp_stati (dp, MW)
+ if (mw != NULL)
+ call mw_close (mw)
+ iferr {
+ mw = mw_openim (im)
+ } then {
+ call dp_seti (dp, MW, NULL)
+ call dp_seti (dp, CTIN, NULL)
+ call dp_seti (dp, CTOUT, NULL)
+ call dp_seti (dp, CTPSF, NULL)
+ } else {
+ call dp_seti (dp, MW, mw)
+ switch (dp_stati (dp, WCSIN)) {
+ case WCS_WORLD:
+ iferr (ct = mw_sctran (mw, "world", "logical", 03B))
+ ct = NULL
+ case WCS_PHYSICAL:
+ iferr (ct = mw_sctran (mw, "physical", "logical", 03B))
+ ct = NULL
+ case WCS_TV, WCS_LOGICAL:
+ ct = NULL
+ default:
+ ct = NULL
+ }
+ call dp_seti (dp, CTIN, ct)
+ switch (dp_stati (dp, WCSOUT)) {
+ case WCS_PHYSICAL:
+ iferr (ct = mw_sctran (mw, "logical", "physical", 03B))
+ ct = NULL
+ case WCS_TV, WCS_LOGICAL:
+ ct = NULL
+ default:
+ ct = NULL
+ }
+ call dp_seti (dp, CTOUT, ct)
+ switch (dp_stati (dp, WCSPSF)) {
+ case WCS_PHYSICAL:
+ iferr (ct = mw_sctran (mw, "logical", "physical", 03B))
+ ct = NULL
+ case WCS_TV, WCS_LOGICAL:
+ ct = NULL
+ default:
+ ct = NULL
+ }
+ call dp_seti (dp, CTPSF, ct)
+ }
+
+ # Get the proper values from the image header if an image is defined.
+ call dp_padu (im, dp)
+ call dp_rdnoise (im, dp)
+ call dp_filter (im, dp)
+ call dp_airmass (im, dp)
+ call dp_otime (im, dp)
+end
diff --git a/noao/digiphot/daophot/daolib/dpinit.x b/noao/digiphot/daophot/daolib/dpinit.x
new file mode 100644
index 00000000..ceac884b
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpinit.x
@@ -0,0 +1,225 @@
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/allstardef.h"
+
+# DP_INIT - Procedure to initialize the daophot structure.
+
+procedure dp_init (dp)
+
+pointer dp # pointer to the daophot structure
+
+begin
+ # Set the daophot structure.
+ call calloc (dp, LEN_DPSTRUCT, TY_STRUCT)
+
+ # Initalize the output type parameters.
+ DP_TEXT(dp) = YES
+ DP_VERBOSE(dp) = YES
+
+ # Initialize the wcs parameters.
+ DP_MW(dp) = NULL
+ DP_WCSIN(dp) = WCS_LOGICAL
+ DP_WCSOUT(dp) = WCS_LOGICAL
+ DP_WCSPSF(dp) = WCS_LOGICAL
+ DP_CTIN(dp) = NULL
+ DP_CTOUT(dp) = NULL
+ DP_CTPSF(dp) = NULL
+
+ # Initialize the data depedent parameters.
+ DP_SCALE(dp) = DEF_SCALE
+ DP_SFWHMPSF(dp) = DEF_FWHMPSF
+ DP_FWHMPSF(dp) = DEF_FWHMPSF / DEF_SCALE
+ DP_MINGDATA(dp) = INDEFR
+ DP_MAXGDATA(dp) = INDEFR
+
+ # Initialize the noise parameters
+ DP_CCDGAIN(dp) = EOS
+ DP_PHOTADU(dp) = INDEFR
+ DP_CCDREAD(dp) = EOS
+ DP_READNOISE(dp) = INDEFR
+
+ # Initialize the observing parameters.
+ DP_EXPTIME(dp) = EOS
+ DP_ITIME(dp) = INDEFR
+ DP_AIRMASS(dp) = EOS
+ DP_XAIRMASS(dp) = INDEFR
+ DP_FILTER(dp) = EOS
+ DP_IFILTER(dp) = EOS
+ DP_OBSTIME(dp) = EOS
+ DP_OTIME(dp) = EOS
+
+ # Initialize the psf fitting parameters.
+ call strcpy (",gauss,", DP_FUNCLIST(dp), SZ_FNAME)
+ call strcpy ("gauss", DP_FUNCTION(dp), SZ_FNAME)
+ DP_VARORDER(dp) = -1
+ DP_FEXPAND(dp) = NO
+ DP_SATURATED(dp) = NO
+ DP_RPSFRAD(dp) = DEF_PSFRAD / DEF_SCALE
+ DP_SPSFRAD (dp) = DEF_PSFRAD / DEF_SCALE
+ DP_PSFRAD (dp) = DEF_PSFRAD
+
+ # Initialize the fitting parameters.
+ DP_SFITRAD(dp) = DEF_FITRAD / DEF_SCALE
+ DP_FITRAD(dp) = DEF_FITRAD
+ DP_SANNULUS(dp) = DEF_ANNULUS / DEF_SCALE
+ DP_ANNULUS(dp) = DEF_ANNULUS
+ DP_SDANNULUS(dp) = DEF_DANNULUS / DEF_SCALE
+ DP_DANNULUS(dp) = DEF_DANNULUS
+ DP_MAXITER(dp) = DEF_MAXITER
+ DP_MAXGROUP(dp) = DEF_MAXGROUP
+ DP_MAXNSTAR(dp) = DEF_MAXNSTAR
+ DP_RECENTER(dp) = YES
+ DP_FITSKY(dp) = NO
+ DP_GROUPSKY(dp) = YES
+
+ # Initialize the file names.
+ DP_INIMAGE(dp) = EOS
+ DP_COORDS(dp) = EOS
+ DP_INPHOTFILE(dp) = EOS
+ DP_PSFIMAGE(dp) = EOS
+ DP_OUTPHOTFILE(dp) = EOS
+ DP_OUTIMAGE(dp) = EOS
+ DP_OUTREJFILE(dp) = EOS
+
+ # Initialize the substructure pointers.
+ DP_PSF(dp) = NULL
+ DP_PSFFIT(dp) = NULL
+ DP_GROUP(dp) = NULL
+ DP_PEAK(dp) = NULL
+ DP_NSTAR(dp) = NULL
+ DP_SUBSTAR(dp) = NULL
+ DP_ADDSTAR(dp) = NULL
+ DP_ALLSTAR(dp) = NULL
+ DP_APSEL(dp) = NULL
+end
+
+
+# DP_FITSETUP -- Setup the current PSF parameters given that the fitting
+# parameters have been correctly read in.
+
+procedure dp_fitsetup (dp)
+
+pointer dp # pointer to daophot structure
+
+pointer psffit
+bool streq()
+
+begin
+ # Set up the psf fit structure.
+ call malloc (DP_PSFFIT(dp), LEN_PSFFIT, TY_STRUCT)
+ psffit = DP_PSFFIT(dp)
+ call calloc (DP_PSFPARS(psffit), MAX_NFCTNPARS, TY_REAL)
+
+ # Define the psf function. The if user entered string is "auto"
+ # or a list then intialize the psf function to "gauss" or the
+ # first function in the list respectively.
+
+ if (streq (DP_FUNCTION(dp), "gauss")) {
+ DP_PSFUNCTION(psffit) = FCTN_GAUSS
+ } else if (streq (DP_FUNCTION(dp), "moffat25")) {
+ DP_PSFUNCTION(psffit) = FCTN_MOFFAT25
+ } else if (streq (DP_FUNCTION(dp), "penny1")) {
+ DP_PSFUNCTION(psffit) = FCTN_PENNY1
+ } else if (streq (DP_FUNCTION(dp), "moffat15")) {
+ DP_PSFUNCTION(psffit) = FCTN_MOFFAT15
+ } else if (streq (DP_FUNCTION(dp), "penny2")) {
+ DP_PSFUNCTION(psffit) = FCTN_PENNY2
+ } else if (streq (DP_FUNCTION(dp), "lorentz")) {
+ DP_PSFUNCTION(psffit) = FCTN_LORENTZ
+ } else if (streq (DP_FUNCTION(dp), "auto")) {
+ DP_PSFUNCTION(psffit) = FCTN_GAUSS
+ } else {
+ call error (0, "Unknown analytic PSF function")
+ }
+
+ switch (DP_VARORDER(dp)) {
+ case -1:
+ DP_NVLTABLE(psffit) = 0
+ case 0:
+ DP_NVLTABLE(psffit) = 1
+ case 1:
+ DP_NVLTABLE(psffit) = 3
+ case 2:
+ DP_NVLTABLE(psffit) = 6
+ }
+ if (DP_FEXPAND(dp) == NO)
+ DP_NFEXTABLE(psffit) = 0
+ else
+ DP_NFEXTABLE(psffit) = 5
+
+ # Set the initial values of the function parameters.
+ switch (DP_PSFUNCTION(psffit)) {
+ case FCTN_GAUSS:
+ DP_PSFNPARS(psffit) = 2
+ Memr[DP_PSFPARS(psffit)] = DP_FWHMPSF(dp) / 2.0
+ Memr[DP_PSFPARS(psffit)+1] = DP_FWHMPSF(dp) / 2.0
+ case FCTN_MOFFAT25:
+ DP_PSFNPARS(psffit) = 3
+ Memr[DP_PSFPARS(psffit)] = DP_FWHMPSF(dp) / 2.0
+ Memr[DP_PSFPARS(psffit)+1] = DP_FWHMPSF(dp) / 2.0
+ Memr[DP_PSFPARS(psffit)+2] = 0.0
+ Memr[DP_PSFPARS(psffit)+3] = 2.5
+ case FCTN_PENNY1:
+ DP_PSFNPARS(psffit) = 4
+ Memr[DP_PSFPARS(psffit)] = DP_FWHMPSF(dp) / 2.0
+ Memr[DP_PSFPARS(psffit)+1] = DP_FWHMPSF(dp) / 2.0
+ Memr[DP_PSFPARS(psffit)+2] = 0.75
+ Memr[DP_PSFPARS(psffit)+3] = 0.0
+ case FCTN_MOFFAT15:
+ DP_PSFNPARS(psffit) = 3
+ Memr[DP_PSFPARS(psffit)] = DP_FWHMPSF(dp) / 2.0
+ Memr[DP_PSFPARS(psffit)+1] = DP_FWHMPSF(dp) / 2.0
+ Memr[DP_PSFPARS(psffit)+2] = 0.0
+ Memr[DP_PSFPARS(psffit)+3] = 1.5
+ case FCTN_PENNY2:
+ DP_PSFNPARS(psffit) = 5
+ Memr[DP_PSFPARS(psffit)] = DP_FWHMPSF(dp) / 2.0
+ Memr[DP_PSFPARS(psffit)+1] = DP_FWHMPSF(dp) / 2.0
+ Memr[DP_PSFPARS(psffit)+2] = 0.75
+ Memr[DP_PSFPARS(psffit)+3] = 0.0
+ Memr[DP_PSFPARS(psffit)+4] = 0.0
+ case FCTN_LORENTZ:
+ DP_PSFNPARS(psffit) = 3
+ Memr[DP_PSFPARS(psffit)] = DP_FWHMPSF(dp) / 2.0
+ Memr[DP_PSFPARS(psffit)+1] = DP_FWHMPSF(dp) / 2.0
+ Memr[DP_PSFPARS(psffit)+2] = 0.0
+ default:
+ call error (0, "Unknown analytic PSF function")
+ }
+
+ DP_PSFHEIGHT(psffit) = INDEFR
+ DP_PSFMAG(psffit) = INDEFR
+ DP_PSFX(psffit) = INDEFR
+ DP_PSFY(psffit) = INDEFR
+
+ DP_PSFSIZE(psffit) = 0
+ DP_PSFLUT(psffit) = NULL
+end
+
+
+# DP_APSELSETUP -- Procedure to set up the APSEL parameters.
+
+procedure dp_apselsetup (dp)
+
+pointer dp # pointer to daophot structure
+
+pointer apsel
+
+begin
+ # APSEL structure
+ call malloc (DP_APSEL(dp), LEN_DPAPSTRUCT, TY_STRUCT)
+ apsel = DP_APSEL(dp)
+ call malloc (DP_APRESULT(apsel), NAPPAR, TY_INT)
+
+ # Set the default values for the apsel parameters.
+ DP_APID(apsel) = NULL
+ DP_APXCEN(apsel)= NULL
+ DP_APYCEN(apsel)= NULL
+ DP_APMAG(apsel) = NULL
+ DP_APERR(apsel) = NULL
+ DP_APMSKY(apsel)= NULL
+ DP_APGROUP(apsel) = NULL
+ DP_APNITER(apsel) = NULL
+ DP_APCHI(apsel) = NULL
+ DP_APSHARP(apsel) = NULL
+end
diff --git a/noao/digiphot/daophot/daolib/dpnames.x b/noao/digiphot/daophot/daolib/dpnames.x
new file mode 100644
index 00000000..ca1fa858
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpnames.x
@@ -0,0 +1,415 @@
+
+# DP_IIMNAME -- Procedure to construct an daophot input image name.
+# If input is null or a directory a name is constructed from the root
+# of the image name and the extension. The disk is searched to avoid
+# name collisions.
+
+procedure dp_iimname (image, input, ext, name, maxch)
+
+char image[ARB] # image name
+char input[ARB] # input directory or name
+char ext[ARB] # extension
+char name[ARB] # input name
+int maxch # maximum size of name
+
+int ndir, nimdir, clindex, clsize
+pointer sp, root, str
+int fnldir(), strlen()
+
+begin
+ call smark (sp)
+ call salloc (root, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ ndir = fnldir (input, name, maxch)
+ if (strlen (input) == ndir) {
+ call imparse (image, Memc[root], SZ_FNAME, Memc[str], SZ_FNAME,
+ Memc[str], SZ_FNAME, clindex, clsize)
+ nimdir = fnldir (Memc[root], Memc[str], SZ_FNAME)
+ if (clindex >= 0) {
+ call sprintf (name[ndir+1], maxch, "%s%d.%s.*")
+ call pargstr (Memc[root+nimdir])
+ call pargi (clindex)
+ call pargstr (ext)
+ } else {
+ call sprintf (name[ndir+1], maxch, "%s.%s.*")
+ call pargstr (Memc[root+nimdir])
+ call pargstr (ext)
+ }
+
+ call dp_iimversion (name, name, maxch)
+ } else
+ call strcpy (input, name, maxch)
+
+ call sfree (sp)
+end
+
+
+# DP_IMROOT -- Fetch the root image name minus the directory specification
+# and the section notation.
+
+procedure dp_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
+
+
+# DP_OIMVERSION -- Routine to compute the next available version number of
+# a given file name template and output the new files name.
+
+procedure dp_oimversion (template, filename, maxch)
+
+char template[ARB] # name template
+char filename[ARB] # output name
+int maxch # maximum number of characters
+
+char period
+int newversion, version, len
+pointer sp, list, name
+int imtopen(), imtgetim(), strldx(), ctoi()
+
+begin
+ # Allocate temporary space
+ call smark (sp)
+ call salloc (name, maxch, TY_CHAR)
+ period = '.'
+ list = imtopen (template)
+
+ # Loop over the names in the list searchng for the highest version.
+ newversion = 0
+ while (imtgetim (list, Memc[name], maxch) != EOF) {
+ len = strldx (period, Memc[name])
+ Memc[name+len-1] = EOS
+ len = strldx (period, Memc[name])
+ len = len + 1
+ if (ctoi (Memc[name], len, version) <= 0)
+ next
+ newversion = max (newversion, version)
+ }
+
+ # Make new output file name.
+ len = strldx (period, template)
+ call strcpy (template, filename, len)
+ call sprintf (filename[len+1], maxch, "%d")
+ call pargi (newversion + 1)
+
+ call imtclose (list)
+ call sfree (sp)
+end
+
+
+# DP_IIMVERSION -- Routine to compute the next available version number of
+# a given file name template and output the new files name.
+
+procedure dp_iimversion (template, filename, maxch)
+
+char template[ARB] # name template
+char filename[ARB] # output name
+int maxch # maximum number of characters
+
+char period
+int newversion, version, len
+pointer sp, list, name
+int imtopen(), imtgetim() strldx(), ctoi()
+
+begin
+ # Allocate temporary space
+ call smark (sp)
+ call salloc (name, maxch, TY_CHAR)
+ period = '.'
+ list = imtopen (template)
+
+ # Loop over the names in the list searchng for the highest version.
+ newversion = 0
+ while (imtgetim (list, Memc[name], maxch) != EOF) {
+ len = strldx (period, Memc[name])
+ Memc[name+len-1] = EOS
+ len = strldx (period, Memc[name])
+ len = len + 1
+ if (ctoi (Memc[name], len, version) <= 0)
+ next
+ newversion = max (newversion, version)
+ }
+
+ # Make new output file name.
+ len = strldx (period, template)
+ call strcpy (template, filename, len)
+ call sprintf (filename[len+1], maxch, "%d")
+ call pargi (newversion)
+
+ call imtclose (list)
+ call sfree (sp)
+end
+
+
+# DP_OIMNAME -- Procedure to construct an daophot output image name.
+# If output is null or a directory a name is constructed from the root
+# of the image name and the extension. The disk is searched to avoid
+# name collisions.
+
+procedure dp_oimname (image, output, ext, name, maxch)
+
+char image[ARB] # image name
+char output[ARB] # output directory or name
+char ext[ARB] # extension
+char name[ARB] # output name
+int maxch # maximum size of name
+
+int ndir, nimdir, clindex, clsize
+pointer sp, root, str
+int fnldir(), strlen()
+
+begin
+ call smark (sp)
+ call salloc (root, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ ndir = fnldir (output, name, maxch)
+ if (strlen (output) == ndir) {
+ call imparse (image, Memc[root], SZ_FNAME, Memc[str], SZ_FNAME,
+ Memc[str], SZ_FNAME, clindex, clsize)
+ nimdir = fnldir (Memc[root], Memc[str], SZ_FNAME)
+ if (clindex >= 0) {
+ call sprintf (name[ndir+1], maxch, "%s%d.%s.*")
+ call pargstr (Memc[root+nimdir])
+ call pargi (clindex)
+ call pargstr (ext)
+ } else {
+ call sprintf (name[ndir+1], maxch, "%s.%s.*")
+ call pargstr (Memc[root+nimdir])
+ call pargstr (ext)
+ }
+ call dp_oimversion (name, name, maxch)
+ } else
+ call strcpy (output, name, maxch)
+
+ call sfree (sp)
+end
+
+
+# DP_INNAME -- Procedure to construct an daophot input file name.
+# If input is null or a directory a name is constructed from the root
+# of the image name and the extension. The disk is searched to avoid
+# name collisions.
+
+procedure dp_inname (image, input, ext, name, maxch)
+
+char image[ARB] # image name
+char input[ARB] # input directory or name
+char ext[ARB] # extension
+char name[ARB] # input name
+int maxch # maximum size of name
+
+int ndir, nimdir, clindex, clsize
+pointer sp, root, str
+int fnldir(), strlen()
+
+begin
+ call smark (sp)
+ call salloc (root, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ ndir = fnldir (input, name, maxch)
+ if (strlen (input) == ndir) {
+ call imparse (image, Memc[root], SZ_FNAME, Memc[str], SZ_FNAME,
+ Memc[str], SZ_FNAME, clindex, clsize)
+ nimdir = fnldir (Memc[root], Memc[str], SZ_FNAME)
+ if (clindex >= 0) {
+ call sprintf (name[ndir+1], maxch, "%s%d.%s.*")
+ call pargstr (Memc[root+nimdir])
+ call pargi (clindex)
+ call pargstr (ext)
+ } else {
+ call sprintf (name[ndir+1], maxch, "%s.%s.*")
+ call pargstr (Memc[root+nimdir])
+ call pargstr (ext)
+ }
+ call dp_iversion (name, name, maxch)
+ } else
+ call strcpy (input, name, maxch)
+
+ call sfree (sp)
+end
+
+
+# DP_OUTNAME -- Procedure to construct an daophot output file name.
+# If output is null or a directory a name is constructed from the root
+# of the image name and the extension. The disk is searched to avoid
+# name collisions.
+
+procedure dp_outname (image, output, ext, name, maxch)
+
+char image[ARB] # image name
+char output[ARB] # output directory or name
+char ext[ARB] # extension
+char name[ARB] # output name
+int maxch # maximum size of name
+
+int ndir, nimdir, clindex, clsize
+pointer sp, root, str
+int fnldir(), strlen()
+
+begin
+ call smark (sp)
+ call salloc (root, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ ndir = fnldir (output, name, maxch)
+ if (strlen (output) == ndir) {
+ call imparse (image, Memc[root], SZ_FNAME, Memc[str], SZ_FNAME,
+ Memc[str], SZ_FNAME, clindex, clsize)
+ nimdir = fnldir (Memc[root], Memc[str], SZ_FNAME)
+ if (clindex >= 0) {
+ call sprintf (name[ndir+1], maxch, "%s%d.%s.*")
+ call pargstr (Memc[root+nimdir])
+ call pargi (clindex)
+ call pargstr (ext)
+ } else {
+ call sprintf (name[ndir+1], maxch, "%s.%s.*")
+ call pargstr (Memc[root+nimdir])
+ call pargstr (ext)
+ }
+ call dp_oversion (name, name, maxch)
+ } else
+ call strcpy (output, name, maxch)
+
+ call sfree (sp)
+end
+
+
+# DP_OVERSION -- Routine to compute the next available version number of a given
+# file name template and output the new files name.
+
+procedure dp_oversion (template, filename, maxch)
+
+char template[ARB] # name template
+char filename[ARB] # output name
+int maxch # maximum number of characters
+
+char period
+int newversion, version, len
+pointer sp, list, name
+int fntgfnb() strldx(), ctoi(), fntopnb()
+
+begin
+ # Allocate temporary space
+ call smark (sp)
+ call salloc (name, maxch, TY_CHAR)
+ period = '.'
+ list = fntopnb (template, NO)
+
+ # Loop over the names in the list searchng for the highest version.
+ newversion = 0
+ while (fntgfnb (list, Memc[name], maxch) != EOF) {
+ len = strldx (period, Memc[name])
+ len = len + 1
+ if (ctoi (Memc[name], len, version) <= 0)
+ next
+ newversion = max (newversion, version)
+ }
+
+ # Make new output file name.
+ len = strldx (period, template)
+ call strcpy (template, filename, len)
+ call sprintf (filename[len+1], maxch, "%d")
+ call pargi (newversion + 1)
+
+ call fntclsb (list)
+ call sfree (sp)
+end
+
+
+# DP_IVERSION -- Routine to compute the last version number of a given
+# file name template and output the new files name.
+
+procedure dp_iversion (template, filename, maxch)
+
+char template[ARB] # name template
+char filename[ARB] # output name
+int maxch # maximum number of characters
+
+char period
+int newversion, version, len
+pointer sp, list, name
+int fntgfnb() strldx(), ctoi(), fntopnb()
+
+begin
+ # Allocate temporary space
+ call smark (sp)
+ call salloc (name, maxch, TY_CHAR)
+ period = '.'
+ list = fntopnb (template, NO)
+
+ # Loop over the names in the list searchng for the highest version.
+ newversion = 0
+ while (fntgfnb (list, Memc[name], maxch) != EOF) {
+ len = strldx (period, Memc[name])
+ len = len + 1
+ if (ctoi (Memc[name], len, version) <= 0)
+ next
+ newversion = max (newversion, version)
+ }
+
+ # Make new output file name.
+ len = strldx (period, template)
+ call strcpy (template, filename, len)
+ call sprintf (filename[len+1], maxch, "%d")
+ call pargi (newversion)
+
+ call fntclsb (list)
+ call sfree (sp)
+end
+
+
+# DP_FROOT -- Fetch the file name minus the directory specification,
+
+procedure dp_froot (filename, root, maxch)
+
+char filename[ARB] # input file name
+char root[ARB] # output root file name
+int maxch # maximum number of characters
+
+pointer sp, str
+int nchars
+int fnldir()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_PATHNAME, TY_CHAR)
+
+ nchars = fnldir (filename, Memc[str], SZ_PATHNAME)
+ call strcpy (filename[nchars+1], root, maxch)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/daolib/dpotime.x b/noao/digiphot/daophot/daolib/dpotime.x
new file mode 100644
index 00000000..0c8a7925
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpotime.x
@@ -0,0 +1,51 @@
+include <imhdr.h>
+include "../lib/daophotdef.h"
+
+# DP_OTIME -- Read the epoch of the observation from the image header.
+
+procedure dp_otime (im, dao)
+
+pointer im # pointer to IRAF image
+pointer dao # pointer to the daophot structure
+
+char timechar
+int index
+pointer sp, key, otime
+bool streq()
+int strldx()
+
+begin
+ call smark (sp)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ call salloc (otime, SZ_FNAME, TY_CHAR)
+
+ call dp_stats (dao, OBSTIME, Memc[key], SZ_FNAME)
+ Memc[otime] = EOS
+ if (Memc[key] == EOS)
+ call dp_stats (dao, OTIME, Memc[otime], SZ_FNAME)
+ else {
+ iferr {
+ call imgstr (im, Memc[key], Memc[otime], SZ_FNAME)
+ } then {
+ call dp_stats (dao, OTIME, Memc[otime], SZ_FNAME)
+ call eprintf ("Warning: Image %s Keyword: %s not found\n")
+ call pargstr (IM_HDRFILE(im))
+ call pargstr (Memc[key])
+ }
+ }
+ if (Memc[otime] == EOS) {
+ call dp_sets (dao, OTIME, "INDEF")
+ } else if (streq ("DATE-OBS", Memc[key]) || streq ("date-obs",
+ Memc[key])) {
+ timechar = 'T'
+ index = strldx (timechar, Memc[otime])
+ if (index > 0)
+ call dp_sets (dao, OTIME, Memc[otime+index])
+ else
+ call dp_sets (dao, OTIME, "INDEF")
+ } else {
+ call dp_sets (dao, OTIME, Memc[otime])
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/daolib/dppadu.x b/noao/digiphot/daophot/daolib/dppadu.x
new file mode 100644
index 00000000..b1ca7c25
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dppadu.x
@@ -0,0 +1,36 @@
+include <imhdr.h>
+include "../lib/daophotdef.h"
+
+# DP_PADU -- Read the gain value from the image header.
+
+procedure dp_padu (im, dao)
+
+pointer im # pointer to IRAF image
+pointer dao # pointer to the daophot structure
+
+pointer sp, key
+real padu
+real imgetr(), dp_statr()
+
+begin
+ call smark (sp)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ call dp_stats (dao, CCDGAIN, Memc[key], SZ_FNAME)
+ if (Memc[key] == EOS)
+ padu = dp_statr (dao, PHOTADU)
+ else {
+ iferr {
+ padu = imgetr (im, Memc[key])
+ } then {
+ padu = dp_statr (dao, PHOTADU)
+ call eprintf ("Warning: Image %s Keyword %s not found.\n")
+ call pargstr (IM_HDRFILE(im))
+ call pargstr (Memc[key])
+ }
+ }
+ if (IS_INDEFR(padu) || padu <= 0.0)
+ call dp_setr (dao, PHOTADU, 1.0)
+ else
+ call dp_setr (dao, PHOTADU, padu)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/daolib/dppcache.x b/noao/digiphot/daophot/daolib/dppcache.x
new file mode 100644
index 00000000..81ca7a3d
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dppcache.x
@@ -0,0 +1,83 @@
+include <imhdr.h>
+include <imset.h>
+
+# DP_MEMSTAT -- Figure out if there is enough memory to cache the image
+# pixels. If it is necessary to request more memory and the memory is
+# avalilable return YES otherwise return NO.
+
+int procedure dp_memstat (cache, req_size, old_size)
+
+int cache #I cache memory ?
+int req_size #I the requested working set size in chars
+int old_size #O the original working set size in chars
+
+int cur_size, max_size
+int begmem()
+
+begin
+ # Find the default working set size.
+ cur_size = begmem (0, old_size, max_size)
+
+ # If cacheing is disabled return NO regardless of the working set size.
+ if (cache == NO)
+ return (NO)
+
+ # If the requested working set size is less than the current working
+ # set size return YES.
+ if (req_size <= cur_size)
+ return (YES)
+
+ # Reset the current working set size.
+ cur_size = begmem (req_size, old_size, max_size)
+ if (req_size <= cur_size) {
+ return (YES)
+ } else {
+ return (NO)
+ }
+end
+
+
+# DP_PCACHE -- Cache the image pixels im memory by resetting the default image
+# buffer size. If req_size is INDEF the size of the image is used to determine
+# the size of the image i/o buffers.
+
+procedure dp_pcache (im, req_size, buf_size)
+
+pointer im #I the input image point
+int req_size #I the requested working set size in chars
+int buf_size #O the new image buffer size
+
+int def_size, new_imbufsize
+int sizeof(), imstati()
+
+begin
+ # Find the default buffer size.
+ def_size = imstati (im, IM_BUFSIZE)
+
+ # Return if the image is not 2-dimensional.
+ if (IM_NDIM(im) != 2) {
+ buf_size = def_size
+ return
+ }
+
+ # Compute the new required image i/o buffer size in chars.
+ if (IS_INDEFI(req_size)) {
+ new_imbufsize = IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ } else {
+ new_imbufsize = req_size
+ }
+
+ # If the default image i/o buffer size is already bigger than
+ # the requested size do nothing.
+ if (def_size >= new_imbufsize) {
+ buf_size = def_size
+ return
+ }
+
+ # Reset the image i/o buffer.
+ call imseti (im, IM_BUFSIZE, new_imbufsize)
+ call imseti (im, IM_BUFFRAC, 0)
+ buf_size = new_imbufsize
+ return
+end
diff --git a/noao/digiphot/daophot/daolib/dpppars.x b/noao/digiphot/daophot/daolib/dpppars.x
new file mode 100644
index 00000000..e1c86f58
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpppars.x
@@ -0,0 +1,94 @@
+include "../lib/daophotdef.h"
+
+# DP_PPPARS -- Store the daophot package parameters in the pset files.
+
+procedure dp_pppars (dao)
+
+pointer dao # pointer to daophot structure
+
+pointer sp, str, fstr, dap
+bool itob()
+int dp_stati(), strlen()
+pointer clopset()
+real dp_statr()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+ call salloc (fstr, SZ_FNAME, TY_CHAR)
+
+ # Set the package parameter text.
+ call clputb ("text", itob (dp_stati (dao, TEXT)))
+
+ # Get and set the datapars parameter sets.
+ dap = clopset ("datapars")
+
+ # Store the data dependent parameters.
+ call clppsetr (dap, "scale", dp_statr (dao, SCALE))
+ call clppsetr (dap, "fwhmpsf", dp_statr (dao, SFWHMPSF))
+ call clppsetr (dap, "datamin", dp_statr (dao, MINGDATA))
+ call clppsetr (dap, "datamax", dp_statr (dao, MAXGDATA))
+
+ # Store the noise parameters.
+ call dp_stats (dao, CCDGAIN, Memc[str], SZ_FNAME)
+ call clppset (dap, "gain", Memc[str])
+ call clppsetr (dap, "epadu", dp_statr (dao, PHOTADU))
+ call dp_stats (dao, CCDREAD, Memc[str], SZ_FNAME)
+ call clppset (dap, "ccdread", Memc[str])
+ call clppsetr (dap, "readnoise", dp_statr (dao, READNOISE))
+
+ # Store the observing parameters.
+ call dp_stats (dao, EXPTIME, Memc[str], SZ_FNAME)
+ call clppset (dap, "exposure", Memc[str])
+ call clppsetr (dap, "itime", dp_statr (dao, ITIME))
+ call dp_stats (dao, AIRMASS, Memc[str], SZ_FNAME)
+ call clppset (dap, "airmass", Memc[str])
+ call clppsetr (dap, "xairmass", dp_statr (dao, XAIRMASS))
+ call dp_stats (dao, FILTER, Memc[str], SZ_FNAME)
+ call clppset (dap, "filter", Memc[str])
+ call dp_stats (dao, IFILTER, Memc[str], SZ_FNAME)
+ call clppset (dap, "ifilter", Memc[str])
+ call dp_stats (dao, OBSTIME, Memc[str], SZ_FNAME)
+ call clppset (dap, "obstime", Memc[str])
+ call dp_stats (dao, OTIME, Memc[str], SZ_FNAME)
+ call clppset (dap, "otime", Memc[str])
+
+ # Close the datapars parameter set.
+ call clcpset (dap)
+
+ # Open the daopars parameter set.
+ dap = clopset ("daopars")
+
+ # Store the psf function parameters.
+ call dp_stats (dao, FUNCLIST, Memc[fstr], SZ_FNAME)
+ call strcpy (Memc[fstr+1], Memc[str], strlen(Memc[fstr+1]) - 1)
+ call clppset (dap, "function", Memc[str])
+ call clppseti (dap, "varorder", dp_stati (dao, VARORDER))
+ #call clppsetb (dap, "fexpand", itob (dp_stati (dao, FEXPAND)))
+ call clppseti (dap, "nclean", dp_stati (dao, NCLEAN))
+ call clppsetb (dap, "saturated", itob (dp_stati (dao, SATURATED)))
+ call clppsetr (dap, "psfrad", dp_statr (dao, SPSFRAD))
+ call clppsetr (dap, "matchrad", dp_statr (dao, SMATCHRAD))
+
+ # Store the fitting algorithm parameters.
+ call clppsetr (dap, "fitrad", dp_statr (dao, SFITRAD))
+ call clppsetr (dap, "sannulus", dp_statr (dao, SANNULUS))
+ call clppsetr (dap, "wsannulus", dp_statr (dao, SDANNULUS))
+ call clppsetr (dap, "critsnratio", dp_statr (dao, CRITSNRATIO))
+ call clppseti (dap, "maxiter", dp_stati (dao, MAXITER))
+ call clppseti (dap, "maxgroup", dp_stati (dao, MAXGROUP))
+ call clppseti (dap, "maxnstar", dp_stati (dao, MAXNSTAR))
+ call clppsetb (dap, "recenter", itob (dp_stati (dao, RECENTER)))
+ call clppsetb (dap, "fitsky", itob (dp_stati (dao, FITSKY)))
+ call clppsetb (dap, "groupsky", itob (dp_stati (dao, GROUPSKY)))
+ call clppsetr (dap, "flaterr", dp_statr (dao, FLATERR))
+ call clppsetr (dap, "proferr", dp_statr (dao, PROFERR))
+ call clppsetr (dap, "cliprange", dp_statr (dao, CLIPRANGE))
+ call clppseti (dap, "clipexp", dp_stati (dao, CLIPEXP))
+ call clppsetr (dap, "mergerad", dp_statr (dao, SMERGERAD))
+
+ # Close the daopars parameter set.
+ call clcpset (dap)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/daolib/dprdnoise.x b/noao/digiphot/daophot/daolib/dprdnoise.x
new file mode 100644
index 00000000..9e4baa3c
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dprdnoise.x
@@ -0,0 +1,36 @@
+include <imhdr.h>
+include "../lib/daophotdef.h"
+
+# DP_RDNOISE - Read the readout noise value from the image header.
+
+procedure dp_rdnoise (im, dao)
+
+pointer im # pointer to IRAF image
+pointer dao # pointer to the daophot structure
+
+pointer sp, key
+real rdnoise
+real imgetr(), dp_statr()
+
+begin
+ call smark (sp)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ call dp_stats (dao, CCDREAD, Memc[key], SZ_FNAME)
+ if (Memc[key] == EOS)
+ rdnoise = dp_statr (dao, READNOISE)
+ else {
+ iferr {
+ rdnoise = imgetr (im, Memc[key])
+ } then {
+ rdnoise = dp_statr (dao, READNOISE)
+ call eprintf ("Warning: Image %s Keyword %s not found.\n")
+ call pargstr (IM_HDRFILE(im))
+ call pargstr (Memc[key])
+ }
+ }
+ if (IS_INDEFR(rdnoise) || rdnoise <= 0.0)
+ call dp_setr (dao, READNOISE, 0.0)
+ else
+ call dp_setr (dao, READNOISE, rdnoise)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/daolib/dpreadpsf.x b/noao/digiphot/daophot/daolib/dpreadpsf.x
new file mode 100644
index 00000000..77aa0b74
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpreadpsf.x
@@ -0,0 +1,138 @@
+include <error.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+
+# DP_READPSF -- Read in the PSF from the specified image.
+
+procedure dp_readpsf (dao, im)
+
+pointer dao # pointer to the DAOPHOT Structure
+pointer im # image descriptor
+
+int i, ival, npsfstars
+pointer sp, str, v, psffit, psflut, buf
+real scale, rval
+bool imgetb(), streq()
+int imgeti(), imgnlr(), btoi()
+real imgetr()
+errchk imgetr(), imgeti()
+
+begin
+ # Allocate working memory.
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+ call salloc (v, IM_MAXDIM, TY_LONG)
+
+ # Set up needed daophot pointers.
+ psffit = DP_PSFFIT(dao)
+
+ # Read in the function parameters.
+ call imgstr (im, "FUNCTION", Memc[str], SZ_FNAME)
+ if (streq (Memc[str], "gauss")) {
+ DP_PSFUNCTION(psffit) = FCTN_GAUSS
+ call strcpy ("gauss", DP_FUNCTION(dao), SZ_FNAME)
+ } else if (streq (Memc[str], "moffat25")) {
+ DP_PSFUNCTION(psffit) = FCTN_MOFFAT25
+ call strcpy ("moffat25", DP_FUNCTION(dao), SZ_FNAME)
+ } else if (streq (Memc[str], "penny1")) {
+ DP_PSFUNCTION(psffit) = FCTN_PENNY1
+ call strcpy ("penny1", DP_FUNCTION(dao), SZ_FNAME)
+ } else if (streq (Memc[str], "moffat15")) {
+ DP_PSFUNCTION(psffit) = FCTN_MOFFAT15
+ call strcpy ("moffat15", DP_FUNCTION(dao), SZ_FNAME)
+ } else if (streq (Memc[str], "penny2")) {
+ DP_PSFUNCTION(psffit) = FCTN_PENNY2
+ call strcpy ("penny2", DP_FUNCTION(dao), SZ_FNAME)
+ } else if (streq (Memc[str], "lorentz")) {
+ DP_PSFUNCTION(psffit) = FCTN_LORENTZ
+ call strcpy ("lorentz", DP_FUNCTION(dao), SZ_FNAME)
+ } else
+ call error (0, "Unknown PSF function in PSF image\n")
+
+ # Read in the position and brightness parameters.
+ DP_PSFX (psffit) = imgetr (im, "PSFX")
+ DP_PSFY (psffit) = imgetr (im, "PSFY")
+ DP_PSFHEIGHT(psffit) = imgetr (im, "PSFHEIGHT")
+ DP_PSFMAG (psffit) = imgetr (im, "PSFMAG")
+
+ DP_PSFNPARS(psffit) = imgeti (im, "NPARS")
+ do i = 1, DP_PSFNPARS(psffit) {
+ call sprintf (Memc[str], SZ_FNAME, "PAR%d")
+ call pargi (i)
+ Memr[DP_PSFPARS(psffit)+i-1] = imgetr (im, Memc[str])
+ }
+
+ # Get the psfradius with which the psf was made. Make sure the
+ # psf radius requested by the user is less than or equal to the
+ # stored psf radius.
+
+ iferr {
+ scale = imgetr (im, "SCALE")
+ } then {
+ DP_PSFRAD(dao) = min (DP_RPSFRAD(dao) / DP_SCALE(dao),
+ imgetr (im, "PSFRAD"))
+ DP_SPSFRAD(dao) = DP_SCALE(dao) * DP_PSFRAD(dao)
+ } else {
+ DP_PSFRAD(dao) = min (DP_RPSFRAD(dao) / DP_SCALE(dao),
+ imgetr (im, "PSFRAD") / scale)
+ DP_SPSFRAD(dao) = DP_SCALE(dao) * DP_PSFRAD(dao)
+ }
+
+ # Get the lookup table(s) parameters.
+ DP_VARORDER(dao) = imgeti (im, "VARORDER")
+ switch (DP_VARORDER(dao)) {
+ case -1:
+ DP_NVLTABLE(psffit) = 0
+ case 0:
+ DP_NVLTABLE(psffit) = 1
+ case 1:
+ DP_NVLTABLE(psffit) = 3
+ case 2:
+ DP_NVLTABLE(psffit) = 6
+ }
+ DP_FEXPAND(dao) = btoi (imgetb (im, "FEXPAND"))
+ if (DP_FEXPAND(dao) == NO)
+ DP_NFEXTABLE(psffit) = 0
+ else
+ DP_NFEXTABLE(psffit) = 5
+
+ # Read in the lookup table(s).
+ if ((DP_NVLTABLE(psffit) + DP_NFEXTABLE(psffit)) <= 0) {
+ DP_PSFSIZE(psffit) = 0
+ } else {
+ DP_PSFSIZE(psffit) = IM_LEN(im,1)
+ call realloc (DP_PSFLUT(psffit), DP_PSFSIZE(psffit) *
+ DP_PSFSIZE(psffit) * IM_LEN(im,3), TY_REAL)
+ psflut = DP_PSFLUT (psffit)
+ call amovkl (long(1), Meml[v], IM_MAXDIM)
+ while (imgnlr (im, buf, Meml[v]) != EOF) {
+ call amovr (Memr[buf], Memr[psflut], DP_PSFSIZE(psffit))
+ psflut = psflut + DP_PSFSIZE(psffit)
+ }
+ }
+
+ # Check that the complete header can be read.
+ iferr {
+ npsfstars = imgeti (im, "NPSFSTAR")
+ call sprintf (Memc[str], SZ_FNAME, "ID%d")
+ call pargi (npsfstars)
+ ival = imgeti (im, Memc[str])
+ call sprintf (Memc[str], SZ_FNAME, "X%d")
+ call pargi (npsfstars)
+ rval = imgetr (im, Memc[str])
+ call sprintf (Memc[str], SZ_FNAME, "Y%d")
+ call pargi (npsfstars)
+ rval = imgetr (im, Memc[str])
+ call sprintf (Memc[str], SZ_FNAME, "MAG%d")
+ call pargi (npsfstars)
+ rval = imgetr (im, Memc[str])
+ } then {
+ call eprintf ("PSF image header is too long to be read in.\n")
+ call eprintf (
+ "Reset min_lenusearea environment variable and try again.")
+ call erract (EA_ERROR)
+ }
+
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/daolib/dprmwhite.x b/noao/digiphot/daophot/daolib/dprmwhite.x
new file mode 100644
index 00000000..9c61969c
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dprmwhite.x
@@ -0,0 +1,22 @@
+include <ctype.h>
+
+# DP_RMWHITE -- Remove whitespace from a string.
+
+procedure dp_rmwhite (instr, outstr, maxch)
+
+char instr[ARB] # the input string
+char outstr[ARB] # the output string, may be the same as instr
+int maxch # maximum number of characters in outstr
+
+int ip, op
+
+begin
+ op = 1
+ for (ip = 1; (instr[ip] != EOS) && (op <= maxch); ip = ip + 1) {
+ if (IS_WHITE(instr[ip]))
+ next
+ outstr[op] = instr[ip]
+ op = op + 1
+ }
+ outstr[op] = EOS
+end
diff --git a/noao/digiphot/daophot/daolib/dpset.x b/noao/digiphot/daophot/daolib/dpset.x
new file mode 100644
index 00000000..ca5b1ad4
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpset.x
@@ -0,0 +1,181 @@
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+
+# DP_SETS -- Set a daophot string parameter.
+
+procedure dp_sets (dao, param, str)
+
+pointer dao # pointer to daophot structure
+int param # parameter
+char str[ARB] # string value
+
+begin
+ switch (param) {
+ case INIMAGE:
+ call strcpy (str, DP_INIMAGE(dao), SZ_FNAME)
+ case INPHOTFILE:
+ call strcpy (str, DP_INPHOTFILE(dao), SZ_FNAME)
+ case COORDS:
+ call strcpy (str, DP_COORDS(dao), SZ_FNAME)
+ case PSFIMAGE:
+ call strcpy (str, DP_PSFIMAGE(dao), SZ_FNAME)
+ case OUTPHOTFILE:
+ call strcpy (str, DP_OUTPHOTFILE(dao), SZ_FNAME)
+ case OUTREJFILE:
+ call strcpy (str, DP_OUTREJFILE(dao), SZ_FNAME)
+ case OUTIMAGE:
+ call strcpy (str, DP_OUTIMAGE(dao), SZ_FNAME)
+ case IFILTER:
+ call strcpy (str, DP_IFILTER(dao), SZ_FNAME)
+ case OTIME:
+ call strcpy (str, DP_OTIME(dao), SZ_FNAME)
+ case CCDGAIN:
+ call strcpy (str, DP_CCDGAIN(dao), SZ_FNAME)
+ case CCDREAD:
+ call strcpy (str, DP_CCDREAD(dao), SZ_FNAME)
+ case EXPTIME:
+ call strcpy (str, DP_EXPTIME(dao), SZ_FNAME)
+ case OBSTIME:
+ call strcpy (str, DP_OBSTIME(dao), SZ_FNAME)
+ case AIRMASS:
+ call strcpy (str, DP_AIRMASS(dao), SZ_FNAME)
+ case FILTER:
+ call strcpy (str, DP_FILTER(dao), SZ_FNAME)
+ case FUNCTION:
+ call strcpy (str, DP_FUNCTION(dao), SZ_FNAME)
+ case FUNCLIST:
+ call strcpy (str, DP_FUNCLIST(dao), SZ_FNAME)
+ default:
+ call error (0, "DP_SETS: Unknown daophot string parameter")
+ }
+end
+
+
+# DP_SETI -- Set a daophot integer parameter.
+
+procedure dp_seti (dao, param, ival)
+
+pointer dao # pointer to daophot structure
+int param # parameter
+int ival # integer value
+
+pointer apsel
+
+begin
+ apsel = DP_APSEL(dao)
+
+ switch (param) {
+ case MW:
+ DP_MW(dao) = ival
+ case WCSIN:
+ DP_WCSIN(dao) = ival
+ case WCSOUT:
+ DP_WCSOUT(dao) = ival
+ case WCSPSF:
+ DP_WCSPSF(dao) = ival
+ case CTIN:
+ DP_CTIN(dao) = ival
+ case CTOUT:
+ DP_CTOUT(dao) = ival
+ case CTPSF:
+ DP_CTPSF(dao) = ival
+ case MAXITER:
+ DP_MAXITER(dao) = ival
+ case VERBOSE:
+ DP_VERBOSE(dao) = ival
+ case TEXT:
+ DP_TEXT(dao) = ival
+ case MAXNSTAR:
+ DP_MAXNSTAR(dao) = ival
+ case MAXGROUP:
+ DP_MAXGROUP(dao) = ival
+ case CLIPEXP:
+ DP_CLIPEXP(dao) = ival
+ case RECENTER:
+ DP_RECENTER(dao) = ival
+ case FITSKY:
+ DP_FITSKY(dao) = ival
+ case GROUPSKY:
+ DP_GROUPSKY(dao) = ival
+ case VARORDER:
+ DP_VARORDER(dao) = ival
+ case FEXPAND:
+ DP_FEXPAND(dao) = ival
+ case SATURATED:
+ DP_SATURATED(dao) = ival
+ case NCLEAN:
+ DP_NCLEAN(dao) = ival
+ case APNUM:
+ DP_APNUM(apsel) = ival
+ default:
+ call error (0, "DP_SETI: Unknown integer daophot parameter")
+ }
+end
+
+
+# DP_SETR -- Set a real daophot parameter.
+
+procedure dp_setr (dao, param, rval)
+
+pointer dao # pointer to daophot structure
+int param # parameter
+real rval # real value
+
+begin
+ switch (param) {
+ case SCALE:
+ DP_SCALE(dao) = rval
+ case SFWHMPSF:
+ DP_SFWHMPSF(dao) = rval
+ case FWHMPSF:
+ DP_FWHMPSF(dao) = rval
+ case MAXGDATA:
+ DP_MAXGDATA(dao) = rval
+ case MINGDATA:
+ DP_MINGDATA(dao) = rval
+ case READNOISE:
+ DP_READNOISE(dao) = rval
+ case PHOTADU:
+ DP_PHOTADU(dao) = rval
+ case RPSFRAD:
+ DP_RPSFRAD(dao) = rval
+ case SPSFRAD:
+ DP_SPSFRAD(dao) = rval
+ case PSFRAD:
+ DP_PSFRAD(dao) = rval
+ case SFITRAD:
+ DP_SFITRAD(dao) = rval
+ case FITRAD:
+ DP_FITRAD(dao) = rval
+ case SMATCHRAD:
+ DP_SMATCHRAD(dao) = rval
+ case MATCHRAD:
+ DP_MATCHRAD(dao) = rval
+ case SANNULUS:
+ DP_SANNULUS(dao) = rval
+ case ANNULUS:
+ DP_ANNULUS(dao) = rval
+ case SDANNULUS:
+ DP_SDANNULUS(dao) = rval
+ case DANNULUS:
+ DP_DANNULUS(dao) = rval
+ case CRITSNRATIO:
+ DP_CRITSNRATIO(dao) = rval
+ case CLIPRANGE:
+ DP_CLIPRANGE(dao) = rval
+ case XAIRMASS:
+ DP_XAIRMASS(dao) = rval
+ case ITIME:
+ DP_ITIME(dao) = rval
+ case FLATERR:
+ DP_FLATERR(dao) = rval
+ case PROFERR:
+ DP_PROFERR(dao) = rval
+ case SMERGERAD:
+ DP_SMERGERAD(dao) = rval
+ case MERGERAD:
+ DP_MERGERAD(dao) = rval
+ default:
+ call error (0, "DP_SETR: Unknown real daophot parameter")
+ }
+end
diff --git a/noao/digiphot/daophot/daolib/dpstat.x b/noao/digiphot/daophot/daolib/dpstat.x
new file mode 100644
index 00000000..45bcf82e
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpstat.x
@@ -0,0 +1,180 @@
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+
+# DP_STATS -- Fetch a daophot string parameter.
+
+procedure dp_stats (dao, param, str, maxch)
+
+pointer dao # pointer to daophot structure
+int param # parameter
+char str[ARB] # string value
+int maxch # maximum number of characters
+
+begin
+ switch (param) {
+ case INIMAGE:
+ call strcpy (DP_INIMAGE(dao), str, maxch)
+ case INPHOTFILE:
+ call strcpy (DP_INPHOTFILE(dao), str, maxch)
+ case COORDS:
+ call strcpy (DP_COORDS(dao), str, maxch)
+ case PSFIMAGE:
+ call strcpy (DP_PSFIMAGE(dao), str, maxch)
+ case OUTPHOTFILE:
+ call strcpy (DP_OUTPHOTFILE(dao), str, maxch)
+ case OUTIMAGE:
+ call strcpy (DP_OUTIMAGE(dao), str, maxch)
+ case OUTREJFILE:
+ call strcpy (DP_OUTREJFILE(dao), str, maxch)
+ case IFILTER:
+ call strcpy (DP_IFILTER(dao), str, maxch)
+ case OTIME:
+ call strcpy (DP_OTIME(dao), str, maxch)
+ case CCDGAIN:
+ call strcpy (DP_CCDGAIN(dao), str, maxch)
+ case CCDREAD:
+ call strcpy (DP_CCDREAD(dao), str, maxch)
+ case EXPTIME:
+ call strcpy (DP_EXPTIME(dao), str, maxch)
+ case OBSTIME:
+ call strcpy (DP_OBSTIME(dao), str, maxch)
+ case FILTER:
+ call strcpy (DP_FILTER(dao), str, maxch)
+ case AIRMASS:
+ call strcpy (DP_AIRMASS(dao), str, maxch)
+ case FUNCTION:
+ call strcpy (DP_FUNCTION(dao), str, maxch)
+ case FUNCLIST:
+ call strcpy (DP_FUNCLIST(dao), str, maxch)
+ default:
+ call error (0, "DP_STATS: Unknown daophot string parameter")
+ }
+end
+
+
+# DP_STATI -- Fetch a daophot integer parameter.
+
+int procedure dp_stati (dao, param)
+
+pointer dao # pointer to daophot structure
+int param # parameter
+
+pointer apsel
+
+begin
+ apsel = DP_APSEL(dao)
+
+ switch (param) {
+ case MW:
+ return (DP_MW(dao))
+ case WCSIN:
+ return (DP_WCSIN(dao))
+ case WCSOUT:
+ return (DP_WCSOUT(dao))
+ case WCSPSF:
+ return (DP_WCSPSF(dao))
+ case CTIN:
+ return (DP_CTIN(dao))
+ case CTOUT:
+ return (DP_CTOUT(dao))
+ case CTPSF:
+ return (DP_CTPSF(dao))
+ case MAXITER:
+ return (DP_MAXITER(dao))
+ case VERBOSE:
+ return (DP_VERBOSE(dao))
+ case TEXT:
+ return (DP_TEXT(dao))
+ case MAXNSTAR:
+ return (DP_MAXNSTAR(dao))
+ case MAXGROUP:
+ return (DP_MAXGROUP(dao))
+ case CLIPEXP:
+ return (DP_CLIPEXP(dao))
+ case RECENTER:
+ return (DP_RECENTER(dao))
+ case FITSKY:
+ return (DP_FITSKY(dao))
+ case GROUPSKY:
+ return (DP_GROUPSKY(dao))
+ case VARORDER:
+ return (DP_VARORDER(dao))
+ case FEXPAND:
+ return (DP_FEXPAND(dao))
+ case SATURATED:
+ return (DP_SATURATED(dao))
+ case NCLEAN:
+ return (DP_NCLEAN(dao))
+ case APNUM:
+ return (DP_APNUM(apsel))
+ default:
+ call error (0, "DP_STATI: Unknown integer daophot parameter")
+ }
+end
+
+
+# DP_STATR -- Fetch a daophot real parameter.
+
+real procedure dp_statr (dao, param)
+
+pointer dao # pointer to daophot structure
+int param # parameter
+
+begin
+ switch (param) {
+ case SCALE:
+ return (DP_SCALE(dao))
+ case FWHMPSF:
+ return (DP_FWHMPSF(dao))
+ case SFWHMPSF:
+ return (DP_SFWHMPSF(dao))
+ case MAXGDATA:
+ return (DP_MAXGDATA(dao))
+ case MINGDATA:
+ return (DP_MINGDATA(dao))
+ case READNOISE:
+ return (DP_READNOISE(dao))
+ case PHOTADU:
+ return (DP_PHOTADU(dao))
+ case RPSFRAD:
+ return (DP_RPSFRAD(dao))
+ case SPSFRAD:
+ return (DP_SPSFRAD(dao))
+ case PSFRAD:
+ return (DP_PSFRAD(dao))
+ case SFITRAD:
+ return (DP_SFITRAD(dao))
+ case FITRAD:
+ return (DP_FITRAD(dao))
+ case SMATCHRAD:
+ return (DP_SMATCHRAD(dao))
+ case MATCHRAD:
+ return (DP_MATCHRAD(dao))
+ case SANNULUS:
+ return (DP_SANNULUS(dao))
+ case ANNULUS:
+ return (DP_ANNULUS(dao))
+ case SDANNULUS:
+ return (DP_SDANNULUS(dao))
+ case DANNULUS:
+ return (DP_DANNULUS(dao))
+ case CRITSNRATIO:
+ return (DP_CRITSNRATIO(dao))
+ case CLIPRANGE:
+ return (DP_CLIPRANGE(dao))
+ case XAIRMASS:
+ return (DP_XAIRMASS(dao))
+ case ITIME:
+ return (DP_ITIME(dao))
+ case FLATERR:
+ return (DP_FLATERR(dao))
+ case PROFERR:
+ return (DP_PROFERR(dao))
+ case SMERGERAD:
+ return (DP_SMERGERAD(dao))
+ case MERGERAD:
+ return (DP_MERGERAD(dao))
+ default:
+ call error (0, "DP_STATR: Unknown real daophot parameter")
+ }
+end
diff --git a/noao/digiphot/daophot/daolib/dpverify.x b/noao/digiphot/daophot/daolib/dpverify.x
new file mode 100644
index 00000000..dcc721ad
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpverify.x
@@ -0,0 +1,563 @@
+include "../lib/daophotdef.h"
+
+# DP_VFUNCTION -- Verify the analytic psf function.
+
+procedure dp_vfunction (dao)
+
+pointer dao # pointer to the daophot structure.
+
+int len
+pointer sp, str, pstr
+int scan(), nscan(), strlen(), dp_fctdecode(), dp_strwrd()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+ call salloc (pstr, SZ_FNAME, TY_CHAR)
+
+ # Print the current function list.
+ len = strlen (DP_FUNCLIST(dao))
+ call strcpy (DP_FUNCLIST(dao), Memc[pstr], len - 1)
+ call printf ("Analytic psf function(s) (%s): ")
+ call pargstr (Memc[pstr+1])
+ call flush (STDOUT)
+
+ # Confirm the PSF function type.
+ if (scan() == EOF)
+ ;
+ else {
+ call gargstr (Memc[str], SZ_FNAME)
+ if (nscan () != 1)
+ ;
+ else if (dp_fctdecode (Memc[str], Memc[pstr], SZ_FNAME) <= 0)
+ ;
+ else
+ call strcpy (Memc[pstr], DP_FUNCLIST(dao), SZ_FNAME)
+ }
+
+ # Print the confirmed function list.
+ len = strlen (DP_FUNCLIST(dao))
+ call strcpy (DP_FUNCLIST(dao), Memc[pstr], len - 1)
+ call printf ( "\tAnalytic psf function(s): %d\n")
+ call pargstr (Memc[pstr+1])
+
+ # Set the function type.
+ if (dp_strwrd (1, Memc[str], SZ_FNAME, DP_FUNCLIST(dao)) <= 0)
+ call strcpy ("gauss", DP_FUNCTION(dao), SZ_FNAME)
+ else
+ call strcpy (Memc[str], DP_FUNCTION(dao), SZ_FNAME)
+
+ call sfree (sp)
+end
+
+
+# DP_VVARORDER -- Verify the order of variability of the psf function.
+
+procedure dp_vvarorder (dao)
+
+pointer dao # pointer to the daophot structure.
+
+int varorder
+int scan(), nscan()
+
+begin
+ # Confirm that the psf is variable.
+ call printf ("Order of variable psf (%d): ")
+ call pargi (DP_VARORDER(dao))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ varorder = DP_VARORDER(dao)
+ else {
+ call gargi (varorder)
+ if (nscan () != 1)
+ varorder = DP_VARORDER(dao)
+ else if (varorder < -1 || varorder > 2)
+ varorder = DP_VARORDER(dao)
+ }
+ DP_VARORDER(dao) = varorder
+ call printf ( "\tOrder of variable psf: %d\n")
+ call pargi (varorder)
+end
+
+
+# DP_VFEXPAND -- Verify whether or not to expand the analytics function.
+
+procedure dp_vfexpand (dao)
+
+pointer dao # pointer to the daophot structure.
+
+bool fexpand
+bool itob()
+int scan(), nscan(), btoi()
+
+begin
+ # Confirm whether of not to expand the analytic function.
+ call printf ("Expand the analytic function (%b): ")
+ call pargb (itob (DP_FEXPAND(dao)))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ fexpand = itob (DP_FEXPAND(dao))
+ else {
+ call gargb (fexpand)
+ if (nscan () != 1)
+ fexpand = itob (DP_FEXPAND(dao))
+ }
+ DP_FEXPAND(dao) = btoi (fexpand)
+ call printf ( "\tExpand analytic fucntion: %b\n")
+ call pargb (fexpand)
+end
+
+
+# DP_VSATURATED -- Verify whether or not to use saturated stars in the
+# psf computation.
+
+procedure dp_vsaturated (dao)
+
+pointer dao # pointer to the daophot structure.
+
+bool saturated
+bool itob()
+int scan(), nscan(), btoi()
+
+begin
+ # Confirm whether of not to use saturated psf stars.
+ call printf ("Use saturated psf stars (%b): ")
+ call pargb (itob (DP_SATURATED(dao)))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ saturated = itob (DP_SATURATED(dao))
+ else {
+ call gargb (saturated)
+ if (nscan () != 1)
+ saturated = itob (DP_SATURATED(dao))
+ }
+ DP_SATURATED(dao) = btoi (saturated)
+ call printf ( "\tUse saturated psf stars: %b\n")
+ call pargb (saturated)
+end
+
+
+# DP_VFWHMPSF -- Confirm the fwhm of the psf.
+
+procedure dp_vfwhmpsf (dao)
+
+pointer dao # pointer to the daophot structure
+
+real sfwhmpsf, fwhmpsf
+int scan(), nscan()
+
+begin
+ # Confirm the psf radius.
+ call printf ( "Fwhm of psf in scale units (%g): ")
+ call pargr (DP_SFWHMPSF(dao))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ sfwhmpsf = DP_SFWHMPSF(dao)
+ else {
+ call gargr (sfwhmpsf)
+ if (nscan () != 1)
+ sfwhmpsf = DP_SFWHMPSF(dao)
+ }
+ fwhmpsf = sfwhmpsf / DP_SCALE(dao)
+
+ DP_SFWHMPSF(dao) = sfwhmpsf
+ DP_FWHMPSF(dao) = fwhmpsf
+
+ call printf ( "\tNew fwhm: %g scale units %g pixels\n")
+ call pargr (sfwhmpsf)
+ call pargr (fwhmpsf)
+end
+
+
+# DP_VPSFRAD -- Confirm the psf radius.
+
+procedure dp_vpsfrad (dao)
+
+pointer dao # pointer to the daophot structure
+
+real rpsfrad, psfrad
+int scan(), nscan()
+
+begin
+ # Confirm the psf radius.
+ call printf ( "Psf radius in scale units (%g): ")
+ call pargr (DP_RPSFRAD(dao))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ rpsfrad = DP_RPSFRAD(dao)
+ else {
+ call gargr (rpsfrad)
+ if (nscan () != 1)
+ rpsfrad = DP_RPSFRAD(dao)
+ }
+ psfrad = rpsfrad / DP_SCALE(dao)
+
+ DP_RPSFRAD(dao) = rpsfrad
+ DP_SPSFRAD(dao) = rpsfrad
+ DP_PSFRAD(dao) = psfrad
+
+ call printf ( "\tNew psf radius: %g scale units %g pixels\n")
+ call pargr (rpsfrad)
+ call pargr (psfrad)
+end
+
+
+# DP_VFITRAD -- Confirm the fitting radius.
+
+procedure dp_vfitrad (dao)
+
+pointer dao # pointer to the daophot structures
+
+real sfitrad, fitrad
+int scan(), nscan()
+
+begin
+ # Confirm the fitting radius.
+ call printf ( "Fitting radius in scale units (%g): ")
+ call pargr (DP_SFITRAD(dao))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ sfitrad = DP_SFITRAD(dao)
+ else {
+ call gargr (sfitrad)
+ if (nscan () != 1)
+ sfitrad = DP_SFITRAD(dao)
+ }
+ fitrad = sfitrad / DP_SCALE(dao)
+
+ DP_SFITRAD(dao) = sfitrad
+ DP_FITRAD(dao) = fitrad
+
+ call printf ( "\tNew fitting radius: %g scale units %g pixels\n")
+ call pargr (sfitrad)
+ call pargr (fitrad)
+end
+
+
+# DP_VMATCHRAD -- Confirm the matching radius.
+
+procedure dp_vmatchrad (dao)
+
+pointer dao # pointer to the daophot structure
+
+real smatchrad, matchrad
+int scan(), nscan()
+
+begin
+ # Confirm the matching radius.
+ call printf ( "Matching radius in scale units (%g): ")
+ call pargr (DP_SMATCHRAD(dao))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ smatchrad = DP_SMATCHRAD(dao)
+ else {
+ call gargr (smatchrad)
+ if (nscan () != 1)
+ smatchrad = DP_SMATCHRAD(dao)
+ }
+ matchrad = smatchrad / DP_SCALE(dao)
+
+ DP_SMATCHRAD(dao) = smatchrad
+ DP_MATCHRAD(dao) = matchrad
+
+ call printf ( "\tNew matching radius: %g scale units %g pixels\n")
+ call pargr (smatchrad)
+ call pargr (matchrad)
+end
+
+
+# DP_VMERGERAD -- Confirm the merging radius.
+
+procedure dp_vmergerad (dao)
+
+pointer dao # pointer to the daophot structure
+
+real smergerad, mergerad
+int scan(), nscan()
+
+begin
+ # Confirm the merging radius.
+ call printf ( "Merging radius in scale units (%g): ")
+ call pargr (DP_SMERGERAD(dao))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ smergerad = DP_SMERGERAD(dao)
+ else {
+ call gargr (smergerad)
+ if (nscan () != 1)
+ smergerad = DP_SMERGERAD(dao)
+ }
+ if (IS_INDEFR(smergerad))
+ mergerad = INDEFR
+ else
+ mergerad = smergerad / DP_SCALE(dao)
+
+ DP_SMERGERAD(dao) = smergerad
+ DP_MERGERAD(dao) = mergerad
+
+ call printf ( "\tNew merging radius: %g scale units %g pixels\n")
+ call pargr (smergerad)
+ call pargr (mergerad)
+end
+
+
+# DP_VFITRAD -- Confirm the fitting radius.
+
+
+# DP_VDATAMIN-- Verify the minimum good data value.
+
+procedure dp_vdatamin (dao)
+
+pointer dao # pointer to the daophot structure
+
+real datamin
+int scan(), nscan()
+
+begin
+ # Confirm the threshold parameter.
+ call printf ("Minimum good data value (%g) (CR or value): ")
+ call pargr (DP_MINGDATA(dao))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ datamin = DP_MINGDATA(dao)
+ else {
+ call gargr (datamin)
+ if (nscan () != 1)
+ datamin = DP_MINGDATA(dao)
+ }
+ DP_MINGDATA(dao) = datamin
+
+ call printf ("\tNew minimum good data value: %g counts\n")
+ call pargr (datamin)
+end
+
+
+# DP_VDATAMAX-- Verify the maximum good data value.
+
+procedure dp_vdatamax (dao)
+
+pointer dao # pointer to the daophot structure
+
+real datamax
+int scan(), nscan()
+
+begin
+ # Confirm the threshold parameter.
+ call printf ("Maximum good data value (%g) (CR or value): ")
+ call pargr (DP_MAXGDATA(dao))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ datamax = DP_MAXGDATA(dao)
+ else {
+ call gargr (datamax)
+ if (nscan () != 1)
+ datamax = DP_MAXGDATA(dao)
+ }
+ DP_MAXGDATA(dao) = datamax
+
+ call printf ("\tNew maximum good data value: %g counts\n")
+ call pargr (datamax)
+end
+
+
+# DP_VMAXGROUP -- Verify the maximum group size.
+
+procedure dp_vmaxgroup (dao)
+
+pointer dao # pointer to the daophot strucuture
+
+int maxgroup
+int scan(), nscan()
+
+begin
+ call printf ( "Maximum group size in number of stars (%d): ")
+ call pargi (DP_MAXGROUP(dao))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ maxgroup = DP_MAXGROUP(dao)
+ else {
+ call gargi (maxgroup)
+ if (nscan () != 1)
+ maxgroup = DP_MAXGROUP(dao)
+ }
+ DP_MAXGROUP(dao) = maxgroup
+
+ call printf ( "\tNew maximum group size: %d stars\n")
+ call pargi (maxgroup)
+end
+
+
+# DP_VCRITSNRATIO -- Verify the critical signal-to-noise ratio.
+
+procedure dp_vcritnsratio (dao)
+
+pointer dao # pointer to the daophot structure
+
+real critsnratio
+int scan(), nscan()
+
+begin
+ # Confirm the critical signal-to-noise ratio.
+ call printf ( "Critical S/N ratio in stdevs per pixel (%g): ")
+ call pargr (DP_CRITSNRATIO(dao))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ critsnratio = DP_CRITSNRATIO(dao)
+ else {
+ call gargr (critsnratio)
+ if (nscan () != 1)
+ critsnratio = DP_CRITSNRATIO(dao)
+ }
+ DP_CRITSNRATIO(dao) = critsnratio
+
+ call printf ( "\tNew critical S/N ratio: %g stdevs per pixel\n")
+ call pargr (critsnratio)
+end
+
+
+# DP_VRECENTER -- Verify whether or not to recenter the stars.
+
+procedure dp_vrecenter (dao)
+
+pointer dao # pointer to the daophot structure.
+
+bool recenter
+bool itob()
+int scan(), nscan(), btoi()
+
+begin
+ # Confirm whether of not to recenter the stars.
+ call printf ("Recenter the stars (%b): ")
+ call pargb (itob (DP_RECENTER(dao)))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ recenter = itob (DP_RECENTER(dao))
+ else {
+ call gargb (recenter)
+ if (nscan () != 1)
+ recenter = itob (DP_RECENTER(dao))
+ }
+ DP_RECENTER(dao) = btoi (recenter)
+ call printf ( "\tRecenter the stars: %b\n")
+ call pargb (recenter)
+end
+
+
+# DP_VFITSKY -- Verify whether or not to refit the sky value.
+
+procedure dp_vfitsky (dao)
+
+pointer dao # pointer to the daophot structure.
+
+bool fitsky
+bool itob()
+int scan(), nscan(), btoi()
+
+begin
+ # Confirm whether of not to refit the sky.
+ call printf ("Refit the sky (%b): ")
+ call pargb (itob (DP_FITSKY(dao)))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ fitsky = itob (DP_FITSKY(dao))
+ else {
+ call gargb (fitsky)
+ if (nscan () != 1)
+ fitsky = itob (DP_FITSKY(dao))
+ }
+ DP_FITSKY(dao) = btoi (fitsky)
+ call printf ( "\tRefit the sky: %b\n")
+ call pargb (fitsky)
+end
+
+
+# DP_VGROUPSKY -- Verify whether or not to fit group sky values.
+
+procedure dp_vgroupsky (dao)
+
+pointer dao # pointer to the daophot structure
+
+bool groupsky
+bool itob()
+int scan(), nscan(), btoi()
+
+begin
+ # Confirm whether of not to use group sky values.
+ call printf ("Use group sky values (%b): ")
+ call pargb (itob (DP_GROUPSKY(dao)))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ groupsky = itob (DP_GROUPSKY(dao))
+ else {
+ call gargb (groupsky)
+ if (nscan () != 1)
+ groupsky = itob (DP_GROUPSKY(dao))
+ }
+ DP_GROUPSKY(dao) = btoi (groupsky)
+ call printf ( "\tUse group sky values: %b\n")
+ call pargb (groupsky)
+end
+
+
+# DP_VSANNULUS -- Confirm the inner radius of the sky fitting annulus.
+
+procedure dp_vsannulus (dao)
+
+pointer dao # pointer to the daophot structure
+
+real sannulus, annulus
+int scan(), nscan()
+
+begin
+ # Confirm the inner radius of the sky annulus.
+ call printf ( "Inner radius of sky annulus in scale units (%g): ")
+ call pargr (DP_SANNULUS(dao))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ sannulus = DP_SANNULUS(dao)
+ else {
+ call gargr (sannulus)
+ if (nscan () != 1)
+ sannulus = DP_SANNULUS(dao)
+ }
+ annulus = sannulus / DP_SCALE(dao)
+
+ DP_SANNULUS(dao) = sannulus
+ DP_ANNULUS(dao) = annulus
+
+ call printf ( "\tNew inner radius: %g scale units %g pixels\n")
+ call pargr (sannulus)
+ call pargr (annulus)
+end
+
+
+# DP_VWSANNULUS -- Confirm the width of the sky fitting annulus.
+
+procedure dp_vwsannulus (dao)
+
+pointer dao # pointer to the daophot structure
+
+real sdannulus, dannulus
+int scan(), nscan()
+
+begin
+ # Confirm the inner radius of the sky annulus.
+ call printf ( "Width of sky annulus in scale units (%g): ")
+ call pargr (DP_SDANNULUS(dao))
+ call flush (STDOUT)
+ if (scan() == EOF)
+ sdannulus = DP_SDANNULUS(dao)
+ else {
+ call gargr (sdannulus)
+ if (nscan () != 1)
+ sdannulus = DP_SDANNULUS(dao)
+ }
+ dannulus = sdannulus / DP_SCALE(dao)
+
+ DP_SDANNULUS(dao) = sdannulus
+ DP_DANNULUS(dao) = dannulus
+
+ call printf ( "\tNew annulus width: %g scale units %g pixels\n")
+ call pargr (sdannulus)
+ call pargr (dannulus)
+end
diff --git a/noao/digiphot/daophot/daolib/dpwcs.x b/noao/digiphot/daophot/daolib/dpwcs.x
new file mode 100644
index 00000000..9961b933
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpwcs.x
@@ -0,0 +1,234 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imio.h>
+include "../lib/daophotdef.h"
+
+# DP_WIN -- Convert the input coordinates to logical coordinates.
+
+procedure dp_win (dp, im, xin, yin, xout, yout, npts)
+
+pointer dp # the apphot package descriptor
+pointer im # the input image descriptor
+real xin[ARB] # the input x coordinate
+real yin[ARB] # the input y coordinate
+real xout[ARB] # the output x coordinate
+real yout[ARB] # the output y coordinate
+int npts # the number of coordinates to convert
+
+int dp_stati()
+
+begin
+ # Transform the input coordinates.
+ switch (dp_stati (dp, WCSIN)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call dp_itol (dp, xin, yin, xout, yout, npts)
+ case WCS_TV:
+ call dp_vtol (im, xin, yin, xout, yout, npts)
+ default:
+ call amovr (xin, xout, npts)
+ call amovr (yin, yout, npts)
+ }
+end
+
+
+# DP_WOUT -- Convert the logical coordinates to output coordinates.
+
+procedure dp_wout (dp, im, xin, yin, xout, yout, npts)
+
+pointer dp # the apphot package descriptor
+pointer im # the input image descriptor
+real xin[ARB] # the input x coordinate
+real yin[ARB] # the input y coordinate
+real xout[ARB] # the output x coordinate
+real yout[ARB] # the output y coordinate
+int npts # the number of coordinates to convert
+
+int dp_stati()
+
+begin
+ # Transform the input coordinates.
+ switch (dp_stati (dp, WCSOUT)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call dp_ltoo (dp, xin, yin, xout, yout, npts)
+ case WCS_TV:
+ call dp_ltov (im, xin, yin, xout, yout, npts)
+ default:
+ call amovr (xin, xout, npts)
+ call amovr (yin, yout, npts)
+ }
+end
+
+
+# DP_WPSF -- Convert the logical coordinates to psf coordinates.
+
+procedure dp_wpsf (dp, im, xin, yin, xout, yout, npts)
+
+pointer dp # the apphot package descriptor
+pointer im # the input image descriptor
+real xin[ARB] # the input x coordinate
+real yin[ARB] # the input y coordinate
+real xout[ARB] # the output x coordinate
+real yout[ARB] # the output y coordinate
+int npts # the number of coordinates to convert
+
+int dp_stati()
+
+begin
+ # Transform the input coordinates.
+ switch (dp_stati (dp, WCSPSF)) {
+ case WCS_WORLD, WCS_PHYSICAL:
+ call dp_ltop (dp, xin, yin, xout, yout, npts)
+ case WCS_TV:
+ call dp_ltov (im, xin, yin, xout, yout, npts)
+ default:
+ call amovr (xin, xout, npts)
+ call amovr (yin, yout, npts)
+ }
+end
+
+
+# DP_ITOL -- Convert coordinates from the input coordinate system to the
+# logical coordinate system.
+
+procedure dp_itol (dp, xin, yin, xout, yout, npts)
+
+pointer dp # the apphot package descriptor
+real xin[ARB] # the input x coordinate
+real yin[ARB] # the input y coordinate
+real xout[ARB] # the output x coordinate
+real yout[ARB] # the output y coordinate
+int npts # the number of coordinates to convert
+
+double xt, yt
+pointer ct
+int i
+int dp_stati()
+
+begin
+ ct = dp_stati (dp, CTIN)
+ if (ct == NULL) {
+ call amovr (xin, xout, npts)
+ call amovr (yin, yout, npts)
+ return
+ }
+
+ do i = 1, npts {
+ call mw_c2trand (ct, double (xin[i]), double (yin[i]), xt, yt)
+ xout[i] = xt
+ yout[i] = yt
+ }
+end
+
+
+# DP_LTOO -- Convert coordinates from the logical coordinate system to the
+# output coordinate system.
+
+procedure dp_ltoo (dp, xin, yin, xout, yout, npts)
+
+pointer dp # the apphot package descriptor
+real xin[ARB] # the input x coordinate
+real yin[ARB] # the input y coordinate
+real xout[ARB] # the output x coordinate
+real yout[ARB] # the output y coordinate
+int npts # the number of coordinates to convert
+
+double xt, yt
+pointer ct
+int i
+int dp_stati()
+
+begin
+ ct = dp_stati (dp, CTOUT)
+ if (ct == NULL) {
+ call amovr (xin, xout, npts)
+ call amovr (yin, yout, npts)
+ return
+ }
+
+ do i = 1, npts {
+ call mw_c2trand (ct, double (xin[i]), double (yin[i]), xt, yt)
+ xout[i] = xt
+ yout[i] = yt
+ }
+end
+
+
+# DP_LTOP -- Convert coordinates from the logical coordinate system to the
+# output coordinate system.
+
+procedure dp_ltop (dp, xin, yin, xout, yout, npts)
+
+pointer dp # the apphot package descriptor
+real xin[ARB] # the input x coordinate
+real yin[ARB] # the input y coordinate
+real xout[ARB] # the output x coordinate
+real yout[ARB] # the output y coordinate
+int npts # the number of coordinates to convert
+
+double xt, yt
+pointer ct
+int i
+int dp_stati()
+
+begin
+ ct = dp_stati (dp, CTPSF)
+ if (ct == NULL) {
+ call amovr (xin, xout, npts)
+ call amovr (yin, yout, npts)
+ return
+ }
+
+ do i = 1, npts {
+ call mw_c2trand (ct, double (xin[i]), double (yin[i]), xt, yt)
+ xout[i] = xt
+ yout[i] = yt
+ }
+end
+
+
+# DP_LTOV -- Convert coordinate from the logical coordinate system to the
+# output coordinate system.
+
+procedure dp_ltov (im, xin, yin, xout, yout, npts)
+
+pointer im # the input image descriptor
+real xin[ARB] # the input x coordinate
+real yin[ARB] # the input y coordinate
+real xout[ARB] # the output x coordinate
+real yout[ARB] # the output y coordinate
+int npts # the number of coordinates to convert
+
+int i, index1, index2
+
+begin
+ index1 = IM_VMAP(im,1)
+ index2 = IM_VMAP(im,2)
+ do i = 1, npts {
+ xout[i] = xin[i] * IM_VSTEP(im,index1) + IM_VOFF(im,index1)
+ yout[i] = yin[i] * IM_VSTEP(im,index2) + IM_VOFF(im,index2)
+ }
+end
+
+
+# DP_VTOL -- Convert coordinate from the tv coordinate system to the
+# logical coordinate system.
+
+procedure dp_vtol (im, xin, yin, xout, yout, npts)
+
+pointer im # the input image descriptor
+real xin[ARB] # the input x coordinate
+real yin[ARB] # the input y coordinate
+real xout[ARB] # the output x coordinate
+real yout[ARB] # the output y coordinate
+int npts # the number of coordinates to convert
+
+int i, index1, index2
+
+begin
+ index1 = IM_VMAP(im,1)
+ index2 = IM_VMAP(im,2)
+ do i = 1, npts {
+ xout[i] = (xin[i] - IM_VOFF(im,index1)) / IM_VSTEP(im,index1)
+ yout[i] = (yin[i] - IM_VOFF(im,index2)) / IM_VSTEP(im,index2)
+ }
+end
diff --git a/noao/digiphot/daophot/daolib/dpwparam.x b/noao/digiphot/daophot/daolib/dpwparam.x
new file mode 100644
index 00000000..6e122dee
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/dpwparam.x
@@ -0,0 +1,98 @@
+# DP_RPARAM -- Encode a daophot real parameter.
+
+procedure dp_rparam (out, keyword, value, units, comments)
+
+int out # output file descriptor
+char keyword[ARB] # keyword string
+real value # parameter value
+char units[ARB] # units string
+char comments[ARB] # comment string
+
+begin
+ if (out == NULL)
+ return
+
+ call strupr (keyword)
+ call fprintf (out,
+ "#K%4t%-10.10s%14t = %17t%-23.7g%41t%-10.10s%52t%-10s\n")
+ call pargstr (keyword)
+ call pargr (value)
+ call pargstr (units)
+ call pargstr ("%-23.7g")
+ call pargstr (comments)
+end
+
+
+# DP_IPARAM -- Encode a daophot integer parameter.
+
+procedure dp_iparam (out, keyword, value, units, comments)
+
+int out # output file descriptor
+char keyword[ARB] # keyword string
+int value # parameter value
+char units[ARB] # units string
+char comments[ARB] # comment string
+
+begin
+ if (out == NULL)
+ return
+
+ call strupr (keyword)
+ call fprintf (out,
+ "#K%4t%-10.10s%14t = %17t%-23d%41t%-10.10s%52t%-10s\n")
+ call pargstr (keyword)
+ call pargi (value)
+ call pargstr (units)
+ call pargstr ("%-23d")
+ call pargstr (comments)
+end
+
+
+# DP_BPARAM -- Encode a daophot boolean parameter.
+
+procedure dp_bparam (out, keyword, value, units, comments)
+
+int out # output file descriptor
+char keyword[ARB] # keyword string
+bool value # parameter value
+char units[ARB] # units string
+char comments[ARB] # comment string
+
+begin
+ if (out == NULL)
+ return
+
+ call strupr (keyword)
+ call fprintf (out,
+ "#K%4t%-10.10s%14t = %17t%-23b%41t%-10.10s%52t%-10s\n")
+ call pargstr (keyword)
+ call pargb (value)
+ call pargstr (units)
+ call pargstr ("%-23b")
+ call pargstr (comments)
+end
+
+
+# DP_SPARAM -- Encode a daophot string parameter.
+
+procedure dp_sparam (out, keyword, value, units, comments)
+
+int out # output file descriptor
+char keyword[ARB] # keyword string
+char value[ARB] # parameter value
+char units[ARB] # units string
+char comments[ARB] # comment string
+
+begin
+ if (out == NULL)
+ return
+
+ call strupr (keyword)
+ call fprintf (out,
+ "#K%4t%-10.10s%14t = %17t%-23.23s%41t%-10.10s%52t%-10s\n")
+ call pargstr (keyword)
+ call pargstr (value)
+ call pargstr (units)
+ call pargstr ("%-23s")
+ call pargstr (comments)
+end
diff --git a/noao/digiphot/daophot/daolib/erf.x b/noao/digiphot/daophot/daolib/erf.x
new file mode 100644
index 00000000..d8a48f50
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/erf.x
@@ -0,0 +1,81 @@
+define NGL 4
+
+# DAOERF -- Numerically integrate a Gaussian function from xin-0.5 to xin+0.5
+# using 4 point Gauss-Legendre integration. Beta is the half-width at
+# half-maximum which is equal to 1.17741 * sigma. The Gaussian function is
+# shown below.
+#
+# erf = exp (-0.5 *((x - x0) / beta) ** 2))
+#
+# or
+#
+# erf = exp (-0.6931472 * [(x - xo) / beta] ** 2)
+#
+# Also provide the first derivative of the integral with respect to xo and beta.
+
+real procedure daoerf (xin, x0, beta, dfdx0, dfdbet)
+
+real xin # the input value
+real x0 # position of Gaussian peak
+real beta # sigma of the Gaussian
+real dfdx0 # derivative of Gaussian wrt x0
+real dfdbet # derivative of Gaussian wrt beta
+
+int i, npt
+real betasq, deltax, erfval, xsq, f, x, wf
+real dx[NGL,NGL], wt[NGL,NGL]
+data dx / 0.0, 0.0, 0.0, 0.0,
+ -0.28867513, 0.28867513, 0.0, 0.0,
+ -0.38729833, 0.0, 0.38729833, 0.0,
+ -0.43056816, -0.16999052, 0.16999052, 0.43056816 /
+data wt / 1.0, 0.0, 0.0, 0.0,
+ 0.5, 0.5, 0.0, 0.0,
+ 0.27777778, 0.44444444, 0.27777778, 0.0,
+ 0.17392742, 0.32607258, 0.32607258, 0.17392742 /
+
+begin
+ # Compute some constants.
+ betasq = beta ** 2
+ deltax = xin - x0
+
+ # Initialize.
+ erfval = 0.0
+ dfdx0 = 0.0
+ dfdbet = 0.0
+
+ xsq = deltax ** 2
+ f = xsq / betasq
+ if (f > 34.0)
+ return (erfval)
+
+ f = exp (-0.6931472 * f)
+ if (f >= 0.046) {
+ npt = 4
+ } else if (f >= 0.0022) {
+ npt = 3
+ } else if (f >= 0.0001) {
+ npt = 2
+ } else if (f >= 1.0e-10) {
+ erfval = f
+ dfdx0 = 1.3862944 * deltax * f / betasq
+ dfdbet = 1.3862944 * xsq * f / (betasq * beta)
+ return (erfval)
+ } else {
+ return (erfval)
+ }
+
+ do i = 1, npt {
+ x = deltax + dx[i,npt]
+ xsq = x ** 2
+ f = exp (-0.6931472 * xsq / betasq)
+ wf = wt[i,npt] * f
+ erfval = erfval + wf
+ dfdx0 = dfdx0 + x * wf
+ dfdbet = dfdbet + xsq * wf
+ }
+
+ dfdx0 = 1.3862944 * dfdx0 / betasq
+ dfdbet = 1.3862944 * dfdbet / (betasq * beta)
+
+ return (erfval)
+end
diff --git a/noao/digiphot/daophot/daolib/invers.f b/noao/digiphot/daophot/daolib/invers.f
new file mode 100644
index 00000000..97d9b582
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/invers.f
@@ -0,0 +1,112 @@
+c subroutine invers (a, max, n, iflag)
+c
+c Although it seems counter-intuitive, the tests that I have run
+c so far suggest that the 180 x 180 matrices that NSTAR needs can
+c be inverted with sufficient accuracy if the elements are REAL*4
+c rather than REAL*8.
+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 is 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 invers (a, max, n, iflag)
+c
+ implicit none
+ integer max, n, iflag
+ real a(max,max)
+ integer i, j, k
+c
+ iflag = 0
+ i = 1
+ 300 if (a(i,i) .eq. 0.0e0) 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
+c
+c
+c
+c subroutine dinvers (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 dinvers (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.0e0) 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/daophot/daolib/invers2.x b/noao/digiphot/daophot/daolib/invers2.x
new file mode 100644
index 00000000..5393c6ea
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/invers2.x
@@ -0,0 +1,72 @@
+define TINY (1.0e-15)
+
+# INVERS
+#
+# Although it seems counter-intuitive, the tests that I have run
+# so far suggest that the 180 x 180 matrices that NSTAR needs can
+# be inverted with sufficient accuracy if the elements are REAL*4
+# rather than REAL*8.
+#
+# Arguments
+#
+# a (input/output) is a square matrix of dimension N. The inverse
+# of the input matrix A is returned in A.
+#
+# nmax (input) is the size assigned to the matrix A in the calling
+# routine. It is needed for the dimension statement below.
+#
+# iflag (output) is an error flag. iflag = 1 if the matrix could not
+# be inverted; iflag = 0 if it could.
+#
+# This is an SPP translation of the original fortran version with the
+# addition of a check for tiny numbers which could cause an FPE.
+
+procedure invers2 (a, nmax, n, iflag)
+
+real a[nmax,nmax]
+int nmax
+int n
+int iflag
+
+int i, j, k
+
+begin
+ # Check for tiny numbers.
+ do i = 1, n
+ do j = 1, n
+ if (abs (a[i,j]) < TINY)
+ a[i,j] = 0e0
+
+ # Original code.
+ iflag = 0
+ i = 1
+ 30 if (a[i,i] .eq. 0.0e0) goto 91
+ a[i,i] = 1.0e0 / a[i,i]
+ j = 1
+ 31 if (j .eq. i) goto 34
+ a[j,i] = -a[j,i] * a[i,i]
+ k = 1
+ 32 if (k .eq. i) goto 33
+ a[j,k] = a[j,k] + a[j,i] * a[i,k]
+ 33 if (k .eq. n) goto 34
+ k = k + 1
+ goto 32
+ 34 if (j .eq. n) goto 35
+ j = j + 1
+ goto 31
+ 35 k = 1
+ 36 if (k .eq. i) goto 37
+ a[i,k] = a[i,k] * a[i,i]
+ 37 if (k .eq. n) goto 38
+ k = k + 1
+ goto 36
+ 38 if (i .eq. n) return
+ i = i+1
+ goto 30
+
+# Error: zero on the diagonal.
+
+ 91 iflag = 1
+ return
+
+end
diff --git a/noao/digiphot/daophot/daolib/mkpkg b/noao/digiphot/daophot/daolib/mkpkg
new file mode 100644
index 00000000..44253943
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/mkpkg
@@ -0,0 +1,48 @@
+# DAOPHOT Library Tools
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ dpairmass.x <imhdr.h> ../lib/daophotdef.h
+ dpapheader.x
+ dpfilter.x <imhdr.h> ../lib/daophotdef.h
+ dpfree.x ../lib/daophotdef.h ../lib/apseldef.h \
+ ../lib/allstardef.h
+ dpgetapert.x ../lib/apseldef.h ../lib/daophotdef.h \
+ <tbset.h> ../../lib/ptkeysdef.h
+ dpgppars.x <ctotok.h> ../lib/daophotdef.h
+ dpgsvw.x <imio.h> <imhdr.h> \
+ <math.h>
+ dpppars.x ../lib/daophotdef.h
+ dpimkeys.x ../lib/daophotdef.h
+ dpinit.x ../lib/daophotdef.h ../lib/apseldef.h \
+ ../lib/allstardef.h
+ dpreadpsf.x <imhdr.h> ../lib/daophotdef.h \
+ <error.h>
+ dpset.x ../lib/daophotdef.h ../lib/apseldef.h
+ dpstat.x ../lib/daophotdef.h ../lib/apseldef.h
+ dpdate.x <time.h>
+ dpgsubrast.x <imhdr.h>
+ dpnames.x
+ dpotime.x <imhdr.h> ../lib/daophotdef.h
+ dppadu.x <imhdr.h> ../lib/daophotdef.h
+ dppcache.x <imhdr.h> <imset.h>
+ dprdnoise.x <imhdr.h> ../lib/daophotdef.h
+ dprmwhite.x <ctype.h>
+ dpverify.x ../lib/daophotdef.h
+ dpwparam.x
+ dpwcs.x <imio.h> ../lib/daophotdef.h
+ bicubic.x
+ daoran.x
+ erf.x
+ invers.f
+ invers2.x
+ mvmul.x
+ quick.f
+ pctile.f
+ profile.x ../lib/daophotdef.h
+ usepsf.x ../lib/daophotdef.h
+ ;
diff --git a/noao/digiphot/daophot/daolib/mvmul.x b/noao/digiphot/daophot/daolib/mvmul.x
new file mode 100644
index 00000000..352def99
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/mvmul.x
@@ -0,0 +1,48 @@
+# MVMUL -- Multply a matrix (left-hand side) by a one dimensional vector
+# (right-hand side) and return the resultant vector.
+
+procedure mvmul (matrix, maxdim, dim, vector, result)
+
+real matrix [maxdim, maxdim] # input matrix
+int maxdim # maximum size of input matrix
+int dim # dimension of matrix and vectors
+real vector[maxdim] # input vector
+real result[maxdim] # iutput vector
+
+double sum
+int i, j
+
+begin
+ do i = 1, dim {
+ sum = 0.0
+ do j = 1, dim
+ sum = sum + double (matrix[j,i]) * double(vector[j])
+ result[i] = sum
+ }
+
+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/daophot/daolib/pctile.f b/noao/digiphot/daophot/daolib/pctile.f
new file mode 100644
index 00000000..e8a3f2d7
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/pctile.f
@@ -0,0 +1,91 @@
+c function pctile (datum, n, npct)
+c
+c This is a modification of a quick-sorting algorithm, which is intended
+c to take in a vector of numbers, and return the value of the npct-th
+c element in that vector:
+c
+c dataum input vector
+c n number of elements in dataum
+c npct npct-th element
+c pctile output value of function
+c
+c
+c The array datum contains randomly ordered data
+c
+c
+ real function pctile (datum, n, npct)
+c
+ implicit none
+ integer n, npct
+ real datum(1)
+ integer min0, max0
+ real dkey
+ integer lo, hi, limlo, limhi
+c
+c Initialize the pointers.
+c
+ npct = max0 (1, min0 (n,npct))
+ limlo = 1
+ limhi = n
+c
+c Compare all elements in the sub-vector between limlo and limhi with
+c the current key datum.
+c
+ 100 dkey = datum (limlo)
+ lo = limlo
+ hi = limhi
+c
+c If lo equals hi, we have tested all the elements in the current search
+c interval.
+c
+ 101 continue
+ if (lo .eq. hi) go to 200
+ if (datum(hi) .le. dkey) go to 109
+c
+c The pointer hi is to be left pointing at a datum SMALLER than the
+c key, which is intended to be overwritten.
+c
+ hi = hi - 1
+c
+ goto 101
+ 109 datum(lo) = datum(hi)
+ lo = lo + 1
+ 110 continue
+ if (lo .eq. hi) goto 200
+ if (datum(lo) .ge. dkey) go to 119
+ lo = lo + 1
+c
+ goto 110
+ 119 datum(hi) = datum(lo)
+c
+c The pointer LO is to be left pointing at a datum LARGER than the
+c key, which is intended to be overwritten.
+c
+ hi = hi - 1
+c
+ go to 101
+c
+c lo and hi are equal, and point at a value which is intended to
+c be overwritten. Since all values below this point are less than
+c the key and all values above this point are greater than the key,
+c this is where we stick the key back into the vector.
+c
+ 200 continue
+c
+c At this point in the subroutine, all data between limlo and lo-1,
+c inclusive, are less than datum (lo), and all data between lo+1 and
+c limhi are larger than dataum(lo). If lo = npct, then datum(lo) is
+c the value we are looking for. If npct < lo, then we want to sort the
+c values of datum from limlo to lo-1, inclusive, whereas if npct > lo,
+c then we want to sort the values of datum from lo+1 to limhi,
+c inclusive.
+c
+ datum(lo) = dkey
+ if (npct - lo) 300, 900, 400
+ 300 limhi = lo - 1
+ go to 100
+ 400 limlo = lo + 1
+ go to 100
+ 900 pctile = datum(lo)
+ return
+ end
diff --git a/noao/digiphot/daophot/daolib/profile.x b/noao/digiphot/daophot/daolib/profile.x
new file mode 100644
index 00000000..96e1a531
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/profile.x
@@ -0,0 +1,506 @@
+include "../lib/daophotdef.h"
+
+define NGL 4
+
+# DP_PROFILE -- Evaluate the analytic part of the psf function and its
+# derivatives.
+
+real procedure dp_profile (ipstyp, dx, dy, par, dhdxc, dhdyc, term, ideriv)
+
+int ipstyp # the analytic psf function type
+real dx, dy # distance of point from center of function
+real par[ARB] # the current parameter values
+real dhdxc, dhdyc # derivatives of the function integral wrt x,y
+real term[ARB] # derivatives of the function wrt parameters
+int ideriv # compute the derivatives ?
+
+int npt, ix, iy
+real d[NGL,NGL], w[NGL,NGL], x[NGL], xsq[NGL], p1xsq[NGL]
+real p1p2, dhdsx, dhdsy, erfx, erfy, p1sq, p2sq, y, ysq, p2ysq, profile
+real xy, wt, denom, alpha, func, p4fod, wp4fod, f, e, rsq, wf
+real wfsq, onemp3, dfby, deby, dbyx0, dbyy0
+real daoerf()
+
+data d / 0.0, 0.0, 0.0, 0.0,
+ -0.28867513, 0.28867513, 0.0, 0.0,
+ -0.38729833, 0.0, 0.38729833, 0.0,
+ -0.43056816, -0.16999052, 0.16999052, 0.43056816 /
+data w / 1.0, 0.0, 0.0, 0.0,
+ 0.5, 0.5, 0.0, 0.0,
+ 0.27777778, 0.44444444, 0.27777778, 0.0,
+ 0.17392742, 0.32607258, 0.32607258, 0.17392742 /
+begin
+ # Initialize.
+ profile = 0.0
+ dhdxc = 0.0
+ dhdyc = 0.0
+
+ # Compute the analytic part of the profile for a given x and y.
+
+ switch (ipstyp) {
+
+ # Evaluate the Gaussian function
+ # f = erfx * erfy / (par[1] * par[2])
+ # par[1] is the hwhm in x; sigma(x) = 0.8493218 * hwhm
+ # par[2] is the hwhm in y; sigma(y) = 0.8493218 * hwhm
+
+ case FCTN_GAUSS:
+
+ p1p2 = par[1] * par[2]
+ erfx = daoerf (dx, 0.0, par[1], dhdxc, dhdsx)
+ erfy = daoerf (dy, 0.0, par[2], dhdyc, dhdsy)
+ profile = erfx * erfy / p1p2
+ dhdxc = dhdxc * erfy / p1p2
+ dhdyc = dhdyc * erfx / p1p2
+ if (ideriv > 0) {
+ term[1] = (dhdsx - erfx / par[1]) * erfy / p1p2
+ term[2] = (dhdsy - erfy / par[2]) * erfx / p1p2
+ }
+
+ # Evaluate the Moffat25 function
+ #
+ # f = (beta - 1) / (ax * ay * (1 + (x/ax) ** 2 + (y/ay) ** 2 +
+ # (xy * axy)) ** beta)
+ #
+ # par[1] is the hwhm in x at y = 0.0
+ # 1/2 = 1 / (1 + (par[1] / ax) ** 2) ** beta
+ # so
+ # 2 ** (1/ beta) - 1 = (par[1] / ax) ** 2
+ # ax ** 2 = par[1] ** 2 / (2 ** (1 / beta) - 1)
+ #
+ # when beta = 2.5 ax ** 2 = 3.129813 * par[1] ** 2
+ #
+ # f = 1 / par[1] * par[2] * (1 + 0.3195079 * ((x / par[1]) ** 2 +
+ # (y / par[2]) ** 2 + xy * par[3])) ** 2.5
+ #
+
+ case FCTN_MOFFAT25:
+
+ alpha = 0.3195079
+ #talpha = 0.6390158
+ p1sq = par[1] ** 2
+ p2sq = par[2] ** 2
+ p1p2 = par[1] * par[2]
+ xy = dx * dy
+ if (ideriv > 0)
+ call aclrr (term, 4)
+
+ denom = 1.0 + alpha * (dx ** 2 / p1sq + dy ** 2 / p2sq + xy *
+ par[3])
+ if (denom > 1.0e4)
+ return (profile)
+ func = 1.0 / (p1p2 * denom ** par[4])
+ if (func >= 0.046) {
+ npt = 4
+ } else if (func >= 0.0022) {
+ npt = 3
+ } else if (func >= 0.0001) {
+ npt = 2
+ } else if (func >= 1.0e-10) {
+ profile = (par[4] - 1.0) * func
+ p4fod = par[4] * alpha * profile / denom
+ dhdxc = p4fod * (2.0 * dx / p1sq + dy * par[3])
+ dhdyc = p4fod * (2.0 * dy / p2sq + dx * par[3])
+ if (ideriv > 0) {
+ term[1] = (2.0 * p4fod * dx ** 2 / p1sq - profile) /
+ par[1]
+ term[2] = (2.0 * p4fod * dy ** 2 / p2sq - profile) /
+ par[2]
+ term[3] = - p4fod * xy
+ term[4] = profile * (1.0 / (par[4] - 1.0) - log (denom))
+ }
+ return (profile)
+ } else {
+ return (profile)
+ }
+
+ do ix = 1, npt {
+ x[ix] = dx + d[ix,npt]
+ xsq[ix] = x[ix] ** 2
+ p1xsq[ix] = xsq[ix] / p1sq
+ }
+
+ do iy = 1, npt {
+ y = dy + d[iy,npt]
+ ysq = y ** 2
+ p2ysq = ysq / p2sq
+ do ix = 1, npt {
+ wt = w[iy,npt] * w[ix,npt]
+ xy = x[ix] * y
+ denom = 1.0 + alpha * (p1xsq[ix] + p2ysq + xy * par[3])
+ func = (par[4] - 1.0) / (p1p2 * denom ** par[4])
+ p4fod = par[4] * alpha * func / denom
+ wp4fod = wt * p4fod
+ wf = wt * func
+ profile = profile + wf
+ dhdxc = dhdxc + wp4fod * (2.0 * x[ix] / p1sq +
+ y * par[3])
+ dhdyc = dhdyc + wp4fod * (2. * y / p2sq + x[ix] *
+ par[3])
+ if (ideriv > 0) {
+ term[1] = term[1] + (2.0 * wp4fod * p1xsq[ix] - wf) /
+ par[1]
+ term[2] = term[2] + (2.0 * wp4fod * p2ysq - wf) /
+ par[2]
+ term[3] = term[3] - wp4fod * xy
+ term[4] = term[4] + wf * (1.0 / (par[4] - 1.0) -
+ log (denom))
+ }
+ }
+ }
+
+ #
+ # Penny function which has a gaussian core and lorentzian wings.
+ # The lorentzian is elongated along the x and y axes.
+
+ case FCTN_PENNY1:
+
+ p1sq = par[1] ** 2
+ p2sq = par[2] ** 2
+ onemp3 = 1.0 - par[3]
+ xy = dx * dy
+ if (ideriv > 0)
+ call aclrr (term, 4)
+
+ rsq = dx ** 2 / p1sq + dy ** 2 / p2sq
+ if (rsq > 1.0e10)
+ return (profile)
+
+ f = 1.0 / (1.0 + rsq)
+ rsq = rsq + xy * par[4]
+ if (rsq < 34.0) {
+ e = exp (-0.6931472 * rsq)
+ func = par[3] * e + onemp3 * f
+ } else {
+ e = 0.0
+ func = onemp3 * f
+ }
+
+ if (func >= 0.046) {
+ npt = 4
+ } else if (func >= 0.0022) {
+ npt = 3
+ } else if (func >= 0.0001) {
+ npt = 2
+ } else if (func >= 1.0e-10) {
+ profile = func
+ dfby = onemp3 * f ** 2
+ deby = 0.6931472 * par[3] * e
+ dbyx0 = 2.0 * dx / p1sq
+ dbyy0 = 2.0 * dy / p2sq
+ dhdxc = deby * (dbyx0 + dy * par[4]) + dfby * dbyx0
+ dhdyc = deby * (dbyy0 + dx * par[4]) + dfby * dbyy0
+ if (ideriv > 0) {
+ dbyx0 = dbyx0 * dx / par[1]
+ dbyy0 = dbyy0 * dy / par[2]
+ dfby = dfby + deby
+ term[1] = dfby * dbyx0
+ term[2] = dfby * dbyy0
+ term[3] = e - f
+ term[4] = - deby * xy / (0.5 - abs(par[4]))
+ }
+ return (profile)
+ } else {
+ return (profile)
+ }
+
+ do ix = 1, npt {
+ x[ix] = dx + d[ix,npt]
+ p1xsq[ix] = x[ix] / p1sq
+ }
+
+ do iy = 1, npt {
+ y = dy + d[iy,npt]
+ p2ysq = y / p2sq
+ do ix = 1, npt {
+ wt = w[iy,npt] * w[ix,npt]
+ xy = x[ix] * y
+ rsq = p1xsq[ix] * x[ix] + p2ysq * y
+ f = 1.0 / (1.0 + rsq)
+ rsq = rsq + xy * par[4]
+ if (rsq < 34.0) {
+ e = exp (- 0.6931472 * rsq)
+ func = par[3] * e + onemp3 * f
+ deby = 0.6931472 * wt * par[3] * e
+ } else {
+ e = 0.0
+ func = onemp3 * f
+ deby = 0.0
+ }
+ profile = profile + wt * func
+ dfby = wt * onemp3 * f ** 2
+ dbyx0 = 2.0 * p1xsq[ix]
+ dbyy0 = 2.0 * p2ysq
+ dhdxc = dhdxc + deby * (dbyx0 + dy * par[4]) + dfby * dbyx0
+ dhdyc = dhdyc + deby * (dbyy0 + dx * par[4]) + dfby * dbyy0
+ if (ideriv > 0) {
+ dbyx0 = dbyx0 * dx / par[1]
+ dbyy0 = dbyy0 * dy / par[2]
+ term[1] = term[1] + (dfby + deby) * dbyx0
+ term[2] = term[2] + (dfby + deby) * dbyy0
+ term[3] = term[3] + wt * (e - f)
+ term[4] = term[4] - deby * xy
+ }
+ }
+ }
+
+ # Penny function which has a gaussian core and lorentzian wings.
+ # The gaussian and lorentzian may be tilted in different directions.
+
+ case FCTN_PENNY2:
+
+ p1sq = par[1] ** 2
+ p2sq = par[2] ** 2
+ onemp3 = 1.0 - par[3]
+ xy = dx * dy
+ if (ideriv > 0)
+ call aclrr (term, 5)
+
+ rsq = dx ** 2 / p1sq + dy ** 2 / p2sq
+ dfby = rsq + par[5] * xy
+ if (dfby > 1.0e10)
+ return (profile)
+ f = 1.0 / (1.0 + dfby)
+
+ deby = rsq + par[4] * xy
+ if (deby < 34.0)
+ e = exp (-0.6931472 * deby)
+ else
+ e = 0.0
+
+ func = par[3] * e + onemp3 * f
+ if (func >= 0.046) {
+ npt = 4
+ } else if (func >= 0.0022) {
+ npt = 3
+ } else if (func >= 0.0001) {
+ npt = 2
+ } else if (func >= 1.0e-10) {
+ profile = func
+ dfby = onemp3 * f ** 2
+ deby = 0.6931472 * par[3] * e
+ dbyx0 = 2.0 * dx / p1sq
+ dbyy0 = 2.0 * dy / p2sq
+ dhdxc = deby * (dbyx0 + dy * par[4]) + dfby * (dbyx0 + dy *
+ par[5])
+ dhdyc = deby * (dbyy0 + dx * par[4]) + dfby * (dbyy0 + dx *
+ par[5])
+ if (ideriv > 0) {
+ dbyx0 = dbyx0 * dx / par[1]
+ dbyy0 = dbyy0 * dy / par[2]
+ term[5] = -dfby * xy
+ dfby = dfby + deby
+ term[1] = dfby * dbyx0
+ term[2] = dfby * dbyy0
+ term[3] = e - f
+ term[4] = - deby * xy
+ }
+ return (profile)
+ } else {
+ return (profile)
+ }
+
+ do ix = 1, npt {
+ x[ix] = dx + d[ix,npt]
+ p1xsq[ix] = x[ix] / p1sq
+ }
+
+ do iy = 1, npt {
+ y = dy + d[iy,npt]
+ p2ysq = y / p2sq
+ do ix = 1, npt {
+ wt = w[iy,npt] * w[ix,npt]
+ xy = x[ix] * y
+ rsq = p1xsq[ix] * x[ix] + p2ysq * y
+ f = 1.0 / (1.0 + rsq + par[5] * xy)
+ deby = rsq + par[4] * xy
+ if (deby < 34.0) {
+ e = exp (- 0.6931472 * deby)
+ func = par[3] * e + onemp3 * f
+ deby = 0.6931472 * wt * par[3] * e
+ } else {
+ e = 0.0
+ func = onemp3 * f
+ deby = 0.0
+ }
+ profile = profile + wt * func
+ dfby = wt * onemp3 * f ** 2
+ dbyx0 = 2.0 * p1xsq[ix]
+ dbyy0 = 2.0 * p2ysq
+ dhdxc = dhdxc + deby * (dbyx0 + dy * par[4]) + dfby *
+ (dbyx0 + dy * par[5])
+ dhdyc = dhdyc + deby * (dbyy0 + dx * par[4]) + dfby *
+ (dbyy0 + dx * par[5])
+ if (ideriv > 0) {
+ dbyx0 = dbyx0 * dx / par[1]
+ dbyy0 = dbyy0 * dy / par[2]
+ term[1] = term[1] + (dfby + deby) * dbyx0
+ term[2] = term[2] + (dfby + deby) * dbyy0
+ term[3] = term[3] + wt * (e - f)
+ term[4] = term[4] - deby * xy
+ term[5] = term[5] - dfby * xy
+ }
+ }
+ }
+
+ # Evaluate the Moffat15 function
+ #
+ # f = (beta - 1) / (ax * ay * (1 + (x/ax) ** 2 + (y/ay) ** 2 +
+ # (xy * axy)) ** beta)
+ #
+ # par[1] is the hwhm in x at y = 0.0
+ # 1/2 = 1 / (1 + (par[1] / ax) ** 2) ** beta
+ # so
+ # 2 ** (1/ beta) - 1 = (par[1] / ax) ** 2
+ # ax ** 2 = par[1] ** 2 / (2 ** (1 / beta) - 1)
+ #
+ # when beta = 1.5 ax ** 2 = 1.7024144 * par[1] ** 2
+ #
+ # f = 1 / par[1] * par[2] * (1 + 0.5874011 * ((x / par[1]) ** 2 +
+ # (y / par[2]) ** 2 + xy * par[3])) ** 2.5
+ #
+
+ case FCTN_MOFFAT15:
+
+ alpha = 0.5874011
+ #talpha = 1.1748021
+ p1sq = par[1] ** 2
+ p2sq = par[2] ** 2
+ p1p2 = par[1] * par[2]
+ xy = dx * dy
+ if (ideriv > 0)
+ call aclrr (term, 4)
+
+ denom = 1.0 + alpha * (dx ** 2 / p1sq + dy ** 2 / p2sq + xy *
+ par[3])
+ if (denom > 5.0e6)
+ return (profile)
+ func = 1.0 / (p1p2 * denom ** par[4])
+ if (func >= 0.046) {
+ npt = 4
+ } else if (func >= 0.0022) {
+ npt = 3
+ } else if (func >= 0.0001) {
+ npt = 2
+ } else if (func >= 1.0e-10) {
+ profile = (par[4] - 1.0) * func
+ p4fod = par[4] * alpha * profile / denom
+ dhdxc = p4fod * (2.0 * dx / p1sq + dy * par[3])
+ dhdyc = p4fod * (2.0 * dy / p2sq + dx * par[3])
+ if (ideriv > 0) {
+ term[1] = (2.0 * p4fod * dx ** 2 / p1sq - profile) /
+ par[1]
+ term[2] = (2.0 * p4fod * dy ** 2 / p2sq - profile) /
+ par[2]
+ term[3] = - p4fod * xy
+ term[4] = profile * (1.0 / (par[4] - 1.0) - log (denom))
+ }
+ return (profile)
+ } else {
+ return (profile)
+ }
+
+ do ix = 1, npt {
+ x[ix] = dx + d[ix,npt]
+ xsq[ix] = x[ix] ** 2
+ p1xsq[ix] = xsq[ix] / p1sq
+ }
+
+ do iy = 1, npt {
+ y = dy + d[iy,npt]
+ ysq = y ** 2
+ p2ysq = ysq / p2sq
+ do ix = 1, npt {
+ wt = w[iy,npt] * w[ix,npt]
+ xy = x[ix] * y
+ denom = 1.0 + alpha * (p1xsq[ix] + p2ysq + xy *
+ par[3])
+ func = (par[4] - 1.0) / (p1p2 * denom ** par[4])
+ p4fod = par[4] * alpha * func / denom
+ wp4fod = wt * p4fod
+ wf = wt * func
+ profile = profile + wf
+ dhdxc = dhdxc + wp4fod * (2.0 * x[ix] / p1sq + y *
+ par[3])
+ dhdyc = dhdyc + wp4fod * (2. * y / p2sq + x[ix] *
+ par[3])
+ if (ideriv > 0) {
+ term[1] = term[1] + (2.0 * wp4fod * p1xsq[ix] - wf) /
+ par[1]
+ term[2] = term[2] + (2.0 * wp4fod * p2ysq - wf) /
+ par[2]
+ term[3] = term[3] - wp4fod * xy
+ term[4] = term[4] + wf * (1.0 / (par[4] - 1.0) -
+ log (denom))
+ }
+ }
+ }
+
+ case FCTN_LORENTZ:
+
+ p1sq = par[1] ** 2
+ p2sq = par[2] ** 2
+ p1p2 = par[1] * par[2]
+ xy = dx * dy
+ if (ideriv > 0)
+ call aclrr (term, 3)
+
+ denom = 1.0 + dx ** 2 / p1sq + dy ** 2 / p2sq + xy * par[3]
+ if (denom > 1.0e10)
+ return (profile)
+ func = 1.0 / denom
+ if (func >= 0.046) {
+ npt = 4
+ } else if (func >= 0.0022) {
+ npt = 3
+ } else if (func >= 0.0001) {
+ npt = 2
+ } else if (func >= 1.0e-10) {
+ profile = func
+ wfsq = func ** 2
+ dhdxc = wfsq * (2.0 * dx / p1sq + dy * par[3])
+ dhdyc = wfsq * (2.0 * dy / p2sq + dx * par[3])
+ if (ideriv > 0) {
+ term[1] = wfsq * (2.0 * dx ** 2 / p1sq) / par[1]
+ term[2] = wfsq * (2.0 * dy ** 2 / p2sq) / par[2]
+ term[3] = - wfsq * xy
+ }
+ return (profile)
+ } else {
+ return (profile)
+ }
+
+ do ix = 1, npt {
+ x[ix] = dx + d[ix,npt]
+ xsq[ix] = x[ix] ** 2
+ p1xsq[ix] = xsq[ix] / p1sq
+ }
+
+ do iy = 1, npt {
+ y = dy + d[iy,npt]
+ ysq = y ** 2
+ p2ysq = ysq / p2sq
+ do ix = 1, npt {
+ wt = w[iy,npt] * w[ix,npt]
+ xy = x[ix] * y
+ denom = 1.0 + p1xsq[ix] + p2ysq + xy * par[3]
+ func = 1.0 / denom
+ wf = wt * func
+ wfsq = wf * func
+ profile = profile + wf
+ dhdxc = dhdxc + wfsq * (2.0 * x[ix] / p1sq + y * par[3])
+ dhdyc = dhdyc + wfsq * (2.0 * y / p2sq + x[ix] * par[3])
+ if (ideriv > 0) {
+ term[1] = term[1] + wfsq * (2.0 * p1xsq[ix]) / par[1]
+ term[2] = term[2] + wfsq * (2.0 * p2ysq) / par[2]
+ term[3] = term[3] - wfsq * xy
+ }
+ }
+ }
+
+ default:
+ profile = INDEFR
+ }
+
+ return (profile)
+end
diff --git a/noao/digiphot/daophot/daolib/quick.f b/noao/digiphot/daophot/daolib/quick.f
new file mode 100644
index 00000000..72a58fe5
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/quick.f
@@ -0,0 +1,202 @@
+c subroutine quick (dataum, n, index)
+c
+c
+c A quick-sorting algorithm suggested by the discussion on pages 114-119
+c of THE ART OF COMPUTER PROGRAMMING, Vol. 3, SORTING AND SEARCHING, by
+c D.E. Knuth, which was referenced in Don Wells' subroutine QUIK. This
+c is my own attempt at encoding a quicksort-- PBS.
+c
+c Arguments
+c
+c datum (input / output) is a vector of dimension n containing randomly
+c ordered real data upon input. Upon output the elements of
+c dataum will be in order of increasing value.
+c
+c
+c index (output) is an integer vector of dimension n. Upon return to
+c the calling program the i-th element of index will tell where
+c the i-th element of the sorted vector datum had been before
+c datum was sorted.
+c
+c
+c
+c parameter (maxstack = 28)
+c
+c Parameters
+c
+c maxstack is the maximum number of entries the stack can contain.
+c A limiting stack length of 28 restricts this quicksort
+
+ subroutine quick (datum, n, index, ier)
+c
+ implicit none
+ integer n, index(n), ier
+ real datum(n)
+c
+ real dkey
+ integer stklo(28), stkhi(28), i, lo, hi, nstak, limlo, limhi, ikey
+c
+c Initialize error code
+
+ ier = 0
+c
+c Initialize index.
+c
+ do 50 i = 1, n
+ 50 index(i) = i
+c
+c Initialize the pointers.
+c
+ nstak = 0
+ limlo = 1
+ limhi = n
+c
+ 100 dkey = datum(limlo)
+ ikey = index(limlo)
+c
+c Compare all elements in the sub-vector between limlo and limhi with
+c the current key datum.
+c
+ lo = limlo
+ hi = limhi
+ 101 continue
+c
+ if (lo .eq. hi) go to 200
+c
+ if (datum(hi) .le. dkey) go to 109
+ hi = hi - 1
+c
+c The pointer hi is to be left pointing at a datum smaller than the
+c key, which is intended to be overwritten.
+c
+ go to 101
+c
+ 109 datum(lo) = datum(hi)
+ index(lo) = index(hi)
+ lo = lo + 1
+ 110 continue
+c
+ if (lo .eq. hi) go to 200
+c
+ if (datum(lo) .ge. dkey) go to 119
+c
+ lo = lo + 1
+ go to 110
+c
+ 119 datum(hi) = datum(lo)
+ index(hi) = index(lo)
+ hi = hi - 1
+c
+c The pointer LO is to be left pointing at a datum LARGER than the
+c key, which is intended to be overwritten.
+c
+ go to 101
+c
+ 200 continue
+c
+c lo and hi are equal, and point at a value which is intended to
+c be overwritten. Since all values below this point are less than
+c the key and all values above this point are greater than the key,
+c this is where we stick the key back into the vector.
+c
+ datum(lo) = dkey
+ index(lo) = ikey
+c
+c At this point in the subroutine, all data between limlo and LO-1,
+c inclusive, are less than datum(LO), and all data between LO+1 and
+c limhi are larger than datum(LO).
+c
+c If both subarrays contain no more than one element, then take the most
+c recent interval from the stack (if the stack is empty, we're done).
+c If the larger of the two subarrays contains more than one element, and
+c if the shorter subarray contains one or no elements, then forget the
+c shorter one and reduce the other subarray. If the shorter subarray
+c contains two or more elements, then place the larger subarray on the
+c stack and process the subarray.
+c
+ if ((limhi - lo) .gt. (lo - limlo)) go to 300
+c
+c Case 1: the lower subarray is longer. If it contains one or no
+c elements then take the most recent interval from the stack and go
+c back and operate on it.
+c
+ if ((lo - limlo) .le. 1) go to 400
+c
+c If the upper (shorter) subinterval contains one or no elements, then
+c process the lower (longer) one, but if the upper subinterval contains
+c more than one element, then place the lower (longer) subinterval on
+c the stack and process the upper one.
+c
+ if ((limhi - lo) .ge. 2) go to 250
+c
+c Case 1a: the upper (shorter) subinterval contains no or one elements,
+c so we go back and operate on the lower (longer) subinterval.
+c
+ limhi = lo - 1
+ go to 100
+c
+ 250 continue
+c
+c Case 1b: the upper (shorter) subinterval contains at least two
+c elements, so we place the lower (longer) subinterval on the stack and
+c then go back and operate on the upper subinterval.
+c
+ nstak = nstak + 1
+ if (nstak .gt. 28) then
+ ier = -1
+ return
+ endif
+ stklo(nstak) = limlo
+ stkhi(nstak) = lo - 1
+ limlo = lo + 1
+ go to 100
+c
+ 300 continue
+c
+c Case 2: the upper subarray is longer. If it contains one or no
+c elements then take the most recent interval from the stack and
+c operate on it.
+c
+ if ((limhi - lo) .le. 1) go to 400
+c
+c If the lower (shorter) subinterval contains one or no elements, then
+c process the upper (longer) one, but if the lower subinterval contains
+c more than one element, then place the upper (longer) subinterval on
+c the stack and process the lower one.
+c
+ if ((lo - limlo) .ge. 2) go to 350
+c
+c Case 2a: the lower (shorter) subinterval contains no or one elements,
+c so we go back and operate on the upper (longer) subinterval.
+c
+ limlo = lo + 1
+ go to 100
+c
+ 350 continue
+c
+c Case 2b: the lower (shorter) subinterval contains at least two
+c elements, so we place the upper (longer) subinterval on the stack and
+c then go back and operate on the lower subinterval.
+c
+ nstak = nstak + 1
+ if (nstak .gt. 28) then
+ ier = -1
+ return
+ endif
+ stklo(nstak) = lo + 1
+ stkhi(nstak) = limhi
+ limhi = lo - 1
+ go to 100
+c
+ 400 continue
+c
+c Take the most recent interval from the stack. If the stack happens
+c to be empty, we are done.
+c
+ if (nstak .le. 0) return
+ limlo = stklo(nstak)
+ limhi = stkhi(nstak)
+ nstak = nstak - 1
+ go to 100
+c
+ end
diff --git a/noao/digiphot/daophot/daolib/ran3.x b/noao/digiphot/daophot/daolib/ran3.x
new file mode 100644
index 00000000..c8915e70
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/ran3.x
@@ -0,0 +1,63 @@
+define MBIG 1000000000
+define MSEED 161803398
+define MZ 0.0
+define FAC 1.0 / MBIG
+
+# RAN3 -- Returns a uniform random deviate between 0.0 and 1.0. Set
+# 'idum' to any negative value to initialize or reinitialize the sequence.
+# From Numerical Recipes (originally attributed to Donald Knuth, 1981;
+# Seminumerical Algorithms, 2nd edition, volume 2 of 'The Art of Computer
+# Programming' - Section 3.2-3.3.
+
+real procedure ran3 (idum)
+
+int idum
+
+int ma[55]
+int mj, mk, i, k, ii
+int iff, inext, inextp
+data iff /0/
+
+begin
+ if(idum < 0 || iff == 0) {
+ iff = 1
+ mj = MSEED - iabs(idum)
+ mj = mod(mj, MBIG)
+ ma[55] = mj
+ mk = 1
+
+ do i = 1, 54 {
+ ii = mod(21 * i , 55)
+ ma[ii] = mk
+ mk = mj - mk
+ if (mk < MZ)
+ mk = mk + MBIG
+ mj = ma[ii]
+ }
+
+ do k = 1, 4 {
+ do i = 1, 55 {
+ ma[i] = ma[i] - ma[1+mod(i+30, 55)]
+ if (ma[i] < MZ)
+ ma[i] = ma[i] + MBIG
+ }
+ }
+
+ inext = 0
+ inextp = 31
+ idum = 1
+ }
+
+ inext = inext + 1
+ if (inext == 56)
+ inext = 1
+ inextp = inextp + 1
+ if (inextp == 56)
+ inextp = 1
+ mj = ma[inext] - ma[inextp]
+ if (mj < MZ)
+ mj = mj + MBIG
+ ma[inext]= mj
+ return (mj * FAC)
+
+end
diff --git a/noao/digiphot/daophot/daolib/usepsf.x b/noao/digiphot/daophot/daolib/usepsf.x
new file mode 100644
index 00000000..f7a7db2f
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/usepsf.x
@@ -0,0 +1,81 @@
+include "../lib/daophotdef.h"
+
+# DP_USEPSF -- Evaluate the psf at a given point.
+
+real procedure dp_usepsf (ipstyp, dx, dy, bright, par, psf, npsf, nexp,
+ nfrac, deltax, deltay, dvdxc, dvdyc)
+
+int ipstyp # analytic psf function type
+real dx, dy # distance for center of function
+real bright # the relative brightness of the object
+real par[ARB] # current values of the parameters
+real psf[npsf,npsf,ARB] # the psf lookup tables
+int npsf # size of the psf look-up table
+int nexp # number pf look-up tables
+int nfrac # fractional pixel expansion
+real deltax, deltay # distance from center of look-up tables
+real dvdxc, dvdyc # derivatives with respect to position
+
+int nterm, j, k, lx, ly
+real psfval, middle, junk[MAX_NEXPTERMS], xx, yy, corr, dfdx, dfdy
+real dp_profile(), bicubic()
+
+begin
+ nterm = nexp + nfrac
+ psfval = bright * dp_profile (ipstyp, dx, dy, par, dvdxc, dvdyc,
+ junk, 0)
+ dvdxc = bright * dvdxc
+ dvdyc = bright * dvdyc
+ if (nterm <= 0)
+ return (psfval)
+
+ # The PSF look-up tables are centered at (MIDDLE, MIDDLE).
+
+ switch (nexp) {
+ case 1:
+ junk[1] = 1.
+ case 3:
+ junk[1] = 1.
+ junk[2] = deltax
+ junk[3] = deltay
+ case 6:
+ junk[1] = 1.
+ junk[2] = deltax
+ junk[3] = deltay
+ junk[4] = 1.5 * deltax ** 2 - 0.5
+ junk[5] = deltax * deltay
+ junk[6] = 1.5 * deltay ** 2 - 0.5
+ }
+
+ if (nfrac > 0) {
+ j = nexp + 1
+ junk[j] = - 2. * (dx - real(nint(dx)))
+ j = j + 1
+ junk[j] = - 2. * (dy - real(nint(dy)))
+ j = j + 1
+ junk[j] = 1.5 * junk[j-2] ** 2 - 0.5
+ j = j + 1
+ junk[j] = junk[j-3] * junk[j-2]
+ j = j + 1
+ junk[j] = 1.5 * junk[j-3] ** 2 - 0.5
+ }
+
+ # This point in the stellar profile lies between columns LX and LX+1,
+ # and between rows LY and LY+1 in the look-up tables.
+
+ middle = (npsf + 1) / 2
+ xx = (2. * dx) + middle
+ lx = int (xx)
+ yy = (2. * dy) + middle
+ ly = int (yy)
+
+ do k = 1, nterm {
+ corr = bicubic (psf[lx-1,ly-1,k], npsf, xx - real(lx),
+ yy - real(ly), dfdx, dfdy)
+ psfval = psfval + junk[k] * corr
+ dvdxc = dvdxc - junk[k] * dfdx
+ dvdyc = dvdyc - junk[k] * dfdy
+ }
+
+ return (psfval)
+end
diff --git a/noao/digiphot/daophot/daopars.par b/noao/digiphot/daophot/daopars.par
new file mode 100644
index 00000000..acfb3f3f
--- /dev/null
+++ b/noao/digiphot/daophot/daopars.par
@@ -0,0 +1,25 @@
+# The DAOPHOT fitting parameters
+
+function,s,h,"gauss",,,"Form of analytic component of psf model"
+varorder,i,h,0,-1,2,"Order of empirical component of psf model"
+nclean,i,h,0,,,Number of cleaning iterations for computing psf model
+saturated,b,h,no,,,"Use wings of saturated stars in psf model computation?"
+matchrad,r,h,3.0,0.0,,"Object matching radius in scale units"
+psfrad,r,h,11.0,0.0,,"Radius of psf model in scale units"
+
+fitrad,r,h,3.0,0.0,,"Fitting radius in scale units"
+recenter,b,h,yes,,,"Recenter stars during fit?"
+fitsky,b,h,no,,,"Recompute group sky value during fit?"
+groupsky,b,h,yes,,,"Use group rather than individual sky values?"
+sannulus,r,h,0.0,,,"Inner radius of sky fitting annulus in scale units"
+wsannulus,r,h,11.0,,,"Width of sky fitting annulus in scale units"
+flaterr,r,h,0.75,0.0,100.0,"Flat field error in percent"
+proferr,r,h,5.0,0.0,100.0,"Profile error in percent"
+maxiter,i,h,50,1,100,"Maximum number of fitting iterations"
+clipexp,i,h,6,0,8,"Bad data clipping exponent"
+cliprange,r,h,2.5,0.0,10.0,"Bad data clipping range in sigma"
+mergerad,r,h,INDEF,0.0,,"Critical object merging radius in scale units"
+critsnratio,r,h,1.0,0.0,,"Critical S/N ratio for group membership"
+maxnstar,i,h,10000,,50000,"Maximum number of stars to fit"
+maxgroup,i,h,60,,100,"Maximum number of stars to fit per group"
+mode,s,h,"ql",,,
diff --git a/noao/digiphot/daophot/daophot.cl b/noao/digiphot/daophot/daophot.cl
new file mode 100644
index 00000000..ad72db45
--- /dev/null
+++ b/noao/digiphot/daophot/daophot.cl
@@ -0,0 +1,77 @@
+# Package script task for the DAOPHOTX package.
+#{ DAOPHOTX -- Point Spread Function photometry package.
+
+
+
+# Load other packages
+
+dataio # rfits task is required for the daotest script
+;
+
+package daophot
+
+task setimpars = "daophot$setimpars.cl"
+task daotest = "daophot$daotest.cl"
+
+task daofind,
+ phot = "daophot$x_apphot.e"
+
+task addstar,
+ allstar,
+ group,
+ grpselect,
+ nstar,
+ peak,
+ pfmerge,
+ psf,
+ pstselect,
+ seepsf,
+ daoedit,
+ substar = "daophot$x_daophot.e"
+
+task datapars = "daophot$datapars.par"
+task findpars = "daophot$findpars.par"
+task centerpars = "daophot$centerpars.par"
+task fitskypars = "daophot$fitskypars.par"
+task photpars = "daophot$photpars.par"
+task daopars = "daophot$daopars.par"
+
+# PTOOLS tasks
+
+task pconvert,
+ istable,
+ txcalc,
+ txconcat,
+ txdump,
+ txrenumber,
+ txselect,
+ txsort = "ptools$x_ptools.e"
+
+task pexamine = "daophot$x_ptools.e"
+
+task xyplot = "ptools$xyplot.par"
+task histplot = "ptools$histplot.par"
+task radplot = "ptools$radplot.par"
+task surfplot = "ptools$surfplot.par"
+task cntrplot = "ptools$cntrplot.par"
+
+# PTOOLS scripts which depend on PTOOLS and TTOOLS tasks
+
+task pcalc = "ptools$pcalc.cl"
+task pconcat = "ptools$pconcat.cl"
+task pdump = "ptools$pdump.cl"
+task prenumber = "ptools$prenumber.cl"
+task pselect = "ptools$pselect.cl"
+task psort = "ptools$psort.cl"
+
+# PTOOLS Scripts which depend only on TTOOLS tasks
+
+task tbconcat = "ptools$tbconcat.cl"
+task tbcalc = "ptools$tbcalc.cl"
+task tbdump = "ptools$tbdump.cl"
+
+hidetask istable, txcalc, txconcat, txdump, txrenumber, txselect, txsort
+hidetask xyplot, histplot, radplot, surfplot, cntrplot
+hidetask tbcalc, tbconcat, tbdump
+
+clbye()
diff --git a/noao/digiphot/daophot/daophot.hd b/noao/digiphot/daophot/daophot.hd
new file mode 100644
index 00000000..a7a8b4a6
--- /dev/null
+++ b/noao/digiphot/daophot/daophot.hd
@@ -0,0 +1,42 @@
+# Help directory for the DAOPHOT package
+
+$doc = "./doc/"
+
+$addstar = "daophot$addstar/"
+$allstar = "daophot$allstar/"
+$daoedit = "daophot$daoedit/"
+$daofind = "apphot$daofind/"
+$group = "daophot$group/"
+$select = "daophot$select/"
+$nstar = "daophot$nstar/"
+$peak = "daophot$peak/"
+$pexamine = "ptools$pexamine/"
+$phot = "apphot$phot/"
+$psf = "daophot$psf/"
+$seepsf = "daophot$seepsf/"
+$substar = "daophot$substar/"
+
+addstar hlp=doc$addstar.hlp, src=addstar$t_addstar.x
+allstar hlp=doc$allstar.hlp, src=allstar$t_allstar.x
+centerpars hlp=doc$centerpars.hlp, src=daophot$centerpars.par
+daoedit hlp=doc$daoedit.hlp, src=daoedit$t_daoedit.x
+daofind hlp=doc$daofind.hlp, src=daofind$t_daofind.x
+daopars hlp=doc$daopars.hlp, src=daophot$daopars.par
+daotest hlp=doc$daotest.hlp, src=daophot$daotest.cl
+datapars hlp=doc$datapars.hlp, src=daophot$datapars.par
+findpars hlp=doc$findpars.hlp, src=daophot$findpars.par
+fitskypars hlp=doc$fitskypars.hlp, src=daophot$fitskypars.par
+group hlp=doc$group.hlp, src=group$t_group.x
+grpselect hlp=doc$grpselect.hlp, src=select$t_grpselect.x
+nstar hlp=doc$nstar.hlp, src=nstar$t_nstar.x
+peak hlp=doc$peak.hlp, src=peak$t_peak.x
+pexamine hlp=doc$pexamine.hlp, src=pexamine$t_pexamine.x
+phot hlp=doc$phot.hlp, src=phot$t_phot.x
+photpars hlp=doc$photpars.hlp, src=daophot$photpars.par
+pfmerge hlp=doc$pfmerge.hlp, src=select$t_pfmerge.x
+psf hlp=doc$psf.hlp, src=psf$t_psf.x
+pstselect hlp=doc$pstselect.hlp, src=psf$t_pstselect.x
+seepsf hlp=doc$seepsf.hlp, src=seepsf$t_seepsf.x
+setimpars hlp=doc$setimpars.hlp, src=daophot$setimpars.cl
+substar hlp=doc$substar.hlp, src=substar$t_substar.x
+revisions sys=Revisions
diff --git a/noao/digiphot/daophot/daophot.men b/noao/digiphot/daophot/daophot.men
new file mode 100644
index 00000000..ea6ffb3c
--- /dev/null
+++ b/noao/digiphot/daophot/daophot.men
@@ -0,0 +1,31 @@
+ addstar - Add artificial stars to an image using the computed psf
+ allstar - Group and fit psf to multiple stars simultaneously
+ centerpars - Edit the centering algorithm parameters
+ daoedit - Review/edit algorithm parameters interactively
+ daofind - Find stars in an image using the DAO algorithm
+ daopars - Edit the daophot algorithms parameter set
+ daotest - Run basic tests on the daophot package tasks
+ datapars - Edit the image data dependent parameters
+ findpars - Edit the star detection parameters
+ fitskypars - Edit the sky fitting algorithm parameters
+ group - Group stars based on positional overlap and signal/noise
+ nstar - Fit the psf to predefined groups of stars
+ peak - Fit the psf to single stars
+ phot - Compute sky values and initial magnitudes for a list of stars
+ photpars - Edit the aperture photometry parameters
+ psf - Compute the point spread function
+ seepsf - Compute an image from the point spread function
+ setimpars - Save/restore parameter sets for a particular image
+ substar - Subtract the fitted stars from the original image
+
+ pcalc - Do arithmetic operations on a list of daophot databases
+ pconcat - Concatenate a list of daophot databases
+ pconvert - Convert a text database to a tables database
+ pdump - Print selected fields from a list of daophot databases
+ pfmerge - Merge a list of photometry databases
+ pstselect - Select candidate psf stars based on proximity
+ grpselect - Select groups of a specified size from a daophot database
+ pexamine - Interactively examine and edit a daophot database
+ prenumber - Renumber stars in a daophot database
+ pselect - Select records from a daophot database
+ psort - Sort a daophot database
diff --git a/noao/digiphot/daophot/daophot.par b/noao/digiphot/daophot/daophot.par
new file mode 100644
index 00000000..f9c38f21
--- /dev/null
+++ b/noao/digiphot/daophot/daophot.par
@@ -0,0 +1,13 @@
+# DAOPHOTX package parameter file
+
+version,s,h,"May00"
+text,b,h,yes,,,"Set the default output photfile format to text?"
+wcsin,s,h,logical,"logical|tv|physical|world",,"The input coordinates wcs"
+wcsout,s,h,logical,"logical|tv|physical",,"The output coordinates wcs"
+wcspsf,s,h,logical,"logical|tv|physical",,"The psf coordinates wcs"
+cache,b,h,no,,,"Cache image in memory?"
+verify,b,h,yes,,,"Verify critical parameters?"
+update,b,h,no,,,"Update critial parameters?"
+verbose,b,h,yes,,,"Print verbose output?"
+graphics,s,h,stdgraph,,,"Default graphics device"
+display,s,h,stdimage,,,"Default display device"
diff --git a/noao/digiphot/daophot/daotest.cl b/noao/digiphot/daophot/daotest.cl
new file mode 100644
index 00000000..15153b5f
--- /dev/null
+++ b/noao/digiphot/daophot/daotest.cl
@@ -0,0 +1,308 @@
+# DAOTEST - Self testing procedure for the DAOPHOT package.
+
+procedure daotest (imname)
+
+string imname {prompt="Name of the output test image"}
+string daologfile {"", prompt="Name of the output log file"}
+string daoplotfile {"", prompt="Name of the output plot file"}
+
+begin
+ # Declare local variables.
+ string im, daolog, daoplot
+
+ # Check that the user truly wants to proceed.
+ s1 = ""
+ print ("")
+ print ("DAOTEST INITIALIZES THE DAOPHOT TASK PARAMETERS")
+ print ("TYPE 'q' or 'Q' TO QUIT, ANY OTHER KEY TO PROCEED")
+ if (scan (s1) != EOF) {
+ if (s1 == "q" || s1 == "Q") {
+ print ("TERMINATING THE DAOTEST TASK")
+ bye
+ }
+ }
+ print ("")
+
+ # Define the image name and the log and plot file names.
+ im = imname
+ daolog = daologfile
+ if (daolog == "") {
+ daolog = im // ".log"
+ }
+ daoplot = daoplotfile
+ if (daoplot == "") {
+ daoplot = im // ".plot"
+ }
+
+ # Read in the FITS file and check for the existance of the log and
+ # plot files.
+
+ if (! access (im // ".imh") && ! access (im // ".hhh")) {
+ rfits ("daophot$test/fits3.fits", "0", im, make_image=yes,
+ long_header=no, short_header=yes, datatype="",blank=0,
+ scale=yes,oldirafname=no,offset=0, >& "dev$null")
+ } else {
+ error (0, "Error: The image already exists on disk")
+ }
+ if (access (daolog)) {
+ error (0, "Error: The log file already exists on disk")
+ }
+ if (access (daoplot)) {
+ error (0, "Error: The plot file already exists on disk")
+ }
+
+ # Initialize the DAOPHOT package.
+
+ print ("INITIALIZE THE DAOPHOT PACKAGE", >> daolog)
+ print ("", >> daolog)
+ print ("")
+ print ("INITIALIZE THE DAOPHOT PACKAGE")
+ print ("")
+
+ daophot.text=yes
+
+ unlearn ("addstar")
+ unlearn ("allstar")
+ unlearn ("centerpars")
+ unlearn ("cntrplot")
+ unlearn ("daofind")
+ unlearn ("daopars")
+ unlearn ("datapars")
+ unlearn ("findpars")
+ unlearn ("fitskypars")
+ unlearn ("group")
+ unlearn ("grpselect")
+ unlearn ("histplot")
+ unlearn ("nstar")
+ unlearn ("pconcat")
+ unlearn ("pconvert")
+ unlearn ("pdump")
+ unlearn ("peak")
+ unlearn ("pexamine")
+ unlearn ("pfmerge")
+ unlearn ("phot")
+ unlearn ("photpars")
+ unlearn ("prenumber")
+ unlearn ("pselect")
+ unlearn ("psf")
+ unlearn ("pstselect")
+ unlearn ("psort")
+ unlearn ("radplot")
+ unlearn ("seepsf")
+ unlearn ("substar")
+ unlearn ("surfplot")
+ unlearn ("xyplot")
+
+ # Test the DAOFIND task.
+
+ print ("TESTING THE DAOFIND TASK", >> daolog)
+ print ("TESTING THE DAOFIND TASK")
+ print ("", >> daolog)
+
+ datapars.fwhmpsf=2.0
+ datapars.sigma=10.0
+ findpars.threshold=3.0
+
+ daofind (im, "default", interactive-, verify-, verbose-)
+ concat (im // ".coo.1", daolog, append=yes)
+
+ # Test the PHOT task.
+
+ print ("", >> daolog)
+ print ("TESTING THE PHOT TASK", >> daolog)
+ print ("TESTING THE PHOT TASK")
+ print ("", >> daolog)
+
+ fitskypars.annulus=6.0
+ fitskypars.dannulus=12.0
+ photpars.apertures="3.0,5.0"
+
+ phot (im, "default", "default", interactive-, verify-, verbose-)
+ concat (im // ".mag.1", daolog, append=yes)
+
+ # Test the PSTSELECT task.
+
+ print ("", >> daolog)
+ print ("TESTING THE PSTSELECT TASK", >> daolog)
+ print ("TESTING THE PSTSELECT TASK")
+ print ("", >> daolog)
+
+ pstselect (im, im // ".mag.1", "default", 1, verify-, verbose-)
+ concat (im // ".pst.1", daolog, append=yes)
+
+ # Test the PSF task.
+
+ print ("", >> daolog)
+ print ("TESTING THE PSF TASK", >> daolog)
+ print ("TESTING THE PSF TASK")
+ print ("", >> daolog)
+
+ daopars.psfrad=5.0
+ daopars.fitrad=3.0
+
+ psf (im, "default", "", "default", "default", "default",
+ plotfile=daoplot, icommands="daophot$test/cmds.dat", verify-,
+ verbose-, >> daolog)
+ imheader (im //".psf.1", longheader+, userfields+, >> daolog)
+ print ("", >> daolog)
+ concat (im // ".psg.1", daolog, append=yes)
+ print ("", >> daolog)
+ concat (im // ".pst.2", daolog, append=yes)
+
+ # Test the PEAK task.
+
+ print ("", >> daolog)
+ print ("TESTING THE PEAK TASK", >> daolog)
+ print ("TESTING THE PEAK TASK")
+ print ("", >> daolog)
+
+ peak (im, "default", "default", "default", "", verify-, verbose-,
+ >> daolog)
+ print ("", >> daolog)
+ concat (im // ".pk.1", daolog, append=yes)
+
+ # Test the GROUP task.
+
+ daopars.critsnratio = 0.2
+
+ print ("", >> daolog)
+ print ("TESTING THE GROUP TASK", >> daolog)
+ print ("TESTING THE GROUP TASK")
+ print ("", >> daolog)
+
+ group (im, "default", "default", "default", verify-, verbose+,
+ >> daolog)
+ print ("", >> daolog)
+ concat (im // ".grp.1", daolog, append=yes)
+
+ # Test the GRPSELECT task.
+
+ print ("", >> daolog)
+ print ("TESTING THE GRPSELECT TASK", >> daolog)
+ print ("TESTING THE GRPSELECT TASK")
+ print ("", >> daolog)
+
+ grpselect (im // ".grp.1", im // ".grp.2", 1, 1, verbose+, >> daolog)
+ print ("", >> daolog)
+ concat (im // ".grp.2", daolog, append=yes)
+ delete (im // ".grp.2", ver-, >& "dev$null")
+
+ # Test the NSTAR task.
+
+ print ("", >> daolog)
+ print ("TESTING THE NSTAR TASK", >> daolog)
+ print ("TESTING THE NSTAR TASK")
+ print ("", >> daolog)
+
+ nstar (im, "default", "default", "default", "", verify-, verbose-,
+ >> daolog)
+ print ("", >> daolog)
+ concat (im // ".nst.1", daolog, append=yes)
+
+ # Test the ALLSTAR task with cache set to yes.
+
+ print ("", >> daolog)
+ print ("TESTING THE ALLSTAR TASK (CACHE=YES)", >> daolog)
+ print ("TESTING THE ALLSTAR TASK (CACHE=YES)")
+ print ("", >> daolog)
+
+ daopars.fitrad=3.0
+
+ allstar (im, "default", "default", "default", "", "default", verify-,
+ verbose-, cache=yes, >> daolog)
+ print ("", >> daolog)
+ concat (im // ".als.1", daolog, append=yes)
+ imdelete (im // ".sub.1", go+, verify-, def+, >& "dev$null")
+
+ # Test the ALLSTAR task with cache set to no.
+
+ print ("", >> daolog)
+ print ("TESTING THE ALLSTAR TASK (CACHE=NO)", >> daolog)
+ print ("TESTING THE ALLSTAR TASK (CACHE=NO)")
+ print ("", >> daolog)
+
+ allstar (im, "default", "default", "default", "", "default", verify-,
+ verbose-, cache=no, >> daolog)
+ print ("", >> daolog)
+ concat (im // ".als.2", daolog, append=yes)
+ imdelete (im // ".sub.1", go+, verify-, def+, >& "dev$null")
+
+ # Test the SUBSTAR task.
+
+ print ("", >> daolog)
+ print ("TESTING THE SUBSTAR TASK", >> daolog)
+ print ("TESTING THE SUBSTAR TASK")
+ print ("", >> daolog)
+
+ substar (im, "default", "", "default", "default", verify-, verbose-,
+ >> daolog)
+ imheader (im //".sub.1", longheader+, userfields+, >> daolog)
+ print ("", >> daolog)
+
+ # Test the ADDSTAR task.
+
+ print ("", >> daolog)
+ print ("TESTING THE ADDSTAR TASK", >> daolog)
+ print ("TESTING THE ADDSTAR TASK")
+ print ("", >> daolog)
+
+ addstar (im, "", "default", "default", minmag=16.0, maxmag=18.0,
+ nstar=3, verify-, verbose-, >> daolog)
+ imheader (im //".add.1", longheader+, userfields+, >> daolog)
+ print ("", >> daolog)
+ concat (im // ".art.1", daolog, append=yes)
+ print ("", >> daolog)
+
+ # Clean up.
+ delete (im // ".coo.1", ver-, >& "dev$null")
+ delete (im // ".mag.1", ver-, >& "dev$null")
+ delete (im // ".pst.1", ver-, >& "dev$null")
+ delete (im // ".psg.1", ver-, >& "dev$null")
+ delete (im // ".pst.2", ver-, >& "dev$null")
+ delete (im // ".pk.1", ver-, >& "dev$null")
+ delete (im // ".grp.1", ver-, >& "dev$null")
+ delete (im // ".nst.1", ver-, >& "dev$null")
+ delete (im // ".als.1", ver-, >& "dev$null")
+ delete (im // ".als.2", ver-, >& "dev$null")
+ delete (im // ".art.1", ver-, >& "dev$null")
+
+ unlearn ("addstar")
+ unlearn ("allstar")
+ unlearn ("centerpars")
+ unlearn ("cntrplot")
+ unlearn ("daofind")
+ unlearn ("daopars")
+ unlearn ("datapars")
+ unlearn ("findpars")
+ unlearn ("fitskypars")
+ unlearn ("group")
+ unlearn ("grpselect")
+ unlearn ("histplot")
+ unlearn ("nstar")
+ unlearn ("pconcat")
+ unlearn ("pconvert")
+ unlearn ("pdump")
+ unlearn ("peak")
+ unlearn ("pexamine")
+ unlearn ("pfmerge")
+ unlearn ("phot")
+ unlearn ("photpars")
+ unlearn ("prenumber")
+ unlearn ("pselect")
+ unlearn ("psf")
+ unlearn ("pstselect")
+ unlearn ("psort")
+ unlearn ("radplot")
+ unlearn ("seepsf")
+ unlearn ("substar")
+ unlearn ("surfplot")
+ unlearn ("xyplot")
+
+ print ("DAOPHOT PACKAGE TESTS COMPLETED", >> daolog)
+ print ("", >> daolog)
+ print ("")
+ print ("DAOPHOT PACKAGE TESTS COMPLETED")
+ print ("")
+
+ bye
+end
diff --git a/noao/digiphot/daophot/datapars.par b/noao/digiphot/daophot/datapars.par
new file mode 100644
index 00000000..4c575bfe
--- /dev/null
+++ b/noao/digiphot/daophot/datapars.par
@@ -0,0 +1,25 @@
+# DATAPARS
+
+scale,r,h,1.0,0.0,,Image scale in units per pixel
+fwhmpsf,r,h,2.5,0.0,,FWHM of the PSF in scale units
+emission,b,h,y,,,Features are positive?
+sigma,r,h,0.0,0.0,,Standard deviation of background in counts
+datamin,r,h,INDEF,,,Minimum good data value
+datamax,r,h,INDEF,,,Maximum good data value
+
+noise,s,h,"poisson","|poisson|",,Noise model
+ccdread,s,h,"",,,CCD readout noise image header keyword
+gain,s,h,"",,,CCD gain image header keyword
+readnoise,r,h,0.0,,,CCD readout noise in electrons
+epadu,r,h,1.0,,,Gain in electrons per count
+
+exposure,s,h,"",,,Exposure time image header keyword
+airmass,s,h,"",,,Airmass image header keyword
+filter,s,h,"",,,Filter image header keyword
+obstime,s,h,"",,,Time of observation image header keyword
+itime,r,h,1.0,,,Exposure time
+xairmass,r,h,INDEF,,,Airmass
+ifilter,s,h,"INDEF",,,Filter
+otime,s,h,"INDEF",,,Time of observation
+
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/doc/addstar.hlp b/noao/digiphot/daophot/doc/addstar.hlp
new file mode 100644
index 00000000..f2e08a45
--- /dev/null
+++ b/noao/digiphot/daophot/doc/addstar.hlp
@@ -0,0 +1,365 @@
+.help addstar May00 noao.digiphot.daophot
+.ih
+NAME
+addstar -- add artificial stars to images
+.ih
+USAGE
+addstar image photfile psfimage addimage
+.ih
+PARAMETERS
+.ls image
+The list of images to which artificial stars are to be added.
+.le
+.ls photfile
+The list of photometry files containing the x and y coordinates and magnitudes
+of the artificial stars to be added to \fIimage\fR. If photfile is undefined,
+then \fInstar\fR artificial stars uniformly distributed in position, and in
+magnitude between \fIminmag\fR and \fImaxmag\fR are added to \fIimage\fR. If
+photfile is defined, there must be one photometry file for every input image.
+Photfile may be a simple text file containing x, y, magnitude, and id number in
+columns 1, 2, 3, and 4 respectively (\fIsimple_text\fR = yes), an APPHOT/DAOPHOT
+text database file (\fIsimple_text\fR = no), or an STSDAS binary table file.
+.le
+.ls psfimage
+The list of images containing the PSF models computed by the DAOPHOT PSF task.
+The number of PSF images must be equal to the number of input images. If
+psfimage is "default", "dir$default", or a directory specification, then PEAK
+will look for an image with the name image.psf.?, where ? is the highest
+existing version number.
+.le
+.ls addimage
+The root name of the output images. There must be one output root image name
+ for every input image. If addimage is "default", "dir$default" or a directory
+specification, then an output artificial image and artificial star list called
+image.add.? and image.art.? respectively are created, where ? is the next
+available version number. If the DAOPHOT package parameter \fItext\fR is "yes",
+then an APPHOT/DAOPHOT text database file is written, otherwise an STSDAS binary
+table is written.
+.le
+.ls minmag
+The minimum magnitude of the computer generated artificial stars to be
+added to the image. The actual intensities of the pixels in the artificial
+stars are computed with respect to the magnitude of the PSF stored in
+\fIpsfimage\fR.
+.le
+.ls maxmag
+The maximum magnitude of the computer generated artificial stars to be
+added to the image. The actual intensities of the pixels in the artificial
+stars are computed with respect to the magnitude of the PSF stored in
+\fIpsfimage\fR.
+.le
+.ls nstar
+The number of computer generated artificial stars to be added to the input
+image.
+.le
+.ls datapars = ""
+The text file in which the data dependent parameters are stored. The gain
+parameter \fIepadu\fR in electrons per ADU is stored here. If datapars is
+undefined then the default parameter set in the user's uparm directory is used.
+.le
+.ls daopars = ""
+The text file in which the daophot fitting parameters are stored. The PSF
+radius parameter \fIpsfrad\fR in scale units is stored here. If daopars is
+undefined then the default parameter set in the user's uparm directory is used.
+.le
+.ls simple_text = no
+If \fIphotfile\fR is a text file and \fIsimple_text\fR = "no", then ADDSTAR
+expects an APPHOT/DAOPHOT database. Otherwise ADDSTAR expects a simple list
+format with x, y, magnitude, and id in columns 1, 2,3, and 4 respectively.
+.le
+.ls seed = 0
+The seed for the random number generator used to generate the positions
+and magnitudes of the artificial stars.
+.le
+.ls nimage = 1
+The number of output images to be created per input image.
+.le
+.ls idoffset = 0
+The integer offset to be added to the id numbers of stars in the output
+artificial photometry file. By default the artificial stars are numbered from 1
+to N where N is the number of artificial stars added to the input frame.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout", wcspsf = ")_.wcspsf"
+The coordinate system of the input coordinates read from \fIphotfile\fR, of the
+psf model \fIpsfimage\fR, and of the output coordinates written to
+\fIaddimage\fR respectively. The image header coordinate system is used to
+transform from the input coordinate system to the "logical" pixel coordinate
+system used internally, from the internal logical system to the PSF model
+system, and from the internal "logical" pixel coordinate system to the output
+coordinate system. The input coordinate system options are "logical", "tv",
+"physical", and "world". The PSF model and output coordinate system options
+are "logical", "tv", and "physical". The image cursor coordinate system is
+assumed to be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin, wcspsf, and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin, wcspsf, and wcsout are "logical", "physical" and "logical" respectively.
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default caching is
+disabled.
+.le
+.ls verify = ")_.verify"
+Verify the critical ADDSTAR task parameters? Verify may be set to the
+daophot package parameter value (the default), "yes", or "no".
+.le
+.ls update = ")_.update"
+Update the critical ADDSTAR task parameters if \fIverify\fR = "yes"?
+Update may be set to the daophot package parameter value (the default),
+"yes", or "no".
+.le
+.ls verbose = ")_.verbose"
+Print messages about the progress of ADDSTAR? Verbose may be set to the
+daophot package parameter value (the default), "yes", or "no".
+.le
+
+.ih
+DESCRIPTION
+
+ADDSTAR adds artificial stars, whose positions and magnitudes are listed in
+\fIphotfile\fR or generated at random by the computer, to the input image
+\fIimage\fR using the PSF in \fIpsfimage\fR, and writes the result to the
+output image and output photometry file \fIaddimage\fR. If \fIphotfile\fR is
+undefined then ADDSTAR generates an artificial photometry list containing
+\fInstar\fR stars uniformly distributed in position over the image and in
+magnitude between \fIminmag\fR and \fImaxmag\fR. The input photometry file
+may be an STSDAS binary table or an APPHOT/DAOPHOT text database file (the
+output of the PHOT, PSF, PEAK, NSTAR, or ALLSTAR tasks) or a simple text file
+with the x and y positions, magnitude, and id in columns 1, 2, 3 and 4
+respectively. The ids of stars in the output photometry file may be set to
+numbers outside the range of the real data by setting the parameter
+\fIoffset\fR. Several output images may be written for each input image by
+setting the parameter \fInimage\fR greater than 1.
+
+The coordinates read from \fIphotfile\fR are assumed to be in coordinate
+system defined by \fIwcsin\fR. If photfile is undefined the input coordinate
+system is logical. The options are "logical", "tv", "physical", and "world"
+and the transformation from the input coordinate system to the internal
+"logical" system is defined by the image coordinate system. The simplest
+default is the "logical" pixel system. Users working on with image sections but
+ importing pixel coordinate lists generated from the parent image must use the
+"tv" or "physical" input coordinate systems.
+
+The coordinate system of the PSF model is the coordinate system defined by the
+\fIwcspsf\fR parameter. Normally the PSF model was derived from the input image
+and this parameter default to "logical". However if the PSF model was derived
+from a larger image which is a "parent" of the input image, then wcspsf should
+be set to "tv" or "physical" depending on the circumstances.
+
+The coordinates written to \fIaddimage\fR are in the coordinate system defined
+by \fIwcsout\fR. The options are "logical", "tv", and "physical". The simplest
+default is the "logical" system. Users wishing to correlate the output
+coordinates of objects measured in image sections or mosaic pieces with
+coordinates in the parent image must use the "tv" or "physical" coordinate
+systems.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the output image pixels are cached in memory. If caching
+is enabled and the first artificial star addition will appear
+to take a long time as the entire input image must be read into the output
+image before the first artificial star addition is actually made. All
+subsequent measurements will be very fast because ADDSTAR is accessing memory
+not disk. The point of caching is to speed up random image access by making
+the internal image i/o buffers the same size as the image itself. However if
+the input object lists are sorted in row order and sparse caching may actually
+worsen not improve the execution time. Also at present there is no point in
+enabling caching for images that are less than or equal to 524288 bytes, i.e.
+the size of the test image dev$ypix, as the default image i/o buffer is exactly
+that size. However if the size of dev$ypix is doubled by converting it to a
+real image with the chpixtype task then the effect of caching in interactive
+is can be quite noticeable if measurements of objects in the top and bottom
+halves of the image are alternated.
+
+The intensities in the artificial stellar images are computed relative to the
+intensities in the PSF image, by scaling the magnitudes of the artificial stars
+to the magnitude of the PSF in \fIpsfimage\fR. Poisson noise is added to the
+artificial stars using the value of the gain stored in the image header keyword
+specified by the DATAPARS parameter \fIgain\fR if present, or the value of the
+DATAPARS parameter \fIepadu\fR.
+
+.ih
+OUTPUT
+
+If \fIverbose\fR = yes, a line of output is written to the terminal for each
+artificial star added to the input image.
+
+Full output is written to the output photometry file \fIaddimage\fR. At the
+beginning of each file is a header listing the current values of all the
+parameters. For each artificial star added to the input image the following
+record is written.
+
+.nf
+ id xcenter ycenter mag
+.fi
+
+Id is the id number of the star, xcenter and ycenter are its coordinates, and
+mag is its magnitude.
+
+.ih
+EXAMPLES
+
+1. Add 30 stars uniformly distributed between 17 and 20th magnitude and in
+position to the input image m92. Display the new image and mark the
+artificial stars. Good stars for making the PSF model can be found at
+(442,410), (348,189), and (379,67).
+
+.nf
+ da> daofind dev$ypix default fwhmpsf=2.5 sigma=5.0 threshold=20.0
+
+ ... answer verify prompts
+
+ ... find stars in the image
+
+ ... answer will appear in ypix.coo.1
+
+ da> phot dev$ypix default default annulus=10. dannulus=5. \
+ apertures = 5.0
+
+ ... answer verify prompts
+
+ ... do aperture photometry on the detected stars
+
+ ... answer will appear in ypix.mag.1
+
+ da> display dev$ypix 1
+
+ ... display the image
+
+ da> psf dev$ypix default "" default default default psfrad=9.0 \
+ fitrad=3.0 mkstars=yes display=imdr
+
+ ... verify the critical parameters
+
+ ... move the image cursor to a candidate star and hit the a key,
+ a plot of the stellar data appears
+
+ ... type ? for a listing of the graphics cursor menu
+
+ ... type a to accept the star, d to reject it
+
+ ... move to the next candidate stars and repeat the previous
+ steps
+
+ ... type l to list all the psf stars
+
+ ... type f to fit the psf
+
+ ... move cursor to first psf star and type s to see residuals,
+ repeat for all the psf stars
+
+ ... type w to save the PSF model
+
+ ... type q to quit, and q again to confirm
+
+ ... the output will appear in ypix.psf.1.imh, ypix.pst.1 and
+ ypix.psg.1
+
+ da> addstar dev$ypix "" default default 12.0 17.0 30 epadu=14.0
+
+ ... verify the critical parameters
+
+ da> display ypix.add.1 2
+
+ ... display the artificial image
+
+ da> pdump ypix.art.1 xcenter,ycenter yes | tvmark 2 STDIN col=204
+
+ ... mark the stars on the artificial image
+.fi
+
+
+2. Repeat example 1 using the output starlist as input.
+
+.nf
+ da> addstar dev$ypix ypix.art.1 default default simple- epadu=14.0
+
+ ... the answers will appear in ypix.add.2 and ypix.art.2
+.fi
+
+
+3. Repeat example 1 using a simple text file as input.
+
+.nf
+ da> pdump ypix.art.1 xc,yc,mag yes > artdata
+
+ ... create a simple text file from the addstar output
+
+ da> addstar dev$ypix artdata default default simple+ epadu=14.0
+
+ ... the answers will appear in ypix.add.3 and ypix.art.3
+.fi
+
+
+4. Run addstar on a section of the input image using the PSF model derived in
+example 1 for the parent image, the artificial star list from examples 2 and
+3, and write the results in the coordinate system of the image section
+not the parent image.
+
+.nf
+ da> addstar dev$ypix[150:450,150:450] artdata default default simple+ \
+ epadu=14.0 wcsin=tv wcspsf=tv wcsout=logical
+
+ ... answer the verify prompts
+
+ ... fit the stars
+
+ ... the results will appear in ypix.add.4 and ypix.art.4
+
+ da> display ypix.add.4 1
+
+ ... display the image
+
+ da> pdump ypix.art.4 xc,yc yes | tvmark 1 STDIN col=204
+
+ ... mark the stars
+
+.fi
+
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+datapars,daopars
+.endhelp
diff --git a/noao/digiphot/daophot/doc/allstar.hlp b/noao/digiphot/daophot/doc/allstar.hlp
new file mode 100644
index 00000000..ab70ff00
--- /dev/null
+++ b/noao/digiphot/daophot/doc/allstar.hlp
@@ -0,0 +1,519 @@
+.help allstar May00 noao.digiphot.daophot
+.ih
+NAME
+allstar -- group and fit psf to multiple stars simultaneously
+.ih
+USAGE
+allstar image photfile psfimage allstarfile rejfile subimage
+.ih
+PARAMETERS
+.ls image
+The list of images containing the stars to be fit.
+.le
+.ls photfile
+The input photometry files containing the initial estimates of the positions,
+sky values, and magnitudes of the stars to be fit. There must be one input
+photometry file for every input image. If photfile is "default", "dir$default",
+or a directory specification, then ALLSTAR looks for a file with the name
+image.mag.? where ? is the highest existing version number. Photfile is usually
+the output of the DAOPHOT PHOT task but may also be the output of the PSF, PEAK
+and NSTAR tasks, or the ALLSTAR task itself.
+.le
+.ls psfimage
+The list of images containing the PSF models computed by the DAOPHOT PSF task.
+The number of PSF images must be equal to the number of input images. If
+psfimage is "default", "dir$default", or a directory specification, then PEAK
+will look for an image with the name image.psf.?, where ? is the highest
+existing version number.
+.le
+.ls allstarfile
+The list of output photometry files. There must be one output photometry
+file for every input image. If allstarfile is "default", "dir$default", or a
+directory specification, then ALLSTAR will write an output file with the name
+image.als.? where ? is the next available version number. Allstarfile is a text
+database if the DAOPHOT package parameter text is "yes", an STSDAS table
+database if it is "no".
+.le
+.ls rejfile
+The list of output rejected photometry files containing the positions and sky
+values of stars that could not be fit. If rejfile is undefined, results for all
+the stars in photfile are written to \fIallstarfile\fR, otherwise only the stars
+which were successfully fit are written to \fIallstarfile\fR and the remainder
+are written to rejfile. If rejfile is "default", "dir$default", or a directory
+specification ALLSTAR writes an output file with the name image.als.? where ? is
+the next available version number. Otherwise rejfile must specify one output
+photometry file for every input image. Rejfile is a text database if the
+DAOPHOT package parameter \fItext\fR is "yes", an STSDAS binary table database
+if it is "no".
+.le
+.ls subimage
+The list of output images with the fitted stars subtracted. There must be one
+subtracted image for every input image. If subimage is "default", "dir$default",
+or a directory specification, then ALLSTAR will create an image with the name
+image.sub.? where ? is the next available version number. Otherwise
+\fIsubimage\fR must specify one output image for every image in \fIimage\fR.
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters. The parameters
+\fIscale\fR, \fIdatamin\fR, and \fIdatamax\fR are located here. If datapars
+is undefined then the default parameter set in uparm directory is used.
+.le
+.ls daopars = ""
+The name of the file containing the daophot fitting parameters. The parameters
+\fIpsfrad\fR and \fIfitrad\fR are located here. If \fIdaopars\fR is undefined
+then the default parameter set in uparm directory is used.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout", wcspsf = ")_.wcspsf"
+The coordinate system of the input coordinates read from \fIphotfile\fR, of the
+psf model \fIpsfimage\fR, and of the output coordinates written to
+\fIallstarfile\fR and \fIrejfile\fR respectively. The image header coordinate
+system is used to transform from the input coordinate system to the "logical"
+pixel coordinate system used internally, from the internal logical system to
+the PSF model system, and from the internal "logical" pixel coordinate system
+to the output coordinate system. The input coordinate system options are
+"logical", "tv", "physical", and "world". The PSF model and output coordinate
+system options are "logical", "tv", and "physical". The image cursor coordinate
+system is assumed to be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin, wcspsf, and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin, wcspsf, and wcsout are "logical", "physical" and "logical" respectively.
+.le
+.ls cache = yes
+Cache all the data in memory ? If \fIcache\fR is "yes", then ALLSTAR attempts
+to preallocate sufficient space to store the input image plus the two
+image-sized working arrays it requires, plus space for the starlist, in memory.
+This can significantly reduce the total execution time. Users should however
+beware of creating a situation where excessive paging occurs. If \fIcache\fR =
+"no", ALLSTAR operates on subrasters containing the group currently being
+reduced, and writes the intermediate results to temporary scratch images. This
+option will work on any-sized image (unless a single group becomes the size of
+the entire image!) but can become slow of there are a large number of disk
+accesses. Users may wish to experiment to see which mode of operation suits
+their system best.
+.le
+.ls verbose = ")_.verbose"
+Print messages about the progress of the task ? Verbose can be set to the
+DAOPHOT package parameter value (the default), "yes", or "no".
+.le
+.ls verify = ")_.verify"
+Verify the critical ALLSTAR task parameters. Verify can be set to the daophot
+package parameter value (the default), "yes", or "no".
+.le
+.ls update = ")_.update"
+Update the critical ALLSTAR task parameters if \fIverify\fR = "yes". Update
+can be set to the daophot package parameter value (the default), "yes", or
+"no".
+.le
+
+.ih
+DESCRIPTION
+
+ALLSTAR computes x and y centers, sky values, and magnitudes for the stars in
+\fIphotfile\fR by fitting the PSF \fIpsfimage\fR to groups of stars in the IRAF
+image \fIimage\fR. Initial estimates of the centers, sky values, and
+magnitudes, are read from the photometry list \fIphotfile\fR. ALLSTAR groups
+the stars dynamically, performing a regrouping operation after every iteration.
+The new computed centers, sky values, and magnitudes are written to
+\fIallstarfile\fR along with the number of iterations it took to fit the
+star, the goodness of fit statistic chi, and the image sharpness statistic
+sharp. If \fIrejfile\fR is not null (""), only stars that are successfully fit
+are written to \fIallstarfile\fR, and the remainder are written to
+\fIrejfile\fR. Otherwise all the stars are written to \fIallstarfile\fR.
+\fIAllstarfile\fR and \fIrejfile\fR are text databases if the DAOPHOT package
+parameter \fItext\fR is "yes", STSDAS table databases if it is "no". An image
+with all the fitted stars subtracted out is written to \fIsubimage\fR. In
+effect ALLSTAR performs the combined operations of GROUP, GRPSELECT, NSTAR,
+and SUBSTAR.
+
+The coordinates read from \fIphotfile\fR are assumed to be in coordinate
+system defined by \fIwcsin\fR. The options are "logical", "tv", "physical",
+and "world" and the transformation from the input coordinate system to the
+internal "logical" system is defined by the image coordinate system. The
+simplest default is the "logical" pixel system. Users working on with image
+sections but importing pixel coordinate lists generated from the parent image
+must use the "tv" or "physical" input coordinate systems.
+
+The coordinate system of the PSF model is the coordinate system defined by the
+\fIwcspsf\fR parameter. Normally the PSF model was derived from the input image
+and this parameter default to "logical". However if the PSF model was derived
+from a larger image which is a "parent" of the input image, then wcspsf should
+be set to "tv" or "physical" depending on the circumstances.
+
+The coordinates written to \fIallstarfile\fR and \fIrejfile\fR are in the
+coordinate system defined by \fIwcsout\fR. The options are "logical", "tv", and
+"physical". The simplest default is the "logical" system. Users wishing to
+correlate the output coordinates of objects measured in image sections or
+mosaic pieces with coordinates in the parent image must use the "tv" or
+"physical" coordinate systems.
+
+By default ALLSTAR computes new centers for all the stars in \fIphotfile\fR.
+However if the DAOPARS parameter \fIrecenter\fR is "no", ALLSTAR assumes that
+the x and y centers in \fIphotfile\fR are the true centers and does not refit
+them. This option can be quite useful in cases where accurate center values
+have been derived from an image that has been through some non-linear image
+restoration algorithm, but the photometry must be derived from the original
+unrestored image.
+
+By default (\fIgroupsky\fR = "yes") ALLSTAR computes the sky value for each
+group by averaging the individual sky values in \fIphotfile\fR for all the
+stars in the group. If \fIgroupsky\fR = "no", the sky value for each pixel
+which contributes to the group fit is set equal to the mean of the sky values
+for those stars for which the pixel falls within one fitting radius. If the
+DAOPARS parameter \fIfitksy\fR is "yes", then ALLSTAR recomputes the individual
+sky values before averaging over the group, by, every third iteration,
+subtracting off the current best fit for the star and using the pixel values in
+the annulus defined by the DAOPARS parameters \fIsannulus\fR and \fIwsannulus\fR
+to recompute the sky. The actual sky recomputation is done by averaging forty
+percent of the sky pixels centered on the median of the distribution.
+Recomputing the sky can significantly reduce the scatter in the magnitudes in
+regions where the sky background is varying rapidly.
+
+Only pixels within the good data range defined by the DATAPARS task parameters
+\fIdatamin\fR and \fIdatamax\fR are included in the fit. Most users set
+\fIdatamin\fR and \fIdatamax\fR so as to exclude pixels outside the linearity
+regime of the detector. By default all the data is fit. Users are advised to
+determine accurate values for these parameters for their detector and set the
+values in DATAPARS before beginning any DAOPHOT reductions.
+
+Only pixels within the fitting radius parameter \fIfitrad\fR / \fIscale\fR are
+included in the fit for each star. \fIFitrad\fR is located in the DAOPARS task
+and \fIscale\fR is located in the DATAPARS task. Since the non-linear
+least-squares fits normally compute three unknowns, the x and y position of
+the star's centroid and its brightness, the value of \fIfitrad\fR must be
+sufficiently large to include at least three pixels in the fit for each star.
+To accelerate the convergence of the non-linear least-squares fitting algorithm
+pixels within \fIfitrad\fR are assigned weights which are inversely
+proportional to the radial distance of the pixel from the x and y centroid of
+the star, falling from a maximum at the centroid to zero at the fitting radius.
+\fIFitrad\fR must be sufficiently large to include at least three pixels with
+non-zero radial weights in the fit for each star. ALLSTAR arbitrarily imposes a
+minimum number of good pixels limit of four. Values of \fIfitrad\fR close to
+the full-width at half-maxima of the PSF are recommended.
+
+ALLSTAR computes a weighted fit to the PSF. The weight of each pixel is
+computed by combining, the radial weighting function described above, with
+weights derived from the random errors ALLSTAR predicts based on the detector
+noise characteristics specified by the DATAPARS parameters \fIreadnoise\fR and
+\fIepadu\fR, and the flat-fielding and profile interpolation errors specified
+by the DAOPARS task \fIflaterr\fR and \fIproferr\fR parameters. Both to obtain
+optimal fits, and because ALLSTAR employs a conservative formula for reducing
+the weights of deviant pixels (parametrized by the \fIclipexp\fR and
+\fIcliprange\fR parameters in the DAOPARS task) which do not approach the model
+as the fit proceeds, which depends on \fIreadnoise\fR, \fIepadu\fR,
+\fIflaterr\fR, and \fIproferr\fR, users are strongly advised to determine those
+parameters accurately and to enter their values in DATAPARS and DAOPARS before
+beginning any DAOPHOT reductions.
+
+By default for each group of stars to be fit during each iteration, ALLSTAR
+extracts a subraster from \fIimage\fR which extends approximately \fIfitrad\fR
+/ \fIscale\fR + 1 pixels wide past the limiting values of x and y coordinates
+of the stars in the group. \fIFitrad\fR is the fitting radius specified in the
+DAOPARS task. \fIScale\fR is the image scale specified by the DATAPARS task.
+\fIFitrad\fR may be less than or equal to but can never exceed the value of the
+image header parameter "PSFRAD" in \fIpsfimage\fR.
+
+If the \fIcache\fR parameter is set to "yes" then ALLSTAR attempts to store all
+the vectors and arrays in memory. This can significantly reduce the system
+overhead but may cause excessive paging on machines with a small amount of
+memory. For large images it may be necessary to set \fIcache\fR to "no", and
+use the disk for scratch storage. Users should experiment to see what suits
+them best.
+
+As well as the computed x and y centers, sky values, and magnitudes, ALLSTAR
+outputs the number of times the PSF fit had to be iterated before convergence
+was achieved. The minimum number of iterations is four. The maximum number of
+iteration permitted is specified by the \fImaxiter\fR parameter in the DAOPARS
+task. Obviously the results for stars which have reached the maximum iteration
+count should be viewed with suspicion. However since the convergence criteria
+are quite strict, (the computed magnitude must change by less than .0005
+magnitudes or 0.10 sigma whichever is larger and the x and y centroids must
+change by less than 0.002 pixels from one iteration to the next), even these
+stars may be reasonably well measured.
+
+ALLSTAR computes a goodness of fit statistic chi which is essentially the ratio
+of the observed pixel-to-pixel scatter in the fitting residuals to the expected
+scatter. Since the expected scatter is dependent on the DATAPARS task parameters
+\fIreadnoise\fR and \fIepadu\fR, and the DAOPARS parameters \fIflaterr\fR and
+\fIproferr\fR, it is important for these values to be set correctly. A plot of
+chi versus magnitude should scatter around unity with little or no trend in chi
+with magnitude, except at the bright end where saturation effects may be
+present.
+
+Finally ALLSTAR computes the statistic sharp which estimates the intrinsic
+angular size of the measured object outside the atmosphere. Sharp is roughly
+defined as the difference between the square of the width of the object and the
+square of the width of PSF. Sharp has values close to zero for single stars,
+large positive values for blended doubles and partially resolved galaxies and
+large negative values for cosmic rays and blemishes.
+
+ALLSTAR implements a sophisticated star rejection algorithm. First of all any
+group of stars which is more than a certain size is not reduced. This maximum
+group size is specified by the \fImaxgroup\fR parameter in the DAOPARS task.
+Large groups may run into numerical precision problems during the fits, so
+users should increase this parameter with caution. ALLSTAR however, in
+contrast to NSTAR, attempts to subdivide large groups. If the group is too
+dense to reduce in size, ALLSTAR throws out the faintest star in the group
+and tries to rereduce it. If two stars in a group have centroids separated
+by a critical distance currently set arbitrarily to 0.37 * the FWHM of the
+stellar core and their photocentric position and combined magnitude is assigned
+to the brighter of the two and the fainter is eliminated. Any star which
+converges to magnitude 12.5 magnitudes greater than the magnitude of the PSF
+is considered to be non-existent and eliminated from the group.
+
+After iteration 5, if the faintest star in the group has a brightness less
+than one sigma above zero it is eliminated. After iteration 10 if the faintest
+star in the group has a brightness less than 1.5 sigma above zero it is
+eliminated. After iteration 15, or whenever the solutions has converged
+whichever comes first, if the faintest star in the group has a brightness less
+than 2.0 sigma above zero it is eliminated. After iterations 5, 10 and 15 if
+two stars are separated by more than 0.37 * FWHM and less than 1.0 * FWHM and
+if the fainter of the two is more uncertain than 1.0, 1.5 or 2.0 sigma
+respectively the fainter one is eliminated.
+
+ALLSTAR replaces the functionality of the GROUP, GRPSELECT, NSTAR and SUBSTAR
+task. However the user has little control over the grouping process and does
+not know at the end which stars were fit together. The grouping process is
+dynamic, as the groups are recomputed after each iteration, and stars can be
+fit and leave the group at any point after the fourth iteration. Therefore the
+quality of the fits may vary over the image as a function of crowding in an
+unknown way. However ALLSTAR is in most cases the routine of choice. NSTAR
+is the task of choice when a user wants to maintain control over the
+composition of the stellar groups.
+
+.ih
+OUTPUT
+
+If \fIverbose\fR = yes, a single line is output to the terminal for each star
+fit or rejected. Full output is written to \fIallstarfile\fR and \fIrejfile\fR.
+At the beginning of these two files a header listing the current values of the
+parameters is written. For each star fit/rejected the following quantities are
+written to the output file.
+
+.nf
+ id xcenter ycenter mag merr msky niter sharpness chi
+ pier perr
+.fi
+
+Id is the id number of the star. Xcenter and ycenter are the fitted coordinates
+in pixels. Mag and merr are the fitted magnitude and magnitude error
+respectively. Msky is the individual sky value for the star. Niter is the
+number of iterations it took to fit the star and sharpness and chi are the
+sharpness and goodness of fit statistic respectively. Pier and perror are the
+photometry error code and accompanying error message respectively.
+
+.ih
+ERRORS
+
+If no errors occur during the fitting process then pier is 0. Non-zero
+values of pier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 1 # The star is in a group too large to fit
+ 2 # The sky is undefined
+ 3 # There are too few good pixels to fit the star
+ 4 # The fit is singular
+ 5 # The star is too faint
+ 6 # The star has merged with a brighter star
+ 7 # The star is off the image
+.fi
+
+.ih
+EXAMPLES
+
+1. Fit the PSF to a list stars in the test image dev$ypix. Good stars for
+making the PSF model can be found at (442,410), (348,189), and (379,67).
+
+.nf
+ da> datapars.epadu = 14.0
+ da> datapars.readnoise = 75.0
+
+ ... set the gain and readout noise for the detector
+
+ da> daofind dev$ypix default fwhmpsf=2.5 sigma=5.0 threshold=20.0
+
+ ... answer verify prompts
+
+ ... find stars in the image
+
+ ... answer will appear in ypix.coo.1
+
+ da> phot dev$ypix default default annulus=10. dannulus=5. \
+ apertures = 3.0
+
+ ... answer verify prompts
+
+ ... do aperture photometry on the detected stars
+
+ ... answer will appear in ypix.mag.1
+
+ da> display dev$ypix 1
+
+ da> psf dev$ypix default "" default default default psfrad=11.0 \
+ fitrad=3.0 mkstars=yes display=imdr
+
+ ... verify the critical parameters
+
+ ... move the image cursor to a candidate star and hit the a key,
+ a plot of the stellar data appears
+
+ ... type ? for a listing of the graphics cursor menu
+
+ ... type a to accept the star, d to reject it
+
+
+ ... move to the next candidate stars and repeat the previous
+ steps
+
+ ... type l to list all the psf stars
+
+ ... type f to fit the psf
+
+ ... move cursor to first psf star and type s to see residuals,
+ repeat for all the psf stars
+
+ ... type w to save the PSF model
+
+ ... type q to quit, and q again to confirm
+
+ ... the output will appear in ypix.psf.1.imh, ypix.pst.1 and
+ ypix.psg.1
+
+ da> allstar dev$ypix default default default default default
+
+ ... verify the prompts
+
+ ... the results will appear in ypix.als.1 and ypix.arj.1
+
+ da> pdump ypix.als.1 sharpness,chi yes | graph
+
+ ... plot chi versus sharpness, the stars should cluster around
+ sharpness = 0.0 and chi = 1.0, note that the frame does
+ not have a lot of stars
+
+ da> display ypix.sub.1 2
+
+ ... note that the psf stars subtract reasonably well but other
+ objects which are not stars don't
+.fi
+
+
+2. Repeat example 1 but refit the sky using an annulus with an inner sky
+radius of 3.0 and an outer radius of 15.0.
+
+.nf
+ da> allstar dev$ypix default default default default default fitsky+ \
+ sannulus=3.0 wsannulus=12.0
+
+ ... verify the prompts
+
+ ... the results will appear in ypix.als.2 and ypix.arj.2
+
+ da> pdump ypix.als.2 sharpness,chi yes | graph
+
+ ... plot chi versus sharpness, the stars should cluster around
+ sharpness = 0.0 and chi = 1.0, note that the frame does
+ not have a lot of stars
+
+ da> display ypix.sub.2 2
+
+ ... note that the psf stars subtract reasonably well but other
+ objects which are not stars don't
+.fi
+
+
+
+3. Run allstar on a section of the input image using the group file and PSF
+model derived in example 1 for the parent image and writing the results
+in the coordinate system of the parent image.
+
+.nf
+ da> allstar dev$ypix[150:450,150:450] default default default default \
+ default wcsin=tv wcspsf=tv wcsout=tv
+
+ ... answer the verify prompts
+
+ ... fit the stars
+
+ ... the results will appear in ypix.als.3 and ypix.arj.3
+
+ da> display dev$ypix[150:450,150:450] 1
+
+ ... display the image
+
+ da> pdump ypix.als.3 xc,yc yes | tvmark 1 STDIN col=204
+
+ ... mark the stars on the original image
+
+ da> display ypix.sub.3 2
+
+ ... display the subtracted image section
+
+.fi
+
+
+4. Run allstar exactly as in example 1 but submit the task to the background.
+Turn off verify and verbose.
+
+.nf
+ da> allstar dev$ypix default default default default default verbose- \
+ verify- &
+
+ ... the results will appear in ypix.als.4 and ypix.arj.4
+.fi
+
+
+4. Run ALLSTAR exactly as in example 3 but turn caching off.
+
+.nf
+ da> allstar m92 m92.grp.1 m92.psf.1 default "" default verb+ veri- \
+ cache- > allstar.out &
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+datapars,daopars,peak,nstar
+.endhelp
diff --git a/noao/digiphot/daophot/doc/centerpars.hlp b/noao/digiphot/daophot/doc/centerpars.hlp
new file mode 100644
index 00000000..7b461cb1
--- /dev/null
+++ b/noao/digiphot/daophot/doc/centerpars.hlp
@@ -0,0 +1,207 @@
+.help centerpars May00 noao.digiphot.daophot
+.ih
+NAME
+centerpars -- edit the centering algorithm parameters
+.ih
+USAGE
+centerpars
+.ih
+PARAMETERS
+.ls calgorithm = "none"
+The centering algorithm. The "gauss" and "ofilter" centering algorithms
+depend critically on the value of the fwhmpsf parameter in the DATAPARS task.
+The centering options are:
+.ls none
+The initial positions are assumed to be the true centers. Users should
+select this option if the initial centers are known to be accurate,
+e.g. they were computed by DAOFIND task.
+.le
+.ls centroid
+The object centers are determined by computing the intensity weighted means
+of the marginal profiles in x and y. Centroid is the recommended centering
+algorithm for users running PHOT interactively and selecting objects
+with the image display cursor, or when the input coordinates may be inaccurate.
+.le
+.ls gauss
+The object centers are computed by fitting a Gaussian of fixed fwhmpsf,
+specified by the DATAPARS fwhmpsf parameter, to the marginal profiles in
+x and y using non-linear least squares techniques.
+.le
+.ls ofilter
+The object centers are computed using optimal filtering techniques,
+a triangular weighting function of half width equal to fwhmpsf as
+specified by the DATAPARS fwhmpsf parameter, and the marginal distributions
+in x and y.
+.le
+.le
+.ls cbox = 5.0 (scale units)
+The width of the subraster used for object centering in units of the
+scale parameter. Cbox needs to be big enough to include sufficient
+pixels for centering but not so large as to include a lot of noise.
+Reasonable starting values are 2.5-4.0 * FWHM of the PSF.
+.le
+.ls cthreshold = 0.0 (sigma units)
+xels cthreshold * sigma above (emission features) or below (absorption
+features) the data minimum or maximum respectively are used by the centering
+algorithms where sigma is equal to the value of the DATAPARS sigma parameter.
+features) the data minimum or maximum are used by the centering algorithms.
+DAOPHOT users should leave this value at 0.0 which invokes the appropriate
+default thresholding technique for each centering algorithm. Setting
+cthreshold to INDEF turns off thresholding altogether for all the centering
+algorithms.
+.le
+.ls minsnratio = 1.0
+The minimum signal to noise ratio for object centering. If the estimated signal
+to noise ratio is less than minsnratio the computed center will be returned
+with an error flag.
+.le
+.ls cmaxiter = 10
+The maximum number of iterations performed by the centering algorithm.
+All the centering algorithms use this parameter.
+.le
+.ls maxshift = 1.0 (scale units)
+The maximum permissible shift of the center with respect to the initial
+coordinates in units of the scale parameter. If the shift produced by the
+centering algorithms is larger than maxshift, the computed center is returned
+with an error flag.
+.le
+.ls clean = no
+Symmetry-clean the centering subraster before centering? DAOPHOT users should
+leave clean set to "no".
+.le
+.ls rclean = 1.0 (scale units)
+The cleaning radius for the symmetry-clean algorithm in units of
+the scale parameter.
+.le
+.ls rclip = 2.0 (scale units)
+The clipping radius for the symmetry-clean algorithm in units of
+the scale parameter.
+.le
+.ls kclean = 3.0 (sigma)
+The number of standard sky deviations for the symmetry-clean algorithm.
+.le
+.ls mkcenter = no
+Mark the fitted centers on the displayed image ?
+.le
+.ih
+DESCRIPTION
+
+The centering algorithm parameters control the action of the centering
+algorithms. The default parameters values have been proven to produce
+reasonable results in the majority of cases. Several of the centering
+parameters are defined in terms of the DATAPARS parameter \fIscale\fR,
+the scale of the image, and \fIsigma\fR the standard deviation of
+the sky pixels.
+
+For each object to be measured a subraster of data \fIcbox\fR / \fIscale\fR
+pixels wide around the initial position supplied by the user is extracted
+from the IRAF image. If scale is defined in units of the number
+the half-width half-maximum of the psf per pixel, then a single value of
+cbox can be used for centering objects in images with different psfs.
+
+If \fIclean\fR is "yes" the symmetry-clean algorithm is applied to the
+centering subraster prior to centering. The cleaning algorithm attempts
+to correct defects in the centering subraster by assuming that the image
+is radially symmetric and comparing pixels on opposite sides of the center
+of symmetry. The center of symmetry is assumed to be the maximum pixel
+in the subraster, unless the maximum pixel is more than \fImaxshift /
+scale\fR from the initial center, in which case the initial center is used
+as the center of symmetry. Pixels inside the cleaning radius are not edited.
+Pairs of pixels in the cleaning region, r > \fIrclean\fR / \fIscale\fR
+and r <= \fIrclip\fR / \fIscale\fR and diametrically opposed about the
+center of symmetry are tested for equality. If the difference between the
+pixels is greater than \fIkclean * sigma\fR, the larger value is replaced
+by the smaller. In the cleaning region the sigma is determined by the
+noise model assumed for the data. Pairs of pixels in the clipping region,
+r > \fIrclip\fR / \fIscale\fR are tested in the same manner as those in
+the cleaning region. However the sigma employed is the sigma of the
+sky background. DAOPHOT users should leave clean set to "no".
+
+
+
+
+New centers are computed using the centering algorithm specified by
+\fIcalgorithm\fR, the data specified by \fIcbox / scale\fR, and pixels
+that are some threshold above (below) an estimate of the local minimum
+(maximum). \fICthreshold\fR values of 0.0, a positive number, and INDEF
+invoke the default thresholding algorithm, a threshold equal to the
+local minimum (maximum) plus (minus) \fIdatapars.sigma * cthreshold\fR,
+and a threshold exactly equal to the local minimum (maximum) respectively.
+
+After thresholding the signal to noise ratio of the subraster is estimated.
+If the SNR < \fIminsnratio\fR the new center is still computed but an error
+flag is set.
+
+The default centering algorithm is \fInone\fR is which case the initial
+centers are assumed to be accurate and no recentering is done.
+
+The simplest centering algorithm is \fIcentroid\fR. Centroid computes the
+intensity weighted mean and mean error of the centering box x and y marginal
+distributions using points in the marginal arrays above (below) the minimum
+(maximum) data pixel plus (minus) a threshold value. The threshold value is
+either the mean, \fIdatapars.sigma * cthreshold\fR above (below) the local
+minimum (maximum) if \fIcthreshold\fR is greater than zero, or zero above
+(below) the local minimum (maximum) if \fIcthreshold\fR is INDEF. The centroid
+algorithm is similar to that by the old KPNO Mountain Photometry Code.
+Note that centroid is the only centering algorithm which does not depend
+on the value of \fIdatapars.fwhmpsf\fR.
+
+The centering algorithm \fIgauss\fR computes the new centers by fitting a
+1D Gaussian function to the marginal distributions in x and y using a
+fixed fwhmpsf set by \fIdatapars.fwhmpsf\fR. Initial guesses for the fit
+parameters are derived from the data. The gauss algorithm iterates until
+a best fit solution is achieved.
+
+The final centering algorithm choice \fIofilter\fR employs a variation of the
+optimal filtering technique in which the profile is simulated by a triangle
+function of width \fIdatapars.fwhmpsf\fR.
+
+The default thresholding algorithm for all centering algorithms other
+than "centroid" is no thresholding.
+
+If the computed shift in either coordinate > \fImaxshift\fR / \fIscale\fR,
+the new center is returned but an error flag is set.
+
+
+1. List the centering parameters.
+
+.nf
+ da> lpar centerpars
+.fi
+
+2. Edit the centering parameters.
+
+.nf
+ da> centerpars
+.fi
+
+3. Edit the CENTERPARS parameters from with the PHOT task.
+
+.nf
+ da> epar phot
+
+ ... edit a few phot parameters
+
+ ... move to the centerpars parameter and type :e
+
+ ... edit the centerpars parameters and type :wq
+
+ ... finish editing the phot parameters and type :wq
+.fi
+
+4. Save the current CENTERPARS parameter set in a text file ctrnite1.par.
+This can also be done from inside a higher level task as in the
+above example.
+
+.nf
+ da> epar centerpars
+
+ ... type ":w ctrnite1.par" from within epar
+.fi
+.ih
+BUGS
+
+.ih
+SEE ALSO
+epar,lpar,datapars,phot
+.endhelp
diff --git a/noao/digiphot/daophot/doc/daoedit.hlp b/noao/digiphot/daophot/doc/daoedit.hlp
new file mode 100644
index 00000000..fa3ed38d
--- /dev/null
+++ b/noao/digiphot/daophot/doc/daoedit.hlp
@@ -0,0 +1,164 @@
+.help daoedit May00 noao.digiphot.daophot
+.ih
+NAME
+daoedit -- edit the daophot package parameters interactively
+.ih
+USAGE
+daoedit image
+.ih
+PARAMETERS
+.ls image
+.le
+.ls icommands = ""
+The image display cursor or image cursor commands file.
+.le
+.ls gcommands = ""
+The graphics cursor or graphics cursor commands file.
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default caching is
+disabled.
+.le
+.ls graphics = ")_.graphics"
+The standard graphics device.
+.le
+.ls display = ")_.display"
+The standard display device.
+.le
+.ih
+DESCRIPTION
+
+DAOEDIT is a general purpose tool for interactively examining and editing
+the DAOPHOT algorithm parameters located in the parameter sets DATAPARS,
+FINDPARS, CENTERPARS, FITSKYPARS, PHOTPARS, and DAOPARS. These five parameter
+sets can be listed, edited, and/or unlearned as a group from within DAOEDIT
+using the IRAF LPAR, EPAR and UNLEARN utilities. Any parameter in each of
+these five parameter sets can be examined or edited individual using a simple
+command. Parameters which are defined in terms of radial distance from the
+center of a star or in terms of image counts can be examined and edited
+interactively using radial profile plots and the graphics cursor.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If caching
+is enabled the first data measurement will appear to take a long time as the
+entire image must be read in before the measurement is actually made. All
+subsequent measurements will be very fast because DAOEDIT is accessing memory
+not disk. The point of caching is to speed up random image access by making
+the internal image i/o buffers the same size as the image itself. At present
+there is no point in enabling caching for images that are less than or equal
+to 524288 bytes, i.e. the size of the test image dev$ypix, as the default image
+ i/o buffer is exactly that size. However if the size of dev$ypix is doubled by
+ converting it to a real image with the chpixtype task then the effect of
+caching in interactive is can be quite noticeable if measurements of objects
+in the top and bottom halves of the image are alternated.
+
+.ih
+CURSOR COMMANDS
+
+.nf
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+a Estimate center, sky, skysigma, fwhmpsf and magnitude of a star
+r Plot the radial profile of a star and its integral
+i Set selected parameters interactively using a radial profile plot
+g Toggle between image and graphics cursor
+x Toggle the radial profile plot between pixel and scale units
+y Toggle the radial profile plot between counts and normal units
+q Quit task
+
+ Colon Commands
+
+:lparam/eparam/unlearn pset List/edit/unlearn the named pset
+:parameter [value] List or set an individual pset parameter
+
+
+ Psets
+
+datapars The data dependent parameters
+findpars The daofind task object detection parameters
+centerpars The phot task centering algorithm parameters
+fitskypars The phot task sky fitting algorithm parameters
+photpars The phot task photometry algorithm parameters
+daopars The psf fitting algorithm parameters
+
+
+The following commands are available from within the interactive setup
+menu.
+
+
+ Interactive Daoedit Setup Menu
+
+? Print help
+spbar Mark/verify critical parameters (f, s, a, d, r, w, b)
+q Quit
+
+f Mark/verify the fwhm of the psf on the radial profile plot
+s Mark/verify the sky sigma on the radial profile plot
+l Mark/verify the minimum good data value on the radial profile plot
+u Mark/verify the maximum good data value on the radial profile plot
+
+c Mark/verify the centering box half-width on the radial profile plot
+n Mark/verify the cleaning radius on the radial profile plot
+p Mark/verify the clipping radius on the radial profile plot
+
+a Mark/verify the inner sky annulus radius on the radial profile plot
+d Mark/verify the width of the sky annulus on the radial profile plot
+g Mark/verify the sky region growing radius on the radial profile plot
+
+r Mark/verify the photometry aperture(s) on the radial profile plot
+w Mark/verify the psf function radius on the radial profile plot
+b Mark/verify the psf fitting radius on the radial profile plot
+
+.fi
+
+.ih
+EXAMPLES
+
+1. Setup the daophot package parameters interactively for the image m92.
+This example assumes that the parameters are all initially at their
+default values.
+
+.nf
+ da> display dev$ypix 1
+ da> daoedit dev$ypix
+
+ ... type :e datapars to edit the data dependent parameters
+ ... leave scale at 1.0 and datamin at INDEF but set the
+ datamax, readnoise, epadu, exposure, airmass, filter,
+ and obstime parameters to appropriate values
+ ... type :l datapars to check the results of the editing
+
+ ... type :e findpars to check the object detection parameters
+ ... change the findpars threshold parameter from 4.0 to 5.0
+ using the command :threshold 5.0
+
+ ... type i to enter the interactive setup menu
+ set the fwhmpsf, sigma, inner radius of the sky annulus,
+ width of the sky annulus, photometry aperture(s), psf
+ radius, and fitting radius using the radial profile
+ plot and graphics cursor
+
+ ... select a bright non-saturated star and check that its
+ radial profile is normal using the r keystroke command
+ ... note the value of the standard deviation of the sky
+ background written in the plot header
+ ... set the datapars sigma parameter to this value using
+ the command :sigma <value>
+
+ ... check the data definition, centering, sky fitting,
+ photometry, and psf fitting parameters with the commands
+ :l datapars, :l centerpars, :l fitskypars, :l photpars,
+ and :l daopars
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+datapars,findpars,centerpars,fitskypars,photpars,daopars,setimpars
+.endhelp
diff --git a/noao/digiphot/daophot/doc/daofind.hlp b/noao/digiphot/daophot/doc/daofind.hlp
new file mode 100644
index 00000000..a2b1c3f8
--- /dev/null
+++ b/noao/digiphot/daophot/doc/daofind.hlp
@@ -0,0 +1,601 @@
+.help daofind May00 noao.digiphot.daophot
+.ih
+NAME
+daofind -- automatically detect objects in images
+.ih
+USAGE
+daofind image output
+.ih
+PARAMETERS
+.ls image
+The list of images in which objects are to be detected.
+.le
+.ls output
+The name of the results file or the results directory. If output is
+"default", "dir$default" or a directory specification then a results file
+name of the form dir$root.extension.version is constructed, where
+dir is the directory, root is the root image name, extension is "coo"
+and version is the next available version number for the file. If the
+output string is undefined then no output file is created. One output
+file is created for every input image.
+.le
+.ls starmap = ""
+The name of the image prefix and/or directory where the density enhancement
+image will be stored. If starmap is undefined or a directory,
+DAOFIND will create a temporary image which is deleted on exit from
+the program. Otherwise starmap is prefixed to the image name
+and the density enhancement image will be saved for use in a subsequent
+run of DAOFIND.
+.le
+.ls skymap = ""
+The name of the image prefix and/or directory where the mean density
+image will be stored. If skymap is undefined or a directory, no mean density
+image is created. Otherwise skymap is prefixed to the image name
+and the mean density image will be saved on disk. Skymap is not used by
+the DAOFIND algorithms, but may be used by the user as a check on DAOFIND,
+since the sum of starmap and skymap is a type of best fit to the original
+image.
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters. The critical
+parameters \fIfwhmpsf\fR and \fIsigma\fR are located here. If \fIdatapars\fR
+is undefined then the default parameter set in the user's uparm directory is
+used.
+.le
+.ls findpars = ""
+The name of the file containing the object detection parameters. The
+parameter \fIthreshold\fR is located here. If findpars is undefined then
+the default parameter set in the user's uparm directory is used.
+.le
+.ls boundary = "nearest"
+The type of boundary extension. The choices are:
+.ls nearest
+Use the value of the nearest boundary pixel.
+.le
+.ls constant
+Use a constant value.
+.le
+.ls reflect
+Generate a value by reflecting around the boundary.
+.le
+.ls wrap
+Generate a value by wrapping around to the other side of the image.
+.le
+.le
+.ls constant = 0
+The constant for constant boundary extension.
+.le
+.ls interactive = no
+Interactive or batch mode?
+.le
+.ls icommands = ""
+The image display cursor or image cursor command file.
+.le
+.ls gcommands = ""
+The graphics cursor or graphics cursor command file.
+.le
+.ls wcsout = ")_.wcsout"
+The coordinate system of the output coordinates written to \fIoutput\fR. The
+image header coordinate system is used to transform from the internal "logical"
+pixel coordinate system to the output coordinate system. The output coordinate
+system options are "logical", "tv", and "physical". The image cursor coordinate
+ system is assumed to be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+The wcsout parameter defaults to the value of the package parameter of the same
+ name. The default values of the package parameters wcsin and wcsout are
+"logical" and "logical" respectively.
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default caching is
+disabled.
+.le
+.ls verify = ")_.verify"
+Automatically confirm the critical parameters when running in non-interactive
+mode ? Verify may be set to the daophot package parameter value (the default),
+"yes", or "no".
+.le
+.ls update = ")_.update"
+Automatically update the parameters when running in non-interactive mode if
+verify is "yes"? Update may be set to the daophot package parameter value
+(the default), "yes", or "no".
+.le
+.ls verbose = ")_.verbose"
+Print out information about the progress of the task in non-interactive mode.
+Verbose may be set to the daophot package parameter value (the default), "yes",
+or "no".
+.le
+.ls graphics = ")_.graphics"
+The standard graphics device. Graphics may be set to the apphot package
+parameter value (the default), "yes", or "no".
+.le
+.ls display = ")_.display"
+The standard image display device. Display may be set to the apphot package
+parameter value (the default), "yes", or "no". By default graphics overlay is
+disabled. Setting display to one of "imdr", "imdg", "imdb", or "imdy" enables
+graphics overlay with the IMD graphics kernel. Setting display to "stdgraph"
+enables DAOFIND to work interactively from a contour plot.
+.le
+
+.ih
+DESCRIPTION
+
+DAOFIND searches the IRAF images \fIimage\fR for local density maxima,
+with a full-width half-maxima of \fIdatapars.fwhmpsf\fR, and a peak amplitude
+greater than \fIfindpars.threshold\fR * \fIdatapars.sigma\fR above the local
+background, and writes a list of detected objects in the file \fIoutput\fR.
+The detected objects are also listed on the standard output if the program is
+running in interactive mode or if the \fIverbose\fR switch is enabled in
+non-interactive mode.
+
+The coordinates written to \fIoutput\fR are in the coordinate
+system defined by \fIwcsout\fR. The options are "logical", "tv",
+and "physical". The simplest default is the "logical" system. Users
+wishing to correlate the output coordinates of objects measured in
+image sections or mosaic pieces with coordinates in the parent
+image must use the "tv" or "physical" coordinate systems.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input and output image pixels are cached in memory. If
+caching is enabled and DAOFIND is run interactively the first measurement
+will appear to take a long time as the entire image must be read in before the
+measurement is actually made. All subsequent measurements will be very fast
+because DAOFIND is accessing memory not disk. The point of caching is to speed
+up random image access by making the internal image i/o buffers the same size
+as the image itself. However if the input object lists are sorted in row order
+and sparse caching may actually worsen not improve the execution time. Also at
+present there is no point in enabling caching for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of caching in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halves of the image are alternated.
+
+DAOFIND can be run either interactively or in batch mode by setting the
+parameter \fIinteractive\fR. In interactive mode the user can examine,
+adjust and save algorithm parameters, and fit or refit the entire list
+with the chosen parameter set. The \fIverify\fR parameter can be used to
+automatically confirm the critical parameters \fIdatapars.fwhmpsf\fR and
+\fIdatapars.sigma\fR when running in non-interactive mode.
+
+
+.ih
+CURSOR COMMANDS
+
+.nf
+
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+v Verify critical parameters
+w Save the current parameters
+d Plot radial profile of star near cursor
+i Interactively set parameters using star near cursor
+f Find stars in the image
+spbar Find stars in the image and output results
+q Exit task
+
+
+ Colon Commands
+
+:show [data/find] List the parameters
+
+ Colon Commands
+
+# Image and file name parameters
+
+:image [string] Image name
+:output [string] Output file name
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Full width half maximum of psf (scale units)
+:emission [y/n] Emission feature (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good data value (counts)
+:datamax [value] Maximum good data value (counts)
+
+# Noise description parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per adu)
+:readnoise [value] Readout noise (electrons)
+
+# Observation parameters
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Exposure time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observation (time units)
+
+# Object detection parameters
+
+:nsigma [value] Size of Gaussian kernel (sigma)
+:threshold [value] Detection intensity threshold (counts)
+:ratio [value] Sigmay / sigmax of Gaussian kernel
+:theta [value] Position angle of Gaussian kernel
+:sharplo [value] Lower bound on sharpness
+:sharphi [value] Upper bound on sharpness
+:roundlo [value] Lower bound on roundness
+:roundhi [value] Upper bound on roundness
+
+# Plotting and marking commands
+
+:mkdetections [y/n] Mark detections on the image display
+
+
+
+The following commands are available from inside the interactive setup menu.
+
+
+ Interactive Daofind Setup Menu
+
+ v Mark and verify critical daofind parameters (f,s)
+
+ f Mark and verify the full-width half-maximum of the psf
+ s Mark and verify the standard deviation of the background
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
+
+.fi
+
+.ih
+ALGORITHMS
+
+DAOFIND approximates the stellar point spread function with an elliptical
+Gaussian function, whose sigma along the semi-major axis is 0.42466 *
+\fIdatapars.fwhmpsf\fR / \fIdatapars.scale\fR pixels, semi-minor to semi-major
+axis ratio is \fIratio\fR, and major axis position angle is \fItheta\fR.
+Using this model, a convolution kernel, truncated at \fInsigma\fR sigma,
+and normalized so as to sum to zero, is constructed.
+
+The density enhancement image \fIstarmap\fR is computed by convolving the input
+image with the Gaussian kernel. This operation is mathematically equivalent to
+fitting, in the least-squares sense, the image data at each point with a
+truncated, lowered elliptical Gaussian function. After convolution each point
+in \fIstarmap\fR contains as estimate of the amplitude of the best fitting
+Gaussian function at that point. Each point in \fIskymap\fR, if the user
+chooses to compute it, contains an estimate of the best fitting sky value
+at that point.
+
+After image convolution , DAOFIND steps through \fIstarmap\fR searching
+for density enhancements greater than \fIfindpars.threshold\fR *
+\fIdatapars.sigma\fR, and brighter than all other density enhancements within
+a semi-major axis of 0.42466 \fIfindpars.nsigma\fR * \fIdatapars.fwhmpsf\fR.
+As the program selects candidates, it computes three shape characteristics,
+sharpness and 2 estimates of roundness. The sharpness statistic measures the
+ratio of, the difference between the height of the central pixel and the mean
+of the surrounding non-bad pixels, to the height of the best fitting Gaussian
+function at that point. The first roundness characteristic computes the ratio
+of a measure of the bilateral symmetry of the object to a measure of the
+four-fold symmetry of the object. The second roundness statistic measures the
+ratio of, the difference in the height of the best fitting Gaussian function
+in x minus the best fitting Gaussian function in y, over the average of the
+best fitting Gaussian functions in x and y. The limits on these parameters
+\fIfindpars.sharplo\fR, \fIfindpars.sharphi\fR \fIfindpars.roundlo\fR, and
+\fIfindpars.roundhi\fR, are set to weed out non-astronomical objects and
+brightness enhancements that are elongated in x and y respectively.
+
+Lastly the x and y centroids of the detected objects are computed by estimating
+the x and y positions of the best fitting 1D Gaussian functions in x and y
+respectively, a rough magnitude is estimated by computing the ratio of the
+amplitude of the best fitting Gaussian at the object position to
+\fIfindpars.threshold\fR * \fIdatapars.sigma\fR, and the object is added to
+the output coordinate file.
+
+
+.ih
+OUTPUT
+
+In interactive mode or in non-interactive with the verbose switch turned on
+the following quantities are written to the terminal as each object is
+detected.
+
+.nf
+ xcenter ycenter mag sharpness sround ground id
+
+ where
+
+ mag = -2.5 * log10 (peak density / detection threshold)
+.fi
+
+
+The object centers are in pixels and the magnitude estimate measures the
+ratio of the maximum density enhancement to the detection threshold.
+Sharpness is typically around .5 to .8 for a star with a fwhmpsf similar to
+the pattern star. Both sround and ground are close to zero for a truly
+round star. Id is the sequence number of the star in the list.
+
+In both interactive and batch mode the full output is written to the text
+file \fIoutput\fR. At the beginning of each file is a header, listing
+the current values of the parameters when the first stellar record was
+written. The parameters can subsequently be altered.
+
+
+.ih
+EXAMPLES
+
+1. Run daofind on the test image dev$ypix.
+
+.nf
+ da> daofind dev$ypix default fwhmpsf=2.5 sigma=5.0 threshold=20
+
+ ... answer the verify prompts
+
+ ... the output will appear in ypix.coo.1
+.fi
+
+
+2. Run daofind interactively on dev$ypix using the image display
+and image display cursor. Set the fwhmpsf and sigma parameters
+with the graphics cursor, radial profile plot, and the interactive
+setup key i.
+
+.nf
+ da> display dev$ypix 1 fi+
+
+ ... display the image
+
+ da> daofind dev$ypix default interactive+
+
+ ... type ? to see help screen
+
+ ... move display cursor to a star
+ ... type i to enter the interactive setup menu
+ ... enter maximum radius in pixels of the radial profile or
+ accept default with a CR
+ ... type v to enter the default setup menu
+ ... set the fwhmpsf and sigma using the graphics cursor and the
+ radial profile plot
+ ... typing <CR> leaves the parameters at their default values
+ ... type q to quit setup menu
+
+ ... type the v key to verify the critical parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... type the space bar to detect stars in the image
+
+ ... a 1 line summary of the answers will appear on the standard
+ output for each star measured
+
+ ... type q to quit and q again to confirm the quit
+
+ ... full output will appear in the text file ypix.coo.2
+
+.fi
+
+
+3. Run daofind interactively on a single image using a contour plot in place
+of the image and the graphics cursor in place of the image cursor.
+This option is only useful for those (now very few) users who have access to
+a graphics terminal but not to an image display server. Set the fwhmpsf and
+sigma parameters with the graphics cursor and radial profile plot and the
+interactive setup key i.
+
+.nf
+ da> show stdimcur
+
+ ... record the default value of stdimcur
+
+ da> set stdimcur = stdgraph
+
+ ... define the image cursor to be the graphics cursor
+
+ da> contour dev$ypix
+
+ ... make a contour plot of dev$ypix
+
+ da> contour dev$ypix >G ypix.plot1
+
+ ... store the contour plot of ypix in the file ypix.plot
+
+ da> daofind dev$ypix default display=stdgraph interactive+
+
+ ... type ? to see the help screen
+
+ ... move graphics cursor to a setup star
+ ... type i to enter the interactive setup menu
+ ... enter maximum radius in pixels of the radial profile or
+ accept the default with a CR
+ ... type v to enter the default setup menu
+ ... set the fwhmpsf and sigma using the graphics cursor and the
+ radial profile plot
+ ... typing <CR> leaves the parameters at their default values
+ ... type q to quit the setup menu
+
+ ... type the v key to confirm the critical parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... retype :.read ypix.plot1 to reload the contour plot
+
+ ... type the space bar to detect stars in the image
+
+ ... a 1 line summary of the answers will appear on the standard
+ output for each star measured
+
+ ... full output will appear in the text file ypix.coo.3
+
+ da> set stdimcur = <default>
+
+ ... reset the image cursor to its default value
+
+.fi
+
+
+4. Run DAOFIND interactively without using the image display cursor.
+
+.nf
+ da> show stdimcur
+
+ ... record the default value of stdimcur
+
+ da> set stdimcur = text
+
+ ... set the image cursor to the standard input
+
+ da> display dev$ypix 1
+
+ ... display the image
+
+ da> daofind dev$ypix default interactive+
+
+ ... type ? for help
+
+ ... type "442 409 101 i" in response to the image cursor query where
+ x and y are the coordinates of the star to be used as setup,
+ 101 is the default world coordinate system, and i enters the
+ interactive setup menu.
+ ... enter maximum radius in pixels of the radial profile or
+ type CR to accept the default
+ ... type v to enter the default setup menu
+ ... set the fwhmpsf and sigma using the graphics cursor and the
+ radial profile plot
+ ... typing <CR> leaves the parameters at their default values
+ ... type q to quit the setup menu
+
+ ... type the v key to verify the parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... type the space bar to detect stars in the image
+
+ ... a 1 line summary of the answers will appear on the standard
+ output for each star measured
+
+ ... type q to quit and q again to confirm
+
+ ... full output will appear in the text file ypix.coo.4
+
+ da> set stdimcur = <default>
+
+ ... reset the image cursor to its default value
+.fi
+
+
+5. Run daofind on a list of 3 images contained in the file imlist in batch mode.
+The program will ask the user to verify that the fwhmpsf and the threshold are
+correct before beginning execution.
+
+.nf
+ da> type imlist
+ dev$ypix
+ dev$wpix
+ dev$pix
+
+ da> daofind @imlist default
+
+ ... answer the verify prompts
+
+ ... the output will appear in ypix.coo.5, wpix.coo.1, pix.coo.1
+.fi
+
+
+6. Display and find stars in an image section. Write the output coordinates
+in the coordinate system of the parent image. Mark the detected stars on
+the displayed image.
+
+.nf
+ da> display dev$ypix[150:450,150:450] 1
+
+ ... display the image section
+
+ da> daofind dev$ypix[150:450,150:450] default wcsout=tv
+
+ ... answer the verify prompts
+
+ ... output will appear in ypix.coo.6
+
+ da> tvmark 1 ypix.coo.6 col=204
+.fi
+
+
+7. Repeat example 5 but submit the job to the background and turn off the
+verify and verbose switches.
+
+.nf
+ da> daofind @imlist default verify- verbose- &
+
+ ... the output will appear in ypix.coo.7, wpix.coo.2, pix.coo.2
+.fi
+
+
+8. Use an image cursor command file to drive the daofind task. The cursor
+command file shown below sets the fwhmpsf, sigma, and threshold parameters,
+located stars in the image, updates the parameter files, and quits the task.
+
+.nf
+ da> type cmdfile
+ : fwhmpsf 2.5
+ : sigma 5.0
+ : threshold 10.0
+ \040
+ w
+ q
+
+ da> daofind dev$ypix default icommands=cmdfile verify-
+
+ ... full output will appear in ypix.coo.8
+.fi
+
+
+.ih
+TIME REQUIREMENTS
+
+.ih
+BUGS
+
+It is currently the responsibility of the user to make sure that the
+image displayed in the frame is the same as that specified by the image
+parameter.
+
+Commands which draw to the image display are disabled by default.
+To enable graphics overlay on the image display, set the display
+parameter to "imdr", "imdg", "imdb", or "imdy" to get red, green,
+blue or yellow overlays and set the findpars mkdetections switch to
+"yes". It may be necessary to run gflush and to redisplay the image
+to get the overlays position correctly.
+
+.ih
+SEE ALSO
+datapars,findpars
+.endhelp
diff --git a/noao/digiphot/daophot/doc/daopars.hlp b/noao/digiphot/daophot/doc/daopars.hlp
new file mode 100644
index 00000000..80f340b6
--- /dev/null
+++ b/noao/digiphot/daophot/doc/daopars.hlp
@@ -0,0 +1,331 @@
+.help daopars May00 noao.digiphot.daophot
+.ih
+NAME
+daopars -- edit the daophot fitting parameters
+.ih
+USAGE
+daopars
+.ih
+PARAMETERS
+.ls function = "gauss"
+The functional form of the analytic component of the PSF model computed by the
+DAOPHOT PSF task. The better this function matches the true PSF, especially in
+the cores of the stars, the smaller the interpolation errors will be. The
+choices are the following.
+
+.ls gauss
+An elliptical Gaussian function aligned along the x and y axes of the
+input image.
+.le
+.ls moffat15
+An elliptical Moffat function with a beta parameter of 1.5.
+.le
+.ls moffat25
+An elliptical Moffat function with a beta parameter of 2.5.
+.le
+.ls lorentz
+An elliptical Lorentzian function with beta parameter of 1.0.
+.le
+.ls penny1
+A Gaussian core with Lorentzian wings function, where the Gaussian core may be
+tilted, but the Lorentzian wings are elongated along the x or y axes. The
+Lorentzian wings have a beta parameter of 1.0.
+.le
+.ls penny2
+A Gaussian core with Lorentzian wings function, where the Gaussian core and
+Lorentzian wings may be tilted in different directions. The Lorentzian wings
+have a beta parameter of 1.0.
+.le
+.ls auto
+The PSF task computes the analytic PSF model for each of the six analytic model
+PSFs in turn and selects the one that produces the smallest standard deviation
+for the model fit.
+.le
+.ls func1,func2,...
+The PSF task computes the analytic PSF model for each of a subset of the six
+defined functions in turn, and selects the one that produces the smallest
+standard deviation for the model fit.
+.le
+
+In general "gauss" is the best and most efficient choice for a well-sampled
+ground-based image, "lorentz" is best for old ST images, and "moffat15" or
+"moffat25" are best for under-sampled ground-based images.
+.le
+.ls varorder = 0
+The order of variability of the PSF model computed by the DAOPHOT PSF task.
+Varorder sets the number of look-up tables containing the deviations of the
+true PSF from the analytic model PSF that are computed by the model.
+.ls "-1"
+Only the analytic function specified by \fIfunction\fR is used to compute
+the PSF model. The PSF model is constant over the image.
+.le
+.ls "0"
+The analytic function and one look-up table are used to compute the
+PSF model. The PSF model is constant over the image.
+.le
+.ls "1"
+The analytic function and three look-up tables are used to compute the PSF
+model. The PSF model is linearly variable over the image, with terms
+proportional to 1, x and y.
+.le
+.ls "2"
+The analytic function and six look-up tables are used to compute the
+PSF model. The PSF model is quadratically variable over the image, with terms
+proportional to 1, x, y, x**2, xy, y**2.
+.le
+.le
+.ls nclean = 0
+The number of additional iterations the PSF task performs to compute the PSF
+look-up tables. If \fInclean\fR is > 0, stars which contribute deviant
+residuals to the PSF look-up tables in the first iteration, will be
+down-weighted in succeeding iterations.
+.le
+.ls saturated = no
+Use saturated stars to improve the signal-to-noise in the wings of the PSF
+model computed by the PSF task? This parameter should only be set to
+"yes" where there are too few high signal-to-noise unsaturated stars
+in the image to compute a reasonable model for the stellar profile wings.
+.le
+.ls matchrad = 3.0 (scale units)
+The tolerance in scale units for matching the stellar x and y centroids in the
+input photometry file with the image cursor position. Matchrad is currently
+used by the PSTSELECT and PSF tasks to match stars shown on the image display
+with stars in the photometry list.
+.le
+.ls psfrad = 11.0 (scale units)
+The radius of the circle in scale units within which the PSF model is defined.
+Psfrad should be a pixel or two larger than the radius at which the intensity
+of the brightest star of interest fades into the noise. Psfrad can never be
+set larger than the size of the PSF model but may set smaller in tasks
+like GROUP, ALLSTAR, SUBSTAR, and ADDSTAR.
+.le
+.ls fitrad = 3.0 (scale units)
+The fitting radius in scale units. Only pixels within the fitting radius of
+the center of a star will contribute to the fits computed by the PEAK, NSTAR
+and ALLSTAR tasks. For most images the fitting radius should be approximately
+equal to the FWHM of the PSF. Under severely crowded conditions a somewhat
+smaller value may be used in order to improve the fit. If the PSF is variable,
+the FWHM is very small, or sky fitting is enabled in PEAK and NSTAR on the
+other hand, it may be necessary to increase the fitting radius to achieve a
+good fit.
+.le
+.ls recenter = yes (peak, nstar, and allstar)
+Compute new positions as well as magnitudes for all the stars in the input
+photometry list?
+.le
+.ls fitsky = no (peak, nstar, and allstar)
+Compute new sky values for the stars in the input list (peak, nstar, allstar).
+If fitsky = "no", the PEAK, NSTAR, and ALLSTAR tasks compute a group sky value
+by averaging the sky values of the stars in the group. If fitsky = "yes",
+PEAK and NSTAR fit the group sky simultaneously with the positions and
+magnitudes. If fitsky = yes the ALLSTAR task computes new sky values for each
+star every third iteration by subtracting off the best current fit for the star
+and and estimating the median of the pixels in the annulus defined by
+\fIsannulus\fR and \fIwsannulus\fR. The new group sky value is the average of
+the new individual values.
+.le
+.ls groupsky = yes (nstar and allstar)
+If groupsky is "yes", then the sky value for every pixel which contributes to
+the fit is identical and equal to the mean of the sky values of all the stars
+in the group. If \fIgroupsky\fR is "no", then the sky value for every pixel
+which contributes to the fit is equal to the mean of the sky values of all the
+stars in the group for which that pixel is within one fitting radius.
+.le
+.ls sannulus = 0.0 (scale units, allstar)
+The inner radius of the sky annulus used by ALLSTAR to recompute the sky
+values.
+.le
+.ls wsannulus = 11 (scale units, allstar)
+The width of the sky annulus used by ALLSTAR to recompute the sky values.
+.le
+.ls flaterr=0.75 (percent, peak, nstar, allstar)
+The image flat-fielding error in percent used to compute the predicted
+errors of the fit.
+.le
+.ls proferr = 5.0 (percent, peak, nstar, allstar)
+The profile or interpolation fitting error in percent used to compute
+the predicted errors of the fit.
+.le
+.ls maxiter = 50 (peak, nstar, allstar)
+The maximum number of times that the PSF fitting tasks PEAK, NSTAR, and ALLSTAR
+will iterate on the PSF fit before giving up.
+.le
+.ls cliprange = 2.5, clipexp = 6.0 (peak, nstar, allstar)
+The parameters of the down-weighting scheme in the fitting code used to resist
+bad data. For values of clipexp greater than 1 a residual small compared to
+cliprange standard deviations does not have its weight significantly altered,
+one with exactly \fIcliprange\fR standard deviations is assigned half its
+normal weight, and large residuals are assigned weights which fall off as the
+standard deviation to the minus clipexp power. For normal applications users
+should leave these parameter at their default value.
+.le
+.ls critsnratio = 1.0 (group)
+The ratio of the model intensity of the brighter star computed at a distance of
+one fitting radius from the center of the fainter star, to the expected random
+error computed from the readout noise, gain and value of the PSF. The critical
+signal-to-noise ratio parameter is used to group stars. In general if a small
+value such as 0.1 divides all the stars in an image into groups less than
+\fImaxgroup\fR, then the expected random errors will determine the accuracy
+of the photometry. On the other hand if a value of critical overlap much
+greater than one is required to divide up the stars, crowding errors will
+dominate random errors. If a value of 1 is sufficient then crowding and
+random errors are roughly equivalent.
+.le
+.ls mergerad = INDEF (scale units, nstar, allstar)
+The critical separation in scale units between two objects for an object merger
+to be considered. Objects with separations > mergerad will not be merged; faint
+objects with separations <= mergerad will be considered for merging. The
+default value of mergerad is sqrt (2 *(PAR1**2 + PAR2**2)), where PAR1 and PAR2
+are the half-width at half-maximum along the major and minor axes of the psf
+model. Merging can be turned off altogether by setting mergerad to 0.0.
+.le
+.ls maxnstar = 10000 (pstselect, psf, group, allstar, substar)
+The initial star list buffer size. If there are more than maxnstar stars in the
+input photometry file buffer, DAOPHOT will resize the buffers as needed.
+The only limitation is the memory and configuration of the host computer.
+.le
+.ls maxgroup = 60 (nstar, allstar)
+The maximum numbers of stars that the multiple star fitting tasks NSTAR and
+ALLSTAR will fit simultaneously. NSTAR will not to fit groups large than
+maxgroup. ALLSTAR dynamically regroups the stars in large groups until the
+group is either maxgroup or smaller in size or becomes too dense to group,
+after which the faintest stars are rejected until the group is less than
+maxgroup ins size.
+.le
+
+.ih
+DESCRIPTION
+
+DAOPARS is a parameter set task which stores the DAOPHOT parameters
+required by all those DAOPHOT tasks which compute the PSF model, fit stars
+to the PSF model, or evaluate the PSF model.
+
+Typing DAOPARS on the terminal invokes the EPAR parameter editing task. The
+DAOPARS parameters may also be edited from within an EPAR command on task,
+for example PSF, which references them. The DAOPARS parameters may also
+be changed on the command line in the usual manner when any task which
+references them is executed.
+
+Any given set of DAOPARS parameters may stored in a text file along with
+the data being reduced by typing the :w command from within the EPAR task. If
+the user then sets the value of the \fIdaopars\fR parameter to the name of
+the file containing the stored parameter set, the stored parameters will be
+used instead of the default set in the uparm directory.
+
+.ih
+ALGORITHMS
+
+The functional forms of the analytic PSF functions are as follows. The
+A is simply an amplitude or normalization constant The Pn are parameters
+which are fit during the PSF model generation process.
+
+.nf
+ z = x ** 2 / p1 ** 2 + y ** 2 / p2 ** 2
+ gauss = A * exp (-0.5 * z)
+
+ z = x ** 2 / p1 ** 2 + y ** 2 / p2 ** 2 + x * y * p3
+ moffat15 = A / (1 + z) ** 1.5
+ moffat25 = A / (1 + z) ** 2.5
+
+ z = x ** 2 / p1 ** 2 + y ** 2 / p2 ** 2 + x * y * p3
+ lorentz = A / (1.0 + z)
+
+ z = x ** 2 / p1 ** 2 + y ** 2 / p2 ** 2
+ e = x ** 2 / p1 ** 2 + y ** 2 / p2 ** 2 + x * y * p4
+ penny1 = A * ((1 - p3) / (1.0 + z) + p3 * exp (-0.693*e))
+
+ z = x ** 2 / p1 ** 2 + y ** 2 / p2 ** 2 + p5 * x * y
+ e = x ** 2 / p1 ** 2 + y ** 2 / p2 ** 2 + x * y * p4
+ penny2 = A * ((1 - p3) / (1.0 + z) + p3 * exp (-0.693*e))
+.fi
+
+
+The predicted errors in the DAOPHOT photometry are computed per
+pixel as follows, where terms 1, 2, 3, and 4 represent the readout
+noise, the poisson noise, the flat-fielding error, and the interpolation
+error respectively. The quantities readnoise, epadu, I, M, p1, and p2
+are the readout noise in electrons, the gain in electrons per ADU,
+the pixel intensity in ADU, the PSF model intensity in ADU, the FWHM
+in x and the FWHM in y, both in pixels.
+
+.nf
+ error = sqrt (term1 + term2 + term3 + term4) (ADU)
+ term1 = (readnoise / epadu) ** 2
+ term2 = I / epadu
+ term3 = (.01 * flaterr * I) ** 2
+ term4 = (.01 * proferr * M / p1 / p2) ** 2
+.fi
+
+The radial weighting function employed by all the PSF fitting tasks is
+the following, where dx and dy are the distance of the pixel from the
+centroid of the star being fit.
+
+.nf
+ wtr = 5.0 / (5.0 + rsq / (1.0 - rsq))
+ rsq = (dx ** 2 + dy ** 2) / fitrad ** 2
+.fi
+
+The weight assigned each pixel in the fit then becomes the following.
+
+.nf
+ wtp = wtr / error ** 2
+.fi
+
+After a few iterations and if clipexp > 0, a clipping scheme to reject bad
+data is enabled. The weights of the pixels are recomputed as follows.
+
+.nf
+ wt = wtp / (1.0 + (residual / error / chiold /
+ cliprange) ** clipexp)
+.fi
+
+Pixels having a residual of cliprange sigma will have their weight reduced
+by half.
+
+.ih
+EXAMPLES
+
+1. Print the DAOPARS task parameters.
+
+.nf
+ da> lpar daopars
+.fi
+
+2. Edit the DAOPARS parameters.
+
+.nf
+ da> daopars
+.fi
+
+3. Edit the DAOPARS parameters from with the PSF task.
+
+.nf
+ da> epar psf
+
+ ... edit a few psf parameters
+
+ ... move to the daopars parameter and type :e
+
+ ... edit the daopars parameters and type :wq
+
+ ... finish editing the psf parameters and type :wq
+.fi
+
+4. Save the current DAOPARS parameter set in a text file daonite1.par.
+ This can also be done from inside a higher level task as in the
+ above example.
+
+.nf
+ da> epar daopars
+
+ ... type ":w daonite1.par" from within epar
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+pstselect,psf,peak,group,nstar,allstar,substar,addstar,setimpars
+.endhelp
diff --git a/noao/digiphot/daophot/doc/daotest.hlp b/noao/digiphot/daophot/doc/daotest.hlp
new file mode 100644
index 00000000..e7d455ae
--- /dev/null
+++ b/noao/digiphot/daophot/doc/daotest.hlp
@@ -0,0 +1,89 @@
+.help daotest Dec92 noao.digiphot.daophot
+.ih
+NAME
+daotest -- run basic tests on the daophot package tasks
+.ih
+USAGE
+daotest imname
+.ih
+PARAMETERS
+.ls imname
+The root name of the output test images. The input test image is stored in
+fits format in the DAOPHOT package test directory. If the image already exists
+DAOTEST will exit with a warning message.
+.le
+.ls daologfile = ""
+The name of the output log file. By default all the output image header
+listings and photometry file output is logged in a file
+called \fI"imname.log"\fR. If the log file already exists DAOTEST will
+exit with a warning message.
+.le
+.ls daoplotfile = ""
+The name of the output plot file. By default all the graphics output is
+logged in a file called \fI"imname.plot"\fR. If the plot file already exists
+DAOTEST will exit with a warning message.
+.le
+.ih
+DESCRIPTION
+DAOTEST is a simple script which exercises each of the major tasks in the
+DAOPHOT package in turn. At startup DAOTEST reads a small fits image stored
+in the DAOPHOT test subdirectory and creates the image \fIimname\fR in
+the user's working directory. DAOTEST initializes the DAOPHOT package by
+returning
+all the parameters to their default state, runs each of the DAOPHOT
+tasks in non-interactive mode, spools the text output to the file
+\fIdaologfile\fR, the graphics output from the PSF task to the plot
+metacode file \fIapplotfile\fR, and the image output from PSF, SUBSTAR
+and ADDSTAR to \fIimname.psf.1\fR, \fIimname.sub.1\fR, and \fIimname.add.1\fR
+respectively.
+.ih
+EXAMPLES
+
+1. Check to see that all the DAOPHOT tasks are functioning correctly.
+.nf
+ da> daophot
+
+ ... load the daophot package
+
+ da> daotest testim
+
+ ... run the test script
+
+ da> lprint testim.log
+
+ ... print the text output
+
+ da> gkidir testim.plot
+
+ ... list the contents of the plot file
+
+ da> gkiextract testim.plot 1-N | stdplot
+
+ ... send the plots to the plotter
+
+ da> display testim 1
+
+ ... display the original image
+
+ da> surface testim.psf.1
+
+ ... make a surface plot of the psf look-up table
+
+ da> display testim.sub.1 1
+
+ ... display the image with all the stars fitted by ALLSTAR
+ subtracted out
+
+ da> display testim.add.1 1
+
+ ... display the image containing three additional artificial
+ stars added by the ADDSTAR routine
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+.endhelp
diff --git a/noao/digiphot/daophot/doc/datapars.hlp b/noao/digiphot/daophot/doc/datapars.hlp
new file mode 100644
index 00000000..3e4345a1
--- /dev/null
+++ b/noao/digiphot/daophot/doc/datapars.hlp
@@ -0,0 +1,289 @@
+.help datapars May00 noao.digiphot.daophot
+.ih
+NAME
+datapars -- edit the data dependent parameters
+.ih
+USAGE
+datapars
+.ih
+PARAMETERS
+.ls scale = 1.0
+The scale of the image in user units, e.g. arcseconds per pixel. All DAOPHOT
+distance dependent parameters are assumed to be in units of scale. If
+\fIscale\fR = 1.0 these parameters are assumed to be in units of pixels. Most
+DAOPHOT users should leave \fIscale\fR set to 1.0 unless they intend to compare
+their aperture photometry results directly with data in the literature.
+.le
+.ls fwhmpsf = 2.5 (scale units)
+The full-width half-maximum of the point spread function in scale units.
+The DAOFIND task and the PHOT task "gauss" and "ofilter" centering algorithms
+depend on the value of fwhmpsf. DAOPHOT users can either determine a value
+for fwhmpsf using an external task such as IMEXAMINE, or make use of the
+interactive capabilities of the DAOPHOT tasks to set and store it.
+.le
+.ls emission = yes
+The features to be measured are above sky. By default the DAOPHOT package
+considers all features to be emission features. DAOPHOT users should
+leave this parameter set to "yes".
+.le
+.ls sigma = 0.0
+The standard deviation of the sky pixels. The DAOFIND task and the PHOT task
+"constant" sky fitting algorithm error estimate depend on the value of sigma.
+DAOPHOT users should set sigma to a value representative of the noise in
+the sky background.
+.le
+.ls datamin = INDEF
+The minimum good pixel value. Datamin defaults to -MAX_REAL the minimum
+floating point number supported by the host computer. Datamin is used
+to detect and remove bad data from the sky aperture, detect and flag
+bad data in the aperture photometry aperture, and detect and remove bad
+data from the PSF fitting aperture. DAOPHOT users should either leave
+datamin set to INDEF or set it to a number between 5-7 sigma below the
+sky background value.
+.le
+.ls datamax = INDEF
+The maximum good pixel value. Datamax defaults to MAX_REAL the maximum
+floating point number supported by the host computer. Datamax is used
+to detect and remove bad data from the sky aperture, detect and flag
+bad data in the aperture photometry aperture, and detect and remove bad
+data from the PSF fitting aperture. DAOPHOT users should either leave
+datamax set to INDEF or set it to the linearity or saturation
+limit of the detector.
+.le
+.ls noise = "poisson"
+The noise model used to estimate the uncertainties in the computed
+magnitudes. DAOPHOT users must leave noise set to "poisson".
+.le
+.ls ccdread = ""
+The image header keyword defining the readout noise parameter whose units
+are assumed to be electrons.
+.le
+.ls gain = ""
+The image header keyword defining the gain parameter whose units are assumed to
+be electrons per adu.
+.le
+.ls readnoise = 0.0
+The readout noise of the detector in electrons. DAOPHOT users should set
+readnoise or ccdread to its correct value before running any of the DAOPHOT
+package tasks in order to ensure that the PSF fitting weights, magnitude
+error estimates, and chi values are correct.
+.le
+.ls epadu = 1.0
+The gain of the detector in electrons per adu. DAOPHOT users should set this
+epadu or gain to its correct value before running any of the DAOPHOT package
+tasks in order to ensure that the PSF fitting weights, magnitude error
+estimates, and chi values are correct.
+.le
+.ls exposure = ""
+The image header exposure time keyword. The time units are arbitrary but
+must be consistent for any list of images whose magnitudes are to be compared.
+The computed magnitudes are normalized to one timeunit by the PHOT task.
+As the magnitude scale of the DAOPHOT package is set by the PHOT task,
+setting exposure can save DAOPHOT users a lot of unnecessary zero point
+corrections in future analysis and calibration steps.
+.le
+.ls airmass = ""
+The image header airmass keyword. The airmass parameter is not used
+directly by DAOPHOT but the airmass value is stored in the output file
+and its presence there will simplify future calibration steps.
+.le
+.ls filter = ""
+The image header filter id keyword. The filter parameter is not used
+directly by DAOPHOT but the filter id is stored in the output file
+and its presence there will simplify future calibration steps.
+.le
+.ls obstime = ""
+The image header time of observation keyword. The obstime parameter is not used
+directly by DAOPHOT but the obstime value is stored in the output file
+and its presence there will simplify future calibration steps.
+.le
+.ls itime = 1.0
+The exposure time for the image in arbitrary units. The DAOPHOT magnitudes are
+normalized to 1 timeunit by the PHOT task using the value of exposure in the
+image header if exposure is defined or the value of itime.
+.le
+.ls xairmass = INDEF
+The airmass value. The airmass is read from the image header if airmass
+is defined or from xairmass. The airmass value is stored in the DAOPHOT
+output files.
+.le
+.ls ifilter = "INDEF"
+The filter id string. The filter id is read from the image header if filter
+is defined otherwise from ifilter. The filter id is stored in the DAOPHOT
+output files.
+.le
+.ls otime = "INDEF"
+The value of the time of observation. The time of observation is read from
+the image header if obstime is defined otherwise from otime. The time of
+observation is stored in the DAOPHOT output files.
+.le
+
+.ih
+DESCRIPTION
+
+\fIDatapars\fR sets the image data dependent parameters. These parameters are
+functions, of the instrument optics, the noise characteristics and range of
+linearity of the detector, and the observing conditions. Many of the
+centering, sky fitting, and photometry algorithm parameters in the CENTERPARS,
+FITSKYPARS, PHOTPARS, and DAOPARS parameter sets scale with the data dependent
+parameters.
+
+The parameter \fIscale\fR sets the scale of the apertures used by the
+centering, sky fitting, aperture photometry, and psf fitting algorithms.
+Scale converts radial distance measurements in pixels to radial distance
+measurements in scale units. The DAOPHOT parameters cbox, maxshift, rclean
+and rclip in the CENTERPARS parameter set; annulus, dannulus, and rgrow in
+FITSKYPARS parameter set; apertures in the PHOTPARS parameter set; and psfrad,
+fitrad, sannulus, wsannulus, and matchrad in the DAOPARS parameter set are
+expressed in units of the scale. The scale parameter is useful in cases where
+the observations are to be compared to published aperture photometry
+measurements in the literature.
+
+The parameter \fIfwhmpsf\fR defines the full-width at half-maximum of the
+stellar point spread function. The DAOFIND task, the PHOT task centering
+algorithms "gauss" and "ofilt", and the PSF modeling task PSF all require
+an accurate estimate for this parameter.
+
+By setting the \fIscale\fR and \fIfwhmpsf\fR appropriately the aperture
+sizes and radial distances may be expressed in terms of the half-width
+at half-maximum of the stellar point spread function. The way to do this
+is to define the scale parameter in units of the number of half-width at
+half-maximum per pixel, set the fwhmpsf parameter to 2.0, and then
+set the remaining scale dependent centering, sky fitting, aperture photometry,
+and psf fitting algorithm parameters in CENTERPARS, FITSKYPARS, PHOTPARS,
+and DAOPARS to appropriate values in units of the half-width at half-maximum
+of the point-spread function. Once an optimum set of algorithm parameters is
+chosen, the user need only alter the DATAPARS scale parameter before
+executing a DAOPHOT task on a new image.
+
+If \fIemission\fR is "yes", the features to be measured are assumed to
+be above sky. By default the DAOPHOT package considers all features to be
+emission features. DAOPHOT users should leave this parameter set to "yes".
+Although the DAOFIND and PHOT tasks can detect and measure absorption features
+the PSF fitting tasks currently cannot.
+
+The parameter \fIsigma\fR estimates the standard deviation of the sky
+background pixels. The star finding algorithm in DAOFIND uses sigma
+and the \fIfindpars.threshold\fR parameter to define the stellar
+detection threshold in adu. The PHOT task centering algorithms use sigma,
+1) with the \fIcenterpars.kclean\fR parameter to define deviant pixels
+if \fIcenterpars.clean\fR is enabled; 2) to estimate the signal to
+noise ratio in the centering box; 3) and with the \fIcenterpars.cthreshold\fR
+parameter to define a lower intensity limit for the pixels to be used
+for centering. If sigma is undefined or <= 0.0 1) no cleaning is performed
+regardless of the value of centerpars.clean; 2) the background noise in the
+centering box is assumed to be 0.0; and 3) default cutoff intensity is used
+for centering.
+
+The \fIdatamin\fR and \fIdatamax\fR parameters define the good data range.
+If datamin or datamax are defined bad data is removed from the sky pixel
+distribution before the sky is fit, data containing bad pixels in the
+photometry apertures is flagged and the corresponding aperture photometry
+magnitudes are set to INDEF, and bad data removed from the PSF fitting
+aperture. DAOPHOT users should set datamin and datamax to appropriate values
+before running the DAOPHOT tasks.
+
+DAOPHOT users must leave \fInoise\fR set to "poisson". This model includes
+Poisson noise from the object and both Poisson and readout noise in the sky
+background.
+
+The parameters \fIgain\fR and \fIepadu\fR define the image gain.
+The gain parameter specifies which keyword in the image header contains
+the gain value. If gain is undefined or not present in the image header
+the value of epadu is used. Epadu must be in units of electrons per adu.
+DAOPHOT users should set either gain or epadu to a correct value before
+running any of the DAOPHOT package tasks to ensure that the aperture
+photometry magnitude error estimates, and the PSF fitting weights, chis, and
+magnitude error estimates are computed correctly.
+
+The two parameters \fIccdread\fR and \fIreadnoise\fR define the image
+readout noise. The ccdread parameter specifies which keyword in the
+image header contains the readout noise value. If ccdread is undefined or
+not present in the image header the value of readnoise is used.
+Readnoise is assumed to be in units of electrons.
+DAOPHOT users should set either ccdread or readnoise before running any
+DAOPHOT tasks to insure that the PSF fitting weights, chis, and magnitude
+error estimates are computed correctly.
+
+The magnitudes computed by PHOT are normalized to an exposure time of 1
+timeunit using the value of the exposure time in the image header parameter
+\fIexposure\fR or \fIitime\fR. If exposure is undefined or not present
+in the image header a warning message is issued and the value of itime
+is used. The itime units are arbitrary but must be consistent for images
+analyzed together. As the magnitude scale in DAOPHOT is determined by the
+PHOT task setting either exposure or itime can save DAOPHOT users a lot
+of unnecessary zero point corrections in future analysis and calibration
+steps.
+
+The parameters \fIairmass\fR and \fIxairmass\fR define the airmass
+of the observation. The airmass parameter specifies which keyword in the
+image header contains the airmass value. If airmass is undefined or
+not present in the image header the value of xairmass is used.
+The airmass values are not used in any DAOPHOT computations, however their
+presence in the DAOPHOT output files will simplify future reduction steps.
+
+The parameters \fIfilter\fR and \fIifilter\fR define the filter
+of the observation. The filter parameter specifies which keyword in the
+image header contains the filter id. If filter is undefined or not present
+in the image header the value of ifilter is used. The filter id values are
+not used in any DAOPHOT computations, however their presence in the DAOPHOT
+output files can will simplify future reduction steps.
+
+The parameters \fIobstime\fR and \fIotime\fR define the time
+of the observation (e.g. UT). The obstime parameter specifies which keyword
+in the image header contains the time stamp of the observation. If obstime is
+undefined or not present in the image header the value of otime is used.
+The time of observations values are not used in any DAOPHOT
+computations, however their presence in the DAOPHOT output files can
+greatly simplify future reduction steps.
+
+
+.ih
+EXAMPLES
+
+1. List the data dependent parameters.
+
+.nf
+ da> lpar datapars
+.fi
+
+2. Edit the data dependent parameters.
+
+.nf
+ da> datapars
+.fi
+
+3. Edit the data dependent parameters from within the PSF task.
+
+.nf
+ da> epar psf
+
+ ... edit a few parameters
+
+ ... move to the datapars parameter and type :e
+
+ ... edit the datapars parameters and type :wq
+
+ ... finish editing the psf parameter and type :wq
+.fi
+
+4. Save the current DATAPARS parameter set in a text file datnite1.par.
+This can also be done from inside a higher level task as in the previous
+example.
+
+.nf
+ da> epar datapars
+
+ ... edit a few parameters
+
+ ... type ":w datnite1.par" from within epar
+.fi
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+
+.ih
+SEE ALSO
+epar,lpar,daofind,phot,pstselect,psf,group,peak,nstar,allstar,substar,addstar
+.endhelp
diff --git a/noao/digiphot/daophot/doc/findpars.hlp b/noao/digiphot/daophot/doc/findpars.hlp
new file mode 100644
index 00000000..1c0bfe1a
--- /dev/null
+++ b/noao/digiphot/daophot/doc/findpars.hlp
@@ -0,0 +1,135 @@
+.help findpars May00 noao.digiphot.daophot
+.ih
+NAME
+findpars -- edit the object detection parameters
+.ih
+USAGE
+findpars
+.ih
+PARAMETERS
+.ls threshold = 4.0 (sigma)
+The object detection threshold above local background in units of
+\fIdatapars.sigma\fR.
+.le
+.ls nsigma = 1.5
+The semi-major axis of the Gaussian convolution kernel used to computed the
+density enhancement and mean density images in Gaussian sigma. This semi-
+major axis is equal to min (2.0, 0.42466 * \fInsigma\fR *
+\fIdatapars.fwhmpsf\fR / \fIdatapars.scale\fR) pixels.
+.le
+.ls ratio = 1.0
+The ratio of the sigma of the Gaussian convolution kernel along the minor axis
+direction to the sigma along the major axis direction. \fIRatio\fR defaults
+to 1.0 in which case the image is convolved with a circular Gaussian.
+.le
+.ls theta = 0.0
+The position of the major axis of the elliptical Gaussian. \fITheta\fR is
+measured counter-clockwise from the x axis.
+.le
+.ls sharplo = .2, sharphi = 1.0
+\fISharplo\fR and \fIsharphi\fR are numerical cutoffs on the image sharpness
+statistic chosen to eliminate brightness maxima which are due to bad pixels
+rather than to astronomical objects.
+.le
+.ls roundlo = -1.0 roundhi = 1.0
+\fIRoundlo\fR and \fIroundhi\fR are numerical cutoffs on the image roundness
+statistic chosen to eliminate brightness maxima which are due to bad rows or
+columns rather than to astronomical objects.
+.le
+.ls mkdetections = no
+Mark the positions of the detected objects on the displayed image ?
+.le
+
+.ih
+DESCRIPTION
+
+DAOFIND approximates the stellar point spread function with an elliptical
+Gaussian function, whose sigma along the semi-major axis is 0.42466 *
+\fIdatapars.fwhmpsf\fR / \fIdatapars.scale\fR pixels, semi-minor to semi-major
+axis ratio is \fIratio\fR, and major axis position angle is \fItheta\fR.
+Using this model, a convolution kernel, truncated at \fInsigma\fR sigma,
+and normalized to sum to zero, is constructed.
+
+The density enhancement image \fIstarmap\fR is computed by convolving the input
+image with the Gaussian kernel. This operation is mathematically equivalent to
+fitting, in the least-squares sense, the image data at each point with a
+truncated, lowered elliptical Gaussian function. After convolution each point
+in \fIstarmap\fR contains as estimate of the amplitude of the best fitting
+Gaussian function at that point. Each point in \fIskymap\fR, if the user
+chooses to compute it, contains an estimate of the best fitting sky value
+at that point.
+
+After image convolution DAOFIND steps through \fIstarmap\fR searching
+for density enhancements greater than \fIfindpars.threshold\fR *
+\fIdatapars.sigma\fR, and brighter than all other density enhancements
+within a semi-major axis of 0.42466 \fIfindpars.nsigma\fR *
+\fIdatapars.fwhmpsf\fR. As the program selects candidates, it computes two
+shape characteristics sharpness and roundness. The sharpness statistic
+measures the ratio of the difference between the height of the central pixel
+and the mean of the surrounding non-bad pixels, to the height of the best
+fitting Gaussian function at that point. The roundness statistics measures
+the ratio of, the difference in the height of the best fitting Gaussian
+function in x minus the best fitting Gaussian function in y, over the average
+of the best fitting Gaussian functions in x and y. The limits on these
+parameters \fIfindpars.sharplo\fR, \fIfindpars.sharphi\fR,
+\fIfindpars.roundlo\fR, and \fIfindpars.roundhi\fR, are set to weed out
+non-astronomical objects and brightness enhancements that are elongated in
+x and y respectively.
+
+Lastly the x and y centroids of the detected objects are computed by
+estimating the x and y positions of the best fitting 1D Gaussian
+functions in x and y respectively, a rough magnitude is estimated
+by computing the ratio of the amplitude of the best fitting Gaussian at
+the object position to \fIfindpars.threshold\fR * \fIdatapars.sigma\fR,
+and the object is added to the output coordinate file.
+
+
+.ih
+EXAMPLES
+
+1. List the object detection parameters.
+
+.nf
+ da> lpar findpars
+.fi
+
+2. Edit the object detection parameters.
+
+.nf
+ da> findpars
+.fi
+
+3. Edit the FINDPARS parameters from within the DAOFIND task.
+
+.nf
+ da> epar daofind
+
+ ... edit a few daofind parameters
+
+ ... move to the findpars parameter and type :e
+
+ ... edit the findpars parameter and type :wq
+
+ ... finish editing the daofind parameters and type :wq
+.fi
+
+4. Save the current FINDPARS parameter set in a text file fndnite1.par.
+This can also be done from inside a higher level task as in the previous
+example.
+
+.nf
+ da> findpars
+
+ ... edit the parameters
+
+ ... type ":w fndnite1.par" from within epar
+.fi
+
+.ih
+BUGS
+daofind
+
+.ih
+SEE ALSO
+epar,lpar,daofind,datapars
+.endhelp
diff --git a/noao/digiphot/daophot/doc/fitskypars.hlp b/noao/digiphot/daophot/doc/fitskypars.hlp
new file mode 100644
index 00000000..6642a551
--- /dev/null
+++ b/noao/digiphot/daophot/doc/fitskypars.hlp
@@ -0,0 +1,212 @@
+.help fitskypars May00 noao.digiphot.daophot
+.ih
+NAME
+fitskypars - edit the sky fitting algorithm parameters
+.ih
+USAGE
+fitskypars
+.ih
+PARAMETERS
+.ls salgorithm = "mode"
+The sky fitting algorithm. The sky fitting options are:
+.ls constant
+Use a user supplied constant sky value.
+This algorithm is useful for measuring large resolved objects on flat
+backgrounds such as galaxies or comets.
+.le
+.ls file
+Read sky values from a text file. This option is useful for importing
+user determined sky values into DAOPHOT.
+.le
+.ls mean
+Compute the mean of the sky pixel distribution. This algorithm is useful
+for computing sky values in regions with few background counts.
+.le
+.ls median
+Compute the median of the sky pixel distribution. This algorithm is a useful
+for computing sky values in regions with rapidly varying sky backgrounds
+and is a good alternative to "centroid".
+.le
+.ls mode
+Compute the mode of the sky pixel distribution using the mean and median.
+This is the recommended algorithm for DAOPHOT users measuring stellar objects in
+crowded stellar fields. Mode may not perform well in regions with
+rapidly varying sky backgrounds.
+.le
+.ls centroid
+Compute the intensity weighted mean of the sky pixel histogram. This algorithm
+is reasonably robust in regions with rapidly varying or crowded sky backgrounds
+and is a good alternative to "median".
+.le
+.ls gauss
+Fit a Gaussian function to the sky pixel histogram using non-linear least-
+squares techniques to determine the peak.
+.le
+.ls ofilter
+Optimally filter the sky pixel histogram using a triangular weighting
+function to determine the peak.
+.le
+.ls crosscor
+Compute the peak of the cross-correlation function of the pixel distribution
+and a Gaussian noise function to determine the peak.
+.le
+.ls histplot
+Mark the peak of the sky pixel histogram with the graphics cursor.
+This algorithm is useful for making careful interactive sky measurements
+for a small number of objects in complicated regions or for checking the
+behavior of other sky algorithms.
+.le
+.ls radplot
+Mark the sky level on a radial profile plot with the graphics cursor.
+This algorithm is useful for making careful interactive sky measurements
+for a small number of objects in complicated regions or for checking the
+behavior of other sky algorithms.
+.le
+.le
+.ls annulus = 10.0 (scale units)
+The inner radius of the annular sky fitting region in units of the DATAPARS
+scale parameter.
+.le
+.ls dannulus = 10.0 (scale units)
+The width of the annular sky fitting region in units of the DATAPARS scale
+parameter.
+.le
+.ls skyvalue = 0.0
+The constant for constant sky subtraction.
+.le
+.ls smaxiter = 10
+The maximum number of iterations performed by the sky fitting algorithm.
+Smaxiter is required by the "gauss" and "ofilter" sky fitting algorithms.
+.le
+.ls sloclip = 0.0, shiclip = 0.0 (percent)
+The high and low side clipping parameters in percent of the total number
+of pixels. If either of these parameters > 0.0 then the specified
+percentage of the pixels will be removed from the sky pixel distribution
+before any sky fitting is done.
+.le
+.ls snreject = 50
+The maximum number of sky pixel rejection cycles.
+.le
+.ls sloreject = 3.0, shireject = 3.0
+The k-sigma clipping factors for the pixel rejection phase of the
+sky fitting algorithm. Sloreject and shireject are in units of the
+computed sky sigma.
+.le
+.ls khist = 3.0
+The k-sigma clipping factor for computing the sky pixels histogram. Khist is in
+units of sigma of the local sky pixel distribution. The histogram will be
+2.0 * khist * sigma wide. Khist is used by the "centroid", "gauss",
+"crosscor", "ofilter", and "histplot" sky fitting algorithms.
+.le
+.ls binsize = 0.10
+The width of a single bin of the sky pixel histogram. Binsize is in units of
+the sigma of the local sky pixel distribution. Binsize is used by the
+"centroid", "gauss", "crosscor", "ofilter", and "histplot" sky fitting
+algorithms.
+.le
+.ls smooth = no
+Boxcar smooth the sky pixel histogram before computing a sky value.
+Smooth is used by the "centroid", "gauss", "crosscor", "ofilter", and
+"histplot" sky fitting algorithms.
+.le
+.ls rgrow = 0.0 (scale units)
+The region growing radius for pixel rejection in the sky region in units
+of the DATAPARS scale parameter. When a bad sky_pixel is detected, all pixels
+within rgrow / scale pixels of the bad pixel will be rejected. If rgrow is
+0.0 region growing is disabled.
+.le
+.ls mksky = no
+Mark the sky annuli on the displayed image ?
+.le
+.ih
+DESCRIPTION
+The sky fitting algorithm parameters control the action of the sky fitting
+algorithms. The default parameter settings should give reasonable results in
+the majority of cases. Several of the sky fitting parameters scale with
+image scale, \fIscale\fR which is data dependent.
+\fIScale\fR is defined in the DATAPARS parameter set.
+
+Sky pixels in an annular region of inner radius \fIannulus / scale\fR pixels
+and a width of \fIdannulus / scale\fR pixels are extracted from the IRAF image.
+If the \fIscale\fR parameter is defined in terms of the number of half-width
+at half-maximum of the point spread function per pixel, then single values of
+annulus and dannulus will work well for images with different seeing and
+detector characteristics.
+
+Pixels outside of the good data range specified by \fIdatamin\fR and
+\fIdatamax\fR are rejected from the sky pixel distribution. After bad
+data rejection \fIPloclip\fR and \fIphiclip\fR percent pixels are rejected
+from the low and high sides of the sorted pixel distribution before any
+sky fitting is done.
+
+Sky values are computed using the sky fitting algorithm specified by
+\fIsalgorithm\fR. The default value is "centroid". If \fIsalgorithm\fR
+= "mean", "median" or "mode", the sky value is computed directly from the
+array of sky pixels. The remaining sky fitting algorithms use the histogram
+of the object sky pixels. The computed histogram is \fIkhist\fR * sigma wide
+with a bin width of \fIbinsize\fR * sigma where sigma is the computed
+standard deviation of the sky pixels for each object. If \fIsmooth\fR = yes,
+boxcar smoothing is performed on the computed histogram before sky fitting.
+The mode of the histogram is computed using, a non-linear least squares
+fit to a Gaussian (salgorithm = "gauss"), optimal filtering of the histogram
+(salgorithm = "ofilter"), computing the centroid of the histogram
+(salgorithm = "centroid"), or by cross-correlation techniques
+(salgorithm = "crosscor").
+
+Two interactive methods of fitting sky are also available. If \fIsalgorithm\fR
+is "radplot" or "histplot", the user must interactively set
+the value of the sky using a radial profile or a histogram plot.
+
+Pixels which deviate from the sky value by more than \fIkreject times the
+computed sky sigma are rejected from the fit. If \fIrgrow\fR > 0, pixels
+within a radius of rgrow / scale of the rejected pixel are also rejected from
+the fit. The rejection procedure iterates until no further pixels are rejected,
+all pixels are rejected, or the maximum number of rejection cycles
+\fIsnreject\fR iterations is reached.
+
+.ih
+EXAMPLES
+
+1. List the sky fitting parameters.
+
+.nf
+ da> lpar fitskypars
+.fi
+
+2. Edit the sky fitting parameters.
+
+.nf
+ da> fitskypars
+.fi
+
+3. Edit the FITSKYPARS parameters from with the PHOT task.
+
+.nf
+ da> epar phot
+
+ ... edit a few phot parameters
+
+ ... move to the fitskypars parameter and type :e
+
+ ... edit the fitskypars parameters and type :wq
+
+ ... finish editing the phot parameters and type :wq
+.fi
+
+4. Save the current FITSKYPARS parameter set in a text file skynite1.par.
+This can also be done from inside a higher level task as in the
+above example.
+
+.nf
+ da> epar fitskypars
+
+ ... type ":w skynite1.par" from within epar
+.fi
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+epar,lpar,datapars,phot
+.endhelp
diff --git a/noao/digiphot/daophot/doc/group.hlp b/noao/digiphot/daophot/doc/group.hlp
new file mode 100644
index 00000000..a8cc35d5
--- /dev/null
+++ b/noao/digiphot/daophot/doc/group.hlp
@@ -0,0 +1,304 @@
+.help group May00 noao.digiphot.daophot
+.ih
+NAME
+group -- group stars in a photometry file
+.ih
+USAGE
+group image photfile psfimage groupfile
+.ih
+PARAMETERS
+.ls image
+The list of images containing the stars to be grouped.
+.le
+.ls photfile
+The list of input photometry files containing initial estimates of the
+positions and magnitudes of the stars to be fit. The number of photometry
+files must be equal to the number of input images. If photfile is "default",
+"dir$default", or a directory specification PSF searches for a file called
+dir$image.mag.# where # is the highest available version number for the file.
+Photfile is normally the output of the PHOT task but may also be the output of
+the PSF, PEAK, NSTAR and ALLSTAR tasks. Photfile may be an APPHOT/DAOPHOT
+text database or an STSDAS binary table.
+.le
+.ls psfimage
+The list of images containing the PSF models computed by the DAOPHOT PSF task.
+The number of PSF images must be equal to the number of input images. If
+psfimage is "default", "dir$default", or a directory specification,
+then PEAK will look for an image with the name image.psf.?, where
+? is the highest existing version number.
+.le
+.ls groupfile =
+The list of output grouped photometry files. There must be one output group
+photometry file for every input image. If groupfile is "default",
+"dir$default", or a directory specification then GROUP writes a file called
+image.grp.? where ? is the next available version number. If the DAOPHOT
+package parameter \fItext\fR is "yes" then an APPHOT/DAOPHOT text database is
+written, otherwise an STSDAS table is written.
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters. The parameters
+\fIscale\fR, \fIdatamin\fR, and \fIdatamax\fR are located here. If datapars
+is undefined then the default parameter set in uparm directory is used.
+.le
+.ls daopars = ""
+The name of the file containing the daophot fitting parameters. The parameters
+\fIpsfrad\fR and \fIfitrad\fR are located here. If \fIdaopars\fR is undefined
+then the default parameter set in uparm directory is used.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout", wcspsf = ")_.wcspsf"
+The coordinate system of the input coordinates read from \fIphotfile\fR, of the
+psf model \fIpsfimage\fR, and of the output coordinates written to
+\fIgroupfile\fR. The image header coordinate system is used to transform from
+the input coordinate system to the "logical" system used internally, from the
+internal logical system to the PSF model system, and from the internal
+"logical" pixel coordinate system to the output coordinate system. The input
+coordinate system options are "logical", "tv", "physical", and "world". The PSF
+model and output coordinate system options are "logical", "tv", and "physical".
+The image cursor coordinate system is assumed to be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin, wcspsf, and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin, wcspsf, and wcsout are "logical", "physical" and "logical" respectively.
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default caching is
+disabled.
+.le
+.ls verify = ")_.verify"
+Verify the critical GROUP task parameters? Verify can be set to the DAOPHOT
+package parameter value (the default), "yes", or "no".
+.le
+.ls update = ")_.update"
+Update the GROUP task parameters if \fIverify\fR is "yes"? Update can be
+set to the default daophot package parameter value, "yes", or "no".
+.le
+.ls verbose = ")_.verbose"
+Print messages about the progress of the task ? Verbose can be set to the
+DAOPHOT package parameter value (the default), "yes", or "no".
+.le
+.ih
+DESCRIPTION
+GROUP takes the photometry file \fIphotfile\fR file containing the stellar
+coordinates and photometry and associates the stars into natural groups based
+upon proximity and the magnitude level at which they overlap. The results are
+written into \fIgroupfile\fR. If the DAOPHOT package parameter \fItext\fR is
+"yes" then \fIgroupfile\fR is a text database, otherwise it is an STSDAS table.
+
+The coordinates read from \fIphotfile\fR are assumed to be in coordinate
+system defined by \fIwcsin\fR. The options are "logical", "tv", "physical",
+and "world" and the transformation from the input coordinate system to the
+internal "logical" system is defined by the image coordinate system. The
+simplest default is the "logical" pixel system. Users working on with image
+sections but importing pixel coordinate lists generated from the parent image
+must use the "tv" or "physical" input coordinate systems.
+
+The coordinate system of the PSF model is the coordinate system defined by the
+\fIwcspsf\fR parameter. Normally the PSF model was derived from the input image
+and this parameter default to "logical". However if the PSF model was derived
+from a larger image which is a "parent" of the input image, then wcspsf should
+be set to "tv" or "physical" depending on the circumstances.
+
+The coordinates written to \fIgroupfile\fR are in the coordinate system
+defined by \fIwcsout\fR. The options are "logical", "tv", and "physical". The
+simplest default is the "logical" system. Users wishing to correlate the
+output coordinates of objects measured in image sections or mosaic pieces
+with coordinates in the parent image must use the "tv" or "physical"
+coordinate systems.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If caching
+is enabled and the first data access will appear to take a long time as the
+entire image must be read in before the measurement is actually made. All
+subsequent data requests will be very fast because GROUP is accessing memory
+not disk. The point of caching is to speed up random image access by making
+the internal image i/o buffers the same size as the image itself. There is
+no point in turning caching on unless a lot of the input magnitudes are INDEF.
+In that case GROUP must access the image to estimate a magnitude. Also at
+present there is no point in enabling caching for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of caching in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halves of the image are alternated.
+
+
+The algorithm works in the following manner. If two stars are within a
+distance R pixels of one another, where R = \fIpsfrad\fR / \fIscale\fR +
+\fIfitrad\fR / \fIscale\fR + 1, the PSF of the brighter one is evaluated at
+a distance d pixels, where d = \fIfitrad\fR / \fIscale\fR + 1 away from the
+fainter. If this value is larger than \fIcritsnratio\fR times the expected
+noise per pixel then the two stars are put into the same group since the
+brighter star is capable of affecting the photometry of the fainter.
+\fIPsfrad\fR, \fIfitrad\fR and \fIcritsnratio\fR are the psf radius, the
+fitting radius, and the critical S/N ratio respectively and are located
+in the DAOPARS task. \fIScale\fR is the image scale parameter and is located
+in the DATAPARS task. In order for this algorithm to work correctly it is
+imperative that the DATAPARS readnoise and gain parameters \fIreadnoise\fR
+and \fIgain\fR be set correctly as these values are used to compute the
+expected random noise per pixel.
+
+The correct value of \fIcritsnratio\fR must be determined by trial and error.
+For example if a critical S/N ratio of 0.1 divides all the stars in the image
+into groups smaller than the \fImaxgroup\fR parameter in the DAOPARS task, then
+unavoidable random errors will dominate over crowding errors. If a critical
+S/N ratio of 1.0 works, then crowding errors will be no worse than the random
+errors. If a critical S/N ratio much greater than 1 is required then in most
+cases crowding will be the dominant source or error.
+
+If \fIverbose\fR is set to "yes", GROUP will write a table on the terminal
+showing the number of groups as a function of group size. If any group is
+larger than \fImaxgroup\fR then \fIcritnsratio\fR must be increased or
+the GRPSELECT task used to cut large groups out of the file. When crowding
+conditions vary across the frame, GROUP and GRPSELECT can be used together
+to get the best possible photometry for stars in different crowding regimes.
+
+If any stars in \fIphotfile\fR have INDEF magnitudes, GROUP will attempt
+to estimate a magnitude for them based on the weighted sum of the pixels
+of a radial weighting function and the value of the PSF at that point.
+
+
+.ih
+EXAMPLES
+
+1. Group the PHOT task output results for the test image dev$ypix using
+a critical S/N ratio of 1 and printing the output summary on the terminal.
+Good stars for making the PSF model can be found at (442,410), (348,189),
+and (379,67).
+
+.nf
+ da> datapars.epadu = 14.0
+ da> datapars.readnoise = 75.0
+
+ ... set the gain and readout noise for the detector
+
+ da> daofind dev$ypix default fwhmpsf=2.5 sigma=5.0 threshold=20.0
+
+ ... answer verify prompts
+
+ ... find stars in the image
+
+ ... answer will appear in ypix.coo.1
+
+ da> phot dev$ypix default default annulus=10. dannulus=5. \
+ apertures = 3.0
+
+ ... answer verify prompts
+
+ ... do aperture photometry on the detected stars
+
+ ... answer will appear in ypix.mag.1
+
+ da> display dev$ypix 1
+
+ da> psf dev$ypix default "" default default default psfrad=11.0 \
+ fitrad=3.0 mkstars=yes display=imdr
+
+ ... verify the critical parameters
+
+ ... move the image cursor to a candidate star and hit the a key,
+ a plot of the stellar data appears
+
+ ... type ? for a listing of the graphics cursor menu
+
+ ... type a to accept the star, d to reject it
+
+ ... move to the next candidate stars and repeat the previous
+ steps
+
+ ... type l to list all the psf stars
+
+ ... type f to fit the psf
+
+ ... move cursor to first psf star and type s to see residuals,
+ repeat for all the psf stars
+
+ ... type w to save the PSF model
+
+ ... type q to quit, and q again to confirm
+
+ ... the output will appear in ypix.psf.1.imh, ypix.pst.1 and
+ ypix.psg.1
+
+
+ da> group dev$ypix default default default crit=1.0 verbose+
+
+ ... verify the critical parameters
+
+ ... answers will appear in ypix.grp.1
+
+.fi
+
+
+2. Run group on a section of the input image using the photometry file and PSF
+model derived in example 1 for the parent image and writing the results
+in the coordinate system of the parent image. Note that the results for
+example 2 are identical to those in example 1.
+
+.nf
+ da> group dev$ypix[150:450,150:450] default default default \
+ wcsin=tv wcspsf=tv wcsout=tv
+
+ ... answer the verify prompts
+
+ ... fit the stars
+
+ ... the results will appear in ypix.grp.2
+
+ da> display dev$ypix[150:450,150:450] 1
+
+ ... display the image
+
+ da> pdump ypix.grp.2 xc,yc yes | tvmark 1 STDIN col=204
+
+ ... mark the stars
+
+.fi
+
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+psf,grpselect,nstar
+.endhelp
diff --git a/noao/digiphot/daophot/doc/grpselect.hlp b/noao/digiphot/daophot/doc/grpselect.hlp
new file mode 100644
index 00000000..f2381fb7
--- /dev/null
+++ b/noao/digiphot/daophot/doc/grpselect.hlp
@@ -0,0 +1,73 @@
+.help grpselect May00 noao.digiphot.daophot
+.ih
+NAME
+grpselect -- select groups from a group file by group size
+.ih
+USAGE
+grpselect ingroupfile outgroupfile min_group max_group
+.ih
+PARAMETERS
+.ls ingroupfile
+The list of input group files. Ingroupfile must have been written by the
+DAOPHOT PSF, GROUP, or NSTAR tasks. Ingroupfile may be an APPHOT/DAOPHOT text
+database or an STSDAS table.
+.le
+.ls outgroupfile
+The list of output group files. There must be one output group file for every
+input group file. Outgroupfile has the same file type as \fIingroupfile\fR.
+.le
+.ls min_group
+The minimum group size to select from the input group file(s).
+.le
+.ls max_group
+The maximum group size to select from the input group file(s).
+.le
+.ls verbose = ")_.verbose"
+Print messages about the progress of the task? Verbose may be set to the value
+of the daophot package parameter (the default), "yes", or "no".
+.le
+.ih
+DESCRIPTION
+GRPSELECT creates a new GROUP file \fIoutgroupfile\fR by selecting groups from
+the input GROUP file \fIingroupfile\fR within a range of group sizes specified
+by \fImin_group\fR and \fImax_group\fR. If \fIingroupfile\fR is a DAOPHOT text
+database, \fIoutgroupfile\fR is a text database. Conversely if \fIingroupfile\fR
+is a DAOPHOT STSDAS table database, \fIoutgroupfile\fR is an STSDAS table
+database.
+
+A typical use for GRPSELECT is to create a new database containing only groups
+which are less than the value of the \fImaxgroup\fR parameter in the DAOPARS
+task for direct input into the NSTAR task. The remaining stars in the larger
+groups are reduced by running GRPSELECT once more, selecting only groups
+greater than \fImaxgroup\fR, rerunning GROUP on the output with a less
+stringent value of the DAOPARS parameter task \fIcritovlap\fR to reduce the
+group sizes and inputting the result into NSTAR.
+
+.ih
+EXAMPLES
+
+1. Select groups with between 1 and 70 stars from the GROUP task output file
+ypix.grp.1 and write them into a new file named ypixsmall.grp.
+
+.nf
+ da> grpselect ypix.grp.1 ypixsmall.grp 1 70
+
+.fi
+
+2. Select groups larger than 70 from the same input group file and rerun
+group with a new value of the critoverlap parameter on the results.
+
+.nf
+ da> grpselect ypix.grp.1 ypixlarge.grp 71 400
+ da> group dev$ypix ypixlarge.grp ypix.psf.1 default crit=5.0
+
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+group
+.endhelp
diff --git a/noao/digiphot/daophot/doc/nstar.hlp b/noao/digiphot/daophot/doc/nstar.hlp
new file mode 100644
index 00000000..cf7c9936
--- /dev/null
+++ b/noao/digiphot/daophot/doc/nstar.hlp
@@ -0,0 +1,501 @@
+.help nstar May00 noao.digiphot.daophot
+.ih
+NAME
+nstar -- fit the PSF to groups of stars simultaneously
+.ih
+USAGE
+nstar image groupfile psfimage nstarfile rejfile
+.ih
+PARAMETERS
+.ls image
+The list of images containing the stellar groups to be fit.
+.le
+.ls groupfile
+The list of input group photometry files containing the group membership
+information and initial estimates for the positions and magnitudes of the stars
+to be measured. There must be one group file for every input image. If
+groupfile is "default", "dir$default", or a directory specification then NSTAR
+will look for a file with the name image.grp.? where ? is the highest existing
+version number. Groupfile is usually the output of the DAOPHOT GROUP task, but
+may also be the output of the NSTAR and PSF tasks. Groupfile may be an
+APPHOT/DAOPHOT text database or an STSDAS binary table.
+.le
+.ls psfimage
+The list of images containing the PSF models computed by the DAOPHOT PSF task.
+The number of PSF images must be equal to the number of input images. If
+psfimage is "default", "dir$default", or a directory specification,
+then PEAK will look for an image with the name image.psf.?, where
+? is the highest existing version number.
+.le
+.ls nstarfile
+The list of output photometry files. There must be one output photometry
+file for every input image. If nstarfile is "default", "dir$default", or a
+directory specification, then NSTAR will write an output file with the name
+image.nst.? where ? is the next available version number. Nstarfile is a text
+database if the DAOPHOT package parameter text is "yes", an STSDAS table
+database if it is "no".
+.le
+.ls rejfile
+The list of output rejected photometry files containing the positions and sky
+values of stars that could not be fit. If rejfile is undefined, results for all
+the stars in photfile are written to \fInstarfile\fR, otherwise only the stars
+which were successfully fit are written to \fInstarfile\fR and the remainder are
+written to rejfile. If rejfile is "default", "dir$default", or a directory
+specification NSTAR writes an output file with the name image.nst.? where ? is
+the next available version number. Otherwise rejfile must specify one output
+photometry file for every input image. Rejfile is a text database if the
+DAOPHOT package parameter \fItext\fR is "yes", an STSDAS binary table database
+if it is "no".
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters. The parameters
+\fIscale\fR, \fIdatamin\fR, and \fIdatamax\fR are located here. If datapars
+is undefined then the default parameter set in uparm directory is used.
+.le
+.ls daopars = ""
+The name of the file containing the daophot fitting parameters. The parameters
+\fIpsfrad\fR and \fIfitrad\fR are located here. If \fIdaopars\fR is undefined
+then the default parameter set in uparm directory is used.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout", wcspsf = ")_.wcspsf"
+The coordinate system of the input coordinates read from \fIgroupfile\fR, of the
+psf model \fIpsfimage\fR, and of the output coordinates written to
+\fInstarfile\fR and \fIrejfile\fR respectively. The image header coordinate
+system is used to transform from the input coordinate system to the "logical"
+pixel coordinate system used internally, from the internal logical system to
+the PSF model system, and from the internal "logical" pixel coordinate system
+to the output coordinate system. The input coordinate system options are
+"logical", "tv", "physical", and "world". The PSF model and output coordinate
+system options are "logical", "tv", and "physical". The image cursor coordinate
+system is assumed to be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin, wcspsf, and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin, wcspsf, and wcsout are "logical", "physical" and "logical" respectively.
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default caching is
+disabled.
+.le
+.ls verify = ")_.verify"
+Verify the critical NSTAR task parameters? Verify can be set to the DAOPHOT
+package parameter value (the default), "yes", or "no".
+.le
+.ls update = ")_.update"
+Update the NSTAR task parameters if \fIverify\fR is "yes"? Update can be
+set to the default daophot package parameter value, "yes", or "no".
+.le
+.ls verbose = ")_.verbose"
+Print messages about the progress of the task ? Verbose can be set to the
+DAOPHOT package parameter value (the default), "yes", or "no".
+.le
+.ih
+DESCRIPTION
+NSTAR computes x and y centers and magnitudes for all the stellar groups in
+\fIgroupfile\fR by fitting the PSF \fIpsfimage\fR to the data in \fIimage\fR.
+NSTAR reads the group membership information along with initial estimates of
+the centers and magnitudes, and the sky values from the photometry file
+\fIgroupfile\fR. \fIGroupfile\fR is usually the output of the DAOPHOT GROUP
+task but may also be the output of the PSF and NSTAR tasks. The computed
+centers and magnitudes are written to \fInstarfile\fR along with the sky
+values, the number of iterations it took to fit the star, the goodness of fit
+statistic chi and the image sharpness statistic sharp. If \fIrejfile\fR is
+undefined, only stars that are successfully fit are written to \fInstarfile\fR,
+and the remainder are written to \fIrejfile\fR. Otherwise all the stars are
+written to \fInstarfile\fR. \fINstarfile\fR and \fIrejfile\fR are text
+databases if the DAOPHOT package parameter \fItext\fR is "yes", an STSDAS table
+database if it is "no".
+
+The coordinates read from \fIgroupfile\fR are assumed to be in coordinate
+system defined by \fIwcsin\fR. The options are "logical", "tv", "physical",
+and "world" and the transformation from the input coordinate system to the
+internal "logical" system is defined by the image coordinate system. The
+simplest default is the "logical" pixel system. Users working on with image
+sections but importing pixel coordinate lists generated from the parent image
+must use the "tv" or "physical" input coordinate systems.
+
+The coordinate system of the PSF model is the coordinate system defined by the
+\fIwcspsf\fR parameter. Normally the PSF model was derived from the input image
+and this parameter default to "logical". However if the PSF model was derived
+from a larger image which is a "parent" of the input image, then wcspsf should
+be set to "tv" or "physical" depending on the circumstances.
+
+The coordinates written to \fInstarfile\fR and \fIrejfile\fR are in the
+coordinate system defined by \fIwcsout\fR with the exception of the psf model
+center coordinates PSFX and PSFY which are always in the logical system of
+the input image. The options are "logical", "tv", and "physical". The simplest
+default is the "logical" system. Users wishing to correlate the output
+coordinates of objects measured in image sections or mosaic pieces with
+coordinates in the parent image must use the "tv" or "physical" coordinate
+systems.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If caching
+is enabled and NSTAR is run interactively the first measurement will appear
+to take a long time as the entire image must be read in before the measurement
+is actually made. All subsequent measurements will be very fast because NSTAR
+is accessing memory not disk. The point of caching is to speed up random
+image access by making the internal image i/o buffers the same size as the
+image itself. However if the input object lists are sorted close to row order
+and sparse caching may actually worsen not improve the execution time. Also at
+present there is no point in enabling caching for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of caching in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halves of the image are alternated.
+
+By default NSTAR computes new centers for all the stars in \fIgroupfile\fR.
+However if the DAOPARS parameter \fIrecenter\fR is "no", NSTAR assumes that the
+x and y centers in \fIgroupfile\fR are the true centers and does not refit
+them. This option can be quite useful in cases where accurate center values
+have been derived from an image that has been through some non-linear image
+restoration algorithm, but the photometry must be derived from the original
+unrestored image.
+
+By default NSTAR computes the sky value for each group by averaging the
+individual sky values in \fIgroupfile\fR for all the stars in the group. If
+\fIgroupsky\fR is "no" then the sky value for a particular pixel which
+contributes to the group fit is set to the mean of the sky values of only those
+stars for which the pixel is within one fitting radius. However if the DAOPARS
+parameter \fIfitksy\fR is "yes", then NSTAR computes a new group sky value as
+part of the non-linear least-squares fit. Recomputing the sky can significantly
+reduce the scatter in the magnitudes in regions where the sky background is
+varying rapidly, but users may need to increase \fIfitrad\fR to include more
+sky pixels in the fit. Users should experiment cautiously with this option.
+
+Only pixels within the good data range delimited by the DATAPARS task
+parameters \fIdatamin\fR and \fIdatamax\fR are included in the fit. Most users
+set \fIdatamin\fR and \fIdatamax\fR so as to exclude pixels outside the
+linearity regime of the detector. By default all the data is fit. Users are
+advised to determine accurate values for these parameters and set the
+appropriate parameters in DATAPARS before beginning any DAOPHOT reductions.
+
+Only pixels within the fitting radius \fIfitrad\fR / \fIscale\fR are included
+in the fit for each star. \fIFitrad\fR is located in the DAOPARS task and
+\fIscale\fR is located in the DATAPARS task. Since the non-linear least-squares
+fitting algorithm determines three unknowns, the x and y position of the star's
+ centroid and its brightness, the value of \fIfitrad\fR must be sufficiently
+large to include at least three pixels in the fit for each star. To accelerate
+the convergence of the non-linear least-squares fitting algorithm pixels within
+\fIfitrad\fR are assigned weights which are inversely proportional to the
+radial distance of the pixel from the x and y centroid of the star, falling
+from a maximum at the centroid to zero at the fitting radius. \fIFitrad\fR must
+ be sufficiently large to include at least three pixels with non-zero weights
+in the fit for each star. Values of \fIfitrad\fR close to the full-width at
+half-maxima of the PSF are recommended. In actual fact NSTAR imposes a minimum
+number of pixel limit of four.
+
+NSTAR performs a weighted fit to the PSF. The weight of each pixel is computed
+by combining, the radial weighting function described above, with weights
+derived from the random errors NSTAR predicts based on the values of the
+DATAPARS parameters \fIreadnoise\fR and \fIepadu\fR, and the flat-fielding and
+profile interpolation errors specified by the DAOPARS \fIflaterr\fR and
+\fIproferr\fR parameters. To obtain optimal fits, users are strongly advised
+to determine those parameters accurately and to enter their values in DATAPARS
+and DAOPARS before beginning any DAOPHOT reductions.
+
+For each group of stars to be fit, NSTAR extracts a subraster from \fIimage\fR
+which extends approximately \fIpsfrad\fR / \fIscale\fR + 1 pixels wide past
+the limiting values of the x and y coordinates of the stars in the group.
+\fIPsfrad\fR is the PSF radius specified in the DAOPARS task, and \fIscale\fR
+is the image scale specified by the DATAPARS task. \fIPsfrad\fR may be less
+than or equal to but can never exceed the value of the image header parameter
+"PSFRAD" in \fIpsfimage\fR. \fIPsfrad\fR should always be several pixels larger
+than \fIfitrad\fR to permit the x and y centroids to wander during the fitting
+process.
+
+As well as the computed x and y centers and magnitudes, NSTAR outputs the number
+ of times the PSF fit had to be iterated before reaching convergence. The
+minimum number of iterations is four. The maximum number of iteration permitted
+is specified by the \fImaxiter\fR parameter in the DAOPARS task. Obviously the
+results for stars which have reached the maximum iteration count should be
+viewed with suspicion. However since the convergence criteria are quite strict,
+(the computed magnitude must change by less than .0005 magnitudes or 0.10
+sigma whichever is larger, and the x and y centroids must change by less than
+0.002 pixels from one iteration to the next), even these stars may be
+reasonably well measured. It must be emphasized that every star in the group
+must individually satisfy the convergence criteria in order for the group to be
+ considered adequately reduced.
+
+NSTAR computes a goodness of fit statistic chi which is essentially the ratio
+of the observed pixel-to-pixel scatter in the fitting residuals to the expected
+scatter. Since the expected scatter is dependent on the DATAPARS task parameters
+\fIreadnoise\fR and \fIepadu\fR, and the DAOPARS parameters \fIflaterr\fR and
+\fIproferr\fR it is important for these values to be set correctly. A plot of
+chi versus magnitude should scatter around unity with little or no trend in
+chi with magnitude, except at the bright end where saturation effects may be
+present.
+
+Finally NSTAR computes the statistic sharp which estimates the intrinsic angular
+size of the measured object outside the atmosphere. Sharp is roughly defined as
+the difference between the square of the width of the object and the square of
+the width of PSF. Sharp has values close to zero for single stars, large
+positive values for blended doubles and partially resolved galaxies and large
+negative values for cosmic rays and blemishes.
+
+NSTAR implements a highly sophisticated star rejection algorithm. First of all,
+ any group of stars which is more than a certain size is simply not fit. The
+maximum group size is specified by the \fImaxgroup\fR parameter in the DAOPARS
+task. Larger groups may run into numerical precision problems during the fits.
+Users should exercise care in increasing the \fImaxgroup\fR parameter. If two
+stars in a group have centroids separated by a critical distance, currently set
+arbitrarily to 0.37 * the FWHM of the stellar core, their photocentric position
+and combined magnitude is assigned to the brighter of the two stars, and the
+fainter is eliminated. Any star which converges to 12.5 magnitudes greater than
+ the magnitude of the PSF is considered to be non-existent and eliminated from
+the group.
+
+After iteration 5, if the faintest star in the group has a brightness less than
+ one sigma above zero, it is eliminated. After iterations 10, if the faintest
+star in the group has a brightness less than 1.5 sigma above zero, it is
+eliminated. After iterations 15 to 50 or whenever the solutions has converged
+whichever comes first, if the faintest star in the group has a brightness less
+than 2.0 sigma above zero, it is eliminated. After iterations 5, 10 and 15,
+if two stars are separated by more than 0.37 * FWHM and less than 1.0 * FWHM
+and if the fainter of the two is more uncertain than 1.0, 1.5 or 2.0 sigma
+respectively the fainter one is eliminated.
+
+Whenever a star is eliminated the iteration counter is backed up by one and
+reduction proceeds with a smaller set of stars. Backing up the counter gives
+the second least certain star in the group two iterations to settle into a new
+fit before its fate is decided. The star rejection algorithm depends upon the
+DATAPARS \fIreadnoise\fR and \fIgain\fR parameters and the DAOPARS parameter
+\fIflaterr\fR and \fIproferr\fR. Therefore these parameters should be set to
+reasonable values before running NSTAR.
+
+NSTAR operates in a very similar manner to PEAK. However because it fits groups
+ of stars simultaneously it is much more accurate than PEAK in crowded regions.
+The ALLSTAR task also fits groups of stars simultaneously, both grouping the
+stars dynamically as well as producing a subtracted image. Essentially it
+replaces GROUP, GRPSELECT, NSTAR and SUBSTAR. However the user has little
+control over the grouping process and does not know at the end which stars were
+actually fit together. NSTAR is the task of choice when a user wants to
+maintain rigorous control over the composition of the stellar groups.
+
+.ih
+OUTPUT
+
+If \fIverbose\fR = yes, a single line is output to the terminal for each star
+fit or rejected. Full output is written to \fInstarfile\fR and \fIrejfile\fR.
+At the beginning of these two files a header listing the current values of the
+parameters is written. For each star fit/rejected the following quantities are
+written to the output file.
+
+.nf
+ id group xcenter ycenter mag merr msky niter sharpness
+ chi pier perr
+.fi
+
+Id is the id number of the star and group is its group number. Xcenter and
+ycenter are the fitted coordinates in pixels. Mag and merr are the fitted
+magnitude and magnitude error respectively. Msky is the individual sky value
+for the star. Niter is the number of iterations it took to fit the star and
+sharpness and chi are the sharpness and goodness of fit statistic respectively.
+Pier and perror are the photometry error code and accompanying error message
+respectively.
+
+.ih
+ERRORS
+
+If no errors occur during the fitting process then pier is 0. Non-zero
+values of pier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 1 # The star is in a group too large to fit
+ 2 # The sky is undefined
+ 3 # There are too few good pixels to fit the star
+ 4 # The fit is singular
+ 5 # The star is too faint
+ 6 # The star has merged with a brighter star
+ 7 # The star is off the image
+.fi
+
+.ih
+EXAMPLES
+
+1. Fit the PSF to a list stars in the test image dev$ypix. Good stars for
+making the PSF model can be found at (442,410), (348,189), and (379,67).
+
+.nf
+ da> datapars.epadu = 14.0
+ da> datapars.readnoise = 75.0
+
+ ... set the gain and readout noise for the detector
+
+ da> daofind dev$ypix default fwhmpsf=2.5 sigma=5.0 threshold=20.0
+
+ ... answer verify prompts
+
+ ... find stars in the image
+
+ ... answer will appear in ypix.coo.1
+
+ da> phot dev$ypix default default annulus=10. dannulus=5. \
+ apertures = 3.0
+
+ ... answer verify prompts
+
+ ... do aperture photometry on the detected stars
+
+ ... answer will appear in ypix.mag.1
+
+ da> display dev$ypix 1
+
+ da> psf dev$ypix default "" default default default psfrad=11.0 \
+ fitrad=3.0 mkstars=yes display=imdr
+
+ ... verify the critical parameters
+
+ ... move the image cursor to a candidate star and hit the a key,
+ a plot of the stellar data appears
+
+ ... type ? for a listing of the graphics cursor menu
+
+ ... type a to accept the star, d to reject it
+
+ ... move to the next candidate stars and repeat the previous
+ steps
+
+ ... type l to list all the psf stars
+
+ ... type f to fit the psf
+
+ ... move cursor to first psf star and type s to see residuals,
+ repeat for all the psf stars
+
+ ... type w to save the PSF model
+
+ ... type q to quit, and q again to confirm
+
+ ... the output will appear in ypix.psf.1.imh, ypix.pst.1 and
+ ypix.psg.1
+
+ da> group dev$ypix default default default
+
+ ... verify the prompts
+
+ ... the output will appear in ypix.grp.1
+
+ da> nstar dev$ypix default default default default
+
+ ... verify the prompts
+
+ ... the results will appear in ypix.nst.1 and ypix.nrj.1
+
+ da> pdump ypix.nst.1 sharpness,chi yes | graph
+
+ ... plot chi versus sharpness, the stars should cluster around
+ sharpness = 0.0 and chi = 1.0, note that the frame does
+ not have a lot of stars
+
+ da> substar dev$ypix default "" default default
+
+ ... subtract the fitted stars
+
+ da> display ypix.sub.1 2
+
+ ... note that the psf stars subtract reasonably well but other
+ objects which are not stars don't
+.fi
+
+
+2. Run nstar on a section of the input image using the group file and PSF
+model derived in example 1 for the parent image and writing the results
+in the coordinate system of the parent image.
+
+.nf
+ da> nstar dev$ypix[150:450,150:450] default default default default \
+ wcsin=tv wcspsf=tv wcsout=tv
+
+ ... answer the verify prompts
+
+ ... fit the stars
+
+ ... the results will appear in ypix.nst.2 and ypix.nrj.2
+
+ da> display dev$ypix[150:450,150:450] 1
+
+ ... display the image
+
+ da> pdump ypix.nst.2 xc,yc yes | tvmark 1 STDIN col=204
+
+ ... mark the stars
+
+ da> substar dev$ypix ypix.nst.2 "" default default
+
+ ... subtract stars from parent image
+
+ ... the output images is ypix.sub.2
+
+
+ da> substar dev$ypix[150:450,150:450] ypix.nst.2 "" default default \
+ wcsin=tv wcspsf=tv wcsout=tv
+
+ ... subtract stars from the nstar input image
+
+ ... the output images is ypix.sub.3
+
+.fi
+
+
+
+3. Run nstar exactly as in example 1 but submit the task to the background.
+Turn off verify and verbose.
+
+.nf
+ da> nstar dev$ypix default default default default verbose- \
+ verify- &
+
+ ... the results will appear in ypix.nst.3 and ypix.nrj.3
+.fi
+
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+datapars,daopars,peak,allstar
+.endhelp
diff --git a/noao/digiphot/daophot/doc/peak.hlp b/noao/digiphot/daophot/doc/peak.hlp
new file mode 100644
index 00000000..9017dcb2
--- /dev/null
+++ b/noao/digiphot/daophot/doc/peak.hlp
@@ -0,0 +1,439 @@
+.help peak May00 noao.digiphot.daophot
+.ih
+NAME
+peak -- fit the PSF model to single stars
+.ih
+USAGE
+peak image photfile psfimage peakfile rejfile
+.ih
+PARAMETERS
+.ls image
+The list of images containing the stars to be fit.
+.le
+.ls photfile
+The list of input photometry files containing initial estimates of the
+positions and magnitudes of the stars to be fit. The number of photometry
+files must be equal to the number of input images. If photfile is "default",
+"dir$default", or a directory specification PSF searches for a file called
+dir$image.mag.# where # is the highest available version number for the file.
+Photfile is usually the output of the DAOPHOT PHOT task, but may also be the
+ output of PEAK itself, or of the DAOPHOT package GROUP, NSTAR, ALLSTAR or
+PSF tasks. Photfile may be an APPHOT/DAOPHOT text database or an STSDAS table.
+.le
+.ls psfimage
+The list of images containing the PSF models computed by the DAOPHOT PSF task.
+The number of PSF images must be equal to the number of input images. If
+psfimage is "default", "dir$default", or a directory specification,
+then PEAK will look for an image with the name image.psf.?, where
+? is the highest existing version number.
+.le
+.ls peakfile
+The list of output photometry files. There must be one output photometry
+file for every input image. If peakfile is "default", "dir$default", or a
+directory specification, then PEAK will write an output file with the name
+image.pk.? where ? is the next available version number. Peakfile is a text
+database if the DAOPHOT package parameter text is "yes", an STSDAS table
+database if it is "no".
+.le
+.ls rejfile
+The list of output rejected photometry files containing the positions and sky
+values of stars that could not be fit. If rejfile is undefined, results for all
+the stars in photfile are written to \fIpeakfile\fR, otherwise only the stars
+which were successfully fit are written to \fIpeakfile\fR and the remainder are
+written to rejfile. If rejfile is "default", "dir$default", or a directory
+specification PEAK writes an output file with the name image.prj.? where ? is
+the next available version number. Otherwise rejfile must specify one output
+photometry file for every input image. Rejfile is a text database if the
+DAOPHOT package parameter \fItext\fR is "yes", an STSDAS binary table database
+if it is "no".
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters. The parameters
+\fIscale\fR, \fIdatamin\fR, and \fIdatamax\fR are located here. If datapars
+is undefined then the default parameter set in uparm directory is used.
+.le
+.ls daopars = ""
+The name of the file containing the daophot fitting parameters. The parameters
+\fIpsfrad\fR and \fIfitrad\fR are located here. If \fIdaopars\fR is undefined
+then the default parameter set in uparm directory is used.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout", wcspsf = ")_.wcspsf"
+The coordinate system of the input coordinates read from \fIphotfile\fR, of the
+psf model \fIpsfimage\fR, and of the output coordinates written to
+\fIpeakfile\fR and \fIrejfile\fR respectively. The image header coordinate
+system is used to transform from the input coordinate system to the "logical"
+pixel coordinate system used internally, from the internal logical system to
+the PSF model system, and from the internal "logical" pixel coordinate system
+to the output coordinate system. The input coordinate system options are
+"logical", "tv", "physical", and "world". The PSF model and output coordinate
+system options are "logical", "tv", and "physical". The image cursor coordinate
+system is assumed to be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin, wcspsf, and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin, wcspsf, and wcsout are "logical", "physical" and "logical" respectively.
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default caching is
+disabled.
+.le
+.ls verify = ")_.verify"
+Verify the critical PEAK task parameters? Verify can be set to the DAOPHOT
+package parameter value (the default), "yes", or "no".
+.le
+.ls update = ")_.update"
+Update the PEAK task parameters if \fIverify\fR is "yes"? Update can be
+set to the default daophot package parameter value, "yes", or "no".
+.le
+.ls verbose = ")_.verbose"
+Print messages about the progress of the task ? Verbose can be set to the
+DAOPHOT package parameter value (the default), "yes", or "no".
+.le
+.ih
+DESCRIPTION
+PEAK computes x and y centers, sky values and magnitudes for all the stars in
+\fIphotfile\fR by fitting the PSF model in \fIpsfimage\fR to single stars in
+\fIimage\fR. PEAK reads initial estimates of the centers and magnitudes along
+with the sky values from the photometry file \fIphotfile\fR. \fIPhotfile\fR is
+usually the output of the DAOPHOT PHOT task but may also be the output of PEAK
+itself, NSTAR, ALLSTAR, GROUP or PSF. The computed centers, sky values, and
+magnitudes are written to \fIpeakfile\fR along with the number of iterations
+it took to fit the star, the goodness of fit statistic chi, and the image
+sharpness statistic sharp. If \fIrejfile\fR is defined only stars that are
+successfully fit are written to \fIpeakfile\fR. The remainder are written to
+\fIrejfile\fR. Otherwise all the stars are written to \fIpeakfile\fR.
+\fIPeakfile\fR and \fIrejfile\fR are APPHOT/DAOPHOT text databases if the
+DAOPHOT package parameter \fItext\fR is "yes", STSDAS binary table databases
+if it is "no".
+
+The coordinates read from \fIphotfile\fR are assumed to be in coordinate
+system defined by \fIwcsin\fR. The options are "logical", "tv", "physical",
+and "world" and the transformation from the input coordinate system to the
+internal "logical" system is defined by the image coordinate system. The
+simplest default is the "logical" pixel system. Users working on with image
+sections but importing pixel coordinate lists generated from the parent image
+must use the "tv" or "physical" input coordinate systems.
+
+The coordinate system of the PSF model is the coordinate system defined by the
+\fIwcspsf\fR parameter. Normally the PSF model was derived from the input image
+and this parameter default to "logical". However if the PSF model was derived
+from a larger image which is a "parent" of the input image, then wcspsf should
+be set to "tv" or "physical" depending on the circumstances.
+
+The coordinates written to \fIpeakfile\fR and \fIrejfile\fR are in the
+coordinate system defined by \fIwcsout\fR. The options are "logical", "tv",
+and "physical". The simplest default is the "logical" system. Users wishing to
+correlate the output coordinates of objects measured in image sections or
+mosaic pieces with coordinates in the parent image must use the "tv" or
+"physical" coordinate systems.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If caching
+is enabled and the first measurement will appear to take a long time as the
+entire image must be read in before the measurement is actually made. All
+subsequent measurements will be very fast because PEAK is accessing memory not
+disk. The point of caching is to speed up random image access by making the
+internal image i/o buffers the same size as the image itself. However if the
+input object lists are sorted in row order and sparse caching may actually
+worsen not improve the execution time. Also at present there is no point in
+enabling caching for images that are less than or equal to 524288 bytes, i.e.
+the size of the test image dev$ypix, as the default image i/o buffer is exactly
+that size. However if the size of dev$ypix is doubled by converting it to a
+real image with the chpixtype task then the effect of caching in interactive
+is can be quite noticeable if measurements of objects in the top and bottom
+halves of the image are alternated.
+
+By default PEAK computes new centers for all the stars in \fIphotfile\fR.
+However if the DAOPARS parameter \fIrecenter\fR is "no", PEAK assumes that the
+x and y centers in \fIphotfile\fR are the true centers and does not refit them.
+This option can be quite useful in cases where accurate center values have been
+derived from an image that has been through some non-linear image restoration
+algorithm, but the photometry must be derived from the original unrestored
+image.
+
+By default PEAK uses the sky value in \fIphotfile\fR. However if the DAOPARS
+parameter \fIfitsky\fR is "yes", then PEAK computes a new sky value as part of
+the non-linear least-squares fit. Recomputing the sky can significantly reduce
+the scatter in the magnitudes in regions where the sky background is varying
+rapidly, but users may need to increase the \fIfitrad\fR parameter to include
+more sky pixels in the fit. Users should experiment cautiously with this option.
+
+Only pixels within the good data range delimited by the DATAPARS task parameters
+\fIdatamin\fR and \fIdatamax\fR are included in the fit. Most users set
+\fIdatamin\fR and \fIdatamax\fR to exclude pixels outside the linearity
+regime of the detector. By default all the data is fit. Users are advised to
+determine the values of these parameters for their detector and set the values
+in DATAPARS before beginning DAOPHOT reductions.
+
+Only pixels within the fitting radius set by the DAOPARS task parameter
+\fIfitrad\fR divided by the DATAPARS parameter \fIscale\fR are included in the
+fit. Since the non-linear least-squares fits determine three unknowns, the x
+and y position of the star's centroid and its brightness, the value of
+\fIfitrad\fR must be sufficiently large to include at least three pixels in
+the fit. To accelerate the convergence of the non-linear least-squares fitting
+algorithm, pixels within \fIfitrad\fR are assigned weights which are inversely
+proportional to the radial distance of the pixel from the x and y centroid of
+the star, falling from a maximum at the centroid to zero at the fitting radius.
+\fIFitrad\fR must be sufficiently large to include at least three pixels with
+non-zero weights in the fit. Values of \fIfitrad\fR close to the full-width at
+half-maxima of the PSF are recommended.
+
+PEAK performs a weighted fit to the PSF. The weight of each pixel is computed
+by combining the radial weighting function described above with weights derived
+from the expected random errors computed using the values of the DATAPARS
+parameters \fIreadnoise\fR and \fIepadu\fR specified by the user. Both to
+obtain optimal fits, and because PEAK employs a conservative formula, dependent
+on \fIreadnoise\fR and \fIepadu\fR, for reducing the weights of deviant pixels
+which do not approach the model as the fit proceeds, users are strongly
+advised to determine the values of these parameters accurately, and to enter
+these values in DATAPARS before beginning any DAOPHOT reductions.
+
+For each star to be fit, PEAK extracts a subraster from \fIimage\fR which is N
+by N pixels square where N is approximately 2 * \fIpsfrad\fR / \fIscale\fR + 1
+pixels wide. \fIPsfrad\fR is the PSF radius specified in the DAOPARS task and
+\fIscale\fR is the scale factor specified in the DATAPARS task. \fIPsfrad\fR may
+be less than or equal to, but can never exceed the value of the image header
+parameter "PSFRAD" in \fIpsfimage\fR. \fIPsfrad\fR should be set to a value
+several pixels larger than \fIfitrad\fR in order to permit the x and y
+centroids to wander during the fitting process.
+
+Along with the computed x and y centers and magnitudes, PEAK outputs the number
+of times the PSF fit had to be iterated to reach convergence for each star. The
+minimum number of iterations is three. The maximum number of iteration permitted
+is specified by the \fImaxiter\fR parameter in the DAOPARS task. Obviously the
+results for stars which have reached the maximum iteration count should be
+viewed with suspicion. However since the convergence criteria are quite strict,
+(the computed magnitude must change by less than .001 magnitudes or 0.05 sigma
+whichever is larger and the x and y centroids must change by less than 0.01
+pixels from one iteration to the next), even these stars may be reasonably well
+measured.
+
+PEAK computes a goodness of fit statistic chi which is essentially the ratio of
+the observed pixel-to-pixel scatter in the fit residuals to the expected
+scatter. Since the expected scatter is dependent on the DATAPARS task parameters
+\fIreadnoise\fR and \fIepadu\fR, it is important for these values to be set
+correctly. A plot of chi versus magnitude should scatter around unity with
+little or no trend in chi with magnitude, except at the bright end where
+saturation effects may be present.
+
+Finally PEAK computes the statistic sharp which estimates the intrinsic angular
+size of the measured object outside the atmosphere. Sharp is roughly defined as
+the difference between the square of the width of the object and the square of
+the width of PSF. Sharp has values close to zero for single stars, large
+positive values for blended doubles and partially resolved galaxies, and large
+negative values for cosmic rays and blemishes.
+
+Because PEAK cannot fit stars in crowded fields with overlapped images like the
+NSTAR and ALLSTAR tasks do, and for sparsely populated frames aperture
+photometry produced by PHOT is often just as good and faster to compute, PEAK
+has few unique functions. PEAK is often useful however for fitting and removing
+single stars in images where the stars are interfering with the real object of
+interest such as a galaxy. In that case the PEAK results can be input to SUBSTAR
+which will then remove the interfering stars. Another potential use of PEAK
+is the removal of stars from sparsely populated sky flats in preparation
+for smoothing.
+
+.ih
+OUTPUT
+
+If \fIverbose\fR = yes, a single line is output to the terminal for each star
+fit or rejected. Full output is written to \fIallstarfile\fR and \fIrejfile\fR.
+At the beginning of these two files a header listing the current values of the
+parameters is written. For each star fit/rejected the following quantities are
+written to the output file.
+
+.nf
+ id xcenter ycenter mag merr msky niter sharpness chi
+ pier perr
+.fi
+
+Id is the id number of the star. Xcenter and ycenter are the fitted coordinates
+in pixels. Mag and merr are the fitted magnitude and magnitude error
+respectively. Msky is the individual sky value for the star. Niter is the
+number of iterations it took to fit the star and sharpness and chi are the
+sharpness and goodness of fit statistic respectively. Pier and perror are the
+photometry error code and accompanying error message respectively.
+
+.ih
+ERRORS
+
+If no errors occur during the fitting process then pier is 0. Non-zero
+values of pier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 1 # The sky is undefined
+ 2 # There are too few good pixels to fit the star
+ 3 # The fit is singular
+ 4 # The star is too faint
+.fi
+
+.ih
+EXAMPLES
+
+
+1. Compute the PSF model for the test image dev$ypix. Good stars for making the
+PSF model can be found at (442,410), (348,189), and (379,67).
+
+
+.nf
+ da> datapars.epadu = 14.0
+ da> datapars.readnoise = 75.0
+
+ ... set the gain and readout noise for the detector
+
+ da> daofind dev$ypix default fwhmpsf=2.5 sigma=5.0 threshold=20.0
+
+ ... answer verify prompts
+
+ ... find stars in the image
+
+ ... answer will appear in ypix.coo.1
+
+ da> phot dev$ypix default default annulus=10. dannulus=5. \
+ apertures = 3.0
+
+ ... answer verify prompts
+
+ ... do aperture photometry on the detected stars
+
+ ... answer will appear in ypix.mag.1
+
+ da> display dev$ypix 1
+
+ da> psf dev$ypix default "" default default default psfrad=11.0 \
+ fitrad=3.0 mkstars=yes display=imdr
+
+ ... verify the critical parameters
+
+ ... move the image cursor to a candidate star and hit the a key,
+ a plot of the stellar data appears
+
+ ... type ? for a listing of the graphics cursor menu
+
+ ... type a to accept the star, d to reject it
+
+ ... move to the next candidate stars and repeat the previous
+ steps
+
+ ... type l to list all the psf stars
+
+ ... type f to fit the psf
+
+ ... move cursor to first psf star and type s to see residuals,
+ repeat for all the psf stars
+
+ ... type w to save the PSF model
+
+ ... type q to quit, and q again to confirm
+
+ ... the output will appear in ypix.psf.1.imh, ypix.pst.1 and
+ ypix.psg.1
+
+ da> peak dev$ypix default default default default
+
+ ... the results will appear in ypix.pk.1 and ypix.prj.1
+
+ da> pdump ypix.pk.1 sharpness,chi yes | graph
+
+ ... plot chi versus sharpness, the stars should cluster around
+ sharpness = 0.0 and chi = 1.0, note that the frame does
+ not have a lot of stars
+
+ da> substar dev$ypix ypix.pk.1 "" default default
+
+ ... subtract the fitted stars
+
+ da> display ypix.sub.1 2
+
+ ... note that the psf stars subtract reasonably well but other
+ objects which are not stars don't
+.fi
+
+
+2. Run peak on a section of the input image using the photometry file and PSF
+model derived in example 1 for the parent image and writing the results
+in the coordinate system of the parent image.
+
+.nf
+ da> peak dev$ypix[150:450,150:450] default default default default \
+ wcsin=tv wcspsf=tv wcsout=tv
+
+ ... answer the verify prompts
+
+ ... fit the stars
+
+ ... the results will appear in ypix.pk.2 and ypix.prj.2
+
+ da> display dev$ypix[150:450,150:450] 1
+
+ ... display the image
+
+ da> pdump ypix.pk.2 xc,yc yes | tvmark 1 STDIN col=204
+
+ ... mark the stars
+
+ da> substar dev$ypix ypix.pk.2 "" default default
+
+ ... subtract stars from parent image
+
+ ... the output images is ypix.sub.2
+
+
+ da> substar dev$ypix[150:450,150:450] ypix.pk.2 "" default default \
+ wcsin=tv wcspsf=tv wcsout=tv
+
+ ... subtract stars from the peak input image
+
+ ... the output images is ypix.sub.3
+
+.fi
+
+.ih
+TIME REQUIREMENTS
+
+.ih
+BUGS
+.ih
+SEE ALSO
+datapars,daopars,nstar,allstar
+.endhelp
diff --git a/noao/digiphot/daophot/doc/pexamine.hlp b/noao/digiphot/daophot/doc/pexamine.hlp
new file mode 100644
index 00000000..920634bc
--- /dev/null
+++ b/noao/digiphot/daophot/doc/pexamine.hlp
@@ -0,0 +1,780 @@
+.help pexamine May00 noao.digiphot.daophot
+.ih
+NAME
+pexamine -- interactively examine or edit a photometry catalog
+.ih
+USAGE
+pexamine input output image
+.ih
+PARAMETERS
+.ls input
+The name of the input photometry catalog. Input may be either an APPHOT/DAOPHOT
+text database file or an STSDAS binary table database.
+.le
+.ls output
+The name of the edited output catalog. Output is either an APPHOT/DAOPHOT text
+database or an STSDAS binary table database depending on the file type of
+\fIinput\fR. If output = "" no output catalog is written.
+.le
+.ls image
+The name of the input image corresponding to the input photometry catalog. If
+\fIimage\fR is "" no image will be attached to PEXAMINE and some interactive
+catalog examining commands will not be available. All the catalog editing
+commands however are still available.
+.le
+.ls deletions = ""
+The name of an optional output deletions photometry catalog. Deletions is either
+an APPHOT/DAOPHOT text database or an STSDAS binary table database depending on
+the file type of \fIinput\fR. If deletions is "" no deletions file is written.
+.le
+.ls photcolumns = "daophot"
+The list of standard photometry columns that are loaded when pexamine is run.
+The options are listed below.
+.ls "daophot"
+The standard columns for the DAOPHOT package. The current list is GROUP, ID,
+XCENTER, YCENTER, MSKY, MAG, MERR, CHI, SHARP and NITER. If any of these columns
+are multi-valued, (as in the case of magnitudes measured through more than one
+aperture), the first value is selected. The standard list may easily be
+extended at user request.
+.le
+.ls "apphot"
+The standard columns for the APPHOT package. The current list is ID, XCENTER,
+YCENTER, MSKY, MAG, and MERR. If any of these columns are multi-valued, (as in
+the case of magnitudes measured through more than one aperture), the first
+value is selected. The standard list may easily be extended at user request.
+.le
+.ls user list
+A user supplied list of standard columns. Column names are listed in full in
+either upper or lower case letters, separated by commas. If more than one value
+of a multi-valued column is requested the individual values must be listed
+separately as in the following example ID, XCENTER, YCENTER, MAG[1], MERR[1],
+MAG[2], MERR[2].
+.le
+Photcolumns can be changed interactively from within PEXAMINE at the cost
+of rereading the database.
+.le
+.ls xcolumn = "mag" (magnitude), ycolumn = "merr" (magnitude error)
+The names of the two columns which define the default X-Y plot. Xcolumn and
+ycolumn must be listed in \fIphotcolumns\fR or \fIusercolumns\fR but may be
+changed interactively by the user. If either xcolumn or ycolumn is a
+multi-valued quantity and more than one value is listed in \fIphotcolumns\fR
+or \fIusercolumns\fR then the desired value number must be specified explicitly
+in, e.g. MAG[2] or MERR[2].
+.le
+.ls hcolumn = "mag" (magnitude)
+The name of the column which defines the default histogram plot. Hcolumn
+must be listed in \fIphotcolumns\fR or \fIusercolumns\fR but may be changed
+interactively by the user. If hcolumn is a multi-valued quantity and more than
+one value is listed in \fIphotcolumns\fR or \fIusercolumns\fR then the desired
+value must be specified explicitly in hcolumn, e.g. MAG[2].
+.le
+.ls xposcolumn = "xcenter", yposcolumn = "ycenter"
+The names of the two columns which define the X and Y coordinates in \fIimage\fR
+of the objects in the catalog. This information is required if the image
+display and image cursor are to be used to visually identify objects in the
+image with objects in the catalog or if plots of image data are requested.
+Xposcolumn and yposcolumn must be listed in \fIphotcolumns\fR or
+\fIusercolumns\fR but may be changed interactively by the user.
+.le
+.ls usercolumns = ""
+The list of columns loaded into memory in addition to the standard photometry
+columns \fIphotcolumns\fR. The column names are listed in full in upper or
+lower case letters and separated by commas. Usercolumns can be changed
+interactively from within PEXAMINE at the cost of rereading the database.
+.le
+.ls first_star = 1
+The index of the first object to be read out of the catalog.
+.le
+.ls max_nstars = 5000
+The maximum number of objects that are loaded into memory at task startup time,
+beginning at object \fIfirst_star\fR. If there are more than max_nstars in the
+catalog only the first max_nstars objects are read in.
+.le
+.ls match_radius = 2.0
+The tolerance in pixels to be used for matching objects in the catalog with
+objects marked on the display with the image cursor.
+.le
+.ls use_display = yes
+Use the image display? Users without access to an image display should set
+use_display to "no".
+.le
+.ls icommands = ""
+The image display cursor. If null the standard image cursor is used whenever
+image cursor input is requested. A cursor file in the appropriate format may be
+substituted by specifying the name of the file. Also the image cursor may be
+changed to query the graphics device or the terminal by setting the environment
+variable "stdimcur" to "stdgraph" or "text" respectively.
+.ls gcommands = ""
+The graphics cursor. If null the standard graphics cursor is used whenever
+graphics cursor input is requested. A cursor file in the appropriate format may
+be substituted by specifying the name of the file.
+.le
+.ls graphics = "stdgraph"
+The default graphics device.
+.le
+
+.ih
+PLOTTING PARAMETERS
+
+PEXAMINE supports five types of plots 1) an X-Y column plot 2) a histogram
+column plot 3) a radial profile plot 4) a surface plot and 5) a contour plot.
+Each supported plot type has its own parameter set which controls the
+appearance of the plot. The names of the five parameter sets are listed below.
+
+.nf
+ cntrplot Parameters for the contour plot
+ histplot Parameters for the column histogram plot
+ radplot Parameters for radial profile plot
+ surfplot Parameters for surface plot
+ xyplot Parameters for the X-Y column plot
+.fi
+
+The same parameters dealing with graph formats occur in many of the parameter
+sets while some are specific only to one parameter set. In the summary below
+those common to more than one parameter set are shown only once. The characters
+in parenthesis are the graph key prefixes for the parameter sets in which the
+parameter occurs.
+
+.ls angh = -33., angv = 25. (s)
+Horizontal and vertical viewing angles in degrees for surface plots.
+.le
+.ls axes = yes (s)
+Draw axes along the edge of surface plots ?
+.le
+.ls banner = yes (chrsx)
+Add a standard banner to a graph ? The standard banner includes the IRAF user
+and host identification and the date and time.
+.le
+.ls box = yes (chrx)
+Draw graph box and axes ?
+.le
+.ls ceiling = INDEF (cs)
+Ceiling data value for contour and surface plots. A value of INDEF does not
+apply a ceiling. In contour plots a value of 0. also does not apply a ceiling.
+.le
+.ls dashpat = 528 (c)
+Dash pattern for negative contours.
+.le
+.ls fill = no (yes) (c) (hrx)
+Fill the output viewport regardless of the device aspect ratio ?
+.le
+.ls floor = INDEF (cs)
+Floor data value for contour and surface plots. A value of INDEF does not apply
+a floor. In contour plots a value of 0. also does not apply a floor.
+.le
+.ls grid = no (rx)
+Draw grid lines at major tick marks ?
+.le
+.ls interval = 0.0 (c)
+Contour interval. If 0.0, a contour interval is chosen which places 20 to 30
+contours spanning the intensity range of the image.
+.le
+.ls label= no (c)
+Label the major contours in the contour plot ?
+.le
+.ls logx = no, logy = no (rx) (hrx)
+Plot the x or y axis logarithmically ? The default for histogram plots is to
+plot the y axis logarithmically.
+.le
+.ls majrx=5, minrx=5, majry=5, minry=5 (chrx)
+Maximum number of major tick marks on each axis and number of minor tick marks
+between major tick marks.
+.le
+.ls marker = "box" (rx)
+Marker to be drawn. Markers are "point", "box", "cross", "plus", "circle",
+"hline", "vline" or "diamond".
+.le
+.ls nbins = 512 (h)
+The number of bins in, or resolution of, histogram plots.
+.le
+.ls ncolumns = 21, nlines = 21 (cs)
+Number of columns and lines used in contour and surface plots.
+.le
+.ls ncontours = 5 (c)
+Number of contours to be drawn. If 0, the contour interval may be specified,
+otherwise 20 to 30 nicely spaced contours are drawn. A maximum of 40 contours
+can be drawn.
+.le
+.ls nhi = -1 (c)
+If -1, highs and lows are not marked. If 0, highs and lows are marked on the
+plot. If 1, the intensity of each pixel is marked on the plot.
+.le
+.ls rinner = 0, router = 8
+The inner and outer radius of the region whose radial profile is to be plotted.
+.le
+.ls round = no (chrx)
+Extend the axes up to "nice" values ?
+.le
+.ls szmarker = 1 (rx)
+Size of mark except for points. A positive size less than 1 specifies a fraction
+of the device size. Values of 1, 2, 3, and 4 signify default sizes of increasing
+size.
+.le
+.ls ticklabels = yes (chrx)
+Label the tick marks ?
+.le
+.ls top_closed = no (h)
+Include z2 in the top histogram bin ? Each bin of the histogram is a subinterval
+that is half open at the top. Top_closed decides whether those pixels with
+values equal to z2 are to be counted in the histogram. If top_closed is yes,
+the top bin will be larger than the other bins.
+.le
+.ls x1 = INDEF, x2 = INDEF, y1 = INDEF, y2 = INDEF (hrx)
+Range of graph along each axis. If INDEF the range is determined from the data
+range. The default y1 for histogram plots is 0.
+.le
+.ls zero = 0. (c)
+Grayscale value of the zero contour, i.e., the value of a zero point shift
+to be applied to the image data before plotting. Does not affect the values
+of the floor and ceiling parameters.
+.le
+.ls z1 = INDEF, z2 = INDEF (h)
+Range of pixel values to be used in histogram. INDEF values default to the
+range in the region being histogramed.
+.le
+
+.ih
+DESCRIPTION
+
+PEXAMINE is a general purpose tool for interactively examining and editing
+photometry catalogs produced by the APPHOT or DAOPHOT packages. It is intended
+to aid the user in assessing the accuracy of the photometry, in diagnosing
+problems with particular catalog objects, in searching the photometry data for
+relationships between the computed quantities, and in editing the catalog
+based on those observed relationships. PEXAMINE is intended to complement the
+more batch oriented editing facilities of the PSELECT task.
+
+PEXAMINE takes the input catalog \fIinput\fR and the corresponding image
+\fIimage\fR (if defined) and produces an output catalog of selected objects
+\fIoutput\fR (if defined) and an output catalog of deleted objects
+\fIdeletions\fR (if defined). The input catalog may be either an APPHOT/DAOPHOT
+text database or an ST binary table database. The file type of the output
+catalogs \fIoutput\fR and \fIdeletions\fR is the same as that of \fIinput\fR.
+
+READING IN THE DATA
+
+PEXAMINE reads the column data specified by \fIphotcolumns\fR and
+\fIusercolumns\fR for up to \fImax_nstars\fR into memory. If there are more
+than \fImax_nstars\fR in the input catalog only the data for the first
+\fImax_nstars\fR is read. The \fIphotcolumns\fR parameter defines the list of
+standard photometry columns to be loaded. If "daophot" or "apphot" is selected
+then the standard columns are GROUP, ID, XCENTER, YCENTER, MSKY, MAG, MERR,
+CHI, SHARP and NITER and ID, XCENTER, YCENTER, MSKY, MAG and MERR respectively.
+Otherwise the user must set \fIphotcolumns\fR to his or her own preferred list
+of standard photometry columns. Non-standard columns may also be specified
+using the parameter \fIusercolumns\fR. Valid column lists contain the full
+names of the specified columns in upper or lower case letters, separated by
+commas. Either \fIphotcolumns\fR or \fIusercolumns\fR may be redefined
+interactively by the user after the task has started up, but only at the
+expense of rereading the data from \fIinput\fR.
+
+PEXAMINE will fail to load a specified column if that column is not in the
+photometry database, is of a datatype other than integer or real, or adding
+that column would exceed the maximum number of columns limit currently set at
+twenty. The user can interactively examine the list of requested and loaded
+standard photometry columns, as well as list all the columns in the input after
+the task has started up.
+
+GRAPHICS AND IMAGE COMMAND MODE
+
+PEXAMINE accepts commands either from the graphics cursor \fIgcommands\fR
+(graphics command mode) or the image display cursor \fIicommands\fR if available
+(image command mode). PEXAMINE starts up in graphics command mode, but all the
+interactive commands are accessible from both modes and the user can switch
+modes at any time assuming that the \fIuse_display\fR parameter to "yes".
+
+PEXAMINE interprets the cursor position in graphics mode differently from how
+it interprets it in image command mode. In graphics command mode the cursor
+coordinates are the position of the cursor in the current plot, whereas in
+image command mode they are the x and y coordinates of the cursor in the
+displayed image. For example, if the user issues a command to PEXAMINE to
+locate the object in the catalog nearest the point in the current X-Y plot
+marked by the graphics cursor, PEXAMINE does so by searching the data for the
+object whose values of \fIxcolumn\fR and \fIycolumn\fR most closely match those
+of the current cursor position. If the user issues a command to PEXAMINE to
+locate the object in the catalog corresponding to the object marked on the
+image display with the image cursor, PEXAMINE does so by searching the data for
+the object whose values of \fIxposcolumn\fR and \fIyposcolumn\fR most closely
+match and fall within \fImatch_radius\fR of the current cursor position.
+
+Input to PEXAMINE is through single keystroke commands or colon commands.
+Keystroke commands are simple commands that may optionally use the cursor
+position but otherwise require no arguments. The PEXAMINE keystroke commands
+fall into three categories, basic commands, data examining commands and data
+editing commands, all described in detail in the following sections. Colon
+commands take an optional argument and function differently depending on the
+presence or absence of that argument. When the argument is absent colon
+commands are used to display the current value of a parameter or list of
+parameters. When the argument is present they change their current value to
+that argument. The basic colon commands are described in detail below.
+
+BASIC KEYSTROKE COMMANDS
+
+These keystroke commands are used to display the help page, switch from
+graphics to image command mode and quit the task.
+
+.ls ?
+Page through the help for the PEXAMINE task
+.le
+.ls :
+Execute a PEXAMINE colon command.
+.le
+.ls g
+Change to graphics command mode. Throughout PEXAMINE graphics command mode is
+the default. All PEXAMINE commands are available in graphics command mode.
+.le
+.ls i
+Change to image command mode. All the PEXAMINE commands are available in image
+command mode. However if \fIuse_display\fR is no and the image cursor has not
+been aliased to the standard input or a text file image command mode is
+disabled.
+.le
+.ls q
+Quit PEXAMINE without writing an output catalog. PEXAMINE queries the user for
+confirmation of this option.
+.le
+.ls e
+Quit PEXAMINE and write the output catalog.
+.le
+
+DATA EXAMINING COMMANDS
+
+The data examining commands fall into two categories, those that examine the
+catalog data including 'l' (catalog listing), 'o' (object listing), 'x' (Y
+column versus X column plot) and 'h' (histogram column plot) commands, and
+those which examine the image data around specific catalog objects including
+'r' (radial profile plotting), 's' (surface plotting), 'c' (contour plotting)
+and 'm' (pixel dumping). The latter group require that \fIimage\fR be defined.
+A brief summary of each data examining command is given below.
+.ls l
+Print out the name, datatype, and units for all the columns in the input
+catalog. The list command can be used to check the contents of the input
+catalog and/or determine why a particular column was not loaded.
+.le
+.ls o
+Print out the names and values of the stored columns of the object nearest the
+cursor. In graphics mode the current plot type must be X-Y. In image command
+mode the object nearest the cursor must also be no more than \fImatch-radius\fR
+pixels away from the image cursor to be found. If an object is found and the
+current plot type is X-Y the graphics cursor is moved to the position of the
+selected object in the X-Y plot.
+.le
+.ls x
+Plot the data in \fIycolumn\fR versus the data in \fIxcolumn\fR excluding any
+already deleted points and identifying objects marked for deletion with a
+cross. X-Y plotting is undefined if \fIxcolumn\fR or \fIycolumn\fR is undefined.
+.le
+.ls h
+Plot the histogram of the data in \fIhcolumn\fR excluding any already deleted
+points and those marked for deletion. Histogram plotting is disabled if
+\fIhcolumn\fR is undefined.
+.le
+.ls r
+Plot the radial profile of the object nearest the cursor including only pixels
+within a distance of \fIrinner\fR and \fIrouter\fR of the object center. Radial
+profile plotting is disabled if \fIimage\fR or \fIxposcolumn\fR or
+\fIyposcolumn\fR is undefined.
+.le
+.ls s
+Plot the surface plot of the object nearest the cursor including only pixels
+within an image section \fIncols\fR by \fInlines\fR around the object center.
+Surface plotting is disabled if \fIimage\fR or \fIxposcolumn\fR or
+\fIyposcolumn\fR is undefined.
+.le
+.ls c
+Plot the contour plot of the object nearest the cursor including only pixels
+within an image section \fIncols\fR by \fInlines\fR around the object center.
+Contour plotting is disabled if \fIimage\fR or \fIxposcolumn\fR or
+\fIyposcolumn\fR is undefined.
+.le
+.ls m
+Dump the pixel values of a grid of 10 by 10 pixels around the object nearest
+the cursor. Pixel value dumping is disabled if \fIimage\fR or \fIxposcolumn\fR
+or \fIyposcolumn\fR is undefined.
+.le
+.ls p
+Replot the current graph.
+.le
+
+DATA EDITING COMMANDS
+
+Data points can be deleted from the catalog in either graphics command mode or
+image command mode. In graphics command mode the graphics cursor and either the
+X-Y or histogram plot is used to delete points. In image command mode the image
+cursor and the displayed image are used to delete points. A data point has three
+possible states good, marked for deletion and deleted. Any one of the keystroke
+commands 'd' (delete point), '(' (delete points with x less than x cursor),
+')' (delete points with x greater than x cursor, '^' (delete points with y > y
+cursor), 'v' (delete points with y < y cursor) or 'b' (delete points in a box)
+can be used to mark points for deletion. The 'f' key is used to actually delete
+the points and replot the data. In between marking the points for deletion and
+actually deleting the marked points the 't' (toggle) key can be used to undelete
+the last set marked. The full list of the data editing keystroke commands is
+given below.
+
+.ls z
+Undelete not just unmark all the data points replot.
+.le
+.ls f
+Delete points marked for deletion and replot. Points marked for deletion but
+not actually deleted will be written to the output catalog and not written to
+the deletions catalog.
+.le
+.ls d
+Mark the point nearest the cursor for deletion.
+.le
+.ls u
+Undelete the marked point nearest the cursor.
+.le
+.ls (
+Mark all points with x values less than the x value of the cursor for deletion.
+In graphics command mode points can only be marked for deletion if the current
+plot type is "xyplot" or "histplot". In image command mode \fIxposcolumn\fR and
+\fIyposcolumn\fR must be defined before points can be marked for deletion.
+.le
+.ls )
+Mark all points with x values greater than the x value of the cursor for
+deletion. In graphics command mode points can only be marked for deletion if
+the current plot type is "xyplot" or "histplot". In image command mode
+\fIxposcolumn\fR and \fIyposcolumn\fR must be defined before points can be
+marked for deletion.
+.le
+.ls v
+Mark all points with y values less than the y value of the cursor for deletion.
+In graphics command mode points can only be marked for deletion if the current
+plot type is "xyplot". In image command mode \fIxposcolumn\fR and
+\fIyposcolumn\fR must be defined before points can be marked for deletion.
+.le
+.ls ^
+Mark all points with y values greater than the y value of the cursor for
+deletion. In graphics command mode points can only be marked for deletion if
+the current plot type is "xyplot". In image command mode \fIxposcolumn\fR and
+\fIyposcolumn\fR must be defined before points can be marked for deletion.
+.le
+.ls b
+Mark all points within a box whose lower left and upper right hand corners are
+marked by the cursor for deletion. In graphics mode points can only be marked
+for deletion if the current plot type is "xyplot". In image command mode
+\fIxposcolumn\fR and \fIyposcolumn\fR must be defined before points can be
+marked for deletion.
+.le
+.ls t
+Toggle between marking points for deletion or undeletion. The default is to
+mark points for deletion.
+.le
+
+BASIC COLON COMMANDS
+
+All the PEXAMINE parameters can be changed interactively with colon commands,
+including those which determine which data is read in, which data is plotted
+and the parameters of each plot. A brief description of the basic commands is
+given here. The full list is given in the following section.
+
+.ls :photcolumns [col1,col2,...]
+Show or set the list of requested standard photometry columns and the list
+of loaded photometry columns. If the user supplies a new list of columns the
+data will be reread from disk.
+.le
+.ls :usercolumns [col1,col2,...]
+Show or set the list of requested user columns and the list of loaded user
+columns. If the user supplies a new list of columns the data will be reread
+from disk.
+.le
+.ls :xcolumn [colname]
+Show or set the name of the column to be plotted along the x axis of the X-Y
+plot.
+.le
+.ls :ycolumn [colname]
+Show or set the name of the column to be plotted along the y axis of the X-Y
+plot.
+.le
+.ls :hcolumn [colname]
+Show or set the name of the column to be whose histogram is to be plotted.
+.le
+.ls :eparam [cntrplot/histplot/radplot/surfplot/xyplot]
+Review or edit the list of parameters for the various plot types.
+.le
+.ls :unlearn [cntrplot/histplot/radplot/surfplot/xyplot]
+Return the list of parameters for the various plot types to their default
+values.
+.le
+.ls :x y key cmd
+Execute any defined keystroke "key" supplying the appropriate x and y value in
+place of the cursor position. In graphics command mode the x and y position are
+assumed to be the position in the current graph. In image command mode the x
+and y position are assumed to be the x and y coordinate in the image display.
+.le
+
+.ih
+COMMANDS
+
+.nf
+ PEXAMINE Interactive Cursor Keystroke Commands
+
+ Basic Commands
+
+? Print help for the PEXAMINE task
+: PEXAMINE colon commands
+g Activate the graphics cursor
+i Activate the image cursor
+e Exit PEXAMINE and save the edited catalog
+q Quit PEXAMINE and discard the edited catalog
+
+ Data Examining Commands
+
+l List the name, datatype and units for all columns in the catalog
+o Print out the names and values of the stored columns for the
+ object nearest the cursor
+x Replot the current y column versus the current x column
+h Replot the current histogram
+r Plot the radial profile of the object nearest the cursor
+s Plot the surface of the object nearest the cursor
+c Plot the contour plot of the object nearest the cursor
+m Print the data values of the object nearest the cursor
+p Replot the current graph
+
+ Data Editing Commands
+
+z Reinitialize the data by removing all deletions and replot
+d Mark the point nearest the cursor for deletion
+u Undelete the marked point nearest the cursor
+t Toggle between marking points for deletion or undeletion
+( Mark points with X < X (cursor) for deletion or undeletion
+) Mark points with X > X (cursor) for deletion or undeletion
+v Mark points with Y < Y (cursor) for deletion or undeletion
+^ Mark points with Y > Y (cursor) for deletion or undeletion
+b Mark points inside a box for deletion or undeletion
+f Actually delete the marked points and replot
+
+
+ PEXAMINE Interactive Colon Commands
+
+:xcolumn [name] Show/set the X-Y plot X axis quantity
+:ycolumn [name] Show/set the X-Y plot Y axis quantity
+:hcolumn [name] Show/set the histogram plot quantity
+:photcolumns [col1,col2,...] Show/set the list of photometry columns
+:usercolumns [col1,col2,...] Show/set the list of user columns
+:delete [yes/no] Delete or undelete points
+:eparam [x/h/r/s/c] Edit/unlearn the specified plot pset
+ or
+:unlearn
+
+
+ PEXAMINE Interactive X-Y Plotting Commands
+
+:x1 [value] Left world x-coord if not autoscaling
+:x2 [value] Right world x-coord if not autoscaling
+:y1 [value] Lower world y-coord if not autoscaling
+:y2 [value] Upper world y-coord if not autoscaling
+:szmarker [value] Marker size
+:marker [point|box|plus|cross|circle|diamond|hline|vline] Marker type
+:logx [yes/no] Log scale the x axis?
+:logy [yes/no] Log scale the y axis?
+:box [yes/no] Draw box around periphery of window?
+:ticklabels [yes/no] Label tick marks?
+:grid [yes/no] Draw grid lines at major tick marks?
+:majrx [value] Number of major divisions along x axis
+:minrx [value] Number of minor divisions along x axis
+:majry [value] Number of major divisions along y axis
+:minry [value] Number of minor divisions along y axis
+:round [yes/no] Round axes to nice values?
+:fill [yes/no] Fill viewport vs enforce unity aspect ratio?
+
+
+ PEXAMINE Interactive Histogram Plotting Commands
+
+:nbins [value] Number of bins in the histogram
+:z1 [value] Minimum histogram intensity
+:z2 [value] Maximum histogram intensity
+:top_closed [y/n] Include z in the top bin?
+:x1 [value] Left world x-coord if not autoscaling
+:x2 [value] Right world x-coord if not autoscaling
+:y1 [value] Lower world y-coord if not autoscaling
+:y2 [value] Upper world y-coord if not autoscaling
+:logy [yes/no] Log scale the y axis?
+:box [yes/no] Draw box around periphery of window?
+:ticklabels [yes/no] Label tick marks?
+:majrx [value] Number of major divisions along x axis
+:minrx [value] Number of minor divisions along x axis
+:majry [value] Number of major divisions along y axis
+:minry [value] Number of minor divisions along y axis
+:round [yes/no] Round axes to nice values?
+:fill [yes/no] Fill viewport vs enforce unity aspect ratio?
+
+ PEXAMINE Interactive Radial Profile Plotting Commands
+
+:rinner [value] Inner radius of the region to be plotted
+:router [value] Outer radius of the region to be plotted
+:x1 [value] Left world x-coord if not autoscaling
+:x2 [value] Right world x-coord if not autoscaling
+:y1 [value] Lower world y-coord if not autoscaling
+:y2 [value] Upper world y-coord if not autoscaling
+:szmarker [value] Marker size
+:marker [point|box|plus|cross|circle|diamond|hline|vline] Marker type
+:logx [yes/no] Log scale the x axis?
+:logy [yes/no] Log scale the y axis?
+:box [yes/no] Draw box around periphery of window?
+:ticklabels [yes/no] Label tick marks?
+:grid [yes/no] Draw grid lines at major tick marks?
+:majrx [value] Number of major divisions along x axis
+:minrx [value] Number of minor divisions along x axis
+:majry [value] Number of major divisions along y axis
+:minry [value] Number of minor divisions along y axis
+:round [yes/no] Round axes to nice values?
+:fill [yes/no] Fill viewport vs enforce unity aspect ratio?
+
+
+ PEXAMINE Interactive Surface Plotting Commands
+
+:ncolumns [value] Number of columns to be plotted
+:nlines [value] Number of lines to be plotted
+:axes [yes/no] Draw axes?
+:angh [value] Horizontal viewing angle
+:angv [value] Vertical viewing angle
+:floor [value] Minimum value to be plotted
+:ceiling [value] Maximum value to be plotted
+
+
+ PEXAMINE Interactive Contour Plotting Commands
+
+:ncolumns [value] Number of columns to be plotted
+:nlines [value] Number of lines to be plotted
+:floor [value] Minimum value to be plotted
+:ceiling [value] Maximum value to be plotted
+:zero [value] Grayscale value of zero contour
+:ncontours [value] Number of contours to be drawn
+:interval [value] Contour interval
+:nhi [value] Hi/low marking option
+:dashpat [value] Bit pattern for generating dashed lines
+:label [yes/no] Label major contours with their values?
+:box [yes/no] Draw box around periphery of window?
+:ticklabels [yes/no] Label tick marks?
+:majrx [value] Number of major divisions along x axis
+:minrx [value] Number of minor divisions along x axis
+:majry [value] Number of major divisions along y axis
+:minry [value] Number of minor divisions along y axis
+:round [yes/no] Round axes to nice values?
+:fill [yes/no] Fill viewport vs enforce unity aspect ratio?
+.fi
+
+.ih
+EXAMPLES
+
+1. Examine and edit an APPHOT aperture photometry catalog and a DAOPHOT
+allstar catalog without either attaching the associated image or using the
+image display.
+
+.nf
+ pt> pexamine ypix.mag.1 ypix.mag.ed use_display-
+
+ ... a plot of magnitude error versus magnitude appears on
+ the screen and the graphics cursor comes up ready to accept
+ commands
+
+ ... the user sees a generally smooth trend of increasing
+ magnitude error with increasing magnitude except for a
+ single deviant point at the bright end of the plot
+
+ ... the user decides to remove the deviant point using the
+ 'd' keystroke command to mark the point and the 'f'
+ keystroke command to actually delete and replot the graph
+
+ ... after examining the plot further the user decides to delete
+ all objects for which the magnitude error is > 0.1 magnitudes
+ using the '^' keystroke command, followed by the 'f'
+ keystroke command to actually replot and delete the data.
+
+ ... after deciding that this new plot is satisfactory the user
+ issues the 'e' keystroke command to exit pexamine and save
+ the good data in m92.mag.ed
+
+ pt> pexamine ypix.als.1 ypix.als.ed use_display-
+
+ ... a plot of magnitude error versus magnitude appears on the
+ screen and the graphics cursor comes up ready to accept
+ commands
+
+ ... after looking at the plot the user decides that what they
+ really want to see is a plot of the goodness of fit parameter
+ chi versus magnitude
+
+ ... the user issues the colon command :ycol chi followed by 'p'
+ keystroke command to replot the data
+
+ ... the user sees a generally smooth trend of increasing
+ chi with increasing magnitude
+
+ ... after examining the plot further the user decides to delete
+ all objects for which the chi value > 2.0 and the
+ magnitude is > 25 using the '^' key and ')' keystroke
+ commands followed by 'f' to save the deletions and replot
+ the data
+
+ ... after deciding that this new plot is satisfactory the user
+ issues the 'e' keystroke command to exit pexamine and save
+ the good data in m92.als.ed
+.fi
+
+2. Examine and edit a DAOPHOT allstar catalog using the subtracted image, the
+original image and the image display.
+
+.nf
+ pt> display ypix.sub.1 1
+
+ ... display the subtracted image
+
+ pt> pexamine ypix.als.1 ypix.als.ed dev$ypix xcol=mag ycol=chi
+
+ ... a plot of the goodness of fit versus magnitude appears
+ on the terminal and the graphics cursor comes up ready to
+ accept commands
+
+ ... the user notices some very anomalous chi values and decides
+ to see if these correspond to objects which have poor
+ subtraction on the displayed image
+
+ ... the user switches to image command mode by tapping the 'i'
+ key, moves to the first poorly subtracted object and taps
+ the 'o' key
+
+ ... a list of the values of the loaded columns including chi
+ appears in the text window , the program switches to graphics
+ mode and places the graphics cursor on the corresponding
+ point in the X-Y plot
+
+ ... the point in question indeed has a very high chi value
+ and the user decides to try and investigate the reason for the
+ anomalous value
+
+ ... the user taps the 'r' key to get a radial profile of the
+ object in the original image
+
+ ... after carefully examining the profile it appears that the
+ object's profile is too broad and that it is not a star
+
+ ... the user switches back to the X-Y plot with the 'x' key,
+ marks the point with the 'd' key and saves the deletions
+ and replots with the 'f' key.
+
+ ... the user goes back to image command mode with the 'i' key
+ and begins investigating the next object
+
+ ... finally after examining the image and making all the changes
+ the user decides to quit and save the changes with the 'e' key
+
+.fi
+
+.ih
+TIME REQUIREMENTS
+
+.ih
+BUGS
+
+INDEF valued points cannot be accessed by PEXAMINE. INDEF valued points should
+be removed from the input catalog with PSELECT prior to entering PEXAMINE.
+
+.ih
+SEE ALSO
+ptools.pselect, ptools.txselect,ptools.tselect
+
+.endhelp
diff --git a/noao/digiphot/daophot/doc/pfmerge.hlp b/noao/digiphot/daophot/doc/pfmerge.hlp
new file mode 100644
index 00000000..a85b60ee
--- /dev/null
+++ b/noao/digiphot/daophot/doc/pfmerge.hlp
@@ -0,0 +1,65 @@
+.help pfmerge May00 noao.digiphot.daophot
+.ih
+NAME
+pfmerge -- merge a list of photometry files
+.ih
+USAGE
+pfmerge inphotfiles outphotfile
+.ih
+PARAMETERS
+.ls inphotfiles
+The list of photometry files to be merged. Inphotfiles may be the output of the
+DAOPHOT tasks PHOT, PSTSELECT, PSF, PEAK, GROUP, GRPSELECT, NSTAR, or ALLSTAR.
+Inphotfiles may be either a list of APPHOT/DAOPHOT text databases or a list of
+STSDAS binary tables.
+.le
+.ls outphotfile
+The output photometry file. Outphotfile consists of the header of the first
+input photometry file, followed by a list of records, one per input file
+record, each consisting of five fields: ID, XCENTER, YCENTER, MAG, and MSKY.
+Outphotfile is a an APPHOT/DAOPHOT text database if the first photometry file
+is a text database, an STSDAS binary table if the first photometry file is an
+ST table.
+.le
+.ls verbose
+Print messages about the progress of the task ?
+.le
+.ih
+DESCRIPTION
+PFMERGE creates a new photometry file suitable for input to PSF, PEAK, GROUP,
+or ALLSTAR by extracting the header of the first input photometry file and the
+values of the five fields: ID, XCENTER, YCENTER, MAG, and MSKY from each
+photometry record in each input file, and writing them to \fIoutphotfile\fR.
+\fIInphotfiles\fR may be either APPHOT/DAOPHOT text databases or STSDAS binary
+tables, but \fIoutphotfile\fR inherits the type of the first input photometry
+file.
+
+The principal application of PFMERGE is to combine the results of one of the
+DAOPHOT fitting tasks, e.g. ALLSTAR, with the results of the aperture photometry
+task PHOT, to create a new photometry file suitable for input to the fitting
+task. e.g. ALLSTAR, since it if often the case that the user wishes to combine
+preliminary results for a few additional stars with the best fit results to
+date on the original star list.
+
+PFMERGE is intended to combine photometry files from different DAOPHOT tasks.
+The task PCONCAT can be used to combine photometry files produced by the same
+task.
+
+.ih
+EXAMPLES
+
+1. Combine the results of the first allstar run with phot task results
+on a small list of stars detected after the first list of stars was
+subtracted from the original image.
+
+.nf
+ cl> pfmerge m92.als.1,m92.mag.5 m92.als.2
+.fi
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+pconcat
+.endhelp
diff --git a/noao/digiphot/daophot/doc/phot.hlp b/noao/digiphot/daophot/doc/phot.hlp
new file mode 100644
index 00000000..cc0033c8
--- /dev/null
+++ b/noao/digiphot/daophot/doc/phot.hlp
@@ -0,0 +1,831 @@
+.help phot May00 noao.digiphot.daophot
+.ih
+NAME
+phot -- do aperture photometry on a list of stars
+.ih
+USAGE
+phot image coords output
+.ih
+PARAMETERS
+.ls image
+The list of images containing the objects to be measured.
+.le
+.ls coords
+The list of text files containing initial coordinates for the objects to
+be centered. Objects are listed in coords one object per line with the
+initial coordinate values in columns one and two. The number of coordinate
+files must be zero, one, or equal to the number of images. If coords is
+"default", "dir$default", or a directory specification then a coords file name
+of the form dir$root.extension.version is constructed and searched for,
+where dir is the directory, root is the root image name, extension is "coo"
+and version is the highest available version number for the file.
+.le
+.ls output
+The name of the results file or results directory. If output is
+"default", "dir$default", or a directory specification then an output file name
+of the form dir$root.extension.version is constructed, where dir is the
+directory, root is the root image name, extension is "mag" and version is
+the next available version number for the file. The number of output files
+must be zero, one, or equal to the number of image files. In both interactive
+and batch mode full output is written to output. In interactive mode
+an output summary is also written to the standard output.
+.le
+.ls skyfile = ""
+The list of text files containing the sky values, of the measured objects,
+one object per line with x, y, the sky value, sky sigma, sky skew, number of sky
+pixels and number of rejected sky pixels in columns one to seven respectively.
+The number of sky files must be zero, one, or equal to the number of input
+images. A skyfile value is only requested if \fIfitskypars.salgorithm\fR =
+"file" and if PHOT is run non-interactively.
+.le
+.ls plotfile = ""
+The name of the file containing radial profile plots of the stars written
+to the output file. If plotfile is defined then a radial profile plot
+is written to plotfile every time a record is written to \fIoutput\fR.
+The user should be aware that this can be a time consuming operation.
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters. The critical
+parameters \fIfwhmpsf\fR and \fIsigma\fR are located here. If \fIdatapars\fR
+is undefined then the default parameter set in uparm directory is used.
+.le
+.ls centerpars = ""
+The name of the file containing the centering parameters. The critical
+parameters \fIcalgorithm\fR and \fIcbox\fR are located here.
+If \fIcenterpars\fR is undefined then the default parameter set in
+uparm directory is used.
+.le
+.ls fitskypars = ""
+The name of the text file containing the sky fitting parameters. The critical
+parameters \fIsalgorithm\fR, \fIannulus\fR, and \fIdannulus\fR are located here.
+If \fIfitskypars\fR is undefined then the default parameter set in uparm
+directory is used.
+.le
+.ls photpars = ""
+The name of the file containing the photometry parameters. The critical
+parameter \fIapertures\fR is located here. If \fIphotpars\fR is undefined
+then the default parameter set in uparm directory is used.
+.le
+.ls interactive = no
+Run the task interactively ?
+.le
+.ls radplots = no
+If \fIradplots\fR is "yes" and PHOT is run in interactive mode, a radial
+profile of each star is plotted on the screen after the star is measured.
+.le
+.ls icommands = ""
+The image display cursor or image cursor command file.
+.le
+.ls gcommands = ""
+The graphics cursor or graphics cursor command file.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout"
+The coordinate system of the input coordinates read from \fIcoords\fR and
+of the output coordinates written to \fIoutput\fR respectively. The image
+header coordinate system is used to transform from the input coordinate
+system to the "logical" pixel coordinate system used internally,
+and from the internal "logical" pixel coordinate system to the output
+coordinate system. The input coordinate system options are "logical", "tv",
+"physical", and "world". The output coordinate system options are "logical",
+"tv", and "physical". The image cursor coordinate system is assumed to
+be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin and wcsout are "logical" and "logical" respectively.
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default caching is
+disabled.
+.le
+.ls verify = ")_.verify"
+Verify the critical PHOT parameters in non-interactive mode ? Verify can be set
+to the DAOPHOT package parameter value (the default), "yes", or "no".
+.le
+.ls update = ")_.update"
+Update the algorithm parameter values if \fIverify\fR is "yes" and
+\fIinteractive\fR is "no" ? Update can be set to the DAOPHOT package parameter
+value (the default), "yes", or "no".
+.le
+.ls verbose = ")_.verbose"
+Print results on the screen in non-interactive mode ? Verbose can be set to
+the DAOPHOT package parameter value (the default), "yes", or "no".
+.le
+.ls graphics = ")_.stdgraph"
+The default graphics device. Graphics may be set to the DAOPHOT package
+parameter value (the default), "yes", or "no".
+.le
+.ls display = ")_.display"
+The default display device. Display may be set to the DAOPHOT package
+parameter value (the default), "yes", or "no". By default graphics overlay is
+disabled. Setting display to one of "imdr", "imdg", "imdb", or "imdy" enables
+graphics overlay with the IMD graphics kernel. Setting display to "stdgraph"
+enables PHOT to work interactively from a contour plot.
+
+.le
+
+.ih
+DESCRIPTION
+
+PHOT computes accurate centers, sky values, and magnitudes for a list of
+objects in the IRAF image \fIimage\fR whose coordinates are read from
+the text file \fIcoords\fR or the image display cursor, and writes the
+computed x and y coordinates, sky values, and magnitudes to the text
+file \fIoutput\fR.
+
+The coordinates read from \fIcoords\fR are assumed to be in coordinate
+system defined by \fIwcsin\fR. The options are "logical", "tv", "physical",
+and "world" and the transformation from the input coordinate system to
+the internal "logical" system is defined by the image coordinate system.
+The simplest default is the "logical" pixel system. Users working on with
+image sections but importing pixel coordinate lists generated from the parent
+image must use the "tv" or "physical" input coordinate systems.
+Users importing coordinate lists in world coordinates, e.g. ra and dec,
+must use the "world" coordinate system and may need to convert their
+equatorial coordinate units from hours and degrees to degrees and degrees first.
+
+The coordinates written to \fIoutput\fR are in the coordinate
+system defined by \fIwcsout\fR. The options are "logical", "tv",
+and "physical". The simplest default is the "logical" system. Users
+wishing to correlate the output coordinates of objects measured in
+image sections or mosaic pieces with coordinates in the parent
+image must use the "tv" or "physical" coordinate systems.
+
+In interactive mode the user may either define the list of objects to be
+measured interactively with the image cursor or create an object list prior
+to running PHOT. In either case the user may adjust the centering, sky fitting,
+ and photometry algorithm parameters until a satisfactory fit is achieved
+and optionally store the final results in \fIoutput\fR. In batch mode the
+initial positions are read from the text file \fIcoords\fR or the image
+cursor parameter \fIicommands\fR can be redirected to a text file containing
+a list of cursor commands. In batch mode the current set of algorithm
+parameters is used.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If caching
+is enabled and PHOT is run interactively the first measurement will appear
+to take a long time as the entire image must be read in before the measurement
+is actually made. All subsequent measurements will be very fast because PHOT
+is accessing memory not disk. The point of caching is to speed up random
+image access by making the internal image i/o buffers the same size as the
+image itself. However if the input object lists are sorted in row order and
+sparse caching may actually worsen not improve the execution time. Also at
+present there is no point in enabling caching for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of caching in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halves of the image are alternated.
+
+
+PHOT computes accurate centers for each object using the centering
+parameters defined in \fIcenterpars\fR, computes an accurate sky value
+for each object using the sky fitting parameters defined in \fIfitskypars\fR,
+ and computes magnitudes using the photometry parameters defined in
+\fIphotpars\fR. The image data characteristics of the data are specified
+in \fIdatapars\fR.
+
+Unlike the APPHOT versions of PHOT the DAOPHOT version of PHOT does NOT
+recenter the stars, as the default input coordinate list is created
+by the DAOFIND task which itself computes accurate centers for the stars.
+DAOPHOT users should set the CENTERPARS task parameter \fIcalgorithm\fR
+to "centroid" if they need to measure stars interactively with the
+image display and image display cursor. The PHOT tasks centers provide
+initial guesses for the PSF modeling and fitting routines in the PSF,
+PEAK, NSTAR, and ALLSTAR tasks.
+
+The DAOPHOT version of PHOT sets the sky fitting algorithm to "mode".
+This algorithm which uses the mean and median to estimate the value
+that the sky would have if the star of interest wasn't there, is in most
+cases the one which will give the best results in crowded fields. Users
+interested in reducing small stellar groups should realizes that they can,
+fix the sky by setting the FITSKYPARS parameter \fIsalgorithm\fR to "constant"
+and setting \fIskyvalue\fR to the desired sky value, or set the sky
+interactively using the "radplot" or "histplot" options. Users with rapidly
+varying sky backgrounds may wish to explore the "median" or "centroid" sky
+fitting algorithm which can be more stable than the "mode" algorithm
+against complex sky pixel histograms. Users with very few counts in their
+data or with quantized data where the standard deviation is small with
+respect to the quantization level may wish to explore the "mean",
+and "centroid" sky fitting algorithms.
+
+The PHOT task sets the instrumental magnitude scale for all the subsequent
+DAOPHOT tasks. Users should be sure they have set the PHOTPARS \fIapertures\fR
+parameter to a reasonable value, and that they have accounted for the
+exposure time by setting either the DATAPARS \fIexposure\fR or \fIitime\fR
+parameters.
+
+
+.ih
+CURSOR COMMANDS
+
+The following list of cursor commands are currently available.
+
+.nf
+ Interactive Keystroke Commands
+
+? Print help
+: Colon commands
+v Verify critical parameters
+w Save current parameters
+d Plot radial profile of current star
+i Set parameters interactively using current star
+c Fit center for current star
+t Fit sky around cursor
+s Fit sky around current centered star
+p Do photometry for current star, using current sky
+o Do photometry for current star, using current sky, output results
+f Do photometry for current star
+spbar Do photometry for current star, output results
+m Move to next star in coordinate list
+n Do photometry for next star in coordinate list, output results
+l Do photometry for remaining stars in coordinate list, output results
+e Print error messages
+r Rewind coordinate list
+q Exit task
+
+
+Photometry parameters are listed or set with the following commands.
+
+ Colon commands
+
+:show [data/center/sky/phot] List the parameters
+:m [n] Move to next [nth] star in coordinate list
+:n [n] Measure next [nth] star in coordinate list, output results
+
+ Colon Parameter Editing Commands
+
+# Image and file name parameters
+
+:image [string] Image name
+:coords [string] Coordinate file name
+:output [string] Output file name
+
+# Data dependent parameters
+
+:scale [value] Image scale (units per pixel)
+:fwhmpsf [value] Full width half maximum of PSF (scale units)
+:emission [y/n] Emission feature (y), absorption (n)
+:sigma [value] Standard deviation of sky (counts)
+:datamin [value] Minimum good data value (counts)
+:datamax [value] Maximum good data value (counts)
+
+# Noise parameters
+
+:noise [string] Noise model (constant|poisson)
+:gain [string] Gain image header keyword
+:ccdread [string] Readout noise image header keyword
+:epadu [value] Gain (electrons per adu)
+:readnoise [value] Readout noise (electrons)
+
+# Observations parameters
+
+:exposure [string] Exposure time image header keyword
+:airmass [string] Airmass image header keyword
+:filter [string] Filter image header keyword
+:obstime [string] Time of observation image header keyword
+:itime [value] Integration time (time units)
+:xairmass [value] Airmass value (number)
+:ifilter [string] Filter id string
+:otime [string] Time of observation (time units)
+
+# Centering algorithm parameters
+
+:calgorithm [string] Centering algorithm
+:cbox [value] Width of the centering box (scale units)
+:cthreshold [value] Centering intensity threshold (sigma)
+:cmaxiter [value] Maximum number of iterations
+:maxshift [value] Maximum center shift (scale units)
+:minsnratio [value] Minimum S/N ratio for centering
+:clean [y/n] Clean subraster before centering
+:rclean [value] Cleaning radius (scale units)
+:rclip [value] Clipping radius (scale units)
+:kclean [value] Clean K-sigma rejection limit (sigma)
+
+# Sky fitting algorithm parameters
+
+:salgorithm [string] Sky fitting algorithm
+:skyvalue [value] User supplied sky value (counts)
+:annulus [value] Inner radius of sky annulus (scale units)
+:dannulus [value] Width of sky annulus (scale units)
+:khist [value] Sky histogram extent (+/- sky sigma)
+:binsize [value] Resolution of sky histogram (sky sigma)
+:smooth [y/n] Lucy smooth the sky histogram
+:sloclip [value] Low-side clipping factor in percent
+:shiclip [value] High-side clipping factor in percent
+:smaxiter [value] Maximum number of iterations
+:snreject [value] Maximum number of rejection cycles
+:sloreject [value] Low-side pixel rejection limits (sky sigma)
+:shireject [value] High-side pixel rejection limits (sky sigma)
+:rgrow [value] Region growing radius (scale units)
+
+# Photometry parameters
+
+:apertures [string] List of aperture radii (scale units)
+:zmag [value] Zero point of magnitude scale
+
+# Plotting and marking parameters
+
+:mkcenter [y/n] Mark computed centers on display
+:mksky [y/n] Mark the sky annuli on the display
+:mkapert [y/n] Mark apertures on the display
+:radplot [y/n] Plot radial profile of object
+
+
+The following commands are available from inside the interactive setup menu.
+
+ Interactive Phot Setup Menu
+
+ v Mark and verify the critical parameters (f,s,c,a,d,r)
+
+ f Mark and verify the full-width half-maximum of psf
+ s Mark and verify the standard deviation of the background
+ l Mark and verify the minimum good data value
+ u Mark and verify the maximum good data value
+
+ c Mark and verify the centering box width
+ n Mark and verify the cleaning radius
+ p Mark and verify the clipping radius
+
+ a Mark and verify the inner radius of the sky annulus
+ d Mark and verify the width of the sky annulus
+ g Mark and verify the region growing radius
+
+ r Mark and verify the aperture radii
+.fi
+
+.ih
+ALGORITHMS
+
+A brief description of the data dependent parameters, centering algorithms,
+sky fitting algorithms and photometry parameters can be found in the
+online help pages for the DATAPARS, CENTERPARS, FITSKYPARS, and PHOTPARS
+tasks.
+
+.ih
+OUTPUT
+
+In interactive mode the following quantities are printed on the standard
+output as each object is measured. Err is a simple string indicating whether
+or not an error was detected in the centering algorithm, the sky fitting
+algorithm or the photometry algorithm. Mag are the magnitudes in apertures 1
+through N respectively and xcenter, ycenter and msky are the x and y centers
+and the sky value respectively.
+
+.nf
+ image xcenter ycenter msky mag[1 ... N] error
+.fi
+
+In both interactive and batch mode full output is written to the text file
+\fIoutput\fR. At the beginning of each file is a header listing the
+current values of the parameters when the first stellar record was written.
+These parameters can be subsequently altered. For each star measured the
+following record is written
+
+.nf
+ image xinit yinit id coords lid
+ xcenter ycenter xshift yshift xerr yerr cier error
+ msky stdev sskew nsky nsrej sier serror
+ itime xairmass ifilter otime
+ rapert sum area mag merr pier perr
+.fi
+
+Image and coords are the name of the image and coordinate file respectively.
+Id and lid are the sequence numbers of stars in the output and coordinate
+files respectively. Cier and cerror are the centering algorithm error code
+and accompanying error message respectively. Xinit, yinit, xcenter, ycenter,
+xshift, yshift, and xerr, yerr are self explanatory and output in pixel units.
+The sense of the xshift and yshift definitions is the following.
+
+
+.nf
+ xshift = xcenter - xinit
+ yshift = ycenter - yinit
+.fi
+
+Sier and serror are the sky fitting error code and accompanying error
+message respectively. Msky, stdev and sskew are the best estimate of the sky
+value (per pixel), standard deviation and skew respectively. Nsky and nsrej
+are the number of sky pixels and the number of sky pixels rejected respectively.
+
+Itime is the exposure time, xairmass is self-evident, ifilter is an
+id string identifying the filter used in the observations, and otime is
+a string containing the time of the observation in whatever units the
+user has set up.
+
+Rapert, sum, area, and flux are the radius of the aperture in scale units,
+the total number of counts including sky in the aperture, the area of the
+aperture in square pixels, and the total number of counts excluding sky
+in the aperture. Mag and merr are the magnitude and error in the magnitude
+in the aperture (see below).
+
+.nf
+ flux = sum - area * msky
+ mag = zmag - 2.5 * log10 (flux) + 2.5 * log10 (itime)
+ merr = 1.0857 * err / flux
+ err = sqrt (flux / epadu + area * stdev**2 +
+ area**2 * stdev**2 / nsky)
+.fi
+
+Pier and perror are photometry error code and accompanying error message.
+
+In interactive mode a radial profile of each measured object is plotted
+in the graphics window if \fIradplots\fR is "yes".
+
+In interactive and batchmode a radial profile plot is written to
+\fIplotfile\fR if it is defined each time the result of an object
+measurement is written to \fIoutput\fR .
+
+
+.ih
+ERRORS
+
+If the object centering was error free then the field cier will be zero.
+Non-zero values of cier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 101 # The centering box is off image
+ 102 # The centering box is partially off the image
+ 103 # The S/N ratio is low in the centering box
+ 104 # There are two few points for a good fit
+ 105 # The x or y center fit is singular
+ 106 # The x or y center fit did not converge
+ 107 # The x or y center shift is greater than maxshift
+ 108 # There is bad data in the centering box
+.fi
+
+If all goes well during the sky fitting process then the error code sier
+will be 0. Non-zero values of sier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 201 # There are no sky pixels in the sky annulus
+ 202 # Sky annulus is partially off the image
+ 203 # The histogram of sky pixels has no width
+ 204 # The histogram of sky pixels is flat or concave
+ 205 # There are too few points for a good sky fit
+ 206 # The sky fit is singular
+ 207 # The sky fit did not converge
+ 208 # The graphics stream is undefined
+ 209 # The file of sky values does not exist
+ 210 # The sky file is at EOF
+ 211 # Cannot read the sky value correctly
+ 212 # The best fit parameter are non-physical
+.fi
+
+If no error occurs during the measurement of the magnitudes then pier is
+0. Non-zero values of pier flag the following error conditions.
+
+.nf
+ 0 # No error
+ 301 # The aperture is off the image
+ 302 # The aperture is partially off the image
+ 303 # The sky value is undefined
+ 305 # There is bad data in the aperture
+.fi
+
+.ih
+EXAMPLES
+
+1. Run PHOT on the image dev$ypix using the coordinate list ypix.coo.1
+created by DAOFIND and the default setup.
+
+.nf
+ da> daofind dev$ypix default fwhmpsf=2.6 sigma=5.0 threshold=20. \
+ verify-
+
+ ... make the coordinate list ypix.coo.1
+
+ da> phot dev$ypix default default
+
+ ... answer the verify prompts
+
+ ... the results will appear in ypix.mag.1
+.fi
+
+
+2. Compute the magnitudes for a few stars in dev$ypix using the display
+and the image cursor. Setup the task parameters using the interactive
+setup menu defined by the i key command and a radial profile plot.
+
+.nf
+ da> display dev$ypix 1 fi+
+
+ ... display the image
+
+ da> phot dev$ypix "" default calgorithm=centroid interactive+
+
+ ... type ? to print an optional help page
+
+ ... move the image cursor to a star
+ ... type i to enter the interactive setup menu
+ ... enter maximum radius in pixels of the radial profile or hit
+ CR to accept the default
+ ... type v to enter the default menu
+ ... set the fwhmpsf, centering radius, inner and outer sky annuli,
+ photometry apertures, and sigma using the graphics cursor and
+ the stellar radial profile plot
+ ... typing <CR> leaves everything at the default value
+ ... type q to quit the setup menu
+
+ ... type the v key to verify the parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... move the image cursor to the stars of interest and tap
+ the space bar
+
+ ... a one line summary of the fitted parameters will appear on the
+ standard output for each star measured
+
+ ... type q to quit and q again to confirm the quit
+
+ ... the output will appear in ypix.mag.2
+.fi
+
+
+3. Compute the magnitudes for a few stars in dev$ypix using a contour plot
+and the graphics cursor. This option is only useful for those (now very few)
+users who have access to a graphics terminal but not to an image display
+server. Setup the task parameters using the interactive setup menu defined by
+the i key command as in example 1.
+
+.nf
+ da> show stdimcur
+
+ ... record the default value of stdimcur
+
+ da> set stdimcur = stdgraph
+
+ ... define the image cursor to be the graphics cursor
+
+ da> contour dev$ypix
+
+ ... make a contour plot of dev$ypix
+
+ da> contour dev$ypix >G ypix.plot1
+
+ ... store the contour plot of dev$ypix in the file ypix.plot1
+
+ da> phot dev$ypix "" default calgorithm="centroid" interactive+ \
+ display=stdgraph
+
+ ... type ? to get an optional help page
+
+ ... move graphics cursor to a star
+ ... type i to enter the interactive setup menu
+ ... enter maximum radius in pixels of the radial profile or CR
+ to accept the default value
+ ... type v to enter the default menu
+ ... set the fwhmpsf, centering radius, inner and outer sky annuli,
+ apertures, and sigma using the graphics cursor and the
+ stellar radial profile plot
+ ... typing <CR> leaves everything at the default value
+ ... type q to quit the setup menu
+
+ ... type the v key to verify the critical parameters
+
+ ... type the w key to save the parameters in the parameter files
+
+ ... retype :.read ypix.plot1 to reload the contour plot
+
+ ... move the graphics cursor to the stars of interest and tap
+ the space bar
+
+ ... a one line summary of the fitted parameters will appear on the
+ standard output for each star measured
+
+ ... type q to quit and q again to verify
+
+ ... full output will appear in the text file ypix.mag.3
+
+ da> set stdimcur = <default>
+
+ ... reset stdimcur to its previous value
+.fi
+
+
+4. Setup and run PHOT interactively on a list of objects temporarily
+overriding the fwhmpsf, sigma, cbox, annulus, dannulus, and apertures
+parameters determined in examples 1 or 2.
+
+.nf
+
+ da> display dev$ypix 1
+
+ ... display the image
+
+ da> phot dev$ypix ypix.coo.1 default calgorithm="centroid" \
+ cbox=7.0 annulus=12.0 dannulus=5.0 apertures="3.0,5.0" \
+ interactive+
+
+ ... type ? for optional help
+
+
+ ... move the graphics cursor to the stars and tap space bar
+
+ or
+
+ ... select stars from the input coordinate list with m / :m #
+ and measure with spbar
+
+ ... measure stars selected from the input coordinate list
+ with n / n #
+
+ ... a one line summary of results will appear on the standard output
+ for each star measured
+
+ ... type q to quit and q again to confirm the quit
+
+ ... the output will appear in ypix.mag.4 ...
+.fi
+
+
+5. Display and measure some stars in an image section and write the output
+coordinates in the coordinate system of the parent image.
+
+.nf
+ da> display dev$ypix[150:450,150:450] 1
+
+ ... display the image section
+
+ da> phot dev$ypix[150:450,150:450] "" default wcsout=tv \
+ calgorithm="centroid" interactive+
+
+ ... move cursor to stars and type spbar
+
+ ... type q to quit and q again to confirm quit
+
+ ... output will appear in ypix.mag.5
+
+ da> pdump ypix.mag.5 xc,yc yes | tvmark 1 STDIN col=204
+.fi
+
+
+6. Run PHOT in batch mode using the coordinate file and the previously
+saved parameters. Verify the critical parameters.
+
+.nf
+ ap> phot dev$ypix default default
+
+ ... output will appear in ypix.mag.6...
+.fi
+
+
+7. Repeat example 6 but assume that the input coordinate are ra and dec
+in degrees and degrees, turn off verification, and submit the task to to
+the background.
+
+.nf
+ da> display dev$ypix 1
+
+ ap> rimcursor wcs=world > radec.coo
+
+ ... move to selected stars and type any key
+
+ ... type ^Z to quit
+
+ da> phot dev$ypix radec.coo default wcsin=world verify- verbose- &
+
+ ... output will appear in ypix.mag.7
+
+ da> pdump ypix.mag.7 xc,yc yes | tvmark 1 STDIN col=204
+
+ ... mark the stars on the display
+.fi
+
+
+8. Run PHOT interactively without using the image display cursor.
+
+.nf
+ da> show stdimcur
+
+ ... record the default value of stdimcur
+
+ da> set stdimcur = text
+
+ ... set the image cursor to the standard input
+
+ da> phot dev$ypix default default interactive+
+
+ ... type ? for optional help
+
+ ... type :m 3 to set the initial coordinates to those of the
+ third star in the list
+
+ ... type i to enter the interactive setup menu
+ ... enter the maximum radius in pixels for the radial profile or
+ accept the default with a CR
+ ... type v to enter the default menu
+ ... set the fwhmpsf, centering radius, inner and outer sky annuli,
+ apertures, and sigma using the graphics cursor and the
+ stellar radial profile plot
+ ... typing <CR> after the prompt leaves the parameter at its default
+ value
+ ... type q to quit the setup menu
+
+ ... type r to rewind the coordinate list
+
+ ... type l to measure all the stars in the coordinate list
+
+ ... a one line summary of the answers will appear on the standard
+ output for each star measured
+
+ ... type q to quit followed by q to confirm the quit
+
+ ... full output will appear in the text file ypix.mag.8
+
+ da> set stdimcur = <default>
+
+ ... reset the value of stdimcur
+
+.fi
+
+8. Use a image cursor command file to drive the PHOT task. The cursor command
+file shown below sets the cbox, annulus, dannulus, and apertures parameters
+computes the centers, sky values, and magnitudes for 3 stars, updates the
+parameter files, and quits the task.
+
+.nf
+ da> type cmdfile
+ : calgorithm centroid
+ : cbox 9.0
+ : annulus 12.0
+ : dannulus 5.0
+ : apertures 5.0
+ 442 410 101 \040
+ 349 188 101 \040
+ 225 131 101 \040
+ w
+ q
+
+ da> phot dev$ypix "" default icommands=cmdfile verify-
+
+ ... full output will appear in ypix.mag.9
+.fi
+
+
+
+
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+
+It is currently the responsibility of the user to make sure that the
+image displayed in the frame is the same as that specified by the image
+parameter.
+
+Commands which draw to the image display are disabled by default.
+To enable graphics overlay on the image display, set the display
+parameter to "imdr", "imdg", "imdb", or "imdy" to get red, green,
+blue or yellow overlays and set the centerpars mkcenter switch to
+"yes", the fitskypars mksky switch to"yes", or the photpars mkapert
+switch to "yes". It may be necessary to run gflush and to redisplay the image
+to get the overlays position correctly.
+
+.ih
+SEE ALSO
+datapars, centerpars, fitskypars, photpars
+.endhelp
diff --git a/noao/digiphot/daophot/doc/photpars.hlp b/noao/digiphot/daophot/doc/photpars.hlp
new file mode 100644
index 00000000..98f4e5f1
--- /dev/null
+++ b/noao/digiphot/daophot/doc/photpars.hlp
@@ -0,0 +1,100 @@
+.help photpars May00 noao.digiphot.daophot
+.ih
+NAME
+photpars -- edit the photometry parameters
+.ih
+USAGE
+photpars
+.ih
+PARAMETERS
+.ls weighting = "constant"
+The type of weighting. The weighting is ignored by the PHOT task. The options
+are:
+.ls constant
+Uniform weights of 1 for each pixel are used.
+.le
+.ls cone
+A conical weighting function of full width half maximum \fIfwhmpsf\fR as
+defined in the DATAPARS parameter set is used.
+.le
+.ls gauss
+A Gaussian weighting function of full width half maximum \fIfwhmpsf\fR as
+defined in the DATAPARS parameter set is used.
+.le
+.le
+.ls apertures = "3" (scale units)
+A list of aperture radii in units of the scale parameter or the name of the
+file containing the list of apertures. List elements may be separated by
+whitespace or commas. A ranges syntax of the form ap1:apN:apstep is also
+supported.
+.le
+.ls zmag = 25.00
+The zero point offset for the magnitude scale.
+.le
+.ls mkapert = no
+Mark the photometry apertures on the displayed image?
+.le
+
+.ih
+DESCRIPTION
+
+The integral of the flux within the circular apertures specified by
+\fIapertures\fR is computed by summing pixels in the aperture with
+the specified weighting function \fIweighting\fR. The fraction of each pixel
+lying within the aperture is computed by an approximation and all the
+approximations are summed. The zero point of the magnitude
+scale is determined by \fIzmag\fR.
+
+\fRApertures\fR is specified in units of the image scale. If \fIscale\fR
+is specified in units of the half-width at half-maximum of the point
+spread function the aperture per pixel a single value of apertures
+will work well on images with differing psfs.
+
+
+.ih
+EXAMPLES
+
+1. List the PHOTPARS parameters.
+
+.nf
+ da> lpar photpars
+.fi
+
+2. Edit the PHOTPARS parameters.
+
+.nf
+ da> photpars
+.fi
+
+3. Edit the PHOTPARS parameters from with the PHOT task.
+
+.nf
+ da> epar phot
+
+ ... edit a few phot parameters
+
+ ... move to the photpars parameter and type :e
+
+ ... edit the photpars parameters and type :wq
+
+ ... finish editing the phot parameters and type :wq
+.fi
+
+4. Save the current PHOTPARS parameter set in a text file photnite1.par.
+ This can also be done from inside a higher level task as in the above
+ example.
+
+.nf
+ da> photpars
+
+ ... type ":w photnite1.par" from within epar
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+epar,datapars,centerpars,fitskypars,phot
+.endhelp
diff --git a/noao/digiphot/daophot/doc/psf.hlp b/noao/digiphot/daophot/doc/psf.hlp
new file mode 100644
index 00000000..5613a8b2
--- /dev/null
+++ b/noao/digiphot/daophot/doc/psf.hlp
@@ -0,0 +1,752 @@
+.help psf May00 noao.digiphot.daophot
+.ih
+NAME
+psf -- build the point spread function for an image
+.ih
+USAGE
+psf image photfile pstfile psfimage opstfile groupfile
+.ih
+PARAMETERS
+.ls image
+The images for which the PSF model is to be built.
+.le
+.ls photfile
+The list of input photometry files. The number of photometry files must
+be equal to the number of input images. If photfile is "default", "dir$default",
+or a directory specification PSF searches for a file called dir$image.mag.#
+where # is the highest available version number for the file. Photfile is
+normally the output of the PHOT task but may also be the output of the PSF,
+PEAK, NSTAR and ALLSTAR tasks. Photfile may be an APPHOT/DAOPHOT text database
+or an STSDAS binary table.
+.le
+.ls pstfile
+The list of input psf star photometry files. The ids of the psf stars in these
+files must be the same as their ids in \fIphotfile\fR. The number of psf
+star files must be zero or equal to the number of input images. If pstfile
+is "default", "dir$default" or a directory specification, PSF searches for
+a file called image.pst.? where ? is the highest existing version number.
+Pstfile is usually the output of the DAOPHOT PSTSELECT task but may also be
+the appropriately edited output psf file produced by PSF itself, or the output
+of the GROUP, NSTAR, PEAK or ALLSTAR tasks. Photfile may be an APPHOT/DAOPHOT
+text database or an STSDAS table.
+.le
+.ls psfimage
+The output PSF model image names or directory. The must be one PSF image name
+for every input image. If psfimage is "default", "dir$default", or a directory
+specification, then PSF creates an image called image.psf.? where ? is the next
+available version number.
+.le
+.ls opstfile
+The output psf star files containing lists of the stars actually used to
+compute the PSF model. There must be one output psf star file for every input
+image. If opstfile is "default", "dir$default", or a directory specification
+then PSF creates a file called image.pst.? where ? is the next available
+version number. If the DAOPHOT package parameter \fItext\fR is "yes" then an
+APPHOT/DAOPHOT text database is written, otherwise an STSDAS binary table is
+written.
+.le
+.ls groupfile
+The output psf star group files listing the PSF stars and their neighbors that
+were used to create the PSF models. There must be one output group file for
+every input image. If groupfile is "default", "dir$default", or a directory
+specification then PSF creates a file called image.psg.? where ? is the
+next available version number. If the DAOPHOT package parameter \fItext\fR is
+"yes" then an APPHOT/DAOPHOT text database is written, otherwise an STSDAS
+table database is written.
+.le
+.ls plotfile = ""
+The name of the output file containing mesh, contour, or profile plots of the
+selected PSF stars. If plotfile is undefined no plot file is created,
+otherwise a mesh, contour, or profile plot is written to this file for each PSF
+star selected. Plotfile is opened in append mode and may become very large.
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters. The parameters
+\fIscale\fR, \fIdatamin\fR, and \fIdatamax\fR are located here. If datapars
+is undefined then the default parameter set in uparm directory is used.
+.le
+.ls daopars = ""
+The name of the file containing the daophot fitting parameters. The parameters
+\fIpsfrad\fR and \fIfitrad\fR are located here. If \fIdaopars\fR is undefined
+then the default parameter set in uparm directory is used.
+.le
+.ls matchbyid = yes
+Match the stars in the psf star list(s) if any to the stars in the input
+photometry files using id numbers (matchbyid = yes) or x and y positions
+(matchbyid = no).
+.le
+.ls interactive = yes
+Fit the PSF interactively ? If interactive = yes and \fIicommands\fR is
+undefined, PSF reads selects the initial list of PSF stars from \fIpstfile\fR
+and waits for commands from the user. If interactive = no and \fIicommands\fR
+is undefined, PSF reads in the candidate PSF stars from \fIpstfile\fR, computes
+ the PSF, and writes it to \fIpsfimage\fR without input from the user. If
+\fIicommands\fR is defined, then interactive = no, and commands are read from
+the image cursor command file.
+.le
+.ls mkstars = no
+Mark the selected or deleted psf stars on the image display ?
+.le
+.ls showplots = yes
+Show plots of the selected PSF stars? After each star is selected
+interactively by the user, a mesh, contour, or profile plot of the data
+subraster around the candidate star is displayed. At this point the user
+can accept or reject the star. In interactive mode the user can set showplots
+to "yes" or "no". In non-interactive mode showplots is always "no".
+.le
+.ls plottype = "mesh"
+The default type of plot displayed when selecting PSF stars. The choices
+are "mesh", "contour", or "radial".
+.le
+.ls icommands = ""
+The image display cursor or the name of the image cursor command file.
+.le
+.ls gcommands = ""
+The graphics cursor or the name of the graphics cursor command file.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout"
+The coordinate system of the input coordinates read from \fIphotfile\fR and
+\fIpstfile\fR, and of the output coordinates written to \fIpsfimage\fR,
+\fIopstfile\fR, \fIgroupfile\fR respectively. The image header coordinate
+system is used to transform from the input coordinate system to the "logical"
+pixel coordinate system used internally, and from the internal "logical" pixel
+coordinate system to the output coordinate system. The input coordinate system
+options are "logical", tv", "physical", and "world". The output coordinate
+system options are "logical", "tv", and "physical". The image cursor coordinate
+system is assumed to be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin and wcsout are "logical" and "logical" respectively.
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default caching is
+disabled.
+.le
+.ls verify = ")_.verify"
+Verify the critical PSF task parameters? Verify can be set to the DAOPHOT
+package parameter value (the default), "yes", or "no".
+.le
+.ls update = ")_.update"
+Update the PSF task parameters if \fIverify\fR is "yes"? Update can be
+set to the default daophot package parameter value, "yes", or "no".
+.le
+.ls verbose = ")_.verbose"
+Print messages about the progress of the task ? Verbose can be set to the
+DAOPHOT package parameter value (the default), "yes", or "no".
+.le
+.ls graphics = ")_.graphics"
+The default graphics device. Graphics can be set to the default DAOPHOT package
+parameter value, "yes", or "no".
+.le
+.ls display = ")_.display"
+The default image display device. Display can be set to the DAOPHOT
+package parameter value (the default), "yes", or "no". By default graphics
+overlay is disabled. Setting display to one of "imdr", "imdg", "imdb", or
+"imdy" enables graphics overlay with the IMD graphics kernel.
+.le
+
+.ih
+DESCRIPTION
+
+The PSF task builds the point spread function for the IRAF image \fIimage\fR
+using stars selected, from the input photometry file \fIphotfile\fR with the
+image cursor, and/or by their ids stored in the psf star file \fIpstfile\fR,
+and writes the PSF model out to the IRAF image \fIpsfimage\fR, the final
+PSF star list to \fIopstfile\fR, and group membership information for the
+selected PSF stars to \fIgroupfile\fR. If the DAOPHOT package parameter
+\fItext\fR is "yes", then \fIgroupfile\fR is an APPHOT/DAOPHOT text database,
+otherwise it is an STSDAS binary table.
+
+The coordinates read from \fIphotfile\fR and \fIpstfile\fR are assumed to be
+in coordinate system defined by \fIwcsin\fR. The options are "logical", "tv",
+"physical", and "world" and the transformation from the input coordinate
+system to the internal "logical" system is defined by the image coordinate
+system. The simplest default is the "logical" pixel system. Users working on
+with image sections but importing pixel coordinate lists generated from the
+parent image must use the "tv" or "physical" input coordinate systems.
+
+The coordinates written to \fIpsfimage\fR, \fIpstfile\fR and \fIgroupfile\fR
+are in the coordinate system defined by \fIwcsout\fR with the exception
+of the psf model center coordinates PSFX and PSFY which are always in the
+logical system of the input image. The options are "logical", "tv", and
+"physical". The simplest default is the "logical" system. Users wishing to
+correlate the output coordinates of objects measured in image sections or
+mosaic pieces with coordinates in the parent image must use the "tv"
+or "physical" coordinate systems.
+
+Suitable PSF stars are normally selected interactively using the image display
+and image cursor and matched with the stars in \fIphotfile\fR using the cursor
+position and a tolerance specified by the \fImatchrad\fR parameter in the
+DAOPARS task. A star must be in the photometry file before it can be used as
+a PSF star. If a match is found, PSF checks that the candidate star is not too
+close to the edge of the image and that it contains no bad pixels as defined
+by \fIdatamin\fR and \fIdatamax\fR in the DATAPARS task. After selection a
+mesh, contour, or profile plot of the data subraster around the candidate star
+is displayed in the graphics window, PSF enters graphics cursor command mode
+and the user is given the option to accept or reject the star. If the user
+accepts the star it is added to the PSF star list. Commands in the graphics
+cursor menu permit the user to manipulate the floor and ceiling levels of the
+contour plot and the viewing angles for the mesh plot interactively.
+
+Users who know which stars they wish to use as PSF stars ahead of time or
+who are without access to an image display can also select PSF stars by id
+number, after which mesh, contour, or radial profile plots will be displayed in
+the graphics window in the usual way.
+
+If the user does not wish to see any plots of the PSF stars or interact with
+the fitting process, the image cursor may be redirected to a text
+file containing cursor commands \fIicommands\fR which specify the PSF stars
+to be used in the fit. If \fIplotfile\fR is defined contour, mesh, or profile
+plots of the selected psf stars can be saved in a metacode plot file for later
+examination.
+
+In interactive mode the PSF star may be initialized by setting \fIpstfile\fR
+to a file created by the PSTSELECT task. If \fIshowplot\fR = "yes" the user is
+asked to accept or delete each star in the input psf star list. Other stars
+may also be added or deleted from this list at any time with the image cursor.
+If \fIinteractive\fR=no or \fIicommands\fR is defined, the PSF stars are read
+in from \fIpstfile\fR, and the PSF model is computed and saved without
+input from the user.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If caching
+is enabled and PSF is run interactively the first data access will appear
+to take a long time as the entire image must be read in before the data
+is actually read. All subsequent measurements will be very fast because PSF
+is accessing memory not disk. The point of caching is to speed up random
+image access by making the internal image i/o buffers the same size as the
+image itself. However if the input object lists are sorted in row order and
+sparse caching may actually worsen not improve the execution time. Also at
+present there is no point in enabling caching for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of caching in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halves of the image are alternated.
+
+The output PSF image \fIpsfimage\fR is normally a 2D image containing the
+image header parameters, "XPSF", "YPSF", "PSFMAG" and "PSFRAD" which define the
+centroid, magnitude and size of the PSF model, the parameters "FUNCTION",
+"PSFHEIGH", "NPARS", and "PAR#" which define the analytic component of the PSF,
+and a single look-up table of residuals from the analytic fit subsampled by a
+factor of 2 with respect to the parent image.
+
+If the DAOPARS parameter \fIvarorder\fR = -1, the PSF is fit by the analytic
+function and \fIpsfimage\fR has no pixel file.
+
+If the DAOPARS parameter \fIvarorder\fR = 1 or 2, then two or five additional
+lookup tables are computed and \fIpsfimage\fR is a 3D image with 3 or 6 planes
+respectively. The first two additional look-up tables contain the first
+derivatives of the PSF wrt the x and y positions in the image (varorder = 1),
+and the next three contains the second derivatives with respect to x ** 2, xy,
+and y ** 2 (varorder = 2).
+
+The positions and magnitudes of each of the stars contributing to the PSF model
+are also stored in the PSF image header.
+
+\fIGroupfile\fR contains a list of the PSF stars, their nearest neighbors, and
+friends of the neighbors. A neighbor is defined to be any star within a
+distance of 1.5 * \fIpsfrad\fR / \fIscale\fR + 2.0 * \fIfitrad\fR /
+\fIscale\fR + 1 pixels of the PSF star. Friends of the neighbors are defined
+to be any stars within 2.0 * \fIfitrad\fR / \fIscale\fR + 1.0 of a neighbor
+star. \fIFitrad\fR and \fIpsfrad\fR are respectively the fitting radius and psf
+radius parameters in the DAOPARS task. \fIScale\fR is the scale factor defined
+in the DATAPARS task.
+
+.ih
+CURSOR COMMANDS
+
+The following cursor commands are available once the image cursor has
+been activated.
+
+.nf
+ Keystroke Commands
+
+? Print help
+p Print photometry for star nearest the cursor
+l List the current psf stars
+a Add star nearest cursor to psf star list
+f Fit the psf
+r Review the fit for all the psf stars
+s Subtract fitted psf from psf star nearest cursor
+d Delete psf star nearest cursor from psf star list
+w Write the psf to the psf image
+z Rebuild the psf from scratch
+q Quit task
+
+ Colon Commands
+
+:p [n] Print photometry for star n
+:a [n] Add star n to psf star list
+:d [n] Delete star n from psf star list
+:s [n] Subtract fitted psf from psf star n
+
+ Colon Parameter Editing Commands
+
+# Data dependent parameters which affect the psf computation
+
+:scale [value] Show/set the image scale (units / pixel)
+:fwhmpsf [value] Show/set the fwhm of psf (scale units)
+:datamin [value] Show/set the minimum good data value (counts)
+:datamax [value] Show/set the maximum good data value (counts)
+:matchrad [value] Show/set matching radius (scale units)
+
+# Psf computation parameters
+
+:psfimage [name,name] Show/set the psf image and groupfile
+:function [string] Show/set the analytic psf function
+:varorder [integer] Show/set order of psf function variability
+:nclean [integer] Show/set number of cleaning iterations
+:saturated [y/n] Show/set the use saturated star flag
+:psfrad [value] Show/set the psf radius (scale units)
+:fitrad [value] Show/set the fitting radius (scale units)
+
+
+The following cursor commands are available once a star has been selected
+and the graphics cursor has been activated.
+
+ Interactive Graphics Keystroke Commands
+
+? Print help
+p Print the photometry for this star
+t Print the plot parameters and data minimum and maximum
+a Accept star and proceed
+d Reject star and select another with image cursor
+m Plot the default mesh plot for this star
+n Increase vertical angle by 15 degrees (mesh plot only)
+s Decrease vertical angle by 15 degrees (mesh plot only)
+w Decrease horizontal angle by 15 degrees (mesh plot only)
+e Increase horizontal angle by 15 degrees (mesh plot only)
+c Plot the default contour plot for this star
+r Plot the radial profile for this star
+
+
+ Colon Graphics Commands
+
+:m [val] [val] Set the mesh plot vertical and horizontal viewing angles
+:v [val] Set the mesh plot vertical viewing angle
+:h [val] Set the mesh plot horizontal viewing angle
+:c [val] [val] Set the contour plot floor and ceiling levels
+:l [value] Set the contour plot floor level
+:u [value] Set the contour plot ceiling level
+.fi
+
+.ih
+ALGORITHMS
+The PSF is determined from the actual observed brightness values as a function
+of x and y
+for one or more stars in the frame and stored as a two-component model.
+The first component is an analytic function which approximates
+the light distribution in the cores of the PSF stars. There are
+currently 6 choices for the analytic component of the model:
+"gauss", "moffat15", "moffat25", "lorentz", "penny1", and "penny2".
+The parameters of the analytic component of the psf model are stored
+in the psf image header parameters "FUNCTION", "PSFHEIGH", "NPARS",
+and "PARN". The magnitude, size, and centroid of the PSF are stored
+in the image header parameters "PSFMAG", "PSFRAD",
+"XPSF", "and "YPSF". If \fImatchbyid\fR is "no" or there is no input psf star list "PSFMAG" is
+set to the magnitude of the first PSF star in the input photometry file. If \fImatchbyid\fR
+is "yes", and there is an input psf star list "PSFMAG" is set to the magnitude of the first psf star
+in the psf star list. "XPSF" and "YPSF" are the center of the image.
+If \fIvarorder\fR >= 0,
+the residuals from this fit are stored as a lookup
+table with twice the sampling interval of the original image.
+This lookup table is used as additive corrections from the integrated
+analytic function to actual observed empirical PSF.
+The parameters of the analytic function are computed by fitting
+all the stars weighted by their signal-to-noise.
+so that the signal-to-noise ratio in
+the PSF does not deteriorate as fainter stars are added in. The more
+crowded the field the more PSF stars are required to lower the noise
+generated by neighbor subtraction.
+
+If the \fIvarorder\fR parameter in the DAOPARS task is set to 1 or 2, two
+or five additional lookup
+tables containing the first derivatives of the PSF in x and y
+and the second order derivatives of the image with respect to
+x ** 2, x * y, and y ** 2 are also written.
+This model
+permits the PSF fitting process to take account of smooth linear
+or quadratic changes in the PSF across the frame caused for example by a tilt in
+the detector with respect to the optical axis or low order optical
+aberrations.
+Users of this option should ensure that the PSF varies in a systematic
+way across the frame and that the chosen PSF stars span the entire
+region of interest in the frame. To avoid mistaking
+neighbor stars for variations in the PSF it is recommended that the
+first few iterations of PSF be run with a constant PSF. Only after
+neighbor stars have been subtracted reasonably cleanly should
+the variable PSF option be enabled.
+
+The brightness of any hypothetical pixel at any arbitrary point within
+the PSF is computed as follows. The analytic function
+is integrated over the area of the pixel, a correction is determined
+by bicubic interpolation within the lookup table and added to the
+integral. Since the values in the table of residuals differ by smaller
+amounts between adjacent grid points than the original brightness data
+would have, the errors in the interpolation are much less than they would
+have been if one had tried to interpolate directly within the original
+data.
+
+.ih
+GUIDE TO COMPUTING A PSF IN A CROWDED FIELD
+
+The following is a rough guide to the methodology of computing the
+PSF in a crowded field. The procedure outlined below assumes
+that the user can either make use of the IRAF display facilities or
+has access to a local display program. At a minimum the display program
+should be able to display an image, read back the coordinates of objects in the
+image, and mark objects in the image.
+
+The crowded field PSF fitting procedure makes use of many of the
+DAOPHOT tasks. Details on the setup and operation of each task can be found
+in the appropriate manual pages.
+
+.ls [1]
+RUN THE DAOFIND and PHOT TASKS ON THE IMAGE OF INTEREST.
+.le
+.ls [2]
+EXAMINE THE IMAGE. Load the image on the display with the IRAF display task.
+Using the display itself, the DAOEDIT task, or the IRAF IMEXAMINE task, estimate the radius
+at which
+the stellar light distribution disappears into the noise for the
+brightest candidate PSF star. Call this parameter \fIpsfrad\fR and record it.
+Mark the objects detected by DAOFIND with dots on the image display using the
+IRAF TVMARK
+task. Users at sites with display devices not currently supported by
+IRAF should substitute their local versions of DISPLAY and TVMARK.
+.le
+.ls [3]
+SELECT CANDIDATE PSF STARS.
+Good PSF stars should have no neighbors
+within the fitting radius stored in the DAOPARS task parameter \fIfitrad\fR.
+In addition all stars within 1.5 times the psf radius,
+(stored in the DAOPARS task parameter
+\fIpsfrad\fR), should be significantly fainter than the candidate star.
+There should be no bad columns, bad rows or blemishes
+near the candidate star. A sufficient number of stars should be
+selected in order to reduce the increased noise resulting from the
+neighbor subtraction process. Users of the variable PSF option should
+take care that the list of PSF stars span the area of interest on the
+image. Twenty-five to thirty stars is not unreasonable in this case.
+
+The task PSTSELECT can be used to preselect candidate PSF stars.
+These candidate PSF stars can be marked on the image display using the
+PDUMP, and TVMARK tasks. Be sure to mark the PSF stars in another
+color from the stars found by DAOFIND. Stars can be added to or
+subtracted from this list interactively when PSF is run.
+.le
+.ls [4]
+EXAMINE THE PSF STARS FOR NEIGHBORS MISSED BY DAOFIND AND ADD THESE TO
+THE PHOT FILE.
+Examine the vicinity of the PSF stars on the display checking for neighbor
+stars which do not have dots on them indicating that they were
+missed by DAOFIND.
+If IRAF supports the local display device simply run PHOT interactively
+selecting the missing stars with the image cursor.
+Be sure to use the same set of PHOT parameters used in step [1] with
+the exception of the CENTERPARS
+task parameter \fIcalgorithm\fR which should be temporarily set to "centroid".
+If IRAF does not support the
+local display generate a list of the approximate coordinates of the
+missing stars.
+Run PHOT in batch mode with this coordinate list as input and with the
+parameters set as described above.
+Create a new PHOT file by using PCONCAT to add the new PHOT output to the
+PHOT output from [1] and renumber using PRENUMBER. Do not resort.
+.le
+.ls [5]
+ESTIMATE OF THE PSF.
+Run PSF using the combined PHOT output from [4] and
+the list of candidate stars from [3].
+Write out the PSF image (extension .psf.#) and the psf group file
+(extension .psg.#). The PSF image is the current estimate of the PSF.
+.le
+.ls [6]
+FIT ALL THE STARS IN EACH PSF STAR GROUP IN THE ORIGINAL IMAGE.
+Run NSTAR on the image using the output group file (extension .psg.#)
+of [5] as the input photometry list. To help prevent the bumps in the initial
+PSF from interfering with the profile fits in NSTAR, it may
+be necessary to temporarily set the psf radius,
+\fIpsfrad\fR in the DAOPARS task,
+to about one pixel greater than the separation of the nearest neighbor
+to a PSF star.
+The fitting radius, \fIfitrad\fR in the
+DAOPARS task, should be sufficiently large to include enough
+pixels for a good fit but not so large as to include any neighbors
+inside the fitting radius.
+.le
+.ls [7]
+SUBTRACT ALL THE FITTED STARS FROM THE ORIGINAL IMAGE.
+Run SUBSTAR to subtract the NSTAR results from the original image.
+Use the IRAF DISPLAY task or the local display program to display
+the subtracted image. If you decreased the value of \fIpsfrad\fR
+in [6] use this smaller value when you subtract as well.
+.le
+.ls [8]
+CHECK FOR PREVIOUSLY INVISIBLE FAINT COMPANIONS.
+Check to see whether the PSF stars and neighbors subtracted
+cleanly or whether there are faint companions that were not previously
+visible before.
+.le
+.ls [9]
+APPEND THESE COMPANIONS TO THE PHOT FILE.
+Run PHOT on the faint companions in the subtracted image
+and append the results to the PHOT file created in [4] using PCONCAT.
+Renumber the stars using PRENUMBER.
+.le
+.ls [10]
+SUBTRACT ALL THE PSF NEIGHBOR STARS FROM THE ORIGINAL IMAGE.
+Edit the nstar output file (extension .nst.#) removing all the PSF stars
+from the file. The PSF stars is the first one in each group. In the
+near future this will be done with the PEXAMINE task but at the
+moment the text editor can be used for text databases and the TTOOLS
+package task TEDIT can be used for tables. PSELECT can also be used
+to remove stars with specific id numbers. Run SUBSTAR using the edited
+nstar output file as input.
+.le
+.ls [11]
+RECOMPUTE THE PSF.
+Run PSF on the subtracted image from [10] using the PHOT file from [9]
+as the input stellar photometry file.
+Temporarily set the minimum good data value, the \fIdatamin\fR parameter
+in the DATAPARS task to a large negative number, to avoid the
+enhanced noise where the
+stars were subtracted from triggering the bad pixel detector in PSF.
+A new psf (extension .psf.#) and new psf group file (extension .psg.#)
+will be created. Be sure to increase the \fIpsfrad\fR value to the
+original large value found in [2].
+.le
+.ls [12]
+RERUN NSTAR.
+Rerun NSTAR on the original image with the newly created group file
+(extension .psg.#) as the input stellar photometry file and the newly
+computed PSF image (extension .psf.#).
+It should not be necessary to reduce the psf radius as in [6]
+but the fitting radius should be left at a generous number.
+.le
+.ls [13]
+REPEAT STEPS [7-12] UNTIL THE PSF FIT IS ACCEPTABLE.
+If any neighbors are still visible iterate on this process by repeating
+steps [7] to [12] until the neighbors completely disappear. The main
+point to remember is that each time through the loop the PSF is obtained
+from an image in which the neighbors but not the PSF stars have been
+subtracted out while NSTAR and SUBSTAR should be run on the original
+picture with all the stars still in it.
+.le
+
+.ih
+EXAMPLES
+
+1. Compute the PSF for the image dev$ypix. Select stars using the display and
+the image cursor and show plots of the data and the residuals from the fit
+for each star. Good stars for making the PSF model can be found at (442,410),
+(348,189), and (379,67).
+
+.nf
+ da> daofind dev$ypix default fwhmpsf=2.5 sigma=5.0 threshold=20.0
+
+ ... answer verify prompts
+
+ ... find stars in the image
+
+ ... answer will appear in ypix.coo.1
+
+ da> phot dev$ypix default default annulus=10. dannulus=5. \
+ apertures = 5.0
+
+ ... answer verify prompts
+
+ ... do aperture photometry on the detected stars
+
+ ... answer will appear in ypix.mag.1
+
+ da> display dev$ypix 1
+
+ ... display the image
+
+ da> psf dev$ypix default "" default default default psfrad=9.0 \
+ fitrad=3.0 mkstars=yes display=imdr
+
+ ... verify the critical parameters
+
+ ... move the image cursor to a candidate star and hit the a key,
+ a plot of the stellar data appears
+
+ ... type ? for a listing of the graphics cursor menu
+
+ ... type a to accept the star, d to reject it
+
+ ... move to the next candidate stars and repeat the previous
+ steps
+
+ ... type l to list all the psf stars
+
+ ... type f to fit the psf
+
+ ... move cursor to first psf star and type s to see residuals,
+ repeat for all the psf stars
+
+ ... type w to save the PSF model
+
+ ... type q to quit, and q again to confirm
+
+ ... the output will appear in ypix.psf.1.imh, ypix.pst.1 and
+ ypix.psg.1
+.fi
+
+
+2. Run PSF non-interactively using the photometry file and psf star file
+created in the previous example.
+
+.nf
+ da> psf dev$ypix default default default default default \
+ psfrad=9.0 fitrad=3.0 interactive- plotfile=psf.plots
+
+ ... the output will appear in ypix.psf.2, ypix.psg.2, and
+ ypix.pst.2
+
+ da> gkidir psf.plots
+
+ ... list the plots created by psf
+
+ da> gkiextract psf.plots 1 | stdgraph
+
+ ... display the surface plots of the first psf star
+
+ da> seepsf ypix.psf.2 ypixpsf
+
+ ... convert the sampled PSF look-up table to a PSF image
+.fi
+
+
+3. Setup and run PSF interactively without using the image display cursor.
+Use the photometry file created in example 1. Before running PSF in this
+manner the user should have a list of the candidate PSF star ids.
+
+.nf
+ da> show stdimcur
+
+ ... store the default value
+
+ da> set stdimcur = text
+
+ ... define the image cursor to be the standard input
+
+ da> epar psf
+
+ ... edit the psf parameters
+
+ ... move to the datapars line and type :e edit the data dependent
+ parameters, type :q to quit the datapars menu
+
+ ... move to the daopars line and type :e edit the daophot fitting
+ parameters, type :q to quit the daopars menu
+
+ ... finish editing the psf parameters
+
+ da> psf dev$ypix default "" default default default \
+ plottype=radial
+
+ ... verify critical parameters
+
+ ... type :a # where # stands for the id number of the star,
+ a plot of the stellar data appears
+
+ ... type a to accept the star, d to reject it
+
+ ... repeat for all the PSF stars
+
+ ... type l to list the psf stars
+
+ ... type f to fit the PSF
+
+ ... type :s # where # stands for the id of the psf star, a plot
+ of the model residuals appears
+
+ ... type w to save the PSF
+
+ ... type q to quit PSF and q again to confirm the quit
+
+ ... the output will appear in ypix.psf.3, ypix.pst.3, ypix.psg.3
+
+ da> set stdimcur = stdimage
+
+ ... reset the image cursor
+.fi
+
+
+4. Run PSF in non-interactive mode using an image cursor command file of
+instructions called icmds.
+
+.nf
+ da> type icmds
+ :a 106
+ :a 24
+ :a 16
+ :a 68
+ f
+ w
+ q
+
+ da> psf dev$ypix default "" default default default \
+ icommands=icmds
+
+ ... verify the critical parameters
+
+ ... the PSF will be constructed from stars 106, 24, 16, 68
+ in the input photometry file
+
+ ... the output will appear in ypix.psf.4, ypix.pst.4, ypix.psg.4
+
+.fi
+
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+datapars,daopars,pstselect,seepsf
+.endhelp
diff --git a/noao/digiphot/daophot/doc/pstselect.hlp b/noao/digiphot/daophot/doc/pstselect.hlp
new file mode 100644
index 00000000..2dd110bd
--- /dev/null
+++ b/noao/digiphot/daophot/doc/pstselect.hlp
@@ -0,0 +1,418 @@
+.help pstselect May00 noao.digiphot.daophot
+.ih
+NAME
+pstselect -- select candidate psf stars from a photometry file
+.ih
+USAGE
+pstselect image photfile pstfile maxnpsf
+.ih
+PARAMETERS
+.ls image
+The list of images containing the candidate psf stars.
+.le
+.ls photfile
+The list of input photometry files. The number of photometry files must
+be equal to the number of input images. If photfile is "default", "dir$default",
+or a directory specification PSTSELECT searches for a file called
+dir$image.mag.# where # is the highest available version number for the file.
+Photfile is normally the output of the PHOT task but may also be the output
+of the PSF, PEAK, NSTAR and ALLSTAR tasks. Photfile may be a
+text file or an STSDAS binary table.
+.le
+.ls pstfile
+The list of output psf star photometry files. There must be one output
+psf star photometry file for every input image. If pstfile is "default",
+"dir$default", or a directory specification then PSTSELECT writes
+a file called dir$image.pst.# where # is the next available version number.
+Pstfile inherits its file type, it may be either an APPHOT/DAOPHOT
+text or STSDAS binary file, from photfile.
+.le
+.ls maxnpsf = 25
+The maximum number of candidate psf stars to be selected.
+.le
+.ls mkstars = no
+Mark the selected or deleted psf stars on the image display ?
+.le
+.ls plotfile = ""
+The name of the output file containing mesh, contour, or profile plots of the
+selected PSF stars. If plotfile is undefined no plot file is created; otherwise
+a mesh, contour, or profile plot is written to this file for each PSF star
+selected. Plotfile is opened in append mode and may become very large.
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters. The parameter
+\fIscale\fR is located here. If \fIdatapars\fR is undefined then the default
+parameter set in uparm directory is used.
+.le
+.ls daopars = ""
+The name of the file containing the daophot fitting parameters. The parameters
+\fIpsfrad\fR and \fIfitrad\fR are located here. If \fIdaopars\fR is undefined
+then the default parameter set in uparm directory is used.
+.le
+.ls interactive = no
+Select the psf stars interactively ? If interactive = yes and icommands is
+undefined, PSTSELECT reads in the star list from \fIphotfile\fR, sorts the
+stars by magnitude and waits for commands from the user. If interactive = no
+and icommands="", PSTSELECT selects candidate PSF stars from \fIphotfile\fR
+automatically. If icommands is not undefined then interactive is automatically
+set to "no", and commands are read from the image cursor command file.
+.le
+.ls plottype = "mesh"
+The default plot type displayed when a psf star is selected interactively.
+The choices are "mesh", "contour", or "radial".
+.le
+.ls icommands = ""
+The image display cursor or image cursor command file.
+.le
+.ls gcommands = ""
+The graphics cursor or graphics cursor command file.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout"
+The coordinate system of the input coordinates read from \fIphotfile\fR and
+of the output coordinates written to \fIpstfile\fR respectively. The image
+header coordinate system is used to transform from the input coordinate
+system to the "logical" pixel coordinate system used internally,
+and from the internal "logical" pixel coordinate system to the output
+coordinate system. The input coordinate system options are "logical", "tv",
+"physical", and "world". The output coordinate system options are "logical",
+"tv", and "physical". The image cursor coordinate system is assumed to
+be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin and wcsout are "logical" and "logical" respectively.
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default caching is
+disabled.
+.le
+.ls verify = ")_.verify"
+Verify the critical PSTSELECT parameters ?
+Verify can be set to the DAOPHOT package parameter value (the default),
+"yes", or "no".
+.le
+.ls update = ")_.update"
+Update the algorithm parameters if verify is "yes"?
+Update can be set to the DAOPHOT package parameter value (the default),
+"yes", or "no".
+.le
+.ls verbose = ")_.verbose"
+Print messages about the progress of the task in non-interactive mode ?
+Verbose can be set to the DAOPHOT package parameter value (the default),
+"yes", or "no".
+.le
+.ls
+graphics = ")_.graphics"
+The default graphics device. Graphics can be set to the default
+daophot package parameter value, "yes", or "no".
+.le
+.ls display = ")_.display"
+The default image display device. Display can be set to the DAOPHOT
+package parameter value (the default), "yes", or "no". By default graphics
+overlay is disabled. Setting display to one of "imdr", "imdg", "imdb", or
+"imdy" enables graphics overlay with the IMD graphics kernel.
+.le
+
+.ih
+DESCRIPTION
+
+PSTSELECT reads the input photometry file \fIphotfile\fR, extracts the ID,
+XCENTER, YCENTER, MAG, and MSKY fields for up to \fImaxnpsf\fR psf stars,
+and the results to \fIpstfile\fR. \fIPstfile\fR automatically inherits the
+file format of \fIphotfile\fR.
+
+The coordinates read from \fIphotfile\fR are assumed to be in coordinate
+system defined by \fIwcsin\fR. The options are "logical", "tv", "physical",
+and "world" and the transformation from the input coordinate system to
+the internal "logical" system is defined by the image coordinate system.
+The simplest default is the "logical" pixel system. Users working on with
+image sections but importing pixel coordinate lists generated from the parent
+image must use the "tv" or "physical" input coordinate systems.
+
+The coordinates written to \fIpstfile\fR are in the coordinate system defined
+by \fIwcsout\fR. The options are "logical", "tv", and "physical". The simplest
+default is the "logical" system. Users wishing to correlate the output
+coordinates of objects measured in image sections or mosaic pieces with
+coordinates in the parent image must use the "tv" or "physical" coordinate
+systems.
+
+After reading the star list from \fIphotfile\fR, PSTSELECT sorts the list in
+order of increasing magnitude, after rejecting any stars that have INDEF
+valued magnitudes, or which lie less than \fIfitrad\fR / \fIscale\fR
+pixels from the edge of the \fIimage\fR. From this list the brightest
+\fImaxnpsf\fR stars which have no brighter neighbor stars within (\fIpsfrad\fR +
+\fIfitrad\fR) / \fIscale\fR + 1 pixels are selected as candidate psf stars.
+\fIPsfrad\fR and \fIfitrad\fR are the psf radius and fitting radius parameters
+respectively and are stored in the DAOPARS parameter set. \fIScale\fR is the
+image scale parameter and is located in the DATAPARS parameter set. Plots,
+either mesh, contour or radial profile depending on the value of
+\fIplottype\fR, of the selected stars may be saved in the file \fIplotfile\fR.
+
+If \fIinteractive\fR = "no", PSTSELECT reads the star list in \fIphotfile\fR,
+selects the candidate psf stars as described above, and writes the results to
+\fIpstfile\fR automatically. If interactive = "yes", PSTSELECT reads
+the star list, selects the candidate psf stars and waits for further
+instruction from the user. At this point the user can step through the stars
+chosen by PSTSELECT, check their surface, contour, or radial profile plots
+for blemishes, neighbors etc, and accept the good candidates and reject
+the poor ones, or use the image cursor and/or id number to select psf
+stars until a maximum of \fImaxnpsf\fR stars is reached. At any point in
+this process a previously selected psf star can be deleted.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough, the input image pixels are cached in memory. If caching
+is enabled and PSTSELECT is run interactively the first data access will appear
+to take a long time as the entire image must be read in before the data
+is actually fetched. All subsequent measurements will be very fast because
+PSTSELECT is accessing memory not disk. The point of caching is to speed up
+random image access by making the internal image i/o buffers the same size as
+the image itself. However if the input object lists are sorted in row order and
+sparse caching may actually worsen not improve the execution time. Also at
+present there is no point in enabling caching for images that are less than
+or equal to 524288 bytes, i.e. the size of the test image dev$ypix, as the
+default image i/o buffer is exactly that size. However if the size of dev$ypix
+is doubled by converting it to a real image with the chpixtype task then the
+effect of caching in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halves of the image are alternated.
+
+
+.ih
+CURSORS
+
+ The following cursor commands are available once the image cursor
+ has been activated.
+
+.nf
+
+ Keystroke Commands
+
+? Print help
+p Print photometry for star nearest the cursor
+l List the current psf stars
+n Select the next good candidate psf star from the list
+a Add star nearest cursor to psf star list
+d Delete psf star nearest cursor from psf star list
+q Quit task
+
+ Colon Commands
+
+:p [n] Print photometry for star n
+:a [n] Add star n to psf star list
+:d [n] Delete star n from psf star list
+
+The following cursor commands are available once a star has been selected
+and the graphics cursor has been activated.
+
+ Interactive Graphics Keystroke Commands
+
+? Print help
+p Print the photometry for this star
+t Print the plot parameters and data minimum and maximum
+a Accept star and proceed
+d Reject star and select another with image cursor
+m Plot the default mesh plot for this star
+n Increase vertical angle by 15 degrees (mesh plot only)
+s Decrease vertical angle by 15 degrees (mesh plot only)
+w Decrease horizontal angle by 15 degrees (mesh plot only)
+e Increase horizontal angle by 15 degrees (mesh plot only)
+c Plot the default contour plot for this star
+r Plot the radial profile for this star
+
+
+ Colon Graphics Commands
+
+:m [val] [val] Set the mesh plot vertical and horizontal viewing angles
+:v [val] Set the mesh plot vertical viewing angle
+:h [val] Set the mesh plot horizontal viewing angle
+:c [val] [val] Set the contour plot floor and ceiling levels
+:l [value] Set the contour plot floor level
+:u [value] Set the contour plot ceiling level
+.fi
+
+.ih
+OUTPUT
+
+If \fIverbose\fR = "yes" a single line is written to the terminal for each
+star added to the candidate psf star list. Full output is written to the
+file \fIpstfile\fR. At the beginning of this file is a header listing the
+values of all the important parameters. For each star included in the candidate
+psf star list the following quantities are written.
+
+.nf
+ id xcenter ycenter mag msky
+.fi
+
+Id, xcenter, ycenter, mag, and msky are the id, x and y coordinates,
+magnitudes and sky values for the candidate psf stars listed in
+\fIphotfile\fR.
+
+.ih
+EXAMPLES
+
+1. Select up to 10 psf stars from the PHOT task output non-interactively.
+Save surface plots of the selected stars in the file "psf.plots".
+
+.nf
+ da> daofind dev$ypix default fwhmpsf=2.5 sigma=5.0 threshold=20.0
+
+ ... answer verify prompts
+
+ ... find stars in the image
+
+ ... answer will appear in ypix.coo.1
+
+ da> phot dev$ypix default default annulus=10. dannulus=5. \
+ apertures = 5.0
+
+ ... answer verify prompts
+
+ ... do aperture photometry on the detected stars
+
+ ... answer will appear in ypix.mag.1
+
+ da> pstselect dev$ypix default default 10 psfrad=9.0 fitrad=3.0 \
+ plotfile=psf.plots
+
+ ... answer verify prompts
+
+ ... select candidate psf stars
+
+ ... the output will appear in ypix.pst.1
+
+ da> display dev$ypix 1
+
+ ... display the image
+
+ da> pdump ypix.pst.1 xc,yc yes | tvmark 1 STDIN col=204
+
+ ... mark the stars
+
+ da> gkiextract psf.plots 1 | stdgraph
+
+ ... make a surface plot of the first candidate psf star
+.fi
+
+
+2. Repeat the previous results for an image section while preserving the
+coordinate system of the original image.
+
+
+.nf
+ da> daofind dev$ypix[150:450,150:450] default wcsout=tv fwhmpsf=2.5 \
+ sigma=5.0 threshold=20.0
+
+ ... answer verify prompts
+
+ ... find stars in the image
+
+ ... answer will appear in ypix.coo.2
+
+ da> phot dev$ypix[150:450,150:450] default default wcsin=tv wcsout=tv \
+ annulus=10. dannulus=5. apertures = 5.0
+
+ ... answer verify prompts
+
+ ... do aperture photometry on the detected stars
+
+ ... answer will appear in ypix.mag.2
+
+ da> pstselect dev$ypix[150:450,150:450] default default 10 wcsin=tv \
+ wcsout=tv psfrad=9.0 fitrad=3.0 plotfile=psf.plots2
+
+ ... answer verify prompts
+
+ ... select candidate psf stars
+
+ ... the output will appear in ypix.pst.2
+
+ da> display dev$ypix[150:450,150:450] 1
+
+ ... display the image
+
+ da> pdump ypix.pst.2 xc,yc yes | tvmark 1 STDIN col=204
+
+ ... mark the stars
+
+ da> gkiextract psf.plots2 4 | stdgraph
+
+ ... make a surface plot of the 4th candidate psf star
+.fi
+
+
+3. Repeat example 1 but run pstselect in interactive mode and do not save the
+plots.
+
+.nf
+ da> display dev$ypix 1
+
+ ... display the image
+
+ da> pstselect dev$ypix ypix.mag.1 default 10 psfrad=9. fitrad=3. \
+ interactive+ mkstars+ display=imdr
+
+ ... verify the critical parameters as instructed
+
+ ... when the image cursor appears type the n keystroke
+ command to select the first suitable candidate psf
+ star, examine its surface plot, and type a or d to
+ accept or reject the candidate
+
+ ... repeat the previous command until 10 psf stars have
+ been selected, the end of the star list is reached,
+ or a sufficient number of stars but fewer than maxnpsf
+ have been selected
+
+ ... if fewer than maxnpsf stars are found automatically
+ add psf stars to the list with the a keystroke command
+
+ ... type q to quit
+
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+datapars,daopars,phot,psf
+.endhelp
diff --git a/noao/digiphot/daophot/doc/seepsf.hlp b/noao/digiphot/daophot/doc/seepsf.hlp
new file mode 100644
index 00000000..ed7a5728
--- /dev/null
+++ b/noao/digiphot/daophot/doc/seepsf.hlp
@@ -0,0 +1,101 @@
+.help seepsf May00 noao.digiphot.daophot
+.ih
+NAME
+seepsf -- convert a sampled PSF lookup table to a PSF image
+.ih
+USAGE
+seepsf psfimage image
+.ih
+PARAMETERS
+.ls psfimage
+The list of input PSF images computed by the PSF task. Each PSF image consists
+of the parameters of a 2D analytic function stored in the image header and an
+optional sampled lookup table of residuals from that fit stored in the image
+pixels.
+.le
+.ls image
+The list of output PSF images consisting of the sum of the analytic function
+and the residuals in the lookup table. There must be one output PSF image for
+each input PSF image.
+.le
+.ls dimension = INDEF
+The dimensions of the output PSF image. By default \fIimage\fR is a 2D image
+with dimensions of N by N where N = 2 * nint (psfrad / scale) + 1 with the
+same scale as the original image from which \fIpsfimage\fR was derived.
+\fIPsfrad\fR is the PSF fitting radius stored in the \fIpsfimage\fR image
+header parameter "PSFRAD". \fIScale\fR is the image scale stored in the image
+header parameter "SCALE".
+.le
+.ls xpsf = INDEF
+The x coordinate of the output PSF. \fIXpsf\fR is only used if \fIpsfimage\fR
+was computed with the variable PSF parameter \fIvarorder\fR in the DAOPARS task
+set to > 0.
+.le
+.ls ypsf = INDEF
+The y coordinate of the output PSF. \fIYpsf\fR is only used if \fIpsfimage\fR
+was computed with the variable PSF parameter \fIvarorder\fR in the DAOPARS task
+set to > 0.
+.le
+.ls magnitude = INDEF
+The intensity scale of the output PSF. By default the intensity scale is set by
+the magnitude of the first star used by the PSF task to compute \fIpsfimage\fR.
+This parameter is stored in the keyword "PSFMAG" in \fIpsfimage\fR.
+.le
+.ih
+DESCRIPTION
+SEEPSF takes the input PSF \fIpsfimage\fR computed by the PSF task, consisting
+of the parameters of a 2D analytic function stored in the image header and an
+optional lookup table of residuals from the fit stored in the image pixels, and
+computes an output PSF, \fIimage\fR, consisting of the sum of the analytic
+function and the residuals.
+
+By default \fIimage\fR is a 2D image of dimensions N by N where N = 2 * nint
+(psfrad) + 1 and the scale of \fIimage\fR is the same as the scale of the
+original image from which \fIpsfimage\fR was derived. If \fIdimension\fR is
+greater or less than N then the output PSF is block-averaged or subsampled with
+respect to the original image. \fIPsfrad\fR is the value of the psf radius
+parameter in the task DAOPARS used to compute \fIpsfimage\fR and is stored in
+the \fIpsfimage\fR header parameter "PSFRAD".
+
+If \fIpsfimage\fR was computed with the variable PSF parameter \fIvarorder\fR
+set to > 0, then \fIimage\fR is computed at a point (xpsf, ypsf) defined
+relative to the original image. By default \fIimage\fR is computed at the
+centroid of the PSF defined by the \fIpsfimage\fR header parameters "XPSF"
+and "YPSF".
+
+The intensity scale of \fIimage\fR is determined by the value of \fImagnitude\fR
+relative to the magnitude of the PSF. By default the output PSF has the
+magnitude of the first PSF star stored in the \fIpsfimage\fR header parameter
+"PSFMAG".
+
+SEEPSF is most commonly used for visualizing the PSF in image scale coordinates
+and checking the form of any variability as a function of position. However
+\fIimage\fR can also be used as input to other image processing program, for
+example it might be used as the kernel in a convolution operation.
+
+.ih
+EXAMPLES
+
+1. Compute the output PSF in image scale coordinates of PSF function
+for image dev$ypix.
+
+.nf
+ da> seepsf ypix.psf.3 ypixpsf
+.fi
+
+2. Compute the output PSF in image scale coordinates of the variable
+PSF for the image m92b at position (113.63,50.48) pixels relative to the
+original image.
+
+.nf
+ da> seepsf m92b.psf.2 m92psf xpsf=113.63 ypsf=50.48
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+datapars,daopars,psf
+.endhelp
diff --git a/noao/digiphot/daophot/doc/setimpars.hlp b/noao/digiphot/daophot/doc/setimpars.hlp
new file mode 100644
index 00000000..dad0d4d1
--- /dev/null
+++ b/noao/digiphot/daophot/doc/setimpars.hlp
@@ -0,0 +1,165 @@
+.help setimpars May00 noao.digiphot.daophot
+.ih
+NAME
+setimpars -- save / restore the daophot parameters for a particular image
+.ih
+USAGE
+setimpars image restore update
+.ih
+PARAMETERS
+.ls image
+The image for which the daophot parameters are to be saved or restored.
+.le
+.ls restore
+If restore = yes, parfile is "", and the file "image.pars" exists, SETIMPARS
+sets the current algorithm parameters by reading in the file "image.pars". If
+parfile is not "", then restore is automatically assumed to be yes.
+.le
+.ls update
+If update = yes, SETIMPARS saves the new current values of the DAOPHOT algorithm
+parameters in the file \fIimage.pars\fR and any previously existing file of the same name is overwritten.
+.le
+.ls review = no
+Review and/or edit the values of the parameters in the parameter sets DATAPARS,
+FINDPARS, CENTERPARS, FITSKYPARS, PHOTPARS, and DAOPARS by calling up the EPAR
+task for each of the named parameter sets in turn?
+.le
+.ls parfile
+The name of the input file containing the values of the DAOPHOT algorithm
+parameters to be restored. If defined \fIparfile\fR must have been written
+by SETIMPARS. If parfile is null (""), SETIMPARS searches for a file named
+\fIimage.pars\fR in the user's current directory. If no file is found, the
+DAOPHOT algorithm parameters are restored from the files \fIdatapars\fR,
+\fIfindpars\fR, \fIcenterpars\fR, \fIfitskypars\fR, \fIphotpars\fR, and
+\fIdaopars\fR.
+.le
+.ls datapars = ""
+The name of the file containing the DATAPARS parameter values. Datapars must be
+a named DATAPARS parameter set file written by the EPAR task, or "" in which
+case the default DATAPARS parameter set in the user's uparm directory is used.
+If the parameter \fIunlearn\fR is "yes" and datapars is "", DATAPARS is
+unlearned.
+.le
+.ls findpars = ""
+The name of the file containing the FINDPARS parameter values. Findpars
+must be a named FINDPARS parameter set file written by the EPAR task, or ""
+in which case the default FINDPARS parameter set in the user's uparm
+directory is used. If the parameter \fIunlearn\fR is "yes" and findpars
+is "", FINDPARS is unlearned.
+.le
+.ls centerpars = ""
+The name of the file containing the CENTERPARS parameter values. Centerpars
+must be a named CENTERPARS parameter set file written by the EPAR task, or ""
+in which case the default CENTERPARS parameter set in the user's uparm
+directory is used. If the parameter \fIunlearn\fR is "yes" and centerpars
+is "", CENTERPARS is unlearned.
+.le
+.ls fitskypars = ""
+The name of the file containing the FITSKYPARS parameter values. Fitskypars
+must be a named FITSKYPARS parameter set file written by the EPAR task, or ""
+in which case the default FITSKYPARS parameter set in the user's uparm
+directory is used. If the parameter \fIunlearn\fR is "yes" and fitskypars
+is "", FITSKYPARS is unlearned.
+.le
+.ls photpars = ""
+The name of the file containing the PHOTPARS parameter values. Photpars must be
+a named PHOTPARS parameter set file written by the EPAR task, or "" in which
+case the default PHOTPARS parameter set in the user's uparm directory is used.
+If the parameter \fIunlearn\fR is "yes" and photpars is "", PHOTPARS is
+unlearned.
+.le
+.ls daopars = ""
+The name of the file containing the DAOPARS parameter values. Daopars must be a
+named DAOPARS parameter set file written by the EPAR task, or "" in which case
+the default DAOPARS parameter set in the user's uparm directory is used. If the
+parameter \fIunlearn\fR is "yes" and daopars is "", DAOPARS is unlearned.
+.le
+.ls unlearn = no
+Return the values of the parameters in the parameter sets DATAPARS, FINDPARS,
+CENTERPARS, FITSKYPARS, PHOTPARS, and DAOPARS to their default values?
+.le
+.ih
+DESCRIPTION
+
+SETIMPARS saves and restores the DAOPHOT task and algorithm parameters for the
+image \fIimage\fR. On startup SETIMPARS initializes all the DAOPHOT package
+input and output coordinates and photometry file names, input and output images,
+and input and output plot files to their default values or \fIimage\fR whichever
+is appropriate. Next SETIMPARS reads in the values of the algorithm parameters
+from \fIparfile\fR if it is defined, or from the file \fIimage.pars\fR if it
+exists and \fIrestore\fR is "yes", or from the named parameter set files
+\fIdatapars\fR, \fIfindpars\fR, \fIcenterpars\fR, \fIfitskypars\fR,
+\fIphotpars\fR, and \fIdaopars\fR if they exist, or from the default parameters
+sets in the user's uparm directory. If \fIunlearn\fR is "yes", these default
+parameter sets are unlearned.
+
+If \fIreview\fR is "yes", the user can review and or edit the newly set
+algorithm parameters in DATAPARS, FINDPARS, CENTERPARS, FITSKYPARS, PHOTPARS,
+and DAOPARS using the IRAF EPAR task.
+
+If \fIupdate\fR is "yes", SETIMPARS saves the new current values of the DAOPHOT
+algorithm parameters DATAPARS, FINDPARS, CENTERPARS, FITSKYPARS, PHOTPARS, and
+DAOPARS in the file \fIimage.pars\fR. Any previously existing file of the same
+name is overwritten.
+
+.ih
+EXAMPLES
+
+1. Save the current values of the daophot task and algorithm parameters for
+the image m92v.
+
+.nf
+ da> setimpars m92v no yes
+
+ ... m92v parameters are saved in m92v.pars
+.fi
+
+2. Make some minor alterations in the current values of the m92v algorithm
+parameters and save the new parameters set.
+
+.nf
+ da> setimpars m92v no yes
+
+ ... m92v parameters are saved in new version of m92v.pars
+.fi
+
+3. Begin work on the image m92b. Initialize the values of the daophot task
+and algorithm parameters for m92b using those stored for m92v. After doing
+some preliminary editing and reductions for m92b, save the parameters,
+and return to work on m92v.
+
+.nf
+ da> setimpars m92b yes no parfile=m92v.pars
+
+ ... current parameters for m92v are set using saved
+ m92v parameters
+
+ da> daoedit m92b
+
+ ... edit the parameters as necessary for the new image
+
+ da> daofind m92b
+
+ ... find the stars in m92b
+
+ da> phot m92b
+
+ ... do the initial photometry for stars in m92b
+
+ da> setimpars m92b no yes
+
+ ... current m92b parameters are saved in m92b.pars
+
+ da> setimpars m92v yes no
+
+ ... m92v parameters are restored from m92v.pars
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+daoedit,datapars,findpars,centerpars,fitskypars,photpars,daopars
+.endhelp
diff --git a/noao/digiphot/daophot/doc/specs/daophot.spc b/noao/digiphot/daophot/doc/specs/daophot.spc
new file mode 100644
index 00000000..221630d5
--- /dev/null
+++ b/noao/digiphot/daophot/doc/specs/daophot.spc
@@ -0,0 +1,1047 @@
+.help daophot Sep87 "Crowded Field Stellar Photometry'
+.sh
+1. Introduction
+
+ The DAOPHOT package will provide a set of routines for performing
+stellar photometry on crowded fields in either interactive or batch mode.
+DAOPHOT works by fitting an empirical point spread function (PSF)
+to each object in the field
+allowing for overlap of closely spaced images. This document presents the
+the requirements and specifications for the package and describes some of
+the algorithms to be used. Most of the algorithms are described in
+the original article by Peter Stetson (1987 P.A.S.P. 99,191).
+
+.sh
+2. Requirements
+.ls 4
+.ls (1)
+The tasks in the DAOPHOT package shall take as input an IRAF imagefile
+containing two-dimensional image data which has been corrected for
+pixel to pixel gain variations, high frequency variations in the background,
+any nonlinearitys in the data except for those which can be specified as
+a lower and/or upper bound,
+and any other instrumental defects affecting the intensity value of an
+individual pixel. However, it shall be possible to exclude bad pixels,
+rows or columns from analysis by DAOPHOT routines in a very crude manner.
+.le
+.ls (2)
+The tasks in the package which produce tabular output shall use the
+SDAS Tables for their output and those tasks which read output from other
+DAOPHOT tasks will be able to read SDAS Tables. In the future the input/output
+shall make use of the DBIO package.
+.le
+.ls (3)
+The DAOPHOT package shall work in conjunction with the APPHOT package produced
+at NOAO. DAOPHOT will not have any provision to do aperture photometry of its
+own. The output format from DAOPHOT tasks will be consistent with APPHOT.
+.le
+.ls (4)
+Given as input a reduced two-dimensional image which has been processed by the
+APPHOT package, the DAOPHOT package shall be able to perform the following
+functions:
+.ls 4
+.ls o
+Interactively define a PSF for the data frame. The PSF will be defined
+empirically from one or more stars in the field. The task to determine the
+PSF shall be interactive and the user shall be able to use a
+graphics terminal and/or an image display device to select the stars which
+will make up the PSF. The user will be able to evaluate the PSF through
+different means including contour plots, 3-d mesh plots, and displaying the
+PSF on an image display device.
+The user shall be able to "mask" out parts of the PSF which may be contaminated
+by nearby stars, bad pixels etc. Only the non-masked portions of the PSF will
+be used in the fitting routines.
+.le
+.ls o
+Fit the PSF simultaneously to groups of stars in the image frame whose
+images overlap to some degree. The parameters in the fit shall include the
+the object brightness, X and Y position of the star and potentially the sky
+background. The sky shall be able to be specified as either a flat uniform
+background or a simple tilted planar sky. The photometry routines shall
+produce realistic errors in the photometry assuming that realistic numbers
+for the characteristics of the data are input.
+.le
+.ls o
+Subtract the fitted stars from the data frame to produce a subtracted
+image for further analysis.
+.le
+.ls o
+Add artificial stars to the data frame in order to check accuracy and
+completeness in the photometry. The user shall have control over the
+number of stars added, the brightness range, the area of the image to contain
+the added stars and the noise characteristics of the added stars.
+.le
+.le
+.ls (5)
+The DAOPHOT package shall include tasks to inspect and edit the results from the
+photometry routines. These shall include tasks such as interactively
+rejecting particular stars from the results,
+producing plots of errors versus brightness, errors versus position etc.
+.le
+.ls (6)
+The DAOPHOT package shall provide utility packages to handle the output
+data from the fitting routines. These shall include such tasks as
+aperture growth curves, photometric calibrations, color-magnitude and
+color-color diagrams.
+.le
+.ls (7)
+The DAOPHOT routines shall optionally keep a history file to keep
+track of the processing done on the images. This will include the values of
+various parameters used in the various tasks of the DAOPHOT package.
+.le
+.ls (8)
+The tasks shall be able to be run in batch mode as well as interative
+mode. In batch mode use of a graphics terminal or image display shall not
+be required.
+.le
+.ls (9)
+The DAOPHOT package shall be written in the SPP language in conformance with
+the standards and conventions of IRAF. The code shall be portable and
+device independent.
+.le
+.le
+.sh
+2.1 Limitations of the Initial DAOPHOT Package
+
+The DAOPHOT package shall perform PSF fitting photometry with the following
+restrictions:
+.ls
+.ls (1)
+The PSF used will be determined empirically and analytic specification of
+the PSF will not be possible. This restricts the use of DAOPHOT to image
+data which is not too badly undersampled.
+.le
+.ls (2)
+There will be an upper limit to the number of stars for which the PSF will
+be fit simultaneously. The initial version of DAOPHOT will have this limit
+set to 60 stars.
+.le
+.ls (3)
+The initial version of DAOPHOT will not have the sky included as a parameter
+in the fitting routines.
+.le
+.ls (4)
+Initially the use will not be able to mask out bad portions of the PSF for
+fitting.
+.le
+.le
+
+.sh
+3. Specifications
+
+ The DAOPHOT package performs stellar photometry on digital data, maintained
+as IRAF image files. DAOPHOT performs this photometry by fitting the PSF
+to the stellar images in the image file. DAOPHOT works by fitting the PSF to
+a maximum number of stars simultaneously thus allowing for overlapping images.
+Input to the package consists of an imagefile and the output from the APPHOT
+package, which contains simple aperture photometry for the objects which have
+been identified in the image frame, and numerous parameters controlling the
+analysis algorithms. Output from the analysis tasks consists of tabular data
+containing the results of the analysis routines. The output will be in the
+form of SDAS tables and will thus be able to be manipulated by various
+other utility tasks available in IRAF.
+
+The CL callable part of the DAOPHOT package consists of the following routines:
+
+.ks
+.nf
+ addstar -- adds synthetic stars to an image file
+ allstar -- fits multiple, overlapping PSFs to star images
+ *calibrate -- apply photometric calibration
+ *cmd -- color-magnitude, color-color diagrams
+ daopars -- DAOPHOT pset parameters
+ examine -- interactively examine/edit photometry results
+ group -- divides stars into natural groupings
+ *growth -- aperture growth curves <--> PSF magnitudes
+ peak -- fit PSF to single stars in an image file
+ psf -- interactively construct a PSF for the frame
+ nstar -- fits multiple, overlapping PSFs to star images
+ seepsf -- converts a PSF file into a IRAF image file
+ select -- selects natural groups with a certain range of sizes
+ substar -- subtract fitted profiles from an image file
+.fi
+.ke
+
+There are routines available in other IRAF/STSDAS tasks for manipulating
+SDAS Tables or DBIO. The capabilities inside the DAOPHOT are specifically
+suited to dealing with large tables of results from these photometry routines.
+
+.sh
+3.1 Standard Analysis Procedures
+
+ Before performing DAOPHOT photometry one must perform certain other tasks
+beforehand. This includes using the APPHOT package to produce an object list
+and aperture photometry for objects in this list. The DAOPHOT package contains
+an additional object finder but one must use APPHOT to obtain the aperture
+photometry results. The standard analysis procedure, including APPHOT, is as
+follows:
+.ls
+.ls (1)
+Use an object finder to produce a list of object coordinates. This may be done
+in many ways:
+.ls
+.ls o
+By using the interactive cusrsor routines available elsewhere in IRAF and
+redirecting the output into a list file.
+.le
+.ls o
+By transforming an existing list using an existing IRAF task or the OFFSET
+task in the DAOPHOT package.
+.le
+.ls o
+By using an automatic object finding procedure such as the one available
+in the APPHOT package or the one in the DAOPHOT package.
+.le
+.ls o
+By any other program which generates a list of objects in suitable format (SDAS
+Tables) for input to the APPHOT routines.
+.le
+.le
+.ls (2)
+The APPHOT package is run to measure the objects identified in the above
+step. One should refer to the APPHOT documentation to understand the
+algorithms and procedures which are used in APPHOT.
+.le
+.ls (3)
+One needs to set up the parameters in the analysis routines for this particular
+image file. OPTIONS allows you to set such parameters as the number of
+electrons/ADC, the fitting radius, and the radius within which the PSF
+is defined.
+.le
+.ls (4)
+The next step is to produce a PSF for the image file currently being processed.
+In crowed fields this is a tricky, iterative procedure which should be done very
+carefully. This is best done using a graphics terminal and/or an image display
+device.
+.le
+.ls (5)
+If one plans on using NSTAR, then the GROUP task must be run. This task
+divides the stars in the output from the APPHOT into natural groups. The size
+of the groups produced depends upon how crowded the field is and what degree of
+overlap of the images one considers.
+.le
+.ls (6)
+Use either NSTAR, if you have grouped the objects using GROUP, or
+ALLSTAR which will dynamically group the stars as the image file is
+processed. These routines will produce the objects' positions and
+intrumental magnitudes by means of multiple-profile fits.
+.le
+.ls (7)
+Use SUBSTAR to subtract the fitted profiles from the image file, thus producing
+a new image file containing the fitting residuals. This will usually contain
+many stars which were missed in the original identification because they lie
+in the wings of brighter objects.
+.le
+.ls (8)
+One now basically runs through steps (1) - (6) one or more times,
+merging the identified object lists each time to produce a master object list,
+until one is satisfied with the final results. There are many subtlties in this
+procedure which are described in the DAOPHOT User's Manual.
+.le
+.ls (9)
+After obtaining the photometry results one may edit the results by throwing out
+those results which do not meet certain criteria. EXAMINE is an interactive
+task which allows the user to examine the results for each individual object
+in the list and either accept or reject that object. There are also routines
+available for courser rejection of results, e.g. reject all objects with
+errors larger than 0.2 magnitudes.
+.le
+.ls (10)
+One may wish to use the tasks to plot up color-color or color-magnitude
+diagrams. Other general purpose list processing tools available in
+IRAF/SDAS may also be used for analysis of DAOPHOT output.
+.le
+.le
+
+.sh
+3.2 The ADDSTAR Task
+
+ The function of ADDSTAR is to add synthetic stars to the image file.
+These stars may be placed randomly by the computer, placed with a certain
+distribution as specifed by the user or at predetermined locations specified
+by the user. Likewise the brightness of these added objects may be completely
+random or may follow a specified distribution.
+
+Objects are added by taking the specified PSF, scaling it, and moving it
+to the desired location. ADDSTAR will also add Poisson noise to the star
+images to make them more realistic.
+
+.sh
+3.2.1 ADDSTAR Parameters
+
+ ADDSTAR has several parameters which control the addition of stars
+into a image file. All data dependent parameters are query mode to ensure
+that they get set properly for the particular image under consideration.
+The data independent parameters are hidden mode, and are given reasonable
+default values. The names, datatypes, and default values of the ADDSTAR
+parameters are shown below.
+
+.ks
+.nf
+Positional or query mode parameters:
+
+ input_image filename
+ output_image filename
+ minmag real
+ maxmag real
+.fi
+.ke
+
+.ks
+.nf
+List structured parameter (filename may be given on command line):
+
+ add_data *imcur
+.fi
+.ke
+
+.ks
+.nf
+Hidden Parameters:
+
+ daopars pset "daophot$daopars.par"
+ nstar integer 100
+ nframe integer 1
+ xmin integer 1
+ ymin integer 1
+ xmax integer NX
+ ymax integer NY
+ verbose boolean false
+.fi
+.ke
+
+The function and format of each of these parameters is explained in
+more detail below.
+
+.ls
+.ls 16 input_image
+The name of the image or image section to which artificial stars will be added
+.le
+.ls output_image
+The name of outout image which will contain the added stars.
+.le
+.ls minmag
+The minumum magnitude of artificial star to add to the data. The magnitude
+scale is set by the magnitude of the PSF.
+.le
+.ls maxmag
+The maximum magnitude of artificial star to add to the data. The magnitude
+scale is set by the magnitude of the PSF.
+.le
+.ls add_data
+This parameter is used to specify a file as input to the ADDSTAR task. This
+file should contain centroid positions and magnitudes for the stars you
+want to add. It is possible to specify the positions of the added stars
+interactively with the image display by setting this parameter to *imcur.
+In this case the user is prompted for the magnitude of each star to be added.
+If this parameter is the null string then the stars are added in a random
+fashion by the ADDSTAR routine.
+.le
+.ls nstar
+The number of artificial stars to add to the input image file.
+.le
+.ls daopars
+This is the name of a file containing parameters which are common to
+many DAOPHOT tasks. This pset parameter serves as a pointer to the external
+parameter set for the DAOPHOT algorithms. The parameters contained in this
+pset and their function are described in section 3.6.1.
+.le
+.ls nframe
+The number of new image files to create. If this parameter is greater
+than one then the new image files will use the output image name as
+a root and produce image files with '.xxx' appended to the root, where
+xxx will range from 001 to nframe. If nframe is one then the output image
+name will be used as is.
+.le
+.ls xmin, ymin, xmax, ymax
+These define the subsection of the image in which to add the artificial
+stars. The default is to add artificial stars to the complete image.
+.le
+.ls verbose
+Controls the amount of output from the ALLSTAR function. The default is
+to have minimal output to STDOUT.
+.le
+.le
+
+.sh
+3.2.2 ADDSTAR Output
+
+ The output of ADDSTAR consists of two parts, an image file and an
+output SDAS Table. The image file is a copy of the input image file but
+with the artificial stars generated by ADDSTAR added. The output table
+contains the x,y position and magnitude of each of the added stars. When the
+nframe parameter is set greater than one then there will be nframe pairs of
+output files generated.
+
+.sh
+3.3 ALLSTAR
+
+ ALLSTAR fits multiple, overlapping point-spread functions to stars images
+in the input image file. It uses as input the results from APPHOT and an
+input PSF and will automatically reduce the entire image performing the necessary
+grouping. It will recalculate the grouping after each iteration. ALLSTAR will
+also produce the star-subtracted image file.
+
+.sh
+3.3.1 ALLSTAR Parameters
+
+ALLSTAR has several parameters which control the fitting algorithms. The
+names, datatypes, default values for the ALLSTAR parameters are given below.
+
+.ks
+.nf
+Positional parameters:
+
+ input_image filename
+ photometry filename
+ output filename
+ sub_image filename
+.fi
+.ke
+
+.ks
+.nf
+Hidden parameters:
+
+ daopars pset "daophot$daopars.par"
+ max_group integer 60
+ redeterm_cent boolean true
+ max_crit real 2.5
+ min_crit real 1.2
+ clip_exp integer 6
+ clip_range real 2.5
+ verbose boolean false
+.fi
+.ke
+
+These parameters perform the following functions:
+
+.ls 4
+.ls 16 input_image
+The name of the input image file.
+.le
+.ls photometry
+The name of the input photometry SDAS table. This may contain output from either
+the APPHOT package or from NSTAR or previous ALLSTAR runs.
+.le
+.ls output
+The name of the SDAS table to contain the results of the psf fittting.
+.le
+.ls sub_image
+The name of the output image file which will have all of the fitted stars
+subtracted from it. If this file is the null string then no star-subtracted
+image file will be produced.
+.le
+.ls daopars
+The pset parameter file containing the DAOPHOT parameter set.
+.le
+.ls max_group
+The maximum size group which ALLSTAR will process. The absolute maximum
+is 60 stars.
+.le
+.ls redeterm_cent
+If true then the centers of the stars are redetermined before each
+iteration.
+.le
+.ls max_crit
+The initial value which ALLSTAR uses as the critical separation for
+use in grouping stars together. For groups larger than "max_group" ALLSTAR
+will use progressively smaller values for the critical separation until the
+group breaks up into units containing fewer than "max_group" stars or until
+the value of "min_crit" is reached.
+.le
+.ls min_crit
+The smallest value of the critical separation which ALLSTAR will use in
+grouping stars together.
+.le
+.ls clip_exp, clip_range
+These parameters are used to "resist bad data". These two
+parameters control the weighting of each pixel as a function of it's
+residual from the fit. Clip_range us variable "a" and clip_exp is
+variable "b" in the paper by Stetson (P.A.S.P. 99, 191)
+.le
+.le
+
+.sh
+3.3.2 The ALLSTAR PSF Fitting Algorithm
+
+ The algorithms which ALLSTAR uses to do the psf fitting photometry are
+very nearly the same as those used by NSTAR. One is referred to Stetson,
+P.A.S.P. 99, 191, for the details on the various fitting, star rejection,
+and weighting algorithms used in this task.
+.sh
+3.3.3 The Output from ALLSTAR
+
+ The output from ALLSTAR consists of three parts. There is the output
+photometry results, an SDAS Table, and a subtracted image file. The subtracted
+image file is a copy of the input image file minus the fitted stars.
+
+For each object processed by ALLSTAR there is one row in the output SDAS
+Table. Each measured object will have entries for the following items:
+
+.nf
+ star, x, y, mag, magerr, sky, niter, chi, sharp
+
+where
+
+ star star ID number
+ x,y coordinates of the stellar centroid
+ mag magnitude relative to the magnitude of the PSF star
+ magerr estimated standard error of the star's magnitude
+ sky estimated sky as returned by APPHOT
+ niter number of iterations for convergence
+ chi observed pixel to pixel scatter DIVIDED BY the expected
+ pixel to pixel scatter
+ sharp an index describing the spatial distribution of the residuals
+ around the star. Objects with SHARP significantly greater
+ than zero are extended (possibly galaxies), while objects with
+ SHARP significantly less than zero may be bad pixels or cosmic
+ rays
+.fi
+
+Other noteworthy pieces of information will be stored in the output SDAS
+Table header. This includes such things as the time and date of processing,
+the name of the PSF file, the name of the input photometry file, the
+fitting radius etc.
+
+.sh
+3.4 The CALIBRATE Task
+
+.sh
+3.5 The CMD Task
+
+.sh
+3.6 The DAOPARS Task
+
+ This is a pset-task which is used to describe a particular image file
+for use with the DAOPHOT package. This pset contains parameters which describe the
+data, e.g. the read out noise, the background sky value, the number of photons
+per ADC unit, etc., and also parameters which control the DAOPHOT tasks, e.g.
+the fitting radius to use. The parameters in this pset are used by several
+DAOPHOT tasks, hence their grouping into a pset.
+
+.sh
+3.6.1 daopars Parameters
+
+ The parameters in this task either describe the data in
+a particular image file
+or are parameters which are used by more algorithms in more than one
+DAOPHOT task. The following parameters make up this pset:
+
+.ks
+.nf
+
+ fitrad real 2.5 (pixels)
+ psfrad real 11.0(pixels)
+ phot_adc real 10.0
+ read_noise real 20.0
+ max_good real 32766.
+ min_good real 0.0
+ sky_val real 0.0
+ numb_exp integer 1
+ comb_type string "average"
+ var_psf boolean false
+.fi
+.ke
+
+The function and format of each of these parameters is described below:
+
+.ls 4
+.ls 16 fitrad
+The fitting radius to use in the PEAK, NSTAR, ALLSTAR and PSF tasks. Only
+the pixels within one fitting radius are actually used in the fit. This should
+normally be on the order of the FWHM of the stellar images.
+.le
+.ls psfrad
+The radius of the circle within which the PSF is defined. This should be
+somewhat larger than the actual radius of the brightest star you are
+interested in.
+.le
+.ls maxgood
+The maximum data value in ADC units at which the CCD or other detector
+is believed to operate linearly.
+.le
+.ls mingood
+The minimum data value in ADC units which should be used as "real" data.
+Dead pixels, bad columns etc. in the image file can be excluded from use in
+the analysis by setting this parameters properly. Any data value which
+falls below this minimum is ignored by DAOPHOT tasks.
+.le
+.ls sky_val
+The typical sky brightness in ADC units for the image file. This parameter is
+updated by the SKY task within the DAOPHOT package.
+.le
+.ls phot_adc
+The number of photons per ADC unit of the CCD or other detector.
+.le
+.ls read_noise
+The readout noise in ADC units of the CCD or other detector.
+.le
+.ls numb_exp
+The number of individual exposures which have been combined to produce the
+current image file. This number combined with information on whether the
+exposures were summed or averaged is used to get a better handle on the
+error estimates of the photometry.
+.le
+.ls comb_type
+Describes whether the individual exposures which went into making up this
+image file were "summed" or "averaged"
+.le
+.ls var_psf
+Controls whether the shape of the PSF is to be regarded as constant over the
+complete image file. Slight and smooth variations can be accomodated by the
+DAOPHOT tasks.
+.le
+.le
+
+ These parameters should be initially set by the user before starting any
+analysis with the DAOPHOT package. Each image file may have it's own set of
+parameters and these should be stored in separate pset files.
+.sh
+3.7 The EXAMINE Task
+
+ EXAMINE allows the user to interactively examine the results of the
+DAOPHOT reduction and to accept or reject individual stars. EXAMINE will
+accept as input the output photometry list from either ALLSTAR or NSTAR.
+For each star in the input list the user can examine either a 3-d meshplot
+or a contour diagram of both the input image and the star-subtracted image.
+The results of the photometry for the star under consideration is also
+displayed.
+
+Two output star lists are produced using this task. One is a list
+of stars which have been "accepted" by the user, the other being a list
+of stars which have been "rejected".
+
+If the TV option is selected then both the original image and subtracted
+image are displayed on the "stdimage" and the star under consideration is
+identified. The user has the ability to blink these two frames to
+evaluate the results of the photometry.
+
+This task is controlled via input from the terminal with various keys
+performing a variety of functions.
+
+.sh
+3.7.1 EXAMINE Parameters
+ There are several parameters which control various aspects of the
+EXAMINE task. The parameters control such things as the input photometry
+list, the type of graphical display desired and whether to use the
+display capabilities.
+
+.ks
+.nf
+Query mode parameters:
+
+ phot_list filename
+
+ fwhm real (pixels)
+ threshold real (in units of sigma)
+ output_file filename
+.fi
+.ke
+
+.sh
+3.9 The GROUP Task
+
+ GROUP is used to divide the stars in the image file into natural
+groups prior to analysis with NSTAR. GROUP works on the following
+principle: if two stars are close enough that the light of one will
+influence the profile fit of the other, then they belong in the same
+group.
+
+.sh
+3.9.1 GROUP Parameters
+
+ GROUP only has a few parameters which govern its operation. These
+are:
+
+.ks
+.nf
+Query mode parameters:
+
+ input_image filename
+ psf_file filename
+ crit_overlap real
+ output filename
+.fi
+.ke
+
+.ks
+.nf
+Hidden mode parameters:
+
+ daopars pset "daophot$daopars.par"
+.fi
+.ke
+
+These parameters perform the following functions:
+
+.ls 4
+.ls 16 input_image
+The name of the input image file.
+.le
+.ls psf_file
+The name of the file containing the PSF.
+.le
+.ls crit_overlap
+The "critical overlap" before one star is determined to influence
+another. When GROUP examines two stars to see whether they might influence
+each others' fits, it firts identifies the fainter of the two stars. It then
+calculates the brightness of the brighter star at a distanceof one fitting
+radius plus one pixel from the center of the fainter. If this brightness is
+greater than the "critical overlap" times the random error per pixel, then
+the brighter star is deemed to be capable of affecting the photometry of the
+fainter, and the two stars are grouped together.
+.le
+.ls output
+The name of the SDAS table which will contain the stellar groups.
+.le
+.ls daopars
+The name of of a pset file containing the daophot parameters. The specific
+parameters which are used from this include the following:
+.le
+.le
+.sh
+3.10 The GROWTH Task
+
+.sh
+3.11 The OFFSET task
+
+.sh
+3.12 The PEAK Task
+
+ PEAK fits the PSF to a single star. It is useful for sparsely populated
+image files where the stars of interest are not blended. In this cases aperture
+photometry is often fine and the use of PEAK is of limited interest. This task
+is included in the DAOPHOT package mainly for completeness.
+
+.sh
+3.12.1 PEAK Parameters
+
+ The parameters specific to the PEAK task are used for specifying the
+input and output from this routine. The names of the parameters and their
+functions are:
+
+.ks
+.nf
+Positional or query parameters:
+
+ input_image filename
+ psf_file filename
+ output filename
+.fi
+.ke
+
+.ks
+.nf
+Hidden parameters:
+
+ daopars pset "daophot$daopars.par"
+ verbose boolean false
+.fi
+.ke
+
+.ls 4
+.ls 16 input_image
+The name of the input image file.
+.le
+.ls psf_file
+The name of the input file containing the point-spread function.
+.le
+.ls output
+The name of the SDAS table to contain the output from PEAK.
+.le
+.ls verbose
+If true then PEAK outputs more information about what it is doing.
+.le
+.ls daopars
+The name of a pset file which contains the parameters specific to the
+input image file. The parameters which PEAK uses from this pset include:
+sthe fitting radius, the maximum and minimum good data value and whether
+a variable PSF is to be used.
+.le
+.le
+.sh
+3.13 The PSF Task
+
+ The PSF task is used for obtaining the point-spread function which
+will be used in the rest of the DAOPHOT reductions. DAOPHOT uses an
+empirical point-spread function as opposed to a mathematically defined
+function. The PSF is defined from the actual brightness distribution
+of one or more stars in the frame under consideration. It is stored as
+a two-component model: (1) an analytic Gaussian profile which approximately
+matches the core of the point-spread function, and (2) a look-up table of
+residuals, which are used as additive corrections to the integrated
+analytic Gaussian function.
+
+The brightness in a hypothetical pixel at an arbitrary point within the
+point-spread function is determined in the following manner. First
+the bivariate Gaussian function is integrated over the area of the pixel,
+and then a correction is determined by double cubic interpolation
+within the lookup table, and is added to the integrated intensity.
+
+The PSF is stored as a binary data file and is in a format specific
+to DAOPHOT. The format of this file is very similar to that used by the
+VMS version of DAOPHOT but is stored in binary for compactness.
+A function is provided to take the PSF and convert it
+to a IRAF image file so that it can be manipulated by other IRAF
+tasks.
+
+PSF allows the user to perform most functions from within the interactive
+graphics part of its operation. PSF allows the user to modify the
+perspective of hist mesh plot, the contouring interval, the PSF radius
+etc. from within the PSF interactive graphics.
+
+.sh
+3.13.1 PSF Parameters
+
+ The PSF task has many parameters which specify the input and
+output files as well as specifying other information. These are
+divided in query mode parameters and hidden parameters.
+
+.ks
+.nf
+Positional or query parameters:
+
+ input_image filename
+ phot_list filename
+ psf_stars filename
+ psf_file filename
+.fi
+.ke
+
+.ks
+.nf
+Hidden parameters:
+
+ daopars pset "daophot$daopars.par"
+ verbose boolean false
+.fi
+.ke
+
+.ls 4
+.ls 16 input_image
+The name of the input image file.
+.le
+.ls phot_list
+The name of the input file containing the aperture photometry
+results for this image frame.
+.le
+.ls psf_stars
+The name of file coordinate file containing the list of stars
+to be used as PSF candidates.
+.le
+.ls psf_file
+The name of the output file for storing the PSF.
+.le
+.ls verbose
+If true then PEAK outputs more information about what it is doing.
+.le
+.ls daopars
+The name of a pset file which contains the parameters specific to the
+input image file. The parameters which PEAK uses from this pset include:
+sthe fitting radius, the maximum and minimum good data value and whether
+a variable PSF is to be used.
+.le
+.le
+.sh
+3.14 The NSTAR Task
+
+ NSTAR is one of DAOPHOT's multiple, simultaneous, profile-fitting
+photometry routine. It is similar to ALLSTAR except that NSTAR must have
+the objects grouped (using the GROUP task) and it does not dynamically
+alter the groups while running. NSTAR also does not automatically produce the
+star subtracted image file.
+
+.sh
+3.14.1 NSTAR Parameters
+
+ There are several parameters which control the function of the
+NSTAR task. These are the following:
+
+.ks
+.nf
+Positional or Query Parameters:
+
+ input_image filename
+ psf_file filename
+ group_file filename
+ output_file filename
+.fi
+.ke
+
+.ks
+.nf
+Hidden parameters:
+
+ daopars pset "daophot$daopars.par"
+ verbose boolean false
+.fi
+.ke
+
+.sh
+3.15 The SEEPSF Task
+
+ The SEEPSF task produces an IRAF image file from the given PSF
+file. This allows other IRAF tasks, especially display and plotting tasks,
+to use access the point-spread function. The user has the ability to create
+any size of image from the PSF enlargements being handled by a number of
+different interpolation schemes.
+
+.sh
+3.15.1 SEEPSF Parameters
+
+ The parameters wich control this task are limted. They basically
+control the input, output and size of the image.
+
+.ks
+.nf
+Positional or Query Parameters:
+
+ psf_file filename
+ image_name filename
+ image_size integer
+.fi
+.ke
+
+.ks
+.nf
+Hidden parameters:
+
+ interpolation string "nearest"
+ boundary string "constant"
+ constant real 0.0
+ daopars pset "daophot$daopars.par"
+ verbose boolean false
+.fi
+.ke
+
+.ls 4
+.ls 16 psf_file
+This specifies the input PSF file which is to be transformed into an
+IRAF image.
+.le
+.ls image_name
+The name of the output IRAF image.
+.le
+.ls image_size
+The size of the output image in pixels per side. Note that only square PSFs
+and PSF images are alllowed.
+.le
+.ls interpolation
+The type of interpolation to be used in expanding the image. The choices
+are "nearest" neighbor, "linear" bilinear, "poly3" bicubic polynomial,
+"poly5" biquintic polynomial, and "spline3" bicubic spline.
+.le
+.ls boundary
+The type of boundary extension to use for handling references to pixels
+outside the bounds of the input image. The choices are: "constant",
+"nearest" edge, "reflect" about the boundary and "wrap" to the other side
+of the image.
+.le
+.le
+.sh
+3.16 The SELECT Task
+
+ The SELECT task is used to select groups of stars with a particular
+range of sizes from a group file which has been produced by GROUP. This
+task is used when some of the groups in the group file are large than the
+maximum allowed in NSTAR, currently 60 stars.
+
+.sh
+3.16.1 SELECT Parameters
+
+ The parameters which control the SELECT task are the following:
+
+.ks
+.nf
+Positional or Query Parameters:
+
+ input_group filename
+ output_group filename
+ min_group integer
+ max_group integer
+.fi
+.ke
+
+.le 4
+.ls 16 input_group
+The input group file which is to be searched for groups within the
+limits specified by min_group and max_group.
+.le
+.ls output_group
+The output group file which will consist of groups between 'min_group'
+and 'max_group' in size.
+.le
+.ls min_group
+The minimum group size to be extracted from the input group file.
+.le
+.ls max_group
+The maximum group size to be extracted from the input group file.
+.le
+.le
+.sh
+3.17 The SKY Task
+
+.sh
+3.18 The SORT Task
+
+.sh
+3.19 The SUBSTAR Task
+
+ The SUBSTAR command takes the point-spread function for an image
+frame and a file containing the x,y coordinates and apparent magnitudes
+for a group of stars, usually an output file from one of the photometry
+routines, shifts and scales the PSF function
+according to each position and magnitude, and then subtracts it from the
+original image frame.
+
+.sh
+3.19.1 SUBSTAR Parameters
+
+ The parameters for SUBSTAR control the input and output from this
+task.
+
+.ks
+.nf
+Positional or Query Parameters:
+
+ psf_file filename
+ phot_file filename
+ input_image filename
+ output_image filename
+.fi
+.ke
+
+.ks
+.nf
+Hidden parameters:
+
+ verbose boolean false
+.fi
+.ke
+
+.ls 4
+.ls 16 psf_file
+The name of the file containing the PSF which is to be used as the template
+in the star subtraction.
+.le
+.ls phot_file
+The file containing the photometry results for the stars which are to be
+subtracted from the input image.
+.le
+.ls input_image
+The name of the input image file from which the stars are to be subtracted.
+.le
+.ls output_image
+The name of the output image file which will be a copy of the input frame
+except for the subtracted stars.
+.le
+.ls verbose
+If this parameter is set to true then more information about the progress
+of SUBSTAR is output.
+.le
+.le
+.sh
+4.0 Example
+
+.endhelp
diff --git a/noao/digiphot/daophot/doc/specs/daoutils.spc b/noao/digiphot/daophot/doc/specs/daoutils.spc
new file mode 100644
index 00000000..d943d63a
--- /dev/null
+++ b/noao/digiphot/daophot/doc/specs/daoutils.spc
@@ -0,0 +1,700 @@
+.help daoutils Jan89 "Utility Package for DAOPHOT"
+.sh
+1. Introduction
+
+The DAOUTILS package will provide a set of tools for working
+with the output from DAOPHOT. These tools will provide the user with
+the ability to select data upon ranges and limits for any of the
+fields in a daophot output table. The package will also provide tools
+for merging results contained in different output files.
+
+.sh
+2. Requirements
+.ls 4
+.ls (1)
+The tasks in the DAOUTILS package shall take as input the output ST Tables
+from the DAOPHOT tasks. The convert task in the daophot package shall be
+used to convert the output from apphot tasks into the proper format for use
+with the daoutils package.
+.le
+.ls (2)
+The tasks in the package which produce tabular output shall use the
+ST Tables for their output and those tasks which read output from other
+DAOUTILS tasks will be able to read ST Tables.
+.le
+.ls (3)
+The DAOUTILS package shall include tasks to inspect and edit the results
+from the photometry routines. These shall include tasks such as interactively
+rejecting particular stars from the results,
+producing plots of errors versus brightness, errors versus position etc. There
+will also be a task for merging the results contained in several different
+Tables. It shall also be possible to interactively examine the photometry
+results with various graphical and/or display tools for inspecting/editing the
+results. It shall also be possible to construct growth curves from the
+aperture photometry for the purpose of calibrating the daophot magnitudes
+to total magnitudes. There shall also be routines for calibrating the
+photometry by the use of standard stars.
+.le
+.ls (4)
+The tasks shall be able to be run in batch mode as well as interative
+mode. In batch mode use of a graphics terminal or image display shall not
+be required.
+.le
+.ls (5)
+The DAOPHOT package shall be written in the SPP language in conformance with
+the standards and conventions of IRAF. The code shall be portable and
+device independent.
+.le
+.le
+.sh
+2.1 Limitations of the Initial DAOUTILS Package
+
+The DAOUTILS package will have the following limitations:
+.ls
+.ls (1)
+The initial version of DAOUTILS will not make direct use of the interactive
+image display. It will make use of cursor readback however.
+.le
+.le
+
+.sh
+3. Specifications
+
+The DAOUTILS package will take the output from the DAOPOHT package as input
+and provide a variety of tools which will allow the use to examine, edit and
+calibrate the output from DAOPHOT. The output from DAOUTILS will consist of
+ST Tables, graphical displays and printed summaries.
+
+The CL callable part of the DAOUTILS package will consist of the following
+tasks:
+
+.ks
+.nf
+ merge -- Merge the results from different runs of daophot
+ daograph -- Graph the results of daophot stored in ST Tables
+ gtedit -- Interactive graphical data editor
+ examine -- Interactively examine the output from daophot
+ growth -- aperture growth curves <--> PSF magnitudes
+ cmd -- Color-magnitude and color-color plots
+ calibrate -- do photometric calibration
+
+.fi
+.ke
+
+In addition the ttools package provided as part of STSDAS provides for
+many generic tools for working with the ST Tables are will be usable for
+many of the data selection tasks which most users will wish to apply to
+daophot output.
+
+.sh
+3.1 The GTEDIT Task
+
+The user will be able to plot any two columns of a Table versus each other
+and with the cursor interactively delete records. The user will move the
+graphics cursor near the point on the graph which represents the record
+which he wishes to delete from the input record. The user will also be able
+to specify 'areas' of the plot for which all records pointed to by points
+in the indicated sections will be deleted. The user will also be
+able to undelete records. The records will not actually be deleted until the
+task ends. The user will also be able to interactively change which columns
+are being plotted versus each other. The user will also have the option of
+editing the table in place or to create a new output table which will contain
+the edited results of the input table.
+
+.sh
+3.1.1 GEDIT Parameters
+
+GEDIT will have input parameters which control the input and initial
+operation of the task.
+
+.ks
+.nf
+Positional or query mode parameters:
+
+ input - filename
+ xcolumn - column name (string)
+ ycolumn - column name (string)
+.fi
+.ke
+
+.ks
+.nf
+Hidden parameters:
+
+ inplace boolean "false"
+ output filename ""
+ reject filename ""
+.fi
+.ke
+
+The function and format of these parameters is decsribed in more detail
+below.
+
+.ls
+.ls 16 input
+The name of the input table which contains the output from DAOPHOT.
+.le
+.ls xcolumn
+The name of the column in the input table which will be used for the
+X axis of the plot
+.le
+.ls ycolumn
+The name of the column in the input table which will be used for the
+Y axis of the plot
+.le
+.ls inplace
+Controls whether the input table is modified in place or whether a new
+table is created.
+.le
+.ls output
+If inplace is false then the value of this parameter will be the name of
+the output table which will contain the edited output.
+.le
+.ls reject
+The name of the output file containing those objects which have been
+deleted. If this parameter is NULL then the records which have been
+deleted are not saved.
+.le
+.le
+
+.sh
+3.1.2 Interactive GEDIT Commands
+
+Once GEDIT has plotted the two columns specified as the input there are
+several commands available to the user. These allow the user to delete/undelete
+points, change which columns are plotted, view a particular record from the
+input table and exit GEDIT.
+
+.ks
+.nf
+In the interactive mode the following cursor keys are active:
+
+ x -- delete the record represented by the point nearest the cursor
+ > -- delete all records represented by Y values > than the cursor
+ < -- delete all records represented by Y values < than the cursor
+ + -- delete all records represented by X values > than the cursor
+ - -- delete all records represented by X values < than the cursor
+ b -- mark the corner of box containing records to be deleted.
+ u -- undelete the record(s) deleted by the last delete operation
+ q -- exit GEDIT
+.fi
+.ke
+
+.ks
+.nf
+In addition the following colon commands are available:
+
+ :xcol <name> Use the column <name> as the X axis
+ :ycol <name> Use the column <name> as the Y axis
+.fi
+.ke
+
+.sh
+3.1.3 GEDIT OUTPUT
+
+The output from GEDIT is a direct copy of the input table with the records
+which the user marked for deletion removed. If the parameter 'inplace' was
+set to true then the edited table replaces the original table, otherwise a
+new table is created. Is it important that no records be deleted until the
+user exits GEDIT and confirms that the update is to take place.
+
+.sh
+3.2 TGRAPH
+
+This task is will produce plots from the DAOPHOT output tables. It is similar
+to the sgraph task in STSDAS but does not have the option of plotting image
+sections. It does have the ability to plot error bars and columns of data from
+two different tables.
+
+The following is the help for sgraph:
+
+.ih
+NAME
+graph -- graph one or more lists, image sections, or tables
+.ih
+USAGE
+graph input
+.ih
+PARAMETERS
+.ls input
+List of operands to be graphed. May be STDIN, or one or more image
+sections, tables and columns, or lists. SDAS table input is specified
+by: a table name and column name, a table and two column names, or a
+pair of table and column names, separated by white space.
+.le
+.ls stack = no
+If stack = yes, plot multiple curves on separate axes (WCS) stacked
+vertically rather than on the same axes.
+.le
+.ls wx1=0., wx2=0., wy1=0., wy2=0.
+The range of user coordinates spanned by the plot. If the range of values
+in x or y = 0, the plot is automatically scaled from the minimum to
+maximum data value along the degenerate dimension.
+.le
+.ls vx1=0., vx2=0., vy1=0., vy2=0.
+NDC coordinates (0-1) of the device plotting viewport. If not set by
+the user, a suitable viewport which allows sufficient room for all labels
+is used.
+.le
+.ls pointmode = no
+If \fBpointmode\fR = yes, plot points or markers at data values, rather than
+connected lines.
+.le
+.ls marker = "box"
+Marker to be drawn if \fBpointmode\fR = yes. Markers are "point", "box",
+"cross", "plus" or "circle".
+.le
+.ls szmarker = 0.005
+The size of a marker in NDC coordinates (0 to 1 spans the screen).
+If zero and the input operand is a list, marker sizes are taken individually
+from the third column of each list element. If positive, all markers are
+of size \fBszmarker\fR. If negative and the input operand is a list,
+the size of a marker is the third column of each list element times the
+absolute value of \fBszmarker\fR.
+.le
+.ls xlabel = "", ylabel = ""
+Label for the X-axis or Y-axis.
+.le
+.ls title = "imtitle"
+Plot title. If \fBtitle\fR = "imtitle"
+and the first operand in \fBinput\fR is an image, the image title is used
+as the plot title.
+.le
+.ls box = yes
+Draw axes at the perimeter of the plotting window.
+.le
+.ls fill = yes
+Fill the output viewport regardless of the device aspect ratio?
+.le
+.ls axis = 1
+Axis along which the projection is to be computed, if an input operand is
+an image section of dimension 2 or higher. Axis 1 is X (line average),
+2 is Y (column average), and so on.
+.le
+.ls erraxis = 0
+If pointmode = no and erraxis is 1 or 2, the axis parallel to which
+error bars are plotted (1 ==> X, 2 ==> Y).
+.le
+.ls errcolumn = ""
+The column(s) in the input table to be used as the error amplitude(s).
+If one column name, then symmetrical symmetrical error bars are drawn,
+centered on the data points with the total size, in WC specified by the
+values in the column from the same table specified in parameter input.
+Two names specify two table columns for the lower and upper errors,
+respectively.
+.le
+.ls pattern = "solid"
+The line pattern for the first curve. Subsequent curves on the same
+plot cycle through the set of patterns: solid, dashed, dotted, dotdash.
+.le
+.ls crvstyle = "straight"
+The style of the plotted curve: "straight" is the usual straight
+line connection between points, "pseudohist" consists of horizontal
+segments at each data point connected by vertical segments, "fullhist"
+is a bar graph or histogram style plot.
+.le
+.ls transpose = no
+Swap the X and Y axes of the plot. If enabled, the axes are transposed
+after the optional linear transformation of the X-axis.
+.le
+.ls xflip = no, yflip = no
+Flip the axis? That is, plot and label X values increasing right to
+left instead of left to right and/or Y values top to bottom instead of
+bottom to top.
+.le
+.ls logx = no, logy = no
+Log scale the X or Y axis. Zero or negative values are indefinite and
+will not be plotted, but are tolerated.
+.le
+.ls ticklabels = yes
+Label the tick marks.
+.le
+.ls majrx=5, minrx=5, majry=5, minry=5
+Number of major tick marks on each axis; number of minor tick marks between
+major tick marks. Ignored if log scaling is in effect for an axis.
+.le
+.ls lintran = no
+Perform a linear transformation of the X-axis upon input. Used to assign
+logical coordinates to the indices of pixel data arrays (image sections).
+.le
+.ls p1=0, p2=0, q1=0, q2=1
+If \fBlintran\fR is enabled, pixel index P1 is mapped to Q1, and P2 to Q2.
+If P1 and P2 are zero, P1 is set to 1 and P2 to the number of pixels in
+the input array.
+.le
+.ls round = no
+Extend the axes up to "nice" values.
+.le
+.ls append = no
+Append to an existing plot.
+.le
+.ls device = "stdgraph"
+The output device.
+.le
+.ih
+DESCRIPTION
+\fBGraph\fR graphs one or more lists, image sections, or table columns;
+lists and image sections may be mixed in the input list at will. If the
+curves are not all the same length the plot will be scaled to the
+longest curve and all curves will be plotted left justified. If an
+image section operand has more than one dimension the projection
+(average) along a designated axis will be computed and plotted. By
+default, a unique dash pattern is used for each curve, up to a maximum
+of 4.
+
+List input may be taken from the standard input or from a file,
+and consists of a sequence of Y values, X and Y values, or X, Y,
+and marker size values, one pair of coordinates per line in the list.
+Blank lines, comment lines, and extra columns are ignored.
+The first element in the list determines whether the list is a Y list
+or and X,Y list; it is an error if an X,Y list has fewer than two
+coordinates in any element. INDEF valued elements appear as gaps
+in the plot.
+
+SDAS table input is specified by a table name and column name, a table
+and two columns, or a pair of table and column names separated by white
+space. The table name may be a file name template. Note that this is a
+single string, so that it must be quoted if entered on the command line.
+
+Error bars may be plotted for data from list or table input. Errors may
+be in X or in Y and separate upper and lower errors may be specified.
+If `pointmode' is "no" then the parameter `erraxis' specifies if the
+errors are in X or in Y if its value is 1 or 2, respectively. If
+`pointmode' is "no" and `erraxis' is zero, a polyline is plotted (see
+below). If the input data come from a list, then the third (size)
+column specifies the amplitude of symmetrical error bars. If there is a
+fourth column, the third and fourth columns specify the amplitudes of
+the lower and upper errors, respectively. If the input data are in a
+table, the parameter `errcol' specifies the source of the errors.
+If `errcol' contains a single word, it is the column in the same table
+as the input data containing the amplitudes of symmetrical errors. If
+`errcol' contains two words, they specify the columns in the same table
+containing the amplitudes of the lower and upper errors, respectively.
+If the X and Y data come from different tables, then `erraxis' specifies
+which table contains the error column or columns. Error data may not
+come from image data. The `append' parameter may be used
+to overplot several curves of different style.
+
+Different line types and curve styles may be selected. The string
+parameter `crvstyle' may take on one of the values: "none", "straight",
+"pseudohist", or "fullhist", specifying the style of connections between
+data points; the string parameter `pattern' can take on one of the
+values "solid", "dashed", "dotted", "dotdash" to indicate the style
+of the first line drawn. Subsequent lines drawn on the same graph cycle
+the available styles.
+
+If \fBappend\fR is enabled, previous values for \fBbox\fR,
+\fBfill\fR, \fBround\fR, the plotting viewport (\fBvx1\fR, \fBvx2\fR,
+\fBvy1\fR, \fBvy2\fR), and the plotting window (\fBwx1\fR, \fBwx2\fR,
+\fBwy1\fR, \fBwy2\fR) are used.
+
+By default, the plot drawn will fill the device viewport, if the viewport
+was either specified by the user or automatically calculated by
+\fIgraph\fR. Setting
+the value of \fBfill\fR to "no" means the viewport will be adjusted so
+that equal numbers of data values in x and y will occupy equal lengths
+when plotted. That is, when \fBfill = no\fR, a unity aspect ratio is
+enforced, and plots
+appear square regardless of the device aspect ratio. On devices with non
+square full device viewports (e.g., the vt640), a plot drawn by \fIgraph\fR
+appears extended in the x direction unless \fBfill\fR = no.
+
+.ih
+EXAMPLES
+Plot the output of a list processing filter:
+
+ cl> ... list_filter | graph
+
+Plot a graph entered interactively from the terminal:
+
+ cl> graph STDIN
+
+Overplot two lists:
+
+ cl> graph list1,list2
+
+Graph line 128 of image "pix":
+
+ cl> graph pix[*,128]
+
+Graph the average of columns 50 through 100:
+
+ cl> graph pix[50:100,*] axis=2
+
+Graph two columns from a table against each other:
+
+ cl> graph "table xcol ycol"
+
+Graph a list in point plot mode:
+
+ cl> graph list po+
+
+Annotate a graph:
+
+.nf
+ cl> graph pix[*,10],pix[*,20] xlabel=column\
+ >>> ylabel=intensity title="lines 10 and 20 of pix"
+.fi
+
+Direct the graph to the standard plotter device:
+
+ cl> graph list device=stdplot
+.ih
+BUGS
+Indefinites are not recognized when computing image projections.
+
+End sgraph help.
+
+.sh
+3.3 The MERGE Task
+
+This task will merge the results from a maximum of four DAOPHOT output
+files based upon positional coincidence. This task will work on files
+which could have been run images with different scales, orientations etc.
+MERGE will need to transform the coordinate systems of the input photometry
+lists to a common coordinate system. There will be two ways of inputing the
+transformations to be applied to the coordinate lists: 1) Simple X, Y shifts
+or 2) transformations as determined by the GEOMAP task. This will allow the
+most common cases to handled in a simple way without having to run the GEOMAP
+task.
+
+The user will be able to specify a match radius which will determine how
+close to each other two objects must be to be considered a coincidence.
+The user will also be able to specify the number of lists an object must
+be identified in to be included in the output file. For example, if the
+user was merging photometry results from four different output tables
+he could request that the output table would contain entries for matches
+between any two or more of the four tables. The output Table from MERGE
+will simply contain pointers to the corresponding rows of the various
+input tables and not contain a copy of the complete row from each table
+for those objects which were matched. The user will then run another task,
+MSELECT to select the fields he wants from the original photometry files.
+This will allow the user to select only the fields he wants and to do the
+selection more than once without remerging the individual files.
+
+.sh
+3.3.1 MERGE Parameters
+
+MERGE shall have parameters which control the input and functioning of the
+task.
+
+.ks
+.nf
+Positional or query parameters:
+
+ ptable1 -- Input photometry table #1
+ ptable2 -- Input photometry table #2
+ ptable3 -- Input photometry table #3
+ ptable4 -- Input photometry table #4
+ matchrad -- Matching radius for coincidence
+ nmatch -- minimum number of matches to be included in output
+ merge_table -- output table containing merge pointers
+.fi
+.ke
+
+.ks
+.nf
+Hidden Parameters:
+
+ gmfile12 -- geomap database name for transforming #1 -> #2
+ gmrec12 -- geomap database record for transforming #1 -> #2
+ gmfile13 -- geomap database name for transforming #1 -> #3
+ gmrec13 -- geomap database record for transforming #1 -> #3
+ gmfile14 -- geomap database name for transforming #1 -> #4
+ gmrec14 -- geomap database record for transforming #1 -> #4
+ dx12 -- X offset (x2 - x1)
+ dy12 -- Y offset (y2 - y1)
+ dx13 -- X offset (x3 - x1)
+ dy13 -- Y offset (y3 - y1)
+ dx14 -- X offset (x4 - x1)
+ dy14 -- Y offset (y4 - y1)
+.fi
+.ke
+
+These parameters perform the following functions:
+
+.ls 4
+.ls 16 ptable1
+The name of the first input photometry table. This should be a standard
+DAOPHOT output table or one whose column names have been modified to agree
+with the DAOPHOT standard.
+.le
+.ls ptable2
+The name of the second input photometry table.
+.le
+.ls ptable3
+The name of the third input photometry table.
+.le
+.ls ptable4
+The name of the fourth input photometry table.
+.le
+.ls matchrad
+The matching radius for determining whether two objects should be identified
+with the same object and potentially included in the output table.
+.le
+.ls nmatch
+The minumum number of matches among the input photometry files for an object
+to be included in the output Table. If there were four input files and
+\fInmatch\fR was set to two then an object would be included in the output
+if it was matched in files 1/2, 1/3, 1/4, 2/3, 2/4 or 3/4. If \fInmatch\fR
+was three then the object would have to be identified in files 1/2/3,
+2/3/4, 1/2/4 or 1/3/4
+.le
+.ls gmfile12
+The name of the \fIGEOMAP\fR database containing the record which specifies
+the transformation between photometry list 2 and photometry list 2 in the
+sense of mapping objects in list #2 into the coordinate frame of the
+list #1
+.le
+.ls gmrec12
+The name of \fIGEOMAP\fR database record within \fIgmfile12\fR which
+describes the transformation from coordinate system #2 to system #1
+.le
+.ls gmfile13
+The name of the \fIGEOMAP\fR database containing the record which specifies
+the transformation between photometry list 3 and photometry list 3 in the
+sense of mapping objects in list #3 into the coordinate frame of the
+list #1
+.le
+.ls gmrec13
+The name of \fIGEOMAP\fR database record within \fIgmfile13\fR which
+describes the transformation from coordinate system #3 to system #1
+.le
+.ls gmfile14
+The name of the \fIGEOMAP\fR database containing the record which specifies
+the transformation between photometry list 4 and photometry list 4 in the
+sense of mapping objects in list #4 into the coordinate frame of the
+list #1
+.le
+.ls gmrec14
+The name of \fIGEOMAP\fR database record within \fIgmfile14\fR which
+describes the transformation from coordinate system #4 to system #1
+.le
+.ls dx12
+The X offset between coordinate system #2 and coordinate system #1
+in the sense of (x2 - x1).
+.le
+.ls dy12
+The Y offset between coordinate system #2 and coordinate system #1
+in the sense of (y2 - y1).
+.le
+.ls dx13
+The X offset between coordinate system #3 and coordinate system #1
+in the sense of (x3 - x1).
+.le
+.ls dy13
+The Y offset between coordinate system #3 and coordinate system #1
+in the sense of (y3 - y1).
+.le
+.ls dx14
+The X offset between coordinate system #4 and coordinate system #1
+in the sense of (x4 - x1).
+.le
+.ls dy14
+The Y offset between coordinate system #4 and coordinate system #1
+in the sense of (y4 - y1).
+.le
+.le
+
+If the parameters specifying the \fIGEOMAP\fR database file name for
+a particular transformation is empty then the corresponding parameters
+describing the transformation in terms of a simple shift are queried.
+
+.sh
+3.3.2
+The Output from MERGE
+
+\fIMERGE\fR will produce an STSDAS Table as output with the table
+containing pointers to records in the input Tables which identify the
+objects which are positionally coincident. The output Table will contain
+columns with the names \fIpoint0\fR, \fIpoint1\fR, \fIpoint2\fR and
+\fIpoint3\fR. If an object is identified in a particular input photometry
+list and also meets the \fInmatch\fR criterion then the entry in the
+output Table will contain the row number in the corrsponding input Table.
+For those objects which are included in the output Table but which are not
+identified in a particular input Table the corrsponding entry will be
+INDEF.
+
+.ks
+.nf
+Sample Output Format (ASCII representation)
+
+ Point0 Point1 Point2 Point3
+
+ 1 3 INDEF 2
+ 3 2 2 4
+ 4 5 4 INDEF
+ INDEF 8 7 6
+
+ .fi
+ .ke
+
+ In the above sample the first matched object corrsponds to rows 1, 3 and
+ 2 in input Tables 0, 1 and 3 respectively. This object was not matched
+ in input Table 0.
+
+The header of the Table output by MERGE shall contain the necessary information
+for tracking the original data files, the data and time the merge was done etc.
+The MSELECT task should check that the original photometry files have not been
+modified since MERGE was run to ensure data integrity.
+
+.sh
+3.4 MSELECT
+
+This task is used to select fields from the photometry Tables which
+were used as input to the \fIMERGE\fR task. The output from \fIMERGE\fR
+is a set of pointers to the appropriate records in the input tables.
+Using \fIMSELECT\fR on an output file from \fIMERGE\fR will produce an
+output file which will contain the specified fields for each of the
+objects which have been matched. If an object has not been identified
+in a particular Table then the values for each output field are set to
+INDEF.
+
+.sh
+3.4.1 MSELECT Parameters
+
+MERGE will have parameters wich will control the input and functioning
+of the task.
+
+.ks
+.nf
+Positional Parameters:
+
+ input filename ""
+ fields string ""
+ output string ""
+.fi
+.ke
+
+.ks
+.nf
+Hidden Parameters:
+
+ tables string ""
+.fi
+.ke
+
+These parameters perform the following functions:
+
+.ls 4
+.ls 16 input
+This specifies the input Table which must be an output Table from the
+\fIMERGE\fR task. \fIMSELECT\fR will get the names of the actual
+photometry Tables from the header of the input merge table.
+.le
+.ls fields
+A list of fields to extract from the input photometry tables.
+.le
+.ls output
+The name of the output table. This table will contain entries for
+each of the selected fields of each photometry table. The values for
+each field in the output table will be the values of the selected fields
+for each of the input photometry tables. For those entries which were not
+nmatched the corresponding entries will be INDEF.
+.le
+.ls tables
+This parameter is used to select output for only a subset of the input
+photometry tables.
+.le
+
+.endhelp
diff --git a/noao/digiphot/daophot/doc/substar.hlp b/noao/digiphot/daophot/doc/substar.hlp
new file mode 100644
index 00000000..5de81b85
--- /dev/null
+++ b/noao/digiphot/daophot/doc/substar.hlp
@@ -0,0 +1,323 @@
+.help substar May00 noao.digiphot.daophot
+.ih
+NAME
+substar -- subtract photometry results from an image
+.ih
+USAGE
+substar image photfile exfile psfimage subimage
+.ih
+PARAMETERS
+.ls image
+The list of images from which to subtract the scaled and shifted PSF.
+.le
+.ls photfile
+The list of PSF fitted photometry files. There must be one photometry file
+for every input image. If photfile is "default", "dir$default", or a directory
+specification, SUBSTAR will look for a file called image.nst.? where the
+question mark stands for the highest existing version number. Photfile is
+usually the output of the NSTAR task but may also be the output of the PEAK
+and ALLSTAR tasks or even the PHOT task. Photfile may be an APPHOT/DAOPHOT text
+database or an STSDAS table.
+.le
+.ls exfile
+The list of photometry files containing the ids of stars to be excluded
+from the subtraction. Exfile must be undefined or contain one exclude file
+for every input image. If exfile is "default", "dir$default", or a directory
+specification, SUBSTAR will look for a file called image.pst.? where the ?
+mark stands for the highest existing version number. Exfile is usually the
+output of the PSTSELECT task but may also be the output of the PEAK, NSTAR and
+ALLSTAR tasks or even the PHOT task. Exfile may be an APPHOT/DAOPHOT text
+database or an STSDAS table.
+.le
+.ls psfimage
+The list of images containing the PSF models computed by the DAOPHOT PSF task.
+The number of PSF images must be equal to the number of input images. If
+psfimage is "default", "dir$default", or a directory specification,
+then PEAK will look for an image with the name image.psf.?, where
+? is the highest existing version number.
+.le
+.ls subimage
+The list of output subtracted images. There must be one output subtracted
+image for every input image. If subimage is "default", "dir$default", or a
+directory specification, then SUBSTAR will write an image called image.sub.?
+where question mark stands for the next available version number.
+.le
+.ls datapars = ""
+The name of the file containing the data dependent parameters. The parameters
+\fIscale\fR, \fIdatamin\fR, and \fIdatamax\fR are located here. If datapars
+is undefined then the default parameter set in uparm directory
+.le
+.ls daopars = ""
+The name of the file containing the daophot fitting parameters. The parameters
+\fIpsfrad\fR and \fIfitrad\fR are located here. If \fIdaopars\fR is undefined
+then the default parameter set in uparm directory is used.
+.le
+.ls wcsin = ")_.wcsin", wcsout = ")_.wcsout", wcspsf = ")_.wcspsf"
+The coordinate system of the input coordinates read from \fIphotfile\fR, of the
+psf model \fIpsfimage\fR, and of the output coordinates written to
+the standard output if \fIverbose\fR = "yes". The image header coordinate
+system is used to transform from the input coordinate system to the "logical"
+pixel coordinate system used internally, from the internal logical system to
+the PSF model system, and from the internal "logical" pixel coordinate system
+to the output coordinate system. The input coordinate system options are
+"logical", "tv", "physical", and "world". The PSF model and output coordinate
+system options are "logical", "tv", and "physical". The image cursor coordinate
+system is assumed to be the "tv" system.
+.ls logical
+Logical coordinates are pixel coordinates relative to the current image.
+The logical coordinate system is the coordinate system used by the image
+input/output routines to access the image data on disk. In the logical
+coordinate system the coordinates of the first pixel of a 2D image, e.g.
+dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300] are
+always (1,1).
+.le
+.ls tv
+Tv coordinates are the pixel coordinates used by the display servers. Tv
+coordinates include the effects of any input image section, but do not
+include the effects of previous linear transformations. If the input
+image name does not include an image section, then tv coordinates are
+identical to logical coordinates. If the input image name does include a
+section, and the input image has not been linearly transformed or copied from
+a parent image, tv coordinates are identical to physical coordinates.
+In the tv coordinate system the coordinates of the first pixel of a
+2D image, e.g. dev$ypix and a 2D image section, e.g. dev$ypix[200:300,200:300]
+are (1,1) and (200,200) respectively.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current image
+was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different. In the physical coordinate system the
+coordinates of the first pixel of a 2D image, e.g. dev$ypix and a 2D
+image section, e.g. dev$ypix[200:300,200:300] are (1,1) and (200,200)
+respectively.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant
+with respect to linear transformations of the physical image data. For
+example, the ra and dec of an object will always be the same no matter
+how the image is linearly transformed. The units of input world coordinates
+must be the same as those expected by the image header wcs, e. g.
+degrees and degrees for celestial coordinate systems.
+.le
+The wcsin, wcspsf, and wcsout parameters default to the values of the package
+parameters of the same name. The default values of the package parameters
+wcsin, wcspsf, and wcsout are "logical", "physical" and "logical" respectively.
+.le
+.ls cache = ")_.cache"
+Cache the image pixels in memory. Cache may be set to the value of the apphot
+package parameter (the default), "yes", or "no". By default caching is
+disabled.
+.le
+.ls verify = ")_.verify"
+Verify the critical SUBSTAR task parameters? Verify can be set to the DAOPHOT
+package parameter value (the default), "yes", or "no".
+.le
+.ls update = ")_update"
+Update the SUBSTAR task parameters if \fIverify\fR is "yes"? Update can be
+set to the default daophot package parameter value, "yes", or "no".
+.le
+.ls verbose = ")_.verbose"
+Print messages about the progress of the task ? Verbose can be set to the
+DAOPHOT package parameter value (the default), "yes", or "no".
+.le
+
+.ih
+DESCRIPTION
+SUBSTAR task takes an input photometry list \fIphotfile\fR containing
+the fitted coordinates and magnitudes, and an input PSF \fIpsfimage\fR, and
+for each star in the photometry list scales and shifts the PSF and subtracts
+it from the input image \fIimage\fR. The final subtracted image is saved in the
+output image \fIsubimage\fR.
+
+The input photometry list can be the output from of the PEAK, NSTAR or ALLSTAR
+tasks or even the PHOT task although most people would not want to use the PHOT
+output for this purpose.
+
+Selected stars may be omitted from the subtraction by supplying their ids in
+the file \fIexfile\fR. \fIExfile\fR is normally the output the PSTSELECT task
+and is used to tell SUBSTAR to subtract the PSF star neighbors, but not the
+PSF stars themselves.
+
+The coordinates read from \fIphotfile\fR are assumed to be in coordinate
+system defined by \fIwcsin\fR. The options are "logical", "tv", "physical",
+and "world" and the transformation from the input coordinate system to the
+internal "logical" system is defined by the image coordinate system. The
+simplest default is the "logical" pixel system. Users working on with image
+sections but importing pixel coordinate lists generated from the parent image
+must use the "tv" or "physical" input coordinate systems.
+
+The coordinate system of the PSF model is the coordinate system defined by the
+\fIwcspsf\fR parameter. Normally the PSF model was derived from the input image
+and this parameter default to "logical". However if the PSF model was derived
+from a larger image which is a "parent" of the input image, then wcspsf should
+be set to "tv" or "physical" depending on the circumstances.
+
+The coordinates written to the standard output if \fIverbose\fR = yes are in the
+coordinate system defined by \fIwcsout\fR. The options are "logical", "tv",
+and "physical". The simplest default is the "logical" system. Users wishing to
+correlate the output coordinates of objects measured in image sections or
+mosaic pieces with coordinates in the parent image must use the "tv" or
+"physical" coordinate systems.
+
+If \fIcache\fR is yes and the host machine physical memory and working set size
+are large enough the input and output image pixels are cached in memory. If
+caching is enabled and SUBSTAR is run interactively the first subtraction
+will appear to take a long time as the entire image must be read in before
+the measurement is actually made. All subsequent measurements will be very
+fast because SUBSTAR is accessing memory not disk. The point of caching is
+to speed up random image access by making the internal image i/o buffers the
+same size as the image itself. However if the input object lists are sorted
+in row order which SUBSTAR does internally and are sparse caching may
+actually worsen not improve the execution time. Also at present there is no
+point in enabling caching for images that are less than or equal to 524288
+bytes, i.e. the size of the test image dev$ypix, as the default image i/o
+buffer is exactly that size. However if the size of dev$ypix is doubled by
+converting it to a real image with the chpixtype task then the effect of
+caching in interactive is can be quite noticeable if measurements
+of objects in the top and bottom halves of the image are alternated.
+
+
+The SUBSTAR task is most commonly used to check on the quality of the PSF
+fitting produced by PEAK and NSTAR, to search for non-stellar objects and close
+binary stars, to generate an improved PSF in crowded fields, and to remove
+neighbors from bright stars which are to be used to determine aperture
+corrections.
+
+.ih
+EXAMPLES
+
+1. Subtract the NSTAR photometry results for the test image dev$ypix from the
+image dev$ypix.
+
+.nf
+ da> datapars.epadu = 14.0
+ da> datapars.readnoise = 75.0
+
+ ... set the gain and readout noise for the detector
+
+ da> daofind dev$ypix default fwhmpsf=2.5 sigma=5.0 threshold=20.0
+
+ ... answer verify prompts
+
+ ... find stars in the image
+
+ ... answer will appear in ypix.coo.1
+
+ da> phot dev$ypix default default annulus=10. dannulus=5. \
+ apertures = 3.0
+
+ ... answer verify prompts
+
+ ... do aperture photometry on the detected stars
+
+ ... answer will appear in ypix.mag.1
+
+ da> display dev$ypix 1
+
+ da> psf dev$ypix default "" default default default psfrad=11.0 \
+ fitrad=3.0 mkstars=yes display=imdr
+
+ ... verify the critical parameters
+
+ ... move the image cursor to a candidate star and hit the a key,
+ a plot of the stellar data appears
+
+ ... type ? for a listing of the graphics cursor menu
+
+ ... type a to accept the star, d to reject it
+
+ ... move to the next candidate stars and repeat the previous
+ steps
+
+ ... type l to list all the psf stars
+
+ ... type f to fit the psf
+
+ ... move cursor to first psf star and type s to see residuals,
+ repeat for all the psf stars
+
+ ... type w to save the PSF model
+
+ ... type q to quit, and q again to confirm
+
+ ... the output will appear in ypix.psf.1.imh, ypix.pst.1 and
+ ypix.psg.1
+
+ da> group dev$ypix default default default
+
+ ... verify the prompts
+
+ ... the output will appear in ypix.grp.1
+
+ da> nstar dev$ypix default default default default
+
+ ... verify the prompts
+
+ ... the results will appear in ypix.nst.1 and ypix.nrj.1
+
+ da> pdump ypix.nst.1 sharpness,chi yes | graph
+
+ ... plot chi versus sharpness, the stars should cluster around
+ sharpness = 0.0 and chi = 1.0, note that the frame does
+ not have a lot of stars
+
+ da> substar dev$ypix default "" default default
+
+ ... subtract the fitted stars
+
+ da> display ypix.sub.1 2
+
+ ... note that the psf stars subtract reasonably well but other
+ objects which are not stars don't
+.fi
+
+
+2. Rerun the previous example on a section of the test image using the group
+file and PSF model derived in example 1 for the parent image and writing the
+results in the coordinate system of the parent image.
+
+.nf
+ da> nstar dev$ypix[150:450,150:450] default default default default \
+ wcsin=tv wcspsf=tv wcsout=tv
+
+ ... answer the verify prompts
+
+ ... fit the stars
+
+ ... the results will appear in ypix.nst.2 and ypix.nst.2
+
+ da> display dev$ypix[150:450,150:450] 1
+
+ ... display the image
+
+ da> pdump ypix.nst.2 xc,yc yes | tvmark 1 STDIN col=204
+
+ ... mark the stars
+
+ da> substar dev$ypix ypix.nst.2 "" default default
+
+ ... subtract stars from parent image
+
+ ... the output images is ypix.sub.2
+
+
+ da> substar dev$ypix[150:450,150:450] ypix.nst.2 "" default default \
+ wcsin=tv wcspsf=tv wcsout=tv
+
+ ... subtract stars from the nstarinput image
+
+ ... the output images is ypix.sub.3
+
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+datapars,daopars,nstar,peak
+.endhelp
diff --git a/noao/digiphot/daophot/doc/userdocs/daophot.usr.tex b/noao/digiphot/daophot/doc/userdocs/daophot.usr.tex
new file mode 100644
index 00000000..ce4ed623
--- /dev/null
+++ b/noao/digiphot/daophot/doc/userdocs/daophot.usr.tex
@@ -0,0 +1,2005 @@
+%de 21 (summer solstice, midnight, la serena) (this is IT, Phil!)
+%more done on Dec 27th or so
+%typos fixed 28 Dec 1pm
+%more done on Dec 28th (1st 4-m night morning)
+%copy xfered from Chile on Jan 1, 1990
+%modifications made after the AAS meeting, Jan 15 1990:
+% end itemize problems fixed
+% buku aperture photometry stuff added Jan 15/16
+% started to make Lindsey's changes Jan 28th
+% Next set of changes made Feb. 18th when we SHOULD have been
+% off with marcia having a good time.
+% more modifications Monday Feb 19
+% march 20/21 mods made in Boulder----Lindsey's comments
+% march 20/21 mods made in Boulder---beginning of JB's comments
+% march 27 mods back in Tucson
+% may 11th, fixed the sumed/average read-noise problem!
+\documentstyle[11pt,moretext]{article}
+\begin{document}
+\title{A User's Guide to Stellar CCD Photometry with IRAF}
+\author{Philip Massey \and Lindsey E. Davis}
+\date{March 29, 1990}
+\maketitle
+\begin{abstract}
+This document is intended to guide you through the steps for obtaining
+stellar photometry from CCD data using IRAF. It deals both with the
+case that the frames are relatively uncrowded (in which case simple
+aperture photometry may suffice) and with the case that the frames
+are crowded and require more sophisticated point-spread-function
+fitting methods (i.e., {\bf daophot}). In addition we show how one
+goes about obtaining photometric solutions for the standard stars, and
+applying these transformations to instrumental magnitudes.
+\end{abstract}
+\tableofcontents
+\eject
+\section{Introduction}
+This user's guide deals with both the ``relatively simple" case of
+isolated
+stars on a CCD frame (standard stars, say, or uncrowded program stars)
+and the horrendously more complicated case of crowded field
+photometry. We describe here all the steps needed to obtain instrumental
+magnitudes and to do the transformation to the standard system. There
+are, of course, many possible paths to this goal, and IRAF provides no
+lack of options. We have chosen to illuminate a straight road, but many
+side trails are yours for the taking, and we will occasionally point
+these out (``let many flowers bloom"). This Guide is {\it not} intended
+as a reference manual; for that, you have available (a) the various
+``help pages" for the routines described herein, (b) ``A User's Guide
+to the IRAF APPHOT Package" by Lindsey Davis, and (c) ``A Reference
+Guide to the IRAF/DAOPHOT Package" by
+Lindsey Davis. (For the ``philosophy" and algorithms of DAOPHOT, see
+Stetson 1987 {\it PASP} {\bf 99}, 111.)
+What {\it this} manual is intended to be is a real
+``user's guide", in which we go through all of the steps necessary to go
+from CCD frames to publishable photometry. (N.B.: as of this writing
+the IRAF routines for determining the standard transformations and
+applying those transformations are still being written.) We outline
+a temporary kludge that will work with Peter Stetson's CCDRED VMS
+Fortran package. Hopefully the PHOTRED package currently under
+development at Cerro Tololo will be available by Spring 1990, and
+this manual will then be revised.
+
+The general steps involved are as follows: (1) fixing the header
+information to reflect accurate exposure times and airmasses,
+(2) determining and cataloging the characteristics of your data (e.g.,
+noise, seeing, etc.),
+(3) obtaining instrumental magnitudes for all the standard stars
+using aperture photometry, (4) obtaining instrumental magnitudes for
+your program stars using IRAF/daophot, (5) determining the aperture
+correction for your program stars, (6) computing the transformation
+equations for the standard star photometry, and (7) applying these
+transformations to your program photometry. We choose to illustrate
+these reductions using {\it UBV} CCD data obtained with an RCA chip on the 0.9-m
+telescope at Cerro Tololo, but the techniques are applicable to data
+taken with any detector whose noise characteristics mimic those of a
+CCD.
+
+If you are a brand-new IRAF user we strongly recommend first reading the
+document ``A User's Introduction to the IRAF
+Command Language" by Shames and Tody, which can be found in Volume 1A
+of the 4 blue binders that compose the IRAF documentation. (Actually
+if you are a brand-new IRAF user one of us recommends that you find
+some simpler task to work on before you tackle digital stellar photometry!)
+The procedures described here will work on any system supported by IRAF;
+for the purposes of discussion, however, we will assume that you are
+using the image display capabilities of a SUN. If this is true you then
+may also want to familiarize yourself with the ins and outs of using
+the SUN Imtool window; the best description is to be found in ``IRAF
+on the SUN".
+
+We assume that your data has been read onto disk, and that the basic
+instrumental signature has been removed; i.e., that you are ready
+to do some photometry. If you haven't processed your
+data this far yet, we
+refer you to ``A User's Guide to Reducing CCD Data with IRAF" by Phil
+Massey.
+
+\section{Getting Started}
+
+\subsection{Fixing your headers}
+You're going to have to this some time or another; why not now? There
+are two specific things we may need to fix at this point: (a) Add any
+missing header words if you are reducing non-NOAO data, (b) correct the
+exposure time for any shutter opening/closing time, and (c) correct the
+airmass to the effective middle of the exposure.
+
+Two things that will be useful to have in your headers are the exposure
+time and the airmass. If you are reducing NOAO data then you will
+already have the exposure time (although this may need to be corrected
+as described in the next paragraph) and enough information for the {\bf
+setairmass} task described below to compute the effective airmass of the
+observation. You can skip to the ``Correcting the exposure time"
+section below.
+If
+you are reducing non-NOAO data you should examine your header with a
+
+\centerline{ {\bf imhead} imagename{\bf l+ $|$ page} }
+
+\noindent
+and see exactly what information {\it is} there. If you are lacking the
+exposure time you can add this by doing an
+
+\centerline{ {\bf hedit} imagename{\bf ``ITIME"} value {\bf add+ up+
+ver- show+} }
+
+\noindent
+If you know the effective airmasses you can add an ``AIRMASS" keyword in
+the same manner, or if you want to compute the effective airmass
+(corrected to mid-exposure) using {\bf setairmass} as described below,
+you will need to have the celestial coordinates key words ``RA" and
+``DEC", as well as the siderial-time (``ST"),
+and preferably the coordinate ``EPOCH" and the date-of-observation
+(``DATE-OBS"), all of which should have the form shown in Fig.~\ref{header}.
+
+You may want to take this opportunity to review the filter numbers in the
+headers, and fix any that are wrong. If you are lacking filter numbers
+you may want to add them at this point.
+
+\subsubsection{Correcting the exposure time}
+The CTIO 0.9-m has an effective exposure time that is
+25-30ms longer than the requested exposure time (Massey et al. 1989 {\it
+A.J.} {\bf 97}, 107; Walker 1988 {\it NOAO Newsletter} {\bf No. 13},
+20). First see what "keyword" in your header gives the exposure time:
+
+\centerline{
+{\bf imhead} imagename{\bf.imh l+ $|$ page} }
+
+\noindent
+will produce a listing such as
+given in Figure~\ref{header}.
+\begin{figure}
+\vspace{3.2in}
+\caption{\label{header}Header information for image n602alu.imh}.
+\end{figure}
+The exposure time keyword in this header is ``ITIME". In this case
+we wish to add a new exposure time to each of the headers; we will call
+this corrected exposure time
+EXPTIME, and make it 25 ms larger than whatever value is listed as
+ITIME. To do this we use the {\bf hedit} command as follows:
+
+\centerline{
+{\bf hedit *.imh EXPTIME ``(ITIME+0.025)" ver- show+ add+}.}
+
+\noindent
+An inspection of the headers will now show a new keyword EXPTIME.
+(Walker lists a similar correction for the CTIO 1.5-m shutter, but the
+CTIO 4-m P/F shutters have a negligible correction.
+The direct CCD shutters on the Kitt Peak CCD cameras give
+an additional 3.5ms of integration on the edges but 13.0ms in the
+center [e.g., Massey 1985 {\it KPNO Newsletter} {\bf 36}, p. 6];
+if you have any 1 second exposures you had best correct these by
+10ms or so if you are interested in 1\% photometry.)
+
+\subsubsection{Computing the effective airmass}
+The task {\bf setairmass} in the {\bf astutil} package will compute
+the effective airmass of your exposure, using the header values of RA,
+DEC, ST, EPOCH, and DATE-OBS, and whatever you specify for the observatory
+latitude. An example is shown in Fig.~\ref{setairmass}.
+\begin{figure}
+\vspace{2.5in}
+\caption{\label{setairmass} The parameter file for {\bf setairmass}.}
+\end{figure}
+The default for the latitude is usually the IRAF
+variable {\bf observatory.latitude}. To by-pass this ``feature", simply
+put the correct latitude in the parameter file
+(e.g., $-30.1652$ for CTIO,
+$+31.963$ for KPNO; $+19.827$ for Mauna Kea.).
+
+\subsection{{\bf imexamine:} A Useful Tool}
+
+The {\bf proto} package task {\bf imexamine} is a powerful and versatile task
+which can be used to interactively examine image data at all stages of
+the photometric reduction process. In this section we discuss and
+illustrate those aspects of {\bf imexamine} which are most useful to
+photometrists with emphasis on three different applications of the task:
+1) examining the image, for example plotting lines and columns
+2) deriving image characteristics, for example computing the
+FWHM of the point-spread function 3) comparing the same region
+in different images.
+
+The task
+{\bf imexamine} lives within the {\bf proto} package, and you will also need
+to load {\bf images} and {\bf tv}. Then
+{\bf display} the image, and type {\bf imexamine}.
+When the task is ready to accept input the image cursor will begin blinking
+in the display window, and the user can begin executing various keystroke
+and colon commands. The most useful data examining commands are summarized
+below. The column, contour, histogram, line and surface plotting commands
+each have their own parameter sets which set the region to be plotted and
+control the various plotting parameters. All can be examined and edited
+interactively from within the {\bf imexamine} task using the
+appropriate {\bf :epar} command.
+
+\begin{description}
+ \item[c] - Plot the column nearest the image cursor
+ \item[e] - Make a contour plot of a region around the image cursor
+ \item[h] - Plot the histogram of a region around the image cursor
+ \item[l] - Plot the line nearest the image cursor
+ \item[s] - Make a surface plot of a region around the image cursor
+ \item[:c N] - Plot column N
+ \item[:l N] - Plot line N
+ \item[x] - Print the x, y, z values of the pixel nearest the image cursor
+ \item[z] - Print a 10 by 10 grid of pixels around the image cursor
+ \item[o] - Overplot
+ \item[g] - Activate the graphics cursor
+ \item[i] - Activate the image cursor
+ \item[?] - Print help
+ \item[q] - Quit {\bf imexamine}
+ \item[:epar c] - Edit the column plot parameters
+ \item[:epar e] - Edit the contour plot parameters
+ \item[:epar h] - Edit the histogram plot parameters
+ \item[:epar l] - Edit the line plot parameters
+ \item[:epar s] - Edit the surface plot parameters
+
+\end{description}
+
+
+Example 1 below shows how a user can interactively
+make and make hardcopies of image line plots using {\bf imexamine} and at the same time
+illustrates many of the general features of the task.
+
+The {\bf imexamine} task also has some elementary image analysis capability, including
+the capacity to do simple aperture photometry, compute image statistics
+and fit radial profiles. The most useful image analysis commands are
+listed below.
+
+\begin{description}
+\item[h] - Plot the histogram of a region around the cursor
+\item[r] - Plot the radial profile of a region around the cursor
+\item[m] - Plot the statistics of a region around the cursor
+\item[:epar h] - Edit the histogram parameters
+\item[:epar r] - Edit the radial profile fitting parameters
+\end{description}
+
+Example 2 shows how a photometrist might use {\bf imexamine}
+and the above commands to estimate the following image characteristics:
+1) the full width at
+half maximum (FWHM) of the point-spread function, 2) the background sky level
+3) the standard deviation of the background level 4) and the radius at which
+the light from the brightest star of interest disappears into the noise
+(this will be used to specify the size of the point-spread-function,
+e.g.,PSFRAD).
+
+Finally {\bf imexamine} can be used to compare images. Example 3
+shows how to compare regions in the original image and in the
+same image with all the fitted stars subtracted out. The example
+assumes that the target image display device supports multiple frame buffers,
+i.e. the user can load at
+least two images into the display device at once.
+
+The {\bf imexamine} task offers even more features than are discussed here and the
+user should refer to the manual page for more details.
+
+\vspace{12pt}
+{\bf Example 1:} Plot and make hardcopies of image lines within {\bf imexamine}.
+
+\begin{itemize}
+\item {\bf display} the image and then type {\bf imexamine}.
+\item move the image cursor to a star and tap {\bf l} to plot the image
+line nearest the cursor
+\item tap the {\bf g} key to activate the graphics cursor
+\item type {\bf :.snap} to make a hardcopy of the plot on your default device
+\item expand a region of interest by first moving the graphics
+cursor to the lower left corner of the region and typing {\bf E},
+and then moving the graphics cursor to the upper right corner
+of the region and typing anything
+\item type {\bf :.snap} to make a hardcopy of the new plot
+\item tap the {\bf i} key to return to the image cursor menu
+\item type {\bf :epar l} to enter the line plot parameter set, change the
+value of the logy parameter to yes and type {\bf CNTL-Z} to exit and
+save the change
+\item repeat the previous line plotting commands
+\item type {\bf q} to quit {\bf imexamine}
+\end{itemize}
+
+{\bf Example 2:} Compute some elementary image characteristics using
+{\bf imexamine}.
+
+\begin{itemize}
+\item {\bf display} the image and then type {\bf imexamine}.
+\item move to a bright star and tap the {\bf r} key
+\item examine the resulting radial profile plot and note the final
+number on the status line which is the FWHM of the best fitting
+Gaussian
+\item repeat this procedure for several stars to estimate a good
+average value for the FWHM
+\item set the parameters of the statistics box ncstat and nlstat
+from 5 and 5 to 21 and 21 with {\bf :ncstat 21} and {\bf :nlstat 21}
+commands so that the sizes of the statistics and histogram
+regions will be identical
+\item move to a region of blank sky and tap the {\bf m} key to get an
+estimate of the mean, median and standard deviation of the
+sky pixels in a region 21 by 21 pixels in size around the
+image cursor
+\item leave the cursor at the same position and tap the {\bf h} key to
+get a plot of the histogram of the pixels in the same region
+\item tap the {\bf g} key to activate the graphics cursor, move the
+cursor to the peak of the histogram and type {\bf C} to print out
+the cursor's value. The ``x" value then gives you a good estimate of
+the sky. Similarly, you can move the cursor to the
+half-power point of
+the histogram and type {\bf C} to estimate the standard deviation
+of the sky pixels. Tap the {\bf i} key to return to the
+image cursor menu
+\item compare the results of the h and m keys
+\item repeat the measurements for several blank sky regions and note
+the results
+\item move to a bright unsaturated star and turn up the zoom and
+ contrast of the display device as much as possible
+\item using the {\bf x} key mark the point on either side of the center
+where the light from the star disappears into the noise
+and estimate PSFRAD
+\item type {\bf :epar r} to edit the radial profile fitting parameters
+and set rplot to something a few pixels larger than PSFRAD
+and tap the {\bf r} key
+\item note the radius where the light levels off and compare with
+the eyeball estimate
+\item repeat for a few stars to check for consistency
+\item type {\bf q} to quit imexamine
+\end{itemize}
+
+\noindent
+{\bf Example 3:} Overplot lines from two different images.
+
+\begin{itemize}
+\item {\bf imexamine image1,image2}
+\item move the image cursor to a star and type {\bf z} to print the
+pixel values near the cursor
+\item tap the {\bf n} key to display the second image followed by {\bf z}
+to look at the values of the same pixels in the second
+image
+\item tap the {\bf p} key to return to the first image
+\item tap {\bf l} to plot a line near the center of the star and tap
+the {\bf o} key to overlay the next plot
+\item tap the {\bf p} key to return to the second image and without
+moving the image cursor tap the l key again to overplot
+the line
+\item type {\bf q} to quit imexamine
+\end{itemize}
+
+\subsection{Dealing with Parameter Files (Wheels within Wheels)}
+
+The {\bf daophot} (and {\bf apphot}) packages are unique in IRAF in that
+they obtain
+pertinent information out of separate ``parameter files" that can be
+shared between tasks. As anyone that
+has used IRAF knows, each IRAF command has its own parameter file that
+can
+be viewed by doing an {\bf lpar} {\it command} or edited by doing an
+{\bf epar} {\it command}.
+However, in {\bf daophot} and {\bf apphot} there are ``wheels within
+wheels"---some of the parameters are in fact parameter files themselves.
+For instance, the aperture photometry routine {\bf phot} does not
+explicitly
+show you the methods and details of
+the sky fitting in its parameter file.
+However, if you do an {\bf lpar phot}
+you will see a parameter
+called ``fitskypars" which
+contains, among many other things, the radii of the annulus to be used
+in determining the sky value.
+You will also find listed ``datapars" (which specifies the properties
+of your data, such as photons per ADU and read-noise), ``centerpars"
+(which
+specifies the centering algorithm to be used), and ``photpars" (which gives
+the
+size of the digital apertures and the zero-point magnitude).
+The contents of any of these parameter files can be altered either by
+{\bf epar}ing them on their own or by typing a ``:e" while on that
+line of the main parameter file. If you do the latter, a control-z
+or a ``:q" will bring you back.
+For example, to examine or edit {\bf fitskypars}, you can
+do an explicit {\bf lpar fitskypars}
+or {\bf epar fitskypars}, or you can do an {\bf epar phot}, move the
+cursor down to the ``fitskypars" line, and then type a {\bf :e} to edit
+(see Fig.~\ref{wheels}).
+\begin{figure}
+\vspace{4.2in}
+\caption{\label{wheels}Changing the Sky Annulus in {\bf fitskypars}.}
+\end{figure}
+Confusing? You bet!
+But once you are used to it, it is a convenient and powerful way to
+specify a whole bunch of things that are used by several different
+commands---i.e., you are guaranteed of using the same parameters in
+several different tasks. If there is only one thing that you want to
+change in
+a parameter file you {\it can} enter it on the command line when
+you run the command, just as if it were a ``normal" (hidden) parameter,
+i.e., {\bf phot imagename dannulus=8.} does the same as
+running {\bf epar fitskypars} and changing the ``width of sky annulus"
+{\bf dannulus} to 8.0.
+
+Mostly these things are kept out of the way (``very hidden" parameters)
+because you {\it don't} want to be changing them, once you have set them
+up for your data. There are exceptions, such as changing the PSF radius
+in making a point-spread function in a crowded field (Sec. 4.6).
+However,
+you are well protected here if you leave the {\bf verify} switch on.
+A task will then give you an opportunity to take one last look at
+anything
+that you really care about when you run the task. For instance, if we
+had simply run {\bf phot} on an image (we'll see how to do this shortly)
+it would have said ``Width of sky annulus (10.)", at which point we
+could
+either have hit [CR] to have accepted the 10., or we could have
+entered a new value.
+
+
+\section{Aperture Photometry on your Standards}
+
+Standard stars provide a good example of relatively uncrowded
+photometry,
+and in this section we will describe how to obtain instrumental
+magnitudes for your standards using {\bf phot}.
+The basic steps are
+\begin{itemize}
+ \item Decide what aperture size you wish to use for measuring your
+ standards {\bf (this should be the same for all the frames).} At the
+ same time we will pick a sky annulus.
+ \item Set up the various parameter files ({\bf datapars,
+ centerpars, fitskypars, photpars}) to have the correct values.
+ \item For each frame:
+ \begin{enumerate}
+ \item Identify the standard star(s) either
+ interactively using a cursor
+ or by using the automatic star finding algorithm
+ {\bf daofind}.
+ \item Run the aperture photometry program {\bf phot}
+ on each of your standard star frames.
+\end{enumerate}
+\end{itemize}
+Although the routines you will need to use are available both in the
+{\bf daophot} and {\bf apphot} packages, we strongly advise you to run
+them from the {\bf daophot} package: the default setup is somewhat different,
+and the two packages each have their own data parameter files.
+
+\subsection{Picking an Aperture Size}
+Unfortunately, there are not good tools available with IRAF to do this
+yet, and we will restrict our discussion here to some of the
+considerations before telling you to just go ahead and use a radius that
+is something like 4 or 5 times the FWHM of a stellar image; e.g.,
+12 or 15
+pixels as a radius, assuming you have the usual sort of ``nearly
+undersampled" FWHM$\approx3$ data.
+You might naively expect (as I did) that you wish to pick an aperture
+size
+that will ``contain all the light" from your standard stars, but in fact
+this is impossible: the wings of a star's profile extend much further
+than you imagine at a ``significant" level. King (1971 {\it Publ.
+A.S.P.} {\bf 83}, 199) and Kormendy (1973 {\it A.J.} {\bf 78}, 255)
+discuss the fact that on photographic plates the profile of a star
+extends out to {\it arcminutes} at an intensity level far exceeding the
+diffraction profile; Kormendy attributes this to scattering off of dust
+and surface irregularities on the optical surfaces.
+Massey {\it et al}.\ (1989 {\bf 97}, 107) discusses
+this in regards to CCD's and standard star solutions using the very data
+we are using here as an example (which is not exactly a coincidence).
+Although the intensity profile falls off rapidly, the increase in area
+with radius increases rapidly, and in practical terms Massey {\it et
+al.}
+found that in cases where the FWHM was typically small (2.5-3 pixels),
+increasing the digital aperture size from a diameter of 18 pixels to
+one of 20 pixels resulted in an additional 1-2\% increase in light
+for a well-exposed star, and that this increase continues
+for larger apertures until masked by the photometric errors.
+
+Given that you presumably want 1\% photometry or better, what should you
+do?
+Well, the fact that photoelectric photometery through fixed apertures
+in fact does
+work suggests that there is some radius beyond which the same fraction
+of
+light is excluded, despite variations in the seeing and guiding. You do
+not want to choose a gigantic aperture ($>$ 20 pixels, say) because the
+probability of your having a bad pixel or two goes up with the area.
+But you do not want to choose too small an aperture ($<$10 pixels, say)
+or you will find yourself at the mercy of the seeing and guiding. Most
+photoelectric photometrists will use an aperture of at least 10
+arcseconds in diameter, but remember you have one advantage over them:
+you are not sensitive to centering errors, since any digital aperture can
+be exactly centered.
+If you
+have enough standard star observations (I used about 300 obtained over a
+10 night run) you can
+compute magnitude differences between a large aperture (20 pixels),
+and a series of smaller apertures (8, 10, 12, 15, 18) for each filter,
+and then see for which radius the difference (in magnitudes) becomes
+constant. Unfortunately, there are no tools currently available within
+IRAF for taking the differences between two apertures, or for conveniently
+plotting these differences, so you are on your own. My recommendation
+would be that if you have typical data with a
+FWHM of $\leq 4$ pixels, that you use something like an aperture of 12 to 15
+pixels in radius for your standard stars. {\bf You can save yourself a lot
+of trouble if you simply adopt a single radius for all the standards
+from all the nights for all filters.}
+
+\subsection{Setting Things Up}
+
+As discussed in ``Dealing with Parameter Files" (Section 2.1) we must
+setup the parameter files from which {\bf phot} will get the details of
+what it is going to do. The easiest way to do this is to simply
+{\bf epar phot}, and on each of the four parameter lists to do a
+{\bf :e}. Mostly we will leave the defaults alone, but in fact you will
+have to change at least one thing in each of the four files.
+
+\begin{figure}
+\vspace{3.5in}
+\caption{\label{photdatapars} Parameters for {\bf datapars}.}
+\end{figure}
+In {\bf datapars} (Fig.~\ref{photdatapars}) we need to specify both
+the FWHM
+of a star image ({\it fwhmpsf}) and the
+threshold value above sky ({\it threshold}) if we are going to use the
+automatic star-finding routine {\bf daofind}; the choices for these
+are discussed further below. In order to have
+realistic
+error estimates for our aperture photometry we need to specify
+the CCD readnoise {\it readnoise} in electrons and the
+gain (photons per ADU) for the CCD {\it epadu}.
+In order to
+correct the results for the exposure time we need the exposure time
+keyword {\it
+exposure}. Do an
+
+\centerline{{\bf imhead} {\it imagename} {\bf l+ $|$ page}}
+
+\noindent
+to see a
+listing of all the header information (Fig.~\ref{phothead}).
+\begin{figure}
+\vspace{4.0in}
+\caption{\label{phothead} Header information for std159.imh}
+\end{figure}
+By specifying the (effective) airmass and filter keywords,
+these can be carried along in the photometry file for use when we do
+the standards solution ({\it airmass} and {\it filter}). Finally we use
+{\it datamin} and {\it datamax} so we will know if we exceeded the
+linearity of the CCD in the exposure, or whether there is some anomalously
+low valued pixel on which our star is sitting.
+Since the value of the sky on our standard exposures is
+probably nearly zero, {\it datamin} should be set to a negative value
+about three times the size of the readnoise in {\it ADU's}; e.g., $-3 \times
+65. \div 2.25 \approx -90$ in this example. Note that although we will
+later argue that the shape of the PSF changes a little about 20000
+ADU's (presumably due to some sort of charge-transfer problem),
+for the purposes of simple aperture photometry we are happy
+using 32000 ADU's as the maximum good data value. (We do not really
+want to use 32767 as afterall the overscan bias was probably at a
+level of several hundred.)
+
+\begin{figure}
+\vspace{3.0in}
+\caption{\label{photcenterpars} Parameters for {\bf centerpars}.}
+\end{figure}
+In {\bf centerpars} (Fig.~\ref{photcenterpars}) we need to
+change the centering algorithm {\it calgorithm}
+from the default value of ``none" to
+``centroid". If the FWHM of your frames are unusually large ($>4$, say,
+you would also do well to up the size of {\bf cbox} to assure that the
+centering works well; make it something like twice the FWHM. In this
+case the FWHM is 3 pixels or a bit smaller, and we are content to leave
+it a the default setting of 5 pixels.
+
+\begin{figure}
+\vspace{2.7in}
+\caption{\label{photfitskypars} Parameters for {\bf fitskypars}.}
+\end{figure}
+In {\bf fitskypars} (Fig.~\ref{photfitskypars})
+the only things we must specify are the size and
+location of the annulus in which the modal value of the sky will be
+determined. If you are going to use a value of 15 for your photometry
+aperture, you probably want to start the sky around pixel 20. Keeping
+the width of the
+annulus large (5 pixels is plenty) assures you of good sampling, but
+making it too large increases the chances of getting some bad pixels in
+the sky.
+
+\begin{figure}
+\vspace{2.7in}
+\caption{\label{photphotpars} Parameters for {\bf photpars}.}
+\end{figure}
+In {\bf photpars} (Fig.~\ref{photphotpars})
+we merely need to specify the size (radius) of the
+aperture we wish to use in measuring our standards.
+
+\subsection{Doing It}
+There are basically two ways of proceeding in running photometry on the
+standard stars, depending upon how you are going to identify the
+relevant star(s) on each frame. If you have only one (or two)
+standard stars on each frame, and it is always one of the brightest
+stars present, then you can avoid a lot of the work and use the
+automatic star-finding program {\bf daofind} to find all your standards
+and the whole thing can be done fairly non-interactively. However,
+if you are one of the believers in cluster field standards, then you
+may actually want to identify the standards in each field using the
+cursor on the image display so that the numbering scheme makes sense.
+We describe below each of the two methods.
+
+\subsubsection{Automatic star finding}
+First let's put the name of each frame containing standard stars into
+a file; if you've put the standard star exposures into a separate
+directory this can be done simply by a {\bf files *.imh $>$ stands}.
+This will leave us with funny default output file
+names for a while (we advise against
+including the ``.imh" extension when we discuss crowded field photometry
+in the next section), but this will only be true for a short
+intermediate
+stage.
+
+We want to run {\bf daofind} in such a way that it finds only the
+brightest
+star or two (presumably your standard was one of the brightest stars
+in the field;
+if not, you are going to have to do this stuff as outlined below in
+the ``Photometry by eye" section). We will delve more fully into the
+nitty-gritty of {\bf daofind} in the crowded-field photometry section,
+but here we are content if we can simply find the brightest few stars.
+Thus the choice of the detection
+threshold is a critical one. If you make it too low you will find all
+sorts of junk; if you make it too high then you may not find any stars.
+You may need to run {\bf imexamine} on a few of your images: first
+{\bf display} the image, and then {\bf imexamine}, using the ``r" cursor
+key to produce a radial profile plot. Things to note are the
+typical full-width-half-maximum and the peak value. If your sky is
+really around zero for your standard exposures, then using a value
+that is, say, twenty times the readnoise (in ADU's) is nearly guaranteed to
+find only the brightest few stars; do your radial plots in {\bf
+imexamine} show this to be a reasonable value? In the example here we
+have decided to use 500 ADUs as the threshold ($20 \times 65 \div 2.25
+\approx 500$).
+
+Now {\bf epar daofind} so it resembles that of Fig.~\ref{photdaofind}.
+\begin{figure}
+\vspace{3.5in}
+\caption{\label{photdaofind} Parameter file for {\bf daofind}.}
+\end{figure}
+Go ahead and execute it (Fig. ~\ref{daoout}).
+\begin{figure}
+\vspace{3.5in}
+\caption{\label{daoout} Screen output from a {\bf daofind} run.}
+\end{figure}
+Note that since {\it verify} is on that you
+will be given a chance to revise the FWHM and detection threshold. By
+turning verbose on you will see how many stars are detected on each
+frame.
+%Probably the best way of doing this is to write the output from
+%{\bf daofind} into a file; do a
+%
+%\centerline{ {\bf daofind @stands $|$ tee starsfound} }
+%
+%\noindent
+%to put the output into the file ``starsfound" as well as on the screen.
+Make a note of any cases where no stars were found; these you will have
+to
+go back and do with a lower threshold.
+
+The run of {\bf daofind} produced one output file named {\it
+imagename.imh.coo.1} for each input file. If you {\bf page} one of
+these you will find that it resembles that of Fig.~\ref{photcooout}.
+\begin{figure}
+\vspace{3.7in}
+\caption{\label{photcooout} Output file from {\bf daofind}.}
+\end{figure}
+The file contains many lines of header, followed by the {\it x} and {\it
+y} center values, the magnitudes above the threshold value, the ``sharpness"
+and ``roundness" values, and finally an ID number.
+In the example shown
+here in Fig.~\ref{photcooout} two stars were found: one 2.9 mags
+brighter than our detection threshold, and one about 0.4 mag brighter
+than our detection threshold.
+
+In a few cases we doubtlessly found more than one star; this is a good
+time to get rid of the uninteresting non-standards in each field.
+If things went by too fast on the screen for you to take careful notes
+while running {\bf daofind} we can find these cases now: do a
+
+\centerline{ {\bf txdump *coo* image,id,x,y yes }}
+
+
+\noindent
+to get a listing of the location and number of stars found on each image.
+If you have cases where there were lots of
+detections (a dozen, say) you may find it easier to first {\bf sort
+*.coo* mag} in order to resort the stars in each file by how bright they
+are. Of course, your standard may not be the brightest star in each
+field; you may want to keep an eye on the {\it x} and {\it y} values to
+see if it is the star you thought you were putting in the middle!
+To get rid of the spurious stars you will need to {\bf edit} each of the
+output files (e.g., {\bf edit std148.imh.coo.1} ) and simply delete the
+extras.
+
+Finally we can run aperture photometry on these frames, using the
+``.coo" files to locate the standard star in each frame. {\bf epar
+phot} until it resembles that of Fig.~\ref{photphot}.
+\begin{figure}
+\vspace{3.5in}
+\caption{\label{photphot} The parameter file for a run of {\bf phot}.}
+\end{figure}
+Note that we are specifying a {\it single} output file name
+(``standstuff" in this example); {\it all} the photometry output will be
+dumped into this single file, including things like the airmass and filter
+number. Go ahead and execute {\bf phot}.
+You should see something much like that of Fig.~\ref{photrun} on the
+screen.
+\begin{figure}
+\vspace{5.5in}
+\caption{\label{photrun} Running {\bf phot} non-interactively
+on the standard stars.}
+\end{figure}
+We will discuss the output below under ``Examining the results".
+
+\subsubsection{Photometry by Eye}
+In this section we will discuss the case of selecting stars {\it
+without}
+running the automatic star-finding program, using the image display
+window and the cursor. The first step is to {\bf epar phot} so it
+resembles that of Fig.~\ref{photeye}.
+\begin{figure}
+\vspace{3.5in}
+\caption{\label{photeye} Parameter file for {\bf phot} when stars will
+be selected interactively.}
+\end{figure}
+Note that we have replaced the {\bf coords} coordinate list with the
+null string (two adjacent double-quotes) and turned ``interactive" on.
+
+We need to display the frame we are going to work on in the imtool
+window:
+
+\centerline { {\bf display std145 1} }
+
+\noindent
+will display image {\bf std145.imh} in the first frame buffer.
+
+Now let's run {\bf phot}. We are not likely to be {\it too} accurate
+with where we place the cursor, so to be generous we will increase the
+allowable center shift to 3 pixels; otherwise we will get error messages
+saying that the ``shift was too large":
+
+\centerline{ {\bf phot std145 maxshift=3.} }
+
+\noindent
+(Note that even though {\bf maxshift} is a parameter of {\bf centerpars}
+we can change it on the command line for {\bf phot}.) Also note that we
+left off the ``{\bf .imh}" extension for a reason: we are going to take
+the default names for the output files, and they will be given names
+such as {\bf std145.mag.1} and so on. If we had included the {\bf .imh}
+extension would would now be getting {\bf std145.imh.mag.1} names.
+
+At this point I get a flashing circle in my {\bf imtool} window; I don't
+know what you get (it depends upon how your defaults are set up) but
+there should be some sort of obvious marker on top of your image.
+Put it on the first star you wish to measure and hit the space bar. The
+coordinates and magnitude should appear in the {\bf gterm} window, and
+you are ready to measure the next star on this frame. Proceed until all
+the stars on this frame are measured, and then type a ``q" followed by
+another ``q". Display the next frame, and run {\bf phot} on it.
+
+When you get done you will have kerjillions of files.
+
+\subsection{Examining the Results: the power of {\bf txdump }}
+
+Depending upon which of the two methods you selected you will either
+have a single file {\bf standstuff} containing the results of all your
+aperture photometry, or you will have a file for each frame ({\bf
+stand145.mag.1}, {\bf stand146.mag.1} \ldots)containing the stars
+on each frame. In either event the file will pretty much resemble that
+shown in Fig.~\ref{photphotout}.
+\begin{figure}
+\vspace{7.5in}
+\caption{\label{photphotout} Output file from {\bf phot}.}
+\end{figure}
+The file begins with a large header describing the parameters in
+force at the time that {\bf phot} was run. There is, however, a real
+subtlety to this statement. If you had changed a parameter in {\bf
+datapars}, say, (or any of the other parameters) between running {\bf
+daofind} and {\bf phot}, the header in {\bf phot} will reflect only the
+setting that was in force at the time that {\bf phot} was run---in other
+words, it does not take the values of what was used for the {\bf
+threshold} from the coordinate file and retain these, but instead simply
+copies what value of {\bf thresh} happens to be in {\bf datapars} at the
+time that {\bf phot} is run. To those used to the
+``self-documenting" feature of VMS DAOPHOT this is a major change!
+
+Once we get past the header information we find that there are 5 lines
+per star measured. The ``key" to these five lines of information are
+found directly above the measurement of the first star. On the first
+line we have ``general information" such as the
+image name, the beginning x and y values, the id,
+and the coordinate file. On the next line we have all the centering
+information: the computed x and y centers,
+the x and y shift, and any centering errors. On the third line of the
+file we have information about the sky. On the fourth line we have some
+information out of the image header: what was the integration time, what
+was the airmass, and what was the filter. Note
+that {\bf phot} has used that integration time in producing the
+magnitude---the exposures are now normalized to a 1.0 sec exposure.
+The fifth line gives the actual photometry, including the size of the
+measuring aperture, the total number of counts within the aperture, the
+area of the aperture, and the output magnitude, photometric error, and
+any problems encountered (such as a bad pixel within the aperture).
+
+We can extract particular fields from this file (or files) by using the
+{\bf txdump} command. For instance, are there any cases where there
+there were problems in the photometry? We can see those by saying
+
+\centerline{\bf txdump standstuff image,id,perror}
+
+\noindent
+(If you did ``Photometry by eye" you can substitute {\bf *mag*} for {\bf
+standstuff}.)
+When it queries you for the ``boolean expression" type
+
+\centerline{ {\bf perror!$=$"No\_error"} }
+
+\noindent
+The ``!$=$" construction is IRAF-ese for "not equal to"; therefore, this
+will select out anything for which there was some problem in the
+photometry.
+
+We can create a single file at this point containing just the
+interesting results from the photometry file(s): do a
+
+\centerline{ {\bf txdump standstuff
+image,id,ifilt,xair,mag,merr yes $>$ standsout} }
+
+\noindent
+to dump the image name, id-number, filter, airmass, magnitude,
+and magnitude error into a file {\bf standsout}. (Again, if you did
+``Photometry by Eye" substitute {\bf *mag*} for {\bf standstuff}).
+Unfortunately, what you do with this file is up to you right now until
+the standard reductions routines become available. In the example shown
+here we have selected the fields in the same order as used in Peter
+Stetson's VMS CCDCAL software, and at the end of this manual we will
+describe a (painful) kludge that nevertheless {\it will} let you use
+these numbers with that software.
+
+\section{Crowded Field Photometry: IRAF/daophot}
+\subsection{Historical Summary}
+
+In the beginning (roughly 1979) astronomers
+interested in obtaining photometry from stars in ``relatively" crowded fields
+would make the journey to Tucson in order to use Doug Tody's RICHFLD
+program which ran on the IPPS display system.
+RICHFLD allowed the user to define a
+point-spread-function (PSF), and then fit this PSF to the brightest star
+in a group, subtract off this star, and then proceed to the next
+brightest star, etc. This represented a giant qualitative improvement
+over the possibilities of aperture photometry, and allowed stars
+separated by a few FWHM's to be accurately measured.
+
+Beginning in 1983, a group of RICHFLD users at the DAO (including
+Ed Olszewski and Linda Stryker) began modifications to the ``poorman"
+program of Jeremy Mould. This was largely motivated by the
+implementation of the ``Kitt Peak CCD" at the prime-focus of the Tololo
+4-m, and the idea was to design a crowded-field
+photometry
+program that (a) allowed simultaneous PSF-fitting, (b) made
+use of the {\it known noise characteristics of a CCD} to do the fitting
+in a
+statistically correct manner (i.e., to make ``optimal" use of the data),
+and (c) to be largely batch oriented.
+In mid-1983 Peter Stetson arrived at the DAO, and took over
+the effort. The result was
+DAOPHOT, which did all these things and more.
+By 1986 DAOPHOT was well distributed within the astronomical community.
+The basic algorithms and philosophy can be found in Stetson 1987 (PASP
+{\bf 99}, 111).
+
+DAOPHOT (and its companion program ALLSTAR) were not part of a
+photometry
+package; they were instead stand-alone Fortran
+programs which did not deal in any way with the issue of image display
+or what to do with the instrumental magnitudes once you had them. They
+were also only supported on VMS, although several ``frozen" versions
+were translated into UNIX by interested parties around the country.
+There was therefore
+much to be gained from integrating the algorithms of daophot
+with IRAF in order to make use of
+the image display capabilities and general tools for manipulating
+images. Also, since many astronomers were now reducing their CCD data
+with IRAF, it avoided the necessity of translating the IRAF files into
+the special format needed by VMS DAOPHOT. Dennis Crabtree began this
+translation program while at the DAO; it was taken over by Lindsey Davis
+of the IRAF group in early 1989, and taken to completion in early 1990.
+Pedro Gigoux of CTIO is currently hard at work on the photometry
+reduction package, scheduled for completion sometime during the spring.
+
+\subsection{{\bf daophot}
+Overview}
+The steps involved in running daophot are certainly more involved than
+in simple aperture photometry, but they are relatively straightforward.
+The following sections will lead you through the necessary procedures.
+Alternative routes will be noted at some points, and more may be gleaned
+from reading the various "help" pages. A general outline is given here
+so that you have some overview in mind; a detailed step-by-step summary
+is provided at the end of this section.
+
+\begin{itemize}
+\item Before you reduce the first frame, {\bf imexamine} your data to
+determine FWHM's and the radius at which the brightest star you wish to
+reduce blends into the sky. Run {\bf imhead} to find the ``key-words"
+in your data headers for exposure times, filter number, and airmass.
+Enter these, along with the characteristics of your chip (read-noise,
+photons per ADU, maximum good data value)
+into the parameter sets {\bf datapars} and {\bf
+daopars}.
+\item Use {\bf daofind} and {\bf tvmark}
+to produce a list of x and y positions of most
+stars on the frame.
+\item Use {\bf phot} to perform aperture photometry on the identified
+stars. This photometry will be the basis of the zero-point of
+your frame via the PSF stars. This is also the only point where sky
+values are determined for your stars.
+\item Use {\bf psf} to define the PSF for your frame. If your PSF stars are crowded this
+will require some iteration using the routines {\bf nstar} and {\bf
+substar}.
+\item Use {\bf allstar} to do simultaneous PSF-fitting for all the stars
+found on your frame, and to produce a subtracted frame.
+\item Use {\bf
+daofind} on the subtracted frame to identify stars that had been
+previously hidden.
+\item Run {\bf phot} {\it on the original frame} to obtain aperture photometry
+and sky values for the stars on the new list.
+\item Use {\bf append} to merge the two aperture photometry lists.
+\item Run {\bf allstar} again on the merged list.
+\end{itemize}
+When you have done this for your {\it U, B,} and {\it V} frames it is
+then time to
+\begin{itemize}
+\item Use {\bf txdump}, {\bf tvmark}, and the image display
+capabilities to come up with a consistent matching between the frames.
+If there are additions or deletions then you will need to re-run
+{\bf phot} and {\bf allstar} one more time.
+\end{itemize}
+Finally you will need to
+\begin{itemize}
+\item Determine the aperture correction for each frame by subtracting
+all but the brightest few isolated stars on your frames and then running
+{\bf phot} to determine the light lost between your zero-point aperture
+and the large aperture you used on your standard stars.
+\end{itemize}
+
+\subsection{How Big Is A Star: A Few Useful Definitions}
+
+The parameter files {\bf datapars} and {\bf daopars} contain three
+``size-like" variables, and although this document is not intended as
+a reference guide, there is bound to be confusion over these three
+parameters, particularly among those new to DAOPHOT. In the hopes
+of un-muddying the waters, we present the following.
+
+\begin{description}
+\item[fwhmpsf] This is the full-width at half-maximum of a stellar object
+(point-spread function, or psf). The value for {\bf fwhmpsf} gets used
+only by the automatic star-finding algorithm {\bf daophot}, unless you
+do something very bad like setting {\bf scale} to non-unity.
+
+\item[psfrad] This is the ``radius" of the PSF. When you construct a PSF,
+the PSF will consist of an array that is
+$$(2 \times psfrad +1) \times
+(2 \times psfrad + 1)$$
+on a side. The idea here is that ``nearly all" of the light of the brightest
+star you care about will be contained within this box. If you were to construct
+a PSF with some large value of {\bf psfrad} and then run {\bf nstar} or
+{\bf allstar}
+specifying
+a smaller value of {\bf psfrad}, the smaller value would be used. Making
+the {\bf psfrad} big enough is necessary to insure that the wings of some
+nearby bright star are properly accounted for when fitting a faint star.
+
+\item[fitrad] This is how much of the psf is used in making the fit
+to a star. The ``best" photometry will be obtained (under most circumstances)
+if this radius is set to something like the value for the fwhm.
+
+\end{description}
+
+\subsection{Setting up the parameter files ``daopars" and ``datapars" }
+
+The first step in using IRAF/daophot is to determine and store the
+characteristics of your data in two parameter files called ``datapars"
+and ``daopars"; these will be used by the various daophot commands.
+In Section 1 we discussed how to deal with parameter files, and
+in Section 2 we went through setting up ``datapars" for the standard
+star solutions; at the risk of repeating ourselves, we will go through
+this again as the emphasis is now a little different.
+
+
+First inspect your headers by doing an {\bf imhead} imagename {\bf long+
+$|$ page}.
+This will produce a listing similar to that shown in Fig.~\ref{newhead}.
+\begin{figure}
+\vspace{3.0in}
+\caption{\label{newhead}Header for image n602alu.imh.}
+\end{figure}
+The things to note here are (a) what the filter keyword is (we can
+see from Fig.~\ref{newhead} that the answer is F1POS; while there is
+an F2POS also listed, the second filter bolt was not used and was always
+in position ``zero"),
+(b) what the effective exposure
+time keyword is (EXPTIME in this example), and (c) what the effective
+airmass keyword is (AIRMASS in this example).
+
+Next you need to examine some ``typical" frames in order to determine
+the FWHM ({\bf fwhmpsf}) and the radius of the brightest star for which
+you plan to do photometry ({\bf psfrad}).
+First {\bf display} an image, and use the
+middle button of the mouse (or whatever you need to do on your image
+display) to zoom on a few bright stars. On the SUN the "F6" key will
+let you see x and y values. The ``default" PSF radius is 11 pixels:
+are your stars bigger than 23 pixels($23=2 \times 11 + 1$)
+pixels from one side to the other? The FWHM is undoubtably variable
+from frame to frame, but unless these change by drastic amounts (factors
+of two, say) using a ``typical" value will doubtless suffice. You can
+use the {\bf imexamine} routine to get some idea of the FWHM; do
+{\bf imexamine} filename and then strike the ``r" key (for radial
+profile) after centering the cursor on a bright (but unsaturated) star.
+The last number on the plot is the FWHM of the best-fit Gaussian.
+
+We are now ready to do an {\bf epar datapars}. This parameter file
+contains information which is data-specific. We set {\bf fwhmpsf} to the FWHM
+determined above, and we enter the names of the keywords determined from
+the header inspection above. The ``gain" and ``read-noise" are values
+you have either determined at the telescope (using the Tololo routines)
+or which are carved in stone for your chip. Choosing the value
+for datamax, the ``Maximum good data value",
+(in ADU's, NOT electrons) is a little bit trickier. In the case of
+aperture photometry we were satisfied to take the nominal value for
+the chip, but point-spread-function fitting is a bit more demanding
+in what's ``linear". The data obtained
+here was taken with an RCA chip, and we all know that RCA chips are
+linear well past 100,000 e-. Thus, naively, we would expect that
+with a gain of 2.25 that the chip was still linear when we hit the
+digitization limit of 32,767 ADU's. Subtract off 500 for the likely
+bias, and we {\it might} think that we were safe up to 32,200. However,
+we would be wrong. Experience with PSF fitting on these data shows that
+something (presumably in those little silver VEB's) has resulted in
+these data being non-linear above 20,000 ADU's. My suggestion here is
+to start with the nominal value but be prepared to lower it if the
+residuals from PSF fitting appear to be magnitude dependent (more on this
+later). The value for
+{\bf datamin}, the
+``Minimum good
+data value", will be different for each frame (depending what the sky
+level is) and there is not much point in entering a value for that yet.
+Similarly the value we will use for threshold will change
+from frame to frame depending upon what the sky level is.
+When you are done your {\bf datapars} should resemble that of
+Fig.~\ref{datapars}.
+\begin{figure}
+\vspace{2.7in}
+\caption{\label{datapars} A sample {\bf datapars} is shown.}
+\end{figure}
+
+Next we will {\bf epar daopars}. This parameter file contains
+information specific to what you want {\bf daophot} to do. The only things here
+we might want to change at this point are the ``Radius of the psf" {\bf psfrad}
+(if your experiment above showed it should be increased somewhat), and
+you might want to change the fitting radius {\bf fitrad}. Leaving the fitting
+radius to ``something like" the FWHM results in the best SNR (you can
+work this out for yourself for a few different regimes if you like to
+do integrals). The ``standard values" are shown in Fig.~\ref{daopars}.
+\begin{figure}
+\vspace{2.7in}
+\caption{\label{daopars} A sample {\bf daopars} is shown.}
+\end{figure}.
+
+\subsection{Finding stars: {\bf daofind} and {\bf tvmark} }
+The automatic star finder {\bf daofind} convolves a Gaussian of
+width FWHM with the image, and looks for peaks greater than some
+threshold in the smoothed image. It then keeps only the ones that are
+within certain roundness and sharpness criteria in order to reject
+non-stellar objects (cosmic rays, background galaxies, bad columns,
+fingerprints). We have already entered a reasonable value for the FWHM
+into {\bf datapars}, but what should we use as a threshold? We expect
+some random fluctuations due to the photon statistics of the sky
+and to the read-noise of the chip. You can calculate this easily by
+first
+measuring the sky value on your frame by
+using {\bf imexamine} and the ``h" key to produce a histogram of
+the data ({\bf implot} and the ``s" key is another way). In the example
+shown in Fig~\ref{hist} we see that the sky value is roughly 150.
+\begin{figure}
+\vspace{3.6in}
+\caption{\label{hist} The {\bf imexamine} histogram (``h" key) indicates
+that the sky value is roughly 150.}
+\end{figure}
+In general, if $s$ is the sky value in ADU, $p$ is the number of
+photons per ADU, and $r$ is the read-noise in units of electrons,
+then the expected $1\sigma$ variance in the sky
+will be
+$$\left(\sqrt{s\times p + r^2}\right)/p$$
+in units of ADU's. For the example here we expect
+$1\sigma=\left(\sqrt{150.\times 2.25 + 65^2}\right)/2.25=30$ ADU's.
+Of course, if you have averaged N frames in producing your image,
+then you should be using
+$N\times p$ as the gain both here and in the value entered in
+{\bf datapars}; similarly the readnoise is really just $r \times \sqrt{N}$.
+If instead you summed N frames then the gain is just {\it p} and the
+readnoise is still $r\times \sqrt{N}$.
+
+In the example shown here the expected $1\sigma$ variation of the sky is
+30 ADU's; we might therefore want to set our star detection threshold to
+3.5 times that amount. That won't guarantee that every last star we
+find is real, nor will it find every last real star, but it should do
+pretty close to that!
+
+We should use this opportunity to set datamin in {\bf
+datapars} to some value like $s-3\sigma$. In this case we will set it
+to 60. This is not currently used by {\bf daofind} but will be used
+by all the photometry routines. Fig.~\ref{ndatapars} shows the data
+parameters with the appropriate values of threshold and datamin now
+entered.
+\begin{figure}
+\vspace{3.0in}
+\caption{\label{ndatapars} Datapars with {\bf threshold} and {\bf datamin}
+entered.}
+\end{figure}
+
+We now can {\bf epar daofind} so it resembles that of
+Fig.~\ref{daofind}.
+\begin{figure}
+\vspace{3.0in}
+\caption{\label{daofind} Parameters for {\bf daofind}.}
+\end{figure}
+Note that although nothing appears to be listed under {\bf datapars} the
+default name is ``datapars"; you could instead have created a separate
+data parameter file for each ``type" of data you have and have called
+them separate names (you could do this by doing an {\bf epar datapars}
+and then exiting with a ``:w newnamepar"). This might be handy if
+all your {\it U} frames were averages, say, but your {\it B} and {\it V}
+frames were
+single exposures; that way you could keep track of the separate
+effective gain and readnoise values. In that case you would enter the
+appropriate data parameter name under {\bf datapars}. As explained earlier,
+you could also do a
+``:e" on the {\bf datapars} line and essentially do the {\bf epar datapars} from
+within the {\bf epar daofind}.
+For normal star images, the
+various numerical values listed are best kept exactly the way they are;
+if you have only football shaped images, then read the help page for
+{\bf daofind} for hints how best to find footballs.
+
+We can now run {\bf daofind} by simply typing {\bf daofind}.
+As shown in Fig.~\ref{daofind} that we were asked for the FWHM and threshold
+values; this is a due to having turned ``verify" on in the parameter
+set. This safeguards to a large extent over having forgotten to set
+something correctly. A [CR] simply takes the default value listed.
+
+Running {\bf daofind} produced an output file with the (default)
+filename of {\bf n602csb.coo.1}.
+(Do {\it not} give the {\bf .imh} extension
+when specifying the image name, or the default naming
+process will get very confused!) We can page
+through that and see the x and y centers, the number of magnitudes
+brighter than the cutoff, the sharpness and roundness values, and the
+star number. However, of more immediate use is to use this file
+to mark the found stars on the image display and see how we did.
+If we have already displayed the frame in frame 1, then we can {\bf epar
+tvmark} to make it resemble Fig.~\ref{tvmark}.
+\begin{figure}
+\vspace{2.7in}
+\caption{\label{tvmark} Parameter file for {\bf tvmark}.}
+\end{figure}
+This will put red dots on top of each star found.
+
+We can see from Fig.~\ref{dots} that {\bf daofind} did a pretty nice
+\begin{figure}
+\vspace{7.0in}
+\caption{\label{dots} Stars found with {\bf daofind} and marked with
+{\bf tvmark}.}
+\end{figure}
+job. If we didn't like what we saw at this point we could rerun
+{\bf daofind} with a slightly higher or slightly lower threshold---try
+varying the threshold by half a sigma or so if you are almost right.
+As you may have guessed, subsequent runs will produce output files with
+the names n602csb.coo.2, n602csb.coo.3,...
+If you are using a very slow computer, or are exceedingly impatient,
+ you could have saved some
+time by putting a ``c" (say) under ``convolv" in your first run of
+{\bf daofind}---this would have saved the
+smoothed image as cn602csb.imh, and would drastically reduce
+the number of cpu cycles needed to rerun {\bf daofind} with
+a different threshold value.
+If you really very happy with what {\bf daofind} did but you
+just want to add one or two stars at this point, you
+can in fact do that quite readily using {\bf tvmark}. Set the
+parameters as in Fig.~\ref{tvmark}, but turn interactive on.
+Position the cursor on top of the star you wish to add and strike
+the ``a" key. Note that this will ``disturb" the format of the file,
+but we really don't care; it will still work just fine as the input to
+{\bf phot}.
+
+Note that it is fairly important that you do a good job at this stage.
+If you have used too low a threshold, and have a lot of junk marked as
+stars, these fictitious objects are likely to wander around during the
+PSF-fittings until they find something to latch onto---{\it not} a good
+idea. However, you also do not want the threshold to be so high that
+you are missing faint stars. Even if you are not planning to publish
+photometry of these faint guys, you need to have included them in the
+list of objects if they are near enough to affect the photometry of
+stars for which you do have some interest. If you find that varying the
+threshold level does not result in a good list, then something is
+wrong---probably you have badly over- or under-estimated the FWHM.
+When you are close to the ``perfect" value of the threshold,
+changing its value by as little as half a sigma will make a substantial
+difference between getting junk and real stars.
+
+\subsection{Aperture Photometry with {\bf phot} }
+The next step is to do simple aperture photometry for each of the stars
+that have been found. These values will be used as starting points in
+doing the PSF fitting, and this is the only time that sky values will be
+determined.
+
+{\bf One of the few ways of ``crash landing" in the current
+implementation of the software is to forget to reset ``datamin" in the
+datapars file before running phot on a new frame. It is the only
+critical parameter which is not queried when verify is turned on. Therefore,
+this is a good time to check to see that ``datamin" is really set to
+several sigma lower than the sky value of this particular frame.}
+
+The aperture photometry routine {\bf phot} has more parameters than all
+the others put together: there are the parameter files
+{\bf centerpars}, {\bf fitskypars}, and {\bf photpars}.
+Fortunately the ``verify"
+option frees you from having to look at these, and helps prevent you
+from making a mistake. If this is your first pass through DAOPHOT it is
+worth your while to do the following:
+
+\centerline{ {\bf unlearn centerpars} }
+
+\centerline{ {\bf unlearn fitskypars} }
+
+\centerline{ {\bf unlearn photpars} }
+
+\noindent
+If you have used {\bf phot} for measuring standard stars, then this will
+reset the defaults to reasonable values for crowded-field photometry;
+in particular, we want to make sure that the centering
+algorithm in {\bf centerpars} is set to ``none".
+Do an {\bf epar phot} and make it look like that of Fig.~\ref{phot}.
+Since we have the ``verify" switch turned on, we can be happy, not
+worry, and simply type {\bf phot}.
+{\bf phot} will then prompt you as shown in
+Fig.~\ref{phot}.
+\begin{figure}
+\vspace{7.0in}
+\caption{\label{phot} Questions and answers with {\bf phot}.}
+\end{figure}
+Note that the answers were particularly simple: we told it the name of
+the frame we wished to work with, we accepted the default for the coordinate
+list (it will take the highest ``version" of image.coo.NUMBER) and the
+default for the output photometry list (n602csb.mag.1 will be produced
+in this case.) We accepted the centers from {\bf daofind} as being
+``good enough" to not have to recenter (they are good to about one-third
+of a pixel, plenty good enough for aperture sizes of 2.5 pixels and
+bigger; when we run this routine later on the second pass we would make
+a Big Mistake by turning centering on here, so leave it off).
+The sky
+values will be taken from an annulus extending from a radius of 10
+pixels to a radius of 20 pixels, and it will determine the standard
+deviation of the sky from the actual data. Note that this is probably a
+lot closer in than you used on your standard stars; in crowded regions
+of variable background keeping this annulus relatively close in will
+help.
+Finally, we used a measuring
+aperture of 3 pixels. The number of counts within this aperture will be
+what defines the zero-point of your frame, as we will see in Section 4.9,
+and keeping this value {\it fixed} to some value like your typical FWHM
+will keep you safe.
+
+\subsection{Making the PSF with {\bf psf} }
+
+If you are used to the VMS version of DAOPHOT, you are in for a pleasant
+surprise when it comes to making a PSF within the IRAF version.
+Nevertheless, just because it's easy doesn't mean that you shouldn't be
+careful.
+
+What constitutes a good PSF star? Stetson recommends that a good PSF
+star meets the following criteria:
+\begin{enumerate}
+\item No other star at all contributes any light within one fitting
+radius of the center of the candidate star. (The fitting radius will be
+something like the FWHM.)
+\item Such stars as lie near the candidate star are significantly
+fainter. (``Near" being defined as, say, 1.5 times the radius of the
+brightest star you are going to measure.)
+\item There are no bad columns or rows near the candidate star; there
+should also be no bad pixels near the candidate star.
+\end{enumerate}
+
+
+In making a PSF, you wish to
+construct a PSF which is free from bumps and wiggles (unless those
+bumps and wiggles are really what a single isolated star would look like.)
+First off, does it matter if we get the PSF ``right"? If we had
+only isolated stars, then the answer would be no---any
+old approximation to the PSF would give you
+good relative magnitudes, and there are programs in the literature
+which do exactly this. However, if your stars are relatively isolated
+you are not going to gain anything by PSF-fitting over aperture photometry
+anyway, so why bother? If you are dealing with crowded images, then the
+PSF has to be right {\it even in the wings}, and for that reason we
+construct a PSF empirically using the brightest and least crowded stars
+in our frame.
+If you are very, very
+lucky you will find that your brightest, unsaturated star is well
+isolated, and has no neighbors about it---if that's the case, use that
+one and forget about the rest. Usually, however, you will find that
+it isn't quite that easy, and it will be necessary to construct the PSF
+interatively. The steps involved will be
+\begin{enumerate}
+ \item Select the brightest, least-crowded stars for the zeroth-order
+ PSF.
+ \item Decrease the size of the PSF radius and fit these stars
+ with their neighbors using {\bf nstar}.
+ \item Subtract off the PSF stars and their neighbors using
+ {\bf substar} to see
+ if any of the PSF stars are ``funny"; if so, go back to
+ the step 1 and start over.
+ \item Edit the {\bf nstar} results file ({\bf imagename.nst.N})
+ and delete the entries for the PSF stars. You are left
+ with a file containing the magnitudes and positions of just
+ the neighbors.
+ \item Subtract off just the neighbors using this file as input
+ to {\bf substar}. Display
+ the results, and examine the region around each PSF star.
+ Are the neighbors cleanly removed?
+ \item Increase the PSF radius back to the original value.
+ Construct an improved PSF using the new frame (the one with the
+ neighbors gone.)
+ \item Run {\bf nstar} on the PSF stars and their neighbors again, and
+ again subtract these using {\bf substar}. Examine the results.
+ If you are happy, proceed; otherwise, if the neighbors need
+ to be removed a bit more cleanly go back to step 4.
+\end{enumerate}
+
+First {\bf display} the frame, and put dots on all the stars you've found
+using {\bf tvmark} as discussed above. Next {\bf epar psf} and make sure
+it looks like that of Fig.~\ref{psfparams}.
+\begin{figure}
+\vspace{2.5in}
+\caption{\label{psfparams} Parameter file for {\bf psf}}
+\end{figure}
+We have set this up so we can choose the stars interactively from the
+display window.
+
+Next run {\bf psf}. The defaults that you will be asked to {\bf verify}
+are probably fine, but pay particular attention to {\bf psf radius}
+and {\bf fitting radius}. The {\bf psf radius} should be as large
+as you determined above (11 usually works well on ``typical" CCD
+frames whose star images have FWHM's $\approx 3$). The ``fitting radius"
+should be relatively generous here---maybe even larger than what you
+want to use on your program stars. A reasonable choice is approximately
+that of the FWHM.
+
+You will find that the cursor has turned into a circle and is sitting
+on your image in the display window. Position it on a likely looking
+PSF star, and strike the ``a" key. You will be confronted with a mesh
+plot that shows the star and it surroundings. To find out more
+about the star (such as what the peak data value is you can type
+an ``s" while looking at the mesh plot. To reject the star type an
+``x", to accept the star type an ``o". In the latter case, you will
+next see a mesh plot that
+shows you the star with a two-dimensional Gaussian fit removed from the
+star.
+Again, exit this with a ``o". If you don't find these mesh
+plots particularly useful, you can avoid them by setting {\bf showplot=no}
+in the {\bf psf} parameters (see Fig.~\ref{psfparams}).
+At this point you will be told what the star number was, what the
+magnitude was, and what the minimum and maximum data values within
+the PSF were. (If you picked a star whose peak intensity was greater
+than ``datamax" it will tell you this and not let you use this star.)
+When you are done selecting stars, type a ``w" (to write the PSF to
+disk) followed by a ``q".
+
+If in making the PSF you noticed that there were stars you could have
+used but didn't because they had faint neighbors not found in the earlier
+step of star finding, you can add these by hand by simply
+running {\bf tvmark} interactively and marking the extra stars. First
+{\bf epar tvmark} so it resembles that of Fig.~\ref{tvmark}. Then:
+
+\centerline{ {\bf display n602csb 1} }
+
+\centerline{ {\bf tvmark 1 n602csb.coo.1 interactive+} }
+
+\noindent
+
+Striking the ``l" key will mark the stars it already knows about onto
+the display (as red dots this time around); positioning the cursor on the
+first star you wish to add and type an ``a". When you are done adding
+stars exit with a ``q" and re-run {\bf phot}.
+
+Now that you have made your preliminary PSF, do a {\bf directory}. You'll
+notice that in addition to the image {\bf n602csb.psf.1.imh} that the
+{\bf psf} routine has also added a text file {\bf n602csb.psg.1}. If
+you {\bf page} this file you will see something like that of Fig.~\ref{psg}.
+\begin{figure}
+\vspace{3.5in}
+\caption{\label{psg} The ``point spread function group" file
+{\bf n602csb.psg.1}}
+\end{figure}
+This contains the aperture photometry of each PSF star plus its neighbors,
+with each set constituting a ``group". Running the psf-fitting photometry
+routine {\bf nstar} will fit PSF's to each of the stars within a group
+simultaneously.
+
+Before we run {\bf nstar}, however, we must decide what psf radius to use.
+Why not simply keep it set to the value found above (e.g., something like 11
+pixels)? The answer to this is a bit subtle, but understanding it will
+help you diagnose what is going wrong when you find a PSF going awry (and
+don't worry, you will). Let's consider the case that you construct a PSF
+from a single star with one neighbor whose center is 12 pixels away from
+the center of the PSF star, and let's have the PSF radius be 11 and the PSF
+fitting radius be 3. The PSF looks something like that of Fig.~\ref{bump}.
+\begin{figure}
+\vspace{5.0in}
+\caption{\label{bump} The zeroth order PSF of a star with a neighbor 12 pixels
+away.}
+\end{figure}
+The light from the neighbor star ``spills
+over" into the PSF.
+
+What happens when you try to fit two PSF's simultaneously? The bump from the
+PSF of the brighter star sits within the fitting radius of the fainter star,
+and it is the sum of the PSF's which are being fit to each star (that's
+what ``simultaneous" means). Thus there is an ``implicit subtraction" of
+the fainter star simply from fitting the bumpy PSF to the brighter star,
+and the brightness of the fainter star will be underestimated. The way
+to avoid this is to see that the PSF of the brighter star does not come
+within the fitting radius of the fainter star, and {\it that} we can
+accomplish easily by truncating the PSF size to something like the separation
+of the two stars minus the fitting radius. Thus in the example here
+we would want to fit the two stars using PSF's that were only ($12-3=9$)
+pixels in radius. It's true that there may still be light of the PSF
+star beyond this radius, but that will matter only if the PSF star is still
+going strong when you get within the {\it fitting radius} of the fainter
+star.
+
+Now that we understand all that, run {\bf nstar}. Specify the appropriate
+image name for ``image corresponding to photometry" and give it
+the ``.psg" file {\bf n602csb.psg.1} for the ``input group file".
+Remember to decrease
+the {\bf psf radius} when it tries to verify that number. {\bf nstar}
+will produce a photometry output file {\bf n60csb.nst.1}.
+You can
+subtract the fitted PSF's from these stars now by running {\bf substar}.
+Again, {\bf verify} the PSF radius to the smaller value. When the routine
+finishes, {\bf display} the resultant frame {\bf n60csb.sub.1.imh} and
+take a look at the PSF stars...or rather, where the PSF stars (and their
+neighbors) were. Are they subtracted cleanly? Does one of the PSF
+stars have residuals that look the reverse of the residuals of the others?
+If so, it would be best to reconstruct the PSF at this point throwing out
+that star---possibly it has a neighbor hidden underneath it, or has something
+else wrong with it. Are the variations in the cores of the subtracted image
+consistent with photon statistics? To answer this you may want to play
+around with {\bf imexamine} on both the original and subtracted images,
+but if the stars have cleanly disappeared and you can't even tell where
+they were, you are doing fine.
+
+The worst thing to find at this point
+is that there is a systematic pattern with position on the chip. This
+would indicate that the PSF is variable. There is the option for making
+a variable PSF, but the assumption is that the PSF varies smoothly in x
+and
+y; usually this is not the case. (In the case of the non-flat TI chips
+the variations are due to the potato-chip like shape.) If you {\it do}
+decide the PSF is variable, be sure to use plenty of stars in making the
+PSF. As it says in the ``help page",
+twenty-five to thirty is then not an unreasonable number. If that
+doesn't scare you off, nothing will.
+
+If the brightest stars have residuals that are systematically different than
+those of the fainter stars, maybe that chip wasn't quite as linear as you
+thought, or perhaps there are charge transfer problems. This proved to
+be the case for the RCA CCD data being reduced here. In Fig.~\ref{yuko}
+we show the residuals that result when we based our PSF on a star whose
+peak counts were 30000 ADUs.
+Empirically we found that stars with peaks of 18K ADUs (a mere 40K electrons)
+were safe to use, with the result that the dynamic range of our data
+was simply not quite as advertised. Although the PSF function broke down
+above 18K, the chip remained ``linear" in the sense that aperture photometry
+continued to give good results---the total number of counts continued to
+scale right up to the A/D limit of 32,767 ADUs (72K electrons after bias
+is allowed for). This appears to be a subtle charge transfer
+\begin{figure}
+\vspace{7.0in}
+\caption{\label{yuko} A ``before" and ``after" pair of images, where the
+PSF was constructed with a star that was too bright. Note the systematic
+residuals for the two bright stars. A ``bad" PSF star would result in a
+similar effect; however, in these data we found that there was always a
+systematic effect if the PSF stars were about 18000 ADU.}
+\end{figure}
+problem.
+
+We will assume that you have gotten the PSF to the point where
+the cores of the stars disappear cleanly, although there may be residuals
+present due to the neighbors. Our next step is to get rid of these neighbors
+so that you can make a cleaner PSF. Edit the {\bf nstar} output file
+{\bf n602csb.nst.1} and delete the lines associated with the PSF stars,
+leaving only the neighbors behind. You can recognize the PSF stars, as
+they are the first entry in each group. When you are done with this
+editing job, re-run {\bf substar}, using the edited ``.nst" file as the
+photometry file. Again in running {\bf substar} make sure you {\bf verify}
+the PSF radius to the smaller value you decided above. Examine the results
+on the image display. Now the PSF stars should be there but the neighbors
+should be cleanly subtracted. Are they? If so, you are ready to proceed.
+If not, re-read the above and keep at it until you get those neighbors
+reasonably well out of the frame.
+
+We can now run {\bf psf} on the subtracted frame---the one with only the
+neighbors gone. We have added some noise by doing the subtraction, and
+so we should reset {\bf datamin} to several sigma below the previously
+used
+value. We are going to have to do more typing this time when
+we run it, as the defaults for things will get very confused when we
+tell it that the ``Image for which to build PSF" is actually
+{\bf n60csb.sub.1}. For the ``Aperture photometry file" we can tell
+it the original photometry file {\bf n602csb.mag.1} if we want, or
+even the old ``.psg" file {\bf n602csb.psg.1} since every star that
+we are concerned about (PSF star plus neighbor) is there. Go ahead
+and give it the next `version" number for the ``Output psf image"
+{\bf n602csb.psf.2} and for the ``Output psf group file"
+{\bf n602csb.psg.2}.
+We can of course do this all on the command line:
+
+\centerline{ {\bf psf n602csb.sub.1 n602csb.mag.1 n602csb.psf.2
+n602csb.psg.2 datamin=-150.} }
+
+\noindent
+An example is shown in Fig.~\ref{psf1}.
+{\it This time make sure you take the
+large psf radius.}
+\begin{figure}
+\vspace{7.0in}
+\caption{\label{psf1} Making the first revision PSF using the frames with the
+neighbors subtracted. Compare this to Fig. 23, which shows the
+same region before the neighbors have been removed.}
+\end{figure}
+Make a new PSF using the cursor as before.
+
+How good is this revised PSF? There's only one way to find out: run
+{\bf nstar} on the original frame, this time keeping the psf radius large.
+Then do {\bf substar} and examine the frame with both the PSF stars and
+neighbors subtracted. Does this show a substantial improvement over the
+first version? Now that you have a cleaner PSF it may be necessary to repeat
+this procedure (edit the {\bf n602csb.nst.2} file, remove the PSF stars,
+run {\bf substar} using this edited file to produce a frame with the
+just the neighbors subtracted this time using a better PSF, run {\bf psf}
+on this improved subtracted frame) but probably not.
+
+\subsection{Doing the psf-fitting: {\bf allstar}.}
+The next step is to go ahead and run simultaneous PSF-fitting on all
+your stars, and produce a subtracted frame with these stars removed.
+To do both these things you need only run {\bf allstar}. The defaults
+are likely to be right: see Fig.~\ref{allstar}.
+\begin{figure}
+\vspace{3.5in}
+\caption{\label{allstar} Running {\bf allstar}.}
+\end{figure}
+As you may imagine, {\bf allstar} produces a photometry file
+{\bf n602csb.als.1}, and another subtracted image: {\bf imagename.sub.N}.
+
+Display the subtracted frame, and blink it against the original. Has
+IRAF/daophot done a nice job? If the stars are clearly gone with a few
+hidden ones now revealed, you can be proud of yourself---if the results
+are disappointing, there is only one place to look, and that is in the
+making of the PSF. Assuming that all is well, it is now time to
+add those previously hidden stars into the photometry.
+The easiest way to do this is to run {\bf daofind} on the subtracted
+image.
+Set the value of {\bf datamin} to a value several sigma lower
+than what you had used earlier in case the subtraction process generated
+some spuriously small values, and you will want to {\it increase} the
+value of threshold by 1 or 2 sigma above what you used previously.
+Why? Because the subtraction process has certainly added noise to the
+frame, and if you don't do this you will be mainly adding spurious
+detections. Use {\bf tvmark} as before to examine the results of {\bf
+daofind}; remember that the coordinate file name will be
+{\bf imagename.sub.N.coo.1} this time around. If you are really close,
+but want to add a couple of stars, re-run {\bf tvmark} on this file
+using
+{\bf interactive+}; this will allow you to add (and delete) coordinates
+from the file.
+
+Now run {\bf phot} using this new coordinate file as the input list.
+However, you do want to use the {\it original} frame for this photometry;
+otherwise the sky values for the newly found stars will be very messed
+up owing to the many subtracted images. A new aperture photometry file
+{\bf n602csb.mag.2} will have been produced. Use {\bf append} to
+concatenate these two files: {\bf append n602csb.mag.1,n602csb.mag.2
+n602csb.mag.3}. You can now re-run {\bf allstar} using this combined
+photometry file as the input.
+
+\subsection{Matching the frames}
+In the example here we have been reducing the {\it B} frame of
+a set of {\it UBV}. Once all three frames have been reduced it is often
+necessary to do a little fiddling. Have the same stars been identified
+in each group? In many cases you don't want the same stars to have been
+identified in each clump---afterall, some stars are red, some are blue
+(that's presumably why you are doing this afterall, right?), but in some
+cases you may find that a clump was identified as three objects on the
+{\it U} and the {\it V} frames and clearly should have been three on the
+{\it B} frame but instead is four or two. What to do?
+
+Using {\bf tvmark} it is relatively easy to set this right. First we
+need to use {\bf txdump} to produce a file for each frame that can be
+displayed. Do something like an
+
+\centerline{ {\bf txdump n602csu.als.2 $>$ tvu}}
+
+\noindent
+followed by an
+
+\centerline{ {\bf txdump n602csb.als.2 $>$
+tvb}}
+
+\noindent
+and a
+
+\centerline{ {\bf
+txdump n602csv.als.2 $>$ tvv}}
+
+\noindent
+In each case select {\bf xc,yc} and use
+{\bf MAG!=INDEF} as a selection criteria. Thus you will then have three text
+files that contain only the x's and y's of the stars with photometry.
+
+Next display the three frames ({\bf display n602csu 1}, {\bf display
+n602csb 2}, {\bf display n602csv 3}) and put colored dots up to denote
+the different allstar stars:
+
+\centerline{ {\bf tvmark 1 tvu color=204 inter-},}
+
+\centerline{
+{\bf tvmark 2 tvb color=205 inter-},}
+
+\noindent
+and
+
+\centerline{ {\bf tvmark 3 tvv color=206
+inter-}}
+
+\noindent
+will give pleasing results. Zoom, pan, register, and blink
+around the frames until you are convinced that you really do want to
+add or delete a star here or there. If you want to add or delete a star to the
+{\it U} frame list, do a
+
+\centerline{ {\bf tvmark 1 tvu color=203 inter+}}
+
+\noindent
+You are
+now in interactive mode, and centering the cursor on the star you want
+to add and striking the ``a" key will append the x and y value of the
+cursor the tvu list. Similarly, striking the ``u" key
+will delete a star from the list if you are using IRAF v2.9 or later.
+(For earlier versions you are just going to have to do a little
+editing by hand, good luck!) The star you add or delete will have
+a white dot appear on top of it.
+If you need to switch to a different coordinate file, simply exit the
+interactive {\bf tvmark} with a ``q" and re-execute it specifying, for
+example, {\bf tvmark 3 tvv color=203 inter+}.
+
+When you are done with adding and deleting stars, then it is time to
+redo the photometry. Do a {\bf phot n602csu coords=tvv datamin=100}
+in order to generate new aperture photometry and sky values. These
+can then be run through {\bf allstar}, and the procedure repeated for
+each
+of the frames.
+
+\subsection{Determining the Aperture Correction}
+
+The zero-point of your magnitudes have been set as follows. When you
+ran {\bf phot} using a small aperture (3 pixels in the example above)
+magnitudes were defined as -2.5 * log{(Counts above sky)/(Exposure
+time)} + Const.
+(The constant Const was hidden away in {\bf photpars} and is the
+magnitude assigned to a star that had a total of one ADU per second
+within the measuring aperture you used.) When you defined your PSF the
+magnitudes of the PSF stars determined from the aperture photometry were
+then used to set the zero-point of the PSF. However, your standard
+stars were presumably measured (if you did things right) through a much
+larger aperture, and what we must do now is measure how much brighter
+the PSF would have been had its zero-point been tied to the same size
+aperture used for the standard stars.
+
+We need to determine the aperture correction from the brightest,
+unsaturated stars (so there will still be reasonable signal above sky
+at the size of the large aperture); if you can pick out stars that are
+reasonably well isolated, so much the better. If this sounds vaguely
+familiar to you, you're right---this is basically what you did for
+selecting PSF stars, and these would be a good starting point for
+selecting stars for determining the aperture correction. Ideally you
+would like to use at least five such stars, but since when is data
+reduction ideal? Nevertheless, it is in the determination of the
+aperture correction the largest uncertainty enters in doing CCD
+photometry on crowded fields.
+
+We will first need to pick out the brightest, isolated stars and then
+to subtract off any stars that might affect their being measured through
+the large ``standard star" aperture (e.g., something like 15 pixels).
+To do this we need good photometry of any of these neighbor stars, and
+we describe two ways to do this (1) the very long complicated way, and
+(2) the very short easy way:
+
+\begin{enumerate}
+
+\item {\bf Method 1: Using the image display}
+We can also use {\bf tvmark} to mark the stars that we wish to use for
+aperture photometry. First we should remind ourselves what are multiple
+stars and what aren't: {\bf display} the image, and then use {\bf
+tvmark} to mark the stars with {\bf allstar} photometry:
+
+\centerline{ {\bf display n602csb 1} }
+
+\centerline{ {\bf txdump n602csb.als.2 xc,yc yes $>$ tvb} }
+
+\centerline{ {\bf tvmark 1 tvb color=204 interact-} }
+
+\noindent
+Now go through and mark the stars you want to use as the aperture
+correction stars {\it plus any neighbors that might contribute light
+to a large aperture centered on the bright stars:}
+
+\centerline{ {\bf tvmark 1 bapstars color=203 interact+ }}
+
+\noindent
+Use the ``a" key to generate a list ({\bf bapstars}) of the approximate
+{\it x} and {\it y} positions of these stars. Next run this list
+through {\bf phot} to generate improved centers and good sky values:
+
+\centerline{ {\bf phot n602csb bapstars bapphot calgor=``centroid" } }
+
+\noindent
+Next run the photometry output file {\bf bapphot} through {\bf group}:
+
+\centerline{ {\bf group n602csb bapphot default default crit=0.2} }
+
+\noindent
+This will have generated a ``group" file {\bf n602csb.grp.1}.
+
+\noindent
+Finally (!) run this group file through {\bf nstar}:
+
+\centerline{ {\bf nstar n602csb default default default} }
+
+\item {\bf Method 2: Using the ``.psg" files}
+If you used a goodly number ($>3-5$, say) stars in
+making the PSF, then we will simply use these stars as the aperture
+correction stars. Your last {\bf nstar} run should have produced an
+``{\bf .nst}" file that contains good photometry for the PSF stars {\it
+and} their neighbors. (If you don't remember if you did this, run {\bf
+nstar} using the ``{\bf .psg}" as the input group file.) Note that this
+method relies upon the assumption that the sum of the psf radius and psf
+fitting radius is about as large as the size of the large aperture you
+will use, so that all the important neighbors have been included in the
+point-spread-function group, but this is probably a reasonable
+assumption.
+
+\end{enumerate}
+
+Now that we are done with the preliminaries (!!),
+we now want to produce two files: one of them containing only the
+neighbors that we wish to subtract off, and another containing only the
+bright isolated stars which we want to use in computing the aperture
+correction. To do this we will use {\bf group} to divide up the ``{\bf
+.nst}" file (we could simply use the editor but that would be a lot of
+work). First we will use {\bf txdump} on the {\bf nstar} file to see the magnitude
+range covered by the PSF stars and their neighbors: hopefully there
+won't be any overlap. To do this try
+
+\centerline{ {\bf txdump n602csb.nst.3 id,group,mag yes} }
+
+\noindent
+In the example shown in Fig.~\ref{grouping} we see that the PSF stars
+\begin{figure}
+\vspace{2.0in}
+\caption{\label{grouping} The three PSF stars and their groups.}
+\end{figure}
+have magnitudes of 13.9, 15.0, and 16.5 in the three groups; all the
+neighbor stars are fainter than 17.0. Thus we can use {\bf select}
+to create a file containing the
+photometry of the faint stars:
+
+\centerline{ {\bf select n602csb.nst.3 n602csbsub} }
+
+\noindent
+and answer {\bf MAG$>$17.0} when you are queried for the ``Boolean
+expression". This will put the photometry of the stars you wish to get
+rid of into the file {\bf n602csbsub}. Next do an
+
+\centerline{ {\bf txdump n602csb.nst.3 xc,yc $>$ n602csbap} }
+
+\noindent
+and answer {\bf MAG$<$17.0} in response to ``Boolean expression". This
+will put the {\it x} and {\it y} values of the stars we wish to use for
+the aperture correction into the file
+{\bf n602csbap}. Next subtract the stars in the first file:
+
+\centerline{ {\bf substar n602csb n602csbsub} }
+
+\noindent and accept the defaults. This will result in the subtracted
+image {\bf n602csb.sub.N}. It is this file on which we wish to run
+the aperture photometry to determine the aperture correction:
+
+\centerline{
+{\bf phot n602csb.sub.N n602csbap n602csbapresults apertures=3.,15. annulus=20. dannu=5.} }
+
+\noindent
+You will see something like Fig.~\ref{apcor1} on your terminal.
+In this example we've made the assumption that the aperture size that
+set your zero-point in making the PSF was 3 pixels (i.e., what you used
+with {\bf phot} Way Back When), and that the aperture size used on your
+standard stars was 15 pixels.
+\begin{figure}
+\vspace{3.0in}
+\caption{\label{apcor1} The aperture correction run of {\bf phot}.}
+\end{figure}
+It is time to drag out your hand calculator. Using all three stars we
+find an average aperture correction of $-0.371$ with a standard
+deviation of the mean of 0.012 mag; given the large range in magnitude,
+I might have been tempted to ignore the two fainter stars and keep the
+aperture correction based only upon the brightest star (the frame is
+sparsely populated, and there isn't a whole heck of a lot else we can
+do). By an amazing coincidence, the aperture correction based just on
+the brightest star is also $-0.371$.
+
+
+\subsection{{\bf daophot} summary}
+\begin{itemize}
+\item Set up {\bf datapars} and {\bf daopars}.
+ \begin{enumerate}
+ \item Do an {\bf imhead} on some image and note the keywords for the
+ filter position, the effective exposure time, and the effective
+ airmass.
+ \item Use {\bf display} and {\bf imexamine} on a few frames to
+ determine the typical full-width-half-max
+ of stars and what would be a good
+ value to use for the radius of the psf (i.e., what radius will
+ contain the brightest star for which you wish to do photometry.)
+ \item Enter these into {\bf daopars} (psfrad) and {\bf datapars}
+ (header key words, fwhm). Also check that the correct values
+ are entered in {\bf datapars} for the gain (photons per ADU)
+ and read-noise (in electrons), as well as the ``maximum good data
+ value".
+ \end{enumerate}
+\item Find stars.
+ \begin {enumerate}
+ \item Do an {\bf implot} or {\bf imexamine} to determine the sky
+ level on your frame. Calculate the expected $1\sigma$ error.
+ \item Enter the sky value minus 3$\sigma$ as your value for
+ {\bf datamin} in {\bf datapars}.
+ \item Run {\bf daofind} using as a threshold value 3 to 5 $\sigma$.
+ \item Use {\bf tvmark} to mark the stars found ({\bf imagename.coo.1}).
+ If you need to, rerun {\bf daofind} with a larger or small
+ threshold.
+ \end {enumerate}
+\item Run aperture photometry using {\bf phot}.
+\item Generate a PSF. Run {\bf psf} and add stars using the ``a" key. Try
+ to select bright, uncrowded stars. Then:
+ \begin {enumerate}
+ \item Run {\bf nstar} using the file {\bf imagename.psg.1} as the
+ ``input photometry group" file. If there are neighbors, be sure
+ to decrease the psf radius as explained above.
+ Run {\bf substar} (also using the smaller sized psf radius)
+ and display the
+ resultant subtracted frame {\bf imagename.sub.1}. Do the residuals
+ of the PSF stars look consistent, or is one of them funny? If need
+ be, start over.
+ \item Remove any neighbor stars by editing the PSF stars out of the
+ ``.nst" file, and rerunning {\bf substar}. Run
+ {\bf psf} on the subtracted file, using the normal psf radius again.
+ You will have to over-ride the defaults for the input and output file
+ names now that you are using the subtracted image. Rerun {\bf nstar}
+ on the original frame using the normal psf radius and the revised
+ PSF. Run {\bf substar} and display the results. Are the PSF stars
+ nicely removed, and do the areas around the PSF stars look clean?
+ It may be necessary to remove neighbors again using this revised
+ PSF.
+ \end {enumerate}
+\item Run {\bf allstar}. Display the subtracted frame and see if your stars
+ have been nicely subtracted off.
+\item Run {\bf daofind} on the subtracted frame, using a value for
+ {\bf threshold} which is another $\sigma$ or two larger than before,
+ and a value for {\bf datamin} which is several $\sigma$ lower than
+ before. Use {\bf tvmark} to examine the results, and if need be
+ run {\bf tvmark} interactively so that you may add any extra stars.
+\item Run aperture photometry using {\bf phot} {\it on the original frame},
+ using the new coordinate list produced above.
+\item {\bf append} the two aperture photometry files.
+\item Run {\bf allstar} using the combine photometry file.
+\item Repeat all of the above for each frame in your ``set" (e.g., all short
+ and long exposures in each filter of a single field, say.
+\item Use {\bf txdump} to select the stars from the allstar files which
+ have magnitudes not equal to ``INDEF". Mark these stars using
+ {\bf tvmark}, and then use the capabilities of the image display
+ and {\bf tvmark} to match stars consistently from frame to frame.
+ Rerun {\bf phot} and {\bf allstar} on the final coordinate lists.
+\item Determine the aperture corrections.
+\item Transform
+ to the standard system (see the next section) and then
+ publish the results.
+\end{itemize}
+\section{Transforming to the Standard System}
+
+This section will eventually tell you how to easily and painless obtain
+the transformation equations for going from your instrumental magnitudes
+to the standard system, and how to apply these transformation equations
+to your program fields. Unfortunately, the IRAF routines for doing this
+are still under construction.
+In the meanwhile, we are providing here a kludge solution that can be
+used by initiates of Stetson's VMS CCDCAL routines. If you haven't been
+made a member of the club yet, and don't feel like waiting until the
+IRAF routines are become available before you get results, then I would
+recommend getting a hold of the good Dr. Stetson and bribing him until he
+offers to send you a copy of CCDCAL. There is an excellent manual that
+comes along with it, and we will not attempt to repeat any of that
+material here.
+
+\subsection{Standard Star Solution}
+First we will describe how to get output good enough to fool
+the CCDCAL software into believing the photometry was produced by CCDOBS
+(for the standard magnitudes), and what modifications need to be made
+to CCDSTD.FOR
+
+On the standard file do a {\bf txdump standstuff lid,ifilt,xair,mag,merr
+$>$ foolit} to dump the star number, filter number, airmass, and
+instrumental magnitudes and errors into the file {\bf foolit}.
+Unfortunately, you are now going to have to edit this file and stick in
+the star name (in what ever form you have it in creating the library of
+standard stars with CCDLIB) in place of the image name and star ID.
+(These were simply placed in the file to help guide you). While you are
+at it, line up the filter numbers, airmasses, and magnitudes into nice,
+neat columns. When you get done, stick in a line at the top that gives
+the number of instrumental magnitudes and their names, using a
+i1,13x,n(6x,a6) format. For instance, in the case shown here there
+are 3 instrumental magnitudes, U, B, and V. Finally, the filter numbers
+have to be edited so they agree with these (e.g., they must denote
+instrumental magnitude 1, 2, and 3...now aren't you sorry you didn't
+decide to wait until the IRAF routines were finished?). In
+Fig~\ref{groan} we show an example of the ``before" and ``after" file.
+\begin{figure}
+\vspace{3.5in}
+\caption{\label{groan}The output of {\bf txdump} and the final file
+ready for {\bf ccdstd}. Note the switching of the filter number ``5"
+with ``1".}
+\end{figure}
+
+CCDOBS.FOR itself now needs to be modified. Search for line statement
+``1120" (which will say JSTAR=JSTAR+1). Add a line that sets the
+integration time to 1 (tint=1.). Modify the READ statement as shown
+in Fig.~\ref{ccdobs}, and finally modify the 213 FORMAT statement
+so it actually matches your data file.
+\begin{figure}
+\vspace{2.5in}
+\caption{\label{ccdobs} Modifications to CCDOBS.FOR}
+\end{figure}
+You should now be able to compile, link, and run this modified
+version of CCDOBS and have it work on your standard star data.
+
+\subsection{Program Stars}
+The work required for faking ``CCDCAL" is actually a lot less. The data
+files are easily produced. Do a
+
+\centerline{{\bf txdump n602csu.als.2
+id,xc,yc,mag,merr,nit,chi $>$ csu} }
+
+\centerline{{\bf txdump n602csb.als.2 id,xc,yc,mag,merr,nit,chi $>$
+csb}}
+
+\centerline{{\bf txdump n602csv.als.2 id,xc,yc,mag,merr,nit,chi $>$
+csv}}
+
+\noindent
+answering {\bf MAG!=INDEF} to ``boolean expression" each time.
+These three files ({\bf csu}, {\bf csb}, {\bf csv} can be used
+with CCDCAL once a single modification is made to CCDCAL.FOR: on
+statement number 2020 change the format to ``free format", e.g.,
+2020 IF(NL(IOBS).NE.2) READ(2,*,END=2040). When CCDCAL queries
+you for an integration time, be sure to tell it 1.0, as your data have
+already been corrected for exposure times.
+
+\section{Acknowledgements}
+We are grateful to Jeannette Barnes and Carol Neese for critical
+readings of this document, although final blame for style and content
+of course rests with the authors.
+\end{document}
diff --git a/noao/digiphot/daophot/doc/userdocs/daoref.ms b/noao/digiphot/daophot/doc/userdocs/daoref.ms
new file mode 100644
index 00000000..6ef3d1f6
--- /dev/null
+++ b/noao/digiphot/daophot/doc/userdocs/daoref.ms
@@ -0,0 +1,6290 @@
+.LP
+\0
+.de XS
+.DS
+.ps -1
+.vs -1p
+.ft CB
+..
+.de XE
+.DE
+.ft R
+.ps
+.vs
+..
+.de YS
+.nf
+.ps -1
+.vs -1p
+.ft CB
+..
+.de YE
+.fi
+.ft R
+.ps
+.vs
+..
+.RP
+.TL
+A Reference Guide to the IRAF/DAOPHOT Package
+.AU
+Lindsey E. Davis
+.AI
+IRAF Programming Group
+.K2
+.ce
+.TU
+.br
+.ce
+January 1994
+.AB
+.PP
+DAOPHOT is a software package for doing stellar photometry in crowded stellar
+fields
+developed by Peter Stetson (1987) of the Dominion Astrophysical
+Observatory. IRAF/DAOPHOT uses the task structure and
+algorithms of DAOPHOT to do crowded-field stellar photometry within the
+IRAF data reduction and analysis environment.
+.PP
+This document briefly describes the principal similarities and differences
+between DAOPHOT and IRAF/DAOPHOT, the data preparation required to
+successfully use IRAF/DAOPHOT, how to examine and edit the IRAF/DAOPHOT
+algorithm parameters, how to run the IRAF/DAOPHOT package tasks interactively,
+non-interactively, or in the background, and how to examine
+and perform simple database operations on the output photometry files.
+.PP
+This document is
+intended as a reference guide to the details of using and
+interpreting the results of IRAF/DAOPHOT not a user's cookbook or a general
+guide to doing photometry in IRAF. Its goal is to take the user
+from a fully reduced image of a crowded stellar field to aperture
+corrected instrumental magnitudes using a small artificial image as a
+sample data set.
+First time IRAF/DAOPHOT users
+should consult \fIA User's Guide to Stellar Photometry With IRAF\fR, by
+Phil Massey and Lindsey Davis. Detailed descriptions of the DAOPHOT photometry
+algorithms can be found in Stetson (1987, 1990, 1992).
+.AE
+.ds CH
+.bp
+\0
+.bp
+.PP
+.na
+.LP
+\fBContents\fP
+.sp 1
+1.\h'|0.4i'\fBIntroduction\fP\l'|5.6i.'\0\01
+.sp
+2.\h'|0.4i'\fBDAOPHOT and IRAF/DAOPHOT\fP\l'|5.6i.'\0\01
+.sp
+3.\h'|0.4i'\fBPreparing Data for DAOPHOT\fP\l'|5.6i.'\0\03
+.sp
+4.\h'|0.4i'\fBSome IRAF Basics for New IRAF and DAOPHOT Users\fP\l'|5.6i.'\0\04
+.br
+.sp
+\h'|0.4i'4.1.\h'|0.9i'\fBPre-loaded Packages\fP\l'|5.6i.'\0\04
+.br
+\h'|0.9i'4.1.1.\h'|1.5i'The DATAIO Package\l'|5.6i.'\0\05
+.br
+\h'|0.9i'4.1.2.\h'|1.5i'The PLOT Package\l'|5.6i.'\0\05
+.br
+\h'|0.9i'4.1.3.\h'|1.5i'The IMAGES Package\l'|5.6i.'\0\05
+.br
+\h'|0.9i'4.1.4.\h'|1.5i'The TV Package\l'|5.6i.'\0\05
+.br
+\h'|0.4i'4.2.\h'|0.9i'\fBOther Useful Packages and Tasks\fP\l'|5.6i.'\0\05
+.br
+\h'|0.4i'4.3.\h'|0.9i'\fBImage Types, Image Directories, and Image Headers\fP\l'|5.6i.'\0\05
+.br
+\h'|0.4i'4.4.\h'|0.9i'\fBThe Image Display and Image Cursor\fP\l'|5.6i.'\0\06
+.br
+\h'|0.4i'4.5.\h'|0.9i'\fBThe Graphics Device and Graphics Cursor\fP\l'|5.6i.'\0\07
+.sp
+5.\h'|0.4i'\fBSome DAOPHOT Basics for New DAOPHOT Users\fP\l'|5.6i.'\0\08
+.br
+.sp
+\h'|0.4i'5.1.\h'|0.9i'\fBLoading the DAOPHOT Package\fP\l'|5.6i.'\0\08
+.br
+\h'|0.4i'5.2.\h'|0.9i'\fBLoading the TABLES Package\fP\l'|5.6i.'\0\08
+.br
+\h'|0.4i'5.3.\h'|0.9i'\fBRunning the Test Script\fP\l'|5.6i.'\0\08
+.br
+\h'|0.4i'5.4.\h'|0.9i'\fBOn-line Help\fP\l'|5.6i.'\0\09
+.br
+\h'|0.4i'5.5.\h'|0.9i'\fBEditing the Package Parameters\fP\l'|5.6i.'\010
+.br
+\h'|0.4i'5.6.\h'|0.9i'\fBEditing the Task Parameters\fP\l'|5.6i.'\011
+.br
+\h'|0.4i'5.7.\h'|0.9i'\fBInput and Output Image Names\fP\l'|5.6i.'\011
+.br
+\h'|0.4i'5.8.\h'|0.9i'\fBInput and Output File Names\fP\l'|5.6i.'\012
+.br
+\h'|0.4i'5.9.\h'|0.9i'\fBAlgorithm Parameter Sets\fP \l'|5.6i.'\012
+.br
+\h'|0.4i'5.10.\h'|0.9i'\fBInteractive Mode and Non-Interactive Mode\fP \l'|5.6i.'\014
+.br
+\h'|0.4i'5.11.\h'|0.9i'\fBImage and Graphics Cursor Input\fP\l'|5.6i.'\014
+.br
+\h'|0.4i'5.12.\h'|0.9i'\fBGraphics Output\fP\l'|5.6i.'\015
+.br
+\h'|0.4i'5.13.\h'|0.9i'\fBVerify, Update, and Verbose\fP\l'|5.6i.'\015
+.br
+\h'|0.4i'5.14.\h'|0.9i'\fBBackground Jobs\fP\l'|5.6i.'\015
+.br
+\h'|0.4i'5.15.\h'|0.9i'\fBTiming Tests\fP\l'|5.6i.'\016
+.sp
+6.\h'|0.4i'\fBDoing Photometry with DAOPHOT\fP\l'|5.6i.'\016
+.br
+.sp
+\h'|0.4i'6.1.\h'|0.9i'\fBThe Test Image\fP\l'|5.6i.'\016
+.br
+\h'|0.4i'6.2.\h'|0.9i'\fBTypical Analysis Sequence\fP\l'|5.6i.'\017
+.br
+\h'|0.4i'6.3.\h'|0.9i'\fBCreating and Organizing an Analysis Directory\fP\l'|5.6i.'\019
+.br
+\h'|0.4i'6.4.\h'|0.9i'\fBReading the Data\fP \l'|5.6i.'\019
+.br
+\h'|0.4i'6.5.\h'|0.9i'\fBEditing the Image Headers\fP\l'|5.6i.'\019
+.br
+\h'|0.9i'6.5.1.\h'|1.5i'The Minimum Image Header Requirements\l'|5.6i.'\019
+.br
+\h'|0.9i'6.5.2.\h'|1.5i'The Effective Gain and Readout Noise\l'|5.6i.'\019
+.br
+\h'|0.9i'6.5.3.\h'|1.5i'The Maximum Good Data Value\l'|5.6i.'\021
+.br
+\h'|0.9i'6.5.4.\h'|1.5i'The Effective Exposure Time\l'|5.6i.'\022
+.br
+\h'|0.9i'6.5.5.\h'|1.5i'The Airmass, Filter Id, and Time of Observation\l'|5.6i.'\022
+.br
+\h'|0.9i'6.5.6.\h'|1.5i'Batch Header Editing\l'|5.6i.'\024
+.br
+\h'|0.4i'6.6.\h'|0.9i'\fBEditing, Checking, and Storing the Algorithm Parameters\fP\l'|5.6i.'\024
+.br
+\h'|0.9i'6.6.1.\h'|1.5i'The Critical Algorithm Parameters\l'|5.6i.'\024
+.br
+\h'|0.9i'6.6.2.\h'|1.5i'Editing the Algorithm Parameters Interactively with Daoedit \l'|5.6i.'\024
+.br
+\h'|1.5i'6.6.2.1.\h'|2.2i'The Data Dependent Algorithm Parameters \l'|5.6i.'\025
+.br
+\h'|1.5i'6.6.2.2.\h'|2.2i'The Centering Algorithm Parameters\l'|5.6i.'\028
+.br
+\h'|1.5i'6.6.2.3.\h'|2.2i'The Sky Fitting Algorithm Parameters\l'|5.6i.'\029
+.br
+\h'|1.5i'6.6.2.4.\h'|2.2i'The Aperture Photometry Parameters\l'|5.6i.'\029
+.br
+\h'|1.5i'6.6.2.5.\h'|2.2i'The Psf Modeling and Fitting Parameters\l'|5.6i.'\030
+.br
+\h'|1.5i'6.6.2.6.\h'|2.2i'Setting the Algorithm Parameters Graphically\l'|5.6i.'\031
+.br
+\h'|0.9i'6.6.3.\h'|1.5i'Checking the Algorithm Parameters with Daoedit\l'|5.6i.'\031
+.br
+\h'|0.9i'6.6.4.\h'|1.5i'Storing the Algorithm Parameter Values with Setimpars\l'|5.6i.'\032
+.br
+\h'|0.9i'6.6.5.\h'|1.5i'Restoring the Algorithm Parameter Values with Setimpars\l'|5.6i.'\032
+.br
+\h'|0.4i'6.7.\h'|0.9i'\fBCreating a Star List\fP\l'|5.6i.'\032
+.br
+\h'|0.9i'6.7.1.\h'|1.5i'The Daofind Task\l'|5.6i.'\033
+.br
+\h'|1.5i'6.7.1.1.\h'|2.2i'The Daofind Algorithm\l'|5.6i.'\033
+.br
+\h'|1.5i'6.7.1.2.\h'|2.2i'The Daofind Algorithm Parameters\l'|5.6i.'\033
+.br
+\h'|1.5i'6.7.1.3.\h'|2.2i'Running Daofind Non-Interactively\l'|5.6i.'\034
+.br
+\h'|1.5i'6.7.1.4.\h'|2.2i'Running Daofind Interactively\l'|5.6i.'\034
+.br
+\h'|1.5i'6.7.1.5.\h'|2.2i'The Daofind Output\l'|5.6i.'\036
+.br
+\h'|1.5i'6.7.1.6.\h'|2.2i'Examining the Daofind Output\l'|5.6i.'\037
+.br
+\h'|0.9i'6.7.2.\h'|1.5i'Rgcursor and Rimcursor\l'|5.6i.'\038
+.br
+\h'|0.9i'6.7.3.\h'|1.5i'User Program\l'|5.6i.'\039
+.br
+\h'|0.9i'6.7.4.\h'|1.5i'Modifying an Existing Coordinate List\l'|5.6i.'\039
+.br
+\h'|0.4i'6.8.\h'|0.9i'\fBInitializing the Photometry with Phot\fP\l'|5.6i.'\039
+.br
+\h'|0.9i'6.8.1.\h'|1.5i'The Phot Algorithm\l'|5.6i.'\039
+.br
+\h'|0.9i'6.8.2.\h'|1.5i'The Phot Algorithm Parameters\l'|5.6i.'\040
+.br
+\h'|0.9i'6.8.3.\h'|1.5i'Running Phot Non-interactively\l'|5.6i.'\040
+.br
+\h'|0.9i'6.8.4.\h'|1.5i'Running Phot Interactively\l'|5.6i.'\042
+.br
+\h'|0.9i'6.8.5.\h'|1.5i'The Phot Output\l'|5.6i.'\043
+.br
+\h'|0.9i'6.8.6.\h'|1.5i'Examining the Results of Phot\l'|5.6i.'\044
+.br
+\h'|0.4i'6.9.\h'|0.9i'\fBCreating a Psf Star List with Pstselect\fP\l'|5.6i.'\044
+.br
+\h'|0.9i'6.9.1.\h'|1.5i'The Pstselect Algorithm\l'|5.6i.'\045
+.br
+\h'|0.9i'6.9.2.\h'|1.5i'The Pstselect Algorithm Parameters\l'|5.6i.'\045
+.br
+\h'|0.9i'6.9.3.\h'|1.5i'How Many Psf Stars Should Be Selected ?\l'|5.6i.'\046
+.br
+\h'|0.9i'6.9.4.\h'|1.5i'Running Pstselect Non-interactively\l'|5.6i.'\047
+.br
+\h'|0.9i'6.9.5.\h'|1.5i'Running Pstselect Interactively\l'|5.6i.'\047
+.br
+\h'|0.9i'6.9.6.\h'|1.5i'The Pstselect Output\l'|5.6i.'\048
+.br
+\h'|0.9i'6.9.7.\h'|1.5i'Examining and/or Editing the Results of Pstselect\l'|5.6i.'\048
+.br
+\h'|0.4i'6.10.\h'|0.9i'\fBComputing the Psf Model with Psf\fP\l'|5.6i.'\049
+.br
+\h'|0.9i'6.10.1.\h'|1.5i'The Psf Algorithm\l'|5.6i.'\049
+.br
+\h'|0.9i'6.10.2.\h'|1.5i'Choosing the Appropriate Analytic Function\l'|5.6i.'\050
+.br
+\h'|0.9i'6.10.3.\h'|1.5i'The Analytic Psf Model\l'|5.6i.'\050
+.br
+\h'|0.9i'6.10.4.\h'|1.5i'The Empirical Constant Psf Model\l'|5.6i.'\051
+.br
+\h'|0.9i'6.10.5.\h'|1.5i'The Empirical Variable Psf Model\l'|5.6i.'\051
+.br
+\h'|0.9i'6.10.6.\h'|1.5i'Rejecting Bad Data from the Psf Model\l'|5.6i.'\051
+.br
+\h'|0.9i'6.10.7.\h'|1.5i'The Model Psf Psfrad and Fitrad\l'|5.6i.'\052
+.br
+\h'|0.9i'6.10.8.\h'|1.5i'Modeling the Psf Interactively Without a Psf Star List\l'|5.6i.'\052
+.br
+\h'|0.9i'6.10.9.\h'|1.5i'Fitting the Psf Model Interactively Using an Initial Psf Star List\l'|5.6i.'\054
+.br
+\h'|0.9i'6.10.10.\h'|1.5i'Fitting the Psf Model Interactively Without an Image Display\l'|5.6i.'\055
+.br
+\h'|0.9i'6.10.11.\h'|1.5i'Fitting the Psf Model Non-interactively\l'|5.6i.'\056
+.br
+\h'|0.9i'6.10.12.\h'|1.5i'The Output of Psf\l'|5.6i.'\057
+.br
+\h'|0.9i'6.10.13.\h'|1.5i'Checking the Psf Model\l'|5.6i.'\059
+.br
+\h'|0.9i'6.10.14.\h'|1.5i'Removing Bad Stars from the Psf Model\l'|5.6i.'\062
+.br
+\h'|0.9i'6.10.15.\h'|1.5i'Adding New Stars to a Psf Star Group\l'|5.6i.'\062
+.br
+\h'|0.9i'6.10.16.\h'|1.5i'Refitting the Psf Model With the New Psf Star Groups\l'|5.6i.'\062
+.br
+\h'|0.9i'6.10.17.\h'|1.5i'Computing the Final Psf Model\l'|5.6i.'\063
+.br
+\h'|0.9i'6.10.18.\h'|1.5i'Visualizing the Psf Model with the Seepsf Task\l'|5.6i.'\063
+.br
+\h'|0.9i'6.10.19.\h'|1.5i'Problems Computing the Psf Model\l'|5.6i.'\064
+.br
+\h'|0.4i'6.11.\h'|0.9i'\fBDoing Psf Fitting Photometry with Peak, Nstar, or Allstar\fP \l'|5.6i.'\065
+.br
+\h'|0.9i'6.11.1.\h'|1.5i'Fitting Single Stars with Peak\l'|5.6i.'\065
+.br
+\h'|1.5i'6.11.1.1.\h'|2.2i'The Peak Algorithm\l'|5.6i.'\065
+.br
+\h'|1.5i'6.11.1.2.\h'|2.2i'Running Peak \l'|5.6i.'\065
+.br
+\h'|1.5i'6.11.1.3.\h'|2.2i'The Peak Output\l'|5.6i.'\066
+.br
+\h'|0.9i'6.11.2.\h'|1.5i'Fitting Stars with Group, Grpselect, Nstar and Substar\l'|5.6i.'\067
+.br
+\h'|1.5i'6.11.2.1.\h'|2.2i'The Group and Nstar Algorithms\l'|5.6i.'\067
+.br
+\h'|1.5i'6.11.2.2.\h'|2.2i'Running Group, Grpselect, and Nstar\l'|5.6i.'\068
+.br
+\h'|1.5i'6.11.2.3.\h'|2.2i'The Nstar Output\l'|5.6i.'\070
+.br
+\h'|0.9i'6.11.3.\h'|1.5i'Fitting Stars With Allstar\l'|5.6i.'\071
+.br
+\h'|1.5i'6.11.3.1.\h'|2.2i'The Allstar Algorithm\l'|5.6i.'\071
+.br
+\h'|1.5i'6.11.3.2.\h'|2.2i'Running Allstar\l'|5.6i.'\072
+.br
+\h'|1.5i'6.11.3.3.\h'|2.2i'The Allstar Output\l'|5.6i.'\073
+.br
+\h'|0.4i'6.12.\h'|0.9i'\fBExamining the Output Photometry Files\fP\l'|5.6i.'\073
+.br
+\h'|0.4i'6.13.\h'|0.9i'\fBProblems with the Photometry\fP\l'|5.6i.'\074
+.br
+\h'|0.4i'6.14.\h'|0.9i'\fBDetecting Stars Missed By Daofind\fP\l'|5.6i.'\075
+.br
+\h'|0.4i'6.15.\h'|0.9i'\fBInitializing the Missing Star Photometry with Phot\fP\l'|5.6i.'\075
+.br
+\h'|0.4i'6.16.\h'|0.9i'\fBMerging Photometry Files with Pfmerge\fP\l'|5.6i.'\076
+.br
+\h'|0.4i'6.17.\h'|0.9i'\fBRefitting the Stars with Allstar\fP\l'|5.6i.'\076
+.br
+\h'|0.4i'6.18.\h'|0.9i'\fBExamining the Subtracted Image\fP\l'|5.6i.'\076
+.br
+\h'|0.4i'6.19.\h'|0.9i'\fBComputing an Aperture Correction\fP\l'|5.6i.'\076
+.sp
+7.\h'|0.4i'\fBReferences\fP\l'|5.6i.'\077
+.sp
+8.\h'|0.4i'\fBAppendices\fP\l'|5.6i.'\077
+.br
+.sp
+\h'|0.4i'8.1.\h'|0.9i'\fBThe Instrumental Magnitude Scale\fP\l'|5.6i.'\077
+.br
+\h'|0.4i'8.2.\h'|0.9i'\fBThe Analytic Psf Models\fP\l'|5.6i.'\077
+.br
+\h'|0.4i'8.3.\h'|0.9i'\fBThe Error Model\fP\l'|5.6i.'\078
+.br
+\h'|0.4i'8.4.\h'|0.9i'\fBThe Radial Weighting Function\fP\l'|5.6i.'\078
+.br
+\h'|0.4i'8.5.\h'|0.9i'\fBTotal Weights\fP\l'|5.6i.'\078
+.br
+\h'|0.4i'8.6.\h'|0.9i'\fBBad Data Detection\fP\l'|5.6i.'\078
+.br
+\h'|0.4i'8.7.\h'|0.9i'\fBStellar Mergers\fP\l'|5.6i.'\079
+.br
+\h'|0.4i'8.8.\h'|0.9i'\fBFaint Stars\fP\l'|5.6i.'\079
+.br
+.bp
+\0
+.ds CH - % -
+.bp 1
+\0
+
+.TL
+A Reference Guide to the IRAF/DAOPHOT Package
+.AU
+Lindsey E. Davis
+.AI
+IRAF Programming Group
+.K2
+.ce
+.TU
+.br
+.ce
+January 1994
+
+.NH
+Introduction
+
+.PP
+DAOPHOT is a software package for doing stellar photometry
+in crowded fields developed by Peter Stetson of the DAO (1987, 1990, 1992).
+The IRAF/DAOPHOT package uses the task structure and algorithms of DAOPHOT
+to do crowded field photometry within the IRAF data reduction and
+analysis environment.
+.PP
+Input to IRAF/DAOPHOT consists of an IRAF image file, numerous parameters
+controlling the analysis algorithms and, optionally, graphics cursor and/or
+image display cursor input. IRAF/DAOPHOT produces output photometry files
+in either text format or STSDAS binary table format. Some IRAF/DAOPHOT tasks
+also produce image output and graphics output in the form of plot metacode
+files.
+.PP
+Separate tasks are provided for examining, editing, storing, and recalling
+the analysis parameters, creating and editing star
+lists, computing accurate centers, sky values and initial magnitudes
+for the stars in the list, computing the point-spread function,
+grouping the stars into physical associations, fitting the stars either
+singly or in groups, subtracting the fitted stars from the original image,
+and adding artificial test stars to the original image. A set of tools are
+also provided for examining and editing the output photometry files.
+
+.NH
+DAOPHOT and IRAF/DAOPHOT
+
+.PP
+The principal similarities and differences between DAOPHOT and IRAF/DAOPHOT
+are summarized below.
+.IP [1]
+The structure of IRAF/DAOPHOT is very similar to the
+structure of DAOPHOT. All the DAOPHOT photometry tasks and many of
+the utilities tasks are present in
+IRAF/DAOPHOT and in many cases the DAOPHOT task names have been preserved.
+A listing of the DAOPHOT photometry tasks and their closest IRAF/DAOPHOT
+equivalents is shown below.
+
+.TS
+l l
+l l
+l l.
+DAOPHOT\tIRAF/DAOPHOT
+TASK\tEQUIVALENT
+
+add*\taddstar
+allstar\tallstar
+attach\tN/A
+append\tpfmerge,pconcat
+find\tdaofind
+group\tgroup
+monitor\tdaophot.verbose=yes
+nomonitor\tdaophot.verbose=no
+nstar\tnstar
+offset\tpcalc
+options\tdaoedit
+peak\tpeak
+photometry\tphot
+pick\tpstselect
+psf\tpsf
+select\tgrpselect
+sort\tpsort,prenumber
+sub*\tsubstar
+.TE
+
+.IP [2]
+Some DAOPHOT utilities tasks are missing from IRAF/DAOPHOT.
+The DAOPHOT tasks \fBdump\fR, \fBexit\fR, \fBfudge\fR,
+\fBhelp\fR, \fBlist\fR, and \fBsky\fR
+have been replaced with general IRAF tasks, or with IRAF system facilities
+that perform the equivalent function. The missing DAOPHOT utilities tasks
+and their IRAF equivalents are shown below.
+
+.TS
+l l
+l l
+l l.
+DAOPHOT\tIRAF/DAOPHOT
+TASK\tEQUIVALENT
+
+dump\tlistpixels,imexamine
+exit\tbye
+fudge\timreplace,fixpix,imedit
+help\thelp daophot
+list\timheader
+sky\timstatistics,phistogram,imexamine
+.TE
+
+.IP [3]
+The IRAF/DAOPHOT default algorithms are the DAOPHOT II algorithms
+(Stetson 1992).
+.IP [4]
+Users have more choice of and control over the algorithms
+in IRAF/DAOPHOT than they do in DAOPHOT. For example the
+IRAF/DAOPHOT aperture photometry task \fBphot\fR offers several
+sky fitting algorithms besides the default "mode" algorithm,
+and full control over the sky fitting algorithm parameters.
+.IP [5]
+The algorithm parameters in IRAF/DAOPHOT are grouped by function into
+six parameter sets or psets rather than three as in DAOPHOT.
+The six IRAF/DAOPHOT parameter sets with their DAOPHOT equivalents
+in brackets are:
+1) \fBdatapars\fR, the data definition parameters (daophot.opt),
+2) \fBfindpars\fR, the detection algorithm parameters (daophot.opt),
+3) \fBcenterpars\fR, the aperture photometry centering algorithm parameters
+(no equivalent),
+4) \fBfitskypars\fR, the aperture photometry sky fitting parameters (photo.opt),
+5) \fBphotpars\fR, the aperture photometry parameters (photo.opt),
+6) \fBdaopars\fR, the IRAF/DAOPHOT psf fitting parameters (daophot.opt,
+allstar.opt).
+.IP [6]
+The IRAF/DAOPHOT algorithm parameter sets unlike the DAOPHOT parameter sets
+can be interactively examined,
+edited and saved with the \fBdaoedit\fR task using the image display
+and radial profile plots.
+.IP [7]
+The IRAF/DAOPHOT algorithm parameter sets unlike the DAOPHOT parameter sets
+can be saved and restored as a function of image using the \fBsetimpars\fR task.
+.IP [8]
+Memory allocation in IRAF/DAOPHOT is dynamic not static as in
+DAOPHOT. IRAF/DAOPHOT allocates and frees memory as required
+at run-time subject to the physical memory and swap space limitations of
+the host computer.
+.IP [9]
+The IRAF/DAOPHOT point-spread function look-up table is stored in an
+IRAF image not an ASCII table as in DAOPHOT.
+.IP [10]
+Unlike DAOPHOT, the IRAF/DAOPHOT tasks \fBdaofind\fR, \fBphot\fR,
+\fBpstselect\fR
+and \fBpsf\fR can be run interactively using the image display and graphics
+window or non-interactively. Display and graphics capabilities were
+deliberately omitted from DAOPHOT to minimize portability problems.
+.IP [11]
+The IRAF/DAOPHOT output photometry files can be written in either text
+format as in DAOPHOT or STSDAS binary table format.
+.IP [12]
+Unlike DAOPHOT, fields or columns in both IRAF/DAOPHOT text and
+STSDAS binary table photometry files are identified
+by name and have an associated units and format specifier.
+The IRAF/DAOPHOT photometry file input routines search for column
+names, for example "GROUP,ID,XCENTER,YCENTER,MAG,MSKY" as
+appropriate but are independent
+of their placement in the input file.
+.IP [13]
+Several general purpose IRAF/DAOPHOT tasks are available for performing
+operations on the final output photometry catalogs. In addition to
+\fBpcalc\fR, \fBpconcat\fR, \fBpfmerge\fR, \fBprenumber\fR,
+and \fBpsort\fR which are
+also available in DAOPHOT, there are three photometry file editing tasks which
+have no analog in DAOPHOT \fBpdump\fR, \fBpexamine\fR, and \fBpselect\fR.
+All these tasks work on IRAF/DAOPHOT output text files or STSDAS binary
+tables. An IRAF/DAOPHOT task is supplied for converting output text files to
+STSDAS binary tables so as to make use of the even more general STSDAS
+tables manipulation tools in the TABLES package.
+.IP [14]
+The IRAF/DAOPHOT output files are self-documenting.
+All the information required to comprehend the history of or decode the
+output photometry file is in the file itself, including the IRAF version
+number, host computer, date, time, and names of all the
+input and output files and the values of all the parameters.
+.PP
+For the remainder of this document IRAF/DAOPHOT will be referred to
+as DAOPHOT.
+
+.NH
+Preparing Data for DAOPHOT
+
+.IP [1]
+DAOPHOT assumes that the images to be analyzed exist on disk in IRAF
+image format. DAOPHOT can read and write old IRAF format ".imh" images
+and ST IRAF format ".hhh" images.
+When the IRAF FITS kernel becomes available DAOPHOT will be able
+to read FITS images on disk as well.
+QPOE IRAF format ".qp" images must be rasterized before they can
+be input to DAOPHOT.
+.IP [2]
+All internal DAOPHOT calculations are done in real precision.
+The pixel type of the image data on disk may be any of the following
+data types: short integer, unsigned short integer, integer, long integer,
+real or double. Users should realize that the extra precision in
+images of type double will not be used by DAOPHOT.
+.IP [3]
+The instrumental signature must be removed from the input images
+prior to running DAOPHOT. All CCD images should be overscan
+corrected, bias corrected, dark current corrected and flat-fielded.
+Users should be aware of the IRAF CCDRED package for reducing CCD data.
+.IP [4]
+DAOPHOT assumes that the input pixel data is linear.
+If the data is non-linear over a large fraction of its total dynamic range,
+the data must be linearized before running DAOPHOT.
+.IP [5]
+Saturated pixels or pixels distinguishable from good data by intensity,
+do not need to be removed from the image prior to running DAOPHOT.
+For example if the data
+is non-linear only above 25000 counts, DAOPHOT can be instructed to
+ignore pixels above 25000 counts.
+.IP [6]
+Extreme-valued pixels should be removed from the images prior to running
+DAOPHOT. Extreme-valued pixels include those with values at or near
+the floating point limits of the host machine and host machine special
+numbers produced by operations like divide by zero, floating point
+underflows and overflows, etc. The latter category of extreme-valued
+pixels should not be produced by IRAF software, but may be produced by
+user programs including imfort programs.
+Floating point operations involving such numbers will frequently cause
+arithmetic exception errors, since for efficiency and portability reasons
+the DAOPHOT package and most IRAF tasks do not test for
+their presence.
+The \fBimreplace\fR task in the PROTO package can be used to remove extreme-
+valued pixels.
+.IP [7]
+The background sky value should NOT be subtracted from the image prior
+to entering the DAOPHOT package. The DAOPHOT fitting routines use an optimal
+weighting scheme which depends on the readout noise, the gain, and the
+true counts in the pixels. If the mean sky has been subtracted
+then the counts in the image are not the true counts and the computed weights
+will be incorrect. For similar reasons users should not attempt to
+correct their magnitudes for exposure time by dividing their images
+by the exposure time.
+.IP [8]
+Cosmic ray and bad pixel removal programs should be used with caution. If the
+data and parameter values are set such that the cosmic ray and bad pixel
+detection and
+removal algorithms have difficulty distinguishing between stars and bad
+pixels or cosmic rays,
+the peaks of the stars may be clipped, altering the point-spread function
+and introducing errors into the photometry.
+.IP [9]
+DAOPHOT assumes that the local sky background is approximately flat in the
+vicinity of the object being measured. This assumption is equivalent to
+requiring that the local sky region have a unique mode. Variations
+in the sky background which occur on the same scale as the size of the
+local sky region will introduce errors into the photometry.
+.IP [10]
+The point spread function must be constant or smoothly
+varying with position over the entire image. This is the fundamental
+assumption
+underlying all of DAOPHOT. All stars in the image must be indistinguishable
+except for position and magnitude. The variable point spread function
+option is capable of handling second order variability as a function of
+position in the image.
+.IP [11]
+The input images should not have undergone any operations which fundamentally
+alter the image point spread function or the image statistics in a non-linear
+way. For example, non-linear image restoration tasks must not be run on
+the image to prior to running DAOPHOT.
+.IP [12]
+The gain, readout noise, exposure time,
+airmass, filter, and observing time should be present and correct in the
+image headers before DAOPHOT reductions are begun.
+DAOPHOT tasks can extract this information from the image headers, use it
+in the computations, and/or store
+it in the output photometry files, greatly simplifying the analysis
+and subsequent calibration procedures.
+.fi
+
+.NH
+Some IRAF Basics for New IRAF and DAOPHOT Users
+
+.NH 2
+Pre-loaded Packages
+
+.PP
+Under IRAF versions 2.10 and later the DATAIO, PLOT, IMAGES, TV and NOAO
+packages are pre-loaded so that all the tasks directly under them are
+available when
+IRAF is started. Each of these packages contains tasks which are useful
+to DAOPHOT users for various reasons, and each is discussed briefly below.
+
+.NH 3
+The DATAIO Package
+
+.PP
+DAOPHOT users should be aware of the DATAIO \fBrfits\fR and \fBwfits\fR tasks
+which are used to transport data into and out of IRAF. Any input
+and output images, including point-spread function look-up table images,
+should normally be archived with \fBwfits\fR.
+The cardimage reader and writer tasks for archiving text files,
+\fBrcardimage\fR and \fBwcardimage\fR, are also located here.
+
+.NH 3
+The PLOT Package
+
+.PP
+Various general purpose image and file plotting utilities can be found
+in the PLOT packages. DAOPHOT users should be aware of the interactive image
+row and column plotting task \fBimplot\fR, the image contour plotting task
+\fBcontour\fR, the image surface plotting task \fBsurface\fR, image
+histogram plotting task \fBphistogram\fR, the image radial profile
+plotting task \fBpradprof\fR, and the general purpose graphing tool
+\fBgraph\fR. The tasks \fBgkidir\fR and \fBgkiextract\fR are also useful
+for extracting individual plots from the plot metacode files which may
+be produced by some DAOPHOT tasks.
+
+.NH 3
+The IMAGES Package
+
+.PP
+The IMAGES package contains a set of general purpose image operators. DAOPHOT
+users
+should be aware of the image header examining tasks \fBimheader\fR and
+\fBhselect\fR, the header editing task \fBhedit\fR, the coordinate and
+pixel value dumping task \fBlistpixels\fR, and the image statistics
+task \fBimstatistics\fR.
+
+.NH 3
+The TV Package
+
+.PP
+The TV package contains tasks which interact with the image display including
+the all important \fBdisplay\fR task for displaying images, the
+interactive image examining task \fBimexamine\fR, and the \fBtvmark\fR task
+for marking objects on the image display. DAOPHOT users should become
+familiar with all three of these tasks.
+
+.NH 2
+Other Useful Packages and Tasks
+
+.PP
+The NPROTO package contains two useful tasks, \fBfindgain\fR,
+for computing the gain and readout noise of a CCD
+from a pair of biases and flats, and \fBfindthresh\fR for computing
+the standard deviation of the background in a CCD frame given the
+readout noise and gain. The ASTUTIL package contains the \fBsetairmass\fR
+task for computing and/or correcting the airmass given the appropriate
+input data.
+Users might also wish to experiment with the tasks in the artificial
+data package ARTDATA, and run the resulting images through DAOPHOT.
+
+.NH 2
+Image Types, Image Directories, and Image Headers
+
+.PP
+The IRAF image environment is controlled by several
+environment variables. The most important of these for DAOPHOT users
+are: \fBimtype\fR the disk image format, \fBimdir\fR the default pixel
+directory, and \fBmin_lenuserarea\fR the maximum length of the image header.
+The values of these environment variables can be listed
+as shown below.
+
+.YS
+cl> show imtype
+imh
+cl> show imdir
+/data/davis/pixels/
+cl> show min_lenuserarea
+24000
+.YE
+
+.PP
+\fB"imh"\fR is the default image format for most IRAF users, \fB"hhh"\fR the
+default image format for ST users, and \fB"qp"\fR the photon counting format
+used for photon counting data. DAOPHOT will work transparently on
+"imh" and "hhh" images. "qp" event lists must be rasterized prior to using
+DAOPHOT. When IRAF supports FITS images on disk, image format "fits", DAOPHOT
+will be able to work directly on FITS images as well. IRAF uses the
+image name extension, e.g. "imh" to automatically sense the image
+disk format on input. The output disk format is set by: 1) the
+extension of the output image name if present e.g. "imh", 2) the cl
+environment variable \fBimtype\fR if the output image is opened as a new
+image, e.g. the output of the \fBrfits\fR task, 3) the type of the input
+image if the output image is opened as a new copy of an existing image,
+e.g. the output of the \fBimcopy\fR task.
+.PP
+\fBimdir\fR specifies the default image pixel directory for "imh" format
+files. The image header files are written to the current directory
+and the pixel files are written to imdir. imdir can be set
+to an existing directory on a scratch disk, the current
+directory "HDR$", or the subdirectory pixels under the current
+directory "HDR$pixels/". DAOPHOT users should keep both the intrinsic
+speed of a disk and its network configuration in mind when setting
+imdir.
+.PP
+\fBmin_lenuserarea\fR is the size of the image header area reserved
+in memory when a new or existing image is opened.
+The current default value of 24000 corresponds to space for approximately
+300 keywords.
+If an image on disk has a header larger than this the image header will
+be truncated when it is read.
+For most DAOPHOT users the default value is sufficient. However users whose
+images have large headers or who are
+creating a point-spread function using more than ~70 stars should set
+min_lenuserarea to a larger value, e.g. 40000.
+.PP
+The following example shows how to change the default pixel directory to
+HDR$pixels/ and set min_lenuserarea to 40000. To avoid redefining these
+quantities for every session, users should enter the redefinitions into
+their login.cl or loginuser.cl files.
+
+
+.YS
+cl> reset imdir = "HDR$pixels/"
+cl> reset min_lenuserarea = 40000
+.YE
+
+.NH 2
+The Image Display and Image Cursor
+
+.PP
+Several DAOPHOT tasks are interactive tasks or have an interactive as well
+as a non-interactive mode. In interactive mode these tasks must be able to
+read the image cursor on a displayed image and perform various
+actions depending on the position of the image cursor and the keystroke
+command typed.
+.PP
+DAOPHOT will work with the display servers Imtool, Saoimage, and Ximtool.
+DAOPHOT users should be aware that both Imtool and Ximtool support multiple
+frame buffers while SAOimage does not. Multiple frame buffers are an
+important feature for users who wish to compare their original
+images with the DAOPHOT output images from which all the fitted
+stars have been subtracted. Users running DAOPHOT on a remote machine, e.g.
+one with lots of memory and/or disk space, but displaying on their local
+machine also need to set the \fBnode\fR environment variable to
+the name of the local machine.
+
+.YS
+cl> show node
+ERROR: No such environment variable
+ show (node)
+cl> set node = mymachine
+.YE
+
+.PP
+The maximum size of the display server frame buffer is defined by the
+environment variable \fBstdimage\fR whose value can be printed as
+shown below.
+
+.YS
+cl> show stdimage
+imt512
+.YE
+
+In the previous example the default frames buffers are 512 pixels square.
+A user whose images are 2K square will want to reset the default frame
+buffer size as shown below.
+
+.YS
+cl> reset stdimage = imt2048
+cl> show stdimage
+imt2048
+.YE
+
+.PP
+In order for image cursor read-back to function correctly the environment
+variable \fBstdimcur\fR must be set to "stdimage" as shown below.
+
+.YS
+cl> show stdimcur
+stdimage
+.YE
+
+To check that image cursor read-back is functioning correctly the user
+should display an image and try to bring up the image display cursor
+as shown below.
+
+.YS
+cl> display image 1
+cl> =imcur
+.YE
+
+The image cursor should appear on the image display reading the correct
+image pixel coordinates and ready to accept a
+keystroke command. Any keystroke will terminate the cursor read.
+
+.NH 2
+The Graphics Device and Graphics Cursor
+
+.PP
+Some interactive DAOPHOT tasks have graphics submenus which require
+them to be able to read the graphics cursor on for example a radial
+profile plot and perform various
+actions based on the position of the graphics cursor in the
+plot and the keystroke
+command issued. The default graphics device is determined by
+the \fBstdgraph\fR environment variable as shown below.
+
+.YS
+cl> show stdgraph
+xgterm
+.YE
+
+To check that graphics cursor read-back is functioning correctly the user
+should draw a plot and try to bring up the graphics cursor as
+shown below.
+
+.YS
+cl> contour image
+cl> =gcur
+.YE
+
+The graphics cursor should appear in the graphics window ready to accept a
+keystroke command. Any keystroke will terminate the cursor read.
+
+.NH
+Some DAOPHOT Basics for New DAOPHOT Users
+
+.NH 2
+Loading the DAOPHOT Package
+
+.PP
+The DAOPHOT package is located in the digital stellar photometry package
+DIGIPHOT. To load DIGIPHOT and DAOPHOT the user types the package names
+in sequence as shown below,
+
+.YS
+cl> digiphot
+di> daophot
+.YE
+
+after which the following menu of tasks appears.
+
+.YS
+addstar daotest nstar pexamine psf
+allstar datapars@ pcalc pfmerge psort
+centerpars@ findpars@ pconcat phot pstselect
+daoedit fitskypars@ pconvert photpars@ seepsf
+daofind group pdump prenumber setimpars
+daopars@ grpselect peak pselect substar
+.YE
+
+Task names with a trailing "@" are parameter set tasks.
+The remaining tasks are script and/or compiled tasks.
+After the DAOPHOT package is loaded the user can redisplay
+the package menu at any time with the command.
+
+.YS
+da> ? daophot
+.YE
+
+.NH 2
+Loading the TABLES Package
+
+.PP
+The DAOPHOT photometry tasks write their output photometry files in
+either text format (the default) or ST binary tables format. Users wishing
+to use the ST binary tables format should acquire and install
+the ST TABLES external package. Without the TABLES package the DAOPHOT
+photometry tasks will read and write ST binary tables, but DAOPHOT
+utilities like \fBpsort\fR which call TABLES package
+tasks will not run on ST binary tables.
+.PP
+When DAOPHOT is loaded, it checks to see if the TABLES package is defined,
+and if so loads it. A warning message is issued if the TABLES package is
+undefined. The TABLES package tasks can be listed at any time after DAOPHOT
+is loaded with the following command.
+
+.YS
+da> ? tables
+.YE
+
+.NH 2
+Running the Test Script
+
+.PP
+The DAOPHOT package includes a script task \fBdaotest\fR which
+executes each of the core DAOPHOT photometry tasks in turn using a test
+image stored
+in FITS format in the DAOPHOT test directory. \fBDaotest\fR is run as
+shown below.
+
+.YS
+da> daotest
+
+DAOTEST INITIALIZES THE DAOPHOT TASK PARAMETERS
+TYPE 'q' or 'Q' TO QUIT, ANY OTHER KEY TO PROCEED
+
+Name of the output test image: test
+
+INITIALIZE THE DAOPHOT PACKAGE
+
+TESTING THE DAOFIND TASK
+TESTING THE PHOT TASK
+TESTING THE PSTSELECT TASK
+TESTING THE PSF TASK
+TESTING THE PEAK TASK
+TESTING THE GROUP TASK
+TESTING THE GRPSELECT TASK
+TESTING THE NSTAR TASK
+TESTING THE ALLSTAR TASK (CACHE=YES)
+TESTING THE ALLSTAR TASK (CACHE=NO)
+TESTING THE SUBSTAR TASK
+TESTING THE ADDSTAR TASK
+
+DAOPHOT PACKAGE TESTS COMPLETED
+.YE
+
+On task completion the user will find the input image in
+test.imh, the psf image in test.psf.1.imh, the subtracted image produced
+by \fBallstar\fR in test.sub.1.imh, the input image with artificial stars
+added in test.add.1.imh, copies of all the output photometry files in
+test.log, and copies of the plots produced by the \fBpsf\fR task
+in test.plot on disk.
+.PP
+Users should be aware that the \fBdaotest\fR task will reset the DAOPHOT
+task and algorithm parameters to their default values before and after it
+is executed.
+
+.NH 2
+On-line Help
+
+.PP
+A one-line description of each DAOPHOT task can be obtained by typing
+the following command,
+
+.YS
+da> help daophot\fR
+.YE
+
+upon which the following package menu appears.
+
+.YS
+digiphot.daophot:
+ addstar - Add stars to an image using the computed psf
+ allstar - Group and fit psf to multiple stars simultaneously
+centerpars - Edit the centering algorithm parameters
+ daoedit - Review/edit algorithm parameters interactively
+ daofind - Find stars in an image using the DAO algorithm
+ daopars - Edit the daophot algorithms parameter set
+ daotest - Run basic tests on the daophot package tasks
+ datapars - Edit the image data dependent parameters
+ findpars - Edit the star detection parameters
+fitskypars - Edit the sky fitting algorithm parameters
+ group - Group stars based on position and signal/noise
+ nstar - Fit the psf to predefined groups of stars
+ peak - Fit the psf to single stars
+ phot - Compute skies and initial magnitudes for a star list
+ photpars - Edit the aperture photometry parameters
+ psf - Compute the point spread function
+ seepsf - Compute an image from the point spread function
+ setimpars - Save/restore parameter sets for a particular image
+ substar - Subtract the fitted stars from the original image
+
+ pcalc - Do arithmetic operations on list of daophot databases
+ pconcat - Concatenate a list of daophot databases
+ pconvert - Convert a text database to a tables database
+ pdump - Print selected fields from daophot databases
+ pfmerge - Merge a list of photometry databases
+ pstselect - Select candidate psf stars based on proximity
+ grpselect - Select groups from a daophot database
+ pexamine - Interactively examine and edit a daophot database
+ prenumber - Renumber stars in a daophot database
+ pselect - Select records from a daophot database
+ psort - Sort a daophot database\fR
+.YE
+
+.PP
+All the DAOPHOT tasks have on-line manual pages which can be
+listed on the terminal. The following command lists the help for the
+\fBphot\fR task on the terminal.
+
+.YS
+da> phelp phot\fR
+.YE
+
+Any section of the manual pages can be listed individually.
+For example the examples section of the \fBphot\fR manual page can be
+listed as follows.
+
+.YS
+da> phelp phot sections=examples\fR
+.YE
+
+The help page for \fBphot\fR can be piped to the local default printer as
+follows.
+
+.YS
+da> phelp phot | lprint\fR
+.YE
+
+Finally the manual pages for the whole DAOPHOT package can be printed
+by typing.
+
+.YS
+da> phelp daophot.* | lprint\fR
+.YE
+
+
+.NH 2
+Editing the Package Parameters
+
+.PP
+DAOPHOT has a package parameter set which defines the DAOPHOT
+package environment. The DAOPHOT package parameters can edited
+with epar as shown below.
+
+.YS
+da> epar daophot
+.YE
+
+.YS
+Image Reduction and Analysis Facility
+ PACKAGE = digiphot
+ TASK = daophot
+ (version = "Dec92")
+ (text = yes) Text file on output ?
+ (verify = yes) Verify critical parameters ?
+ (update = no) Update critical parameters ?
+ (verbose = yes) Print verbose output ?
+(graphics = "stdgraph") Default graphics device
+ (display = "stdimage") Default display device
+ (mode = "ql")
+.YE
+
+To edit a parameter simply move the cursor to the parameter in question,
+enter the new value, type return, and finally type \fB:wq\fR to quit and
+update the parameter set. Package parameters can also be edited on the
+command line as shown below.
+
+.YS
+da> daophot.text = yes
+.YE
+
+.PP
+The DAOPHOT package parameters control the operation of the DAOPHOT package
+as a whole. For example the \fBtext\fR parameter specifies whether the
+output photometry files will be written in text or STSDAS binary tables format,
+the parameters \fBverify\fR, \fBupdate\fR, and \fBverbose\fR determine
+the default mode of operation of the DAOPHOT package tasks, and the parameters
+\fBgraphics\fR and \fBdisplay\fR determine the default graphics and display
+devices for the entire package.
+
+.NH 2
+Editing the Task Parameters
+
+.PP
+The DAOPHOT task level parameters specify the input and output images and
+files, the algorithm parameter sets, the graphics and image display input and
+output devices, and the mode of operation of each DAOPHOT task.
+.PP
+To enter and edit the parameter set for the DAOPHOT \fBphot\fR task
+the user types the following command,
+
+.YS
+cl> epar phot
+.YE
+
+after which the parameter set for the \fBphot\fR task appears on the
+terminal ready for editing as shown below.
+
+.YS
+Image Reduction and Analysis Facility
+PACKAGE = daophot
+ TASK = phot
+
+image = Input image(s)
+coords = default Input coordinate list(s)
+output = default Output photometry file(s)
+skyfile = Input sky value file(s)
+(plotfil= ) Output plot metacode file
+(datapar= ) Data dependent parameters
+(centerp= ) Centering parameters
+(fitskyp= ) Sky fitting parameters
+(photpar= ) Photometry parameters
+(interac= no) Interactive mode ?
+(radplot= no) Plot the radial profiles?
+(verify = )_.verify) Verify critical phot parameters ?
+(update = )_.update) Update critical phot parameters ?
+(verbose= )_.verbose) Print phot messages ?
+(graphic= )_.graphics) Graphics device
+(display= )_.display) Display device
+(icomman= ) Image cursor: [x y wcs] key [cmd]
+(gcomman= ) Graphics cursor: [x y wcs] key [cmd]
+(mode = ql)
+.YE
+
+The \fBphot\fR parameters can be edited by moving
+the cursor to the line opposite the parameter name, entering the new value
+followed by a carriage return, and typing \fB:wq\fR to exit the
+\fBepar\fR task and update the parameters.
+.PP
+In the following sections the \fBphot\fR task is used to illustrate
+some general features of the DAOPHOT package.
+
+.NH 2
+Input and Output Image Names
+
+.PP
+The \fBphot\fR parameter \fIimage\fR
+defines the image to be analyzed. The
+root image name, the value of \fIimage\fR
+stripped of directory and section information,
+sets up the default input and output image naming convention for the task.
+Users should avoid appending the ".imh" or ".hhh" extension
+to their image name specification as these extensions are not required by IRAF
+image i/o and become part of the default output image names.
+.PP
+The \fBphot\fR task does not create an output image but DAOPHOT tasks
+which do, will by default create an output image name of the form
+"image.extension.?" where image is the input image name
+stripped of directory
+and section information, extension is an id appropriate
+to the task, and ? is the next available version number.
+For example the first run of the \fBsubstar\fR task on the image "image"
+will create an image called "image.sub.1", the second an image
+called "image.sub.2", and so on. The default output image naming convention
+can always be overridden by the user in any task.
+
+.NH 2
+Input and Output File Names
+
+.PP
+DAOPHOT uses a default input and output file naming convention based on the
+root image name or the input image name with the directory and
+section specification removed. Users should avoid appending the ".imh" or
+".hhh" extension to their input image name specification as these extensions
+are not required by IRAF image i/o and become part of the default input
+and output file names.
+.PP
+If a DAOPHOT task expects its input to have been written
+by another DAOPHOT task, and the input file parameter value is "default",
+the task will search for an existing
+file called "image.extension.?" where image is the root image
+name, extension identifies the task expected to have written the file,
+and version is the highest version number for that file. For example,
+if the user sets the \fBphot\fR parameters \fIimage\fR and
+\fIcoords\fR to "m92b" and "default", \fBphot\fR will search
+for a coordinate file called "m92b.coo.#" written by the
+\fBdaofind\fR task. The default input file naming convention
+can be over-ridden by the user at any point.
+.PP
+The output file naming convention works
+in an identical manner to the input file naming convention,
+although in this situation ? is the next available
+version number. For example if the user sets the \fBphot\fR task
+parameter \fIoutput\fR to "default", the output photometry file name
+will be "image.mag.?"
+where ? is 1 for the first run of \fBphot\fR, 2 for the second run, and so
+on. The default output file naming convention can be over-ridden
+by the user at any point.
+
+.NH 2
+Algorithm Parameter Sets
+
+.PP
+The DAOPHOT parameters have been grouped together into parameter sets
+or psets.
+The use of psets encourages the logical grouping of parameters, permits
+the various DAOPHOT tasks to share common parameters, and
+permits the user to optionally store the DAOPHOT algorithm parameters
+with the data rather than in the default uparm directory.
+.PP
+Six DAOPHOT psets, \fBdatapars\fR, \fBfindpars\fR, \fBcenterpars\fR,
+\fBfitskypars\fR, \fBphotpars\fR and \fBdaopars\fR
+control the DAOPHOT algorithm parameters. The \fBphot\fR task
+uses four of them, \fBdatapars\fR which specifies data dependent
+parameters like \fIfwhmpsf\fR (the full-width half-maximum of the psf),
+\fIsigma\fR (the standard deviation of
+the sky background), \fIepadu\fR and \fIreadout noise\fR
+(the gain and readout noise of the detector),
+and the \fBcenterpars\fR, \fBfitskypars\fR and \fBphotpars\fR parameter
+sets which define the centering algorithm, sky fitting algorithm
+and aperture photometry algorithm parameters respectively,
+used by phot to compute initial centers, sky values,
+and initial magnitudes for the stars to be analyzed. The \fBfindpars\fR pset
+controls the star detection algorithm parameters used by the \fBdaofind\fR
+task. The \fBdaopars\fR pset defines the psf model fitting
+and evaluation parameters including the radius of the psf, the fitting radius,
+and the grouping parameters used by all the psf fitting tasks.
+.PP
+By default the pset parameters can be examined, edited and stored
+in the user's uparm directory, in the same manner as the task level
+parameters. For example to list the current \fBdatapars\fR
+pset the user types.
+
+.YS
+da> lpar datapars
+.YE
+
+To edit the \fBdatapars\fR parameter set, the user types either
+
+.YS
+da> epar datapars
+
+or
+
+da> datapars
+.YE
+
+and edits the parameter set in the usual manner with \fBepar\fR.
+All the DAOPHOT tasks which reference this
+pset will pick up the changes from the uparm directory, assuming
+that the \fIdatapars\fR parameter is specified as "" in the calling task.
+The user can also edit the \fBdatapars\fR
+pset from within the \fBphot\fR
+task or any other task which calls it as shown below.
+
+.YS
+da> epar phot
+.YE
+
+Move the cursor to the \fBdatapars\fR parameter line and type \fB:e\fR.
+The menu for the
+\fBdatapars\fR pset will appear ready for editing. Edit the desired
+parameters and type \fB:wq\fR. \fBEpar\fR will return to the main
+\fBphot\fR parameter set after which other psets or the main task parameters
+can be edited.
+.PP
+Psets may also be stored in user files providing
+a mechanism for saving a particular pset
+with the data.
+The example below shows how to store a pset in a file in the same directory
+as the data and recall it for use by the \fBphot\fR task. The user types
+
+.YS
+da> epar phot
+.YE
+
+as before, enters the \fBdatapars\fR menu with \fB:e\fR and edits the
+parameters. The command \fB:w data1.par\fR
+writes the parameter set to a file called "data1.par" and a \fB:q\fR
+returns to the main task menu.
+A file called "data1.par" containing the new \fBdatapars\fR parameters
+is written in the current directory. At this point the user is still in the
+\fBphot\fR parameter set at the line opposite \fBdatapars\fR. He/she
+enters "data1.par" on the line opposite this parameter.
+The next time \fBphot\fR is run the parameters will
+be read from "data1.par" not from the pset in the uparm directory.
+The new parameter set can be edited in the usual way by typing
+
+.YS
+da> epar data1.par
+
+or
+
+da> epar phot
+.YE
+
+Users should be sure to append a .par extension to any pset files they
+create as IRAF needs this extension to identify the file as a pset.
+.PP
+It is possible to develop quite efficient and creative schemes for using psets.
+For example a user might choose to copy each crowded stellar field
+image to its own directory, copy the default psets \fBdatapars\fR,
+\fBfindpars\fR, \fBcenterpars\fR, \fBfitskypars\fR, \fBphotpars\fR
+and \fBdaopars\fR to the files "datapars.par", "findpars.par",
+"centerpars.par", "fitskypars.par", "photpars.par" and "daopars.par" in
+each image directory, and then edit
+the parameter sets of the top level tasks to look for psets with those names.
+Once this is done the psets in each directory can be edited at will
+without ever needing to edit the names of the psets in the top
+level tasks.
+.PP
+The individual pset parameters themselves have the same attributes as
+task level parameters. Hidden pset parameters may be altered on the
+command line in the same way as task parameters.
+The only distinction between task level parameters and pset parameters
+is that the latter may be stored in or read from a user defined file.
+
+.NH 2
+Interactive Mode and Non-Interactive Mode
+
+.PP
+The \fBphot\fR task's \fIinteractive\fR parameter
+switches the task between interactive and non-interactive mode.
+.PP
+In interactive mode user instructions in the form of single keystroke
+commands or colon commands are read from the image cursor.
+For example the \fBphot\fR task \fB'i'\fR keystroke command enters the
+interactive setup menu and the \fB'v'\fR keystroke command verifies the
+current parameters. The colon commands are used to show or set any parameter.
+For example, if the user does not like the fact that the full-width
+half-maximum of a star
+as measured with the cursor is 2.5368945 he/she can set it to 2.54 by
+typing \fB:fw 2.54\fR.
+.PP
+In non-interactive mode the input files and images are read,
+the parameters are read from the psets,
+and the output files are written,
+all, with the exception of an optional verification step, without the
+intervention of the user.
+.PP
+The DAOPHOT parameter editing task \fBdaoedit\fR and the photometry catalog
+examining task \fBpexamine\fR are interactive tasks.
+Four other DAOPHOT tasks, \fBdaofind\fR, \fBphot\fR, \fBpstselect\fR,
+and \fBpsf\fR
+have an interactive and a non-interactive mode. The default mode for
+\fBdaofind\fR, \fBphot\fR, and \fBpstselect\fR is non-interactive while
+for \fBpsf\fR
+it is interactive.
+The remaining DAOPHOT tasks are currently non-interactive tasks.
+
+.NH 2
+Image and Graphics Cursor Input
+
+.PP
+All tasks which can be run interactively accept commands from the logical image
+cursor parameter \fIicommands\fR. Logical image cursor commands can
+read from the logical image cursor, \fIicommands\fR = "" or a file,
+\fIicommands\fR = "filename". The logical image cursor is normally
+the physical image cursor and the value of the IRAF environment
+variable \fBstdimcur\fR is normally "stdimage". In cases where the image
+display device is non-existent or cursor read-back is not implemented for
+a particular device the logical image cursor may be reassigned globally to the
+the graphics cursor or the standard input
+by setting the IRAF environment variable \fBstdimcur\fR as follows.
+
+.YS
+da> set stdimcur = "stdimage" (image cursor default)
+
+da> set stdimcur = stdgraph (graphics cursor)
+
+da> set stdimcur = "text" (standard input)
+.YE
+
+If logical image cursor commands are read from the standard input or a
+file, the commands must have the following format
+
+.YS
+[x y wcs] key [cmd]\fR
+.YE
+
+where x and y stand for the x and y position of the image cursor, wcs defines
+the world coordinate system, key is
+a keystroke command, and cmd is an optional user command.
+Quantities in square brackets are optional. The necessity for their
+presence is dictated by the nature of the keystroke command. In the
+case of the \fBphot "i"\fR keystroke described above they are required, whereas
+in the case of the \fBphot "v"\fR keystroke they are not.
+.PP
+Some interactive commands require input from the logical graphics cursor
+parameter \fIgcommands\fR which may be the logical graphics cursor,
+\fIgcommands\fR = "", or a file of graphics cursor commands,
+\fIgcommands\fR = "filename".
+In DAOPHOT the logical graphics cursor must be set to the physical
+graphics cursor and the value of the IRAF environment variable
+\fBstdgcur\fR should be "stdgraph".
+
+.NH 2
+Graphics Output
+
+.PP
+The \fBphot\fR parameters \fIgraphics\fR and \fIdisplay\fR specify the
+default vector graphics and image display graphics devices.
+Vector graphics output is written to the user's
+graphics window, and image
+graphics is overlaid on the user's image display. window
+All interactive vector graphics output is written to
+the device specified by \fIgraphics\fR. An example of this type of graphics
+output is the
+radial profile plot of a star plotted by the \fBphot\fR interactive
+setup menu.
+Image graphics is written to the image display device
+specified by \fIdisplay\fR.
+Examples of this type of output are the optional crosses
+which mark the centers of the stars being measured by \fBphot\fR.
+\fBIRAF does not currently support writing interactive graphics
+to the image display device
+so the display marking features of DAOPHOT are not supported\fR.
+The single exception occurs in the situation
+where the user is running interactively
+off a contour plot as described in the \fBphot\fR help documentation.
+In this case marking will work if
+the parameter \fIdisplay\fR is set to "stdgraph".
+DAOPHOT tasks which reference \fIgraphics\fR or \fIdisplay\fR will, in
+interactive mode, issue
+a warning if they cannot open either or both of these devices,
+and continue execution.
+.PP
+Some DAOPHOT tasks permit the user to save plots of the results
+for each measured star in a plot metacode file.
+For example. if the \fBphot\fR task parameter \fIplotfile\fR is defined,
+then for each star written to \fIoutput\fR
+a radial profile plot is written to the plot metacode file \fIplotfile\fR.
+\fIPlotfile\fR is opened in append mode and succeeding executions
+of \fBphot\fR will write to the end of the same file.
+Users should be aware plotfile can become very large and
+that writing radial profile plots
+to \fIplotfile\fR will greatly slow the execution of \fBphot\fR or any
+other task.
+
+.NH 2
+Verify, Update, and Verbose
+
+.PP
+In non-interactive mode the algorithm parameter values are read from the psets,
+critical parameters are verified if the \fIverify\fR switch is on, and
+updated if both the \fIverify\fR and \fIupdate\fR switches are on.
+The \fIverify\fR and \fIupdate\fR options are also available as
+separate keystroke commands in interactive mode.
+Users must remember to turn off the
+\fIverify\fR switch if they submit a task to the background or the task
+will pause and wait indefinitely for input from the terminal.
+.PP
+In interactive or non-interactive mode a results summary and/or
+error messages are written
+to the standard output if the \fIverbose\fR switch is on.
+Users must remember to redirect
+any verbose output to a file if they submit the task to the background or
+it will be lost.
+
+.NH 2
+Background Jobs
+
+.PP
+Any DAOPHOT task can be run in background by appending an ampersand
+to the end of the command. For example the \fBphot\fR task can be run
+as a background job as shown below.
+
+.YS
+da> phot image image.coo.1 image.mag.1 verbose- verify- &
+.YE
+
+The user must be sure to turn off verbose mode
+and set the verify switch to no. VMS users may have to append a queue
+name after the trailing ampersand.
+If verbose output is desired it can be captured in a file as shown
+in the example below below. The & after the > will ensure that any error
+output is also captured.
+
+.YS
+da> phot image image.coo.1 image.mag.1 verbose+ inter- verify- \\
+ >& listing &
+.YE
+
+.NH 2
+Timing Tests
+
+.PP
+Any DAOPHOT or IRAF task can be timed by prepending a $ sign to the
+command as shown below.
+
+.YS
+da> $phot image image.coo.1 image.mag.1 inter- verify- verbose- &
+.YE
+
+At task termination the computer will print the cpu and elapsed
+time on the terminal.
+.PP
+Care must be taken in using this feature
+to make timing comparisons between hosts or even between runs on the same host,
+as factors like which queue a task is submitted to (VMS), which version of
+the OS the host is running, which version of the compiler
+two programs were compiled under,
+whether the disks are local or networked, and the number of users on the
+machine will effect the elapsed time and/or the cpu time.
+
+.NH
+Doing Photometry with DAOPHOT
+
+.NH 2
+The Test Image
+
+.PP
+Each of the DAOPHOT analysis steps summarized in the following section
+and discussed in detail in succeeding
+sections uses the artificial image stored in fits format in
+the file "daophot$test/fits3.fits" as test data. This image is small,
+51 by 51 pixels, contains 10 stars whose coordinates and magnitudes
+are listed below, has, a mean background level of ~100, poisson noise
+statistics, a gain of 1.0, and a readout noise of 0.0.
+
+.YS
+# Artificial Stars for Image Test
+
+ 41.0 4.0 17.268
+ 23.0 7.0 17.600
+ 18.0 8.0 17.596
+ 26.0 22.0 16.777
+ 36.0 22.0 16.317
+ 8.0 23.0 16.631
+ 31.0 25.0 16.990
+ 21.0 26.0 19.462
+ 29.0 34.0 17.606
+ 36.0 42.0 16.544
+.YE
+
+.PP
+Results for this test image are used to illustrate the text. It is hoped
+that users so inclined will be able to mimic the reductions on
+their host machine. The fact that the image is small, means that
+the tasks execute quickly, it is possible to display all the
+important results in the manual, and it is possible for
+the user to track and examine all the important numbers, something not
+easy with larger images. Users are encouraged to construct more
+challenging artificial images with the ARTDATA package, and to run
+them through DAOPHOT.
+.PP
+All the examples in the following text were run
+under IRAF 2.10.3 on a SPARCstation IPX. Users with different hardware
+may see minor deviations from the output shown here due to machine
+precision differences.
+
+.NH 2
+Typical Analysis Sequence
+
+.PP
+The following sequence of operations summarizes the steps required to analyze
+a crowded stellar field with DAOPHOT.
+.IP [1]
+Create a directory in which to analyze the image and make it the current
+working directory. By default all output photometry and image files
+will be written there.
+.IP [2]
+Read the reduced image into the working directory with the DATAIO package
+task \fBrfits\fR.
+.IP [3]
+Check that the correct exposure time, airmass, filter id, time of
+observation, gain, and readout noise are present and correct
+in the image header with the \fBhselect\fR task. Enter / edit them
+with the \fBhedit\fR task if they are not. Correct the exposure time for
+shutter error, the airmass to mid-exposure, and the gain
+and readout noise to the effective gain and readout noise, using the
+\fBhedit\fR and/or \fBsetairmass\fR tasks.
+.IP [4]
+Edit the DAOPHOT algorithm psets with the interactive \fBdaoedit\fR
+task. The parameters that require editing at this point are:
+1) the numerical parameters
+\fIfwhmpsf\fR (full-width at half-maximum of the point-spread function),
+\fIsigma\fR (standard deviation of the background in counts), \fIdatamin\fR
+(the minimum good data value in counts), \fIdatamax\fR (the maximum good
+data value in counts), and the image header keyword parameters
+\fIccdread\fR, \fIgain\fR, \fIexposure\fR, \fIairmass\fR, \fIfilter\fR,
+and \fIobstimes\fR in the \fBdatapars\fR parameter set,
+2) \fIcbox\fR (the centering box width) in the \fBcenterpars\fR parameter set,
+3) \fIannulus\fR (inner radius of the sky annulus) and
+\fIdannulus\fR (width of the sky annulus) in the \fBfitskypars\fR parameter set,
+4) \fIapertures\fR (radii of the photometry apertures) in the \fBphotpars\fR
+parameter set, and 5) \fIpsfrad\fR (maximum radius of the psf model)
+and \fIfitrad\fR (psf model fitting radius) in the \fBdaopars\fR parameter set.
+.IP [5]
+Create an initial star list using the \fBdaofind\fR task.
+Mark the detected stars on the image display with the \fBtvmark\fR task
+and adjust the \fBfindpars\fR parameter \fIthreshold\fR until
+a satisfactory star list is created.
+.IP [6]
+Compute sky background values and initial magnitudes for
+the detected stars using the \fBphot\fR task and the star
+list written by the \fBdaofind\fR task in step [5].
+.IP [7]
+Create a psf star list using the \fBpstselect\fR task
+and the photometry file written by \fBphot\fR in step [6]. Mark
+the coordinates of the psf stars on the image display with the
+\fBtvmark\fR task
+and edit out any non-stellar objects, stars with
+neighbors within \fIfitrad\fR pixels, or stars with obvious
+cosmetic blemishes, using the \fBpexamine\fR task.
+.IP [8]
+Compute the current psf model using the
+\fBpsf\fR task, the input photometry file written by the \fBphot\fR task
+in step [6], and the psf star list written by the \fBpstselect\fR task
+in step [7].
+.IP [9]
+Fit the current psf model to the psf stars and their neighbors
+using the \fBnstar\fR task, the psf star group photometry file
+written by the \fBpsf\fR task in step [8] or created by the user in step [11],
+and the current psf model written by the \fBpsf\fR task in steps [8] or [13].
+Subtract the fitted psf stars
+and their neighbors from the original image using the \fBsubstar\fR task,
+the photometry file written by the \fBnstar\fR task, and the current
+psf model.
+Display the subtracted image, mark the psf stars and their neighbors
+on the display with the \fBtvmark\fR task,
+and examine the \fBnstar\fR photometry
+file and the subtracted image with the \fBpexamine\fR task.
+If all the psf stars subtract out cleanly and none of them have any
+significant neighbors, skip directly to step [14]. If all the psf stars
+and their neighbors subtract out cleanly, and one or more of the psf
+stars do have significant neighbors, skip directly to step [13].
+.IP [10]
+Reexamine the subtracted image written in step [9]. Remove any psf stars
+revealed by the subtraction to be non-stellar, multiple, or to contain
+cosmetic blemishes,
+from the psf star list written by the \fBpsf\fR task in step
+[8] using the \fBpexamine\fR task.
+If any bad psf stars are detected recompute the psf model by returning to
+step [8] using the newly edited psf star list in place
+of the one written by the previous execution of the \fBpsf\fR task in step [8].
+.IP [11]
+Add any psf star neighbors too faint to be detected by the \fBdaofind\fR
+task in step [5] but bright enough to effect the computation of the
+psf model, to the original psf star group photometry file written
+by the \fBpsf\fR task in step [8],
+by estimating their positions, sky values, and magnitudes interactively
+with the \fBphot\fR task, merging the results with the original psf star group
+photometry file
+using the \fBpfmerge\fR task, and regrouping the stars with the \fBgroup\fR
+task. Refit the newly grouped psf stars and their neighbors using
+the current psf model by returning to step [9],
+replacing the original input group photometry file with the one
+including the new psf star neighbors.
+.IP [12]
+Using the subtracted image written by the \fBsubstar\fR task in step [9],
+note any systematic patterns in the psf star residuals with distance from
+the star (\fIthese indicate a poorly chosen value for the annulus,
+dannulus, function, or psfrad parameters),
+position in the image (\fIthese suggest that the psf is variable
+and that the value of the varorder parameter should be increased\fR),
+or intensity (\fIthis suggests problems with the image data itself, e.g.
+non-linearity\fR). If the problem is in the sky fitting parameters
+edit the appropriate algorithm parameters and return to step [6]. If
+the problem is in the psf modeling and fitting parameters, edit the
+appropriate algorithm parameters and return to step [7]. I the problem
+appears to be in the data or the data reduction procedures, review the
+data taking and reduction history of the image before proceeding.
+.IP [13]
+Subtract the psf star neighbors but not the psf stars from the original
+image using the \fBsubstar\fR task,
+the photometry file written by the \fBnstar\fR task
+in step [9], and the psf star list and current psf model written by
+the \fBpsf\fR task in step [8].
+Recompute the current psf model using
+the psf neighbor star subtracted image, the psf star group photometry file
+written by the \fBpsf\fR task in step [8] or created by the user in step [11],
+and the psf star list written in step [8].
+If the \fIvarorder\fR parameter was changed
+return to step [9].
+Otherwise save the psf star neighbor subtracted image as it may be
+required for computing the image
+aperture correction in step [20], and proceed to step [14].
+.IP [14]
+Fit the final psf model computed in steps [8] or [13]
+to the stars in the photometry file written in
+step [6] using the \fBallstar\fR task.
+.IP [15]
+Run \fBdaofind\fR on the subtracted image produced by \fBallstar\fR in step
+[14] in order to pick up stars missed by the first pass of \fBdaofind\fR in
+step [5].
+.IP [16]
+Run \fBphot\fR on the original image using the new star list produced by
+\fBdaofind\fR in step [15] and the \fBphot\fR algorithm parameters used
+in step [6].
+.IP [17]
+Merge the photometry file produced by \fBallstar\fR in step [14] with
+the one produced by \fBphot\fR in step [16] using the \fBpfmerge\fR
+task.
+.IP [18]
+Rerun \fBallstar\fR on the original image using the merged photometry file
+created in step [17] and the psf model created in steps [8] or [13].
+.IP [19]
+Repeat steps [15]-[18] as required, remembering to run \fBdaofind\fR
+on the subtracted image produced by \fBallstar\fR and \fBphot\fR on the
+original image.
+.IP [20]
+If the psf model is constant, compute the aperture correction for the
+image using the original image and a sample of bright well-isolated stars
+if possible, or the image with
+the psf neighbor stars subtracted if necessary, the
+\fBphot\fR task, and the PHOTCAL package \fBmkapfile\fR task.
+If the psf model is variable, compute the aperture correction by calculating
+the mean magnitude difference, for the psf stars with any
+the neighbors subtracted, between the psf model fitted magnitudes computed
+by the \fBnstar\fR task, and large aperture photometry magnitudes computed
+with the \fBphot\fR task.
+.IP [21]
+Archive the algorithm parameters for the image with the \fBsetimpars\fR task
+and proceed to the next image.
+
+
+.NH 2
+Creating and Organizing an Analysis Directory
+
+.PP
+By default DAOPHOT reads and writes data from and to the current working
+directory. To create and set a new working directory the user must
+execute the commands \fBmkdir\fR and \fBchdir\fR as shown below.
+
+.YS
+da> mkdir testim
+da> chdir testim
+.YE
+
+.PP
+DAOPHOT can in the course of reducing a single image,
+generate a large number of photometry catalogs and output images.
+Users should take a moment to consider how they wish to organize their data
+directories before beginning any DAOPHOT analysis. Some possibilities for data
+directory organization are: 1) by night of observation for standard star fields,
+2) by star field for multi-filter observations of a crowded field, or
+3) by individual image for single filter observations of several fields,
+or any combination of the above.
+
+.NH 2
+Reading the Data
+
+.PP
+DAOPHOT input images are normally read into IRAF from FITS files with
+the DATAIO package task \fBrfits\fR. The following example shows how to
+read the DAOPHOT test image stored in the FITS file "daophot$test/fits3.fits"
+into the IRAF image test.imh.
+
+.YS
+da> rfits daophot$test/fits3.fits 1 test
+File: test Artificial Starfield Size = 51 x 51
+.YE
+
+When IRAF supports FITS format images on disk this step will no longer be
+necessary, although for some images it may still be desirable for
+image i/o efficiency reasons.
+
+.NH 2
+Editing the Image Headers
+
+.NH 3
+The Minimum Image Header Requirements
+
+.PP
+Before beginning DAOPHOT reductions the user must gather
+all the data required to determine the following quantities:
+1) the effective readout noise of the detector in electrons, 2) the effective
+gain of the detector in electrons per count, 3) the maximum good data value
+of the detector in counts, 4) the effective exposure time in any units
+as long as these units are identical for all the images to be analyzed
+together,
+5) the filter id, 6) the effective airmass of the observation at mid-exposure,
+and 7) the time of the observation.
+
+.NH 3
+The Effective Gain and Readout Noise
+
+.PP
+The DAOPHOT package tasks require correct effective
+gain and readout noise values for:
+1) the computation of the magnitude errors in the \fBphot\fR (gain only
+required), \fBpeak\fR, \fBnstar\fR and \fBallstar\fR tasks,
+2) the computation of the optimal weights used by the non-linear
+least-squares fitting code in the \fBpeak\fR, \fBnstar\fR, and
+\fBallstar\fR tasks,
+3) the computation of the predicted signal-to-noise
+ratios in the \fBgroup\fR task,
+4) the computation of the sharpness and chi statistics in the \fBpeak\fR,
+\fBnstar\fR, and \fBallstar\fR tasks, and 5) the correct computation of
+the poisson noise (gain only required) in the \fBaddstar\fR task.
+.PP
+Nominal gain and readout noise values for a single image
+should be obtained from the instrument
+scientist. These values should also be determined/checked empirically with the
+PROTO package task \fBfindgain\fR using bias and flat-field frames that
+are unprocessed and uncoadded so that the noise characteristics of the
+original data are preserved.
+.PP
+If the input image is the sum or average of several frames
+the gain and readout noise values in the image headers must be edited
+from single frame to effective gain and readout noise values
+as shown below. In the following examples
+gain and effective gain are in electrons / ADU,
+readout noise and effective readout noise are in electrons, and N is the
+number of individual frames which
+have been summed, averaged, or medianed to create the input image.
+
+.nf
+ [1]. The image is the sum of N frames
+
+ effective gain = gain
+ effective readout noise = sqrt (N) * readout noise
+
+ [2]. The image is the average of N frames
+
+ effective gain = N * gain
+ effective readout noise = sqrt (N) * readout noise
+
+ [3]. The image is the median of N frames
+
+ effective gain = 2.0 * N * gain / 3
+ effective readout noise = sqrt (2 * N / 3) * readout noise
+.fi
+
+.PP
+The following example shows how to add the correct values of gain and
+readout noise, which in this very artificial example are 1.0 and 0.0
+respectively, to the header of the test image with the \fBhedit\fR task.
+
+.YS
+da> imheader test l+
+test[51,51][real]: Artificial Starfield with Noise
+ No bad pixels, no histogram, min=71.00896, max=535.1335
+ Line storage mode, physdim [51,51], length of user area 163 s.u.
+ Created Mon 09:59:00 17-May-93, Last modified Mon 09:59:00 17-May-93
+ Pixel file 'tucana!/d0/iraf/davis/test.pix' [ok]
+ 'KPNO-IRAF' /
+ '10-05-93' /
+ IRAF-MAX= 5.351335E2 / DATA MAX
+ IRAF-MIN= 7.100896E1 / DATA MIN
+ IRAF-BPX= 32 / DATA BITS/PIXEL
+ IRAFTYPE= 'REAL ' / PIXEL TYPE
+da> hedit test gain 1.0 add+ verify-
+add test,gain = 1.
+test updated
+da> hedit test rdnoise 0.0 add+ verify-
+add test,rdnoise = 0.
+test updated
+da> imheader test l+
+test[51,51][real]: Artificial Starfield with Noise
+ No bad pixels, no histogram, min=71.00896, max=535.1335
+ Line storage mode, physdim [51,51], length of user area 244 s.u.
+ Created Mon 09:59:00 17-May-93, Last modified Mon 09:59:00 17-May-93
+ Pixel file 'tucana!/d0/iraf/davis/test.pix' [ok]
+ 'KPNO-IRAF' /
+ '10-05-93' /
+ IRAF-MAX= 5.351335E2 / DATA MAX
+ IRAF-MIN= 7.100896E1 / DATA MIN
+ IRAF-BPX= 32 / DATA BITS/PIXEL
+ IRAFTYPE= 'REAL ' / PIXEL TYPE
+ GAIN = 1.
+ RDNOISE = 0.\fR
+.YE
+
+.PP
+The following example shows how to correct the single frame
+values of gain and readout noise, already present in the input image
+header, to account for the fact that the input image is actually the
+average of three frames (note that the frames are NOT actually independent
+in this example!).
+
+.YS
+da> imsum test,test,test testav3 option=average
+da> hedit testav3 gain "(3.0*gain)" verify-
+testav3,GAIN: 1. -> 3.
+testav3 updated
+da> hedit testav3 rdnoise "(rdnoise*sqrt(3.0))" verify-
+testav3,RDNOISE: 0. -> 0.
+testav3 updated
+da> imheader testav3 l+
+testav3.imh[51,51][real]: Artificial Starfield with Noise
+ No bad pixels, no histogram, min=unknown, max=unknown
+ Line storage mode, physdim [51,51], length of user area 244 s.u.
+ Created Mon 11:02:22 17-May-93, Last modified Mon 11:02:22 17-May-93
+ Pixel file 'tucana!/d0/iraf/davis/testav3.pix' [ok]
+ 'KPNO-IRAF' /
+ '10-05-93' /
+ New copy of test
+ IRAF-MAX= 5.351335E2 / DATA MAX
+ IRAF-MIN= 7.100896E1 / DATA MIN
+ IRAF-BPX= 32 / DATA BITS/PIXEL
+ IRAFTYPE= 'REAL ' / PIXEL TYPE
+ GAIN = 3.
+ RDNOISE = 0.
+.YE
+
+.NH 3
+The Maximum Good Data Value
+
+.PP
+Datamax is the maximum good data value in counts. Datamax
+is the count level at which the detector saturates or the count
+level at which it becomes non-linear, whichever is lower. DAOPHOT requires
+a correct value of datamax to: 1) identify bad data in the \fBdaofind\fR,
+\fBphot\fR, \fBpsf\fR, \fBpeak\fR, \fBgroup\fR, \fBnstar\fR,
+and \fBallstar\fR tasks, and 2) identify saturated stars in the \fBphot\fR,
+\fBpsf\fR, and \fBsubstar\fR tasks.
+.PP
+Users should be sure to allow adequate leeway for the detector bias level
+in their determination of datamax. Test is an artificial image
+linear over its entire data range. However as an example assume that it was
+actually observed with a detector which is linear from 0 to 25000 counts
+at a gain setting of 1.0, and that the mean bias level that was subtracted
+from the raw data was ~400 counts.
+In that case the user should set datamax to something like 24500 not 25000
+counts.
+.PP
+Datamax may be stored in the image header with \fBhedit\fR
+as shown below. The use of the header keyword gdatamax instead of
+datamax avoids any confusion with the reserved FITS keywords
+datamin and datamax should they already be present in the image header,
+or the IRAF keywords iraf-max and iraf-min which have the same meaning.
+
+.YS
+da> hedit test gdatamax 24500 add+ verify-
+add test,gdatamax = 24500
+test updated
+.YE
+
+.NH 3
+The Effective Exposure Time
+
+.PP
+The exposure time is used by the \fBphot\fR task to normalize the computed
+initial magnitudes to an effective exposure time of one time unit. The
+magnitude scale established in \fBphot\fR is preserved
+in all the subsequent DAOPHOT analysis. Setting the correct exposure
+time in the image headers before beginning DAOPHOT reductions will
+simplify the book-keeping required in the later calibration step
+significantly.
+.PP
+Exposure times should also be corrected
+for any timing errors in the instrument shutter, although this is normally
+important only for short exposure observations of standard stars.
+.PP
+The following example shows how to add the exposure time in seconds
+to the image header, and how to correct it for a known shutter error
+of 13 milli-seconds. Note that rather than overwrite the nominal exposure time
+exptime, the user has chosen to store the corrected exposure time in
+a new keyword cexptime.
+
+.YS
+da> hedit test exptime 1.0 add+ verify-
+add test,exptime = 1.
+test updated
+da> hedit test cexptime "(exptime+.013)" add+ verify-
+add test,cexptime = 1.013
+test updated
+da> imheader test l+
+test[51,51][real]: Artificial Starfield with Noise
+ No bad pixels, no histogram, min=71.00896, max=535.1335
+ Line storage mode, physdim [51,51], length of user area 365 s.u.
+ Created Mon 09:59:00 17-May-93, Last modified Mon 09:59:00 17-May-93
+ Pixel file 'tucana!/d0/iraf/davis/test.pix' [ok]
+ 'KPNO-IRAF' /
+ '10-05-93' /
+ IRAF-MAX= 5.351335E2 / DATA MAX
+ IRAF-MIN= 7.100896E1 / DATA MIN
+ IRAF-BPX= 32 / DATA BITS/PIXEL
+ IRAFTYPE= 'REAL ' / PIXEL TYPE
+ GAIN = 1.
+ RDNOISE = 0.
+ GDATAMAX= 24500
+ EXPTIME = 1.
+ CEXPTIME= 1.013
+.YE
+
+.NH 3
+The Airmass, Filter Id, and Time of Observation
+
+.PP
+The airmass, filter id, and time of observation are not used directly by
+any of the DAOPHOT tasks. They are read from the image header and recorded
+in the output photometry files. Correctly setting the airmass,
+filter id, and the time of observation in the image headers before running
+any DAOPHOT tasks will however significantly reduce the book-keeping
+required in the subsequent calibration step.
+.PP
+The airmass can be computed and/or corrected to mid-exposure with the
+ASTUTIL package task \fBsetairmass\fR. By default \fBsetairmass\fR requires
+that the name of the observatory, date of observation, ra and dec, epoch of
+the ra and dec, sidereal time, and exposure time be recorded
+in the image header in the appropriate units in the keywords
+observat, date-obs, ra, dec, epoch, st, and exptime. Hopefully most or
+all of this information is already in the image header but in case
+it is not, the following example shows how to edit it in and run
+\fBsetairmass\fR.
+
+.YS
+da> hedit test observat "CTIO" add+ verify- show-
+da> hedit test "date-obs" "12/10/88" add+ verify- show-
+da> hedit test ra "(str('21:51:59.0'))" add+ verify- show-
+da> hedit test dec "(str('02:33:31.0'))" add+ verify- show-
+da> hedit test epoch 1985.0 add+ verify- show-
+da> hedit test st "(str('20:47:55.0'))" add+ verify- show-
+da> setairmass test show-
+da> imheader test l+
+test[51,51][real]: Artificial Starfield with Noise
+ No bad pixels, no histogram, min=71.00896, max=535.1335
+ Line storage mode, physdim [51,51], length of user area 649 s.u.
+ Created Mon 09:59:00 17-May-93, Last modified Mon 09:59:00 17-May-93
+ Pixel file 'tucana!/d0/iraf/davis/test.pix' [ok]
+ 'KPNO-IRAF' /
+ '10-05-93' /
+ IRAF-MAX= 5.351335E2 / DATA MAX
+ IRAF-MIN= 7.100896E1 / DATA MIN
+ IRAF-BPX= 32 / DATA BITS/PIXEL
+ IRAFTYPE= 'REAL ' / PIXEL TYPE
+ GAIN = 1.
+ RDNOISE = 0.
+ GDATAMAX= 24500
+ EXPTIME = 1.
+ CEXPTIME= 1.013
+ OBSERVAT= 'CTIO '
+ DATE-OBS= '12/10/88'
+ RA = '21:51:59.0'
+ DEC = '02:33:31.0'
+ EPOCH = 1985.
+ ST = '20:47:55.0'
+ AIRMASS = 1.238106
+.YE
+
+The tortuous syntax required to enter the ra, dec, and st keywords is
+necessary in order to avoid \fBhedit\fR turning strings like
+"21:51:59.0" into numbers,
+e.g. 21.86639. \fBSetairmass\fR permits the user to change the
+default names for the date-obs and exptime image header keywords but
+not those of observat, ra, dec, epoch or st.
+To list the observatories in the IRAF observatory database and/or to find out
+how to deal with the case of data taken at an observatory not in the
+observatory database, the user should consult the help page for the
+\fBobservatory\fR task.
+.PP
+The filter id is a string defining the filter used to take the observations.
+It can be easily edited into the image header as shown below.
+
+.YS
+da> hedit test filters V add+ verify- show-
+.YE
+
+Users should be aware that any embedded blanks will be removed from the
+filter id after it is read from the image header, but before it is
+recorded in the photometry files. For example a filter id of "V band"
+in the image header will become "Vband" in the photometry file.
+.PP
+The time of observation is a string defining the time at which the
+observation was taken. The time of observation may be ut or local
+standard time. If the time of observation is not already recorded in
+the image header it can be entered in the usual fashion as shown below.
+
+.YS
+da> hedit test ut "(str('00:07:59.0'))" add+ verify- show-
+.YE
+
+.PP
+After editing the "final" image header should look something like the
+following.
+
+.YS
+da> imheader test l+
+test[51,51][real]: Artificial Starfield with Noise
+ No bad pixels, no histogram, min=71.00896, max=535.1335
+ Line storage mode, physdim [51,51], length of user area 730 s.u.
+ Created Mon 09:59:00 17-May-93, Last modified Mon 09:59:00 17-May-93
+ Pixel file 'tucana!/d0/iraf/davis/test.pix' [ok]
+ 'KPNO-IRAF' /
+ '10-05-93' /
+ IRAF-MAX= 5.351335E2 / DATA MAX
+ IRAF-MIN= 7.100896E1 / DATA MIN
+ IRAF-BPX= 32 / DATA BITS/PIXEL
+ IRAFTYPE= 'REAL ' / PIXEL TYPE
+ GAIN = 1.
+ RDNOISE = 0.
+ GDATAMAX= 24500
+ EXPTIME = 1.
+ CEXPTIME= 1.013
+ OBSERVAT= 'CTIO '
+ DATE-OBS= '12/10/88'
+ RA = '21:51:59.0'
+ DEC = '02:33:31.0'
+ EPOCH = 1985.
+ ST = '20:47:55.0'
+ AIRMASS = 1.238106
+ FILTER = 'V '
+ UT = '00:07:59.0'\fR
+.YE
+
+
+.NH 3
+Batch Header Editing
+
+.PP
+The previous examples described in detail how to enter each of the required
+keyword and value pairs into the image header using the \fBhedit\fR task.
+Users with large number of header keywords to enter should consider using the
+more batch oriented alternative task \fBasthedit\fR.
+
+
+.NH 2
+Editing, Checking, and Storing the Algorithm Parameters
+
+.NH 3
+The Critical Algorithm Parameters
+
+.PP
+The critical DAOPHOT algorithm parameters that should be set
+before beginning any DAOPHOT analysis are:
+1) the
+full-width at half-maximum of the psf \fIfwhmpsf\fR, the standard
+deviation of the sky background in counts \fIsigma\fR, the minimum and
+maximum good data values \fIdatamin\fR and \fIdatamax\fR, and the image
+header keyword parameters
+\fIccdread\fR, \fIgain\fR, \fIexposure\fR, \fIairmass\fR, \fIfilter\fR,
+and \fIobstimes\fR in the \fBdatapars\fR parameter set,
+2) the default centering algorithm \fIcalgorithm\fR and centering box
+\fIcbox\fR parameters in the \fBcenterpars\fR parameter set, 3) the sky fitting
+algorithm \fIsalgorithm\fR, and the sky annulus \fIannulus\fR and
+\fIdannulus\fR parameters in the \fBfitskypars\fR parameter set,
+4) the \fIapertures\fR parameter in the \fBphotpars\fR parameter set,
+and 5) the psf radius \fIpsfrad\fR
+and fitting radius \fIfitrad\fR parameters in the \fBdaopars\fR parameter set.
+The reamining parameters should be left at their default values, at least
+initially.
+
+.NH 3
+Editing the Algorithm Parameters Interactively with Daoedit
+
+.PP
+The DAOPHOT algorithm parameter editing task is \fBdaoedit\fR. \fBDaoedit\fR
+permits
+the user to edit all the algorithm parameter sets at once. It offers all the
+capabilities of the IRAF parameter editing task \fBepar\fR, plus the
+ability to set parameters using the displayed image and radial
+profile plots of isolated stars.
+.PP
+To run \fBdaoedit\fR the user displays the image, types \fBdaoedit\fR, and waits
+for the image cursor to appear ready to accept user commands. The following
+example summarizes a typical \fBdaoedit\fR parameter editing session.
+
+.YS
+da> display test 1 fi+
+da> daoedit test
+.YE
+
+.IP ...
+Execute the command \fB":epar datapars"\fR and enter the correct
+values for the \fIdatamax\fR parameter, and the image header
+keyword parameters \fIccdread\fR, \fIgain\fR, \fIexposure\fR, \fIairmass\fR,
+\fIfilter\fR, and \fIobstime\fR.
+.IP ...
+Choose a bright isolated star and execute the \fBr\fR cursor
+keystroke command to plot its radial profile.
+.IP ...
+From the information in the radial plot header and the plot
+itself estimate reasonable values for the full-width at
+half-maximum of the psf, the sky level, and the standard
+deviation of the sky level in the image.
+.IP ...
+Repeat the previous step for several stars in order to
+confirm that the original estimated values are reasonable.
+.IP ...
+Execute the \fB":epar datapars"\fR command once more and enter
+the estimated values of the full-width at half-maximum of the psf and
+the standard deviation of the sky background in the \fIfwhmpsf\fR
+and \fIsigma\fR parameters respectively.
+.IP ...
+Set the \fIdatamin\fR parameter to the estimated sky background level
+minus k times the standard deviation of the sky background, where
+k is a number between 5.0 and 7.0.
+
+.IP
+then
+
+.IP ...
+Execute the command \fB":epar centerpars"\fR and set the \fIcbox\fR
+parameter to 5 pixels or ~ 2 * \fIfwhmpsf\fR whichever is
+greater.
+.IP ...
+Execute the command \fB":epar fitskypars"\fR and set the \fIannulus\fR
+parameter to ~ 4 * \fIfwhmpsf\fR and the \fIdannulus\fR parameter to a
+number between 2.5 * \fIfwhmpsf\fR and 4.0 * \fIfwhmpsf\fR.
+.IP ...
+Execute the command \fB":epar photpars"\fR and set the apertures
+parameter to ~ 1.0 * fwhmpsf or 3 pixels whichever is greater.
+.IP ...
+Execute the command \fB":epar daopars"\fR and set the \fIpsfrad\fR
+parameter to ~ 4 * \fIfwhmpsf\fR + 1 and the \fIfitrad\fR parameter to
+~ 1.0 * \fIfwhmpsf\fR or 3 pixels whichever is greater.
+
+.IP
+or alternatively
+
+.IP ...
+Move to a bright star and execute the \fBi\fR cursor keystroke
+command to enter the interactive setup menu.
+.IP ...
+Mark the \fIfwhmpsf\fR, \fIcbox\fR, \fIannulus\fR, \fIdannulus\fR,
+\fIapertures\fR, \fIpsfrad\fR, and \fIfitrad\fR parameters with the
+graphics cursor on the displayed radial profile plot, and verify and/or
+roundoff the marked values.
+.PP
+The following sections discuss in detail how to edit each of the
+parameter sets using the test image as a specific example.
+
+.NH 4
+The Data Dependent Algorithm Parameters
+
+.PP
+A subset of the datapars parameters are used to specify the
+characteristics of the detector, including the saturation or linearity
+limit (\fIdatamax\fR) and noise model (\fIccdread\fR
+and \fIgain\fR), and the parameters of the observation, including
+exposure time (\fIexposure\fR),
+airmass (\fIairmass\fR), filter (\fIfilter\fR), and time of observation
+(\fIobstime\fR).
+.PP
+To edit the \fBdatapars\fR algorithm parameter set
+from within the \fBdaoedit\fR task the user enters the command
+\fB":epar datapars"\fR to invoke the \fBepar\fR task and edits the
+parameters in the usual manner.
+Editing is terminated with the usual \fB":wq"\fR command which returns the
+user to the main \fBdaoedit\fR command loop.
+.PP
+After the appropriate \fIdatamax\fR, \fIccdread\fR, \fIgain\fR,
+\fIexposure\fR, \fIairmass\fR,
+\fIfilter\fR, and \fIobstime\fR parameter values for the
+test image are entered, the \fBdatapars\fR
+parameter should look as follows.
+
+.YS
+Image Reduction and Analysis Facility
+PACKAGE = daophot
+ TASK = datapars
+
+(scale = 1.) Image scale in units per pixel
+(fwhmpsf= 2.5) FWHM of the PSF in scale units
+(emissio= yes) Features are positive ?
+(sigma = 0.) Standard deviation of background in counts
+(datamin= INDEF) Minimum good data value
+(datamax= 24500) Maximum good data value
+(noise = poisson) Noise model
+(ccdread= rdnoise) CCD readout noise image header keyword
+(gain = gain) CCD gain image header keyword
+(readnoi= 0.) CCD readout noise in electrons
+(epadu = 1.) Gain in electrons per count
+(exposur= cexptime) Exposure time image header keyword
+(airmass= airmass) Airmass image header keyword
+(filter = filter) Filter image header keyword
+(obstime= ut) Time of observation image header keyword
+(itime = 1.) Exposure time
+(xairmas= INDEF) Airmass
+(ifilter= INDEF) Filter
+(otime = INDEF) Time of observation
+(mode = ql)
+.YE
+
+.PP
+Users should realize that the values of the parameters \fIreadnoise\fR
+and \fIepadu\fR will be used for the gain and readout noise if the image
+header keywords specified by \fIccdread\fR and \fIgain\fR are not found
+in the image header or cannot be correctly decoded. Similarly the values of
+the \fIitime\fR,
+\fIxairmass\fR, \fIifilter\fR, and \fIotime\fR parameters will be used
+for the exposure time, airmass, filter id, and time of observation if
+the image header keywords specified by \fIexposure\fR, \fIairmass\fR,
+\fIfilter\fR, and \fIobstime\fR are not found in the image header
+or cannot be correctly decoded.
+.PP
+The \fBdatapars\fR parameters \fIfwhmpsf\fR, \fIsigma\fR, and \fIdatamin\fR
+are used to: 1) determine the size of star for which the \fBdaofind\fR star
+detection algorithm is optimized (fwhmpsf), 2) define the \fBdaofind\fR
+algorithm detection threshold for faint objects (sigma),
+3) define the fwhm of the psf for the \fBphot\fR task centering algorithms
+"gauss" and "ofilter" (fwhmpsf),
+4) supply a first guess for the true fwhm of the psf to the psf
+function fitting task \fBpsf\fR (fwhmpsf), 5) determine the
+minimum good data value
+in the \fBdaofind\fR, \fBphot\fR, \fBpsf\fR, \fBpeak\fR, \fBgroup\fR,
+\fBnstar\fR, and \fBallstar\fR tasks (datamin).
+.PP
+Reasonable values for these parameters can be obtained by examining the
+radial profile plots of several isolated stars from within the
+\fBdaoedit\fR task as outlined below:
+
+.IP ...
+Move the image cursor on the displayed image to a
+reasonably bright isolated star (a good candidate is
+the star at pixel 8,23 in the test image) and execute
+the \fBr\fR keystroke command.
+A radial and integrated profile plot of the selected
+star will appear on the screen with the largest photometry aperture radius,
+inner and outer radii of the sky annulus, and median sky level in the sky
+annulus marked on the plot.
+.IP ...
+Assuming that the plot is normal, note the computed
+fwhmpsf (2.6 rounded to the nearest tenth of a pixel for
+the star at 8,23), median sky value (100 counts rounded
+to the nearest count for the star at 8,23), and standard
+deviation of the sky values (10 counts rounded to the
+nearest count for the star at 8,23) written in the plot header.
+These numbers suggest a value of ~50 for datamin (50 is ~5
+standard deviations of the background counts below the
+background count estimate)
+.IP ...
+Edit the estimated values into the datapars pset by
+typing the command \fB":epar datapars"\fR, entering the values,
+and typing \fB":wq"\fR to update the parameter set.
+
+.IP
+or
+
+.IP ...
+Enter them individually using the daoedit colon commands,
+e.g. \fB":fwhmpsf 2.5"\fR, \fB":sigma 10.0"\fR, and \fB":datamin 50.0"\fR.
+.IP ...
+Check the new values of \fIfwhmpsf\fR, \fIsigma\fR, and \fIdatamin\fR
+by doing radial profile plots of several
+other isolated stars (the stars at 36,42 and 41,4 in
+the test image are good test stars).
+.IP ...
+On the basis of the estimated \fIfwhmpsf\fR of these stars change the
+fwhmpsf parameter back to 2.5 with the command
+\fB":fwhmpsf 2.5"\fR.
+.IP ...
+Check that the observed standard deviation of the sky
+background, sigma, agrees reasonably well with the
+predicted value, psigma, based on the median sky level,
+and the effective gain and readout noise of the image.
+For the test image these numbers are related as shown below.
+
+.nf
+ psigma = sqrt (median sky / effective gain +
+ (effective rdnoise / effective gain) ** 2)
+ ~ sqrt (100.0 / 1.0 + (0. / 1.0) ** 2)
+ ~ 10.0
+ ~ sigma
+.fi
+
+.IP ...
+If psigma and sigma are significantly different check
+that the sky region is uncrowded, that the effective
+gain and readout noise values are correct, and that
+earlier reduction procedures have not altered the image
+statistics in some fundamental manner
+
+.PP
+The \fIemission\fR parameter must be left at "yes",
+since DAOPHOT assumes that stars are local maxima not local minima.
+.PP
+The \fInoise\fR parameter must be left at "poisson" since poisson noise
+statistics are assumed throughout the DAOPHOT package.
+.PP
+The \fIscale\fR parameter defines the units in which radial distances
+in the image will be measured. For example if the image scale
+is 0.25 "/pixel, users can set \fIscale\fR to 0.25 if they wish
+to define the \fIfwhmpsf\fR, \fIcbox\fR, \fIannulus\fR, \fIdannulus\fR,
+\fIapertures\fR, \fIpsfrad\fR, \fIfitrad\fR and all the other algorithm
+parameters which are defined in terms of a radial distance in arc-seconds.
+For simplicity most users choose to leave scale set to 1.0 and
+work in pixels.
+.PP
+The final version of the \fBdatapars\fR parameter set should look something
+like the following.
+
+.YS
+Image Reduction and Analysis Facility
+PACKAGE = daophot
+ TASK = datapars
+
+(scale = 1.) Image scale in units per pixel
+(fwhmpsf= 2.5) FWHM of the PSF in scale units
+(emissio= yes) Features are positive ?
+(sigma = 10.) Standard deviation of background in counts
+(datamin= 50.) Minimum good data value
+(datamax= 24500) Maximum good data value
+(noise = poisson) Noise model
+(ccdread= rdnoise) CCD readout noise image header keyword
+(gain = gain) CCD gain image header keyword
+(readnoi= 0.) CCD readout noise in electrons
+(epadu = 1.) Gain in electrons per count
+(exposur= cexptime) Exposure time image header keyword
+(airmass= airmass) Airmass image header keyword
+(filter = filter) Filter image header keyword
+(obstime= obstime) Time of observation image header keyword
+(itime = 1.0) Exposure time
+(xairmas= INDEF) Airmass
+(ifilter= INDEF) Filter
+(otime = INDEF) Time of observation
+(mode = ql)
+.YE
+
+
+.NH 4
+The Centering Algorithm Parameters
+
+.PP
+The \fBcenterpars\fR parameter set controls the centering algorithms used by
+the \fBphot\fR aperture photometry task. DAOPHOT users should concern
+themselves with only two of these parameters, \fIcalgorithm\fR and \fIcbox\fR,
+and leave the remaining \fBcenterpars\fR parameters at their default values.
+.PP
+\fICalgorithm\fR specifies the default \fBphot\fR centering algorithm. Its value
+should be "none" if the input coordinate list is the output of the
+\fBdaofind\fR task, or "centroid", "gauss", or "ofilter" if the input
+coordinate list was
+created with the image or graphics cursor list tasks \fBrimcursor\fR
+or \fBrgcursor\fR or the coordinates are
+read from the image cursor in interactive mode. The choice of centering
+algorithm is not critical since the centers are recomputed using accurate
+non-linear least-squares fitting techniques during the psf fitting
+process. The most efficient and simplest choice is "centroid", although
+more accurate results may be obtained with "gauss" which is
+very similar to the centering algorithm used in \fBdaofind\fR.
+.PP
+The \fIcbox\fR
+parameter determines the width in scale units of the data used to compute
+the center if \fIcalgorithm \fR is not "none".
+For reasonable results \fIcbox\fR should be set to the equivalent of 5 or
+~ 2 * \fIfwhmpsf\fR in pixels whichever is larger.
+.PP
+\fBCenterpars\fR can be edited from within the \fBdaoedit\fR task
+with the command \fB":epar centerpars"\fR. After editing, the \fBcenterpars\fR
+parameter set should look like the example below. Note that for the test
+image \fIfwhmpsf\fR is ~2.5 pixels so \fIcbox\fR is left at 5.0.
+
+.YS
+PACKAGE = daophot
+TASK = centerpars
+
+(calgori= none) Centering algorithm
+(cbox = 5.) Centering box width in scale units
+(cthresh= 0.) Centering threshold in sigma above background
+(minsnra= 1.) Minimum signal-to-noise ratio
+(cmaxite= 10) Maximum iterations
+(maxshif= 1.) Maximum center shift in scale units
+(clean = no) Symmetry clean before centering
+(rclean = 1.) Cleaning radius in scale units
+(rclip = 2.) Clipping radius in scale units
+(kclean = 3.) K-sigma rejection criterion in skysigma
+(mkcente= no) Mark the computed center
+(mode = ql)
+.YE
+
+.NH 4
+The Sky Fitting Algorithm Parameters
+
+.PP
+The \fBfitskypars\fR parameter set controls the sky fitting algorithm
+parameters used by the \fBphot\fR task. At this point DAOPHOT users should
+concern themselves with only three of these parameters: \fIsalgorithm\fR,
+\fIannulus\fR, and \fIdannulus\fR.
+.PP
+Users should realize that the \fBphot\fR task computes sky values
+for the individual stars, and that these values are
+used in the \fBpsf\fR task to compute the psf, averaged to form a group sky
+value in the \fBpeak\fR, \fBnstar\fR and \fBallstar\fR tasks if sky refitting
+is disabled (the default) or an initial sky value if sky refitting
+is enabled, and used
+to compute the predicted signal-to-noise ratios in the \fBgroup\fR task.
+Although the option to refit the skies at a later stage of analysis exists,
+there are difficulties associated with this choice. It is
+in the user's best interest to determine the skies as accurately as
+possible as early as possible, since sky determination will probably be
+the single most important factor in doing good photometry.
+.PP
+In cases where contamination of the sky region is mostly due
+to crowding by neighboring stars users should use the default sky fitting
+algorithm "mode"; if the variations in the background are due instead
+to nebulosity or large contaminating objects so that the sky statistics are
+confused
+"median", "centroid", or "crosscor" might be a better choice; in cases
+where the sky statistics
+are so poor that the histogram is aliased, undersampled, or sparse such
+as might be the case with
+very low sky backgrounds "mean" might be the best choice.
+When in doubt about the correct choice the user should leave \fIsalgorithm\fR
+at "mode" but examine the results carefully for accuracy at each step.
+.PP
+A good starting value for the inner radius of the sky annulus is ~ 4 *
+\fIfwhmpsf\fR
+or ~ 10 pixels for the test image. The width of the sky annulus should be
+sufficient to give a reasonable sample of sky pixels, >= 5 pixels. We have
+chosen a dannulus of ~4 * \fIfwhmpsf\fR or 10 pixels for the test image.
+.PP
+\fBFitskypars\fR can be edited from within the \fBdaoedit\fR task
+with the command \fB":epar fitskypars"\fR. After editing the \fBfitskypars\fR
+parameter set should look like the example below.
+
+.YS
+PACKAGE = daophot
+TASK = fitskypars
+
+(salgori= mode) Sky fitting algorithm
+(annulus= 10.) Inner radius of sky annulus in scale units
+(dannulu= 10.) Width of sky annulus in scale units
+(skyvalu= 0.) User sky value
+(smaxite= 10) Maximum number of sky fitting iterations
+(sloclip= 0.) Lower clipping factor in percent
+(shiclip= 0.) Upper clipping factor in percent
+(snrejec= 50) Maximum number of sky fitting rejection iteratio
+(sloreje= 3.) Lower K-sigma rejection limit in sky sigma
+(shireje= 3.) Upper K-sigma rejection limit in sky sigma
+(khist = 3.) Half width of histogram in sky sigma
+(binsize= 0.1) Binsize of histogram in sky sigma
+(smooth = no) Boxcar smooth the histogram
+(rgrow = 0.) Region growing radius in scale units
+(mksky = no) Mark sky annuli on the display
+(mode = ql)
+.YE
+
+.NH 4
+The Aperture Photometry Parameters
+
+.PP
+The \fBphotpars\fR parameter set controls the aperture photometry algorithm
+parameters used by the \fBphot\fR task. At this point DAOPHOT users should
+concern themselves with only one of these, \fIapertures\fR, the radius
+of the aperture through which the initial magnitudes will be computed.
+A good rule of thumb is to set the aperture radius to the maximum
+of 3 pixels or 1.0 * \fIfwhmpsf\fR pixels. Although magnitudes can be measured
+through more than one aperture at a time, it is the magnitude of the
+smallest aperture radius along with \fIzmag\fR and the exposure time
+which set the DAOPHOT instrumental magnitude scale, and
+the magnitudes through the other apertures contribute nothing to the
+DAOPHOT analysis until it comes time to compute accurate aperture
+corrections. Therefore it is in the user's best interest to set \fIapertures\fR
+to a single value at this point and carefully record it.
+.PP
+\fBPhotpars\fR can be edited from within the \fBdaoedit\fR task
+with the command \fB":epar photpars"\fR. After editing the \fBphotpars\fR
+parameter set should look like the example below. Note that in this example
+\fIfwhmpsf\fR is ~2.5 pixels so \fIapertures\fR is left at 3.0.
+
+.YS
+PACKAGE = daophot
+TASK = photpars
+
+(weighti= constant) Photometric weighting scheme
+(apertur= 3.0) List of aperture radii in scale units
+(zmag = 25.) Zero point of magnitude scale
+(mkapert= no) Draw apertures on the display
+(mode = ql)
+.YE
+
+.NH 4
+The Psf Modeling and Fitting Parameters
+
+.PP
+The \fBdaopars\fR parameter set controls the psf computation, star grouping,
+and psf fitting
+parameters used by the \fBpstselect\fR, \fBpsf\fR, \fBpeak\fR,
+\fBgroup\fR, \fBnstar\fR,
+\fBallstar\fR, \fBsubstar\fR, and \fBaddstar\fR tasks. At this point
+DAOPHOT users should
+concern themselves with only two of these parameters \fIpsfrad\fR, the radius
+over which the psf will be defined, and \fIfitrad\fR, the radius
+over which the psf will be fit to the individual stars. A good rule of thumb is
+to set \fIpsfrad\fR to the radius at which the radial profile of the brightest
+star of interest disappears into the noise plus 1, something like
+~ 4 * \fIfwhmpsf\fR + 1, and
+to set \fIfitrad\fR to the maximum of 3 pixels or ~ 1 * \fIfwhmpsf\fR in pixels.
+
+.PP
+\fBDaopars\fR can be edited from within the daoedit task
+with the command \fB":epar daopars"\fR. After editing the \fBdaopars\fR
+parameter set should look something like the example below for the
+test image.
+
+.YS
+PACKAGE = daophot
+TASK = daopars
+
+(functio= gauss) Analytic component of psf
+(varorde= 0) Order of psf variation
+(nclean = 0) Number of cleaning passes
+(saturat= no) Use wings of saturated stars
+(matchra= 3.) Matching radius in scale units
+(psfrad = 11.) Radius of psf in scale units
+(fitrad = 3.) Fitting radius in scale units
+(recente= yes) Recenter stars during fit
+(fitsky = no) Recompute group sky value during fit
+(sannulu= 0.) Inner radius of sky annulus in scale units
+(wsannul= 11.) Width of sky annulus in scale units
+(flaterr= 0.75) Flat field error in percent
+(proferr= 5.) Profile error in percent
+(maxiter= 50) Maximum number of iterations
+(clipexp= 6) Data clipping exponent
+(clipran= 2.5) Data clipping range in sigma
+(critove= 1.) Critical overlap group for membership
+(maxnsta= 10000) Maximum number of stars to fit
+(maxgrou= 60) Maximum number of stars to fit per group
+(mode = ql)
+.YE
+
+.NH 4
+Setting the Algorithm Parameters Graphically
+
+.PP
+Each of the radial distance dependent parameters \fIfwhmpsf\fR,
+\fIcbox\fR, \fIannulus\fR, \fIdannulus\fR, \fIapertures,\fR,
+\fIpsfrad\fR, \fIfitrad\fR can be edited
+individually and interactively by marking the current radial profile
+plot with the
+graphics cursor after executing the appropriate keystroke command.
+For example the \fBf\fR keystroke command will prompt the user to
+mark the fwhm of
+the psf on the current radial profile plot,
+verify the marked value, and update the \fIfwhmpsf\fR parameter.
+.PP
+All the radial distance dependent parameters listed above
+can be edited at once my moving the
+image cursor to a bright star, typing the \fB daoedit i\fR keystroke command
+to invoke the interactive graphics setup menu.
+The size of the radial profile plot and the sky regions
+are set by the \fIscale\fR, \fIannulus\fR, and \fIdannulus\fR parameters.
+The centering algorithm
+used is always "centroid" regardless of the value of the \fIcalgorithm\fR
+parameter, \fIcbox\fR and \fIscale\fR determine the centering box size,
+and the photometry is computed inside the largest aperture specified by
+the \fIapertures\fR parameter. After the user finishes marking all the
+parameters on the plot
+he/she is given an opportunity to verify or edit the results, e.g., change the
+value for fwhmpsf from 2.536 as read from the graphics cursor to 2.5.
+
+.NH 3
+Checking the Algorithm Parameters with Daoedit
+
+.PP
+The purpose of setting all the critical algorithm parameters to reasonable
+values before beginning any DAOPHOT analysis, is to ensure that the user
+gets off to a good start. Although setting the parameters to unreasonable
+values often results in bizarre results which are immediately obvious,
+e.g., the detection of thousands of
+noise spikes, the problems can sometimes be more subtle.
+For example, a sky annulus that is too close to the star will result in
+measured sky values which are too high and poor subtractions of
+the fitted stars which may not be discovered until the user has
+become thoroughly exasperated trying to produce good fits to the psf
+stars.
+.PP
+The current DAOPHOT algorithm parameters can be checked at any time with
+the \fBdaoedit\fR task and the \fB":lpar"\fR command. For example the
+\fBdatapars\fR parameters set can be listed with the \fBdaoedit
+":lpar datapars"\fR command. The remaining parameters sets \fBfindpars\fR,
+\fBcenterpars\fR, \fBfitskypars\fR, \fBphotpars\fR, and \fBdaopars\fR
+may be listed in the same way.
+.PP
+When listing the algorithm parameters users should check that:
+.IP [1]
+the \fBdatapars\fR image header keyword parameters \fIccdread\fR, \fIgain\fR,
+\fIexposure\fR, \fIairmass\fR, \fIfilter\fR, and \fIobstime\fR are
+properly set.
+.IP [2]
+the \fBdatapars\fR \fIfwhmpsf\fR, \fIsigma\fR, \fIdatamin\fR, and \fIdatamax\fR parameters
+are appropriate for the image. Be especially careful of datamin as the
+correct value for this parameter varies with the mean sky.
+.IP [3]
+the \fBdatapars\fR parameter \fIscale\fR is 1.0 unless the user is
+thoroughly aware of the meaning of this parameter and the consequences
+of setting it to something other than 1.0, and \fIemission\fR is "yes".
+.IP [4]
+the \fBcenterpars\fR \fIcbox\fR parameter is
+appropriate for the image and the remaining \fBcenterpars\fR parameters
+are at their default values unless the user
+really understands the consequences of altering these parameters.
+.IP [5]
+the \fBfitskypars\fR \fIannulus\fR, and \fIdannulus\fR
+parameters are appropriate for the image and the remaining \fBfitkskypars\fR
+parameters are at their default values unless the user really
+understands the consequences of altering these parameters.
+.IP [6]
+the \fBphotpars\fR \fIapertures\fR parameter is appropriate for the image
+and the remaining parameters are at their default values unless the user
+really understands the consequences of altering these parameters.
+.IP [6]
+the \fBdaopars\fR \fIpsfrad\fR and \fIfitrad\fR parameters are appropriate
+for the image and all the remaining \fBdaopars\fR parameters are at their
+default values unless the user really understands the consequences of
+altering these parameters.
+
+.NH 3
+Storing the Algorithm Parameter Values with Setimpars
+
+.PP
+The current values of all the algorithm parameters for a particular
+image may be saved in a file on disk at any
+point in the reduction sequence by executing the \fBsetimpars\fR task.
+The following command saves the current values of the parameters for
+the test image in a file called "test.pars".
+
+.YS
+da> setimpars test no yes
+.YE
+
+Repeating the previous command at any point in the reduction sequence will
+replace the stored parameter values with the current parameter values.
+
+
+.NH 3
+Restoring the Algorithm Parameter Values with Setimpars
+
+.PP
+At some point the user may wish to interrupt work on a particular image and
+begin work on a different image. This should be no problem as long as the
+user remembers to save the algorithm parameter sets with \fBsetimpars\fR
+as described in the previous section.
+.PP
+The command to restore the algorithm parameter sets for the test image is:
+
+.YS
+da> setimpars test yes no
+.YE
+
+or
+
+.YS
+da> setimpars test yes no parfile=test.pars
+.YE
+
+
+.NH 2
+Creating a Star List
+
+.PP
+The initial input to the DAOPHOT package is a star list.
+Star lists may be created with the DAOPHOT package task \fBdaofind\fR,
+interactively with the image or graphics cursor (the
+\fBrimcursor\fR and \fBrgcursor\fR tasks), by another IRAF task, or by
+any user program which writes a text file in the correct format.
+.PP
+Legal star lists are text files containing a list of stars, one star
+per line with the x and y coordinates in columns one and two.
+Blank lines, lines beginning with "#", and lines containing anything other
+than numbers in columns one and two are ignored.
+A sample DAOPHOT star list is shown below.
+
+.YS
+# Artificial Stars for Image Test
+
+ 41.0 4.0 17.268
+ 23.0 7.0 17.600
+ 18.0 8.0 17.596
+ 26.0 22.0 16.777
+ 36.0 22.0 16.317
+ 8.0 23.0 16.631
+ 31.0 25.0 16.990
+ 21.0 26.0 19.462
+ 29.0 34.0 17.606
+ 36.0 42.0 16.544
+.YE
+
+.NH 3
+The Daofind Task
+
+.PP
+The \fBdaofind\fR task, searches for point sources
+in an image whose peak intensities are above some user-defined threshold,
+computes approximate centers, magnitudes, and
+shape characteristics for all the detected objects, and writes the results
+to the output star list.
+
+.NH 4
+The Daofind Algorithm
+
+.PP
+By default the \fBdaofind\fR algorithm performs the following steps:
+.IP[1]
+reads the \fBdaofind\fR task parameters, including the input image
+and output star list names and the \fBdatapars\fR and \fBfindpars\fR
+algorithm parameters, and asks the user to verify the
+\fIfwhmpsf\fR, \fIsigma\fR,
+\fIthreshold\fR, \fIdatamin\fR, and \fIdatamax\fR parameters
+.IP[2]
+calculates the convolution kernel whose mathematical function when
+convolved with the input image is to
+compute the amplitude of the best-fitting Gaussian of
+full-width half-maximum \fIfwhmpsf\fR at each point in the input image
+.IP[3]
+convolves the input image with the convolution kernel after
+eliminating bad data with the \fIdatamin\fR and \fIdatamax\fR parameters,
+and writes the results to a temporary convolved image
+.IP[4]
+searches for local maxima in the convolved image whose amplitudes are greater
+than the detection threshold, and greater than the amplitudes of any neighbors
+within a region the size of the convolution kernel
+.IP[5]
+computes approximate centers, magnitudes, and shape
+statistics for these local maxima
+.IP[6]
+eliminates local maxima whose centers are outside the image, and whose
+sharpness and roundness statistics are outside the limits set by the user
+.IP[7]
+writes the centers, approximate magnitudes, sharpness and roundness
+statistics, and id number for the remaining local maxima, to the
+output star list
+.IP[8]
+deletes the convolved image
+
+.NH 4
+The Daofind Algorithm Parameters
+
+.PP
+The critical \fBdaofind\fR algorithm parameters are \fIfwhmpsf\fR,
+\fIdatamin\fR, \fIdatamax\fR, \fIsigma\fR, and \fIthreshold\fR.
+These parameters are verified at startup time by \fBdaofind\fR.
+.PP
+The \fIfwhmpsf\fR parameter should be close
+to the true full-width at half-maximum of the psf in order
+to optimize the detection algorithm for stellar objects. If \fIfwhmpsf\fR
+is too far from the true value, stars may be omitted from the star list
+and/or non-stellar objects added to it.
+.PP
+The \fIdatamin\fR and \fIdatamax\fR parameters are used to flag and remove
+bad data from the convolved image.
+If \fIdatamin\fR and \fIdatamax\fR are
+too far from the true value stars may be omitted from the star list
+and/or non-stellar objects added to it.
+.PP
+The \fIsigma\fR parameter should be close to the true standard deviation of
+the sky background in an uncrowded region of the frame. This parameter
+in combination with \fIthreshold\fR
+determines the detection threshold in counts for faint objects. If it is
+incorrect either too few or too many objects will be detected.
+.PP
+The \fIthreshold\fR parameter should normally be set to some small
+number between 3.0 and 5.0. If threshold is too big only
+the brightest stars will be detected. If threshold is too small too
+many noise spikes will be detected.
+
+.NH 4
+Running Daofind Non-Interactively
+
+.PP
+The following example shows how to run \fBdaofind\fR in non-interactive mode.
+
+.YS
+da> daofind test default
+
+FWHM of features in scale units (2.5) (CR or value):
+ New FWHM of features: 2.5 scale units 2.5 pixels
+Standard deviation of background in counts (10.) (CR or value):
+ New standard deviation of background: 10. counts
+Detection threshold in sigma (4.) (CR or value):
+ New detection threshold: 4. sigma 40. counts
+Minimum good data value (50.) (CR or value):
+ New minimum good data value: 50. counts
+Maximum good data value (24500.) (CR or value):
+ New maximum good data value: 24500. counts
+
+Image: test.imh fwhmpsf: 2.5 ratio: 1. theta: 0. nsigma: 1.5
+
+ 40.97 4.02 -1.663 0.612 0.017 1
+ 23.06 7.03 -1.214 0.636 -0.019 2
+ 18.02 7.96 -1.318 0.622 0.010 3
+ 25.99 22.01 -2.167 0.658 0.001 4
+ 35.98 22.00 -2.499 0.572 -0.039 5
+ 8.02 22.97 -2.239 0.550 0.068 6
+ 30.97 25.01 -1.934 0.711 -0.044 7
+ 28.96 33.92 -1.087 0.418 0.132 8
+ 35.98 42.03 -2.332 0.639 0.108 9
+
+threshold: 40. relerr: 1.140 0.2 <= sharp <= 1. -1. <= round <= 1.\fR
+.YE
+
+If this is the first time \fBdaofind\fR has been run the results will appear
+in the file "test.coo.1".
+.PP
+The detected objects can be marked on the image display using the
+\fBtvmark\fR task as shown below.
+
+.YS
+da> display test 1 fi+
+da> tvmark 1 test.coo.1 col=204
+.YE
+
+In this example the detected stars will be marked on the displayed image
+as red dots. If too many faints stars have been missed the user
+can rerun \fBdaofind\fR with a lower value of the \fIthreshold\fR
+parameter.
+
+.NH 4
+Running Daofind Interactively
+
+.PP
+\fBDaofind\fR may also be run in interactive mode.
+Most users will only exercise this option for small images which do not
+require long cpu/elapsed times to perform the convolution.
+.PP
+The following example shows how to run \fBdaofind\fR interactively.
+
+.YS
+da> display test 1 fi+
+
+da> daofind test default inter+
+.YE
+
+.IP ...
+Type the \fBv\fR keystroke command to verify the critical algorithm
+parameters.
+.LP
+
+.YS
+FWHM of features in scale units (2.5) (CR or value):
+ New FWHM of features: 2.5 scale units 2.5 pixels
+Standard deviation of background in counts (10.) (CR or value):
+ New standard deviation of background: 10. counts
+Detection threshold in sigma (4.) (CR or value):
+ New detection threshold: 4. sigma 40. counts
+Minimum good data value (50.) (CR or value):
+ New minimum good data value: 50. counts
+Maximum good data value (24500.) (CR or value):
+ New maximum good data value: 24500. counts
+.YE
+
+.IP ...
+Type the \fBspacebar\fR keystroke command to detect the objects and write them
+out to the star list file.
+.LP
+
+.YS
+Image: test.imh fwhmpsf: 2.5 ratio: 1. theta: 0. nsigma: 1.5
+
+ 40.97 4.02 -1.663 0.612 0.017 1
+ 23.06 7.03 -1.214 0.636 -0.019 2
+ 18.02 7.96 -1.318 0.622 0.010 3
+ 25.99 22.01 -2.167 0.658 0.001 4
+ 35.98 22.00 -2.499 0.572 -0.039 5
+ 8.02 22.97 -2.239 0.550 0.068 6
+ 30.97 25.01 -1.934 0.711 -0.044 7
+ 28.96 33.92 -1.087 0.418 0.132 8
+ 35.98 42.03 -2.332 0.639 0.108 9
+
+threshold: 40. relerr: 1.140 0.2 <= sharp <= 1. -1. <= round <= 1.
+
+Output file: test.coo.1
+.YE
+
+.IP ...
+Change \fIthreshold\fR to 3.0 with the colon command \fB:threshold 3.0\fR.
+.IP ...
+Type the \fBspacebar\fR keystroke command to detect the objects and write
+them out to a new star list file.
+.LP
+
+.YS
+Image: test.imh fwhmpsf: 2.5 ratio: 1. theta: 0. nsigma: 1.5
+
+ 40.97 4.02 -1.975 0.577 0.017 1
+ 23.06 7.03 -1.526 0.604 -0.019 2
+ 18.02 7.96 -1.631 0.587 0.010 3
+ 25.99 22.01 -2.480 0.626 0.001 4
+ 35.98 22.00 -2.811 0.537 -0.039 5
+ 8.02 22.97 -2.551 0.515 0.068 6
+ 30.97 25.01 -2.246 0.681 -0.044 7
+ 21.27 25.94 -0.146 0.804 -0.558 8
+ 28.96 33.92 -1.400 0.379 0.132 9
+ 35.98 42.03 -2.645 0.606 0.108 10
+
+threshold: 30. relerr: 1.140 0.2 <= sharp <= 1. -1. <= round <= 1.
+
+Output file: test.coo.2
+.YE
+
+.IP ...
+Change \fIthreshold\fR to 5.0 with the colon command \fB:threshold 5.0.
+.IP ...
+Type the \fBspacebar\fR keystroke command to detect the objects and write them
+out to a new coordinate file.
+.LP
+
+.YS
+Image: test.imh fwhmpsf: 2.5 ratio: 1. theta: 0. nsigma: 1.5
+
+ 40.97 4.02 -1.420 0.577 0.017 1
+ 23.06 7.03 -0.972 0.604 -0.019 2
+ 18.02 7.96 -1.076 0.587 0.010 3
+ 25.99 22.01 -1.925 0.626 0.001 4
+ 35.98 22.00 -2.257 0.537 -0.039 5
+ 8.02 22.97 -1.997 0.515 0.068 6
+ 30.97 25.01 -1.692 0.681 -0.044 7
+ 28.96 33.92 -0.845 0.379 0.132 8
+ 35.98 42.03 -2.090 0.606 0.108 9
+
+threshold: 50. relerr: 1.140 0.2 <= sharp <= 1. -1. <= round <= 1.
+
+Output file: test.coo.3
+.YE
+
+.IP ...
+Type the \fBq\fR keystroke, first in the image display window then the
+text window to quit the task.
+.LP
+
+If this is the first run of \fBdaofind\fR,
+the three star list files for the \fIthreshold\fR values of
+4.0, 3.0, and 5.0 will be written to "test.coo.1", "test.coo.2", and
+"test.coo.3" respectively.
+.PP
+The \fBdaofind\fR results for different thresholds can be evaluated by
+marking the detected objects on the image display using the \fBtvmark\fR
+task and different
+colors for each threshold. In the following example objects detected
+at threshold=3.0 are marked in red, at threshold=4.0 in green, at threshold=
+5.0 in blue.
+
+.YS
+da> display test 1 fi+
+da> tvmark 1 test.coo.2 col=204 point=3
+da> tvmark 1 test.coo.1 col=205 point=3
+da> tvmark 1 test.coo.3 col=206 point=3
+.YE
+
+Note that the identical stars were detected at thresholds 4.0 and 5.0 but
+the faint star at 21,26 was only detected at threshold=3.0.
+.PP
+In this example the user decides that threshold = 4.0 is the
+"best" threshold, sets the \fIthreshold\fR parameter appropriately as shown
+below, and deletes the the star lists for threshold = 3.0 and threshold = 5.0.
+
+.YS
+da> findpars.threshold = 4.0
+da> delete test.coo.2,test.coo.3
+.YE
+
+.NH 4
+The Daofind Output
+
+.PP
+The quantities xcenter, ycenter, mag, sharpness, roundness, and id
+are recorded for each detected object. Each is described briefly below.
+.IP [1]
+\fIXcenter\fR and \fIycenter\fR are the coordinates of
+the detected object in fractional pixel units. They are computed by
+fitting one-dimensional Gaussian functions of full-width at half-maximum
+\fIfwhmpsf\fR to the x and y marginal pixel distributions centered on
+the star. The computed coordinates can be overlaid on the
+displayed image with the \fBtvmark\fR command.
+.IP [2]
+The estimated magnitude is measured relative to the detection threshold
+and is defined as
+
+.YS
+mag = -2.5 * log10 (density / (relerr * threshold * sigma))
+.YE
+
+where density is the peak density of the object in the convolved image,
+relerr an internally
+computed factor measuring the amount by which the standard error in one pixel
+in the input image must be multiplied to obtain the standard error
+in one pixel in the convolved image, and threshold and sigma
+are the values of the corresponding \fIthreshold\fR and \fIsigma\fR
+parameters. For stellar
+objects the computed magnitude is directly proportional to the true
+magnitude of the star. Stars with a peak density exactly equal to
+the detection threshold will have a magnitude of 0.0. The remaining
+stars will have negative magnitudes.
+.IP [3]
+The sharpness statistic is the ratio of the amplitude of the best fitting
+delta function at the position of a detected object to the amplitude of
+the best fitting gaussian at the same position as shown below.
+
+.YS
+sharpness = (data - <data>) / density
+.YE
+
+The amplitude of the best fitting gaussian is simply the density
+of the detected object in the convolved image.
+The amplitude of the best fitting delta function is defined
+as corresponding original image data value minus the average of all
+the neighboring
+pixels in the image <data>. Typical values of sharpness are of ~0.6 for
+approximately gaussian stars and \fInsigma\fR = 1.5.
+Hot pixels will have sharpness values >> 1 and cold pixels will have
+sharpness values
+of ~0, hence reasonable limits for the \fIsharphi\fR and \fIsharplo\fR
+parameters are 1.0 and 0.2 respectively.
+Increasing the size of convolution box defined by the
+\fInsigma\fR parameter from its default value of 1.5 to a larger value
+(smaller values should be avoided !) while keeping the \fIfwhmpsf\fR the
+same, will increase the average value of the sharpness statistic because
+more pixels further from the center of the star are included in the
+computation of <data>. If \fInsigma\fR is changed
+the \fBfindpars\fR parameters \fIsharphi\fR and \fIsharplo\fR
+will also need to be changed.
+.IP [4]
+The roundness statistic is computed by fitting a one-dimensional
+gaussian function of full-width at half-maximum \fIfwhmpsf\fR to the
+x and y marginal pixel distributions.
+
+.YS
+roundness = 2.0 * (hx - hy) / (hx + hy)
+.YE
+
+hx and hy are the heights of the best fitting one-dimensional
+gaussians in x and y. A totally
+round object will have a roundness of ~ 0.0. If the object is very
+elongated in x roundness will be a large negative number; a large positive
+number if it is elongated in y. The roundness statistic is
+effective at filtering out bad columns and rows of data. It is not
+effective at filtering out objects elongated at intermediate angles.
+.IP [5]
+Id is a sequence number which identifies the star.
+
+.NH 4
+Examining the Daofind Output
+
+.PP
+The easiest way to check that \fBdaofind\fR is performing correctly is to mark
+the detected stars on the image display with \fBtvmark\fR.
+.PP
+If the marked image suggests that \fBdaofind\fR is detecting too few or
+too many stars the first items to check are the the values of the
+\fIsigma\fR and \fIthreshold\fR parameters since these parameters determine the
+detection threshold. Sigma should be
+the standard deviation of the sky pixels in an uncrowded region of the image.
+Threshold should normally be some number between 3.0 and 5.0. If sigma
+and threshold are reasonable the user should compare the observed value of
+sigma with the predicted value derived from the median background level and the
+effective gain and readout noise values. If there is a significant
+mismatch in these numbers the user should check the reduction history of the
+image. The number of spurious detections goes up dramatically for
+thresholds less than ~3.0 * sigma. A plot of number
+of detections versus threshold will show a change in slope at some point below
+this threshold. Users who wish to detect faint objects while keeping
+spurious detections at a manageable minimum should
+set the detection threshold to a value just above the threshold at
+which this change in slope occurs.
+.PP
+Users should also check the values of the
+parameters \fIsharplo\fR, \fIsharphi\fR,
+\fIroundlo\fR, and \fIroundhi\fR parameters to ensure that
+detected objects are not being unfairly filtered out. In particular the values
+of \fIsharplo\fR and \fIsharphi\fR should be changed if the \fInsigma\fR
+parameter is changed.
+.PP
+Finally the user should check
+the \fIfwhmpsf\fR, \fInsigma\fR, \fIdatamin\fR and \fIdatamax\fR parameters
+for correctness since these parameters control the computation of the
+convolution kernel and the density enhancement image.
+.PP
+Histograms of the various columns in the \fBdaofind\fR output can be
+plotted using the \fBpdump\fR and \fBphistogram\fR tasks. The following
+example shows how to plot a histogram of the magnitudes.
+
+.YS
+da> pdump test.coo.1 mag yes | phistogram STDIN binwidth=.1
+.YE
+
+The various columns can also be plotted against each other.
+The following example shows how to plot magnitude error versus magnitude.
+
+.YS
+da> pdump test.coo.1 mag,merr yes | graph point+
+.YE
+
+.PP
+By setting the \fBdaofind\fR \fIstarmap\fR and \fIskymap\fR parameters the
+user can save and examine the density enhancement image and the corresponding
+background density image. The sum of these two images should yield a
+close representation of the original image except for regions of
+bad data and edge pixels. Due to the nature of the convolution kernel
+the starmap image will have a mean value of
+~0.0 in the sky regions, an rms \(~= relerr * sigma in the sky regions,
+and positive peaks of intensity surrounded by negative valleys at the positions
+of bright stars. The skymap image will have a mean value \(~= sky in
+the sky regions, an rms \(~= sqrt (sigma ** 2 / N + K * (relerr * sigma) ** 2),
+(N is the number of pixels in the gaussian kernel and K is the average power
+in the gaussian kernel), and dips in intensity surrounded by
+bright rings at the position of the stars.
+
+.NH 3
+Rgcursor and Rimcursor
+
+.PP
+The LISTS package tasks \fBrimcursor\fR and \fBrgcursor\fR can be used to
+generate coordinate lists interactively. For example a coordinate
+list can be created using the image display and the image display cursor
+as shown below.
+
+.YS
+da> display test 1 fi+
+
+da> rimcursor > test.coo
+.YE
+
+.IP ...
+Move cursor to stars of interest and tap the space bar.
+.IP ...
+Type <EOF> to terminate the list.
+
+.PP
+A coordinate list can also be created using a contour plot and the graphics
+cursor as shown below.
+
+.YS
+da> contour test
+
+da> rgcursor > test.coo
+.YE
+
+.IP ...
+Move the cursor to the stars of interest and tap the space bar.
+.IP ...
+Type <EOF> to terminate the list.
+
+.PP
+In both cases the text file "test.coo" contains the x and y coordinates of
+the marked stars in image pixel units. The output of \fBrimcursor\fR or
+\fBrgcursor\fR can
+be read directly by the DAOPHOT \fBphot\fR task.
+
+.NH 3
+User Program
+
+.PP
+Any user program which produces a text file with the stellar coordinates
+listed one per line with x and y in columns 1 and 2, can be used to produce
+DAOPHOT coordinate files which can be read by the \fBphot\fR task.
+
+.NH 3
+Modifying an Existing Coordinate List
+
+.PP
+The LISTS package routine \fBlintran\fR
+can be used to perform simple coordinate transformations on
+coordinate lists including shifts, magnifications, and rotations.
+
+.NH 2
+Initializing the Photometry with Phot
+
+.PP
+The \fBphot\fR task computes initial centers,
+sky values, and initial magnitudes for all the objects in the input
+star list. The centers and magnitudes are used as starting
+values for the non-linear
+least-squares psf computation and fitting routines in the \fBpsf\fR,
+\fBpeak\fR, \fBnstar\fR, and \fBallstar\fR tasks, and to estimate
+signal-to-noise
+values in the \fBgroup\fR task. The individual sky values
+computed by \fBphot\fR are used directly by the \fBpsf\fR task to compute
+the psf model, by the
+\fBpeak\fR, \fBnstar\fR,
+and \fBallstar\fR tasks to compute the group sky values, and by the
+\fBgroup\fR task to estimate signal-to-noise ratios.
+
+.NH 3
+The Phot Algorithm
+
+.PP
+By default the \fBphot\fR task performs the following functions:
+.IP [1]
+reads in the \fBphot\fR task parameters including the input image name,
+the input coordinate file name, the output photometry file name,
+the \fBdatapars\fR, \fBcenterpars\fR, \fBfitskypars\fR, and \fBphotpars\fR
+algorithm parameters, and determines whether the task mode of operation
+is interactive or non-interactive
+.IP [2]
+reads in the initial coordinates of a star from the coordinate list and/or
+the image cursor, and computes new coordinates for the star using the centering
+algorithm defined by the \fIcalgorithm\fR parameter (if \fIcalgorithm\fR
+is not "none") using data in a box whose size is defined by the \fIcbox\fR
+parameter
+.IP [3]
+computes the sky value for the star using the default algorithm
+specified by the \fIsalgorithm\fR parameter and the data in an annulus of
+pixels defined by the \fIannulus\fR and \fIdannulus\fR parameters
+.IP [4]
+computes the instrumental magnitude and magnitude error for each star
+inside the aperture radii
+specified by the \fIapertures\fR parameter using fractional pixel techniques,
+the computed sky value, the standard deviation of the sky pixels, and the
+gain of the CCD
+.IP [6]
+sets the instrumental magnitude scale for the image using the
+\fBphotpars\fR \fIzmag\fR parameter and the exposure time specified by
+the \fBdatapars\fR \fIexposure\fR or \fIitime\fR parameters
+.IP [7]
+sets the magnitude(s) to INDEF for stars which are saturated or contain
+bad data,
+for which the aperture is partially off the image, for which a sky
+value could not be computed, or for which the
+signal is fainter than the background
+.IP [8]
+writes the results to the output photometry file
+
+.NH 3
+The Phot Algorithm Parameters
+
+.PP
+The critical \fBphot\fR algorithm parameters are \fIcalgorithm\fR,
+\fIsalgorithm\fR,
+\fIannulus\fR, \fIdannulus\fR, \fIapertures\fR, \fIdatamin\fR and
+\fIdatamax\fR. These parameters are verified by \fBphot\fR
+at startup time.
+.PP
+The \fIcalgorithm\fR parameter tells \fBphot\fR how to compute
+centers for the objects in the coordinate list. Calgorithm should be "none"
+if the coordinate
+list was computed by \fBdaofind\fR or the coordinates are known to
+be precise; otherwise calgorithm should one of "centroid", "gauss", or
+"ofilter". "centroid" is quick and sufficiently accurate in most cases;
+"gauss" and "ofilter" take longer but are more accurate. If calgorithm is
+not "none",
+\fBphot\fR will ask the user to verify the centering box size
+\fIcbox\fR. \fIcbox\fR should be set to 5 or ~2 * \fIfwhmpsf\fR pixels wide
+whichever is greater.
+.PP
+The \fIsalgorithm\fR parameter tells \fBphot\fR how to compute the sky
+values. If the
+fluctuations in the sky background are due primarily to crowding the
+default choice
+"mode" should be used. If the fluctuations in the sky background
+are due to nebulosity or large galaxies
+and the sky statistics are confused, "median", "centroid" or
+"crosscor" might be the best choice. In cases where the
+background is very low and the sky histogram is sparse or
+undersampled "mean" might be the best choice.
+.PP
+The \fIannulus\fR and \fIdannulus\fR parameters tell \fBphot\fR the
+position of the sky annulus with respect to the star. The sky region
+must be far enough away from the star to avoid contamination from
+the star itself, but close enough
+to be representative of the intensity distribution under the star. Values of
+~ 4.0 * \fIfwhmpsf\fR for both parameters are good starting values.
+.PP
+The \fIapertures\fR parameter tells \fBphot\fR the radius of the
+photometry aperture. The photometry through this aperture sets the
+instrumental magnitude scale for all the subsequent DAOPHOT
+reductions. \fIApertures\fR should be ~ 1.0 * \fIfwhmpsf\fR.
+.PP
+The \fIdatamin\fR and \fIdatamax\fR parameters are used to detect
+bad data in the photometry and sky apertures. Bad data is removed from
+the sky pixel list before sky fitting takes place so it is important
+that datamax and datamin, but particularly datamin, be correct.
+Stars which have bad data in the photometry apertures will have their
+magnitudes set to INDEF and be flagged with an error.
+
+.NH 3
+Running Phot Non-interactively
+
+.PP
+The following example shows how to run \fBphot\fR in non-interactive
+mode using the results of \fBdaofind\fR as input.
+
+.YS
+da> phot test default default
+
+Centering algorithm (none) (CR or value):
+ New centering algorithm: none
+Sky fitting algorithm (mode) (CR or value):
+ Sky fitting algorithm: mode
+Inner radius of sky annulus in scale units (10.) (CR or value):
+ New inner radius of sky annulus: 10. scale units 10. pixels
+Width of the sky annulus in scale units (10.) (CR or value):
+ New width of the sky annulus: 10. scale units 10. pixels
+File/list of aperture radii in scale units (3.0) (CR or value): 3.0
+ Aperture radius 1: 3. scale units 3. pixels
+Minimum good data value (50.) (CR or value):
+ New minimum good data value: 50. counts
+Maximum good data value (24500.) (CR or value):
+ New maximum good data value: 24500. counts
+
+test 40.97 4.02 100.7955 17.218 ok
+test 23.06 7.03 100.3257 17.650 ok
+test 18.02 7.96 99.40262 17.484 ok
+test 25.99 22.01 101.3196 16.800 ok
+test 35.98 22.00 101.1601 16.373 ok
+test 8.02 22.97 98.89139 16.603 ok
+test 30.97 25.01 101.2904 17.051 ok
+test 28.96 33.92 100.6189 17.782 ok
+test 35.98 42.03 101.043 16.594 ok
+
+.YE
+
+\fBPhot\fR looks for an input star list called "test.coo.?",
+creates a file called "test.mag.?", and verifies
+the critical parameters. By default the verbose switch is set to "yes",
+so a short summary of the results for each star is printed on the
+terminal as it is computed.
+.PP
+\fBPhot\fR may also be run non-interactively from a coordinate list created
+with the image cursor list task \fBrimcursor\fR as shown below. Note
+that centering has been turned on, and the verify switch has been turned off.
+
+.YS
+da> display test 1 fi+
+
+da> rimcursor > cursor.coo
+
+da> page cursor.coo
+
+41.02 4.033 101 \040
+22.918 6.969 101 \040
+18.123 7.849 101 \040
+25.951 21.939 101 \040
+35.736 21.744 101 \040
+ 7.947 23.016 101 \040
+30.843 24.777 101 \040
+28.984 33.779 101 \040
+36.127 41.705 101 \040
+
+da> phot test cursor.coo default calg=centroid verify-
+
+test 40.92 4.04 100.8871 17.222 ok
+test 23.17 6.97 100.6163 17.666 ok
+test 18.04 7.92 99.55305 17.487 ok
+test 25.96 21.97 101.4161 16.801 ok
+test 35.94 21.98 101.2101 16.373 ok
+test 8.05 23.00 98.74371 16.601 ok
+test 30.94 25.02 101.3224 17.052 ok
+test 28.91 33.85 100.6207 17.786 ok
+test 35.96 42.08 100.9039 16.591 ok\fR
+.YE
+
+The "centroid" algorithm
+computes a new center by doing an intensity-weighted sum of the
+x and y marginals, whereas the \fBdaofind\fR algorithm
+fits a 1D gaussian to the marginal pixel distributions in x and y.
+The following example shows the results for the almost equivalent
+\fBphot\fR centering algorithm "gauss".
+
+.YS
+da> phot test cursor.coo default calg=gauss verify-
+
+test 41.00 4.03 100.8698 17.219 ok
+test 23.11 7.03 100.3567 17.653 ok
+test 18.02 7.96 99.40262 17.484 ok
+test 25.98 21.97 101.4021 16.801 ok
+test 35.96 21.99 101.2101 16.373 ok
+test 8.02 22.98 98.77907 16.601 ok
+test 30.97 25.02 101.2904 17.051 ok
+test 28.93 33.94 100.6726 17.783 ok
+test 35.97 42.02 100.976 16.593 ok\fR
+.YE
+
+The positions produced by the "gauss" algorithm are closer to
+the positions computed by the \fBdaofind\fR task,
+than those computed by the "centroid" algorithm.
+However as the positions computed by \fBphot\fR are used as initial
+positions by the DAOPHOT tasks,
+it is usually not necessary to go to the more expensive "gauss" algorithm.
+
+.NH 3
+Running Phot Interactively
+
+.PP
+\fBPhot\fR can also be configured to run interactively using the
+image display and image
+cursor for coordinate input. In this mode the user loads the image
+into the display and runs
+\fBphot\fR interactively by turning the interactive switch on as
+shown below.
+When the program is ready to accept input the cursor will begin
+blinking in the display window. The following series of steps will
+do photometry on stars selected with the image cursor.
+
+.YS
+da> display test 1 fi+
+
+da> phot test "" default interactive+ calgorithm=centroid
+.YE
+
+.IP ...
+Execute the \fBv\fR keystroke command to verify the critical parameters.
+.LP
+
+.YS
+Centering algorithm (centroid) (CR or value):
+ New centering algorithm: centroid
+Centering box width in scale units (5.) (CR or value):
+ New centering box width: 5. scale units 5. pixels
+Sky fitting algorithm (mode) (CR or value):
+ Sky fitting algorithm: mode
+Inner radius of sky annulus in scale units (10.) (CR or value):
+ New inner radius of sky annulus: 10. scale units 10. pixels
+Width of the sky annulus in scale units (10.) (CR or value):
+ New width of the sky annulus: 10. scale units 10. pixels
+File/list of aperture radii in scale units (3.) (CR or value):
+ Aperture radius 1: 3. scale units 3. pixels
+Standard deviation of background in counts (10.) (CR or value):
+ New standard deviation of background: 10. counts
+Minimum good data value (50.) (CR or value):
+ New minimum good data value: 50. counts
+Maximum good data value (24500.) (CR or value):
+ New maximum good data value: 24500. counts
+.YE
+
+.IP ...
+Move the cursor to the stars of interest and tap the \fBspacebar\fR to do
+the photometry.
+.LP
+
+.YS
+test 40.92 4.04 100.8871 17.222 ok
+test 23.17 6.97 100.6163 17.666 ok
+test 18.04 7.92 99.55305 17.487 ok
+test 25.96 21.97 101.4161 16.801 ok
+test 35.94 21.98 101.2101 16.373 ok
+test 8.05 23.00 98.74371 16.601 ok
+test 30.94 25.02 101.3224 17.052 ok
+test 28.91 33.85 100.6207 17.786 ok
+test 35.96 42.08 100.9039 16.591 ok
+.YE
+
+.IP ...
+Type \fBq\fR to quit image, and \fBq\fR again to exit task.
+.LP
+
+The coordinate file name has been set to "" so that initial
+positions for the stars to be measured will be read from the image
+cursor, and the centering algorithm has been temporarily changed
+on the command line
+from "none" to "centroid" so that new centers will be computed.
+The user simply points the cursor to the stars to be measured and taps the
+space bar to measure the star. This option is often useful for
+picking up stars missed by \fBdaofind\fR in a previous iteration,
+or in cases where the user only wishes to measure a small group of stars.
+
+.NH 3
+The Phot Output
+
+.PP
+\fBPhot\fR produces a large output file containing many parameters,
+intermediate and final results. The principle
+quantities of interest are: 1) the position
+of the star xcenter and ycenter, 2) the sky value,
+its standard deviation, and the number of pixels used to compute
+it, msky, stdev, and nsky 3) the total
+counts inside the aperture and the effective area of the aperture,
+sum and area 4) the magnitude and magnitude error in the
+aperture, mag and merr,
+and 5) the exposure time, airmass, filter, and time of observation, itime,
+xairmass, ifilter, and otime.
+.IP [1]
+\fIXcenter\fR and \fIycenter\fR are the computed coordinates for
+the detected objects in fractional pixels. They can be overlaid on the
+displayed image with the \fBtvmark\fR command. These numbers should be compared
+with the initial coordinates xinit and yinit, to which they will be equal
+if the centering algorithm was "none", or to which they should be close
+if the centering algorithm is "centroid", "gauss", or "ofilter" assuming
+that the original x and y positions were reasonable.
+.IP [2]
+\fIMsky\fR, \fIstdev\fR and \fInsky\fR are the estimated sky value in counts,
+its standard deviation in counts, and the number of pixels used to compute it.
+Users should, check that the position of the sky annulus is reasonable
+and, check that the msky, stdev, and nsky values are reasonable
+for a few isolated stars before proceeding.
+.IP [3]
+\fISum\fR and \fIarea\fR are the total counts (star + sky) in the
+photometry aperture and area is area of the aperture in pixels squared
+and should be roughly
+equal to PI * r ** 2 where r is the radius of the photometry aperture
+in pixels.
+.IP [4]
+\fIMag\fR and \fImerr\fR are the magnitude and magnitude error respectively
+computed as follows.
+
+.YS
+ mag = zmag - 2.5 * log10(sum - area * msky) + 2.5 * log10(itime)
+
+merr = 1.0857 * sqrt((sum - area * msky) / gain + area * stdev ** 2
+ + area ** 2 * stdev ** 2 / nsky) / (sum - area * msky)
+.YE
+
+Users should check that the exposure time \fIitime\fR is correct since it
+is used to determine the instrumental magnitude scale. The correct value
+of gain is also required in order to get a correct estimate of the
+magnitude error. Stdev is the observed standard deviation
+of the sky pixels not the predicted value.
+.IP [5]
+The remaining quantities itime, \fIxairmass\fR, \fIifilter\fR, and \fIotime\fR
+should be checked for correctness, e.g., were they read correctly from the image
+header.
+
+.NH 3
+Examining the Results of Phot
+
+.PP
+The user can check the results of \fBphot\fR in several
+ways. The following command will mark all
+stars in the \fBphot\fR output file on the display in red.
+
+.YS
+da> display test 1
+da> pdump test.mag.1 xcenter,ycenter yes | tvmark 1 STDIN col=204
+.YE
+
+The following command will mark all the stars whose magnitudes are INDEF on
+the screen in green.
+
+.YS
+da> pdump test.mag.1 xcenter,ycenter "mag == INDEF" | tvmark \\
+ 1 STDIN col=205
+.YE
+
+The following command will plot magnitude error versus magnitude for all
+the stars in the photometry file.
+
+.YS
+da> pdump test.mag.1 mag,merr yes | graph STDIN point+
+.YE
+
+The following command will plot a histogram of the magnitude distribution.
+
+.YS
+da> pdump test.mag.1 mag,merr yes | phist STDIN plot_type=box
+.YE
+
+The photometry file can be examined interactively with the \fBpexamine\fR
+task as shown below.
+
+.YS
+da> pexamine test.mag.1 "" test
+.YE
+.IP ...
+A vector plot of magnitude error versus magnitude appears on the screen.
+.IP ...
+To examine individual stars in the vector plot move the graphics cursor to a
+star and type \fBo\fR to get a record listing for the star,
+followed by \fBr\fR, \fBc\fR, or \fBs\fR to see a radial profile plot,
+contour plot, or surface plot respectively, of the star.
+.IP ...
+To activate the image cursor type \fBi\fR, move the cursor to a star
+and type \fBo\fR to get a record listing
+for the star, followed by \fBr\fR, \fBc\fR or \fBs\fR to draw the desired plot.
+To reactivate the graphics cursor type \fBg\fR.
+.IP ...
+To plot magnitude error versus x coordinate for all the stars in the file, type
+\fB:xcolumn xcenter\fR and \fB:ycolumn merr\fR followed by \fBp\fR to
+redraw the plot.
+.IP ...
+To plot a histogram of the magnitudes of the objects type \fBh\fR.
+.IP ...
+Type \fBq\fR to quit.
+
+.NH 2
+Creating a Psf Star List with Pstselect
+
+.PP
+The psf model fitting routines require a list of bright isolated stars
+well distributed over the image to use as psf model templates.
+The \fBpstselect\fR
+task is used to select suitable candidate stars from the photometry file
+for input to the psf modeling task \fBpsf\fR.
+
+.NH 3
+The Pstselect Algorithm
+
+.PP
+By default the \fBpstselect\fR task performs the following functions:
+.IP[1]
+reads the task parameters including the input image name, input
+photometry file, and output psf star list, reads the \fBdatapars\fR
+and \fBdaopars\fR algorithm parameters, and determines whether the
+task will be run interactively or non-interactively
+.IP [2]
+reads the dimensions of the input image from the input image header, and
+the ids, x and y coordinates, magnitudes, and sky values of up to
+\fImaxnstar\fR stars from the input photometry file
+.IP [2]
+assigns a large negative number to the magnitudes of all stars whose
+measured magnitudes are INDEF in the input photometry file
+.IP [3]
+sorts the stars in order of increasing magnitude so that
+the saturated and brightest stars are at the beginning of the list
+.IP [4]
+selects the
+brightest \fImaxnpsf\fR stars (where maxnpsf is a number chosen by the user)
+which are, not saturated, more than \fIfitrad\fR pixels away from the edge
+of the input image, have no bad data within \fIfitrad\fR pixels,
+and have no brighter neighbor stars within
+(\fIpsfrad\fR + \fIfitrad\fR + 2) pixels
+.IP [5]
+writes the ids, x and y coordinates, magnitudes, and sky values
+of the selected stars as read from the input photometry list
+to the output psf star list
+
+.NH 3
+The Pstselect Algorithm Parameters
+
+.PP
+The critical \fBpstselect\fR algorithm parameters are \fIpsfrad\fR,
+\fIfitrad\fR, \fIdatamin\fR, and \fIdatamax\fR.
+.PP
+\fIPsfrad\fR and \fIfitrad\fR are used by \fBpstselect\fR to eliminate
+potential psf stars which have bright neighbors.
+For the test image these parameters are currently set
+to 4 * \fIfwhmpsf\fR + 1 and 1 * \fIfwhmpsf\fR or 11 and 3 pixels respectively.
+However as \fBpstselect\fR is the first task to actually use the values
+of these parameters, the user should
+check them here one more time before running \fBpstselect\fR.
+\fIFitrad\fR should be ~ 1 * \fIfwhmpsf\fR
+for optimal psf model computation and fitting so the user leaves it
+at its current value of 3.0. \fIPsfrad\fR should be set to the radius at which
+the profile of the brightest stars of interest disappear into the
+noise. Normally 4 * \fIfwhmpsf\fR + 1 pixels is a good starting value for
+this quantity.
+If \fIpsfrad\fR is too small the fitted stars will not subtract completely
+from the input image, if it is too big DAOPHOT
+will consume cpu time doing unnecessary data extractions
+and subtractions.
+One way to check the value of the \fIpsfrad\fR parameter is to
+use the \fBdaoedit\fR task to examine
+radial profiles of isolated stars in the input image as shown below.
+
+.YS
+da> display test 1 fi+
+
+da> daoedit test
+.YE
+
+.IP ...
+Move cursor to star at 36,42 and press the \fBr\fR key.
+.IP ...
+Examine the resulting radial profile and note that the stellar profile
+disappears into the noise at ~4 pixels.
+.IP ...
+Move the cursor to the star at 8,23 and press the \fBr\fR key.
+.IP ...
+Examine the radial profile and note that this stellar profile
+also disappears into the noise at ~4 pixels.
+.IP ...
+Set \fIpsfrad\fR to 5.0 pixels by typing the command \fB:psfrad 5.0\fR.
+.IP ...
+Type \fBq\fR to quit the \fBdaoedit\fR task.
+.YE
+
+.PP
+The \fBpexamine\fR task and the input photometry file can also be
+used to examine the radial profiles of isolated stars in the
+photometry file.
+
+.YS
+da> display test 1 fi+
+
+da> pexamine test.mag.1 "" test
+.YE
+
+.IP ...
+A plot of magnitude error versus magnitude appears on the screen.
+.IP ...
+Type \fBi\fR to activate the image cursor.
+.IP ...
+Move the cursor to the star at 36,42 and type \fBr\fR, adjust the
+outer radius of the plot with the command \fB:router\fR if necessary,
+e.g., \fB:router 10\fR.
+.IP ...
+Examine the radial profile and note that it disappears into the noise at a
+radius of ~4 pixels.
+.IP ...
+Move the cursor to the star at 8,23 and type \fBr\fR.
+.IP ...
+Examine the radial profile and note that that it
+also disappears into the noise at a radius of ~4 pixels.
+.IP ...
+Type \fBq\fR to quit the pexamine task.
+.LP
+
+The new value of \fIpsfrad\fR can be stored by editing the \fBdaopars\fR
+parameter set with \fBepar\fR in the usual manner or on the command
+line as shown below.
+
+.YS
+da> daopars.psfrad = 5.0
+.YE
+
+.PP
+Why is the value of 5.0 pixels for \fBpsfrad\fR so different from the
+original estimate of 11.0 ?
+There are two reasons. Firstly the stars in artificial image
+test are quite faint,
+with the brightest peaking at ~400 counts above background. Their stellar
+profiles disappear into the noise quite quickly. Secondly the artificial
+stars are gaussian in shape with a sigma \(~= 1.0 pixels.
+Unlike real stars they have almost all their light
+in the core and none in the wings. For realistic optical images
+11.0 pixels rather than 5.0 would be a more reasonable choice
+for \fIpsfrad\fR than 5.0.
+.PP
+The \fIdatamin\fR and \fIdatamax\fR parameters are used to reject
+psf stars with bad data within \fIfitrad\fR pixels.
+If \fIdatamin\fR and \fIdatamax\fR are set correctly before
+the \fBphot\fR task is run, these parameters are redundant as stars
+with bad data inside the photometry aperture will have INDEF magnitudes.
+.PP
+At this point the user should check that the current value of the
+\fImaxnstar\fR parameter is larger than the total number of stars
+in the photometry file written by the \fBphot\fR task. If \fImaxnstar\fR
+is too small, \fBpstselect\fR cannot read the entire input photometry
+file into memory and potential psf stars may be missed.
+
+.NH 3
+How Many Psf Stars Should Be Selected ?
+
+.PP
+How many stars should the user select to create the psf model ?
+An absolute minimum
+set by the mathematics is 1 star for a constant psf model,
+3 stars for a linearly variable psf model, and
+6 stars for a quadratically variable psf model. A more reasonable minimum
+suggested by Stetson (1992) is 3 stars
+per degree of freedom or,
+3 stars for a constant psf model, 9 stars for a linearly variable psf model,
+and 18 stars for a quadratically variable psf model. If a variable psf model
+is required, it is vitally important that the psf star list
+sample the region of interest in the input image completely and
+reasonably uniformly.
+As the contribution of each psf star to the psf model is weighted by
+its signal-to-noise, the psf stars may cover a range in magnitude without
+compromising the resulting psf model.
+
+.NH 3
+Running Pstselect Non-interactively
+
+.PP
+The following example shows how to run the \fBpstselect\fR task
+in non-interactive mode.
+
+.YS
+da> pstselect image default default 3
+
+Psf radius in scale units (5.):
+ New psf radius: 5. scale units 5. pixels
+Fitting radius in scale units (3.):
+ New fitting radius: 3. scale units 3. pixels
+Minimum good data value (50.) (CR or value):
+ New minimum good data value: 50. counts
+Maximum good data value (24500.) (CR or value):
+ New maximum good data value: 24500. counts
+
+Star 5 has been added to the PSF star list
+ X: 35.98 Y: 22.00 Mag: 16.372 Dmin: 82.96088 Dmax: 535.1335
+Star 9 has been added to the PSF star list
+ X: 35.98 Y: 42.03 Mag: 16.594 Dmin: 80.25255 Dmax: 489.9732
+Star 6 has been added to the PSF star list
+ X: 8.02 Y: 22.97 Mag: 16.603 Dmin: 71.00896 Dmax: 436.3393
+
+Total of 3 PSF stars selected\fR
+.YE
+
+By default \fBpstselect \fR looks for an input photometry file called
+"test.mag.?" and writes an output psf star list called
+"test.pst.?".
+
+.NH 3
+Running Pstselect Interactively
+
+.PP
+\fBPstselect\fR may also be run interactively. In this mode of operation
+the stars selected
+by \fBpstselect\fR are examined by the user and accepted or rejected on
+the basis of the appearance of their mesh, contour or radial profile plots
+until a total of \fImaxnpsf\fR psf stars is reached.
+Stars from the input photometry file which do not meet the
+\fBpstselect\fR task selection criteria,
+can be added to the psf star list by the user with the image cursor
+until a total of \fImaxnpsf\fR psf stars have been selected.
+.PP
+The following example shows how to run \fBpstselect\fR in interactive
+mode.
+
+.YS
+da> pstselect image default default 3 inter+ plottype=radial
+
+Psf radius in scale units (5.):
+ New psf radius: 5. scale units 5. pixels
+Fitting radius in scale units (3.):
+ New fitting radius: 3. scale units 3. pixels
+Minimum good data value (50.) (CR or value):
+ New minimum good data value: 50. counts
+Maximum good data value (24500.) (CR or value):
+.YE
+
+.IP ...
+The image cursor appears on the screen ready to accept user input.
+.IP ...
+Type \fBn\fR to display the first potential psf star found by
+\fBpstselect\fR, \fBa\fR to select the star, or \fBd\fR to delete it.
+.IP ...
+Repeat the previous step for 2 more stars.
+.IP ...
+Type \fBl\fR to list the selected psf stars.
+.IP ...
+Type \fBq\fR to quit the task.
+
+.PP
+By default \fBpstselect \fR looks for an input photometry file called
+"test.mag.?" and writes an output psf star list called
+"test.pst.?" as before.
+
+.NH 3
+The Pstselect Output
+
+.PP
+The output psf star list consists of the ids, x and y coordinates,
+magnitudes, and sky values of the selected psf stars copied from the
+input photometry file without change.
+
+.NH 3
+Examining and/or Editing the Results of Pstselect
+
+.PP
+The \fBpdump\fR and \fBtvmark\fR commands can be used to mark
+and label the selected psf stars on the image display as shown in the
+following example.
+
+.YS
+da> display test 1 fi+
+da> pdump test.pst.1 xcenter,ycenter,id yes | tvmark 1 STDIN \\
+ col=204 label+\fR
+.YE
+
+Bad stars can be removed from the psf star list using the displayed and
+labeled image and
+the text editor, the \fBpselect\fR task, or
+the \fBpexamine\fR task.
+.PP
+The following command shows how to create a new psf star list
+without the psf star whose id is "5" using the \fBpselect\fR task.
+
+.YS
+da> pselect test.pst.1 test.pst.2 "id != 5"\fR
+.YE
+
+.PP
+The same operation can be accomplished using the \fBpexamine\fR task
+as shown below.
+
+.YS
+da> pexamine test.pst.1 test.pst.2 test
+.YE
+
+.IP ...
+A message appears on the screen to the affect that
+pexamine cannot plot x versus y since the default y
+column merr is not in the input file.
+.IP ...
+The user types \fBh\fR to plot a histogram of the magnitudes
+and notes that there are three stars in the histogram.
+.IP ...
+The user decides that the star with id number 5 marked on the
+display should be deleted because it is too crowded.
+.IP ...
+The user types the \fBi\fR key to bring up the image cursor, moves
+it to star number 5, types the \fBd\fR key to delete the star, and
+the \fBp\fR key to replot the data.
+.IP ...
+The user types the \fBf\fR key to make the deletions permanent and the \fBe\fR
+key to exit the task, and update the output catalog.
+.LP
+
+Finally the user marks the new list on the display image using a
+different marking color.
+
+.YS
+da> pdump test.pst.2 xcenter,ycenter,id yes | tvmark 1 STDIN \\
+ col=205 label+
+.YE
+.LP
+
+.NH 2
+Computing the Psf Model with Psf
+
+.PP
+The \fBpsf\fR task computes the psf model used by the
+\fBpeak\fR, \fBnstar\fR, and \fBallstar\fR tasks to do psf fitting
+photometry, by the \fBgroup\fR task to estimate magnitudes for stars
+whose initial magnitudes are INDEF, and by the \fBaddstar\fR and
+\fBsubstar\fR tasks to add stars to and subtract stars from an image.
+
+.NH 3
+The Psf Algorithm
+
+.PP
+By default the \fBpsf\fR task performs the following functions:
+.IP [1]
+reads the \fBpsf\fR task parameters including, the input image name,
+the input photometry file name, the input psf star list name,
+the output psf image name,
+the output psf star list name, the output psf star group file name, and
+the \fBdatapars\fR and \fBdaopars\fR algorithm parameters
+.IP [2]
+reads the ids, x and y coordinates, magnitudes, and sky values
+of the first \fImaxnstar\fR stars in the input photometry file
+.IP [3]
+reads the ids, x and y coordinates, magnitudes, and sky values
+of the candidate psf stars from the input psf star list and/or
+the image cursor, rejecting stars
+which are not in the input photometry file, are within \fIfitrad\fR pixels
+of the edge of the image, are saturated (if
+the parameter \fIsaturated\fR is "no"),
+or have bad data within \fIfitrad\fR pixels
+.IP [4]
+computes the analytic component of the psf model
+specified by the parameter \fIfunction\fR using, data within \fIfitrad\fR
+pixels of each psf star, weights proportional to the signal-to-noise
+ratio in each psf star, and non-linear least-squares fitting techniques
+.IP [5]
+computes the residuals of each psf star from the best fit analytic function
+within a radius of \fIpsfrad\fR + 2 pixels
+.IP [6]
+scales the residuals for each psf star to match the intensity of the first
+psf star, subsamples the scaled residuals in x and y by a factor of 2,
+weights the residuals by the signal-to-noise ratio of the psf star,
+and combines the scaled, subsampled, and weighted residuals
+to create 0, 1, 3, or 6, depending on the \fIvarorder\fR parameter,
+psf model look-up tables
+.IP [7]
+repeats steps [5] and [6] \fInclean\fR times, down-weighting the contributions
+to the psf model look-up table(s) of pixels with particularly large
+residuals each time through the loop
+.IP [8]
+estimates magnitudes for the saturated psf stars (if any exist and
+if the parameter \fIsaturated\fR is "yes"),
+by fitting the current psf model to the wings of the saturated stars
+using the \fBpeak\fR task fitting algorithm,
+.IP [9]
+computes the residuals of each saturated psf star (if any exist and they
+were successfully fit) from the best fit
+analytic function within a radius of \fIpsfrad\fR + 2 pixels, weights
+the residuals by a factor of 0.5, and adds
+the contribution of the scaled, subsampled, and weighted residuals
+to the psf model look-up table(s)
+.IP [10]
+writes the computed analytic function parameters and
+look-up tables to the output psf image
+.IP [11]
+identifies all stars within (psfrad + 2 * fitrad + 1) pixels of
+a psf star as psf star neighbors, and stars within (2 * fitrad) pixels of
+the psf star neighbors as friends of the neighbors
+.IP [12]
+writes the ids, x and y coordinates, magnitudes, and sky values of
+the final list of psf stars to the output psf star list, and the group
+and star ids,
+x and y coordinates, magnitudes, and sky values of the psf stars,
+psf star neighbors, and friends of the psf star neighbors
+to the output psf star group file
+
+.NH 3
+Choosing the Appropriate Analytic Function
+
+.PP
+DAOPHOT offers several choices for the functional form of the analytic
+component of the psf model (see Appendix 8.2 for details).
+To achieve the best fits and to minimize interpolation errors in
+the psf model look-up tables,
+users should choose the analytic function that most closely
+approximates the stellar psf. The options are:
+.IP [1]
+\fBgauss\fR (2 parameters),
+a 2D elliptical gaussian function aligned along the x and y axes of the image.
+Gauss is generally the best choice for well-sampled, fwhmpsf >= 2.5 pixels,
+ground-based images because the interpolation errors are small
+and evaluation is efficient as the function is separable in x and y.
+.IP [2]
+\fBmoffat25\fR and \fBmoffat15\fR (3 parameters),
+elliptical Moffat functions of beta 2.5 and 1.5 respectively which can
+be aligned along an arbitrary position angle. The Moffat functions
+are good choices for under-sampled ground-based data.
+.IP [3]
+\fBlorentz\fR (3 parameters),
+an elliptical Lorentz function which can be aligned along an arbitrary position
+angle. The Lorenz function is a good choice for old ST data since it has
+extended wings.
+.IP [4]
+\fBpenny1\fR (4 parameters),
+a two component model consisting of an elliptical gaussian core
+which can be aligned along an arbitrary position angle and
+lorentzian wings aligned along the x and y axes of the image.
+The Penny1 function is a good choice for a purely analytic psf model.
+.IP [5]
+\fBpenny2\fR (5 parameters),
+a two component model consisting of an elliptical gaussian core
+aligned along an arbitrary position angle and lorentzian wings aligned
+along an arbitrary position angle which may be different from that of the
+core. The Penny2 function is a good choice for a purely analytic psf model.
+.IP [6]
+\fBauto\fR (2, 3, 4 or 5 parameters),
+try each of the 6 analytic psf functions in turn and select the one which
+yields the smallest scatter in the fit. Users should use
+this option with caution
+since the greater number of free parameters in some models may
+artificially produce a fit with less scatter without significantly
+improving the resulting photometry.
+.IP [7]
+\fBlist\fR (2, 3, 4 or 5 parameters),
+check only those functions in a user specified list, e.g.
+"gauss,moffat25,lorentz" and select the one that gives the smallest
+scatter.
+.PP
+Users uncertain of which analytic function to choose should leave
+\fIfunction\fR set to "gauss"
+and only if the results prove unsatisfactory experiment with one of the
+more complicated analytic functions.
+
+.NH 3
+The Analytic Psf Model
+
+.PP
+A purely analytic psf model may be computed
+by setting the \fBdaopars\fR parameter \fIvarorder\fR = -1.
+Analytic psf models are
+constant, i.e. they have the same shape everywhere in the
+image.
+In the majority
+of cases this is NOT the best modeling option,
+as a better representation of the true psf is almost always obtained by
+computing an empirical psf model composed of an
+analytic function plus one look-up table.
+.PP
+An analytic psf model may be required to model severely undersampled
+data because interpolation errors can produce large uncertainties
+in the computed look-up tables and the resulting fits.
+.PP
+Fields which are so crowded that
+isolated psf stars are non-existent, may also require psf modeling and
+psf star neighbor subtraction with an analytic psf model,
+before a more accurate higher order model free of ghosts produced
+by the psf star neighbors can be computed.
+This step is particularly important if the field is very crowded AND the
+psf is known to be variable.
+
+.NH 3
+The Empirical Constant Psf Model
+
+.PP
+Most users with typical ground-based optical
+data choose to compute an empirical constant psf
+model composed of an analytic component and a single look-up table,
+by setting the \fBdaopars\fR parameter \fIvarorder\fR = 0.
+This type of model is constant, i.e. the psf model has
+the same shape everywhere in the image.
+.PP
+Because of interpolation errors, severely undersampled data may be better
+fit with a purely analytic psf model as described in the previous section.
+.PP
+Fields which are so crowded that
+isolated psf stars are non-existent may require psf modeling and
+psf neighbor star subtraction with an analytic psf model,
+before an accurate look-up table free of ghosts caused by the bright
+psf star neighbors can be computed.
+
+.NH 3
+The Empirical Variable Psf Model
+
+.PP
+Psf models which vary linearly or quadratically
+with position in the image can be computed by setting
+the \fIvarorder\fR parameter to 1 or 2 respectively.
+In the first case a total of 3 look-up tables will be computed;
+in the second case 6 look-up tables will be computed.
+Users should always begin their analysis with \fIvarorder\fR = -1 or
+0 if their data is from a telescope/instrument combination that
+is unfamiliar to them. Only if the patterns of the residuals around stars
+fit and subtracted with a constant psf model show systematic variations
+with position
+in the image, should the user proceed to experiment with the variable
+psf models.
+.PP
+In very crowded regions it may be necessary to compute a good
+variable psf model iteratively, starting with \fIvarorder\fR = -1
+and proceeding to \fIvarorder\fR = 2 by, computing the psf model,
+fitting the psf model to the psf stars and their neighbors, subtracting
+the psf star neighbors but not the psf stars from the original image,
+increasing \fIvarorder\fR by 1, and recomputing the
+psf model using the subtracted image, until all the psf stars and their
+neighbors subtract out cleanly.
+
+.NH 3
+Rejecting Bad Data from the Psf Model
+
+.PP
+The \fBpsf\fR task uses the \fBdatapars\fR parameters \fIdatamin\fR
+and \fIdatamax\fR to flag bad data.
+If the \fBdaopars\fR parameter \fIsaturated\fR is "no", a prospective
+psf star
+will be rejected outright if it has high or low bad data inside the fitting
+radius; if \fIsaturated\fR is "yes" a star with low bad data will
+be rejected outright but one with high bad data will be flagged
+as saturated and accepted. Except in rare cases (see below) users should leave
+\fIsaturated\fR set to "no". Stars with bad data outside the fitting radius
+but inside the psf radius are flagged, and the user warned, but are still
+accepted as psf stars.
+.PP
+All data within one fitting radius of the unsaturated psf stars is weighted by
+the signal-to-noise ratio of the psf star and used to compute the
+analytic component of the psf model.
+Pixels which deviate strongly from the current best fit
+analytic function are down-weighted during the course of the fit.
+.PP
+After the analytic function is fit, the residuals of the psf star data
+from the best fit analytic function are computed, scaled to the magnitude
+of the first psf star, weighted by the signal-to-noise in the psf star,
+subsampled for a factor
+of 2 in x and y, and added into the look-up table(s).
+If there are too few psf stars with
+good data to compute a particular element of the look-up table(s),
+\fBpsf\fR will quit with an error. If the \fBdaopars\fR parameter
+\fInclean\fR > 0, deviant pixels contributing to the psf model look-up tables
+are down-weighted and the look-up table(s) are recomputed \fInclean\fR
+times.
+.PP
+For images where all the bright candidate psf stars are saturated and all the
+remaining
+candidate psf stars are faint, it may be necessary to use the faint stars to
+compute the analytic component of the psf model and bright saturated stars
+to compute the look-up tables(s).
+In this circumstance the user must set the parameter \fIsaturated\fR
+to "yes" and include several saturated stars in the psf star list.
+After the analytic function and an initial set of look-up tables(s)
+is computed without using the saturated psf stars, the \fBpeak\fR task
+fitting algorithm is used to compute accurate magnitudes for the
+saturated psf stars by fitting the wings of the saturated stars to
+the current psf model. New look-up table(s) are computed
+which include the contributions weighted by 0.5 of the saturated psf stars.
+
+.NH 3
+The Model Psf Psfrad and Fitrad
+
+.PP
+The \fBdaopars\fR parameter \fIpsfrad\fR defines the region over which
+the psf model is defined. This radius should equal the radius at which the
+radial profile of the brightest star of interest disappears into the noise,
+e.g. \(~= 5 pixels for the test image as determined
+in the section describing the
+\fBpstselect\fR task. The fitting radius defines the region of data around
+each psf star used to compute the analytic component of the psf model
+and should be the larger of the numbers 3 and 1 * \fIfwhmpsf\fR pixels.
+
+.NH 3
+Modeling the Psf Interactively Without a Psf Star List
+
+.PP
+The psf can be modeled interactively without an initial list of candidate
+psf stars by displaying the image and selecting candidate psf stars
+with the image
+cursor. Good candidate psf stars must be in the input photometry file,
+have no neighbors within \fIfitrad\fR
+pixels, and be free of cosmetic blemishes.
+.PP
+The following example shows how to model the psf interactively without
+using an initial psf star list.
+
+.YS
+da> display test 1 fi+
+
+da> psf test default "" default default default
+
+Analytic psf function(s) (gauss):
+ Analytic psf function(s): gauss
+Order of variable psf (0):
+ Order of variable psf: 0
+Psf radius in scale units (5.):
+ New psf radius: 5. scale units 5. pixels
+Fitting radius in scale units (3.):
+ New fitting radius: 3. scale units 3. pixels
+Minimum good data value (50.) (CR or value):
+ New minimum good data value: 50. counts
+Maximum good data value (24500.) (CR or value):
+ New maximum good data value: 24500. counts
+
+Warning: Graphics overlay not available for display device.
+
+Computing PSF for image: test
+9 stars read from test.mag.1
+.YE
+
+.IP ...
+A message appears on the screen telling the user how
+many stars have been read from the photometry file
+(users should make sure that this is the entire star list)
+and the image cursor begins blinking.
+.IP ...
+The user types the \fBa\fR keystroke at pixel 36,42
+followed by another \fBa\fR keystroke after the default
+plot appears,
+to add star 9 psf star list. Star 6 at pixel 8,23 is added
+to the psf star list in the identical manner.
+.LP
+
+.YS
+Star 9 has been added to the PSF star list
+ X: 35.98 Y: 42.03 Mag: 16.594 Dmin: 80.25255 Dmax: 489.9732
+Star 6 has been added to the PSF star list
+ X: 8.02 Y: 22.97 Mag: 16.603 Dmin: 71.00896 Dmax: 436.3393
+.YE
+
+.IP ...
+The user types the \fBl\fR keystroke command to list the selected psf stars.
+.LP
+
+.YS
+Current PSF star list
+ Star: 9 X: 35.98 Y: 42.03 Mag: 16.59 Sky: 101.0
+ Star: 6 X: 8.02 Y: 22.97 Mag: 16.60 Sky: 98.9
+.YE
+.LP
+
+.IP ...
+The user types the \fBf\fR keystroke command to compute the psf model.
+.LP
+
+.YS
+Fitting function gauss norm scatter: 0.03422394
+
+Analytic PSF fit
+ Function: gauss X: 25. Y: 25. Height: 523.8066 Psfmag: 16.594
+ Par1: 1.082032 Par2: 1.162063
+
+Computed 1 lookup table(s)
+.YE
+
+.IP ...
+The user reviews the model fit with the \fBr\fR keystroke command and
+decides to keep both psf stars.
+.LP
+
+.YS
+PSF star 9 saved by user
+PSF star 6 saved by user
+.YE
+
+.IP ...
+The user types the \fBf\fR keystroke command to remodel the psf.
+.LP
+
+.YS
+Fitting function gauss norm scatter: 0.03422394
+
+Analytic PSF fit
+ Function: gauss X: 25. Y: 25. Height: 523.8066 Psfmag: 16.594
+ Par1: 1.082032 Par2: 1.162063
+
+Computed 1 lookup table(s)
+.YE
+
+.IP ...
+The user types the \fBw\fR keystroke command to save the psf model
+followed by the \fBq\fR keystroke command, executed twice, to quit the task.
+.LP
+
+.YS
+Writing PSF image test.psf.1.imh
+Writing output PSF star list test.pst.1
+Writing output PSF star group file test.psg.1
+.YE
+
+.PP
+At this point the user has created an initial psf model in the image
+test.psf.1, a list of the psf stars in test.pst.1, and a list of the
+psf stars and their neighbors in the file
+test.psg.1 respectively.
+.PP
+Users may occasionally see "Star not found" messages when
+selecting psf stars with the image cursor. This may mean: 1) that the star
+is truly not in the input photometry file (this can be checked
+with the \fBtvmark\fR task), 2) that the image cursor
+is more than \fImatchrad\fR pixels from the position of the star
+in the input photometry file (either position the image cursor more
+carefully by hand or increase the value of the \fImatchrad\fR parameter), or,
+3) that the input photometry file contains
+more than \fImaxnstar\fR stars (increase the value of the parameter
+\fImaxnstar\fR so that it is greater than the number of stars in
+the photometry file).
+
+.NH 3
+Fitting the Psf Model Interactively Using an Initial Psf Star List
+
+.PP
+The \fBpsf\fR task can also be run interactively using an initial list of
+psf stars chosen by the user with the \fBpstselect\fR task.
+If the \fBpsf\fR task parameter \fIshowpsf\fR is "yes" (the default),
+the psf stars are read from the psf star list one at a time,
+a mesh, contour, or radial profile plot is displayed in the graphics window,
+and the user can accept or delete the star with the \fBa\fR or \fBd\fR
+keystroke commands. If
+\fIshowplots\fR is "no", the psf star list is read without intervention
+by the user. In both cases new stars can be added to the end of the psf
+star list with the image cursor in the usual manner.
+.PP
+A sample run is shown below.
+
+.YS
+da> display test 1 fi+
+
+da> pdump test.pst.1 xcenter,ycenter,id yes | tvmark 1 STDIN \\
+ col=205 label+
+.YE
+
+.IP ...
+The user marks and labels the initial list of psf stars on the image display.
+.LP
+
+.YS
+da> psf test default test.pst.1 default default default
+
+Analytic psf function(s) (gauss):
+ Analytic psf function(s): gauss
+Order of variable psf (0):
+ Order of variable psf: 0
+Psf radius in scale units (5.):
+ New psf radius: 5. scale units 5. pixels
+Fitting radius in scale units (3.):
+ New fitting radius: 3. scale units 3. pixels
+Minimum good data value (50.) (CR or value):
+ New minimum good data value: 50. counts
+Maximum good data value (24500.) (CR or value):
+ New maximum good data value: 24500. counts
+
+Warning: Graphics overlay not available for display device.
+
+Computing PSF for image: test
+9 stars read from test.mag.1
+.YE
+
+.IP ...
+The user rejects or accepts the stars in the .pst file by typing the
+\fBd\fR or \fBa\fR keystroke commands respectively after the
+default plot appears.
+.LP
+
+.YS
+Star 5 rejected by user
+Star 9 has been added to the PSF star list
+ X: 35.98 Y: 42.03 Mag: 16.594 Dmin: 80.25255 Dmax: 489.9732
+Star 6 has been added to the PSF star list
+ X: 8.02 Y: 22.97 Mag: 16.603 Dmin: 71.00896 Dmax: 436.3393
+
+2 PSF stars read from test.pst.1
+.YE
+
+.IP ...
+The user types the \fBl\fR keystroke command to view the psf star
+list one more time.
+.LP
+
+.YS
+Current PSF star list
+ Star: 9 X: 35.98 Y: 42.03 Mag: 16.59 Sky: 101.0
+ Star: 6 X: 8.02 Y: 22.97 Mag: 16.60 Sky: 98.9
+.YE
+
+.IP ...
+The user computes the psf model with the \fBf\fR keystroke command.
+.LP
+
+.YS
+Fitting function gauss norm scatter: 0.03422394
+
+Analytic PSF fit
+ Function: gauss X: 25. Y: 25. Height: 523.8066 Psfmag: 16.594
+ Par1: 1.082032 Par2: 1.162063
+
+Computed 1 lookup table(s)
+.YE
+
+.IP ...
+The user saves the psf model with the \fBw\fR keystroke command.
+.LP
+
+.YS
+Writing PSF image test.psf.1.imh
+Writing output PSF star list test.pst.2
+Writing output PSF star group file test.psg.1
+.YE
+
+.IP ...
+The user types the \fBq\fR keystroke command to quit the task.
+.LP
+
+The user notes that the output psf star list is given a version number
+of 2 in this example, since version 1 was written by the \fBpstselect\fR task.
+
+.NH 3
+Fitting the Psf Model Interactively Without an Image Display
+
+.PP
+Users without access to an image display, may still run \fBpsf\fR
+interactively by redirecting
+the image cursor commands to the terminal as shown below.
+
+.YS
+da> set stdimcur = text
+
+da> psf test default test.pst.1 default default default
+
+Analytic psf function(s) (gauss):
+ Analytic psf function(s): gauss
+Order of variable psf (0):
+ Order of variable psf: 0
+Psf radius in scale units (5.):
+ New psf radius: 5. scale units 5. pixels
+Fitting radius in scale units (3.):
+ New fitting radius: 3. scale units 3. pixels
+Minimum good data value (50.) (CR or value):
+ New minimum good data value: 50. counts
+Maximum good data value (24500.) (CR or value):
+ New maximum good data value: 24500. counts
+
+Warning: Graphics overlay not available for display device.
+
+Computing PSF for image: test
+9 stars read from test.mag.1
+.YE
+
+.IP ...
+The user rejects or accepts the stars in the .pst file by typing
+the \fBd\fR or \fBa\fR keystroke commands respectively at the prompt.
+.LP
+
+.YS
+Star 5 rejected by user
+Star 9 has been added to the PSF star list
+ X: 35.98 Y: 42.03 Mag: 16.594 Dmin: 80.25255 Dmax: 489.9732
+Star 6 has been added to the PSF star list
+ X: 8.02 Y: 22.97 Mag: 16.603 Dmin: 71.00896 Dmax: 436.3393
+
+2 PSF stars read from test.pst.1
+.YE
+
+.IP ...
+The user types the \fBl\fR keystroke command at the prompt to
+view the psf star list one more time.
+.LP
+
+.YS
+Current PSF star list
+ Star: 9 X: 35.98 Y: 42.03 Mag: 16.59 Sky: 101.0
+ Star: 6 X: 8.02 Y: 22.97 Mag: 16.60 Sky: 98.9
+.YE
+
+.IP ...
+The user computes the psf model by typing the \fBf\fR keystroke
+command at the prompt.
+.LP
+
+.YS
+Fitting function gauss norm scatter: 0.03422394
+
+Analytic PSF fit
+ Function: gauss X: 25. Y: 25. Height: 523.8066 Psfmag: 16.594
+ Par1: 1.082032 Par2: 1.162063
+
+Computed 1 lookup table(s)
+.YE
+
+.IP ...
+The user saves the psf model by typing the \fBw\fR keystroke command
+at the prompt.
+.LP
+
+.YS
+Writing PSF image test.psf.1.imh
+Writing PSF output star list test.pst.2
+Writing PSF output star group file test.psg.1
+.YE
+
+.IP ...
+The user types the \fBq\fR keystroke command at the prompt to quit the task.
+.LP
+
+Additional stars can be added to the psf star list by commands of
+the form \fB":a id#"\fR or \fB"100.2 305.6 1 a"\fR typed in at the
+terminal prompt.
+The user should remember to reset the image cursor to the logical
+image cursor with the command \fB"reset stdimcur = stdimage"\fR
+after running the \fBpsf\fR task in "no image display" mode.
+
+.NH 3
+Fitting the Psf Model Non-interactively
+
+.PP
+Finally the psf model can be fit non-interactively by setting the
+\fIinteractive\fR parameter to "no", and using the list of psf stars produced by
+the \fBpstselect\fR task as input. This is the preferred method for computing
+the psf model when the number of psf stars is large (e.g. the psf
+model to be computed is variable).
+
+.YS
+da> psf test default test.pst.1 default default default inter-
+.YE
+
+.NH 3
+The Output of Psf
+
+.PP
+\fBPsf\fR writes an output psf star list test.pst.# containing the ids, x and
+y coordinates, magnitudes, and sky values, copied from the
+input photometry file,
+of the psf stars actually used to compute the final psf model.
+Because of the ability
+to add and subtract stars within \fBpsf\fR itself, this list may be different
+from the input psf star list if any. A sample output psf star list is
+shown below.
+
+.YS
+#K IRAF = NOAO/IRAFV2.10EXPORT version %-23s
+#K USER = davis name %-23s
+#K HOST = tucana computer %-23s
+#K DATE = 05-28-93 mm-dd-yr %-23s
+#K TIME = 14:34:31 hh:mm:ss %-23s
+#K PACKAGE = daophot name %-23s
+#K TASK = psf name %-23s
+#K IMAGE = test imagename %-23s
+#K PHOTFILE = test.mag.1 filename %-23s
+#K PSTFILE = test.pst.1 filename %-23s
+#K PSFIMAGE = test.psf.1 imagename %-23s
+#K GRPSFILE = test.psg.1 filename %-23s
+#K OPSTFILE = test.pst.2 filename %-23s
+#K SCALE = 1. units/pix %-23.7g
+#K OTIME = 00:07:59.0 timeunit %-23s
+#K IFILTER = V filter %-23s
+#K XAIRMASS = 1.238106 number %-23.7g
+#K PSFRAD = 5. scaleunit %-23.7g
+#K FITRAD = 3. scaleunit %-23.7g
+#
+#N ID XCENTER YCENTER MAG MSKY \\
+#U ## pixels pixels magnitudes counts \\
+#F %-9d %-10.3f %-10.3f %-12.3f %-12.3f
+#
+9 35.980 42.029 16.594 101.043
+6 8.022 22.970 16.603 98.891
+.YE
+
+.PP
+\fBPsf\fR also writes an output psf star group photometry file
+test.psg.? containing the group ids, and the star ids,
+x and y coordinates, magnitudes, and sky values
+copied from the input photometry file,
+for the psf stars and their
+neighbors. A sample psf star group file is shown below.
+
+.YS
+#K IRAF = NOAO/IRAFV2.10EXPORT version %-23s
+#K USER = davis name %-23s
+#K HOST = tucana computer %-23s
+#K DATE = 05-26-93 mm-dd-yr %-23s
+#K TIME = 16:10:48 hh:mm:ss %-23s
+#K PACKAGE = daophot name %-23s
+#K TASK = psf name %-23s
+#K IMAGE = test imagename %-23s
+#K PHOTFILE = test.mag.2 filename %-23s
+#K PSTFILE = test.pst.2 filename %-23s
+#K PSFIMAGE = test.psf.2 imagename %-23s
+#K GRPSFILE = test.psg.2 filename %-23s
+#K SCALE = 1. units/pix %-23.7g
+#K OTIME = 00:07:59.0 timeunit %-23s
+#K IFILTER = V filter %-23s
+#K XAIRMASS = 1.238106 number %-23.7g
+#K PSFRAD = 5. scaleunit %-23.7g
+#K FITRAD = 3. scaleunit %-23.7g
+#
+#N ID GROUP XCENTER YCENTER MAG MSKY \\
+#U ## ## pixels pixels magnitudes counts \\
+#F %-9d %-6d %-10.3f %-10.3f %-12.3f %-14.3f
+#
+9 1 35.980 42.029 16.594 101.043
+8 1 28.958 33.924 17.781 100.619
+6 2 8.022 22.970 16.603 98.891
+.YE
+
+There are two stellar groups, one group per psf star,
+in this file. The first psf star
+has a single neighbor so there are two stars in the first group.
+The first star in a group is always the psf star. The header parameters
+record the input and output image and file names, the name of the
+computed psf model, and the values
+of the parameters
+\fIpsfrad\fR and \fIfitrad\fR used to define the psf star groups.
+.PP
+The psf image contains, in the image header, the values of the
+parameters that were used
+to compute the psf model, the best fit values of the parameters of
+the chosen analytic function, and a record of all the
+psf stars used to compute the psf, and in the image pixels, the best fit
+look-up table(s) of the residuals from the analytic function
+subsampled by a factor of 2.
+The psf image look-up table(s) can be plotted and examined just like any
+other IRAF image.
+.PP
+A sample psf image header is shown below.
+
+.YS
+test.psf.2[23,23][real]: PSF for image: test
+ No bad pixels, no histogram, min=unknown, max=unknown
+ Line storage mode, physdim [23,23], length of user area 1540 s.u.
+ Created Wed 16:10:47 26-May-93, Last modified Wed 16:10:47 26-May-93
+ Pixel file 'tucana!/d0/iraf/davis/test.psf.2.pix' [ok]
+ IRAF = 'NOAO/IRAFV2.10EXPORT'
+ HOST = 'tucana '
+ USER = 'davis '
+ DATE = '05-26-93'
+ TIME = '16:10:48'
+ PACKAGE = 'daophot '
+ TASK = 'psf '
+ IMAGE = 'test '
+ PHOTFILE= 'test.mag.2'
+ PSTFILE = 'test.pst.2'
+ PSFIMAGE= 'test.psf.2'
+ GRPSFILE= 'test.psg.2'
+ SCALE = 1.
+ PSFRAD = 5.
+ FITRAD = 3.
+ DATAMIN = 50.
+ DATAMAX = 24500.
+ NCLEAN = 0
+ USESAT = F
+ FUNCTION= 'gauss '
+ PSFX = 25.
+ PSFY = 25.
+ PSFHEIGH= 523.8066
+ PSFMAG = 16.594
+ NPARS = 2
+ PAR1 = 1.082032
+ PAR2 = 1.162063
+ VARORDER= 0
+ FEXPAND = F
+ NPSFSTAR= 2
+ ID1 = 9
+ X1 = 35.98
+ Y1 = 42.029
+ MAG1 = 16.594
+ ID2 = 6
+ X2 = 8.022
+ Y2 = 22.97
+ MAG2 = 16.603
+.YE
+
+This psf image header records that: the psf model
+was computed with a gaussian
+analytic function (function = gauss), the analytic
+function has two parameters (npars=2)
+whose values are 1.08 and 1.16 (par1 and par2 are the fwhm of the function
+in x and y respectively in this case), the psf is constant but there is
+1 look-up
+table (varorder = 0), no saturated stars were used to compute the psf
+(usesat=no), and no cleaning of bad pixels was done to compute the
+lookup table (nclean=0). The number of psf stars and their positions
+and magnitudes
+are also listed. The psf model is defined over a radius of 5
+pixels (psfrad = 5.0), resulting in a square look-up table with dimensions
+of 2 * (nint (2 * psfrad) + 1) + 1 pixels in x and y, and a fitting radius
+of 3 (fitrad = 3.0) was used to compute the analytic portion of the psf
+model.
+.PP
+The height of the best fit gaussian psfheigh is 523.81 counts.
+The psf model has been assigned a magnitude of 16.594 which is the
+magnitude of the first psf star in the input photometry file.
+All fits to the psf model are scaled with respect to this
+magnitude. Therefore a star which is twice as bright as the psf model will
+have a fitted magnitude of ~15.841.
+.PP
+Psfx and psfy define the distance from the center of the input image to the
+center of the edge pixels in x and y respectively, e.g psfx =
+(ncols - 1.0) / 2.0 and psfy = (nlines - 1) / 2.0. These numbers are used to
+evaluate the psf model only if the model is variable, \fIvarorder\fR > 0.
+.PP
+If the value of \fIvarorder\fR in this example had been 1 or 2 the
+psf model image would have been 3-dimensional with 3 and 6 23 by 23
+pixel look-up
+tables in planes 1-3 and 1-6 of the image respectively.
+In both cases planes 1-3 would contain the 0th, 1st order in x,
+and 1st order in y Taylor expansion coefficients around the analytic function.
+In the latter case planes 4-6 would contain the
+2nd order in x, 2nd order in xy, and 2nd order in y Taylor expansion
+coefficients. If the value of \fIvarorder\fR
+had been -1 no look-up tables would have been computed and the
+psf model image would consist of an image header but no pixel file.
+
+.NH 3
+Checking the Psf Model
+
+.PP
+To check the accuracy of the psf model, the user must fit each psf
+star and its neighbors and friends
+as a group using the \fBnstar\fR task, and the psf model and psf star group
+photometry file
+produced by \fBpsf\fR as shown below. In the following example
+the user has chosen to set the rejections
+file to "", so that all stars, even those too faint to be properly
+fit, will be placed in the same output file.
+
+.YS
+da> nstar test test.psg.1 default default ""
+
+Recenter the stars (yes):
+ Recenter the stars: yes
+Refit the sky (no):
+ Refit the sky: no
+Psf radius in scale units (5.):
+ New psf radius: 5. scale units 5. pixels
+Fitting radius in scale units (3.):
+ New fitting radius: 3. scale units 3. pixels
+Maximum group size in number of stars (60):
+ New maximum group size: 60 stars
+Minimum good data value (50.) (CR or value):
+ New minimum good data value: 50. counts
+Maximum good data value (24500.) (CR or value):
+ New maximum good data value: 24500. counts
+
+Group: 1 contains 2 stars
+ ID: 9 XCEN: 35.98 YCEN: 42.01 MAG: 16.60
+ ID: 8 XCEN: 28.96 YCEN: 33.91 MAG: 17.73
+Group: 2 contains 1 stars
+ ID: 6 XCEN: 8.02 YCEN: 22.97 MAG: 16.63
+.YE
+
+The results of the fits will appear in test.nst.? as shown below.
+
+.YS
+da> page test.nst.1
+
+#K IRAF = NOAO/IRAFV2.10EXPORT version %-23s
+#K USER = davis name %-23s
+#K HOST = tucana computer %-23s
+#K DATE = 05-28-93 mm-dd-yy %-23s
+#K TIME = 14:46:13 hh:mm:ss %-23s
+#K PACKAGE = daophot name %-23s
+#K TASK = nstar name %-23s
+#K IMAGE = test imagename %-23s
+#K GRPFILE = test.psg.1 filename %-23s
+#K PSFIMAGE = test.psf.1 imagename %-23s
+#K NSTARFILE = test.nst.1 filename %-23s
+#K REJFILE = "" filename %-23s
+#K SCALE = 1. units/pix %-23.7g
+#K DATAMIN = 50. counts %-23.7g
+#K DATAMAX = 24500. counts %-23.7g
+#K GAIN = 1. number %-23.7g
+#K READNOISE = 0. electrons %-23.7g
+#K OTIME = 00:07:59.0 timeunit %-23s
+#K XAIRMASS = 1.238106 number %-23.7g
+#K IFILTER = V filter %-23s
+#K RECENTER = yes switch %-23b
+#K FITSKY = no switch %-23b
+#K PSFMAG = 16.594 magnitude %-23.7g
+#K PSFRAD = 5. scaleunit %-23.7g
+#K FITRAD = 3. scaleunit %-23.7g
+#K MAXITER = 50 number %-23d
+#K MAXGROUP = 60 number %-23d
+#K FLATERROR = 0.75 percentage %-23.7g
+#K PROFERROR = 5. percentage %-23.7g
+#K CLIPEXP = 6 number %-23d
+#K CLIPRANGE = 2.5 sigma %-23.7g
+#
+#N ID GROUP XCENTER YCENTER MAG MERR MSKY \\
+#U ## ## pixels pixels magnitudes magnitudes counts \\
+#F %-9d %-6d %-10.3f %-10.3f %-12.3f %-14.3f %-12.3f
+#
+#N NITER SHARPNESS CHI PIER PERROR \\
+#U ## ## ## ## perrors \\
+#F %-17d %-12.3f %-12.3f %-6d %-13s
+#
+9 1 35.982 42.006 16.601 0.019 101.043 \\
+ 4 -0.019 0.512 0 No_error
+8 1 28.962 33.912 17.730 0.074 100.619 \\
+ 4 0.026 1.093 0 No_error
+6 2 8.017 22.968 16.628 0.021 98.891 \\
+ 3 0.022 0.558 0 No_error
+.YE
+
+In this example the chi values computed by \fBnstar\fR for the two
+psf stars are lower than expected, ~ 0.5 instead of ~ 1.0, meaning that the
+observed errors are less than the predicted errors.
+This occurs because there are only 2 psf stars,
+and therefore the model psf and the fitted psf stars are not totally
+independent.
+For example, if only one psf star is used to compute
+the psf model, the chi
+computed by \fBnstar\fR for that star would be ~ 0.0 and for any others
+such as its neighbors ~ 1.0.
+.PP
+After checking that the chi values look reasonable, the user subtracts the
+fitted psf stars and their neighbors from the input image
+with the \fBsubstar\fR task, and examines the residuals
+of the fit around the psf stars as shown below. After \fBsubstar\fR is
+run the subtracted
+image is displayed and the psf stars are marked in green and the
+psf neighbor stars are marked in red.
+
+.YS
+da> substar test default "" default default
+
+Psf radius in scale units (5.):
+ New psf radius: 5. scale units 5. pixels
+Minimum good data value (50.) (CR or value):
+ New minimum good data value: 50. counts
+Maximum good data value (24500.) (CR or value):
+ New maximum good data value: 24500. counts
+
+SUBTRACTING - Star: 6 X = 8.02 Y = 22.97 Mag = 16.63
+SUBTRACTING - Star: 8 X = 28.96 Y = 33.91 Mag = 17.73
+SUBTRACTING - Star: 9 X = 35.98 Y = 42.01 Mag = 16.60
+
+A total of 3 stars were subtracted out of a possible 3
+
+da> display test.sub.1 1 fi+
+da> pdump test.nst.1 xc,yc,id yes | tvmark 1 STDIN col=204 label+
+da> pdump test.pst.1 xc,yc,id yes | tvmark 1 STDIN col=205 label+
+.YE
+
+.PP
+The psf stars and their neighbors should subtract out cleanly
+with no systematic patterns in the residuals as a function of distance
+from the star (note this may not be the case if the psf is purely analytic
+or so severely undersampled that the interpolation errors near the
+center are very large), with magnitude, or with position in the image.
+There should be no hidden
+underlying neighbors revealed after the subtraction (these psf stars
+should be rejected) or neighbors
+that are not in the photometry file (this can be fixed up later).
+The amplitudes of the fit residuals
+should be consistent with the noise if sufficient stars are
+used to determine the psf model.
+.PP
+The displayed and marked subtracted image and the output of \fBnstar\fR can
+be examined in more detail with the \fBpexamine\fR task as shown below.
+
+.YS
+da> pexamine test.nst.1 "" test.sub.1
+.YE
+.IP ...
+A plot of magnitude versus magnitude error for the psf stars and their
+neighbors will appear.
+.IP ...
+Change the default plot to mag versus chi with the command \fB:ycolumn chi\fR
+followed by the \fBp\fR keystroke command.
+.IP ...
+Activate the image cursor with the \fBi\fR keystroke command.
+.IP ...
+Move to psf star number 9 and type \fBr\fR to examine the radial profile
+of the subtracted star, followed by \fBo\fR to get a listing of its position,
+magnitude, magnitude error, sky value, etc.
+.IP ...
+Examine the radial profiles of the other subtracted psf stars and their
+neighbors.
+.IP ...
+Type \fBq\fR to quit the task.
+
+.PP
+For the test image "test", examination of the radial profiles of the
+subtracted stars shows that the residuals are
+consistent with the noise in the image and have no unusual features
+leading to the conclusion that the current psf model is a good representation
+of the true psf.
+
+.NH 3
+Removing Bad Stars from the Psf Model
+
+.PP
+Bad psf stars detected after the psf star and neighbor subtraction,
+for example those with
+a cosmetic blemish, a close double, or an underlying neighbor star,
+should be removed altogether from
+the psf star list. This can be done by editing the psf star list written
+by \fBpsf\fR with the text editor, with the \fBpselect\fR task and an
+expression, e.g. "id != 5", specifying the star to be deleted, or
+with the interactive \fBpexamine\fR task using the delete and update keys,
+and rerunning \fBpsf\fR with the new psf star list.
+.PP
+This step is not required for the test image as both psf stars and their
+neighbors subtracted cleanly from the image.
+
+.NH 3
+Adding New Stars to a Psf Star Group
+
+.PP
+Occasionally stars that are too faint to be included
+in initial star list produced by \fBdaofind\fR and measured with \fBphot\fR, are
+nevertheless sufficiently bright and close to a psf star
+to affect the computation of the psf model.
+Ideally the psf stars should have no such companions and/or the look-up
+table cleaning option in the \fBpsf\fR task should minimize the problem of
+undetected neighbors. However in some cases it is necessary for
+the user to intervene and add faint stars to the photometry list.
+.PP
+The easiest way to accomplish this
+is to run \fBphot\fR interactively, selecting the
+missing neighbor stars with the image cursor and appending the results
+for the new neighbor stars to the photometry file produced by the first
+run of \fBnstar\fR.
+
+.YS
+da> phot test "" psf.mag inter+ calgorithm=centroid
+.YE
+
+.IP ...
+Point cursor to undetected psf star neighbors and hit spacebar.
+.IP ...
+Type \fBq\fR to quit.
+.LP
+
+.YS
+da> prenumber psf.mag idoffset=5000
+.YE
+
+.IP ...
+Renumber the stars in the new file starting with a number greater
+than the number of stars in the original photometry file in order
+to insure that all the stars have unique ids.
+.LP
+
+.YS
+da> pfmerge test.psg.1,psf.mag test.psf.psg
+.YE
+
+.IP ...
+Combine the psf star group photometry file produced by the \fBpsf\fR task
+with the photometry file for the new psf star neighbors produced by
+the \fBphot\fR task.
+.LP
+
+Users should note that there is no input coordinate list to \fBphot\fR in
+this case. Therefore the coordinate list is set to "", interactive mode
+is on, and centering is turned on.
+The remaining photometry parameters should be set exactly as they were in the
+first run of \fBphot\fR.
+.PP
+This step is not required for the test image as all the significant
+psf star neighbors were detected by the first run of the \fBdaofind\fR task.
+
+.NH 3
+Refitting the Psf Model With the New Psf Star Groups
+
+.PP
+After the \fBpsf \fR and \fBphot\fR results have been merged, the
+user must regroup the psf stars and their neighbors with
+the \fBgroup\fR task, and refit the
+new groups with the \fBnstar\fR task.
+
+.YS
+da> group test test.psf.psg default test.grp critov=.2
+.YE
+
+.IP ...
+Regroup the stars using a very small value for the critical overlap
+parameter.
+.LP
+
+.YS
+da> nstar test test.grp default default ""
+.YE
+
+.IP ...
+Rerun nstar on the new psf star groups.
+.LP
+
+.YS
+da> substar test test.nst.2 "" default default
+.YE
+
+.IP ...
+Check that the new psf star groups subtract cleanly from the original
+image.
+.PP
+This step is not required for the test image as all the significant
+psf star neighbors were detected by the first run of the \fBdaofind\fR task.
+
+
+.NH 3
+Computing the Final Psf Model
+
+.PP
+Once the psf star and psf star neighbors subtract out cleanly
+from the input image with the current psf model,
+a final psf model should be computed using an image from which all
+the psf star neighbors but not the psf stars have been subtracted.
+To do this the user runs the \fBsubstar\fR task, setting the input photometry
+file to the final output of \fBnstar\fR, and the exclude file to the final
+psf star list written by the \fBpsf\fR task, and reruns \fBpsf\fR.
+An example of this procedure is shown below.
+
+.YS
+da> substar test test.nst.2 test.pst.2 default default
+da> psf test.sub.3 test.grp test.pst.2 test.psf.2 test.pst.3 \\
+ test.psg.3 inter-
+.YE
+
+After this step the user should have a good psf model and can proceed to do
+psf fitting photometry.
+.PP
+This step is not required for the test image as the single psf star
+neighbor is sufficiently far from the psf star to have a negligible
+effect on the computation of the psf model.
+
+.NH 3
+Visualizing the Psf Model with the Seepsf Task
+
+.PP
+The psf analytic function parameters are stored in the psf image header
+and the look-up table(s) in the psf image pixels. The look-up table(s) are
+subsampled by a factor of 2 with respect to the image, and cannot
+be used directly to visualize what the psf model looks like
+at the scale of the image. The task \fBseepsf\fR can be used to
+do this conversion as shown below.
+
+.YS
+da> seepsf test.psf.3 psf3
+.YE
+
+The output image will contain a picture of what an ideal star of magnitude
+equal to the magnitude of the psf (see the psfmag keyword in the psf
+image header) should look like at the center of the image.
+.PP
+In the case of a variable psf the appearance of the psf model can be examined at
+various
+places in the image by specifying a position at which to compute the psf
+model.
+
+.YS
+da> seepsf test.psf.3 psf.13.8 xpsf=13 ypsf=8
+.YE
+
+.PP
+The total power in a variable psf should be constant
+as a function of position in the image even though its shape is
+different. The variable psf fitting code
+in DAOPHOT does perform flux conservation. Users can check this by using
+the \fBimstatistics\fR task to check that there is no net power in the
+look-up tables 2-3 or
+2-6 if the psf order is 1 or 2. Similarly they can use \fBseepsf\fR to compute
+the psf at various positions in the input image and \fBimstat\fR to check
+that the net power in the psf is constant over the image
+even though the shape of the
+psf is variable.
+
+.NH 3
+Problems Computing the Psf Model
+
+.PP
+Computing the psf model is the most crucial step in DAOPHOT.
+The \fBdaofind\fR and \fBphot\fR
+steps are usually straight-forward, and the principal fitting task
+\fBallstar\fR runs entirely in batch once started. However computing
+a good psf model requires user input.
+.PP
+This section suggests a few
+things to check if the computed psf model is not doing a good
+job of fitting and subtracting the psf or program stars. The user
+should check:
+.IP [1]
+that the sky annulus chosen in the \fBphot\fR step is neither too
+close or too far from the stars. If the sky annulus is too close
+the computed skies will tend to be too high and the psf model
+will have too small an amplitude,
+producing false halos around the fitted and subtracted stars. If the sky annulus
+is too far away the computed sky value will not represent the sky under the
+psf star well, adding scatter to the photometry.
+.IP [2]
+the psf radius.
+If the stars appear to be well fit in the cores but have residual halos with a
+sharp inner edge around
+them then the psf radius may be too small. The psf radius needs to
+be big enough to give good subtractions for the brightest stars of interest.
+.IP [3]
+that the analytic component of the psf function is appropriate for
+the data.
+If the data is somewhat undersampled, fwhmpsf < 2.5 pixels,
+one of the Moffat functions may give a better fit to the data than
+the Gauss function. If that data is extremely undersampled an analytic
+function may do better than one involving look-up tables.
+.IP [4]
+the psf stars.
+One or more of the psf stars may not be stars, may be doubles, or contain
+bad data. Although psf does try to detect and down-weight bad data it may
+not be completely successful. Users need to examine the subtracted image
+for objects with bad residuals and for stars with large fitted chi values
+and eliminate them.
+.IP [5]
+for psf variability with position in the image. The true psf may be variable
+and inadequately fit by a constant psf model. The user should examine the
+residuals around the subtracted psf stars to see if there are patterns
+with position in the image and
+increase the order of the psf model if these are detected.
+Large fitted chi values may also be an indication of a poor psf model.
+.IP [6]
+the distribution of the psf stars.
+If the psf is variable the user must ensure that the psf stars adequately
+cover the region of interest in the image. For example if there are no
+psf stars in a certain portion of the image the psf may not
+be well represented there.
+.IP [7]
+the data. If the psf is a higher order than quadratic \fBpsf\fR may
+not be able to model it adequately. The user should check the image data
+reduction history, and investigate any image combining, bad pixel and cosmic
+ray removal
+operations, etc., that may have fundamentally altered the data.
+The data should also be checked for linearity.
+.IP [8]
+the noise model. If the chi values for the fitted psf stars are unusually
+large or small, the effective readout noise and gain for the image
+may not be correct. The user should check that these values are
+being read from the image header correctly and that they are appropriate
+for the data.
+
+
+.NH 2
+Doing Psf Fitting Photometry with Peak, Nstar, or Allstar
+
+.PP
+There are three psf fitting
+photometry tasks in DAOPHOT. The \fBpeak\fR task fits the current psf
+model to stars individually; the \fBnstar\fR task fits the psf model to
+stars in fixed stellar groups simultaneously; the \fBallstar\fR task
+groups and fits the psf model to stellar groups dynamically
+and subtracts the fitted stars from the input image.
+\fBAllstar\fR is the
+task of choice for the majority of users, but all three options are
+discussed in the following sections.
+
+.NH 3
+Fitting Single Stars with Peak
+
+.PP
+\fBPeak\fR is the simplest psf fitting task.
+\fBPeak\fR fits the psf model to the stars in the
+input photometry list individually. Because \fBpeak\fR cannot fit stars in
+groups as the \fBnstar\fR and \fBallstar\fR tasks do, and in
+uncrowded frames aperture photometry is often simpler and just as accurate,
+\fBpeak\fR has few unique functions.
+However \fBpeak\fR can be useful in cases where the user wishes to: 1) improve
+the signal to noise of faint stars by taking advantage of
+\fBpeak's\fR optimal weighting scheme, 2) do astrometry of single
+stars, 3) fit and remove single stars from the frame in order to
+examine the underlying light distribution.
+
+.NH 4
+The Peak Algorithm
+
+.PP
+By default the \fBpeak\fR task performs the following functions:
+.IP [1]
+reads the task parameters, including the name of
+the input image, the input photometry file, the psf model, the
+output photometry and rejections files, and the
+\fBdatapars\fR and \fBdaopars\fR algorithm parameter sets
+.IP [2]
+reads the id, x and y coordinates, magnitude, and sky value
+of a star from the input photometry file
+.IP [3]
+rejects the star if it has an undefined sky value, too
+few good data pixels to obtain a fit, or is too faint
+.IP [4]
+extracts the image data within one fitting radius of each star and
+performs an optimally weighted non-linear least-squares fit of the psf model
+to the extracted data
+.IP [5]
+rejects the star if its signal-to-noise ratio is too low
+or a unique solution cannot be found
+.IP [6]
+computes the best fit x, y, and magnitude for the star
+.IP [7]
+writes the id, new x and y coordinates, sky value, new magnitude, magnitude
+error, number of iterations required to fit the star, chi statistic,
+and sharpness
+statistic for the fitted star to the
+output photometry file, and the id, last computed x and y position,
+and sky value of the rejected star, to
+the rejections file
+.IP [8]
+repeats steps [2]-[7] for each star in the input photometry list
+
+.NH 4
+Running Peak
+
+.PP
+A sample run of the \fBpeak\fR task is shown below. The user is prompted
+for all the input and output file names and asked to verify the
+critical parameters \fIrecenter\fR, \fIfitsky\fR, \fIpsfrad\fR, \fIfitrad\fR,
+\fIdatamin\fR, and \fIdatamax\fR.
+
+.YS
+da> peak test default default default default
+
+Recenter the stars (yes):
+ Recenter the stars: yes
+Refit the sky (no):
+ Refit the sky: no
+Psf radius in scale units (5.):
+ New psf radius: 5. scale units 5. pixels
+Fitting radius in scale units (3.):
+ New fitting radius: 3. scale units 3. pixels
+Minimum good data value (50.) (CR or value):
+ New minimum good data value: 50. counts
+Maximum good data value (24500.) (CR or value):
+ New maximum good data value: 24500. counts
+
+Star: 1 X: 40.97 Y: 4.01 Mag: 17.22 Sky: 100.74
+ FIT: Star: 1 X: 41.01 Y: 4.03 Mag: 17.22 Sky = 100.74
+Star: 2 X: 23.06 Y: 7.03 Mag: 17.65 Sky: 100.33
+ FIT: Star: 2 X: 23.02 Y: 7.05 Mag: 17.75 Sky = 100.33
+Star: 3 X: 18.02 Y: 7.96 Mag: 17.48 Sky: 99.40
+ FIT: Star: 3 X: 17.98 Y: 8.00 Mag: 17.57 Sky = 99.40
+Star: 4 X: 25.99 Y: 22.01 Mag: 16.80 Sky: 101.34
+ FIT: Star: 4 X: 25.99 Y: 22.01 Mag: 16.81 Sky = 101.34
+Star: 5 X: 35.98 Y: 22.00 Mag: 16.37 Sky: 101.12
+ FIT: Star: 5 X: 35.97 Y: 22.02 Mag: 16.39 Sky = 101.12
+Star: 6 X: 8.02 Y: 22.97 Mag: 16.60 Sky: 98.89
+ FIT: Star: 6 X: 8.02 Y: 22.97 Mag: 16.63 Sky = 98.89
+Star: 7 X: 30.97 Y: 25.01 Mag: 17.05 Sky: 101.29
+ FIT: Star: 7 X: 30.96 Y: 25.04 Mag: 17.05 Sky = 101.29
+Star: 8 X: 28.96 Y: 33.92 Mag: 17.78 Sky: 100.62
+ FIT: Star: 8 X: 28.96 Y: 33.93 Mag: 17.74 Sky = 100.62
+Star: 9 X: 35.98 Y: 42.03 Mag: 16.59 Sky: 101.04
+ FIT: Star: 9 X: 35.98 Y: 42.01 Mag: 16.60 Sky = 101.04\fR
+.YE
+
+In this example the user chose to recenter the stars (almost always
+the best choice), and not to refit the sky (usually the best choice).
+Recentering should only be turned off if the initial centers in the input
+photometry file are known to be very accurate, e.g. they
+are derived from a better seeing
+image or one that has gone through some image restoration program.
+Users who elect to refit the sky,
+should realize that they will almost certainly need to increase
+the fitting radius to
+obtain a reasonable fitted sky value. Increasing the fitting radius
+however may also increase the scatter caused by neighboring stars.
+.PP
+The fitted stars can be subtracted from the input image with the \fBsubstar\fR
+task as shown below.
+
+.YS
+da> substar test test.pk.1 "" default default\fR
+.YE
+
+.PP
+
+.NH 4
+The Peak Output
+
+.PP
+Peak writes the quantities: id, xcenter, ycenter, mag, merr, msky,
+niter, chi, sharp, pier, and perror to the output photometry file and the
+rejections file.
+.IP [1]
+Id is the id number of the star as read from the input photometry file.
+.IP [2]
+Xcenter and ycenter are the best fit position of the star.
+If the star was rejected xcenter and ycenter will be the computed
+values of x and
+y at the time it was rejected. If \fIrecenter\fR is "no", xcenter and ycenter
+will be the position of the star in the input photometry file.
+.IP [3]
+Mag and merr are the best fit magnitude and magnitude error respectively.
+The instrumental magnitude is computed relative to the
+magnitude assigned to the
+psf model.
+Mag and merr are set to INDEF if the star cannot be fit to the psf model.
+.IP [4]
+Msky is the sky value in the input photometry file if fitsky = "no",
+otherwise it is the
+fitted sky value. If the star is not fit for some reason,
+msky is the computed sky value
+at the time the star was rejected.
+.IP [5]
+Niter is the number of iterations it took to fit the star. If this
+number if equal to the \fBdaopars\fR parameter \fImaxiter\fR the user should be
+suspicious of the computed positions, magnitudes, and sky values.
+However as the convergence criteria are
+conservative the star may still be reasonably well fit.
+Niter is set to 0 if the star cannot be fit to the psf model.
+.IP [6]
+Chi and sharp are measures of the goodness of fit and the shape
+of the star respectively. Chi should be ~ 1.0. If it is not then,
+either the object is not a single star, the noise model including
+one or more of the gain, readout noise, flat-fielding error, and
+interpolation error parameters for the image are incorrect, the
+psf model is a poor representation of the true psf, or the input
+image does not conform to the requirements of the DAOPHOT package.
+Sharp is a measure of the difference between the observed width
+of the object and the width of the psf model. Stars should have a sharpness
+value ~ 0.0, resolved objects a sharpness of > 0.0, and cosmic rays and similar
+blemishes a sharpness of < 0. Chi and sharp are set to INDEF if the star
+cannot be fit to the psf model.
+.IP [7]
+Pier and perror are an integer error code and error string respectively.
+If no error was encountered during the fit pier is 0 and perror is
+"No_error". Stars are rejected by the \fBpeak\fR task if 1) the sky value of
+the star is INDEF 2) there are too few good data pixels to fit the star
+3) the fitting matrix is singular meaning a unique solution could not
+be found 4) the star is too faint, i.e. its signal / noise < 2.0. A fifth
+condition, the solution did not converge by \fImaxiter\fR iterations, is not
+used to reject the star, although users should be suspicious of a star
+for which niter = \fImaxiter\fR.
+
+
+.NH 3
+Fitting Stars with Group, Grpselect, Nstar and Substar
+
+.PP
+Stars can be fit simultaneously in fixed groups using the
+\fBnstar\fR task.
+This psf fitting technique requires grouping the stars
+into physically meaningful
+associations with the \fBgroup\fR and/or the \fBgrpselect\fR tasks,
+fitting the stars in each group simultaneously with the \fBnstar\fR task,
+and subtracting
+the fitted stars from the image with the \fBsubstar\fR task.
+\fBNstar\fR is the task of choice when the user wishes to explicitly
+control the grouping process or fit stars in a small number of
+widely separated groups efficiently.
+\fBNstar\fR is most commonly used to fit the psf model to the psf stars and
+their neighbors.
+
+.NH 4
+The Group and Nstar Algorithms
+
+.PP
+By default the \fBgroup\fR task performs the following steps:
+
+.IP [1]
+reads the task parameters, including the name of the input image, the input
+photometry file, the psf model, the output photometry
+file, and the \fBdatapars\fR and \fBdaopars\fR
+algorithm parameter sets
+.IP [2]
+reads the ids, x and y coordinates, magnitudes, and sky values
+of up to \fImaxnstar\fR stars in the input photometry file, computes an
+approximate magnitude for the stars with INDEF magnitudes, and sorts
+the stars in increasing order of y
+.IP [3]
+finds all the stars which are within \fIpsfrad\fR + \fIfitrad\fR + 1 pixels
+of a given star, evaluates the psf of the brighter star at a distance
+of \fIfitrad\fR pixels from
+the fainter, and if this value is larger than \fIcritovlap\fR
+times the expected
+error per pixel, or the two stars are within \fIfitrad\fR + 1 pixels of
+each other, adds the star to the group
+.IP [4]
+writes the group and star ids, x and y coordinates, magnitudes and sky values
+for all the groups, to the output group photometry file.
+
+.PP
+By default the \fBnstar\fR task performs the following steps:
+
+.IP [1]
+reads the task parameters including the name of
+the input image, the input group file, the psf image, the
+output group photometry and rejections files and the \fBdatapars\fR and
+\fBdaopars\fR algorithm parameter sets
+.IP [2]
+reads the group and star ids, x and y coordinates, magnitudes, and
+sky values for all the stars in a group from the input group photometry
+file
+.IP [3]
+extracts the data within psfrad + fitrad pixels
+around the group and
+performs a weighted least-squares fit of the psf model to the extracted
+data
+.IP [4]
+rejects stars which have an undefined sky value, which are too faint (more
+than 12.5 magnitudes fainter than the psf), which are
+too noisy (faintest star in the group less than a 1.0, 1.5, or 2.0
+sigma detection after 5, 10, and 15 iterations or convergence respectively),
+for which there are too few good
+pixels to compute a fit, for which a unique solution cannot
+be found, which have merged with another star (fainter star < 0.37 *
+fwhmpsf from a brighter star in the group), which are both too
+noisy and too
+close to a brighter star (a star is between .37 and 1.0 fwhm of
+a brighter star and is a 1.0, 1.5, or 2.0 sigma detection before
+iterations 5, 10, and 15 respectively), or which are in a group
+too large (> than the value of the \fImaxgroup\fR parameter) to be reduced.
+.IP [5]
+estimates new x and y coordinates and magnitudes for each star in
+the group
+.IP [6]
+iterates until all the stars in the group satisfy the convergence criteria
+backing up the iteration counter by 1 each time a star is rejected from
+the group to allow the remaining stars time to settle into a new fit
+.IP [7]
+writes the star and group ids, new x and y coordinates, sky values,
+new magnitudes and magnitude errors, chi and sharpness statistics
+for the fitted stars to the
+output group photometry and rejections files
+.IP [8]
+repeats steps [2]-[7] for each group in the input group photometry file.
+
+.NH 4
+Running Group, Grpselect, and Nstar
+
+.PP
+Before \fBnstar\fR can be run the stars must be grouped with the
+\fBgroup\fR task as shown below.
+
+.YS
+da> group test default default default
+
+Psf radius in scale units (5.):
+ New psf radius: 5. scale units 5. pixels
+Fitting radius in scale units (3.):
+ New fitting radius: 3. scale units 3. pixels
+Critical overlap in stdevs per pixel (1.): .2
+ New critical overlap: 0.2 stdevs per pixel
+Minimum good data value (50.) (CR or value):
+ New minimum good data value: 50. counts
+Maximum good data value (24500.) (CR or value):
+ New maximum good data value: 24500. counts
+
+Size of Number of
+group groups
+
+1 4
+2 1
+3 1
+
+Total of 9 stars in 6 groups\fR
+.YE
+
+The critical overlap parameter \fIcritovlap\fR determines the degree
+to which crowding and/or random photometric errors are expected/allowed
+to influence the photometry. If the default value of 1 is required to group
+all the stars into associations of <= the current value of
+\fImaxgroup\fR stars, then unavoidable random photometric errors and
+crowding errors will affect the photometry about equally.
+If a critical
+overlap much greater than 1 is required, then crowding errors will
+dominate the random photometric errors. If a critical overlap
+much less than 1 does the
+job then
+unavoidable random photometric errors will dominate, and crowding errors
+are relatively insignificant.
+In
+the previous example the user chose to set \fIcritovlap\fR to a value
+much smaller
+than 1 to test whether random photometric rather than crowding errors will
+dominate the photometry.
+.PP
+If the first run of \fBgroup\fR separates all the stars into groups of less than
+60 all is well and the user can proceed to the \fBnstar\fR task. Otherwise
+the \fBgrpselect\fR task must be used to select out the larger groups
+and subdivide them as shown in the following example.
+
+.YS
+da> grpselect test.grp.1 small.grp 1 60
+.YE
+
+.IP ...
+First separate out the small groups.
+.LP
+
+.YS
+da> grpselect test.grp.1 big.grp.1 61 10000
+.YE
+
+.IP ...
+Next separate out the large groups.
+.LP
+
+.YS
+da> group test big.grp.1 default big.grp.2 critovlap=1.0
+.YE
+
+.IP ...
+Rerun the group task on the large group file with a bigger value
+of critovlap.
+.LP
+
+.YS
+da> pconcat small.grp,big.grp.2 all.grp
+.YE
+
+.IP ...
+Finally concatenate all the new group files together.
+.LP
+This step is not required for the test image since there are only a
+few stars and the field is not very crowded.
+
+.PP
+Run \fBnstar\fR on the grouped photometry file and \fBsubstar\fR on the
+fitted photometry file.
+
+.YS
+da> nstar test default default default default
+
+Recenter the stars (yes):
+ Recenter the stars: yes
+Refit the sky (no):
+ Refit the sky: no
+Psf radius in scale units (5.):
+ New psf radius: 5. scale units 5. pixels
+Fitting radius in scale units (3.):
+ New fitting radius: 3. scale units 3. pixels
+Maximum group size in number of stars (60):
+ New maximum group size: 60 stars
+Minimum good data value (50.) (CR or value):
+ New minimum good data value: 50. counts
+Maximum good data value (24500.) (CR or value):
+ New maximum good data value: 24500. counts
+
+Group: 1 contains 1 stars
+ ID: 1 XCEN: 41.01 YCEN: 4.03 MAG: 17.22
+Group: 2 contains 2 stars
+ ID: 2 XCEN: 23.04 YCEN: 7.07 MAG: 17.75
+ ID: 3 XCEN: 17.99 YCEN: 8.00 MAG: 17.57
+Group: 3 contains 3 stars
+ ID: 5 XCEN: 35.98 YCEN: 22.01 MAG: 16.39
+ ID: 7 XCEN: 30.99 YCEN: 25.04 MAG: 17.04
+ ID: 4 XCEN: 26.00 YCEN: 22.01 MAG: 16.80
+Group: 4 contains 1 stars
+ ID: 6 XCEN: 8.02 YCEN: 22.97 MAG: 16.63
+Group: 5 contains 1 stars
+ ID: 8 XCEN: 28.96 YCEN: 33.93 MAG: 17.74
+Group: 6 contains 1 stars
+ ID: 9 XCEN: 35.98 YCEN: 42.01 MAG: 16.60
+
+da> substar test default "" default default
+.YE
+
+The parameter \fImaxgroup\fR specifies the
+maximum number of stars that \fBnstar\fR will
+fit simultaneously. The default value of 60
+is a conservative number based
+on the observed numerical behavior of the matrix inversion routines.
+.PP
+For most crowded field photometry applications it is simpler and easier
+to use the automated \fBallstar\fR task.
+
+.NH 4
+The Nstar Output
+
+.PP
+By default \fBnstar\fR writes the quantities: id, group, xcenter, ycenter,
+mag, merr, msky, niter, chi, sharp, pier, and perror to the output
+photometry and rejections files.
+.IP [1]
+Id and group are the star and group id numbers in the input group
+photometry file.
+.IP [2]
+Xcenter and ycenter are the best fit coordinates of the star.
+If the star was rejected xcenter and ycenter will be the best fit
+values of x and y at the time it was rejected. If \fIrecenter\fR is "no"
+xcenter and ycenter will be the position of the star in the input
+group photometry file.
+.IP [3]
+Mag and merr are the best fit magnitude and magnitude error respectively.
+The instrumental magnitude is computed relative to the magnitude
+of the psf model.
+Mag and merr are set to INDEF if the star cannot be fit to the
+psf model.
+.IP [4]
+Msky is always the individual sky for the star in the input photometry
+file regardless of whether fitsky is "no" or "yes". In the former
+case the actual value of the sky used in \fBnstar\fR is
+the mean of all the sky values for all the stars in the group. In the
+latter case it is a fitted parameter.
+.IP [5]
+Niter is the number of iterations it took to fit the star. If \fBniter\fR
+is equal to the parameter \fImaxiter\fR the user should be
+suspicious of the result. However since the convergence criteria are
+quite tightly constrained the result may still be reasonable.
+Niter is set to 0 if the star cannot be fit to the psf model.
+.IP [6]
+Chi and sharp are measures of the goodness of fit and the star's shape
+respectively. Chi should be ~ 1.0. If it is not then
+either the object is not a single star,
+the noise model including the ccd gain and readout noise, the flat
+fielding error and the interpolation error parameters assumed for the image are
+not correct, the
+psf model is a poor representation of the true psf, or the input
+image does not conform to the requirements of the DAOPHOT package.
+Sharp is a measure of the difference between the observed width
+of the object and the width of the psf model. Stars should have sharpness
+values \(~= 0.0, resolved objects sharpness values > 0.0, and cosmic rays
+and similar blemishes sharpnesses values < 0.0. Chi and sharp are set to INDEF
+if the star cannot be fit to the psf model.
+.IP [7]
+Pier and perror are an integer error code and error string respectively.
+If no error was encountered during the fit, pier is 0 and perror is
+"No_error".
+
+.NH 3
+Fitting Stars With Allstar
+
+.PP
+\fBAllstar\fR groups, fits
+and subtracts the fitted stars from the input image without intervention
+by the user.
+Because the grouping process is dynamic and the best
+fit stars are fit and subtracted first, fewer weak stars
+and noise spikes migrate to the position of stronger stars in \fBallstar\fR
+than is the case with \fBnstar\fR. \fBAllstar\fR replaces the functionality
+of the tasks \fBgroup\fR, \fBgrpselect\fR, \fBnstar\fR, and \fBallstar\fR.
+\fBAllstar\fR is the task of choice for doing crowded
+field photometry with DAOPHOT.
+
+.NH 4
+The Allstar Algorithm
+
+.PP
+By default the \fBallstar\fR task performs the following steps:
+.IP [1]
+reads the task parameters including the name of the input image, the input
+photometry file, the psf
+model, the output photometry and rejections files, the output
+subtracted image, and the \fBdatapars\fR and \fBdaopars\fR algorithm
+parameter sets
+sets
+.IP [2]
+reads the ids, x and y coordinates, magnitudes, and sky values for
+the first \fImaxnstars\fR stars in the input photometry file, rejecting
+at the start stars which have undefined sky values or which
+are too close to another star
+.IP [3]
+reads the original image into a working array and initializes
+two scratch arrays containing 1) the noise model and 2) the residuals from
+the current best fit for all the stars
+.IP [4]
+at the beginning of each iteration:
+1) groups the stars into physical associations that contain fewer
+than \fImaxgroup\fR
+stars, regrouping as necessary until all the groups are less than
+\fImaxgroup\fR or until the group is too dense to reduce, 2)
+subtracts the current best fit for all the stars that are still unfit from
+the working copy of the image and stores the results in the residuals
+array 3) initializes the weight array for all the unfitted stars
+.IP [5]
+during each iteration: 1) extracts the data within fitrad pixels
+around each star in each group from the residuals image, 2)
+performs a weighted non-linear least-squares fit of the psf model to
+the extracted
+data, ignoring bad pixels and down-weighting pixels that deviate too
+far from the psf model, and 3) computes new x and y coordinates and
+magnitudes for each star in each group
+.IP [6]
+after the fourth iteration 1) writes the id, new x and y coordinates,
+sky value, new magnitude and magnitude error, number of iterations
+required to fit the star, and the chi and sharpness statistic of stars
+which meet the convergence criteria, to
+the output photometry file, 2) subtracts the fitted star permanently from
+the working copy of the image, 3) updates the
+noise model in the weight array, 4) and eliminates the star from
+the active star list
+.IP [7]
+after the fourth iteration rejects stars which: 1) are too faint
+(more than 12.5 magnitudes fainter
+than the psf model), 2) have too low a signal-to-
+noise ratio (1.0, 1.5 and 2.0 sigma detection after 5, 10, and 15 iterations
+respectively), 3) have too few good
+pixels to compute a fit, 4) do not permit a unique solution,
+5) have merged with another star (star is
+< 0.37 * fwhmpsf from a brighter star), 6) are both too noisy
+and too close to a neighbor star (star is between 0.37 and 1.0 * fwhmpsf from
+a brighter star in the group and is a 1.0, 1.5, or 2.0 sigma
+detection before iterations 5, 10, and 15 respectively),
+or 7) are part of a group too dense to be reduced.
+.IP [8]
+writes out the final version of the work array into the output subtracted
+image
+
+.NH 4
+Running Allstar
+
+.PP
+\fBAllstar\fR is run as shown below.
+
+.YS
+da> allstar test default default default default default
+
+Recenter the stars (yes):
+ Recenter the stars: yes
+Refit the sky (no):
+ Refit the sky: no
+Psf radius in scale units (5.):
+ New psf radius: 5. scale units 5. pixels
+Fitting radius in scale units (3.):
+ New fitting radius: 3. scale units 3. pixels
+Maximum group size in number of stars (60):
+ New maximum group size: 60 stars
+Minimum good data value (50.) (CR or value):
+ New minimum good data value: 50. counts
+Maximum good data value (24500.) (CR or value):
+ New maximum good data value: 24500. counts
+
+NITER = 1
+NITER = 2
+NITER = 3
+NITER = 4
+FITTING: ID: 1 XCEN: 41.01 YCEN: 4.03 MAG: 17.22
+FITTING: ID: 4 XCEN: 26.00 YCEN: 22.01 MAG: 16.80
+FITTING: ID: 7 XCEN: 30.99 YCEN: 25.04 MAG: 17.04
+FITTING: ID: 6 XCEN: 8.02 YCEN: 22.97 MAG: 16.63
+FITTING: ID: 8 XCEN: 28.96 YCEN: 33.93 MAG: 17.74
+FITTING: ID: 9 XCEN: 35.98 YCEN: 42.01 MAG: 16.60
+NITER = 5
+FITTING: ID: 2 XCEN: 23.04 YCEN: 7.05 MAG: 17.75
+FITTING: ID: 3 XCEN: 18.00 YCEN: 7.99 MAG: 17.56
+FITTING: ID: 5 XCEN: 35.98 YCEN: 22.01 MAG: 16.39
+.YE
+
+.PP
+Users can easily run \fBallstar\fR as a background job as shown below.
+
+.YS
+da> allstar test default default default default default verify- \\
+ >& allstar.out &
+.YE
+
+.NH 4
+The Allstar Output
+
+.PP
+\fBAllstar\fR writes the following
+quantities: id, xcenter, ycenter, mag, merr, msky, niter, chi, sharp,
+pier, and perror to the output photometry and
+rejections files.
+.IP [1]
+Id is the id number of the star as read from the input photometry file.
+.IP [2]
+Xcenter and ycenter are the best fit position of the star.
+If the star was rejected xcenter and ycenter will be the computed
+values of x and
+y at the time it was rejected. If \fIrecenter\fR is "no", xcenter and ycenter
+will be the position of the star in the input photometry file.
+.IP [3]
+Mag and merr are the best fit magnitude and magnitude error respectively.
+The instrumental magnitude is computed relative to the magnitude of the
+psf model.
+Mag and merr are set to INDEF if the star cannot be fit to the psf model.
+.IP [4]
+Msky is the sky value in the input photometry file if \fIfitsky\fR = "no",
+otherwise it is the
+recomputed sky value. If \fIfitsky\fR is "yes" the sky is recomputed
+every third iteration after the current best fit for the star is
+subtracted from the image data. The new sky value is set to the
+average of 40% of the sky pixels, centered on the median sky value,
+which are inside the sky
+annulus defined by the parameters \fIsannulus\fR and
+\fIwsannulus\fR. The sky value is not recomputed
+if there are fewer than 100 sky pixels in the specified sky annulus
+even if \fIfitsky\fR is "yes".
+If the star is not fit for some reason,
+msky is the sky value at the time the star was rejected.
+.IP [5]
+Niter is the number of iterations it took to fit the star. If this
+number is equal to \fImaxiter\fR the user should be
+suspicious of the result. However as the convergence criteria are
+conservative the star may still be reasonably well fit.
+Niter is set to 0 if the star cannot be fit to the psf model.
+.IP [6]
+Chi and sharp are measures of the goodness of fit and the shape
+respectively. Chi should be ~ 1.0. If it is not, then
+either the object is not a single star, the noise model including
+one or more of the gain, readout noise, flat-fielding error, and
+interpolation error parameters for the image are incorrect, the
+psf model is a poor representation of the true psf, or the input
+image does not conform to the requirements of the DAOPHOT package.
+Sharpness is a measure of the difference between the observed width
+of the object and the width of the psf model. Stars should have a sharpness
+value ~ 0.0, resolved objects a sharpness of > 0.0, and cosmic rays and similar
+blemishes a sharpness of < 0. Chi and sharp are set to INDEF if the star
+cannot be fit for some reason.
+.IP [7]
+Pier and perror are an integer error code and error string respectively.
+If no error was encountered during the fit, pier is 0 and perror is
+"No_error".
+
+.NH 2
+Examining the Output Photometry Files
+
+.PP
+The identical tools can be used to examine the output of the \fBpeak\fR,
+\fBnstar\fR, and \fBallstar\fR tasks. Some examples using the output of
+\fBallstar\fR are shown below.
+.PP
+The following command produces a plot of magnitude error versus magnitude.
+
+.YS
+da> pdump test.als.1 mag,merr yes | graph point+
+.YE
+
+The following command produces a plot of chi versus magnitude.
+
+.YS
+da> pdump test.als.1 mag,chi yes | graph STDIN point+
+.YE
+
+The following command produces a plot of chi versus sharpness.
+
+.YS
+da> pdump test.als.1 sharp,chi yes | graph STDIN point+
+.YE
+
+The output photometry file can also be examined interactively
+with the \fBpexamine\fR task and the displayed subtracted image.
+Note that the fitted stars are marked in green and the rejected stars
+are marked in red on the display.
+
+.YS
+da> display test.sub.1 1 fi+
+
+da> pdump test.als.1 xcenter,ycenter yes | tvmark 1 STDIN col=205
+
+da> pdump test.arj.1 xcenter,ycenter yes | tvmark 1 STDIN col=204
+
+da> pexamine test.als.1 "" test.sub.1
+.YE
+
+.IP ...
+A plot of magnitude error versus magnitude appears on the screen.
+.IP ...
+The user moves to a discrepant point in the graph and types o to get a
+listing of the results for the star, r to get a radial profile plot
+around the subtracted star, and concludes on the basis of the plots
+that the bad chi value is due to the star being a close double.
+.IP ...
+The user types i to switch to image cursor mode,
+moves to several other stars with poor subtractions and types
+s to see a surface plot of the residuals.
+.IP ...
+The user types q to quit.
+
+.NH 2
+Problems with the Photometry
+
+.PP
+Bad chi values in, and poor
+subtractions of, \fBpeak\fR, \fBnstar\fR or \fBallstar\fR
+photometry can usually be traced to: 1) a psf model which was
+poorly determined in the first place, e.g. poor choice of
+parameters, bad choice of
+psf stars or too few stars used for determining a good variable psf model,
+2) data reduction problems e.g. the mean sky value was subtracted from the
+image, the image statistics have been altered, or cosmic ray removal
+clipped the tops of the stars, to give a few of many examples,
+or 3) the properties of the image, e.g. non-linearity, a psf which has
+very high order variability or very undersampled data, make computation
+of a good psf model difficult or impossible.
+.PP
+Bad chi values can also be caused by incorrect
+values of gain and readout noise or by a data reduction operation
+which has significantly affected the image statistics.
+.PP
+Poor sky fitting can also cause scatter
+in the photometry. Users should carefully check the position of the
+sky annulus used in \fBphot\fR if they are seeing poor subtractions.
+If the images have a rapidly varying
+background due, due for example to nebulosity, it might be useful to
+check out the alternate sky fitting routines, median or centroid, in the
+\fBphot\fR task. The refit sky option in \fBpeak\fR and \fBnstar\fR
+should be exercised with caution
+since a larger fitting radius is often required
+to get a reasonable sky fit, than is required to get good positions
+and magnitudes, and this in turn can cause more scatter
+in the photometry due to the influence of neighbors. On the other
+hand the refit sky option in \fBallstar\fR can often significantly
+reduce scatter in very crowded regions since it can use data closer to
+or even underneath (!) the star to improve the sky estimate.
+Users who use this option must remember to set the inner
+radius of the \fBallstar\fR sky annulus to avoid the inner stellar
+core region where there is a lot of noise in the subtraction.
+.PP
+After running \fBsubstar\fR on a file produced by the \fBpeak\fR
+task, users will sometimes see large holes in the data at the
+position of some subtracted
+stars. This is usually caused by fainter stars (which are fit individually)
+migrating to the position of a brighter nearby star and then being
+subtracted out twice by \fBsubstar\fR. Keeping the fitting radius small
+will help minimize this problem, but if it is frequent and the frame
+is somewhat crowded, the user should run \fBnstar\fR or \fBallstar\fR
+instead of \fBpeak\fR.
+.PP
+A similar problem can be caused by users running \fBdaofind\fR
+with a very low threshold and detecting a lot of noise spikes, which
+then migrate to the positions of brighter stars
+and cause scatter and holes in the subtracted \fBpeak\fR photometry,
+or attach themselves to noise spikes in the stellar profiles and cause
+scatter and holes in the subtracted \fBnstar\fR photometry.
+Similar problems can affect \fBallstar\fR photometry but to a much
+lesser degree since the
+stars are grouped dynamically and subtracted from the input data as
+they are fit. For all three photometry tasks spurious detections
+can consume a lot of excess computer time because the stellar groups
+become much larger.
+
+.NH 2
+Detecting Stars Missed By Daofind
+
+.PP
+In very crowded fields many new stars, missed by the first run of \fBdaofind\fR,
+will be detected after
+the first run of \fBpeak\fR+\fBsubstar\fR, \fBnstar\fR+\fBsubstar\fR,
+or \fBallstar\fR. If there
+are many "missed" stars
+\fBdaofind\fR should be run on the subtracted image after increasing the
+\fIthreshold\fR parameter to avoid detecting the residuals
+of previously subtracted stars. If there
+are only a few such stars they can be "detected" by creating a coordinate
+file using the subtracted image and \fBtvmark\fR in interactive mode.
+Examples of both techniques are shown below.
+
+.YS
+da> daofind test.sub.1 newstars.coo threshold=5.0
+.YE
+
+or
+
+.YS
+da> display test.sub.1 1 fi+
+
+da> pdump test.als.1 xcen,ycen yes | tvmark 1 STDIN col=204
+
+da> tvmark 1 newstars.coo inter+
+.YE
+
+.IP ...
+Move cursor to missing stars and tap the \fBa\fR key to append them to the
+output coordinate file.
+
+.NH 2
+Initializing the Missing Star Photometry with Phot
+
+.PP
+The next step is to get initial photometry for the "missing"
+stars. The simplest way is
+to run \fBphot\fR on the original image using the coordinate list created
+by \fBdaofind\fR or \fBtvmark\fR, and the same algorithm parameters as
+were used
+in the first run of \fBphot\fR. It is also possible to use \fBphot\fR directly
+in interactive mode to create a photometry file of missed stars. Both
+options are shown below.
+
+.YS
+da> phot test newstars.coo newstars.mag
+.YE
+
+or
+
+.YS
+da> display test.sub.1 1 fi+
+
+da> pdump test.als.1 xcen,ycen yes | tvmark 1 STDIN col=204
+
+da> phot test "" newstars.mag centroid=calgorithm inter+
+.YE
+
+.IP ...
+Point the cursor to the missing stars and tap \fBspacebar\fR.
+.LP
+
+Note that if the stars are or were marked with the cursor, the user must
+turn centroiding on in order to center them correctly.
+
+.NH 2
+Merging Photometry Files with Pfmerge
+
+.PP
+The photometry file containing the aperture photometry for the new stars
+can be combined with the best psf fitting photometry already computed
+by the \fBnstar\fR or \fBallstar\fR tasks
+for the original star list, using the task \fBpfmerge\fR as shown below.
+The \fBprenumber\fR task ensures that the new stars all have unique ids.
+
+.YS
+da> pfmerge test.als.1,newstars.mag newstars.als.1
+da> prenumber newstars.als.1\fR
+.YE
+
+
+.NH 2
+Refitting the Stars with Allstar
+
+.PP
+After the photometry files have been merged a final run of \fBallstar\fR or
+\fBgroup\fR+\fBnstar\fR+\fBsubstar\fR on the combined file in order
+to compute accurate magnitudes for the new stars should be made
+as shown below.
+
+.YS
+da> allstar test newstars.als.1 default default default default
+.YE
+
+.NH 2
+Examining the Subtracted Image
+
+.PP
+The user should search the subtracted image for any remaining unfit
+stars and perform another iteration of \fBdaofind\fR, \fBphot\fR,
+\fBpfmerge\fR and \fBallstar\fR to computed fitted magnitudes for
+the new objects.
+
+.NH 2
+Computing an Aperture Correction
+
+.PP
+The aperture correction is the number which must be added to the
+fitted instrumental magnitudes computed by the \fBpeak\fR,
+\fBnstar\fR, or \fBallstar\fR tasks to produce the total instrumental
+magnitude.
+.PP
+In order to compute aperture corrections for an image with a constant psf model
+the user must:
+.IP [1]
+identify several bright isolated stars in the input image or subtract
+all the neighbors from around several bright stars such as the
+psf stars using the current psf model and the \fBsubstar\fR task
+.IP [2]
+using a minimum aperture radius equal to the one used in \fBphot\fR to compute
+initial aperture photometry for all the crowded field stars,
+and a maximum aperture radius equal to the one through which
+the instrumental magnitudes of the standard stars were or will be measured,
+use the \fBphot\fR task to
+do multi-aperture photometry of the stars identified in [1] through at
+least five apertures
+.IP [3]
+run the \fBmkapfile\fR task in the PHOTCAL package on the aperture
+photometry file produced in 2, to determine the aperture
+correction for the image as shown below
+.LP
+
+.YS
+da> phot test "" test.apmags calg=centroid aperture="3,3.5,4.0,4.5 5.0"
+.YE
+
+.IP ...
+Do multi-aperture photometry of the selected stars.
+.LP
+
+.YS
+da> mkapfile test.apmags 5 test.apcors
+.YE
+
+.IP ...
+Compute the aperture correction between apertures 1 and 5.
+
+.PP
+To compute compute aperture corrections for an image with a variable psf model
+the user must:
+.IP [1]
+identify several bright isolated stars in the input image or subtract
+all the neighbors from around several bright stars such as the
+psf stars using the current psf model and the \fBsubstar\fR task
+.IP [2]
+using a photometry aperture equal to the one through which
+the magnitudes of the standard stars were or will be measured,
+use the \fBphot\fR task to
+do aperture photometry of the stars identified in [1]
+.IP [3]
+extract the fitted magnitudes for these stars from existing \fBnstar\fR
+or \fBallstar\fR photometry or recompute them using the
+\fBnstar\fR or \fBallstar\fR tasks and the current psf model
+.IP [4]
+set the aperture correction to the mean difference between the fitted
+magnitudes computed in [3] and the aperture photometry magnitudes
+computed through the large aperture in [2]
+
+.NH
+References
+
+.LP
+.nf
+Stetson, P. B. 1987 Pub .A.S.P., \fB99\fR, 191
+Stetson, P. B., Davis, L.E. and Crabtree, D.B. 1989, in
+ \fICCDs in Astronomy\fR, G.H. Jacoby, San Francisco: Astronomical
+ Society of the Pacific, 289
+Stetson, P. B. 19 Pub .A.S.P., \fB102\fR, 932
+Stetson, P.B, 1992, \fIUser's Manual for DAOPHOT II\fR
+Stetson, P. B. 1992 in \fIAstronomical Data Analysis Software and Systems I\fR,
+ D.M. Worall, C. Biemesderfer, and J. Barnes, San Francisco: Astronomical
+ Society of the Pacific, 297
+.fi
+
+.NH
+Appendices
+
+.NH 2
+The Instrumental Magnitude Scale
+
+.PP
+The instrumental magnitude scale is set by the magnitude assigned
+to the psf model, the quantity \fIpsfmag\fR stored in the psf image header.
+Psfmag is the magnitude of the first psf star in the input photometry
+file, usually but not always the file written by the \fBphot\fR task.
+If magnitudes were measured through more than one aperture
+in \fBphot\fR, the magnitude used will be the
+magnitude through the smallest aperture.
+
+.NH 2
+The Analytic Psf Models
+
+.PP
+The functional forms of the currently supported analytic psf models
+are listed below.
+The quantity A is a normalization factor. The Pn are
+the parameters which are fit during the psf modeling process.
+
+.nf
+ z = x ** 2 / p1 ** 2 + y ** 2 / p2 ** 2
+ gauss = A * exp (-0.5 * z)
+
+ z = x ** 2 / p1 ** 2 + y ** 2 / p2 ** 2 + x * y * p3
+ moffat15 = A / (1 + z) ** 1.5
+ moffat25 = A / (1 + z) ** 2.5
+
+ z = x ** 2 / p1 ** 2 + y ** 2 / p2 ** 2 + x * y * p3
+ lorentz = A / (1.0 + z)
+
+ z = x ** 2 / p1 ** 2 + y ** 2 / p2 ** 2
+ e = x ** 2 / p1 ** 2 + y ** 2 / p2 ** 2 + x * y * p4
+ penny1 = A * ((1 - p3) / (1.0 + z) + p3 * exp (-0.693*e))
+
+ z = x ** 2 / p1 ** 2 + y ** 2 / p2 ** 2 + p5 * x * y
+ e = x ** 2 / p1 ** 2 + y ** 2 / p2 ** 2 + x * y * p4
+ penny2 = A * ((1 - p3) / (1.0 + z) + p3 * exp (-0.693*e))
+.fi
+
+.NH 2
+The Error Model
+
+.PP
+The predicted errors in the the DAOPHOT photometry are computed per
+pixel as shown below, where terms 1, 2, 3, and 4 represent the readout
+noise, the poisson noise, the flat-fielding error, and the
+interpolation error respectively. The quantities readnoise, epadu,
+I, M, p1, and p2 are the effective readout noise in electrons, the
+effective gain in
+electrons per ADU, the pixel intensity in ADU, the PSF model
+intensity in ADU, the FWHM in x in pixels, and the FWHM in y in pixels.
+
+.nf
+ error = sqrt (term1 + term2 + term3 + term4) (ADU)
+ term1 = (readnoise / epadu) ** 2
+ term2 = I / epadu
+ term3 = (.01 * flaterr * I) ** 2
+ term4 = (.01 * proferr * M / p1 / p2) ** 2
+.fi
+
+
+.NH 2
+The Radial Weighting Function
+
+.PP
+The radial weighting function employed by all the psf fitting tasks
+is shown below, where dx and dy are the distance of the pixel
+in question from the centroid of the star being fit.
+
+.nf
+ wtr = 5.0 / (5.0 + rsq / (1.0 - rsq))
+ rsq = (dx ** 2 + dy ** 2) / fitrad ** 2
+.fi
+
+.NH 2
+Total Weights
+
+.PP
+The total weight assigned each pixel in the fit is the
+following.
+
+.nf
+ wtp = wtr / error ** 2
+.fi
+
+.NH 2
+Bad Data Detection
+
+.PP
+Pixels less than the good data minimum \fIdatamax\fR or greater than
+the good data maximum \fIdatamax\fR are rejected immediately from the
+fit.
+.PP
+After a few iterations and if clipexp > 0, a clipping scheme to
+reject bad data is enabled. The weights of the pixels are
+recomputed as follows. Pixels having a residual of cliprange sigma
+will have their weight reduced by half.
+
+.nf
+ wt = wtp / (1.0 + (residual / error / chiold /
+ cliprange) ** clipexp)
+.fi
+
+.NH 2
+Stellar Mergers
+
+.PP
+In order for two stars to merge during the course of the psf fitting
+process either their separation must be < 0.37 * FWHM of the psf model,
+or their separation must be > 0.37 * FWHM but < 1.0 * FWHM of the
+psf model and the signal-to-noise ratio of the fainter is less than 1.0, 1.5,
+or 2.0 after iterations 4, 9, and 14 respectively.
+
+.NH 2
+Faint Stars
+
+.PP
+Stars are considered to be too faint if they are more than 12.5
+magnitudes fainter than the psf, or if after a certain number of iterations,
+they have a signal-to-noise ratio less than 2.0.
diff --git a/noao/digiphot/daophot/findpars.par b/noao/digiphot/daophot/findpars.par
new file mode 100644
index 00000000..f42b3e89
--- /dev/null
+++ b/noao/digiphot/daophot/findpars.par
@@ -0,0 +1,12 @@
+# FINDPARS
+
+threshold,r,h,4.0,,,Threshold in sigma for feature detection
+nsigma,r,h,1.5,,,Width of convolution kernel in sigma
+ratio,r,h,1.0,0.0,1.0,Ratio of minor to major axis of Gaussian kernel
+theta,r,h,0.0,0.0,180.0,Position angle of major axis of Gaussian kernel
+sharplo,r,h,.2,,,Lower bound on sharpness for feature detection
+sharphi,r,h,1.0,,,Upper bound on sharpness for feature detection
+roundlo,r,h,-1.0,,,Lower bound on roundness for feature detection
+roundhi,r,h,1.0,,,Upper bound on roundness for feature detection
+mkdetections,b,h,no,,,Mark detections on the image display?
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/fitskypars.par b/noao/digiphot/daophot/fitskypars.par
new file mode 100644
index 00000000..bbb17dd1
--- /dev/null
+++ b/noao/digiphot/daophot/fitskypars.par
@@ -0,0 +1,17 @@
+# SKY FITTING PARAMETERS
+
+salgorithm,s,h,"mode","|median|mode|centroid|gauss|crosscor|ofilter|histplot|radplot|constant|file|mean|",,Sky fitting algorithm
+annulus,r,h,10.0,,,Inner radius of sky annulus in scale units
+dannulus,r,h,10.0,,,Width of sky annulus in scale units
+skyvalue,r,h,0.0,,,User sky value
+smaxiter,i,h,10,,,Maximum number of sky fitting iterations
+sloclip,r,h,0.0,,,Lower clipping factor in percent
+shiclip,r,h,0.0,,,Upper clipping factor in percent
+snreject,i,h,50,,,Maximum number of sky fitting rejection iterations
+sloreject,r,h,3.0,,,Lower K-sigma rejection limit in sky sigma
+shireject,r,h,3.0,,,Upper K-sigma rejection limit in sky sigma
+khist,r,h,3.0,,,Half width of histogram in sky sigma
+binsize,r,h,0.10,,,Binsize of histogram in sky sigma
+smooth,b,h,no,,,Boxcar smooth the histogram
+rgrow,r,h,0.0,,,Region growing radius in scale units
+mksky,b,h,no,,,Mark sky annuli on the display
diff --git a/noao/digiphot/daophot/group.par b/noao/digiphot/daophot/group.par
new file mode 100644
index 00000000..6deeedd3
--- /dev/null
+++ b/noao/digiphot/daophot/group.par
@@ -0,0 +1,16 @@
+# Parameters for the GROUP task
+
+image,f,a,,,,"Image corresponding to the photometry file"
+photfile,f,a,default,,,"Photometry file (default: image.mag.?)"
+psfimage,f,a,default,,,"PSF image (default: image.psf.?)"
+groupfile,f,a,"default",,,"Output group file (default: image.grp.?)"
+datapars,pset,h,"",,,Data dependent parameters
+daopars,pset,h,"",,,Psf fitting parameters
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+wcspsf,s,h,)_.wcspsf,,,"The psf coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the input image pixels in memory?"
+verify,b,h,)_.verify,,,Verify critical group parameters?
+update,b,h,)_.update,,,Update critical group parameters?
+verbose,b,h,)_.verbose,,,Print group messages?
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/group/dpgconfirm.x b/noao/digiphot/daophot/group/dpgconfirm.x
new file mode 100644
index 00000000..4dcb3003
--- /dev/null
+++ b/noao/digiphot/daophot/group/dpgconfirm.x
@@ -0,0 +1,24 @@
+# DP_GCONFIRM -- Confirm the critical GROUP task parameters.
+
+procedure dp_gconfirm (dao)
+
+pointer dao # pointer to the group structure
+
+begin
+ call printf ("\n")
+
+ # Confirm the psf radius.
+ call dp_vpsfrad (dao)
+
+ # Confirm the fitting radius.
+ call dp_vfitrad (dao)
+
+ # Confirm the critical signal-to-noise ratio.
+ call dp_vcritsnratio (dao)
+
+ # Confirm the minimum and maximum good data values.
+ call dp_vdatamin (dao)
+ call dp_vdatamax (dao)
+
+ call printf ("\n")
+end
diff --git a/noao/digiphot/daophot/group/dpmkgroup.x b/noao/digiphot/daophot/group/dpmkgroup.x
new file mode 100644
index 00000000..741fc8b0
--- /dev/null
+++ b/noao/digiphot/daophot/group/dpmkgroup.x
@@ -0,0 +1,484 @@
+include <mach.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+
+define EPS_OVERLAP (1.0e-10)
+
+# DP_MKGROUP -- Arrange the photometry results into natural groupings
+# based on physical proximity and the signal-to-noise ratio.
+
+procedure dp_mkgroup (dao, im, grp)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to input image
+int grp # the output file descriptor
+
+bool overlap
+int i, maxgroup, curr_star, first_unknown, first_ingrp, nin_currgrp
+int curr_point, crit_point, ier
+pointer psffit, apsel, index, group_size, number
+real fradius, critovlap, bright_mag, read_noise, fitradsq, critsep
+real critsep_sq, xcurr, ycurr, dxcurr_frompsf, dycurr_frompsf, magcurr
+real skycurr, magcrit, skycrit, dxcrit_frompsf, dycrit_frompsf
+real deltax, deltay, radsq, rel_bright, radius, ratio, stand_err, dvdx, dvdy
+
+bool dp_gchkstar()
+real dp_usepsf()
+
+begin
+ # Get the daophot pointers.
+ psffit = DP_PSFFIT(dao)
+ apsel = DP_APSEL(dao)
+
+ # Return if the photometry file is empty.
+ if (DP_APNUM(apsel) <= 0)
+ return
+
+ # Store the original fitting radius.
+ fradius = DP_FITRAD(dao)
+ DP_FITRAD(dao) = min (DP_FITRAD(dao), DP_PSFRAD(dao))
+ DP_SFITRAD(dao) = DP_FITRAD(dao) * DP_SCALE(dao)
+
+ # Get some working memory.
+ call malloc (index, DP_APNUM(apsel), TY_INT)
+ call malloc (group_size, DP_APNUM(apsel), TY_INT)
+ call malloc (number, DP_APNUM(apsel), TY_INT)
+
+ # Initialize the group information.
+ call aclri (Memi[index], DP_APNUM(apsel))
+ call aclri (Memi[group_size], DP_APNUM(apsel))
+ call aclri (Memi[number], DP_APNUM(apsel))
+
+ # Check for INDEF results and fix them up..
+ call dp_gpfix (dao, im, bright_mag)
+
+ # Sort the stars into order of increasing y value. The star ID's, X,
+ # MAG and SKY values are still in the order in which they were read
+ # in. INDEX points to the proper value, i.e. Y (i) and X (index(i)).
+
+ call quick (Memr[DP_APYCEN(apsel)], DP_APNUM(apsel), Memi[index], ier)
+
+ # Bright_mag is the apparent magnitude of the brightest star
+ # in the input file. If this is INDEF then set to the PSFMAG.
+
+ if (! IS_INDEFR(bright_mag))
+ bright_mag = DAO_RELBRIGHT (psffit, bright_mag)
+ else
+ bright_mag = 1.0
+
+ # Smooth the PSF.
+ if ((DP_NVLTABLE(psffit) + DP_NFEXTABLE(psffit)) > 0)
+ call dp_smpsf (dao)
+
+ # Define some important constants in terms of the daophot parameters.
+
+ critovlap = DP_CRITSNRATIO(dao) * DP_CRITSNRATIO(dao)
+ read_noise = (DP_READNOISE (dao) / DP_PHOTADU(dao)) ** 2
+ fitradsq = (DP_FITRAD(dao) + 1) * (DP_FITRAD(dao) + 1)
+
+ ## Note that the definition of firadsq has been changed in this
+ ## version of group. This has been done so that the grouping
+ ## algorithm defaults to the one used by ALLSTAR in the case that
+ ## the critoverlap parameter is very large.
+ ## fitradsq = (2.0 * DP_FITRAD(dao)) * (2.0 * DP_FITRAD(dao))
+
+ # Define the critical separation.
+ critsep = DP_PSFRAD(dao) + DP_FITRAD(dao) + 1.0
+ critsep_sq = critsep * critsep
+
+ # Now we search the list for stars lying within one critical
+ # separation of each other. The stars are currently in a stack
+ # DP_APNUM(apsel) stars long. FIRST_INGRP points to the first star
+ # in the current group and starts out, of course, with the
+ # value CURR_STAR. CURR_STAR will point to the position in the stack
+ # occupied by the star which is currently the center of a circle
+ # of radius equal to the critical radius, within which we are
+ # looking for other stars. CURR_STAR starts out with a value of
+ # 1. FIRST_UNKNOWN points to the top position in the stack of the
+ # stars which have not yet been assigned to groups. FIRST_UNKNOWN
+ # starts out with the value 2. Each time through, the program goes
+ # down through the stack from FIRST_UNKNOWN to DP_APNUM(apsel) and
+ # looks for stars within the critical distance from the star at stack
+ # position CURR_STAR. When such a star is found, it changes places
+ # in the stack with the star at FIRST_UNKNOWN and FIRST_UNKNOWN is
+ # incremented by one. When the search has gotten to the last
+ # position in the stack (DP_APNUM(apsel)), the pointer CURR_STAR is
+ # incremented by one, and the search proceeds again from the new
+ # value of FIRST_UNKNOWN to DP_APNUM(apsel). If the pointer CURR_STAR
+ # catches up with the pointer FIRST_UNKNOWN, that means that the
+ # group currently being built up is complete. The number of stars in
+ # the newly-created group (the first star of which is at stack
+ # position FIRST_INGRP) is stored in array element GROUP_SIZE[FIRST_
+ # INGRP]. Then a new group is started beginning with the star at the
+ # current position CURR_STAR, ( = FIRST_UNKNOWN for the moment),
+ # FIRST_UNKNOWN is incremented by 1, and the next group is built up
+ # as before.
+
+ # Initialize.
+ maxgroup = 0
+ curr_star = 1
+ first_unknown = 1
+
+ # Loop through the list of stars.
+ while (curr_star <= DP_APNUM(apsel)) {
+
+ # Initialize for the next group.
+ first_ingrp = curr_star
+ nin_currgrp = 1
+ first_unknown = first_unknown + 1
+
+ # Begin defining a group.
+ while (curr_star < first_unknown) {
+
+ # Get the parameters of the current star.
+ curr_point = Memi[index+curr_star-1]
+ xcurr = Memr[DP_APXCEN(apsel)+curr_point-1]
+ ycurr = Memr[DP_APYCEN(apsel)+curr_star-1]
+ call dp_wpsf (dao, im, xcurr, ycurr, dxcurr_frompsf,
+ dycurr_frompsf, 1)
+ dxcurr_frompsf = (dxcurr_frompsf - 1.0) / DP_PSFX(psffit) - 1.0
+ dycurr_frompsf = (dycurr_frompsf - 1.0) / DP_PSFY(psffit) - 1.0
+ magcurr = Memr[DP_APMAG(apsel)+curr_point-1]
+ skycurr = Memr[DP_APMSKY(apsel)+curr_point-1]
+ if (IS_INDEFR(magcurr))
+ magcurr = bright_mag
+ else if (abs (DAO_MAGCHECK(psffit, magcurr)) > (MAX_EXPONENTR -
+ 1))
+ magcurr = bright_mag
+ else
+ magcurr = DAO_RELBRIGHT (psffit, magcurr)
+
+ # Go through the list of unassigned stars looking for stars
+ # within one critical distance of the current star.
+
+ do i = first_unknown, DP_APNUM(apsel) {
+
+ # Is this star within one critical separation of the
+ # current star ?
+
+ overlap = dp_gchkstar (Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memi[index], i, xcurr, ycurr,
+ critsep_sq, deltax, deltay, radsq)
+
+ # Break from the do loop if we are beyond the the critical
+ # separation.
+
+ if (deltay > critsep)
+ break
+ if (! overlap)
+ next
+
+ # Define the characteristics of the unknown star.
+
+ crit_point = Memi[index+i-1]
+ magcrit = Memr[DP_APMAG(apsel)+crit_point-1]
+ skycrit = Memr[DP_APMSKY(apsel)+crit_point-1]
+ call dp_wpsf (dao, im, Memr[DP_APXCEN(apsel)+crit_point-1],
+ Memr[DP_APYCEN(apsel)+i-1], dxcrit_frompsf,
+ dycrit_frompsf, 1)
+ dxcrit_frompsf = (dxcrit_frompsf - 1.0) / DP_PSFX(psffit) -
+ 1.0
+ dycrit_frompsf = (dycrit_frompsf - 1.0) / DP_PSFY(psffit) -
+ 1.0
+
+ # Check to see if stars overlap critically.
+
+ if ((critovlap > EPS_OVERLAP) && (radsq > fitradsq)) {
+
+ overlap = false
+
+ # Rel_bright is the brightness of the star currently
+ # being tested relative to the star in the center.
+
+ if (IS_INDEFR(magcrit))
+ rel_bright = bright_mag
+ else if (abs (DAO_MAGCHECK (psffit, magcrit)) >
+ (MAX_EXPONENTR - 1))
+ rel_bright = bright_mag
+ else
+ rel_bright = DAO_RELBRIGHT(psffit, magcrit)
+
+ # Determine the point at which to evaluate the PSF.
+
+ radius = sqrt (radsq)
+ ratio = (radius - (DP_FITRAD(dao) + 1)) / radius
+ deltax = ratio * deltax
+ deltay = ratio * deltay
+
+ # Determine which star is brighter.
+
+ if (magcurr > rel_bright) {
+ rel_bright = magcurr *
+ dp_usepsf (DP_PSFUNCTION(psffit), deltax,
+ deltay, DP_PSFHEIGHT(psffit),
+ Memr[DP_PSFPARS(psffit)],
+ Memr[DP_PSFLUT(psffit)], DP_PSFSIZE(psffit),
+ DP_NVLTABLE(psffit), DP_NFEXTABLE(psffit),
+ dxcurr_frompsf, dycurr_frompsf, dvdx, dvdy)
+ } else {
+ rel_bright = rel_bright *
+ dp_usepsf (DP_PSFUNCTION(psffit), -deltax,
+ -deltay, DP_PSFHEIGHT(psffit),
+ Memr[DP_PSFPARS(psffit)],
+ Memr[DP_PSFLUT(psffit)], DP_PSFSIZE(psffit),
+ DP_NVLTABLE(psffit), DP_NFEXTABLE(psffit),
+ dxcrit_frompsf, dycrit_frompsf, dvdx, dvdy)
+ }
+
+ # Do the stars overlap ?
+
+ if (! IS_INDEFR(skycurr) && ! IS_INDEFR(skycrit)) {
+ stand_err = read_noise + 0.5 * (skycurr +
+ skycrit) / DP_PHOTADU(dao)
+ if ((rel_bright * rel_bright) >= (stand_err *
+ critovlap))
+ overlap = true
+ }
+ }
+
+ # The two stars do overlap. Increment the pointers
+ # and move this star to the top of the stack.
+
+ if (overlap) {
+ nin_currgrp = nin_currgrp + 1
+ call dp_gswap2 (i, first_unknown, Memi[index],
+ Memr[DP_APYCEN(apsel)])
+ first_unknown = first_unknown + 1
+ }
+ }
+
+ curr_star = curr_star + 1
+ }
+
+ # Check for maximum group size.
+ if (nin_currgrp > maxgroup)
+ maxgroup = nin_currgrp
+
+ # Increment the number of groups versus size counter. Stars
+ # with undefined centers are always in a group with a membrship
+ # of 1 and are skipped.
+
+ if (! IS_INDEFR(xcurr) && ! IS_INDEFR(ycurr))
+ Memi[number+nin_currgrp-1] = Memi[number+nin_currgrp-1] + 1
+
+ # Define the group size.
+ Memi[group_size+first_ingrp-1] = nin_currgrp
+ }
+
+ # Write out all the groups to the output file.
+ call dp_wrtgroup (dao, im, grp, Memi[number], Memi[index],
+ Memi[group_size], maxgroup)
+
+ call mfree (number, TY_INT)
+ call mfree (index, TY_INT)
+ call mfree (group_size, TY_INT)
+
+ # Restore the original fitting radius.
+ DP_FITRAD(dao) = fradius
+ DP_SFITRAD(dao) = DP_FITRAD(dao) * DP_SCALE(dao)
+end
+
+
+# DP_GSWAP2 -- Interchange two stars in the photometry list and then shift
+# the list.
+
+procedure dp_gswap2 (star1, star2, index, y)
+
+int star1, star2 # the two star numbers to interchange
+int index[ARB] # the index array
+real y[ARB] # array of y positions
+
+int j, k, l, ihold
+real yhold
+
+begin
+ yhold = y[star1]
+ ihold = index[star1]
+
+ l = star1 + star2
+ do j = star2, star1 - 1 {
+ k = l - j
+ y[k] = y[k-1]
+ index[k] = index [k-1]
+ }
+
+ y[star2] = yhold
+ index[star2] = ihold
+end
+
+
+# DP_GCHKSTR -- Check to see if the unknown stars star is within one critical
+# separation of the current star.
+
+bool procedure dp_gchkstar (x, y, index, i, xcurr, ycurr, crit, deltax,
+ deltay, radsq)
+
+real x[ARB] # array of x positions
+real y[ARB] # array of y positions
+int index[ARB] # index array from the quick sort
+int i # position of test star in stack
+real xcurr # x position of current star
+real ycurr # y position of current star
+real crit # critical radius squared
+real deltax # output difference in x
+real deltay # output difference in y
+real radsq # separation squared
+
+begin
+ # Initialize the deltas.
+ deltax = MAX_REAL
+ deltay = MAX_REAL
+
+ # Check to see if star is within a critical radius. Reject the
+ # star if any of the positions are INDEF.
+ if (IS_INDEFR(xcurr) || IS_INDEFR(ycurr)) {
+ return (false)
+ } else if (IS_INDEFR(y[i]) || IS_INDEFR(x[index[i]])) {
+ return (false)
+ } else {
+ deltay = y[i] - ycurr
+ deltax = x[index[i]] - xcurr
+ radsq = deltax * deltax + deltay * deltay
+ if (radsq <= crit)
+ return (true)
+ else
+ return (false)
+ }
+end
+
+
+# DP_GPFIX -- Check for INDEF photometry and get estimate of magnitude.
+
+procedure dp_gpfix (dao, im, bright_mag)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+real bright_mag # apparent magnitude of the brightest star
+
+int i, lowx, lowy, nxpix, nypix
+pointer apsel, subim
+real fitrad, fitradsq, mingdata, maxgdata, x, y, sky, mag
+
+bool fp_equalr()
+pointer dp_gsubrast()
+real dp_gaccum()
+
+begin
+ # Get pointers to the daophot structures.
+ apsel = DP_APSEL (dao)
+
+ # Initialize.
+ fitrad = DP_FITRAD(dao)
+ fitradsq = fitrad * fitrad
+ if (IS_INDEFR (DP_MINGDATA(dao)))
+ mingdata = -MAX_REAL
+ else
+ mingdata = DP_MINGDATA(dao)
+ if (IS_INDEFR (DP_MAXGDATA(dao)))
+ maxgdata = MAX_REAL
+ else
+ maxgdata = DP_MAXGDATA(dao)
+ bright_mag = MAX_REAL
+
+ # Get a magnitude estimate for stars with INDEF magnitudes by summing
+ # all of the pixels within one fitting radius and scaling with respect
+ # to the PSFMAG.
+
+ do i = 1, DP_APNUM(apsel) {
+
+ # Check for undefined centers.
+ x = Memr[DP_APXCEN(apsel)+i-1]
+ y = Memr[DP_APYCEN(apsel)+i-1]
+ if (IS_INDEFR(x) || IS_INDEFR(y))
+ next
+
+ # Check for an undefined sky.
+ sky = Memr[DP_APMSKY(apsel)+i-1]
+ if (IS_INDEFR(sky))
+ next
+
+ # Correct the magnitudes.
+ mag = Memr[DP_APMAG(apsel)+i-1]
+ if (IS_INDEFR(mag)) {
+
+ # Get subraster around star position. If the subraster
+ # cannot be extracted leave the magnitude as INDEF.
+ subim = dp_gsubrast (im, x, y, fitrad, lowx, lowy, nxpix,
+ nypix)
+ if (subim == NULL)
+ next
+
+ # Estimate the value of the PSF.
+ mag = dp_gaccum (dao, Memr[subim], nxpix, nypix, lowx, lowy,
+ x, y, sky, fitradsq, mingdata, maxgdata)
+
+ if (! IS_INDEFR(mag))
+ Memr[DP_APMAG(apsel)+i-1] = mag
+
+
+ } else if (mag < bright_mag)
+ bright_mag = mag
+ }
+
+ if (fp_equalr (bright_mag, MAX_REAL))
+ bright_mag = INDEFR
+end
+
+
+# DP_GACCUM -- Accumulate the model counts.
+
+real procedure dp_gaccum (dao, subim, nxpix, nypix, lowx, lowy, x, y, sky,
+ fitradsq, mingdata, maxgdata)
+
+pointer dao # pointer to the daophot structure
+real subim[nxpix,nypix] # the input data subraster
+int nxpix, nypix # the dimensions of the data subraster
+int lowx, lowy # the lower left corner of the subraster
+real x, y # the coordinates of the star
+real sky # the sky value of the star
+real fitradsq # the fitting radius of the star
+real mingdata, maxgdata # the minimum and maximum good data values
+
+int k, j
+pointer psffit
+real mag, dxfrom_psf, dyfrom_psf, numer, denom, dx, dy, radsq, dvdx, dvdy
+real weight, value
+real dp_usepsf()
+
+begin
+ psffit = DP_PSFFIT(dao)
+
+ # Compute the distance from the psf star.
+ dxfrom_psf = (x - 1.0) / DP_PSFX(psffit) - 1.0
+ dyfrom_psf = (y - 1.0) / DP_PSFY(psffit) - 1.0
+
+ denom = 0.
+ numer = 0.
+ mag = INDEFR
+ do k = 1, nypix {
+ do j = 1, nxpix {
+
+ dx = real (lowx + j - 1) - x
+ dy = real (lowy + k - 1) - y
+ radsq = dx * dx + dy * dy
+ if ((radsq >= fitradsq) || (subim[j,k] < mingdata) ||
+ (subim[j,k] > maxgdata))
+ next
+
+ value = dp_usepsf (DP_PSFUNCTION(psffit), dx, dy,
+ DP_PSFHEIGHT(psffit), Memr[DP_PSFPARS(psffit)],
+ Memr[DP_PSFLUT(psffit)], DP_PSFSIZE(psffit),
+ DP_NVLTABLE(psffit), DP_NFEXTABLE(psffit),
+ dxfrom_psf, dyfrom_psf, dvdx, dvdy)
+ radsq = radsq / fitradsq
+ weight = 5. / (5. + radsq / (1.0 - radsq))
+ numer = numer + weight * value * (subim[j,k] - sky)
+ denom = denom + weight * value * value
+ }
+ }
+
+ if (denom > 0.0 && numer > 0.0)
+ mag = DP_PSFMAG(psffit) - 2.5 * log10 (numer / denom)
+
+ return (mag)
+end
diff --git a/noao/digiphot/daophot/group/dpsmpsf.x b/noao/digiphot/daophot/group/dpsmpsf.x
new file mode 100644
index 00000000..96cdb324
--- /dev/null
+++ b/noao/digiphot/daophot/group/dpsmpsf.x
@@ -0,0 +1,199 @@
+include <mach.h>
+include "../lib/daophotdef.h"
+
+define NSEC 4
+define IRMIN 4
+
+# DP_SMPSF -- Smooth the psf before grouping.
+
+procedure dp_smpsf (dao)
+
+pointer dao # pointer to the daophot strucuture
+
+int k, icenter, irmax, nexpand
+pointer psffit, sum, high, low, n
+real rmax
+
+begin
+ # Get some pointers.
+ psffit = DP_PSFFIT(dao)
+
+ # Get some constants.
+ icenter = (DP_PSFSIZE(psffit) + 1) / 2
+ rmax = .7071068 * real (DP_PSFSIZE(psffit) - 1)
+ irmax = int (rmax + 1.0e-5)
+ nexpand = DP_NVLTABLE(psffit) + DP_NFEXTABLE(psffit)
+
+ # Allocate working memory.
+ call malloc (sum, NSEC * irmax, TY_REAL)
+ call malloc (high, NSEC * irmax, TY_REAL)
+ call malloc (low, NSEC * irmax, TY_REAL)
+ call malloc (n, NSEC * irmax, TY_INT)
+
+ # Do the smoothing.
+ do k = 1, nexpand {
+
+ # Initialize.
+ call aclrr (Memr[sum], NSEC * irmax)
+ call amovkr (-MAX_REAL, Memr[high], NSEC * irmax)
+ call amovkr (MAX_REAL, Memr[low], NSEC * irmax)
+ call aclri (Memi[n], NSEC * irmax)
+
+ # Acumulate.
+ call dp_smaccum (Memr[DP_PSFLUT(psffit)], DP_PSFSIZE(psffit),
+ DP_PSFSIZE(psffit), Memr[sum], Memr[low], Memr[high], Memi[n],
+ NSEC, IRMIN, icenter, rmax, k)
+
+ # Normalize.
+ call dp_smnorm (Memr[sum], Memr[low], Memr[high], Memi[n], NSEC,
+ IRMIN, irmax)
+
+ # Smooth.
+ call dp_smo (Memr[DP_PSFLUT(psffit)], DP_PSFSIZE(psffit),
+ DP_PSFSIZE(psffit), Memr[sum], NSEC, IRMIN, icenter, rmax, k)
+ }
+
+ call mfree (sum, TY_REAL)
+ call mfree (low, TY_REAL)
+ call mfree (high, TY_REAL)
+ call mfree (n, TY_INT)
+end
+
+
+# DP_SMACCUM -- Accumulate the sums and limits
+
+procedure dp_smaccum (psflut, nxpsf, nypsf, sum, low, high, n, nsec, irmin,
+ icenter, rmax, k)
+
+real psflut[nxpsf,nypsf,ARB] # the psf lookup table
+int nxpsf, nypsf # size of the psf lookup table
+real sum[nsec,ARB] # array of sums
+real low[nsec,ARB] # array of low values
+real high[nsec,ARB] # array of high values
+int n[nsec,ARB] # array of number of points
+int nsec # dimension of sum arrays
+int irmin # number of sums
+int icenter # center of the array
+real rmax # max radius
+int k # third dimension array index
+
+int i, j, idx, idy, is, ir
+real dxsq, dysq, r
+int dp_isctr()
+
+begin
+ do j = 1, nypsf {
+ idy = j - icenter
+ dysq = idy ** 2
+ do i = 1, nxpsf {
+ idx = i - icenter
+ dxsq = idx ** 2
+ r = sqrt (dxsq + dysq)
+ if (r > rmax)
+ next
+ ir = int (r + 1.0e-5)
+ if (ir < irmin)
+ next
+ is = dp_isctr (idx, idy)
+ sum[is,ir] = sum[is,ir] + psflut[i,j,k]
+ if (psflut[i,j,k] > high[is,ir])
+ high[is,ir] = psflut[i,j,k]
+ if (psflut[i,j,k] < low[is,ir])
+ low[is,ir] = psflut[i,j,k]
+ n[is,ir] = n[is,ir] + 1
+ }
+ }
+end
+
+
+# DP_SMNORM -- Normalize the sum
+
+procedure dp_smnorm (sum, low, high, n, nsec, irmin, irmax)
+
+real sum[nsec,ARB] # array of sums
+real low[nsec,ARB] # array of low values
+real high[nsec,ARB] # array of high values
+int n[nsec,ARB] # array of counter
+int nsec # array dimension
+int irmin # radius index
+int irmax # maximum radius index
+
+int ir, is
+
+begin
+ do ir = irmin, irmax {
+ do is = 1, nsec {
+ if (n[is,ir] > 2)
+ sum[is,ir] = (sum[is,ir] - high[is,ir] - low[is,ir]) /
+ (n[is,ir] - 2)
+ }
+ }
+end
+
+
+# DP_SMO -- Do the actual smoothing.
+
+procedure dp_smo (psflut, nxpsf, nypsf, sum, nrec, irmin, icenter, rmax, k)
+
+real psflut[nxpsf,nypsf,ARB] # the lookup table
+int nxpsf, nypsf # size of the psf lookup table
+real sum[nrec,ARB] # array of sums
+int nrec # dimension of sum array
+int irmin # min radius index
+int icenter # index of center
+real rmax # maximum radius
+int k # index of third dimension
+
+int i, j, idx, idy, ir, is
+real dysq, r
+int dp_isctr()
+
+begin
+ do j = 1, nypsf {
+ idy = j - icenter
+ dysq = idy ** 2
+ do i = 1, nxpsf {
+ idx = i - icenter
+ r = sqrt (real (idx ** 2) + dysq)
+ if (r > rmax)
+ next
+ ir = int (r + 1.0e-5)
+ if (ir < irmin)
+ next
+ is = dp_isctr (idx, idy)
+ psflut[i,j,k] = sum[is,ir]
+ }
+ }
+end
+
+
+# DP_ISCTR -- Convert an index pair into a numbered sector from 1 to 4.
+
+int procedure dp_isctr (i, j)
+
+int i # first index
+int j # second index
+
+int isctr
+
+begin
+ if (i > 0) {
+ isctr = 1
+ } else if (i < 0) {
+ isctr = 3
+ } else {
+ if (j <= 0)
+ isctr = 1
+ else
+ isctr = 3
+ }
+
+ if (j > 0) {
+ isctr = isctr + 1
+ } else if (j == 0) {
+ if (i > 0)
+ isctr = 2
+ }
+
+ return (isctr)
+end
diff --git a/noao/digiphot/daophot/group/dpwrtgroup.x b/noao/digiphot/daophot/group/dpwrtgroup.x
new file mode 100644
index 00000000..97b9a714
--- /dev/null
+++ b/noao/digiphot/daophot/group/dpwrtgroup.x
@@ -0,0 +1,448 @@
+include <mach.h>
+include <time.h>
+include <tbset.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+
+define NCOLUMN 6
+
+# DP_TGNEWGRP -- Create a new GROUP output ST table.
+
+procedure dp_tgnewgrp (tp, colpoint)
+
+pointer tp # pointer to outpu ST table
+pointer colpoint[ARB] # array of pointers to columns
+
+pointer sp, colnames, colunits, colformat, col_dtype, col_len
+
+begin
+ # Allocate space for table definition.
+ call smark (sp)
+ call salloc (colnames, NCOLUMN * (SZ_COLNAME + 1), TY_CHAR)
+ call salloc (colunits, NCOLUMN * (SZ_COLUNITS + 1), TY_CHAR)
+ call salloc (colformat, NCOLUMN * (SZ_COLFMT + 1), TY_CHAR)
+ call salloc (col_dtype, NCOLUMN, TY_INT)
+ call salloc (col_len, NCOLUMN, TY_INT)
+
+ # Set up the column definitions.
+ call strcpy (GROUP, Memc[colnames], SZ_COLNAME)
+ call strcpy (ID, Memc[colnames+SZ_COLNAME+1], SZ_COLNAME)
+ call strcpy (XCENTER, Memc[colnames+2*SZ_COLNAME+2], SZ_COLNAME)
+ call strcpy (YCENTER, Memc[colnames+3*SZ_COLNAME+3], SZ_COLNAME)
+ call strcpy (MAG, Memc[colnames+4*SZ_COLNAME+4], SZ_COLNAME)
+ call strcpy (SKY, Memc[colnames+5*SZ_COLNAME+5], SZ_COLNAME)
+
+ # Set up the format definitions.
+ call strcpy ("%6d", Memc[colformat], SZ_COLFMT)
+ call strcpy ("%6d", Memc[colformat+SZ_COLFMT+1], SZ_COLFMT)
+ call strcpy ("%10.3f", Memc[colformat+2*SZ_COLFMT+2], SZ_COLFMT)
+ call strcpy ("%10.3f", Memc[colformat+3*SZ_COLFMT+3], SZ_COLFMT)
+ call strcpy ("%12.3f", Memc[colformat+4*SZ_COLFMT+4], SZ_COLFMT)
+ call strcpy ("%15.7g", Memc[colformat+5*SZ_COLFMT+5], SZ_COLFMT)
+
+ # Set up the unit definitions.
+ call strcpy ("##", Memc[colunits], SZ_COLUNITS)
+ call strcpy ("##", Memc[colunits+SZ_COLUNITS+1], SZ_COLUNITS)
+ call strcpy ("PIXELS", Memc[colunits+2*SZ_COLUNITS+2], SZ_COLUNITS)
+ call strcpy ("PIXELS", Memc[colunits+3*SZ_COLUNITS+3], SZ_COLUNITS)
+ call strcpy ("MAGNITUDES", Memc[colunits+4*SZ_COLUNITS+4], SZ_COLUNITS)
+ call strcpy ("ADC", Memc[colunits+5*SZ_COLUNITS+5], SZ_COLUNITS)
+
+ # Set up the data type definitions.
+ Memi[col_dtype] = TY_INT
+ Memi[col_dtype+1] = TY_INT
+ Memi[col_dtype+2] = TY_REAL
+ Memi[col_dtype+3] = TY_REAL
+ Memi[col_dtype+4] = TY_REAL
+ Memi[col_dtype+5] = TY_REAL
+
+ # Define the column lengths.
+ Memi[col_len] = 1
+ Memi[col_len+1] = 1
+ Memi[col_len+2] = 1
+ Memi[col_len+3] = 1
+ Memi[col_len+4] = 1
+ Memi[col_len+5] = 1
+
+ # Define and create the table.
+ call tbcdef (tp, colpoint, Memc[colnames], Memc[colunits],
+ Memc[colformat], Memi[col_dtype], Memi[col_len], NCOLUMN)
+ call tbtcre (tp)
+
+ call sfree (sp)
+end
+
+
+# DP_XGGRPPARS -- Write out the parameters to the header of the GROUP text
+# output file.
+
+procedure dp_xggrppars (dao, tp)
+
+pointer dao # pointer to the DAOPHOT structure
+int tp # the output file descriptor
+
+pointer sp, outstr, date, time, psffit
+int envfind()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+ call salloc (date, SZ_DATE, TY_CHAR)
+ call salloc (time, SZ_DATE, TY_CHAR)
+
+ psffit = DP_PSFFIT(dao)
+
+ # Write the id.
+ if (envfind ("version", Memc[outstr], SZ_LINE) <= 0)
+ call strcpy ("NOAO/IRAF", Memc[outstr], SZ_LINE)
+ call dp_rmwhite (Memc[outstr], Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "IRAF", Memc[outstr], "version", "")
+ if (envfind ("userid", Memc[outstr], SZ_LINE) > 0)
+ call dp_sparam (tp, "USER", Memc[outstr], "name", "")
+ call gethost (Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "HOST", Memc[outstr], "computer", "")
+ call dp_date (Memc[date], Memc[time], SZ_DATE)
+ call dp_sparam (tp, "DATE", Memc[date], "yyyy-mm-dd", "")
+ call dp_sparam (tp, "TIME", Memc[time], "hh:mm:ss", "")
+ call dp_sparam (tp, "PACKAGE", "daophot", "name", "")
+ call dp_sparam (tp, "TASK", "group", "name", "")
+
+ # Write the file name parameters.
+ call dp_imroot (DP_INIMAGE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "IMAGE", Memc[outstr], "imagename", "")
+ call dp_froot (DP_INPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "PHOTFILE", Memc[outstr], "filename", "")
+ call dp_imroot (DP_PSFIMAGE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "PSFIMAGE", Memc[outstr], "imagename", "")
+ call dp_froot (DP_OUTPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "GRPFILE", Memc[outstr], "filename", "")
+
+ # Write out relevant data parameters.
+ call dp_rparam (tp, "SCALE", DP_SCALE(dao), "units/pix", "")
+ call dp_rparam (tp, "DATAMIN", DP_MINGDATA(dao), "counts", "")
+ call dp_rparam (tp, "DATAMAX", DP_MAXGDATA(dao), "counts", "")
+ call dp_rparam (tp, "GAIN", DP_PHOTADU(dao), "number", "")
+ call dp_rparam (tp, "READNOISE", DP_READNOISE(dao), "electrons", "")
+
+ # Write out the observing parameters.
+ call dp_sparam (tp, "OTIME", DP_OTIME(dao), "timeunit", "")
+ call dp_rparam (tp, "XAIRMASS", DP_XAIRMASS(dao), "number", "")
+ call dp_sparam (tp, "IFILTER", DP_IFILTER(dao), "filter", "")
+
+ # Write out the daophot parameters.
+ call dp_rparam (tp, "PSFRAD", DP_SPSFRAD(dao), "scaleunit", "")
+ call dp_rparam (tp, "FITRAD", DP_SFITRAD(dao), "scaleunit", "")
+ call dp_rparam (tp, "PSFMAG", DP_PSFMAG(psffit), "magnitude", "")
+ call dp_rparam (tp, "CRITSNRATIO", DP_CRITSNRATIO(dao), "sigma", "")
+ call dp_iparam (tp, "MAXGROUP", DP_MAXGROUP(dao), "number", "")
+ #call dp_iparam (tp, "MAXNSTAR", DP_MAXNSTAR(dao), "number", "")
+
+ # Write out the group size parameters.
+ # call dp_iparam (tp, "MINSZGROUP", 1, "number", "")
+ # call dp_iparam (tp, "MAXSZGROUP", MAX_INT, "number", "")
+
+ call sfree(sp)
+end
+
+
+# DP_TGGRPPARS -- Write out the parameters to the header of the GROUP output
+# ST table file.
+
+procedure dp_tggrppars (dao, tp)
+
+pointer dao # pointer to the DAOPHOT structure
+pointer tp # pointer to the output table
+
+pointer sp, outstr, date, time, psffit
+int envfind()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+ call salloc (date, SZ_DATE, TY_CHAR)
+ call salloc (time, SZ_DATE, TY_CHAR)
+
+ psffit = DP_PSFFIT(dao)
+
+ # Write the id.
+ if (envfind ("version", Memc[outstr], SZ_LINE) <= 0)
+ call strcpy ("NOAO/IRAF", Memc[outstr], SZ_LINE)
+ call dp_rmwhite (Memc[outstr], Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "IRAF", Memc[outstr])
+ if (envfind ("userid", Memc[outstr], SZ_LINE) > 0)
+ call tbhadt (tp, "USER", Memc[outstr])
+ call gethost (Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "HOST", Memc[outstr])
+ call dp_date (Memc[date], Memc[time], SZ_DATE)
+ call tbhadt (tp, "DATE", Memc[date])
+ call tbhadt (tp, "TIME", Memc[time])
+ call tbhadt (tp, "PACKAGE", "daophot")
+ call tbhadt (tp, "TASK", "group")
+
+ # Write the file name parameters.
+ call dp_imroot (DP_INIMAGE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "IMAGE", Memc[outstr])
+ call dp_froot (DP_INPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "PHOTFILE", Memc[outstr])
+ call dp_imroot (DP_PSFIMAGE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "PSFIMAGE", Memc[outstr])
+ call dp_froot (DP_OUTPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "GRPFILE", Memc[outstr])
+
+ # Write out relevant data parameters.
+ call tbhadr (tp, "SCALE", DP_SCALE(dao))
+ call tbhadr (tp, "DATAMIN", DP_MINGDATA(dao))
+ call tbhadr (tp, "DATAMAX", DP_MAXGDATA(dao))
+ call tbhadr (tp, "GAIN", DP_PHOTADU(dao))
+ call tbhadr (tp, "READNOISE", DP_READNOISE(dao))
+
+ # Write out the observing parameters.
+ call tbhadt (tp, "OTIME", DP_OTIME(dao))
+ call tbhadr (tp, "XAIRMASS", DP_XAIRMASS(dao))
+ call tbhadt (tp, "IFILTER", DP_IFILTER(dao))
+
+ # Write out the daophot parameters.
+ call tbhadr (tp, "PSFRAD", DP_SPSFRAD(dao))
+ call tbhadr (tp, "FITRAD", DP_SFITRAD(dao))
+ call tbhadr (tp, "PSFMAG", DP_PSFMAG(psffit))
+ call tbhadr (tp, "CRITSNRATIO", DP_CRITSNRATIO(dao))
+ call tbhadi (tp, "MAXGROUP", DP_MAXGROUP(dao))
+ #call tbhadi (tp, "MAXNSTAR", DP_MAXNSTAR(dao))
+
+ # call tbhadi (tp, "MINSZGROUP", 1)
+ # call tbhadi (tp, "MAXSZGROUP", MAX_INT)
+
+ call sfree(sp)
+end
+
+
+# DP_WRTGROUP -- Write out each group into a text file or an ST table.
+
+procedure dp_wrtgroup (dao, im, grp, number, index, group_size, maxgroup)
+
+pointer dao # pointer to daophot structure
+pointer im # the input image descriptor
+int grp # the output file descriptor
+int number[ARB] # number in group of each size
+int index[ARB] # index to results
+int group_size[ARB] # size of groups
+int maxgroup # maximum group size
+
+begin
+ if (DP_TEXT(dao) == YES)
+ call dp_xwrtgroup (dao, im, grp, number, index, group_size,
+ maxgroup)
+ else
+ call dp_twrtgroup (dao, im, grp, number, index, group_size,
+ maxgroup)
+end
+
+
+define GR_NAMESTR "#N%4tGROUP%10tID%16tXCENTER%26tYCENTER%36tMAG%48tMSKY\
+%80t\\\n"
+define GR_UNITSTR "#U%4t##%10t##%16tpixels%26tpixels%36tmagnitudes%48tcounts\
+%80t\\\n"
+define GR_FORMATSTR "#F%4t%%-9d%10t%%-6d%16t%%-10.3f%26t%%-10.3f%36t%%-12.3f\
+%48t%%-15.7g%80t \n"
+define GR_DATASTR "%-9d%10t%-6d%16t%-10.3f%26t%-10.3f%36t%-12.3f%48t%-15.7g\
+%80t \n"
+
+
+# DP_XWRTGROUP -- Write each group into the GROUP output ST table.
+
+procedure dp_xwrtgroup (dao, im, grp, number, index, group_size, maxgroup)
+
+pointer dao # pointer to the daophot structure
+pointer im # the input image descriptor
+int grp # the output file descriptor
+int number[ARB] # number in group of each size
+int index[ARB] # index to results
+int group_size[ARB] # size of groups
+int maxgroup # maximum group size
+
+int i, j, k, id, ngroup, nstars, first_ingrp
+pointer apsel
+real x, y, mag, sky
+
+begin
+ # Get the daophot pointer.
+ apsel = DP_APSEL(dao)
+
+ # Print results to the standard output.
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (" Size of Number of\n")
+ call printf (" group groups\n\n")
+ do i = 1, maxgroup {
+ if (number[i] <= 0)
+ next
+ call printf ("%8d %9d\n")
+ call pargi (i)
+ call pargi (number[i])
+ }
+ }
+
+ # Add header parameters to the table.
+ call dp_xggrppars (dao, grp)
+
+ # Write out the banner.
+ call fprintf (grp, "#\n")
+ call fprintf (grp, GR_NAMESTR)
+ call fprintf (grp, GR_UNITSTR)
+ call fprintf (grp, GR_FORMATSTR)
+ call fprintf (grp, "#\n")
+
+ # Write out each group.
+ ngroup = 1
+ first_ingrp = 1
+ while (first_ingrp <= DP_APNUM(apsel)) {
+
+ do j = first_ingrp, first_ingrp + group_size[first_ingrp] - 1 {
+
+ # Test the center.
+ k = index[j]
+ x = Memr[DP_APXCEN(apsel)+k-1]
+ y = Memr[DP_APYCEN(apsel)+j-1]
+ if (IS_INDEFR(x) || IS_INDEFR(y))
+ break
+ call dp_wout (dao, im, x, y, x, y, 1)
+
+ # Get the rest of the numbers.
+ id = Memi[DP_APID(apsel)+k-1]
+ mag = Memr[DP_APMAG(apsel)+k-1]
+ sky = Memr[DP_APMSKY(apsel)+k-1]
+
+ # Write the results.
+ call fprintf (grp, GR_DATASTR)
+ call pargi (ngroup)
+ call pargi (id)
+ call pargr (x)
+ call pargr (y)
+ call pargr (mag)
+ call pargr (sky)
+ }
+
+ ngroup = ngroup + 1
+ first_ingrp = first_ingrp + group_size[first_ingrp]
+ }
+
+ # Compute the number of groups and the number of stars.
+ ngroup = 0
+ nstars = 0
+ do i = 1, maxgroup {
+ if (number[i] <= 0)
+ next
+ nstars = nstars + i * number[i]
+ ngroup = ngroup + number[i]
+ }
+
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("\nTotal of %d stars in %d groups\n")
+ call pargi (nstars)
+ call pargi (ngroup)
+ }
+end
+
+
+# DP_TWRTGROUP -- Write each group into the GROUP output text file.
+
+procedure dp_twrtgroup (dao, im, grp, number, index, group_size, maxgroup)
+
+pointer dao # pointer to the daophot structure
+pointer im # the input image descriptor
+pointer grp # pointer to group output file
+int number[ARB] # number in group of each size
+int index[ARB] # index to results
+int group_size[ARB] # size of groups
+int maxgroup # maximum group size
+
+int row, first_ingrp, ngroup, nstars, i, j, k, id
+pointer apsel, sp, colpoint
+real x, y, mag, sky
+
+begin
+ # Get the daophot pointer.
+ apsel = DP_APSEL(dao)
+
+ # Allocate space for the column pointers.
+ call smark( sp)
+ call salloc (colpoint, NCOLUMN, TY_INT)
+
+ # Get the necessary info to create the ST table.
+ call dp_tgnewgrp (grp, Memi[colpoint])
+
+ # Add header parameters to the ST table.
+ call dp_tggrppars (dao, grp)
+
+ # Optionally print results to the standard output.
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (" Size of Number of\n")
+ call printf (" group groups\n\n")
+ do i = 1, maxgroup {
+ if (number[i] <= 0)
+ next
+ call printf (" %d %d\n")
+ call pargi (i)
+ call pargi (number[i])
+ }
+ }
+
+ # Initialize for writing.
+ ngroup = 1
+ row = 0
+
+ # Initialize for reading.
+ first_ingrp = 1
+
+ # Write out the data for all the groups.
+ while (first_ingrp <= DP_APNUM(apsel)) {
+
+ do j = first_ingrp, first_ingrp + group_size[first_ingrp] - 1 {
+
+ # Test the center.
+ k = index[j]
+ x = Memr[DP_APXCEN(apsel)+k-1]
+ y = Memr[DP_APYCEN(apsel)+j-1]
+ if (IS_INDEFR(x) || IS_INDEFR(y))
+ break
+ call dp_wout (dao, im, x, y, x, y, 1)
+
+ # Get the rest of the values.
+ id = Memi[DP_APID(apsel)+k-1]
+ mag = Memr[DP_APMAG(apsel)+k-1]
+ sky = Memr[DP_APMSKY(apsel)+k-1]
+
+ # Copy the values to the correct table row.
+ row = row + 1
+ call tbrpti (grp, Memi[colpoint], ngroup, 1, row)
+ call tbrpti (grp, Memi[colpoint+1], id, 1, row)
+ call tbrptr (grp, Memi[colpoint+2], x, 1, row)
+ call tbrptr (grp, Memi[colpoint+3], y, 1, row)
+ call tbrptr (grp, Memi[colpoint+4], mag, 1, row)
+ call tbrptr (grp, Memi[colpoint+5], sky, 1, row)
+ }
+
+ ngroup = ngroup + 1
+ first_ingrp = first_ingrp + group_size[first_ingrp]
+ }
+
+ # Compute the number of groups and the number of stars.
+ ngroup = 0
+ nstars = 0
+ do i = 1, maxgroup {
+ if (number[i] <= 0)
+ next
+ nstars = nstars + i * number[i]
+ ngroup = ngroup + number[i]
+ }
+
+ # Optionally print out a summary of the results.
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("\nTotal of %d stars in %d groups\n")
+ call pargi (nstars)
+ call pargi (ngroup)
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/group/mkpkg b/noao/digiphot/daophot/group/mkpkg
new file mode 100644
index 00000000..35173772
--- /dev/null
+++ b/noao/digiphot/daophot/group/mkpkg
@@ -0,0 +1,18 @@
+# GROUP task
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ dpmkgroup.x <mach.h> ../lib/apseldef.h \
+ ../lib/daophotdef.h
+ dpsmpsf.x <mach.h> ../lib/daophotdef.h
+ dpgconfirm.x
+ dpwrtgroup.x <mach.h> <time.h> \
+ <tbset.h> ../lib/daophotdef.h \
+ ../lib/apseldef.h
+ t_group.x <fset.h> <imhdr.h> \
+ ../lib/daophotdef.h
+ ;
diff --git a/noao/digiphot/daophot/group/t_group.x b/noao/digiphot/daophot/group/t_group.x
new file mode 100644
index 00000000..5596c0b3
--- /dev/null
+++ b/noao/digiphot/daophot/group/t_group.x
@@ -0,0 +1,246 @@
+include <fset.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+
+# T_GROUP -- Procedure to divide the stars in a photometry table into
+# natural groups based on the magnitude level at which they overlap.
+
+procedure t_group ()
+
+pointer image # name of the image
+pointer apfile # aperture photometry file
+pointer psfimage # name of the output PSF
+pointer groupfile # output group table
+
+pointer sp, im, dao, outfname, str
+int apd, root, cache, verbose, verify, update, grp, tp, wcs
+int imlist, limlist, alist, lalist, pimlist, lpimlist, olist, lolist
+int req_size, old_size, buf_size, memstat
+bool ap_text
+
+pointer immap(), tbtopn()
+int access(), fnldir(), strlen(), strncmp(), fstati(), btoi()
+int imtopen(), imtlen(), imtgetim(), fntopnb(), fntlenb(), fntgfnb()
+int open(), clgwrd(), sizeof(), dp_memstat()
+bool clgetb(), itob()
+
+begin
+ # Set the standard output to flush on newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get some memory.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (apfile, SZ_FNAME, TY_CHAR)
+ call salloc (psfimage, SZ_FNAME, TY_CHAR)
+ call salloc (groupfile, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Get the various task parameters.
+ call clgstr ("image", Memc[image], SZ_FNAME)
+ call clgstr ("photfile", Memc[apfile], SZ_FNAME)
+ call clgstr ("psfimage", Memc[psfimage], SZ_FNAME)
+ call clgstr ("groupfile", Memc[groupfile], SZ_FNAME)
+ verbose = btoi (clgetb ("verbose"))
+ verify = btoi (clgetb ("verify"))
+ update = btoi (clgetb ("update"))
+ cache = btoi (clgetb ("cache"))
+
+ # Get the lists.
+ imlist = imtopen (Memc[image])
+ limlist = imtlen (imlist)
+ alist = fntopnb (Memc[apfile], NO)
+ lalist = fntlenb (alist)
+ pimlist = imtopen (Memc[psfimage])
+ lpimlist = imtlen (pimlist)
+ olist = fntopnb (Memc[groupfile], NO)
+ lolist = fntlenb (olist)
+
+ # Test that the lengths of the photometry file, psf image, and output
+ # file lists are the same as the length of the input image list.
+
+ if ((limlist != lalist) && (strncmp (Memc[apfile], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call sfree (sp)
+ call error (0,
+ "Incompatible image and photometry file list lengths")
+ }
+
+ if ((limlist != lpimlist) && (strncmp (Memc[psfimage], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call sfree (sp)
+ call error (0,
+ "Incompatible image and psf file list lengths")
+ }
+
+ if ((limlist != lolist) && (strncmp (Memc[groupfile], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call sfree (sp)
+ call error (0,
+ "Incompatible image and group file list lengths")
+ }
+
+ # Initialize the daophot structure and get the pset parameters.
+ call dp_gppars (dao)
+ call dp_seti (dao, VERBOSE, verbose)
+
+ # Optionally verify and update the parameters.
+ if (verify == YES) {
+ call dp_gconfirm (dao)
+ if (update == YES)
+ call dp_pppars (dao)
+ }
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_FNAME, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_FNAME, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSOUT, wcs)
+ wcs = clgwrd ("wcspsf", Memc[str], SZ_FNAME, WCSPSFSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the psf coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSPSF, wcs)
+
+ # Open the PSF structure.
+ call dp_fitsetup (dao)
+
+ # Open the photometry list structure.
+ call dp_apselsetup (dao)
+
+ # Loop over the image list.
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open input image and grab some header parameters.
+ im = immap (Memc[image], READ_ONLY, 0)
+ call dp_imkeys (dao, im)
+ call dp_sets (dao, INIMAGE, Memc[image])
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = dp_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call dp_pcache (im, INDEFI, buf_size)
+
+ # Open input photometry list and read in the photometry.
+ if (fntgfnb (alist, Memc[apfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[apfile], SZ_FNAME)
+ root = fnldir (Memc[apfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[apfile+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[apfile]))
+ call dp_inname (Memc[image], Memc[outfname], "mag",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[apfile], Memc[outfname], SZ_FNAME)
+ ap_text = itob (access (Memc[outfname], 0, TEXT_FILE))
+ if (ap_text)
+ apd = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ else
+ apd = tbtopn (Memc[outfname], READ_ONLY, 0)
+ call dp_wgetapert (dao, im, apd, DP_MAXNSTAR(dao), ap_text)
+ call dp_sets (dao, INPHOTFILE, Memc[outfname])
+
+ # Read the PSF.
+ if (imtgetim (pimlist, Memc[psfimage], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[psfimage], SZ_FNAME)
+ root = fnldir (Memc[psfimage], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[psfimage+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[psfimage]))
+ call dp_iimname (Memc[image], Memc[outfname], "psf",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[psfimage], Memc[outfname], SZ_FNAME)
+ tp = immap (Memc[outfname], READ_ONLY, 0)
+ call dp_readpsf (dao, tp)
+ call dp_sets (dao, PSFIMAGE, Memc[outfname])
+
+ # Open output GROUP file. If the output is "default", dir$default
+ # or a directory specification then the extension "grp" is added to
+ # the image name and a suitable version number is appended to the
+ # output name.
+
+ if (fntgfnb (olist, Memc[groupfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[groupfile], SZ_FNAME)
+ root = fnldir (Memc[groupfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[groupfile + root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[groupfile]))
+ call dp_outname (Memc[image], Memc[outfname], "grp",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[groupfile], Memc[outfname], SZ_FNAME)
+ if (DP_TEXT(dao) == YES)
+ grp = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ else
+ grp = tbtopn (Memc[outfname], NEW_FILE, 0)
+ call dp_sets (dao, OUTPHOTFILE, Memc[outfname])
+
+ # Now go and group the stars.
+ call dp_mkgroup (dao, im, grp)
+
+ # Close up the input image.
+ call imunmap (im)
+
+ # Close up the photometry file.
+ if (ap_text)
+ call close (apd)
+ else
+ call tbtclo (apd)
+
+ # Close up the PSF image.
+ call imunmap (tp)
+
+ # Close up the group table.
+ if (DP_TEXT(dao) == YES)
+ call close (grp)
+ else
+ call tbtclo (grp)
+
+ # Uncache memory.
+ call fixmem (old_size)
+
+ }
+
+ # Close the image/file lists.
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+
+ # Free the photometry structure
+ call dp_apclose (dao)
+
+ # Free the PSF structure.
+ call dp_fitclose (dao)
+
+ # Free the daophot structure.
+ call dp_free (dao)
+
+ call sfree(sp)
+end
diff --git a/noao/digiphot/daophot/grpselect.par b/noao/digiphot/daophot/grpselect.par
new file mode 100644
index 00000000..4129ef54
--- /dev/null
+++ b/noao/digiphot/daophot/grpselect.par
@@ -0,0 +1,8 @@
+# GRPSELECT Parameters
+
+ingroupfile,s,a,,,,Input group file
+outgroupfile,s,a,,,,Output group file
+min_group,i,a,,,,Minimum group size to select
+max_group,i,a,,,,Maximum group size to select
+verbose,b,h,)_.verbose,,,Print grpselect messages?
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/lib/allstardef.h b/noao/digiphot/daophot/lib/allstardef.h
new file mode 100644
index 00000000..3f71aa28
--- /dev/null
+++ b/noao/digiphot/daophot/lib/allstardef.h
@@ -0,0 +1,116 @@
+# ALLSTAR Structure
+
+define LEN_ALLSTARSTRUCT (80)
+
+define DP_ISCACHE Memi[$1] # is data cached (default no)
+define DP_ALLCACHE Memi[$1+2] # is all the data cached ? (yes)
+define DP_CACHE Memi[$1+3+$2-1] # which data is cached ?
+define DP_SZCACHE Memi[$1+6] # current working set size
+define DP_SZOLDCACHE Memi[$1+7] # old working set size
+define DP_DATA Memi[$1+8] # pointer to data
+define DP_SUBT Memi[$1+9] # pointer to subt
+define DP_WEIGHTS Memi[$1+10] # pointer to weights
+
+define DP_SBUF Memi[$1+13] # local subt buffer
+define DP_SNX Memi[$1+14] # subt x dimension
+define DP_SNY Memi[$1+15] # subt y dimension
+define DP_SLX Memi[$1+16] # subt lower left x coord
+define DP_SMX Memi[$1+17] # subt lower right x coord
+define DP_SLY Memi[$1+18] # subt lower left y coord
+define DP_SMY Memi[$1+19] # subt lower right y coord
+define DP_SXOFF Memi[$1+20] # subt lower left x offset
+define DP_SYOFF Memi[$1+21] # subt lower left y offset
+
+define DP_WBUF Memi[$1+23] # local weight buffer
+define DP_WNX Memi[$1+24] # weight x dimension
+define DP_WNY Memi[$1+25] # weight y dimension
+define DP_WLX Memi[$1+26] # weight lower left x coord
+define DP_WMX Memi[$1+27] # weight lower right x coord
+define DP_WLY Memi[$1+28] # weight lower left y coord
+define DP_WMY Memi[$1+29] # weight lower right y coord
+define DP_WXOFF Memi[$1+30] # weight lower left x offset
+define DP_WYOFF Memi[$1+31] # weight lower left y offset
+
+define DP_DBUF Memi[$1+33] # local weight buffer
+define DP_DNX Memi[$1+34] # weight x dimension
+define DP_DNY Memi[$1+35] # weight y dimension
+define DP_DLX Memi[$1+36] # weight lower left x coord
+define DP_DMX Memi[$1+37] # weight lower right x coord
+define DP_DLY Memi[$1+38] # weight lower left y coord
+define DP_DMY Memi[$1+39] # weight lower right y coord
+define DP_DXOFF Memi[$1+40] # weight lower left x offset
+define DP_DYOFF Memi[$1+41] # weight lower left y offset
+
+define DP_ANUMER Memi[$1+55] # pointer to the anumer1 directory
+define DP_ADENOM Memi[$1+57] # pointer to the adenom1 directory
+define DP_ARPIXSQ Memi[$1+59] # pointer to the rpixsq directory
+define DP_ASUMWT Memi[$1+60] # pointer to the sumwt directory
+define DP_ASKIP Memi[$1+61] # pointer to the skip directory
+define DP_ALAST Memi[$1+62] # pointer to the last directory
+define DP_AXOLD Memi[$1+63] # pointer to the xold array
+define DP_AYOLD Memi[$1+64] # pointer to the yold array
+define DP_AXCLAMP Memi[$1+65] # pointer to the xclamp array
+define DP_AYCLAMP Memi[$1+66] # pointer to the yclamp array
+define DP_AX Memi[$1+67] # pointer to the x array
+define DP_AV Memi[$1+68] # pointer to the v array
+define DP_AC Memi[$1+69] # pointer to the c array
+define DP_ANPIX Memi[$1+70] # pointer to the npix array
+define DP_AIER Memi[$1+71] # pointer to the error array
+
+define A_SUBT 1
+define A_WEIGHT 2
+define A_DCOPY 3
+
+# Separation criterion
+
+define FRACTION_MINSEP 0.14
+define CLAMP_FRACTION 0.25
+
+# Limit on N/S ** 2 for two stars to merge.
+
+define WCRIT0 0.0
+define WCRIT5 1.0
+define WCRIT10 1.5
+define WCRIT15 2.0
+
+# Minimum and maximum sharpness limits.
+
+define MIN_SHARP -99.99
+define MAX_SHARP 99.99
+
+# Number of output files columns
+
+define ALL_NOUTCOLUMN 11
+
+# Define the fitting contstants and constraints
+
+define RADIUS_FRACTION 0.95 # % decrease in radius for regrouping
+define DENSE_RADIUS1 1.2 # 1st limiting radius for regrouping
+define DENSE_RADIUS2 0.8 # 2nd limiting radius for regrouping
+define MIN_ITER 4 # minimum number of iterations
+define MAX_RELERR 100.0 # maximum relative error
+define MAX_RSQ 0.999999 # maximum values of ratio of radii ** 2
+define MAX_RHOSQ 36.0 # limit on core radius ** 2 for sharp
+define CHI_NORM 1.2533141 # sqrt (PI / 2.0)
+define MIN_SUMWT 3.0 # min value for radial weight sum
+define MIN_NPIX 4 # min pixels per star for a fit
+define MIN_XYCLAMP 0.001 # min value of x-y clamp
+define MIN_XYCLAMP_FRACTION 0.5 # min change in value of x-y clamp
+define MAX_XYCLAMP_FRACTION 1.2 # max change in value of x-y clamp
+define MAX_DELTA_FAINTER 0.84 # max permitted brightness decrease
+define MAX_DELTA_BRIGHTER 5.25 # max permitted brightness increase
+define MAX_NEW_ERRMAG 0.10 # 1st convergence check on mag error
+define MAX_NEW_RELBRIGHT2 0.0005 # 2nd convergenge check on mag
+define MAX_PIXERR2 4.0e-6 # 2nd convergence check on x/y
+define MIN_REL_BRIGHT 1.0e-5 # min relative brightness
+
+# List of ALLSTAR error codes
+
+define ALLERR_OK 0
+define ALLERR_BIGGROUP 1
+define ALLERR_INDEFSKY 2
+define ALLERR_NOPIX 3
+define ALLERR_SINGULAR 4
+define ALLERR_FAINT 5
+define ALLERR_MERGE 6
+define ALLERR_OFFIMAGE 7
diff --git a/noao/digiphot/daophot/lib/apseldef.h b/noao/digiphot/daophot/lib/apseldef.h
new file mode 100644
index 00000000..ddf3c7d2
--- /dev/null
+++ b/noao/digiphot/daophot/lib/apseldef.h
@@ -0,0 +1,57 @@
+# the photometry structure definition
+
+
+# input photometry list parameters (# 101 - 200)
+
+define APNUM 101
+
+# parameters for reading photometry results
+
+define DP_PAPID 1 # star id number
+define DP_PAPXCEN 2 # x center
+define DP_PAPYCEN 3 # y center
+define DP_PAPSKY 4 # sky value
+define DP_PAPMAG1 5 # aperture 1 magnitude
+define DP_PAPMERR1 6 # aperture 1 magnitude error
+define DP_PAPGROUP 7 # group number
+define DP_PAPNITER 8 # number of iterations
+define DP_PAPCHI 9 # chi squared of fit
+define DP_PAPSHARP 10 # sharpness characteristic
+
+# some useful definitions
+
+define NAPRESULT 5
+define NAPGROUP 6
+define NAPPAR 10
+
+# define the column names for reading and writing photometry files
+
+define ID "ID"
+define GROUP "GROUP"
+define XCENTER "XCENTER"
+define YCENTER "YCENTER"
+define APMAG "MAG[1]"
+define MAG "MAG"
+define APMAGERR "MERR[1]"
+define MAGERR "MERR"
+define SKY "MSKY"
+define NITER "NITER"
+define CHI "CHI"
+define SHARP "SHARPNESS"
+define PIER "PIER"
+define PERROR "PERROR"
+
+define LEN_DPAPSTRUCT (15)
+
+define DP_APNUM Memi[$1] # number of stars in list
+define DP_APRESULT Memi[$1+1] # pointer to fields needed
+define DP_APID Memi[$1+2] # pointer to star ids
+define DP_APXCEN Memi[$1+3] # pointer to stellar x centers
+define DP_APYCEN Memi[$1+4] # pointer to stellar y centers
+define DP_APMAG Memi[$1+5] # pointer to magnitudes
+define DP_APERR Memi[$1+6] # pointer to magnitude errors
+define DP_APMSKY Memi[$1+7] # pointer to sky values
+define DP_APGROUP Memi[$1+8] # pointer to group numbers
+define DP_APNITER Memi[$1+9] # pointer to number of iterations
+define DP_APCHI Memi[$1+10] # pointer to output chi values
+define DP_APSHARP Memi[$1+11] # pointer to output sharp values
diff --git a/noao/digiphot/daophot/lib/daophotdef.h b/noao/digiphot/daophot/lib/daophotdef.h
new file mode 100644
index 00000000..043e7f1b
--- /dev/null
+++ b/noao/digiphot/daophot/lib/daophotdef.h
@@ -0,0 +1,257 @@
+# DAOPHOT header file
+
+# DAOPHOT PSF function types
+
+define FCTN_FTYPES "|gauss|lorentz|moffat15|moffat25|penny1|penny2|auto|"
+define FCTN_GAUSS 1
+define FCTN_LORENTZ 2
+define FCTN_MOFFAT15 3
+define FCTN_MOFFAT25 4
+define FCTN_PENNY1 5
+define FCTN_PENNY2 6
+define FCTN_AUTO 7
+
+define FCTN_NFTYPES 6
+
+# WCS types
+
+define WCS_LOGICAL 1
+define WCS_TV 2
+define WCS_PHYSICAL 3
+define WCS_WORLD 4
+
+define WCSINSTR "|logical|tv|physical|world|"
+define WCSOUTSTR "|logical|tv|physical|"
+define WCSPSFSTR "|logical|tv|physical|"
+
+# DAOPHOT parameters (# 1 - 100)
+
+# wcs parameters
+
+define MW 1 # mwcs pointer
+define WCSIN 2 # input wcs type
+define WCSOUT 3 # output wcs type
+define WCSPSF 4 # psf wcs type
+define CTIN 5 # input transform
+define CTOUT 6 # output transform
+define CTPSF 7 # psf transform
+
+# data dependent parameters
+
+define SFWHMPSF 8 # full-width at half-max of the psf (scale)
+define FWHMPSF 9 # full-width at half-max of the psf (pixels)
+define MAXGDATA 10 # maximum good data value (ADU)
+define MINGDATA 11 # minimum good data value (ADU)
+define PHOTADU 12 # gain (e- / ADU)
+define READNOISE 13 # readout noise (e-)
+define SCALE 14 # scale of the imge
+
+# keyword parameters
+
+define CCDGAIN 15 # gain image header keyword
+define CCDREAD 16 # readnoise image header keyword
+define EXPTIME 17 # exposure time image header keyword
+define FILTER 18 # filter image header keyword
+define OBSTIME 19 # observing time image header keyword
+define AIRMASS 20 # airmass image header keyword
+
+# observing parameters
+
+define XAIRMASS 21 # value of the airmass
+define IFILTER 22 # filter id
+define ITIME 23 # integration time
+define OTIME 24 # time of observation
+
+# psf fitting parameters
+
+define FUNCTION 25 # psf function analytic function
+define VARORDER 26 # order of psf variability (0, 1, or 2)
+define FEXPAND 27 # fraction pixel interpolation (yes or no)
+define SATURATED 28 # use saturated psf stars ?
+define NCLEAN 29 # the number of psf clean passes
+define FUNCLIST 30 # user function list
+define RPSFRAD 31 # requested psf radius (scale)
+define SPSFRAD 32 # psf radius (scale)
+define PSFRAD 33 # psf radius (pixels)
+define SMATCHRAD 34 # matching radius (scale)
+define MATCHRAD 35 # matching radius (pixels)
+
+# star fitting parameters
+
+define SFITRAD 36 # fitting radius (scale)
+define FITRAD 37 # fitting radius (pixels)
+define SANNULUS 38 # inner sky radius (scale)
+define ANNULUS 39 # inner sky radius (pixels)
+define SDANNULUS 40 # width of sky annulus (scale)
+define DANNULUS 41 # width of sky annulus (pixels)
+define SMERGERAD 42 # merging radius (scale)
+define MERGERAD 43 # merging radius (pixels)
+
+define CRITSNRATIO 44 # critical S/N overlap
+define MAXNSTAR 45 # maximum number of stars to fit
+define MAXGROUP 46 # maximum number of stars in group
+define MAXITER 47 # maximum number of iterations
+define RECENTER 48 # recenter ?
+define FITSKY 49 # refit the group sky ?
+define GROUPSKY 50 # use group or individual sky values
+define FLATERR 51 # the flat field error
+define PROFERR 52 # the profile or interpolation error
+define CLIPRANGE 53 # clipping range
+define CLIPEXP 54 # clipping exponent
+
+
+# file/image name and input/output parameters
+
+define TEXT 55 # text file
+define VERBOSE 56 # verbose mode
+define INIMAGE 57 # input image name
+define INPHOTFILE 58 # input photometry file
+define PSFIMAGE 59 # psf image name
+define COORDS 60 # input coordinate file
+define OUTPHOTFILE 61 # output photometry file
+define OUTIMAGE 62 # output image name
+define OUTREJFILE 63 # output rejected photometry file
+
+define MEMFUDGE 1.05
+
+# DAOPHOT structure definitions
+
+define LEN_DPSTRUCT (70 + 17 * SZ_FNAME + 17)
+
+# sub-structure pointers
+
+define DP_VERSION Memi[$1] # package version number
+define DP_ADDSTAR Memi[$1+1] # pointer to addstar structure
+define DP_ALLSTAR Memi[$1+2] # pointer to allstar structure (used)
+define DP_APSEL Memi[$1+3] # pointer to phot structure (used)
+define DP_GROUP Memi[$1+4] # pointer to group structure
+define DP_NSTAR Memi[$1+5] # pointer to nstar structure (used)
+define DP_PEAK Memi[$1+6] # pointer to the peak structure
+define DP_PSF Memi[$1+7] # pointer to psf structure (used)
+define DP_PSFFIT Memi[$1+8] # pointer to psffit structure (used)
+define DP_SUBSTAR Memi[$1+9] # pointer to substar structure
+
+# the wcs parameters
+
+define DP_WCSIN Memi[$1+10] # the input wcs
+define DP_WCSOUT Memi[$1+11] # the output wcs
+define DP_WCSPSF Memi[$1+12] # the psf wcs
+define DP_MW Memi[$1+13] # pointer to mwcs structure
+define DP_CTIN Memi[$1+14] # the input transformation pointer
+define DP_CTOUT Memi[$1+15] # the output transformation pointer
+define DP_CTPSF Memi[$1+16] # the psf transformation pointer
+
+# parameters
+
+define DP_VARORDER Memi[$1+17] # order of psf variability
+define DP_FEXPAND Memi[$1+18] # expand the analytic function ?
+define DP_SATURATED Memi[$1+19] # use saturated psf stars ?
+define DP_NCLEAN Memi[$1+20] # number of psf cleaning passes
+define DP_MAXNSTAR Memi[$1+21] # maximum number of stars
+define DP_MAXGROUP Memi[$1+22] # maximum group size
+define DP_MAXITER Memi[$1+23] # maximum number of iterations
+define DP_RECENTER Memi[$1+24] # recenter ?
+define DP_FITSKY Memi[$1+25] # fit the sky ?
+define DP_GROUPSKY Memi[$1+26] # use the group sky value ?
+define DP_CLIPEXP Memi[$1+27] # clip exponent
+define DP_TEXT Memi[$1+28] # text file or table input/output ?
+define DP_VERBOSE Memi[$1+29] # verbose mode ?
+
+define DP_SCALE Memr[P2R($1+30)] # image scale in units/pixel
+define DP_SFWHMPSF Memr[P2R($1+31)] # fwhm of the psf (scale)
+define DP_FWHMPSF Memr[P2R($1+32)] # fwhm of the psf (pixels)
+define DP_MAXGDATA Memr[P2R($1+33)] # maximum good data value (ADU)
+define DP_MINGDATA Memr[P2R($1+34)] # minimum good data value (ADU)
+define DP_PHOTADU Memr[P2R($1+35)] # gain in electrons/ADU
+define DP_READNOISE Memr[P2R($1+36)] # readout noise (electrons)
+define DP_XAIRMASS Memr[P2R($1+37)] # value of the airmass
+define DP_ITIME Memr[P2R($1+38)] # value of the exposure time
+define DP_SMATCHRAD Memr[P2R($1+39)] # matching radius (scale)
+define DP_MATCHRAD Memr[P2R($1+40)] # matching radius (pixels)
+define DP_RPSFRAD Memr[P2R($1+41)] # requested psf radius (scale)
+define DP_SPSFRAD Memr[P2R($1+42)] # actual psf radius (scale)
+define DP_PSFRAD Memr[P2R($1+43)] # actual psf radius (pixels)
+define DP_SFITRAD Memr[P2R($1+44)] # fitting radius (scale)
+define DP_FITRAD Memr[P2R($1+45)] # fitting radius (pixels)
+define DP_SANNULUS Memr[P2R($1+46)] # inner sky radius (scale)
+define DP_ANNULUS Memr[P2R($1+47)] # inner sky radius (pixels)
+define DP_SDANNULUS Memr[P2R($1+48)] # width of sky annulus (scale)
+define DP_DANNULUS Memr[P2R($1+49)] # width of sky annulus (pixels)
+define DP_CRITSNRATIO Memr[P2R($1+50)] # critical S/N overlap
+define DP_FLATERR Memr[P2R($1+51)] # percent flat field error
+define DP_PROFERR Memr[P2R($1+52)] # percent profile error
+define DP_CLIPRANGE Memr[P2R($1+53)] # clipping range
+define DP_SMERGERAD Memr[P2R($1+54)] # merging radius (scale)
+define DP_MERGERAD Memr[P2R($1+55)] # merging radius (pixels)
+
+# temporary variables, not yet used
+
+#define DP_FITRADSQ Memr[P2R($1+56)] # fit radius squared (pixels)
+#define DP_PSFRADSQ Memr[P2R($1+57)] # psf radius squared (pixels)
+#define DP_RNOISESQ Memr[P2R($1+58)] # read noise squared (ADU)
+#define DP_PERR Memr[P2R($1+59)] # percentage error
+#define DP_PKERR Memr[P2R($1+60)] # peak error
+#define DP_TMAXGDATA Memr[P2R($1+61)] # true data max
+#define DP_TMINGDATA Memr[P2R($1+62)] # true data min
+
+# file / image names
+
+define DP_INIMAGE Memc[P2C($1+64)] # input image name
+define DP_PSFIMAGE Memc[P2C($1+64+SZ_FNAME+1)] # psf image name
+define DP_INPHOTFILE Memc[P2C($1+64+2*SZ_FNAME+2)] # input photometry file
+define DP_COORDS Memc[P2C($1+64+3*SZ_FNAME+3)] # input coordinate file
+define DP_OUTIMAGE Memc[P2C($1+64+4*SZ_FNAME+4)] # output image name
+define DP_OUTPHOTFILE Memc[P2C($1+64+5*SZ_FNAME+5)] # output photometry file
+define DP_OUTREJFILE Memc[P2C($1+64+6*SZ_FNAME+6)] # output photometry file
+
+# keyword / parameter names
+
+define DP_IFILTER Memc[P2C($1+64+7*SZ_FNAME+7)] # filter id
+define DP_OTIME Memc[P2C($1+64+8*SZ_FNAME+8)] # time of observation
+define DP_CCDGAIN Memc[P2C($1+64+9*SZ_FNAME+9)] # gain keyword
+define DP_CCDREAD Memc[P2C($1+64+10*SZ_FNAME+10)] # readnoise keyword
+define DP_EXPTIME Memc[P2C($1+64+11*SZ_FNAME+11)] # exposure keyword
+define DP_FILTER Memc[P2C($1+64+12*SZ_FNAME+12)] # filter keyword
+define DP_OBSTIME Memc[P2C($1+64+13*SZ_FNAME+13)] # obstime keyword
+define DP_AIRMASS Memc[P2C($1+64+14*SZ_FNAME+14)] # airmass keyword
+define DP_FUNCTION Memc[P2C($1+64+15*SZ_FNAME+15)] # analytic psf function
+define DP_FUNCLIST Memc[P2C($1+64+16*SZ_FNAME+16)] # psf function list
+
+# PSF Fit Parameters
+
+define LEN_PSFFIT (20)
+
+define DP_PSFUNCTION Memi[$1] # PSF type
+define DP_PSFNPARS Memi[$1+1] # number of psf parameters
+define DP_PSFSIZE Memi[$1+2] # size of PSF lut
+define DP_PSFPARS Memi[$1+3] # pointer to the PSF parameters
+define DP_PSFLUT Memi[$1+4] # pointer to the PSF lookup table
+define DP_NVLTABLE Memi[$1+5] # number of variability luts
+define DP_NFEXTABLE Memi[$1+6] # number of PSF expansion luts
+define DP_PSFHEIGHT Memr[P2R($1+7)] # brightness of psf
+define DP_PSFMAG Memr[P2R($1+8)] # magnitude of the PSF
+define DP_PSFX Memr[P2R($1+9)] # x position of the PSF
+define DP_PSFY Memr[P2R($1+10)]# y position of the PSF
+
+define MAX_NFCTNPARS (6) # max number of pars in psf function
+define MAX_NEXPTERMS (11) # max number of expansion terms
+
+# default daophot parameter values
+
+define DEF_SCALE 1.0
+define DEF_FWHMPSF 2.5
+define DEF_PSFRAD 11.0
+define DEF_FITRAD 2.5
+define DEF_ANNULUS 10.0
+define DEF_DANNULUS 10.0
+define DEF_MAXNSTAR 5000
+define DEF_MAXGROUP 60
+define DEF_MAXITER 50
+define DEF_DEFNAME "default"
+define DEF_LENDEFNAME 7
+
+# some useful macros
+
+define DAO_GOODDATA ($2>DP_MINGDATA($1)&&$2<DP_MAXGDATA($1))
+define DAO_RELBRIGHT (10.0**(0.4*(DP_PSFMAG($1) - $2)))
+define DAO_MAGCHECK (0.4*(DP_PSFMAG($1) - $2))
diff --git a/noao/digiphot/daophot/lib/nstardef.h b/noao/digiphot/daophot/lib/nstardef.h
new file mode 100644
index 00000000..460f8031
--- /dev/null
+++ b/noao/digiphot/daophot/lib/nstardef.h
@@ -0,0 +1,63 @@
+# NSTAR Structure
+
+define LEN_NSTARSTRUCT (20)
+
+define DP_NGNUM Memi[$1] # current group number
+define DP_NNUM Memi[$1+1] # number of stars in current group
+define DP_NSTARCOLS Memi[$1+2] # pointer to NSTAR table columns
+define DP_NNPIX Memi[$1+3] # pointer to number of pixels
+define DP_NNUMER Memi[$1+4] # pointer to NUMER in curr group
+define DP_NDENOM Memi[$1+5] # pointer to DENOM stat in curr group
+define DP_NSKIP Memi[$1+6] # pointer to SKIP in curr group
+define DP_NXCLAMP Memi[$1+7] # pointer to CLAMP stat in curr group
+define DP_NXOLD Memi[$1+8] # pointer to XOLD stat in curr group
+define DP_NX Memi[$1+9] # pointer to X array in curr group
+define DP_NV Memi[$1+10] # pointer to V array in curr group
+define DP_NSUMWT Memi[$1+11] # pointer to SUMWT array in curr group
+define DP_NC Memi[$1+12] # pointer to C array in curr group
+define DP_NRPIXSQ Memi[$1+13] # pointer to RPIXSQ array in curr group
+define DP_NIER Memi[$1+14] # pointer to NSTAR error codes
+
+# Definitions controlling the input / output format
+
+define NST_NOUTCOL 12
+
+# NSTAR fitting constants
+
+define CUT_FACTOR 0.999998 # the pixel cutoff radius in fitrad ** 2
+define FRACTION_MINSEP 0.14 # min sep in fwhmpsf for merging
+define NITER_MAX 15 # iteration limit for difficult stars
+define NITER_MED 10 # iteration limit for moderate stars
+define NITER_MIN 5 # iteration limit for easy stars
+define WCRIT_MAX 0.5 # max N/S for difficult stars
+define WCRIT_MED 0.66667 # max N/S for moderate stars
+define WCRIT_MIN 1.0 # max N/S for easy stars
+define NCORE_SIGMASQ 36.0 # max number of hwidths for sharpness
+define MIN_NPIX 4 # min pixels per star for fit
+define CHI_NORM 1.2533141 # sqrt (PI / 2.0)
+define MIN_SUMWT 3.0 # min value for radial weight sum
+define MAX_DELTA_FAINTER 0.84 # max permitted brightness decrease
+define MAX_DELTA_BRIGHTER 5.25 # max permitted brightness increase
+define MAX_NEW_ERRMAG 0.1 # 1st convergence check on mag error
+define MAX_NEW_RELBRIGHT1 0.005 # 1st convergence check on magnitude
+define MAX_NEW_RELBRIGHT2 0.0005 # 2nd convergence check on magnitude
+define MAX_PIXERR1 4.0e-4 # 1st convergence check on x/y positions
+define MAX_PIXERR2 4.0e-6 # 2nd convergence check on x/y positions
+define MAX_DELTA_PIX 0.4 # max +/- change in x/y positions
+define MAX_PIX_INCREMENT 0.001 # test for nearness to edge of image
+define MIN_REL_BRIGHT 1.0e-5 # minimum relative brightness
+define MIN_FAINT 0.5 # min N/S
+define MIN_ITER 4 # min number of iterations
+define MIN_SHARP -99.9 # min sharpness value
+define MAX_SHARP 99.9 # max sharpness value
+
+# List of NSTAR error codes
+
+define NSTERR_OK 0
+define NSTERR_BIGGROUP 1
+define NSTERR_INDEFSKY 2
+define NSTERR_NOPIX 3
+define NSTERR_SINGULAR 4
+define NSTERR_FAINT 5
+define NSTERR_MERGE 6
+define NSTERR_OFFIMAGE 7
diff --git a/noao/digiphot/daophot/lib/peakdef.h b/noao/digiphot/daophot/lib/peakdef.h
new file mode 100644
index 00000000..badc6246
--- /dev/null
+++ b/noao/digiphot/daophot/lib/peakdef.h
@@ -0,0 +1,55 @@
+# The PEAK task definitions files
+
+# The fitting algorithm error codes
+
+define PKERR_OK 0
+define PKERR_INDEFSKY 1
+define PKERR_NOPIX 2
+define PKERR_SINGULAR 3
+define PKERR_FAINT 4
+#define PKERR_NOCONVERGE 5
+
+# The PEAK fitting structure
+
+define LEN_PKSTRUCT 10
+
+define DP_PKNTERM Memi[$1] # the number of terms to be fit
+define DP_PKCLAMP Memi[$1+1] # pointer to the clamp array
+define DP_PKNORMAL Memi[$1+2] # pointer to the norm array
+define DP_PKRESID Memi[$1+3] # pointer to the residuals vector
+define DP_PKDERIV Memi[$1+4] # pointer to the derivative array
+define DP_PKRESULT Memi[$1+5] # pointer to the results vector
+define DP_PKOLDRESULT Memi[$1+6] # pointer to the old results vector
+
+# Definitions controlling input / output variables
+
+define DELTA_MAG 5.0 # mag difference assigned to input INDEF stars
+define PK_NOUTCOL 11 # the number of columns in the output table
+
+# Various PEAK fitting constants
+
+#define SIGN_CHECK -1.2e-38 # check for change of sign
+define MAX_DELTA_BRIGHTER 5.25 # max permitted brightness increase
+define MAX_DELTA_FAINTER 0.84 # max permitted brightness decrease
+define MAX_DELTA_PIX 0.4 # max +/- change in x/y positions
+define MAX_NEW_ERRMAG 0.05 # convergenge check on magnitude error
+define MIN_REL_BRIGHT 1.0e-5 # minimum relative brightness
+define MAX_NEW_RELBRIGHT1 0.0001 # convergence check on brightness
+define MAX_NEW_RELBRIGHT2 0.002 # convergence check on brightness
+define MAX_PIXERR1 0.001 # convergence check on x/y positions
+define MAX_PIXERR2 0.02 # convergence check on x/y positions
+define MAX_CLAMPFACTOR 0.25 # maximum clamping factor
+define MIN_SHARP -99.99 # min sharpness value
+define MAX_SHARP 99.99 # max sharpness value
+define PEAK_EPSILONR 2.0e-6 # test for inclusion inside fitrad
+define NCORE_SIGMASQ 36.0 # max gsigma-sq for sharpness value
+define CHI_NORM 1.2533141 # sqrt (PI / 2.0)
+define MIN_SUMWT 3.0 # min value of the radial weight sum
+define MIN_NPIX 4 # min number of pixels for fit
+
+define WCRIT_MAX 0.5 # max noise / signal ratio
+define WCRIT_MED 0.6667 # median noise / signal ratio
+define WCRIT_MIN 1.0 # min noise / signal ratio
+define WCRIT_NMAX 15 # max number of iterations
+define WCRIT_NMED 10 # median number of iterations
+define WCRIT_NMIN 5 # minimum number of iterations
diff --git a/noao/digiphot/daophot/lib/psfdef.h b/noao/digiphot/daophot/lib/psfdef.h
new file mode 100644
index 00000000..2a40b590
--- /dev/null
+++ b/noao/digiphot/daophot/lib/psfdef.h
@@ -0,0 +1,111 @@
+# PSF fitting task definitions
+
+# PSF fitting parameters (# 201 - 300)
+
+define PNUM 201 # number of PSF stars
+define CUR_PSF 202 # index of current PSF star
+define CUR_PSFID 203 # id of current PSF star
+define CUR_PSFX 204 # x coordinate of current PSF star
+define CUR_PSFY 205 # y coordinate of current PSF star
+define CUR_PSFSKY 206 # sky value of current PSF star
+define CUR_PSFMAG 207 # magnitude of current PSF star
+define CUR_PSFMIN 208 # min data value of current PSF star
+define CUR_PSFMAX 209 # max data value of current PSF star
+define CUR_PSFGMAX 210 # max good data value of current PSF star
+define PLOTTYPE 211 # the plot type
+define LENUSERAREA 212 # PSF image user area length
+
+# PSF task plot types
+
+define PSF_PLOTS "|mesh|contour|radial|" # list of plot types
+define PSF_MESHPLOT 1 # mesh plot
+define PSF_CONTOURPLOT 2 # contour plot
+define PSF_RADIALPLOT 3 # radial profile plot
+
+# miscellaneous definitions
+
+define MIN_LENUSERAREA 50000 # minimum length of the user area
+define PSF_NINCOLS 4 # number of columns in input psf star list
+define PSF_NOUTCOLS 6 # number of columns in output group table
+define MAX_NPSFITER 300 # max number of analytic fit iterations
+
+# PSF fitting colon commands
+
+define PSF_CMDS "|psfimage|groupfile|function|varorder|fexpand|psfrad|\
+fitrad|nclean|saturated|matchrad|scale|fwhmpsf|datamin|datamax|"
+
+define PSFCMD_PSFIMAGE 1
+define PSFCMD_GROUPFILE 2
+define PSFCMD_FUNCTION 3
+define PSFCMD_VARORDER 4
+define PSFCMD_FEXPAND 5
+define PSFCMD_PSFRAD 6
+define PSFCMD_FITRAD 7
+define PSFCMD_NCLEAN 8
+define PSFCMD_SATURATED 9
+define PSFCMD_MATCHRAD 10
+define PSFCMD_SCALE 11
+define PSFCMD_FWHMPSF 12
+define PSFCMD_DATAMIN 13
+define PSFCMD_DATAMAX 14
+
+# the PSF task fitting structure
+
+define LEN_PSFSTRUCT (50)
+
+# arrays required for fitting analytic psf and the look-up table
+
+define DP_LENUSERAREA Memi[$1] # size of the output psf user area
+define DP_PC Memi[$1+1] # pointer to fitting matrix
+define DP_PV Memi[$1+3] # pointer to fitting vector
+define DP_PTMP Memi[$1+4] # pointer to temporary vector
+define DP_PZ Memi[$1+5] # pointer to parameter changes
+define DP_PCLAMP Memi[$1+6] # pointer to clamp vector
+define DP_POLD Memi[$1+7] # pointer to previous parameter changes
+define DP_PSIGANA Memr[P2R($1+8)] # normalized sigma for analytic fit
+define DP_PSUMANA Memr[P2R($1+9)] # number of points in analytic fit
+
+# dimensions and arrays required for psf star list
+
+define DP_PNUM Memi[$1+10] # number of stars in PSF
+define DP_PSAT Memi[$1+11] # pointer to PSF star saturation indices
+define DP_PXCEN Memi[$1+12] # pointer to the PSF star x coords
+define DP_PYCEN Memi[$1+13] # pointer to the PSF star y coords
+define DP_PMAG Memi[$1+14] # pointer to the PSF star list mags
+define DP_PH Memi[$1+15] # pointer to the PSF star heights
+define DP_PWEIGHT Memi[$1+16] # pointer to the PSF star weights
+define DP_PXCLAMP Memi[$1+17] # pointer to the PSF star x clamps
+define DP_PYCLAMP Memi[$1+18] # pointer to the PSF star y clamps
+define DP_PXOLD Memi[$1+19] # pointer to the old PSF star x values
+define DP_PYOLD Memi[$1+20] # pointer to the old PSF star y values
+
+# additional arrays required for fitting the look-up table
+
+define DP_PSUMN Memi[$1+21] # pointer to the number of points
+define DP_PSUMW Memi[$1+22] # pointer to the weights corrections
+define DP_PSUMSQ Memi[$1+23] # pointer to the resdiduals
+define DP_PSIGMA Memi[$1+24] # pointer to the standard deviations
+define DP_PCONST Memi[$1+25] # pointer to the const part of psf
+define DP_POLDLUT Memi[$1+26] # pointer to the old lookup table
+
+# description of current psf star
+
+define DP_CUR_PSF Memi[$1+27] # position of current PSF star in file
+define DP_CUR_PSFID Memi[$1+28] # id of current PSF star
+define DP_CUR_PSFX Memr[P2R($1+29)]# x position of current PSF star
+define DP_CUR_PSFY Memr[P2R($1+30)]# y position of current PSF star
+define DP_CUR_PSFSKY Memr[P2R($1+31)]# sky for current PSF star
+define DP_CUR_PSFMAG Memr[P2R($1+32)]# magnitude for current PSF star
+define DP_CUR_PSFMIN Memr[P2R($1+33)]# minimum data value in PSF subrast
+define DP_CUR_PSFMAX Memr[P2R($1+34)]# maximum data value in PSF subrast
+define DP_CUR_PSFGMAX Memr[P2R($1+35)]# maximum good data value in fitrad
+
+# the psf plotting parameters
+
+define DP_PLOTTYPE Memi[$1+36] # type of PSF plot
+define DP_MANGV Memr[P2R($1+37)]# vertical angle for surface plot
+define DP_MANGH Memr[P2R($1+38)]# horizontal angle for surface plot
+define DP_MFLOOR Memr[P2R($1+39)]# floor value for surface plot
+define DP_MCEILING Memr[P2R($1+40)]# ceiling for surface plot
+define DP_CFLOOR Memr[P2R($1+41)]# floor for contour
+define DP_CCEILING Memr[P2R($1+42)]# ceiling for contour
diff --git a/noao/digiphot/daophot/lib/warning.dat b/noao/digiphot/daophot/lib/warning.dat
new file mode 100644
index 00000000..ee8d55c1
--- /dev/null
+++ b/noao/digiphot/daophot/lib/warning.dat
@@ -0,0 +1,14 @@
+
+
+ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+ WARNING FROM THE DAOPHOT PACKAGE LOADER
+ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+
+ The SDAS external package TABLES optionally used by some of the
+ DAOPHOT tasks is not available. The tasks PAPPEND, PDUMP,
+ PRENUMBER, PSELECT and PSORT will run only on DAOPHOT output
+ files written in text database format (the default) but will not
+ run on files written in ST tables format. Check the value of the
+ DAOPHOT package parameter "text" before beginning reductions.
+
+
diff --git a/noao/digiphot/daophot/mkpkg b/noao/digiphot/daophot/mkpkg
new file mode 100644
index 00000000..84fab316
--- /dev/null
+++ b/noao/digiphot/daophot/mkpkg
@@ -0,0 +1,44 @@
+# DAOPHOT libraries
+
+$call relink
+$exit
+
+update:
+ $call relink
+ $call install
+ ;
+
+relink:
+ $omake x_daophot.x
+ !mkpkg -p noao trelink XF="$(XFLAGS)" LF="$(LFLAGS)"
+ ;
+
+linkonly:
+ !mkpkg -p noao trelink XF="$(XFLAGS)" LF="$(LFLAGS)"
+ ;
+
+install:
+ $move xx_daophot.e noaobin$x_daophot.e
+ ;
+
+trelink:
+ $set LIBS = "-lncar -lgks -ltbtables -lxtools -lds"
+ $set XFLAGS = "$(XFLAGS) $(XF)"
+ $set LFLAGS = "$(LFLAGS) $(LF)"
+ $update libpkg.a
+ $link x_daophot.o libpkg.a ../lib/libpttables.a $(LIBS) -o xx_daophot.e
+ ;
+
+libpkg.a:
+ @addstar
+ @allstar
+ @daoedit
+ @daolib
+ @group
+ @nstar
+ @peak
+ @psf
+ @seepsf
+ @select
+ @substar
+ ;
diff --git a/noao/digiphot/daophot/nstar.par b/noao/digiphot/daophot/nstar.par
new file mode 100644
index 00000000..28589e90
--- /dev/null
+++ b/noao/digiphot/daophot/nstar.par
@@ -0,0 +1,17 @@
+# Parameters for the NSTAR task
+
+image,f,a,,,,"Image corresponding to photometry"
+groupfile,f,a,default,,,"Input group file (image.grp.?)"
+psfimage,f,a,default,,,"PSF image (default: image.psf.?)"
+nstarfile,f,a,default,,,"Output photometry file (default: image.nst.?)"
+rejfile,f,a,default,,,"Output rejections file (default: image.nrj.?)"
+datapars,pset,h,"",,,Data parameters
+daopars,pset,h,"",,,Psf fitting parameters
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+wcspsf,s,h,)_.wcspsf,,,"The psf coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the input image pixels in memory?"
+verify,b,h,)_.verify,,,Verify critical nstar parameters?
+update,b,h,)_.update,,,Update critical nstar parameters?
+verbose,b,h,)_.verbose,,,Print nstar messages?
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/nstar/dpggroup.x b/noao/digiphot/daophot/nstar/dpggroup.x
new file mode 100644
index 00000000..fa180c17
--- /dev/null
+++ b/noao/digiphot/daophot/nstar/dpggroup.x
@@ -0,0 +1,386 @@
+include "../../lib/ptkeysdef.h"
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+
+# DP_GNSTPSF -- Procedure to initialize for reading the group file fields from
+# a photometry text file . The group file fields are ID, GROUP, X, Y, MAG, ERR,
+# and SKY.
+
+procedure dp_gnstpsf (fields, sel_fields, max_nfields)
+
+int fields[ARB] # array of selected fields
+char sel_fields[ARB] # names of selected containing fields
+int max_nfields # maximum number of fields selected
+
+int i
+int strlen()
+
+begin
+ # Initialize the fields string.
+ sel_fields[1] = EOS
+
+ # Encode the fields.
+ do i = 1, max_nfields {
+ switch (fields[i]) {
+ case DP_PAPID:
+ call sprintf (sel_fields[strlen(sel_fields)+1], SZ_LINE, "%s ")
+ call pargstr (ID)
+ case DP_PAPXCEN:
+ call sprintf (sel_fields[strlen(sel_fields)+1], SZ_LINE, "%s ")
+ call pargstr (XCENTER)
+ case DP_PAPYCEN:
+ call sprintf (sel_fields[strlen(sel_fields)+1], SZ_LINE, "%s ")
+ call pargstr (YCENTER)
+ case DP_PAPSKY:
+ call sprintf (sel_fields[strlen(sel_fields)+1], SZ_LINE, "%s ")
+ call pargstr (SKY)
+ case DP_PAPMAG1:
+ call sprintf (sel_fields[strlen(sel_fields)+1], SZ_LINE, "%s ")
+ call pargstr (MAG)
+ case DP_PAPGROUP:
+ call sprintf (sel_fields[strlen(sel_fields)+1], SZ_LINE, "%s ")
+ call pargstr (GROUP)
+ }
+ }
+
+ # Backspace over the terminating blank character.
+ if (sel_fields[1] != EOS)
+ sel_fields[strlen(sel_fields)] = EOS
+end
+
+
+# DP_TNSTINIT -- Procedure to initialize for reading the group file fields from
+# a photometry table. The group file fields are ID, GROUP, X, Y, MAG, ERR,
+# and SKY.
+
+procedure dp_tnstinit (tp, colpoint)
+
+pointer tp # the table descriptor
+pointer colpoint[ARB] # the column descriptor
+
+begin
+ # Get the id.
+ # First the ID
+ call tbcfnd (tp, ID, colpoint[1], 1)
+ if (colpoint[1] == NULL) {
+ call eprintf ("Column %s not found\n")
+ call pargstr (ID)
+ }
+
+ # Get the x position.
+ call tbcfnd (tp, XCENTER, colpoint[2], 1)
+ if (colpoint[2] == NULL) {
+ call eprintf ("Column %s not found\n")
+ call pargstr (XCENTER)
+ }
+
+ # Get the y position.
+ call tbcfnd (tp, YCENTER, colpoint[3], 1)
+ if (colpoint[3] == NULL) {
+ call eprintf ("Column %s not found\n")
+ call pargstr (YCENTER)
+ }
+
+ # Get the magnitude.
+ call tbcfnd (tp, MAG, colpoint[4], 1)
+ if (colpoint[4] == NULL) # No column
+ call tbcfnd (tp, APMAG, colpoint[4], 1)
+ if (colpoint[4] == NULL) {
+ call eprintf ("Column %s not found\n")
+ call pargstr (APMAG)
+ }
+
+ # Get the sky.
+ call tbcfnd (tp, SKY, colpoint[5], 1)
+ if (colpoint[5] == NULL)
+ call tbcfnd (tp, SKY, colpoint[5], 1)
+ if (colpoint[5] == NULL) {
+ call eprintf ("Column %s not found\n")
+ call pargstr (SKY)
+ }
+
+ # Get the group number.
+ call tbcfnd (tp, GROUP, colpoint[6], 1)
+ if (colpoint[6] == NULL) {
+ call eprintf ("Column %s not found\n")
+ call pargstr (GROUP)
+ }
+end
+
+
+# DP_GGROUP -- Read in a single group.
+
+int procedure dp_ggroup (dao, tp, key, fields, indices, colpoint, max_row,
+ max_group, in_record, curr_group)
+
+pointer dao # pointer to daophot structure
+int tp # input file/table descriptor
+pointer key # pointer to text database structure
+char fields[ARB] # nstar fields to be read
+int indices[ARB] # array of text file field pointers
+int colpoint[ARB] # array of column pointers
+int max_row # number of rows in table
+int max_group # maximum group size
+int in_record # pointer to current input record
+int curr_group # current group number
+
+bool nullflag
+int istar, group, buf_size
+pointer apsel
+int dp_nstsel()
+
+begin
+ # If the current input record is set to zero we are at EOF. In_record
+ # is initialized to one on entry to this routine.
+
+ if (in_record == 0)
+ return (0)
+
+ # Get the next group number. Note that the last star read on the
+ # previous call is the first star in the new group.
+
+ apsel = DP_APSEL(dao)
+ if (in_record == 1) {
+ buf_size = max_group
+ group = 0
+ istar = 0
+ } else {
+ Memi[DP_APID(apsel)] = Memi[DP_APID(apsel)+istar-1]
+ Memr[DP_APXCEN(apsel)] = Memr[DP_APXCEN(apsel)+istar-1]
+ Memr[DP_APYCEN(apsel)] = Memr[DP_APYCEN(apsel)+istar-1]
+ Memr[DP_APMAG(apsel)] = Memr[DP_APMAG(apsel)+istar-1]
+ Memr[DP_APMSKY(apsel)] = Memr[DP_APMSKY(apsel)+istar-1]
+ istar = 1
+ }
+
+ # Loop over the stars in a single group.
+ repeat {
+
+ # Set the current group.
+ curr_group = group
+
+ # Read in the photometry for a single star.
+
+ # In this case we have a text database file.
+ if (key != NULL) {
+
+ if (dp_nstsel (key, tp, fields, indices, Memi[DP_APID(apsel)+
+ istar], group, Memr[DP_APXCEN(apsel)+istar],
+ Memr[DP_APYCEN(apsel)+istar], Memr[DP_APMSKY(apsel)+
+ istar], Memr[DP_APMAG(apsel)+ istar]) == EOF) {
+ in_record = 0
+ break
+ }
+
+ # In this case we have a table.
+ } else {
+
+ if (in_record > max_row) {
+ in_record = 0
+ break
+ } else {
+ call tbrgti (tp, colpoint[1], Memi[DP_APID(apsel)+istar],
+ nullflag, 1, in_record)
+ call tbrgtr (tp, colpoint[2], Memr[DP_APXCEN(apsel)+istar],
+ nullflag, 1, in_record)
+ call tbrgtr (tp, colpoint[3], Memr[DP_APYCEN(apsel)+istar],
+ nullflag, 1, in_record)
+ call tbrgtr (tp, colpoint[4], Memr[DP_APMAG(apsel)+istar],
+ nullflag, 1, in_record)
+ call tbrgtr (tp, colpoint[5], Memr[DP_APMSKY(apsel)+istar],
+ nullflag, 1, in_record)
+ call tbrgti (tp, colpoint[6], group, nullflag, 1, in_record)
+ }
+ }
+
+ # Increment the record and star counters.
+ in_record = in_record + 1
+ istar = istar + 1
+
+ # Allocate more memory as needed.
+ if (istar == buf_size) {
+ buf_size = buf_size + max_group
+ call dp_rmemapsel (dao, indices, NAPPAR, buf_size + 1)
+ }
+
+ } until ((group != curr_group) && (curr_group != 0))
+
+ # Return the number of stars in the group.
+ if (in_record == 0) {
+ if (curr_group == 0)
+ curr_group = group
+ return (istar)
+ } else
+ return (istar - 1)
+end
+
+
+# DP_NSTSEL -- Read in the required photometry records from a text file.
+
+int procedure dp_nstsel (key, fd, fields, indices, id, group, x, y, sky, mag)
+
+pointer key # pointer to key structure
+int fd # text file descriptor
+char fields[ARB] # fields to be output
+int indices[ARB] # indices array
+int id # star id number
+int group # group number
+real x # x center
+real y # y center
+real sky # sky value
+real mag # magnitude
+
+int nchars, nunique, uunique, funique, ncontinue, recptr
+int first_rec, nselect, record
+pointer line
+int getline(), strncmp(), pt_choose()
+data first_rec /YES/
+
+begin
+ # Initialize the file read.
+ if (first_rec == YES) {
+ nunique = 0
+ uunique = 0
+ funique = 0
+ nselect = 0
+ record = 0
+ call malloc (line, SZ_LINE, TY_CHAR)
+ }
+
+ # Initialize the record read.
+ ncontinue = 0
+ recptr = 1
+
+ # Loop over the text file records.
+ repeat {
+
+ # Read in a line of the text file.
+ nchars = getline (fd, Memc[line])
+ if (nchars == EOF)
+ break
+
+ # Determine the type of record.
+ if (Memc[line] == KY_CHAR_POUND) {
+
+ if (strncmp (Memc[line], KY_CHAR_KEYWORD, KY_LEN_STR) == 0) {
+ call pt_kyadd (key, Memc[line], nchars)
+ } else if (strncmp (Memc[line], KY_CHAR_NAME,
+ KY_LEN_STR) == 0) {
+ nunique = nunique + 1
+ call pt_kname (key, Memc[line], nchars, nunique)
+ } else if (strncmp (Memc[line], KY_CHAR_UNITS,
+ KY_LEN_STR) == 0) {
+ uunique = uunique + 1
+ call pt_knunits (key, Memc[line], nchars, uunique)
+ } else if (strncmp (Memc[line], KY_CHAR_FORMAT,
+ KY_LEN_STR) == 0) {
+ funique = funique + 1
+ call pt_knformats (key, Memc[line], nchars, funique)
+ }
+
+ } else if (Memc[line] == KY_CHAR_NEWLINE) {
+ # skip blank lines
+
+ } else {
+
+ # Construct the text file record.
+ call pt_mkrec (key, Memc[line], nchars, first_rec, recptr,
+ ncontinue)
+
+ # Construct output record when there is no continuation char.
+ if (Memc[line+nchars-2] != KY_CHAR_CONT) {
+
+ # Select the appropriate records.
+ if (nselect <= 0) {
+ nselect = pt_choose (key, fields)
+ if (nselect < NAPGROUP) {
+ call eprintf (
+ "The group file does not have the correct format\n")
+ break
+ }
+ }
+
+ # Construct the output record by moving the selected fields
+ # into the data structures.
+
+ call dp_gnst (key, indices, id, group, x, y, sky, mag)
+ record = record + 1
+ first_rec = NO
+
+ # Record is complete so exit the loop.
+ break
+ }
+ }
+
+ }
+
+ # Return EOF or the record number.
+ if (nchars == EOF || (nselect < NAPGROUP)) {
+ first_rec = YES
+ nunique = 0
+ uunique = 0
+ funique = 0
+ nselect = 0
+ call mfree (line, TY_CHAR)
+ return (EOF)
+ } else
+ return (record)
+end
+
+
+# DP_GNST -- Decode the standard GROUP text file fields into the appropriate
+# arrays.
+
+procedure dp_gnst (key, fields, id, group, x, y, sky, mag)
+
+pointer key # pointer to keys strucuture
+int fields[ARB] # fields array
+int id # star id
+int group # group id
+real x # x position
+real y # y position
+real sky # sky value
+real mag # magnitude
+
+int i, index, elem, maxch, kip, ip
+int ctoi(), ctor()
+char buffer[SZ_LINE]
+
+begin
+ do i = 1, KY_NSELECT(key) {
+
+ # Find the key.
+ index = Memi[KY_SELECT(key)+i-1]
+ elem = Memi[KY_ELEM_SELECT(key)+i-1]
+ maxch = Memi[KY_LEN_SELECT(key)+i-1]
+ kip = Memi[KY_PTRS(key)+index-1] + (elem - 1) * maxch
+ call amovc (Memc[kip], buffer, maxch)
+ buffer[maxch+1] = EOS
+
+ # Decode the output value.
+ ip = 1
+ switch (fields[i]) {
+ case DP_PAPID:
+ if (ctoi (buffer, ip, id) <= 0)
+ call error (0, "ERROR: Error reading ID field.")
+ case DP_PAPGROUP:
+ if (ctoi (buffer, ip, group) <= 0)
+ call error (0, "ERROR: Error reading GROUP field.")
+ case DP_PAPXCEN:
+ if (ctor (buffer, ip, x) <= 0)
+ call error (0, "ERROR: Error reading XCENTER field.")
+ case DP_PAPYCEN:
+ if (ctor (buffer, ip, y) <= 0)
+ call error (0, "ERROR: Error reading YCENTER field.")
+ case DP_PAPSKY:
+ if (ctor (buffer, ip, sky) <= 0)
+ call error (0, "ERROR: Error reading MSKY field.")
+ case DP_PAPMAG1:
+ if (ctor (buffer, ip, mag) <= 0)
+ call error (0, "ERROR: Error reading MAG field.")
+ default:
+ call printf ("Error reading the photometry file.\n")
+ }
+
+ }
+end
diff --git a/noao/digiphot/daophot/nstar/dpmemnstar.x b/noao/digiphot/daophot/nstar/dpmemnstar.x
new file mode 100644
index 00000000..04bd25f4
--- /dev/null
+++ b/noao/digiphot/daophot/nstar/dpmemnstar.x
@@ -0,0 +1,158 @@
+include "../lib/daophotdef.h"
+include "../lib/nstardef.h"
+
+# DP_NSTARSETUP -- Procedure to set up the NSTAR parameters.
+
+procedure dp_nstarsetup (dp)
+
+pointer dp # pointer to daophot structure
+
+pointer nstar
+
+begin
+ # Allocate Memory
+ call malloc (DP_NSTAR(dp), LEN_NSTARSTRUCT, TY_STRUCT)
+ nstar = DP_NSTAR(dp)
+
+ DP_NNPIX(nstar) = NULL
+ DP_NNUMER(nstar) = NULL
+ DP_NDENOM(nstar) = NULL
+ DP_NRPIXSQ(nstar) = NULL
+ DP_NSKIP(nstar) = NULL
+ DP_NXCLAMP(nstar) = NULL
+ DP_NXOLD(nstar) = NULL
+ DP_NX(nstar) = NULL
+ DP_NV(nstar) = NULL
+ DP_NSUMWT(nstar) = NULL
+ DP_NC(nstar) = NULL
+ DP_NIER(nstar) = NULL
+end
+
+
+# DP_MEMNSTAR -- Procedure to allocate sufficient memory for NSTAR.
+
+procedure dp_memnstar (dao, max_star)
+
+pointer dao # pointer to daophot structure
+int max_star # maximum number of stars
+
+pointer nstar
+
+begin
+ nstar = DP_NSTAR(dao)
+
+ if (DP_NNPIX (nstar) != NULL)
+ call mfree (DP_NNPIX (nstar), TY_INT)
+ call malloc (DP_NNPIX (nstar), max_star + 1, TY_INT)
+
+ if (DP_NNUMER (nstar) != NULL)
+ call mfree (DP_NNUMER (nstar), TY_REAL)
+ call malloc (DP_NNUMER (nstar), max_star + 1, TY_REAL)
+
+ if (DP_NDENOM (nstar) != NULL)
+ call mfree (DP_NDENOM (nstar), TY_REAL)
+ call malloc (DP_NDENOM (nstar), max_star + 1, TY_REAL)
+
+ if (DP_NRPIXSQ (nstar) != NULL)
+ call mfree (DP_NRPIXSQ (nstar), TY_REAL)
+ call malloc (DP_NRPIXSQ (nstar), max_star + 1, TY_REAL)
+
+ if (DP_NSKIP (nstar) != NULL)
+ call mfree (DP_NSKIP (nstar), TY_INT)
+ call malloc (DP_NSKIP (nstar), max_star + 1, TY_INT)
+
+ if (DP_NIER (nstar) != NULL)
+ call mfree (DP_NIER (nstar), TY_INT)
+ call malloc (DP_NIER(nstar), max_star + 1, TY_INT)
+
+ if (DP_NSUMWT (nstar) != NULL)
+ call mfree (DP_NSUMWT (nstar), TY_REAL)
+ call malloc (DP_NSUMWT (nstar), max_star + 1, TY_REAL)
+
+ if (DP_RECENTER(dao) == YES) {
+
+ if (DP_NXCLAMP (nstar) != NULL)
+ call mfree (DP_NXCLAMP (nstar), TY_REAL)
+ call malloc (DP_NXCLAMP (nstar), 3 * max_star + 1, TY_REAL)
+
+ if (DP_NXOLD (nstar) != NULL)
+ call mfree (DP_NXOLD (nstar), TY_REAL)
+ call malloc (DP_NXOLD (nstar), 3 * max_star + 1, TY_REAL)
+
+ if (DP_NX (nstar) != NULL)
+ call mfree (DP_NX (nstar), TY_REAL)
+ call malloc (DP_NX (nstar), 3 * max_star + 1, TY_REAL)
+
+ if (DP_NC (nstar) != NULL)
+ call mfree (DP_NC (nstar), TY_REAL)
+ call malloc (DP_NC (nstar), (3 * max_star + 1) * (3 * max_star + 1),
+ TY_REAL)
+
+ if (DP_NV (nstar) != NULL)
+ call mfree (DP_NV (nstar), TY_REAL)
+ call malloc (DP_NV (nstar), 3 * max_star + 1, TY_REAL)
+
+ } else {
+
+ if (DP_NXCLAMP (nstar) != NULL)
+ call mfree (DP_NXCLAMP (nstar), TY_REAL)
+ call malloc (DP_NXCLAMP (nstar), max_star + 1, TY_REAL)
+
+ if (DP_NXOLD (nstar) != NULL)
+ call mfree (DP_NXOLD (nstar), TY_REAL)
+ call malloc (DP_NXOLD (nstar), max_star + 1, TY_REAL)
+
+ if (DP_NX (nstar) != NULL)
+ call mfree (DP_NX (nstar), TY_REAL)
+ call malloc (DP_NX (nstar), max_star + 1, TY_REAL)
+
+ if (DP_NC (nstar) != NULL)
+ call mfree (DP_NC (nstar), TY_REAL)
+ call malloc (DP_NC (nstar), (max_star + 1) * (max_star + 1),
+ TY_REAL)
+
+ if (DP_NV (nstar) != NULL)
+ call mfree (DP_NV (nstar), TY_REAL)
+ call malloc (DP_NV (nstar), max_star + 1, TY_REAL)
+ }
+end
+
+
+# DP_NSCLOSE -- Procedure to close up the NSTAR parameters.
+
+procedure dp_nsclose (dp)
+
+pointer dp # pointer to daophot structure
+
+pointer nstar
+
+begin
+ nstar = DP_NSTAR(dp)
+
+ if (DP_NNPIX (nstar) != NULL)
+ call mfree (DP_NNPIX (nstar), TY_INT)
+ if (DP_NNUMER (nstar) != NULL)
+ call mfree (DP_NNUMER (nstar), TY_REAL)
+ if (DP_NDENOM (nstar) != NULL)
+ call mfree (DP_NDENOM (nstar), TY_REAL)
+ if (DP_NRPIXSQ (nstar) != NULL)
+ call mfree (DP_NRPIXSQ (nstar), TY_REAL)
+ if (DP_NSKIP (nstar) != NULL)
+ call mfree (DP_NSKIP (nstar), TY_INT)
+ if (DP_NXCLAMP (nstar) != NULL)
+ call mfree (DP_NXCLAMP (nstar), TY_REAL)
+ if (DP_NXOLD (nstar) != NULL)
+ call mfree (DP_NXOLD (nstar), TY_REAL)
+ if (DP_NX (nstar) != NULL)
+ call mfree (DP_NX (nstar), TY_REAL)
+ if (DP_NV (nstar) != NULL)
+ call mfree (DP_NV (nstar), TY_REAL)
+ if (DP_NSUMWT (nstar) != NULL)
+ call mfree (DP_NSUMWT (nstar), TY_REAL)
+ if (DP_NC (nstar) != NULL)
+ call mfree (DP_NC (nstar), TY_REAL)
+ if (DP_NIER (nstar) != NULL)
+ call mfree (DP_NIER (nstar), TY_INT)
+
+ call mfree (nstar, TY_STRUCT)
+end
diff --git a/noao/digiphot/daophot/nstar/dpnconfirm.x b/noao/digiphot/daophot/nstar/dpnconfirm.x
new file mode 100644
index 00000000..ecbd3056
--- /dev/null
+++ b/noao/digiphot/daophot/nstar/dpnconfirm.x
@@ -0,0 +1,34 @@
+include "../lib/daophotdef.h"
+
+# DP_NCONFIRM -- Procedure to confirm the critical nstar parameters.
+
+procedure dp_nconfirm (dao)
+
+pointer dao # pointer to the group structure
+
+int dp_stati()
+
+begin
+ call printf ("\n")
+
+ # Confirm recentering and sky fitting.
+ call dp_vrecenter (dao)
+ call dp_vfitsky (dao)
+ if (dp_stati (dao, FITSKY) == NO)
+ call dp_vgroupsky (dao)
+
+ # Confirm the psf radius.
+ call dp_vpsfrad (dao)
+
+ # Confirm the fitting radius.
+ call dp_vfitrad (dao)
+
+ # Confirm the maximum group size.
+ call dp_vmaxgroup (dao)
+
+ # Confirm the minimum and maximum good data values.
+ call dp_vdatamin (dao)
+ call dp_vdatamax (dao)
+
+ call printf ("\n")
+end
diff --git a/noao/digiphot/daophot/nstar/dpnstar.x b/noao/digiphot/daophot/nstar/dpnstar.x
new file mode 100644
index 00000000..66ba10a4
--- /dev/null
+++ b/noao/digiphot/daophot/nstar/dpnstar.x
@@ -0,0 +1,355 @@
+include <imhdr.h>
+include <tbset.h>
+include <mach.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/nstardef.h"
+
+
+# DP_NPHOT -- Read in the groups and fit all the stars in each group
+# simultaneously.
+
+procedure dp_nphot (dao, im, grp, nst, rej, ap_text)
+
+pointer dao # pointer to the daophot structure
+pointer im # input image descriptor
+int grp # input group file descriptor
+int nst # output photometry file descriptor
+int rej # rejections file descriptor
+bool ap_text # photometry text file
+
+bool converge
+int out_record, rout_record, in_record, nrow_in_table, old_size, niter
+int cdimen, stat
+pointer sp, indices, fields, icolpoint, ocolpoint, key, nstar, apsel
+real radius, mean_sky
+
+int dp_ggroup(), tbpsta(), dp_nstarfit(), dp_nxycheck()
+real dp_nmsky()
+
+begin
+ # Store the original value of the fitting radius.
+ radius = DP_FITRAD(dao)
+ DP_FITRAD(dao) = min (DP_FITRAD(dao), DP_PSFRAD(dao))
+ DP_SFITRAD(dao) = DP_FITRAD(dao) * DP_SCALE(dao)
+
+ # Allocate working memory.
+ call smark (sp)
+ call salloc (icolpoint, NAPGROUP, TY_INT)
+ call salloc (indices, NAPPAR, TY_INT)
+ call salloc (fields, SZ_LINE, TY_CHAR)
+ call salloc (ocolpoint, NST_NOUTCOL, TY_INT)
+
+ # Get some daophot pointers.
+ apsel = DP_APSEL(dao)
+ nstar = DP_NSTAR (dao)
+
+ # Allocate space for and define the output table.
+ if (DP_TEXT(dao) == YES) {
+ call dp_xpnewnstar (dao, nst)
+ if (rej != NULL)
+ call dp_xpnewnstar (dao, rej)
+ } else {
+ call dp_tpnewnstar (dao, nst, Memi[ocolpoint])
+ if (rej != NULL)
+ call dp_tpnewnstar (dao, rej, Memi[ocolpoint])
+ }
+
+ # Set up the input file.
+ call dp_gnindices (Memi[indices])
+ if (ap_text) {
+ call pt_kyinit (key)
+ call dp_gnstpsf (Memi[indices], Memc[fields], NAPGROUP)
+ nrow_in_table = 0
+ } else {
+ key = NULL
+ call dp_tnstinit (grp, Memi[icolpoint])
+ nrow_in_table = tbpsta (grp, TBL_NROWS)
+ }
+
+ # Allocate some memory for fitting.
+ call dp_memapsel (dao, Memi[indices], NAPPAR, DP_MAXGROUP(dao) + 1)
+ call dp_memnstar (dao, DP_MAXGROUP(dao) + 1)
+
+ # Initialize the input/output files for reading/writing.
+ in_record = 1
+ out_record = 0
+ rout_record = 0
+
+ repeat {
+
+ # Read in the next group of stars.
+ old_size = dp_ggroup (dao, grp, key, Memc[fields], Memi[indices],
+ Memi[icolpoint], nrow_in_table, DP_MAXGROUP(dao), in_record,
+ DP_NGNUM(nstar))
+ if (old_size <= 0)
+ break
+ DP_NNUM(nstar) = old_size
+
+ # Convert coordinates if necessary.
+ call dp_win (dao, im, Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], DP_NNUM(nstar))
+
+ # Print out the group number and number of stars.
+ if (DP_VERBOSE (dao) == YES) {
+ call printf ("Group: %4d contains %2d stars\n")
+ call pargi (DP_NGNUM (nstar))
+ call pargi (DP_NNUM (nstar))
+ }
+
+ # If the group center is undefined or off image skip to next
+ # group.
+ if (dp_nxycheck (im, Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ DP_NNUM(nstar), DP_FITRAD(dao), stat) <= 0) {
+
+ if (DP_VERBOSE(dao) == YES) {
+ if (stat < 0)
+ call printf (
+ "\tGroup %d center is undefined: skipping\n")
+ else if (stat == 0)
+ call printf ("\tGroup %d is off the image: skipping\n")
+ call pargi (DP_NGNUM(nstar))
+ }
+ next
+
+ # If too many stars skip to the next group.
+ } else if (DP_NNUM (nstar) > DP_MAXGROUP(dao)) {
+
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("\tGroup %d larger than %d stars: skipping\n")
+ call pargi (DP_NGNUM(nstar))
+ call pargi (DP_MAXGROUP(dao))
+ }
+ niter = 0
+ call realloc (DP_NIER(nstar), DP_NNUM(nstar), TY_INT)
+ call dp_nstindef (dao, DP_NNUM(nstar), NSTERR_BIGGROUP)
+
+ # If the mean sky value of group is undefined skip to next group.
+ } else if (IS_INDEFR (dp_nmsky (Memr[DP_APMSKY(apsel)],
+ DP_NNUM(nstar), mean_sky))) {
+
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (
+ "\tGroup %d sky value is undefined: skipping\n")
+ call pargi (DP_NGNUM(nstar))
+ }
+ niter = 0
+ call dp_nstindef (dao, DP_NNUM(nstar), NSTERR_INDEFSKY)
+
+ # Do the fit.
+ } else {
+
+ # Estimate values of INDEF magnitudes.
+ call dp_nmaginit (dao, Memr[DP_APMAG(apsel)],
+ Memr[DP_APERR(apsel)], DP_NNUM(nstar))
+
+ # Set up for the fit.
+ if (DP_RECENTER(dao) == YES)
+ cdimen = 3 * DP_NNUM(nstar) + 1
+ else
+ cdimen = DP_NNUM(nstar) + 1
+
+ # Iterate.
+ for (niter = 1; niter <= DP_MAXITER(dao); niter = niter + 1) {
+ DP_NNUM(nstar) = dp_nstarfit (dao, im, DP_NNUM(nstar),
+ mean_sky, cdimen, niter, converge)
+ if (DP_NNUM(nstar) <= 0)
+ break
+ if (converge)
+ break
+ }
+
+ # Solution did not converge.
+ niter = min (niter, DP_MAXITER(dao))
+ }
+
+ # Now write out the results.
+ if (DP_TEXT(dao) == YES)
+ call dp_xntwrite (dao, im, nst, rej, niter, old_size)
+ else
+ call dp_tntwrite (dao, im, nst, rej, niter, old_size,
+ out_record, rout_record, Memi[ocolpoint])
+ }
+
+ if (ap_text)
+ call pt_kyfree (key)
+
+ call sfree (sp)
+
+ # Restore the original value of the fitting radius.
+ DP_FITRAD(dao) = radius
+ DP_SFITRAD(dao) = DP_FITRAD(dao) * DP_SCALE(dao)
+end
+
+
+# DP_NSTINDEF -- Set magnitudes and fitting parameters of unfit stars to indef.
+
+procedure dp_nstindef (dao, max_nstars, pier)
+
+pointer dao # pointer to the daophot structure
+int max_nstars # number of stars
+int pier # the photometry error code
+
+int i
+pointer apsel, nstar
+
+begin
+ apsel = DP_APSEL(dao)
+ nstar = DP_NSTAR(dao)
+ do i = 1, max_nstars {
+ Memr[DP_APMAG(apsel)+i-1] = INDEFR
+ Memr[DP_APERR(apsel)+i-1] = INDEFR
+ Memr[DP_APCHI(apsel)+i-1] = INDEFR
+ Memr[DP_APSHARP(apsel)+i-1] = INDEFR
+ Memi[DP_NIER(nstar)+i-1] = pier
+ }
+end
+
+
+# DP_GNINDICES -- Get the memory allocation fields.
+
+procedure dp_gnindices (indices)
+
+int indices[ARB] # index array
+
+begin
+ indices[1] = DP_PAPID
+ indices[2] = DP_PAPXCEN
+ indices[3] = DP_PAPYCEN
+ indices[4] = DP_PAPMAG1
+ indices[5] = DP_PAPSKY
+ indices[6] = DP_PAPGROUP
+ indices[7] = DP_PAPMERR1
+ indices[8] = DP_PAPNITER
+ indices[9] = DP_PAPSHARP
+ indices[10] = DP_PAPCHI
+end
+
+
+define GRP_CTRINDEF -1
+define GRP_CTROFFIMAGE 0
+define GRP_CTROK 1
+
+# DP_NXYCHECK -- Check that the center of the group is defined. -1 is
+# returned if the center of the group is undefined, 0, is returned if the
+# group is entirely off the image, 1 is returned if the group is at least
+# partially on the input image.
+
+int procedure dp_nxycheck (im, x, y, group_size, radius, stat)
+
+pointer im # pointer to the input image
+real x[ARB] # array of x values
+real y[ARB] # array of y values
+int group_size # the size of the group
+real radius # the fitting radius
+int stat # the return status
+
+int i, nxy
+real xmin, xmax, ymin, ymax, xx, yy
+
+begin
+ # Initialize.
+ stat = GRP_CTRINDEF
+ xmin = MAX_REAL
+ xmax = -MAX_REAL
+ ymin = MAX_REAL
+ ymax = -MAX_REAL
+
+ # Compute the minimum and maximum x and y values.
+ nxy = 0
+ do i = 1, group_size {
+ xx = x[i]
+ yy = y[i]
+ if (IS_INDEFR(xx) || IS_INDEFR(yy))
+ next
+ nxy = nxy + 1
+ if (xx < xmin)
+ xmin = xx
+ if (xx > xmax)
+ xmax = xx
+ if (yy < ymin)
+ ymin = yy
+ if (yy > ymax)
+ ymax = yy
+ }
+ if (nxy <= 0)
+ return (stat)
+
+ # Test the min and max values.
+ stat = GRP_CTROFFIMAGE
+ if ((int (xmin - radius) + 1) > IM_LEN(im,1))
+ return (stat)
+ if (int (xmax + radius) < 1)
+ return (stat)
+ if ((int (ymin - radius) + 1) > IM_LEN(im,2))
+ return (stat)
+ if (int (ymax + radius) < 1)
+ return (stat)
+
+ # The group is on the image.
+ stat = GRP_CTROK
+ return (stat)
+end
+
+
+# DP_NMSKY -- Compute the mean sky value for the group of stars.
+
+real procedure dp_nmsky (sky, group_size, msky)
+
+real sky[ARB] # the array of sky values
+int group_size # the size of the group of stars
+real msky # the mean sky value
+
+int i, nsky
+real sky_sum
+
+begin
+ sky_sum = 0.0
+ nsky = 0
+
+ do i = 1, group_size {
+ if (IS_INDEFR(sky[i]))
+ next
+ sky_sum = sky_sum + sky[i]
+ nsky = nsky + 1
+ }
+
+ if (nsky <= 0)
+ msky = INDEFR
+ else
+ msky = sky_sum / nsky
+
+ return (msky)
+end
+
+
+define MIN_REL_BRIGHT 1.0E-04 # minimum relative brightness
+define INIT_REL_BRIGHT 0.01 # initial relative brightness
+
+# DP_NMAGINIT -- Initialize the magnitude and magnitude error arrays before
+# fitting the group.
+
+procedure dp_nmaginit (dao, mag, magerr, group_size)
+
+pointer dao # pointer to the daophot strucuture
+real mag[ARB] # the magnitude array
+real magerr[ARB] # the magnitude error array
+int group_size # size of the group
+
+int i
+pointer psffit
+
+begin
+ psffit = DP_PSFFIT (dao)
+ do i = 1, group_size {
+ if (IS_INDEFR(mag[i]))
+ mag[i] = INIT_REL_BRIGHT
+ else {
+ mag[i] = DAO_RELBRIGHT (psffit, mag[i])
+ if (mag[i] <= MIN_REL_BRIGHT)
+ mag[i] = INIT_REL_BRIGHT
+ }
+ magerr[i] = 0.0
+ }
+end
diff --git a/noao/digiphot/daophot/nstar/dpnstarfit.x b/noao/digiphot/daophot/nstar/dpnstarfit.x
new file mode 100644
index 00000000..8b864c86
--- /dev/null
+++ b/noao/digiphot/daophot/nstar/dpnstarfit.x
@@ -0,0 +1,1383 @@
+include <mach.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/nstardef.h"
+
+
+# DP_NSTARFIT -- Fit the stellar group.
+
+int procedure dp_nstarfit (dao, im, nin_group, mean_sky, cdimen, iter,
+ converge)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+int nin_group # original group size
+real mean_sky # the mean sky for the group
+int cdimen # dimensions of the coefficient matrix
+int iter # the current iteration
+bool converge # did the fit converge ?
+
+bool clip, refit
+int i, j, k, xpix, ypix, group_size, nterm, ncols, mindex, ifaint, tifaint
+int ntmin, ixmin, ixmax, iymin, iymax, ifxmin, ifxmax, ifymin, ifymax, flag
+pointer apsel, psffit, nstar, subim, ypixel, pixel
+real fitradsq, cutoff, psfradsq, sepcrit, sepmin, perr, peakerr, sky_value
+real read_noise, mingdata, maxgdata, chigrp, wcrit, xmin, xmax, ymin, ymax
+real datum, sumres, grpwt, xtemp, ytemp, weight, ds, pred_pixval, sigmasq
+real relerr, dswt, faint, tfaint, noise
+
+bool dp_nstmerge(), dp_ntomit(), dp_ntmin(), dp_ncheckc()
+pointer imgs2r()
+real dp_ntskyval(), dp_ntsubtract()
+
+begin
+ # Define the daophot pointers.
+ psffit = DP_PSFFIT (dao)
+ apsel = DP_APSEL(dao)
+ nstar = DP_NSTAR (dao)
+
+ # Set up some daophot constants. At some point these will be computed
+ # when the NSTAR task is started up instead of at the beginning of
+ # each group fit. For the moment it is convenient and not too
+ # costly to compute them here. Also initialize the fit.
+
+ if (iter == 1) {
+
+ # Compute the fitting and psf radii.
+ fitradsq = DP_FITRAD (dao) ** 2
+ psfradsq = DP_PSFRAD(dao) ** 2
+ cutoff = CUT_FACTOR * fitradsq
+
+ # Compute the merging parameters.
+ if (IS_INDEFR(DP_MERGERAD(dao))) {
+ sepcrit = 2.0 * (Memr[DP_PSFPARS(psffit)] ** 2 +
+ Memr[DP_PSFPARS(psffit)+1] ** 2)
+ sepmin = min (1.0, FRACTION_MINSEP * sepcrit)
+ } else {
+ sepcrit = DP_MERGERAD(dao) ** 2
+ sepmin = min (1.0, FRACTION_MINSEP * sepcrit)
+ }
+
+ # Compute the noise parameters.
+ read_noise = (DP_READNOISE(dao) / DP_PHOTADU(dao)) ** 2
+ perr = 0.01 * DP_FLATERR(dao)
+ peakerr = 0.01 * DP_PROFERR(dao) / (Memr[DP_PSFPARS(psffit)] *
+ Memr[DP_PSFPARS(psffit)+1])
+
+ # Compute the minimum and maximum good pixel values.
+ if (IS_INDEFR(DP_MINGDATA(dao)))
+ mingdata = -MAX_REAL
+ else
+ mingdata = DP_MINGDATA(dao)
+ if (IS_INDEFR(DP_MAXGDATA(dao)))
+ maxgdata = MAX_REAL
+ else
+ maxgdata = DP_MAXGDATA(dao)
+
+ # Initialize the fit.
+ chigrp = 1.0
+ clip = false
+ if (DP_RECENTER(dao) == YES) {
+ nterm = 3 * nin_group
+ ntmin = 3
+ } else {
+ nterm = nin_group
+ ntmin = 1
+ }
+ if (DP_FITSKY(dao) == YES) {
+ nterm = nterm + 1
+ ntmin = ntmin + 1
+ }
+ call aclrr (Memr[DP_NXOLD(nstar)], nterm)
+ call amovkr (1.0, Memr[DP_NXCLAMP(nstar)], nterm)
+ }
+
+ # Start a new iteration.
+ group_size = nin_group
+ if (DP_RECENTER(dao) == YES)
+ nterm = 3 * group_size
+ else
+ nterm = group_size
+ if (DP_FITSKY(dao) == YES)
+ nterm = nterm + 1
+
+ # Begin fitting the current group of stars.
+ repeat {
+
+ # Initialize the convergence criteria.
+ converge = false
+
+ # Check that there is at least 1 star in the group.
+ if (group_size < 1)
+ return (group_size)
+
+ # Set up the critical error for star rejection.
+ if (iter >= NITER_MAX)
+ wcrit = WCRIT_MAX
+ else if (iter >= NITER_MED)
+ wcrit = WCRIT_MED
+ else if (iter >= NITER_MIN)
+ wcrit = WCRIT_MIN
+ else
+ wcrit = MAX_REAL
+
+ # Set the sky fitting derivative.
+ if (DP_FITSKY(dao) == YES)
+ Memr[DP_NX(nstar)+nterm-1] = -1.0
+
+ # Initialize arrays.
+ call aclrr (Memr[DP_APCHI(apsel)], group_size)
+ call aclrr (Memr[DP_NSUMWT(nstar)], group_size)
+ call aclrr (Memr[DP_NNUMER(nstar)], group_size)
+ call aclrr (Memr[DP_NDENOM(nstar)], group_size)
+ call amovki (NSTERR_OK, Memi[DP_NIER(nstar)], group_size)
+
+ # Compute the minimum and maximum x and y values.
+ call alimr (Memr[DP_APXCEN(apsel)], group_size, xmin, xmax)
+ call alimr (Memr[DP_APYCEN(apsel)], group_size, ymin, ymax)
+
+ # Check to see whether any two stars are within the critical
+ # difference from each other.
+
+ if ((group_size > 1) && dp_nstmerge (Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMAG(apsel)],
+ Memr[DP_APERR(apsel)], group_size, sepcrit, sepmin, wcrit,
+ i, j, k)) {
+
+ # Compute the new centroid and brightness.
+ call dp_nstcen (Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[DP_APMAG(apsel)], i, j, k)
+
+ # Print out verbose comments.
+ if (DP_VERBOSE (dao) == YES) {
+ call printf ("\tStar %-5d has merged with star %-5d\n")
+ call pargi (Memi[DP_APID(apsel)+k-1])
+ call pargi (Memi[DP_APID(apsel)+i-1])
+ }
+
+ # Recompute the mean sky.
+ if ((DP_FITSKY(dao) == NO) && (DP_GROUPSKY(dao) == YES))
+ mean_sky = (mean_sky * group_size -
+ Memr[DP_APMSKY(apsel)+k-1]) / (group_size - 1)
+
+ # Now remove the k-th star from the group.
+ call dp_remove (k, group_size, Memi[DP_APID(apsel)],
+ Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[DP_APMAG(apsel)], Memr[DP_APMSKY(apsel)],
+ Memi[DP_NIER(nstar)], NSTERR_MERGE)
+
+ # After deleting a star, resize the matrix, release all of
+ # the clamps and back up the iteration counter.
+
+ if (DP_RECENTER(dao) == YES)
+ nterm = 3 * group_size
+ else
+ nterm = group_size
+ if (DP_FITSKY(dao) == YES)
+ nterm = nterm + 1
+ clip = false
+ call aclrr (Memr[DP_NXOLD(nstar)], nterm)
+ call amovkr (1.0, Memr[DP_NXCLAMP(nstar)], nterm)
+ iter = max (1, iter - 1)
+ next
+ }
+
+ # Now we can proceed with the iteration. If this is the first
+ # iteration read in the subraster. Determine the size of the
+ # subraster we need to extract from the image for this group.
+
+ if (iter == 1) {
+ ixmin = max (1, int (xmin - DP_PSFRAD(dao) -
+ DP_FITRAD(dao)) + 1)
+ iymin = max (1, int (ymin - DP_PSFRAD(dao) -
+ DP_FITRAD(dao)) + 1)
+ ixmax = min (IM_LEN(im,1), int (xmax + DP_PSFRAD(dao) +
+ DP_FITRAD(dao)))
+ iymax = min (IM_LEN(im,2), int (ymax + DP_PSFRAD(dao) +
+ DP_FITRAD(dao)))
+ subim = imgs2r (im, ixmin, ixmax, iymin, iymax)
+ ncols = ixmax - ixmin + 1
+ }
+
+ # Compute the area on the subraster that is off interest to
+ # the current iteration.
+
+ ifxmin = max (ixmin, int (xmin - DP_FITRAD(dao)) + 1)
+ ifymin = max (iymin, int (ymin - DP_FITRAD(dao)) + 1)
+ ifxmax = min (ixmax, int (xmax + DP_FITRAD(dao)))
+ ifymax = min (iymax, int (ymax + DP_FITRAD(dao)))
+
+ # Zero the normal matrix and the vector of residuals.
+
+ call aclrr (Memr[DP_NV(nstar)], nterm)
+ call aclrr (Memr[DP_NC(nstar)], cdimen * cdimen)
+ call aclri (Memi[DP_NNPIX(nstar)], group_size)
+
+ sumres = 0.0
+ grpwt = 0.0
+
+ # Loop over the pixels in the subraster.
+
+ ypixel = subim + (ifymin - iymin) * ncols + ifxmin - ixmin - 1
+ do ypix = ifymin, ifymax {
+
+ ytemp = ypix
+ pixel = ypixel
+
+ do xpix = ifxmin, ifxmax {
+
+ xtemp = xpix
+ pixel = pixel + 1
+ datum = Memr[pixel]
+
+ # Reject pixel if not in good data range.
+ if ((datum < mingdata) || (datum > maxgdata))
+ next
+
+ # If this pixel is within one fitting radius of at
+ # least one star then include it in the solution.
+ # While figuring this out, compute the squared distance
+ # of this pixel from the centroid of each star in the
+ # group, and sum its contribution to the number
+ # of pixels within one fitting radius of each star.
+
+ if (dp_ntomit (Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_NRPIXSQ(nstar)],
+ Memi[DP_NSKIP(nstar)], group_size, xtemp, ytemp,
+ cutoff))
+ next
+
+ if ((DP_FITSKY(dao) == NO) && (DP_GROUPSKY(dao) == NO)) {
+ sky_value = dp_ntskyval (Memr[DP_APMSKY(apsel)],
+ Memi[DP_NSKIP(nstar)], group_size)
+ if (IS_INDEFR(sky_value))
+ sky_value = mean_sky
+ } else
+ sky_value = mean_sky
+
+ # Subtract the mean sky from the pixel.
+ #ds = datum - mean_sky
+ ds = datum - sky_value
+
+ # Now loop over the stars and subtract from this pixel
+ # the light contribution from each star within one psf
+ # radius.
+ #
+ # The condition equation for pixel[xpix,ypix] is
+ #
+ # residual = data[xpix,ypix] - sky - sum (scale *
+ # psf[xpix-xc,ypix-yc])
+ #
+ # The scale, xc, and yc are iterated until
+ #
+ # sum (weight * residual ** 2)
+ #
+ # is minimized. Weight will be a function of 1) the
+ # distance of the pixel from the center of the nearest
+ # star, 2) the model-predicted brightness of the pixel
+ # (taking into consideration the readout noise, the
+ # photons/ADU, and the interpolating error of the PSF,
+ # and, 3) the size of the residual itself. One is
+ # necessary to prevent the non-linear least squares
+ # solution from oscillating: oftimes it will come
+ # to pass that if you include a pixel in the solution
+ # then the predicted shift of the centroid will cause
+ # that pixel to be excluded in the next iteration, and the
+ # new predicted shift of the centroid will cause that
+ # pixel to be included again. This could go on ad
+ # infinitum. The cure is to have the weight of the pixel
+ # go asymptotically to zero as its distance from the
+ # stellar centroid approaches the fitting radius. In
+ # the case like that just described, the solution can
+ # then find a real minimum of the sum of the weighted
+ # squared residuals with that pixel at some low-weight
+ # position just inside the fitting radius. Two is
+ # just sensible weighting. Three is a crude attempt
+ # at making the solution more robust against bad pixels.
+
+ weight = dp_ntsubtract (dao, im, Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_NRPIXSQ(nstar)],
+ Memr[DP_APMAG(apsel)], Memi[DP_NSKIP(nstar)],
+ Memr[DP_NX(nstar)], group_size, xtemp, ytemp, ds,
+ psfradsq, fitradsq, DP_RECENTER(dao))
+
+ # At this point the vector X contains the first
+ # derivative of the condition equation, for the pixel
+ # under consideration, with respect to each of the
+ # fitting parameters for all of these stars. We now need
+ # to add these values into the normal matrix and the vector
+ # of residuals.
+
+ # The expected random error in the pixel is the quadratic
+ # sum of the Poisson statistics, plus the readout noise,
+ # plus an estimated error of 0.75% of the total brightness
+ # of the total brightness for the difficulty of flat-
+ # fielding and bias subtraction, plus an estimated error
+ # of the same fraction of the fourth derivative at the
+ # peak of the profile, to account for the difficulty
+ # of accurately interpolating within the point-spread
+ # function. The fourth derivative of the PSF is
+ # proportional to H / sigma ** 4 (sigma is the Gaussian
+ # width parameter for the stellar core); using the geometric
+ # mean of sigma(x) and sigma(y), this becomes H / [sigma(x)
+ # * sigma(y)] ** 2. The ratio of the fitting error to this
+ # quantity is estimated to be approximately 0.027 from a
+ # good-seeing CTIO frame. (This is probably a function of
+ # seeing, sampling etc.)
+
+ # Get the residual from the PSF fit and the pixel
+ # intensity as predicted by the fit. Pred_pixval = raw data
+ # minus residual = model predicted value of the intensity at
+ # this point.
+
+ pred_pixval = max (0.0, datum - ds)
+ if ((pred_pixval > maxgdata) && (iter >= 4))
+ next
+
+ #sigmasq = pred_pixval / DP_PHOTADU (dao) + read_noise +
+ #(perr * pred_pixval) ** 2 + (peakerr *
+ #(pred_pixval - mean_sky)) ** 2
+ sigmasq = pred_pixval / DP_PHOTADU (dao) + read_noise +
+ (perr * pred_pixval) ** 2 + (peakerr *
+ (pred_pixval - sky_value)) ** 2
+ if (sigmasq <= 0.0)
+ next
+ relerr = abs (ds) / sqrt (sigmasq)
+
+ # Add this residual into the weighted sum of the
+ # absolute relative residuals.
+
+ sumres = sumres + relerr * weight
+ grpwt = grpwt + weight
+
+ # Add into the accumulating sums of the weighted
+ # absolute relative residuals and of the image sharpness
+ # parameter for each of the stars. Include in the
+ # sharpness index only those pixels within NCORE_SIGMA
+ # sigma of the centroid of the object. This saves time
+ # and floating underflows by excluding pixels
+ # which contribute less than about one part in a
+ # million to the index.
+
+ call dp_acsharp (Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memi[DP_NSKIP(nstar)],
+ Memi[DP_NNPIX(nstar)], Memr[DP_NNUMER(nstar)],
+ Memr[DP_NDENOM(nstar)], Memr[DP_NSUMWT(nstar)],
+ Memr[DP_APCHI(apsel)], group_size, xtemp, ytemp,
+ Memr[DP_PSFPARS(psffit)], Memr[DP_PSFPARS(psffit)+1],
+ ds, sigmasq, relerr, weight)
+
+ # If clipping is in effect, reduce the weight of a bad
+ # pixel. A pixel having a residual of 2.5 sigma gets
+ # reduced to half weight and one with a rersidual of 5
+ # sigma gets weight of 1 / 257.
+
+ weight = weight / sigmasq
+ if (clip)
+ weight = weight / (1.0 + (relerr / (DP_CLIPRANGE(dao) *
+ chigrp)) ** DP_CLIPEXP(dao))
+ dswt = ds * weight
+
+ # Work this pixel into the normal matrix.
+ call dp_mataccum (Memr[DP_NX(nstar)], Memi[DP_NSKIP(nstar)],
+ group_size, Memr[DP_NC(nstar)], Memr[DP_NV(nstar)],
+ cdimen, nterm, weight, dswt, DP_RECENTER(dao),
+ DP_FITSKY(dao))
+
+ }
+
+ ypixel = ypixel + ncols
+ }
+
+ # Make sure that every star in the group has at least MIN_FIT_PIXEL
+ # pixels within one fitting radius.
+
+ refit = dp_ntmin (Memi[DP_APID(apsel)], Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMAG(apsel)],
+ Memr[DP_APMSKY(apsel)], Memi[DP_NNPIX(nstar)],
+ Memi[DP_NIER(nstar)], group_size, nterm, DP_RECENTER(dao),
+ DP_FITSKY(dao), DP_GROUPSKY(dao), mean_sky, DP_VERBOSE(dao))
+ if (group_size < 1)
+ return (group_size)
+ if (refit)
+ next
+
+ # Reflect the normal matrix across the diagonal.
+ call dp_mreflect (Memr[DP_NC(nstar)], cdimen, nterm)
+
+ # Compute the robust estimate of the standard deviation of the
+ # residuals for the group as a whole, and for each star. This
+ # estimate is sqrt (PI/2) * weighted mean absolute relative
+ # residual. Do you like that "absolute relative" stuff? (PBS)
+ # NO! (LED)
+ #
+ # CHI = CHI_NORM * SUM (weight * resid) / (# of pixels)
+ #
+ # This gets corrected for bias by being multiplied by
+ #
+ # SQRT (# of pixels) / (# of pixels - 3)
+
+ # Then the value is driven towards unity, depending on
+ # exactly how many pixels were involved: if CHIOLD is based
+ # on a total weight of 3, then it is extremely poorly determined
+ # and we just want to keep CHIOLD = 1. The larger GRPWT is, the
+ # better determined CHIOLD is, and the less we want to force it
+ # toward unity. So, just take the weighted average of CHIOLD and
+ # unity, with weights GRPWT - 3 and 1, respectively.
+
+ if (grpwt > ntmin) {
+ chigrp = CHI_NORM * sumres * sqrt (1.0 / (grpwt * (grpwt -
+ ntmin)))
+ chigrp = ((grpwt - ntmin) * chigrp + ntmin) / grpwt
+ }
+
+ # CHIOLD has been pulled toward its expected value of unity to
+ # keep the statistics of a small number of pixels from completely
+ # dominating the error analysis. Similarly, the photometric
+ # errors for the individual stars will be pulled toward unity
+ # now. Later on, if the number of stars in the group is
+ # greated than one, CHI will be nudged toward the group average.
+ # In order to work optimally, of course, this requires that
+ # the # of photons / ADU, the READNOISE and the other noise
+ # contributors are properly specified.
+
+ call dp_ntchi (Memr[DP_NSUMWT(nstar)], Memr[DP_APCHI(apsel)],
+ group_size, ntmin, chigrp, grpwt)
+
+ # Invert the matrix.
+ call invers (Memr[DP_NC(nstar)], cdimen, nterm, flag)
+
+ # Check for a singular matrix.
+ refit = dp_ncheckc (Memr[DP_NC(nstar)], cdimen, nterm,
+ Memi[DP_APID(apsel)], Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMAG(apsel)],
+ Memr[DP_APMSKY(apsel)], Memi[DP_NIER(nstar)], group_size,
+ DP_RECENTER(dao), DP_FITSKY(dao), DP_GROUPSKY(dao), mean_sky,
+ DP_VERBOSE(dao))
+ if (group_size < 1)
+ return (group_size)
+ if (refit)
+ next
+
+ # Solve for position and scale factor increments.
+ call mvmul (Memr[DP_NC(nstar)], cdimen, nterm, Memr[DP_NV(nstar)],
+ Memr[DP_NX(nstar)])
+
+ if (iter <= 1)
+ refit = true
+ else
+ refit = false
+
+ # Fit the sky.
+ if (DP_FITSKY(dao) == YES) {
+ noise = sqrt (abs (mean_sky / DP_PHOTADU(dao)) + read_noise)
+ mean_sky = mean_sky - max (-3.0 * noise,
+ min (Memr[DP_NX(nstar)+nterm-1], 3.0 * noise))
+ if (abs (Memr[DP_NX(nstar)+nterm-1]) > (1.0e-4 * mean_sky))
+ refit = true
+ }
+
+ # In the beginning, the brightness of each star will be permitted
+ # to change by no more than 2 magnitudes per iteration, and the x,y
+ # coordinates of each centroid will be permitted to change by
+ # no more than 0.4 pixels per iteration. Any time that the
+ # parameter correction changes sign from one iteration to the
+ # next, the maximum permissible change will be reduced by a factor
+ # of two. These clamps are released any time a star disappears.
+
+ call dp_ntclamp (Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[DP_APMAG(apsel)], Memr[DP_APERR(apsel)],
+ Memr[DP_NSUMWT(nstar)], group_size, Memr[DP_NC(nstar)], cdimen,
+ Memr[DP_NX(nstar)], Memr[DP_NXOLD(nstar)],
+ Memr[DP_NXCLAMP(nstar)], DP_RECENTER(dao), clip, refit)
+
+ # Check whether the estimated centroid of the any star has
+ # moved so far out of the limits of the picture that it has fewer
+ # than 4 or 5 pixels within one fitting radius.
+
+ call dp_ntcentroid (Memi[DP_APID(apsel)], Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMAG(apsel)],
+ Memr[DP_APMSKY(apsel)], Memi[DP_NIER(nstar)], group_size,
+ ixmin, ixmax, iymin, iymax, fitradsq, DP_FITSKY(dao),
+ DP_GROUPSKY(dao), mean_sky, refit, DP_VERBOSE(dao))
+
+ if (group_size < 1)
+ return (group_size)
+
+ # Update matrix dimensions.
+ if (DP_RECENTER(dao) == YES)
+ nterm = 3 * group_size
+ else
+ nterm = group_size
+ if (DP_FITSKY(dao) == YES)
+ nterm = nterm + 1
+
+ # Now check whether any of the stars is too faint (more than 12.5
+ # magnitudes fainter than the PSF star). If several stars are too
+ # faint, delete the faintest one, and set the brightness of the
+ # other faint ones to 12.5 magnitudes below the PSF star. That way
+ # on the next iteration we will see whether these stars want to
+ # grow or to disappear.
+
+ faint = 0.0
+ ifaint = 0
+ call dp_ntfmag (Memr[DP_APMAG(apsel)], group_size, tfaint, tifaint)
+
+ # If at least one star is more than 12.5 magnitudes fainter
+ # than the PSF then ifaint is the relative index of the faintest
+ # of them, and faint is the relative brightness of the
+ # faintest of them.
+
+ # No very faint star was detected.
+ if (tifaint <= 0) {
+
+ # If the solution has not converged and if the number of
+ # iterations is less than MIN_ITER, perform another iteration
+ # with no questions asked.
+
+ if ((refit) && (iter < MIN_ITER))
+ return (group_size)
+
+ # If the solution doesn't think it has converged, after the
+ # fourth iteration delete the least certain star if it is less
+ # less than a one-sigma detection; after the eighth iteration
+ # delete the least certain star if it is less than a 1.5 sigma
+ # detection; after the twelfth iteration OR if the solution
+ # thinks it has converged, delete the least certain star if it
+ # is less than a two-sigma detection.
+
+ call dp_fsnoise (Memr[DP_APMAG(apsel)], Memr[DP_APERR(apsel)],
+ group_size, faint, ifaint)
+
+ if ((refit) && (iter < DP_MAXITER (dao)) && (faint < wcrit))
+ return (group_size)
+ }
+
+ # Reject the appropriate star.
+ if ((tifaint > 0) || (faint >= MIN_FAINT)) {
+
+ # Either (a) the solution thinks it has not converged
+ # and the faintest star is more uncertain than sqrt(wcrit)
+ # or (b) the solution thinks it has converged and the
+ # faintest star is more uncertain than two-sigma.
+
+ if (DP_VERBOSE (dao) == YES) {
+ mindex = max (tifaint, ifaint)
+ call printf (
+ "\tStar %-5d has been deleted because it is too faint\n")
+ call pargi (Memi[DP_APID(apsel)+mindex-1])
+ }
+
+ if ((DP_FITSKY(dao) == NO) && (DP_GROUPSKY(dao) == YES) &&
+ (group_size > 1))
+ mean_sky = (mean_sky * group_size -
+ Memr[DP_APMSKY(apsel)+max(tifaint,ifaint)-1]) /
+ (group_size - 1)
+
+ call dp_remove (max (tifaint, ifaint), group_size,
+ Memi[DP_APID(apsel)], Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMAG(apsel)],
+ Memr[DP_APMSKY(apsel)], Memi[DP_NIER(nstar)],
+ NSTERR_FAINT)
+
+ if (group_size < 1)
+ return (group_size)
+
+ if (DP_RECENTER(dao) == YES)
+ nterm = 3 * group_size
+ else
+ nterm = group_size
+ if (DP_FITSKY(dao) == YES)
+ nterm = nterm + 1
+ call aclrr (Memr[DP_NXOLD(nstar)], nterm)
+ call amovkr (1.0, Memr[DP_NXCLAMP(nstar)], nterm)
+ clip = false
+ iter = max (1, iter - 1)
+ next
+ }
+
+ # Solution has either converged or gone to the maximum number
+ # of iterations.
+
+ if ((iter < DP_MAXITER(dao)) && (! clip)) {
+
+ # The first convergence milestone has been reached. Turn on the
+ # clipper, loosen the clamps and keep on going.
+
+ if (DP_CLIPEXP(dao) > 0)
+ clip = true
+ converge = false
+ call aclrr (Memr[DP_NXOLD(nstar)], nterm)
+ call amaxkr (Memr[DP_NXCLAMP(nstar)], 0.25,
+ Memr[DP_NXCLAMP(nstar)], nterm)
+ return (group_size)
+ }
+
+ converge = true
+
+ } until (converge)
+
+ return (group_size)
+end
+
+
+# DP_NSTMERGE -- Decide whether two stars in a group should merge.
+
+bool procedure dp_nstmerge (xcen, ycen, mag, magerr, group_size, sepcrit,
+ sepmin, wcrit, i, j, k)
+
+real xcen[ARB] # array of x centers
+real ycen[ARB] # array of y centers
+real mag[ARB] # array of magnitudes
+real magerr[ARB] # array of magnitude errors
+int group_size # group size
+real sepcrit # the critical separation squared
+real sepmin # the minimum separation
+real wcrit # critical error for rejection
+int i, j, k # output indices
+
+real separation
+
+begin
+ do i = 1, group_size {
+ do j = 1, i - 1 {
+
+ # Compute the separation.
+ separation = (xcen[j] - xcen[i]) ** 2 +
+ (ycen[j] - ycen[i]) ** 2
+ if (separation > sepcrit)
+ next
+
+ # Find the fainter of the two stars.
+ k = j
+ if (mag[i] < mag[j])
+ k = i
+ if ((separation < sepmin) || ((magerr[k] / mag[k]) > wcrit))
+ return (true)
+ }
+ }
+
+ return (false)
+end
+
+
+# DP_NSTCEN -- Recompute the centroid and brightness of the i-th star.
+
+procedure dp_nstcen (xcen, ycen, mag, i, j, k)
+
+real xcen[ARB] # the x centers
+real ycen[ARB] # the y centers
+real mag[ARB] # the magnitudes
+int i, j, k # array indices
+
+begin
+ # Now eliminate the fainter of the two stars. The k-th
+ # star is now the fainter of the two, the i-th the
+ # brighter.
+
+ if (mag[i] < mag[j])
+ i = j
+
+ # Now replace the centroid of the i-th star with the
+ # weighted mean of the most recent estimates of the
+ # centroids of the i-th and the k-th stars, and the
+ # brightness of i-th with the sum of the brightnesses.
+
+ xcen[i] = xcen[i] * mag[i] + xcen[k] * mag[k]
+ ycen[i] = ycen[i] * mag[i] + ycen[k] * mag[k]
+ mag[i] = mag[i] + mag[k]
+ xcen[i] = xcen[i] / mag[i]
+ ycen[i] = ycen[i] / mag[i]
+end
+
+
+# DP_NTOMIT -- Check whether a pixel is within one fitting radius of another
+# star.
+
+bool procedure dp_ntomit (xcen, ycen, rpixsq, skip, group_size, fx, fy, cutoff)
+
+real xcen[ARB] # array of x centers
+real ycen[ARB] # array of y centers
+real rpixsq[ARB] # array of distances squared
+int skip[ARB] # array of skip values
+int group_size # the group size
+real fx, fy # pixel position in image
+real cutoff # radius cuttoff for pixel inclusion
+
+bool omit
+int i
+
+begin
+ omit = true
+ do i = 1, group_size {
+ skip[i] = YES
+ rpixsq[i] = (fx - xcen[i]) ** 2 + (fy - ycen[i]) ** 2
+ if (rpixsq[i] > cutoff)
+ next
+ skip[i] = NO
+ omit = false
+ }
+
+ return (omit)
+end
+
+
+# DP_NTSKYVAL -- Compute the average sky value to use for a particular
+# pixel by averaging the sky values of all stars for which the
+# pixel is within one fitting radius.
+
+real procedure dp_ntskyval (sky, skip, nstar)
+
+real sky[ARB] # array of sky values
+int skip[ARB] # array of skip values
+int nstar # the number of stars
+
+int i, npts
+real sum
+
+begin
+ sum = 0.0
+ npts = 0
+ do i = 1, nstar {
+ if (skip[i] == YES)
+ next
+ sum = sum + sky[i]
+ npts = npts + 1
+ }
+ if (npts <= 0)
+ return (INDEFR)
+ else
+ return (sum / npts)
+end
+
+
+# DP_NTSUBTRACT -- Procedure to subtract the contribution of a particular
+# pixel from a particular star.
+
+real procedure dp_ntsubtract (dao, im, xcen, ycen, rpixsq, mag, skip, x,
+ group_size, fx, fy, ds, psfradsq, fitradsq, recenter)
+
+pointer dao # pointer to the daophot structure
+pointer im # the input image descriptor
+real xcen[ARB] # array of x centers
+real ycen[ARB] # array of y centers
+real rpixsq[ARB] # array of distances squared
+real mag[ARB] # array of magnitudes
+int skip[ARB] # array of skip values
+real x[ARB] # x accumulation vector array
+int group_size # size of the group
+real fx, fy # center of pixel in image
+real ds # pixel value
+real psfradsq # psf radius squared
+real fitradsq # fit radius squared
+int recenter # recenter the coordinates
+
+int i, i3, k
+pointer psffit
+real weight, dx, dy, deltax, deltay, val, dvdx, dvdy, rsq
+real dp_usepsf()
+
+begin
+ psffit = DP_PSFFIT(dao)
+
+ weight = 0.0
+ do i = 1, group_size {
+ if (rpixsq[i] >= psfradsq)
+ next
+ dx = fx - xcen[i]
+ dy = fy - ycen[i]
+ call dp_wpsf (dao, im, xcen[i], ycen[i], deltax, deltay, 1)
+ deltax = (deltax - 1.0) / DP_PSFX(psffit) - 1.0
+ deltay = (deltay - 1.0) / DP_PSFY(psffit) - 1.0
+ val = dp_usepsf (DP_PSFUNCTION(psffit), dx, dy,
+ DP_PSFHEIGHT(psffit), Memr[DP_PSFPARS(psffit)],
+ Memr[DP_PSFLUT(psffit)], DP_PSFSIZE(psffit),
+ DP_NVLTABLE(psffit), DP_NFEXTABLE(psffit), deltax, deltay,
+ dvdx, dvdy)
+ ds = ds - mag[i] * val
+ if (skip[i] == YES)
+ next
+ rsq = rpixsq[i] / fitradsq
+ weight = max (weight, 5.0 / (5.0 + rsq / (1.0 - rsq)))
+ if (recenter == YES) {
+ i3 = 3 * i
+ k = i3 - 2
+ x[k] = -val
+ k = i3 - 1
+ x[k] = -mag[i] * dvdx
+ x[i3] = -mag[i] * dvdy
+ } else
+ x[i] = -val
+ }
+
+ return (weight)
+end
+
+
+# DP_ACSHARP -- Procedure to accumulate sums of the weighted absolute
+# relative residuals and the image sharpness parameter for each of the
+# stars.
+
+procedure dp_acsharp (xcen, ycen, skip, npix, numer, denom, sumwt, chi,
+ group_size, fx, fy, fwhmx, fwhmy, ds, sigmasq, relerr, weight)
+
+real xcen[ARB] # array of object x centers
+real ycen[ARB] # array of object y centers
+int skip[ARB] # array of skip values
+int npix[ARB] # array of numbers of pixels
+real numer[ARB] # numerator array
+real denom[ARB] # denominator array
+real sumwt[ARB] # array of summed weights
+real chi[ARB] # array of chis
+int group_size # group size paramter.
+real fx, fy # position of data in image
+real fwhmx, fwhmy # gaussian core widths in x and y
+real ds # the data residual
+real sigmasq # the sigma squared
+real relerr # the relative error
+real weight # the weight
+
+int i
+real rhosq, dfdsig
+
+begin
+ do i = 1, group_size {
+
+ if (skip[i] == YES)
+ next
+
+ # Accumulate the number of pixels, chi and sum of the weights.
+ npix[i] = npix[i] + 1
+ chi[i] = chi[i] + relerr * weight
+ sumwt[i] = sumwt[i] + weight
+
+ # Include in the sharpness index only those pixels
+ # within NCORE_SIGMASQ of the centroid of the
+ # object. (This saves time and floating underflows
+ # by excluding pixels which contribute very little
+ # to the index.
+
+ rhosq = ((xcen[i] - fx) / fwhmx) ** 2 + ((ycen[i] - fy) /
+ fwhmy) ** 2
+ if (rhosq > NCORE_SIGMASQ)
+ next
+ rhosq = 0.6931472 * rhosq
+ dfdsig = exp (-rhosq) * (rhosq - 1.0)
+ numer[i] = numer[i] + dfdsig * ds / sigmasq
+ denom[i] = denom[i] + (dfdsig ** 2) / sigmasq
+ }
+end
+
+
+# DP_MATACCUM -- Procedure to accumulate the data into the matrices.
+
+procedure dp_mataccum (x, skip, group_size, c, v, cdimen, nterm, weight, dswt,
+ recenter, fitsky)
+
+real x[ARB] # x array
+int skip[ARB] # skip vector
+int group_size # size of the group
+real c[cdimen,ARB] # coefficient matrix
+real v[ARB] # vector array
+int cdimen # dimensions of the coefficient matrix
+int nterm # the number of terms
+real weight # weight
+real dswt # data weight
+int recenter # recenter the coordinates
+int fitsky # fit the sky value
+
+int i, i3, i3m2, k, j, l
+
+begin
+ if (fitsky == YES) {
+ c[nterm,nterm] = c[nterm,nterm] + weight
+ v[nterm] = v[nterm] - dswt
+ }
+
+ do i = 1, group_size {
+ if (skip[i] == YES)
+ next
+ if (recenter == YES) {
+ i3 = i * 3
+ i3m2 = i3 - 2
+ do k = i3m2, i3 {
+ if (fitsky == YES)
+ c[nterm,k] = c[nterm,k] - x[k] * weight
+ v[k] = v[k] + x[k] * dswt
+ }
+ do j = 1, i {
+ if (skip[j] == YES)
+ next
+ do k = i3m2, i3 {
+ do l = 3 * j - 2, min (k, 3 * j)
+ c[k,l] = c[k,l] + x[k] * x[l] * weight
+ }
+ }
+ } else {
+ v[i] = v[i] + x[i] * dswt
+ if (fitsky == YES)
+ c[nterm,i] = c[nterm,i] - x[i] * weight
+ do j = 1, i {
+ if (skip[j] == YES)
+ next
+ c[i,j] = c[i,j] + x[i] * x[j] * weight
+ }
+ }
+ }
+end
+
+
+# DP_NTMIN -- Make sure that every star in the group has at least
+# MIN_NPIX pixels within one fitting radius.
+
+bool procedure dp_ntmin (ids, xcen, ycen, mag, sky, npix, nier, group_size,
+ nterm, recenter, fitsky, groupsky, mean_sky, verbose)
+
+int ids[ARB] # array of ids
+real xcen[ARB] # array of x centers
+real ycen[ARB] # array of y centers
+real mag[ARB] # array of magnitudes
+real sky[ARB] # array of sky values
+int npix[ARB] # array of pixel numbers
+int nier[ARB] # array of error codes
+int group_size # size of the group
+int nterm # number of terms
+int recenter # recenter the objects
+int fitsky # fit the sky value
+int groupsky # use group sky value
+real mean_sky # the current mean sky value
+int verbose # verbose flag
+
+bool redo
+int i
+
+begin
+ redo = false
+ do i = 1, group_size {
+ if (npix[i] >= MIN_NPIX)
+ next
+ redo = true
+ if (verbose == YES) {
+ call printf (
+ "\tStar %-5d has been deleted: too few good pixels\n")
+ call pargi (ids[i])
+ }
+ if ((fitsky == NO) && (groupsky == YES) && (group_size > 1))
+ mean_sky = (mean_sky * group_size - sky[i]) / (group_size - 1)
+ call dp_remove (i, group_size, ids, xcen, ycen, mag, sky,
+ nier, NSTERR_NOPIX)
+ if (group_size <= 0)
+ return (redo)
+ if (recenter == YES)
+ nterm = 3 * group_size
+ else
+ nterm = group_size
+ if (fitsky == YES)
+ nterm = nterm + 1
+ }
+
+ return (redo)
+end
+
+
+# DP_MREFLECT -- Reflect the normal matrix around the diagonal.
+
+procedure dp_mreflect (c, cdimen, nterm)
+
+real c[cdimen,ARB] # coefficient matrix
+int cdimen # dimension of the c matrix
+int nterm # number of terms
+
+int l, k
+
+begin
+ # Reflect the normal matrix across the diagonal.
+ do l = 2, nterm {
+ do k = 1, l - 1
+ c[k,l] = c[l,k]
+ }
+end
+
+
+# DP_NTCHI -- Compute the chi value for each star.
+
+procedure dp_ntchi (sumwt, chi, group_size, ntmin, chigrp, grpwt)
+
+real sumwt[ARB] # sum of the weights
+real chi[ARB] # the chis:wq
+int group_size # size of the group
+int ntmin # minimum number of points
+real chigrp # the group chi
+real grpwt # the group weight
+
+int i
+
+begin
+ do i = 1, group_size {
+ if (sumwt[i] > ntmin) {
+ chi[i] = CHI_NORM * chi[i] / sqrt ((sumwt[i] - ntmin) *
+ sumwt[i])
+ sumwt[i] = ((sumwt[i] - ntmin) * chi[i] + MIN_SUMWT) /
+ sumwt[i]
+ } else {
+ chi[i] = chigrp
+ sumwt[i] = grpwt
+ }
+ }
+end
+
+
+# DP_NCHECKC -- Check the inverted matrix for singularity.
+
+bool procedure dp_ncheckc (c, cdimen, nterm, ids, xcen, ycen, mag, sky,
+ nier, group_size, recenter, fitsky, groupsky, mean_sky, verbose)
+
+real c[cdimen,ARB] # coefficient matrix
+int cdimen # dimension of the c matrix
+int nterm # number of terms
+int ids[ARB] # array of ids
+real xcen[ARB] # array of x centers
+real ycen[ARB] # array of y centers
+real mag[ARB] # array of magnitudes
+real sky[ARB] # array of sky values
+int nier[ARB] # array of error codes
+int group_size # size of the group
+int recenter # recenter the objects
+int fitsky # fit the sky value
+int groupsky # use group sky value
+real mean_sky # the current mean sky value
+int verbose # verbose flag
+
+bool redo
+int j, starno, i
+
+begin
+ redo = false
+ do j = 1, nterm {
+ if (c[j,j] > 0.0)
+ next
+ redo = true
+ if ((j == nterm) && (fitsky == YES))
+ starno = 0
+ else if (recenter == YES)
+ starno = (j + 2) / 3
+ else
+ starno = j
+ if (starno == 0) {
+ if (verbose == YES) {
+ do i = 1, group_size {
+ call printf (
+ "\tStar %-5d has been deleted: singular matrix\n")
+ call pargi (ids[i])
+ }
+ }
+ call amovki (NSTERR_SINGULAR, nier, group_size)
+ group_size = 0
+ } else {
+ if (verbose == YES) {
+ call printf (
+ "\tStar %-5d has been deleted: singular matrix\n")
+ call pargi (ids[starno])
+ }
+ if ((fitsky == NO) && (groupsky == YES) && (group_size > 1))
+ mean_sky = (mean_sky * group_size - sky[starno]) /
+ (group_size - 1)
+ call dp_remove (starno, group_size, ids, xcen, ycen, mag,
+ sky, nier, NSTERR_SINGULAR)
+ }
+ if (group_size <= 0)
+ return (redo)
+ if (recenter == YES)
+ nterm = 3 * group_size
+ else
+ nterm = group_size
+ if (fitsky == YES)
+ nterm = nterm + 1
+ }
+
+ return (redo)
+end
+
+
+# DP_NTCLAMP -- Restrict the amount the solution can vary on each iteration.
+
+procedure dp_ntclamp (xcen, ycen, mag, magerr, sumwt, group_size, c, cdimen,
+ x, xold, clamp, recenter, clip, redo)
+
+real xcen[ARB] # x centers array
+real ycen[ARB] # y centers array
+real mag[ARB] # magnitude array
+real magerr[ARB] # magnitude errors array
+real sumwt[ARB] # array of weight sums
+int group_size # size of the group
+real c[cdimen, ARB] # coefficient matrix
+int cdimen # dimensions of c
+real x[ARB] # x vector
+real xold[ARB] # old x vector
+real clamp[ARB] # clamp on solution matrix
+int recenter # recenter the objects
+bool clip # clip the matrix
+bool redo # redo the solution
+
+int i, l, j, k
+real df
+
+begin
+ do i = 1, group_size {
+
+
+ # If any correction has changed sign since the last
+ # iteration, reduce the maximum permissible change by
+ # a factor of two.
+
+ # Note that the sign of the correction is such that it
+ # must be SUBTRACTED from the current value of the
+ # parameter to get the improved parameter value. This being
+ # the case, if the correction to the brightness is
+ # negative (the least-squares thinks that the star should
+ # be brighter) a change of 1 magnitude is a change of a
+ # factor of 2.5; if the brightness correction is positive
+ # (the star should be fainter) a change of 1 magnitude
+ # is a change of 60%.
+
+ if (recenter == YES) {
+
+ l = 3 * i
+ k = l - 1
+ j = l - 2
+
+ if ((xold[j] * x[j]) < 0.0)
+ clamp[j] = 0.5 * clamp[j]
+ mag[i] = mag[i] - x[j] / (1.0 + max (x[j] /
+ (MAX_DELTA_FAINTER * mag[i]), -x[j] / (MAX_DELTA_BRIGHTER *
+ mag[i])) / clamp[j])
+ xold[j] = x[j]
+
+ if ((xold[k] * x[k]) < 0.0)
+ clamp[k] = 0.5 * clamp[k]
+ if ((xold[l] * x[l]) < 0.0)
+ clamp[l] = 0.5 * clamp[l]
+ xcen[i] = xcen[i] - x[k] / (1.0 + abs(x[k]) / (clamp[k] *
+ MAX_DELTA_PIX))
+ ycen[i] = ycen[i] - x[l] / (1.0 + abs(x[l]) / (clamp[l] *
+ MAX_DELTA_PIX))
+ xold[k] = x[k]
+ xold[l] = x[l]
+ magerr[i] =sumwt[i] * sqrt (c[j,j])
+
+ } else {
+
+ if ((xold[i] * x[i]) < 0.0)
+ clamp[i] = 0.5 * clamp[i]
+ mag[i] = mag[i] - x[i] / (1.0 + max (x[i] /
+ (MAX_DELTA_FAINTER * mag[i]), -x[i] / (MAX_DELTA_BRIGHTER *
+ mag[i])) / clamp[i])
+ xold[i] = x[i]
+ magerr[i] =sumwt[i] * sqrt (c[i,i])
+ }
+
+
+ # There are two milestones in the convergence process: the fits
+ # proceed normally until each star's magnitude changes by less
+ # than its standard error or MAX_NEW_ERRMAG magnitudes, whichever
+ # is greater, and its x and y centroids change by less than 0.02
+ # pixel. At this point the least squares begins to apply
+ # down-weighting of pixels with large residuals as described
+ # above. The fits then continue until each star's
+ # magnitude changes by less than MAX (MAX_NEW_ERRMAG * std. error,
+ # MAX_NEW_RELBRIGHT2 magnitude), ad its centroids change by
+ # less than 0.002 pixel.
+
+ if (redo)
+ next
+
+ if (clip) {
+ if (abs (x[j]) > max (MAX_NEW_ERRMAG * magerr[i],
+ MAX_NEW_RELBRIGHT2 * mag[i])) {
+ redo = true
+ } else if (recenter == YES) {
+ df = (MAX_NEW_ERRMAG * sumwt[i]) ** 2
+ if (x[k] ** 2 > max (df * c[k,k], MAX_PIXERR2))
+ redo = true
+ else if (x[l] ** 2 > max (df * c[l,l], MAX_PIXERR2))
+ redo = true
+ }
+ } else {
+ if (abs (x[j]) > max (magerr[i], MAX_NEW_RELBRIGHT1 *
+ mag[i])) {
+ redo = true
+ } else if (recenter == YES) {
+ df = sumwt[i] ** 2
+ if (x[k] ** 2 > max (df * c[k,k], MAX_PIXERR1))
+ redo = true
+ else if (x[l] ** 2 > max (df * c[l,l], MAX_PIXERR1))
+ redo = true
+ }
+ }
+ }
+end
+
+
+# DP_NTCENTROID -- Check the new centroids to see if they have moved too
+# far off the edge of the image.
+
+procedure dp_ntcentroid (ids, xcen, ycen, mag, sky, nier, group_size, ixmin,
+ ixmax, iymin, iymax, fitradsq, fitsky, groupsky, mean_sky, redo,
+ verbose)
+
+int ids[ARB] # array of ids
+real xcen[ARB] # array of x centers
+real ycen[ARB] # array of y centers
+real mag[ARB] # array of magnitudes
+real sky[ARB] # array of sky values
+int nier[ARB] # array of error codes
+int group_size # size of the group
+int ixmin,ixmax # subraster x limits
+int iymin,iymax # subraster y limits
+real fitradsq # fit radius squared
+int fitsky # fit the sky value
+int groupsky # use the group sky value
+real mean_sky # the mean sky value
+bool redo # redo fit
+int verbose # verbose mode
+
+int i
+real dx, dy
+
+begin
+ # Check whether the centroid of any star has moved so far outside
+ # the picture that it has fewer than four or five pixels within
+ # one fitting radius.
+
+ do i = 1, group_size {
+
+ # If the centroid of the star is outside the picture in x or
+ # y, then DX or DY is its distance from the center of the edge
+ # pixel; otherwise DX and DY are zero.
+
+ dx = max (ixmin - xcen[i], xcen[i] - ixmax, 0.0)
+ dy = max (iymin - ycen[i], ycen[i] - iymax, 0.0)
+ if ((dx <= MAX_PIX_INCREMENT) && (dy <= MAX_PIX_INCREMENT))
+ next
+ if (((dx + 1.0) ** 2 + (dy + 1.0) ** 2) < fitradsq)
+ next
+
+ # Print a warning message about the star.
+ if (verbose == YES) {
+ call printf (
+ "\tStar %-5d has been deleted: new center too far off image\n")
+ call pargi (i)
+ }
+
+ # Adjust the sky.
+ if ((fitsky == NO) && (groupsky == YES) && (group_size > 1))
+ mean_sky = (mean_sky * group_size - sky[i]) / (group_size - 1)
+
+ # Delete it.
+ call dp_remove (i, group_size, ids, xcen, ycen, mag, sky, nier,
+ NSTERR_OFFIMAGE)
+ if (group_size < 1)
+ break
+ redo = true
+ }
+end
+
+
+# DP_NTFMAG -- Check for faint stars.
+
+procedure dp_ntfmag (mag, group_size, faint, ifaint)
+
+real mag[ARB] # array of magnitudes
+int group_size # size of the group
+real faint # faintest magnitude
+int ifaint # index of faintest magnitude
+
+int i
+
+begin
+ faint = 1.0
+ ifaint = 0
+ do i = 1, group_size {
+ if (mag[i] > MIN_REL_BRIGHT)
+ next
+ if (mag[i] <= faint) {
+ faint = mag[i]
+ ifaint = i
+ }
+ mag[i] = MIN_REL_BRIGHT
+ }
+end
+
+
+# DP_FSNOISE -- Compute the smallest signal to noise ratio.
+
+procedure dp_fsnoise (mag, magerr, group_size, faint, ifaint)
+
+real mag[ARB] # array of magnitudes
+real magerr[ARB] # array of magnitude errors
+int group_size # size of group
+real faint # faint value
+int ifaint # faint index
+
+int i
+real weight
+
+begin
+ faint = 0.0
+ ifaint = 0
+ do i = 1, group_size {
+ weight = magerr[i] / mag[i]
+ if (weight < faint)
+ next
+ faint = weight
+ ifaint = i
+ }
+end
+
+
+# DP_REMOVE -- Remove the i-th star from the list of stars in the current
+# group by moving it to the end of the group.
+
+procedure dp_remove (i, nstar, ids, xcen, ycen, mag, sky, nier, pier)
+
+int i # the star to be removed
+int nstar # the number of stars in the group
+int ids[ARB] # the array of star ids
+real xcen[ARB] # the array of star x positions
+real ycen[ARB] # the array of star y positions
+real mag[ARB] # the array of magnitudes
+real sky[ARB] # the array of sky values.
+int nier[ARB] # array of error codes
+int pier # error code for deleted star
+
+int ihold, phold
+real xhold, yhold, shold, mhold
+
+begin
+ nier[i] = pier
+ if (i != nstar) {
+
+ ihold = ids[i]
+ xhold = xcen[i]
+ yhold = ycen[i]
+ shold = sky[i]
+ mhold = mag[i]
+ phold = nier[i]
+
+ ids[i] = ids[nstar]
+ xcen[i] = xcen[nstar]
+ ycen[i] = ycen[nstar]
+ sky[i] = sky[nstar]
+ mag[i] = mag[nstar]
+ nier[i] = nier[nstar]
+
+ ids[nstar] = ihold
+ xcen[nstar] = xhold
+ ycen[nstar] = yhold
+ sky[nstar] = shold
+ mag[nstar] = mhold
+ nier[nstar] = phold
+ }
+ nstar = nstar - 1
+end
diff --git a/noao/digiphot/daophot/nstar/dpntwrite.x b/noao/digiphot/daophot/nstar/dpntwrite.x
new file mode 100644
index 00000000..248a9f28
--- /dev/null
+++ b/noao/digiphot/daophot/nstar/dpntwrite.x
@@ -0,0 +1,600 @@
+include <tbset.h>
+include <time.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/nstardef.h"
+
+
+# DP_TPNEWNSTAR -- Create a new NSTAR output ST table.
+
+procedure dp_tpnewnstar (dao, nst, colpoint)
+
+pointer dao # pointer to the daophot structure
+pointer nst # pointer to output photometry file
+pointer colpoint[ARB] # array of column pointers
+
+
+int i
+pointer sp, colnames, colunits, colformat, col_dtype, col_len
+
+begin
+ # Allocate space for table definition.
+ call smark (sp)
+ call salloc (colnames, NST_NOUTCOL * (SZ_COLNAME + 1), TY_CHAR)
+ call salloc (colunits, NST_NOUTCOL * (SZ_COLUNITS + 1), TY_CHAR)
+ call salloc (colformat, NST_NOUTCOL * (SZ_COLFMT + 1), TY_CHAR)
+ call salloc (col_dtype, NST_NOUTCOL, TY_INT)
+ call salloc (col_len, NST_NOUTCOL, TY_INT)
+
+ # Set up the column definitions.
+ call strcpy (ID, Memc[colnames], SZ_COLNAME)
+ call strcpy (GROUP, Memc[colnames+SZ_COLNAME+1], SZ_COLNAME)
+ call strcpy (XCENTER, Memc[colnames+2*SZ_COLNAME+2], SZ_COLNAME)
+ call strcpy (YCENTER, Memc[colnames+3*SZ_COLNAME+3], SZ_COLNAME)
+ call strcpy (MAG, Memc[colnames+4*SZ_COLNAME+4], SZ_COLNAME)
+ call strcpy (MAGERR, Memc[colnames+5*SZ_COLNAME+5], SZ_COLNAME)
+ call strcpy (SKY, Memc[colnames+6*SZ_COLNAME+6], SZ_COLNAME)
+ call strcpy (NITER, Memc[colnames+7*SZ_COLNAME+7], SZ_COLNAME)
+ call strcpy (SHARP, Memc[colnames+8*SZ_COLNAME+8], SZ_COLNAME)
+ call strcpy (CHI, Memc[colnames+9*SZ_COLNAME+9], SZ_COLNAME)
+ call strcpy (PIER, Memc[colnames+10*SZ_COLNAME+10], SZ_COLNAME)
+ call strcpy (PERROR, Memc[colnames+11*SZ_COLNAME+11], SZ_COLNAME)
+
+ # Se up the column format definitions.
+ call strcpy ("%6d", Memc[colformat], SZ_COLFMT)
+ call strcpy ("%6d", Memc[colformat+SZ_COLFMT+1], SZ_COLFMT)
+ call strcpy ("%10.3f", Memc[colformat+2*SZ_COLFMT+2], SZ_COLFMT)
+ call strcpy ("%10.3f", Memc[colformat+3*SZ_COLFMT+3], SZ_COLFMT)
+ call strcpy ("%12.3f", Memc[colformat+4*SZ_COLFMT+4], SZ_COLFMT)
+ call strcpy ("%14.3f", Memc[colformat+5*SZ_COLFMT+5], SZ_COLFMT)
+ call strcpy ("%15.7g", Memc[colformat+6*SZ_COLFMT + 6], SZ_COLFMT)
+ call strcpy ("%6d", Memc[colformat+7*SZ_COLFMT+7], SZ_COLFMT)
+ call strcpy ("%12.3f", Memc[colformat+8*SZ_COLFMT+8], SZ_COLFMT)
+ call strcpy ("%12.3f", Memc[colformat+9*SZ_COLFMT+9], SZ_COLFMT)
+ call strcpy ("%6d", Memc[colformat+10*SZ_COLFMT+10], SZ_COLFMT)
+ call strcpy ("%13s", Memc[colformat+11*SZ_COLFMT+11], SZ_COLFMT)
+
+ # Set up the column unit definitions.
+ call strcpy ("NUMBER", Memc[colunits], SZ_COLUNITS)
+ call strcpy ("NUMBER", Memc[colunits+SZ_COLUNITS+1], SZ_COLUNITS)
+ call strcpy ("PIXELS", Memc[colunits+2*SZ_COLUNITS+2], SZ_COLUNITS)
+ call strcpy ("PIXELS", Memc[colunits+3*SZ_COLUNITS+3], SZ_COLUNITS)
+ call strcpy ("MAGNITIDES", Memc[colunits+4*SZ_COLUNITS+4], SZ_COLUNITS)
+ call strcpy ("MAGNITIDES", Memc[colunits+5*SZ_COLUNITS+5], SZ_COLUNITS)
+ call strcpy ("COUNTS", Memc[colunits+6*SZ_COLUNITS+6], SZ_COLUNITS)
+ call strcpy ("NUMBER", Memc[colunits+7*SZ_COLUNITS+7], SZ_COLUNITS)
+ call strcpy ("NUMBER", Memc[colunits+8*SZ_COLUNITS+8], SZ_COLUNITS)
+ call strcpy ("NUMBER", Memc[colunits+9*SZ_COLUNITS+9], SZ_COLUNITS)
+ call strcpy ("NUMBER", Memc[colunits+10*SZ_COLUNITS+10], SZ_COLUNITS)
+ call strcpy ("PERRORS", Memc[colunits+11*SZ_COLUNITS+11], SZ_COLUNITS)
+
+ # Define the column datatypes.
+ Memi[col_dtype] = TY_INT
+ Memi[col_dtype+1] = TY_INT
+ Memi[col_dtype+2] = TY_REAL
+ Memi[col_dtype+3] = TY_REAL
+ Memi[col_dtype+4] = TY_REAL
+ Memi[col_dtype+5] = TY_REAL
+ Memi[col_dtype+6] = TY_REAL
+ Memi[col_dtype+7] = TY_INT
+ Memi[col_dtype+8] = TY_REAL
+ Memi[col_dtype+9] = TY_REAL
+ Memi[col_dtype+10] = TY_INT
+ Memi[col_dtype+11] = -13
+
+ # Define columnlengths.
+ do i = 1, NST_NOUTCOL
+ Memi[col_len+i-1] = 1
+
+ # Define and create the table.
+ call tbcdef (nst, colpoint, Memc[colnames], Memc[colunits],
+ Memc[colformat], Memi[col_dtype], Memi[col_len], NST_NOUTCOL)
+ call tbtcre (nst)
+
+ # Write out some header parameters.
+ call dp_tnstarpars (dao, nst)
+
+ call sfree (sp)
+
+end
+
+
+define NST_NAME1STR "#N%4tID%10tGROUP%16tXCENTER%26tYCENTER%36tMAG%48t\
+MERR%62tMSKY%80t\\\n"
+define NST_UNIT1STR "#U%4t##%10t##%16tpixels%26tpixels%36tmagnitudes%48t\
+magnitudes%62tcounts%80t\\\n"
+define NST_FORMAT1STR "#F%4t%%-9d%10t%%-6d%16t%%-10.3f%26t%%-10.3f%36t\
+%%-12.3f%48t%%-14.3f%62t%%-15.7g%80t \n"
+
+define NST_NAME2STR "#N%12tNITER%18tSHARPNESS%30tCHI%42tPIER%48tPERROR%80t\\\n"
+define NST_UNIT2STR "#U%12t##%18t##%30t##%42t##%48tperrors%80t\\\n"
+define NST_FORMAT2STR "#F%12t%%-17d%18t%%-12.3f%30t%%-12.3f%42t%%-6d\
+%48t%%-13s%80t \n"
+
+# DP_XPNEWNSTAR -- Create a new NSTAR output text file.
+
+procedure dp_xpnewnstar (dao, nst)
+
+pointer dao # pointer to the daophot structure
+int nst # the output file descriptor
+
+
+begin
+ # Write out some header parameters.
+ call dp_xnstarpars (dao, nst)
+
+ # Write out the header banner.
+ call fprintf (nst, "#\n")
+ call fprintf (nst, NST_NAME1STR)
+ call fprintf (nst, NST_UNIT1STR)
+ call fprintf (nst, NST_FORMAT1STR)
+ call fprintf (nst, "#\n")
+ call fprintf (nst, NST_NAME2STR)
+ call fprintf (nst, NST_UNIT2STR)
+ call fprintf (nst, NST_FORMAT2STR)
+ call fprintf (nst, "#\n")
+end
+
+
+# DP_XNSTARPARS -- Add parameters to the header of the output NSTAR text file.
+
+procedure dp_xnstarpars (dao, nst)
+
+pointer dao # pointer to the daophot structure
+int nst # the output file descriptor
+
+pointer psffit, sp, outstr, date, time, comment
+bool itob()
+int envfind()
+
+begin
+ # Get pointers
+ psffit = DP_PSFFIT(dao)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+ call salloc (date, SZ_DATE, TY_CHAR)
+ call salloc (time, SZ_DATE, TY_CHAR)
+ call salloc (comment, SZ_LINE, TY_CHAR)
+ Memc[comment] = EOS
+
+ # Write the id.
+ if (envfind ("version", Memc[outstr], SZ_LINE) <=0)
+ call strcpy ("NOAO/IRAF", Memc[outstr], SZ_LINE)
+ call dp_rmwhite (Memc[outstr], Memc[outstr], SZ_LINE)
+ call dp_sparam (nst, "IRAF", Memc[outstr], "version", Memc[comment])
+ if (envfind ("userid", Memc[outstr], SZ_LINE) > 0)
+ call dp_sparam (nst, "USER", Memc[outstr], "name", Memc[comment])
+ call gethost (Memc[outstr], SZ_LINE)
+ call dp_sparam (nst, "HOST", Memc[outstr], "computer", Memc[comment])
+ call dp_date (Memc[date], Memc[time], SZ_DATE)
+ call dp_sparam (nst, "DATE", Memc[date], "yyyy-mm-dd", Memc[comment])
+ call dp_sparam (nst, "TIME", Memc[time], "hh:mm:ss", Memc[comment])
+ call dp_sparam (nst, "PACKAGE", "daophot", "name", Memc[comment])
+ call dp_sparam (nst, "TASK", "nstar", "name", Memc[comment])
+
+ # Write out the file names.
+ call dp_imroot (DP_INIMAGE(dao), Memc[outstr], SZ_FNAME)
+ call dp_sparam (nst, "IMAGE", Memc[outstr], "imagename",
+ Memc[comment])
+ call dp_froot (DP_INPHOTFILE(dao), Memc[outstr], SZ_FNAME)
+ call dp_sparam (nst, "GRPFILE", Memc[outstr], "filename", Memc[comment])
+ call dp_imroot (DP_PSFIMAGE(dao), Memc[outstr], SZ_FNAME)
+ call dp_sparam (nst, "PSFIMAGE", Memc[outstr], "imagename",
+ Memc[comment])
+ call dp_froot (DP_OUTPHOTFILE(dao), Memc[outstr], SZ_FNAME)
+ call dp_sparam (nst, "NSTARFILE", Memc[outstr], "filename",
+ Memc[comment])
+ if (DP_OUTREJFILE(dao) == EOS)
+ call dp_sparam (nst, "REJFILE", "\"\"", "filename", Memc[comment])
+ else {
+ call dp_froot (DP_OUTREJFILE(dao), Memc[outstr], SZ_FNAME)
+ call dp_sparam (nst, "REJFILE", Memc[outstr], "filename",
+ Memc[comment])
+ }
+
+ # Write out the data dependent parameters.
+ call dp_rparam (nst, "SCALE", DP_SCALE(dao), "units/pix",
+ Memc[comment])
+ call dp_rparam (nst, "DATAMIN", DP_MINGDATA(dao), "counts",
+ Memc[comment])
+ call dp_rparam (nst, "DATAMAX", DP_MAXGDATA(dao), "counts",
+ Memc[comment])
+ call dp_rparam (nst, "GAIN", DP_PHOTADU(dao), "number", Memc[comment])
+ call dp_rparam (nst, "READNOISE", DP_READNOISE(dao), "electrons",
+ Memc[comment])
+
+ # Write out the observing parameters.
+ call dp_sparam (nst, "OTIME", DP_OTIME(dao), "timeunit", Memc[comment])
+ call dp_rparam (nst, "XAIRMASS", DP_XAIRMASS(dao), "number",
+ Memc[comment])
+ call dp_sparam (nst, "IFILTER", DP_IFILTER(dao), "filter",
+ Memc[comment])
+
+ # Write out the fitting parameters.
+ call dp_bparam (nst, "RECENTER", itob (DP_RECENTER(dao)), "switch",
+ Memc[comment])
+ call dp_bparam (nst, "FITSKY", itob (DP_FITSKY(dao)), "switch",
+ Memc[comment])
+ call dp_bparam (nst, "GRPSKY", itob (DP_GROUPSKY(dao)), "switch",
+ Memc[comment])
+ call dp_rparam (nst, "PSFMAG", DP_PSFMAG(psffit), "magnitude",
+ Memc[comment])
+ call dp_rparam (nst, "PSFRAD", DP_SPSFRAD(dao), "scaleunit",
+ Memc[comment])
+ call dp_rparam (nst, "FITRAD", DP_SFITRAD(dao), "scaleunit",
+ Memc[comment])
+ call dp_iparam (nst, "MAXITER", DP_MAXITER(dao), "number",
+ Memc[comment])
+ call dp_iparam (nst, "MAXGROUP", DP_MAXGROUP(dao), "number",
+ Memc[comment])
+ call dp_rparam (nst, "FLATERROR", DP_FLATERR(dao), "percentage",
+ Memc[comment])
+ call dp_rparam (nst, "PROFERROR", DP_PROFERR(dao), "percentage",
+ Memc[comment])
+ call dp_iparam (nst, "CLIPEXP", DP_CLIPEXP(dao), "number",
+ Memc[comment])
+ call dp_rparam (nst, "CLIPRANGE", DP_CLIPRANGE(dao), "sigma",
+ Memc[comment])
+ call dp_rparam (nst, "MERGERAD", DP_SMERGERAD(dao), "scaleunit",
+ Memc[comment])
+
+ call sfree(sp)
+end
+
+
+# DP_TNSTARPARS -- Add parameters to the header of the output NSTAR ST table.
+
+procedure dp_tnstarpars (dao, nst)
+
+pointer dao # pointer to the daophot structure
+pointer nst # pointer to the output photometry table
+
+pointer psffit, sp, outstr, date, time
+bool itob()
+int envfind()
+
+begin
+ # Get pointers
+ psffit = DP_PSFFIT(dao)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+ call salloc (date, SZ_DATE, TY_CHAR)
+ call salloc (time, SZ_DATE, TY_CHAR)
+
+ # Write the id.
+ if (envfind ("version", Memc[outstr], SZ_LINE) <=0)
+ call strcpy ("NOAO/IRAF", Memc[outstr], SZ_LINE)
+ call dp_rmwhite (Memc[outstr], Memc[outstr], SZ_LINE)
+ call tbhadt (nst, "IRAF", Memc[outstr])
+ if (envfind ("userid", Memc[outstr], SZ_LINE) > 0)
+ call tbhadt (nst, "USER", Memc[outstr])
+ call gethost (Memc[outstr], SZ_LINE)
+ call tbhadt (nst, "HOST", Memc[outstr])
+ call dp_date (Memc[date], Memc[time], SZ_DATE)
+ call tbhadt (nst, "DATE", Memc[date])
+ call tbhadt (nst, "TIME", Memc[time])
+ call tbhadt (nst, "PACKAGE", "daophot")
+ call tbhadt (nst, "TASK", "nstar")
+
+ # Write out the file names.
+ call dp_imroot (DP_INIMAGE(dao), Memc[outstr], SZ_FNAME)
+ call tbhadt (nst, "IMAGE", Memc[outstr])
+ call dp_froot (DP_INPHOTFILE(dao), Memc[outstr], SZ_FNAME)
+ call tbhadt (nst, "GRPFILE", Memc[outstr])
+ call dp_imroot (DP_PSFIMAGE(dao), Memc[outstr], SZ_FNAME)
+ call tbhadt (nst, "PSFIMAGE", Memc[outstr])
+ call dp_froot (DP_OUTPHOTFILE(dao), Memc[outstr], SZ_FNAME)
+ call tbhadt (nst, "NSTARFILE", Memc[outstr])
+ if (DP_OUTREJFILE(dao) == EOS)
+ call tbhadt (nst, "REJFILE", "\"\"")
+ else {
+ call dp_froot (DP_OUTPHOTFILE(dao), Memc[outstr], SZ_FNAME)
+ call tbhadt (nst, "REJFILE", Memc[outstr])
+ }
+
+ # Write out the data dependent parameters.
+ call tbhadr (nst, "SCALE", DP_SCALE(dao))
+ call tbhadr (nst, "DATAMIN", DP_MINGDATA(dao))
+ call tbhadr (nst, "DATAMAX", DP_MAXGDATA(dao))
+ call tbhadr (nst, "GAIN", DP_PHOTADU(dao))
+ call tbhadr (nst, "READNOISE", DP_READNOISE(dao))
+
+ # Write out the observing parameters.
+ call tbhadt (nst, "OTIME", DP_OTIME(dao))
+ call tbhadr (nst, "XAIRMASS", DP_XAIRMASS(dao))
+ call tbhadt (nst, "IFILTER", DP_IFILTER(dao))
+
+ # Write out the fitting parameters.
+ call tbhadb (nst, "RECENTER", itob (DP_RECENTER(dao)))
+ call tbhadb (nst, "FITSKY", itob (DP_FITSKY(dao)))
+ call tbhadb (nst, "GRPSKY", itob (DP_GROUPSKY(dao)))
+ call tbhadr (nst, "PSFMAG", DP_PSFMAG(psffit))
+ call tbhadr (nst, "PSFRAD", DP_SPSFRAD(dao))
+ call tbhadr (nst, "FITRAD", DP_SFITRAD(dao))
+ call tbhadi (nst, "MAXITER", DP_MAXITER(dao))
+ call tbhadi (nst, "MAXGROUP", DP_MAXGROUP(dao))
+ call tbhadr (nst, "FLATERROR", DP_FLATERR(dao))
+ call tbhadr (nst, "PROFERROR", DP_PROFERR(dao))
+ call tbhadi (nst, "CLIPEXP", DP_CLIPEXP(dao))
+ call tbhadr (nst, "CLIPRANGE", DP_CLIPRANGE(dao))
+ call tbhadr (nst, "MERGERAD", DP_SMERGERAD(dao))
+
+ call sfree(sp)
+end
+
+
+# DP_TNTWRITE -- Write out the NSTAR results to an ST table.
+
+procedure dp_tntwrite (dao, im, nst, rej, niter, old_size, output_row,
+ routput_row, colpoint)
+
+pointer dao # pointer to the daophot structure
+pointer im # the input image descriptor
+pointer nst # output photometry file descriptor
+int rej # output rejections file descriptor
+int niter # number of iterations
+int old_size # original size of group
+int output_row # output photometry file row number
+int routput_row # output rejections file row number
+pointer colpoint[ARB] # column pointer array
+
+int i, id, nkeep, nreject, pier, plen, iter
+pointer psffit, nstar, apsel, sp, perror
+real xcen, ycen, mag, errmag, sharp
+int dp_gnsterr()
+
+begin
+ # Get some daophot pointers.
+ nstar = DP_NSTAR(dao)
+ apsel = DP_APSEL(dao)
+ psffit = DP_PSFFIT(dao)
+
+ # Fill in the INDEFS.
+ nkeep = DP_NNUM(nstar)
+ nreject = old_size - nkeep
+ if (nreject > 0) {
+ call amovkr (INDEFR, Memr[DP_APMAG(apsel)+nkeep], nreject)
+ call amovkr (INDEFR, Memr[DP_APERR(apsel)+nkeep], nreject)
+ call amovkr (INDEFR, Memr[DP_APCHI(apsel)+nkeep], nreject)
+ }
+
+ call smark (sp)
+ call salloc (perror, SZ_FNAME, TY_CHAR)
+
+ # Now write out the results.
+ do i = 1, old_size {
+
+ # Get the results.
+ id = Memi[DP_APID (apsel)+i-1]
+ xcen = Memr[DP_APXCEN (apsel)+i-1]
+ ycen = Memr[DP_APYCEN (apsel)+i-1]
+ if (IS_INDEFR(xcen) || IS_INDEFR(ycen))
+ next
+ call dp_wout (dao, im, xcen, ycen, xcen, ycen, 1)
+ mag = Memr[DP_APMAG(apsel)+i-1]
+ errmag = Memr[DP_APERR(apsel)+i-1]
+ if (! IS_INDEFR(mag)) {
+ if (! IS_INDEFR(errmag))
+ errmag = 1.085736 * errmag / mag
+ sharp = 1.4427 * Memr[DP_PSFPARS(psffit)] *
+ Memr[DP_PSFPARS(psffit)+1] * Memr[DP_NNUMER(nstar)+i-1] /
+ (mag * DP_PSFHEIGHT(psffit) * Memr[DP_NDENOM(nstar)+i-1])
+ if ((sharp < MIN_SHARP) || (sharp > MAX_SHARP))
+ sharp = INDEFR
+ mag = DP_PSFMAG (psffit) - 2.5 * log10 (mag)
+ } else
+ sharp = INDEFR
+ pier = Memi[DP_NIER(nstar)+i-1]
+ if (pier == NSTERR_OK)
+ iter = niter
+ else
+ iter = 0
+ plen = dp_gnsterr (pier, Memc[perror], SZ_FNAME)
+
+ # Write the results to the standard output.
+ if (DP_VERBOSE (dao) == YES) {
+ call printf (
+ "\tID: %5d XCEN: %8.2f YCEN: %8.2f MAG: %8.2f\n")
+ call pargi (id)
+ call pargr (xcen)
+ call pargr (ycen)
+ call pargr (mag)
+ }
+
+ # Write the output row to the proper table.
+ if ((rej != NULL) && (pier != NSTERR_OK)) {
+ routput_row = routput_row + 1
+ call tbrpti (rej, colpoint[1], id, 1, routput_row)
+ call tbrpti (rej, colpoint[2], DP_NGNUM(nstar), 1, routput_row)
+ call tbrptr (rej, colpoint[3], xcen, 1, routput_row)
+ call tbrptr (rej, colpoint[4], ycen, 1, routput_row)
+ call tbrptr (rej, colpoint[5], mag, 1, routput_row)
+ call tbrptr (rej, colpoint[6], errmag, 1, routput_row)
+ call tbrptr (rej, colpoint[7], Memr[DP_APMSKY(apsel)+i-1],
+ 1, routput_row)
+ call tbrpti (rej, colpoint[8], iter, 1, routput_row)
+ call tbrptr (rej, colpoint[9], sharp, 1, routput_row)
+ call tbrptr (rej, colpoint[10], Memr[DP_APCHI(apsel)+i-1],
+ 1, routput_row)
+ call tbrpti (rej, colpoint[11], pier, 1, routput_row)
+ call tbrptt (rej, colpoint[12], Memc[perror], plen, 1,
+ routput_row)
+ } else {
+ output_row = output_row + 1
+ call tbrpti (nst, colpoint[1], id, 1, output_row)
+ call tbrpti (nst, colpoint[2], DP_NGNUM(nstar), 1, output_row)
+ call tbrptr (nst, colpoint[3], xcen, 1, output_row)
+ call tbrptr (nst, colpoint[4], ycen, 1, output_row)
+ call tbrptr (nst, colpoint[5], mag, 1, output_row)
+ call tbrptr (nst, colpoint[6], errmag, 1, output_row)
+ call tbrptr (nst, colpoint[7], Memr[DP_APMSKY(apsel)+i-1],
+ 1, output_row)
+ call tbrpti (nst, colpoint[8], iter, 1, output_row)
+ call tbrptr (nst, colpoint[9], sharp, 1, output_row)
+ call tbrptr (nst, colpoint[10], Memr[DP_APCHI(apsel)+i-1],
+ 1, output_row)
+ call tbrpti (nst, colpoint[11], pier, 1, output_row)
+ call tbrptt (nst, colpoint[12], Memc[perror], plen, 1,
+ output_row)
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+define NST_DATA1STR "%-9d%10t%-6d%16t%-10.3f%26t%-10.3f%36t%-12.3f%48t\
+%-14.3f%62t%-15.7g%80t\\\n"
+define NST_DATA2STR "%12t%-6d%18t%-12.3f%30t%-12.3f%42t%-6d%48t%-13.13s%80t \n"
+
+# DP_XNTWRITE -- Write out the NSTAR results to a text file.
+
+procedure dp_xntwrite (dao, im, nst, rej, niter, old_size)
+
+pointer dao # pointer to the daophot structure
+pointer im # the input image descriptor
+int nst # the output photometry file descriptor
+int rej # the output rejections file descriptor
+int niter # the number of the iteration
+int old_size # old size of group
+
+int i, id, nkeep, nreject, pier, plen, iter
+pointer nstar, psffit, apsel, sp, perror
+real xcen, ycen, mag, errmag, sharp
+int dp_gnsterr()
+
+begin
+ # Get some daophot pointers.
+ nstar = DP_NSTAR(dao)
+ psffit = DP_PSFFIT(dao)
+ apsel = DP_APSEL(dao)
+
+ # Fill in the results for the rejected stars with INDEFS.
+ nkeep = DP_NNUM(nstar)
+ nreject = old_size - nkeep
+ if (nreject > 0) {
+ call amovkr (INDEFR, Memr[DP_APMAG(apsel)+nkeep], nreject)
+ call amovkr (INDEFR, Memr[DP_APERR(apsel)+nkeep], nreject)
+ call amovkr (INDEFR, Memr[DP_APCHI(apsel)+nkeep], nreject)
+ }
+
+ call smark (sp)
+ call salloc (perror, SZ_FNAME, TY_CHAR)
+
+ # Now write out the results.
+ do i = 1, old_size {
+
+ # Get the results.
+ id = Memi[DP_APID (apsel)+i-1]
+ xcen = Memr[DP_APXCEN (apsel)+i-1]
+ ycen = Memr[DP_APYCEN (apsel)+i-1]
+ if (IS_INDEFR(xcen) || IS_INDEFR(ycen))
+ next
+ call dp_wout (dao, im, xcen, ycen, xcen, ycen, 1)
+ mag = Memr[DP_APMAG(apsel)+i-1]
+ errmag = Memr[DP_APERR(apsel)+i-1]
+ if (! IS_INDEFR(mag)) {
+ if (! IS_INDEFR(errmag))
+ errmag = 1.085736 * errmag / mag
+ sharp = 1.4427 * Memr[DP_PSFPARS(psffit)] *
+ Memr[DP_PSFPARS(psffit)+1] * Memr[DP_NNUMER(nstar)+i-1] /
+ (mag * DP_PSFHEIGHT(psffit) * Memr[DP_NDENOM(nstar)+i-1])
+ if ((sharp < MIN_SHARP) || (sharp > MAX_SHARP))
+ sharp = INDEFR
+ mag = DP_PSFMAG (psffit) - 2.5 * log10 (mag)
+ } else
+ sharp = INDEFR
+ pier = Memi[DP_NIER(nstar)+i-1]
+ if (pier == NSTERR_OK)
+ iter = niter
+ else
+ iter = 0
+ plen = dp_gnsterr (pier, Memc[perror], SZ_FNAME)
+
+ # Write the results to the standard output.
+ if (DP_VERBOSE (dao) == YES) {
+ call printf (
+ "\tID: %5d XCEN: %8.2f YCEN: %8.2f MAG: %8.2f\n")
+ call pargi (id)
+ call pargr (xcen)
+ call pargr (ycen)
+ call pargr (mag)
+ }
+
+ # Write the results to the output file.
+ if ((rej != NULL) && (pier != NSTERR_OK)) {
+ call fprintf (rej, NST_DATA1STR)
+ call pargi (id)
+ call pargi (DP_NGNUM(nstar))
+ call pargr (xcen)
+ call pargr (ycen)
+ call pargr (mag)
+ call pargr (errmag)
+ call pargr (Memr[DP_APMSKY(apsel)+i-1])
+ call fprintf (rej, NST_DATA2STR)
+ call pargi (iter)
+ call pargr (sharp)
+ call pargr (Memr[DP_APCHI(apsel)+i-1])
+ call pargi (pier)
+ call pargstr (Memc[perror])
+ } else {
+ call fprintf (nst, NST_DATA1STR)
+ call pargi (id)
+ call pargi (DP_NGNUM(nstar))
+ call pargr (xcen)
+ call pargr (ycen)
+ call pargr (mag)
+ call pargr (errmag)
+ call pargr (Memr[DP_APMSKY(apsel)+i-1])
+ call fprintf (nst, NST_DATA2STR)
+ call pargi (iter)
+ call pargr (sharp)
+ call pargr (Memr[DP_APCHI(apsel)+i-1])
+ call pargi (pier)
+ call pargstr (Memc[perror])
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# DP_GNSTERR -- Set the NSTAR task error code string.
+
+int procedure dp_gnsterr (ier, perror, maxch)
+
+int ier # the integer error code
+char perror # the output error code string
+int maxch # the maximum size of the error code string
+
+int plen
+int gstrcpy()
+
+begin
+ switch (ier) {
+ case NSTERR_OK:
+ plen = gstrcpy ("No_error", perror, maxch)
+ case NSTERR_BIGGROUP:
+ plen = gstrcpy ("Big_group", perror, maxch)
+ case NSTERR_INDEFSKY:
+ plen = gstrcpy ("Bad_sky", perror, maxch)
+ case NSTERR_NOPIX:
+ plen = gstrcpy ("Npix_too_few", perror, maxch)
+ case NSTERR_SINGULAR:
+ plen = gstrcpy ("Singular", perror, maxch)
+ case NSTERR_FAINT:
+ plen = gstrcpy ("Too_faint", perror, maxch)
+ case NSTERR_MERGE:
+ plen = gstrcpy ("Merged", perror, maxch)
+ case NSTERR_OFFIMAGE:
+ plen = gstrcpy ("Off_image", perror, maxch)
+ default:
+ plen = gstrcpy ("No_error", perror, maxch)
+ }
+
+ return (plen)
+end
diff --git a/noao/digiphot/daophot/nstar/mkpkg b/noao/digiphot/daophot/nstar/mkpkg
new file mode 100644
index 00000000..327f3487
--- /dev/null
+++ b/noao/digiphot/daophot/nstar/mkpkg
@@ -0,0 +1,24 @@
+# NSTAR task
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ dpggroup.x "../../lib/ptkeysdef.h" ../lib/daophotdef.h \
+ ../lib/apseldef.h
+ dpmemnstar.x ../lib/daophotdef.h ../lib/nstardef.h
+ dpnconfirm.x ../lib/daophotdef.h
+ dpnstar.x <imhdr.h> <tbset.h> \
+ <mach.h> ../lib/daophotdef.h \
+ ../lib/apseldef.h ../lib/nstardef.h
+ dpnstarfit.x <imhdr.h> ../lib/daophotdef.h \
+ ../lib/apseldef.h ../lib/nstardef.h \
+ <mach.h>
+ dpntwrite.x <tbset.h> <time.h> \
+ ../lib/daophotdef.h ../lib/apseldef.h \
+ ../lib/nstardef.h
+ t_nstar.x <fset.h> <imhdr.h> \
+ ../lib/daophotdef.h
+ ;
diff --git a/noao/digiphot/daophot/nstar/t_nstar.x b/noao/digiphot/daophot/nstar/t_nstar.x
new file mode 100644
index 00000000..8f6c542e
--- /dev/null
+++ b/noao/digiphot/daophot/nstar/t_nstar.x
@@ -0,0 +1,308 @@
+include <fset.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+
+# T_NSTAR -- Procedure to fit the PSF to multiple stars.
+
+procedure t_nstar ()
+
+pointer image # input image descriptor
+pointer groupfile # input group file descriptor
+pointer psfimage # input PSF image descriptor
+pointer nstarfile # output photometry file descriptor
+pointer rejfile # output rejections file descriptor
+int verbose # print messages
+int verify # verify the critical parameters
+int update # update the parameter set
+int cache # cache the input image pixels
+
+pointer sp, outfname, im, psfim, dao, str
+int imlist, limlist, alist, lalist, pimlist, lpimlist, olist, lolist
+int rlist, lrlist, root, grp, nst, rejfd, wcs, req_size, old_size
+int buf_size, memstat
+bool ap_text
+
+pointer immap(), tbtopn()
+int strlen(), strncmp(), fnldir(), fstati(), open(), btoi()
+int access(), imtopen(), imtlen(), imtgetim(), fntopnb(), fntlenb()
+int fntgfnb(), clgwrd(), sizeof(), dp_memstat()
+bool clgetb(), itob()
+
+begin
+ # Set the standard output to flush on newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Allocate working memory.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (groupfile, SZ_FNAME, TY_CHAR)
+ call salloc (psfimage, SZ_FNAME, TY_CHAR)
+ call salloc (nstarfile, SZ_FNAME, TY_CHAR)
+ call salloc (rejfile, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Get the input and output file names.
+ call clgstr ("image", Memc[image], SZ_FNAME)
+ call clgstr ("groupfile", Memc[groupfile], SZ_FNAME)
+ call clgstr ("psfimage", Memc[psfimage], SZ_FNAME)
+ call clgstr ("nstarfile", Memc[nstarfile], SZ_FNAME)
+ call clgstr ("rejfile", Memc[rejfile], SZ_FNAME)
+
+ # Get the task mode parameters.
+ verbose = btoi (clgetb ("verbose"))
+ verify = btoi (clgetb ("verify"))
+ update = btoi (clgetb ("update"))
+ cache = btoi (clgetb ("cache"))
+
+ # Get the lists.
+ imlist = imtopen (Memc[image])
+ limlist = imtlen (imlist)
+ alist = fntopnb (Memc[groupfile], NO)
+ lalist = fntlenb (alist)
+ pimlist = imtopen (Memc[psfimage])
+ lpimlist = imtlen (pimlist)
+ olist = fntopnb (Memc[nstarfile], NO)
+ lolist = fntlenb (olist)
+ rlist = fntopnb (Memc[rejfile], NO)
+ lrlist = fntlenb (rlist)
+
+ # Test that the lengths of the photometry file, psf image, and
+ # output file lists are the same as the length of the input image
+ # list.
+
+ if ((limlist != lalist) && (strncmp (Memc[groupfile], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (rlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatable image and group file list lengths")
+ }
+
+ if ((limlist != lpimlist) && (strncmp (Memc[psfimage], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (rlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatable image and psf file list lengths")
+ }
+
+ if ((limlist != lolist) && (strncmp (Memc[nstarfile], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (rlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatable image and nstar file list lengths")
+ }
+
+ if ((lrlist > 0) && (limlist != lrlist) && (strncmp (Memc[rejfile],
+ DEF_DEFNAME, DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (rlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatable image and rejections file list lengths")
+ }
+
+ # Open the daophot structure and get some parameters.
+ call dp_gppars (dao)
+
+ # Set some parameters.
+ call dp_seti (dao, VERBOSE, verbose)
+
+ # Verify and update the parameters if appropriate.
+ if (verify == YES) {
+ call dp_nconfirm (dao)
+ if (update == YES)
+ call dp_pppars (dao)
+ }
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_FNAME, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_FNAME, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSOUT, wcs)
+ wcs = clgwrd ("wcspsf", Memc[str], SZ_FNAME, WCSPSFSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the psf coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSPSF, wcs)
+
+ # Initialize the photometry structure.
+ call dp_apsetup (dao)
+
+ # Initialize the PSF structure.
+ call dp_fitsetup (dao)
+
+ # Initialize the nstar structure.
+ call dp_nstarsetup (dao)
+
+ # Loop over the images.
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open the input image.
+ im = immap (Memc[image], READ_ONLY, 0)
+ call dp_imkeys (dao, im)
+ call dp_sets (dao, INIMAGE, Memc[image])
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = dp_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call dp_pcache (im, INDEFI, buf_size)
+
+ # Open the input group table.
+ if (fntgfnb (alist, Memc[groupfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[groupfile], SZ_FNAME)
+ root = fnldir (Memc[groupfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[groupfile+root],
+ DEF_LENDEFNAME) == 0 || (root == strlen (Memc[groupfile])))
+ call dp_inname (Memc[image], Memc[outfname], "grp",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[groupfile], Memc[outfname], SZ_FNAME)
+ ap_text = itob (access (Memc[outfname], 0, TEXT_FILE))
+ if (ap_text)
+ grp = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ else
+ grp = tbtopn (Memc[outfname], READ_ONLY, 0)
+ call dp_sets (dao, INPHOTFILE, Memc[outfname])
+
+ # Open and read the PSF image.
+ if (imtgetim (pimlist, Memc[psfimage], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[psfimage], SZ_FNAME)
+ root = fnldir (Memc[psfimage], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[psfimage+root],
+ DEF_LENDEFNAME) == 0 || (root == strlen (Memc[psfimage])))
+ call dp_iimname (Memc[image], Memc[outfname], "psf",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[psfimage], Memc[outfname], SZ_FNAME)
+ psfim = immap (Memc[outfname], READ_ONLY, 0)
+ call dp_readpsf (dao, psfim)
+ call dp_sets (dao, PSFIMAGE, Memc[outfname])
+
+ # Open the output NSTAR file. If the output is DEF_DEFNAME,
+ # dir$default or a directory specification then the extension
+ # "nst" is added to the image name and a suitable version number
+ # is appended to the output name.
+
+ if (fntgfnb (olist, Memc[nstarfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[nstarfile], SZ_FNAME)
+ root = fnldir (Memc[nstarfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[nstarfile+root],
+ DEF_LENDEFNAME) == 0 || (root == strlen (Memc[nstarfile]))) {
+ call dp_outname (Memc[image], Memc[outfname], "nst",
+ Memc[outfname], SZ_FNAME)
+ } else
+ call strcpy (Memc[nstarfile], Memc[outfname], SZ_FNAME)
+ if (DP_TEXT(dao) == YES)
+ nst = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ else
+ nst = tbtopn (Memc[outfname], NEW_FILE, 0)
+ call dp_sets (dao, OUTPHOTFILE, Memc[outfname])
+
+ if (lrlist <= 0) {
+ rejfd = NULL
+ Memc[outfname] = EOS
+ } else {
+ if (fntgfnb (rlist, Memc[rejfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[rejfile], SZ_FNAME)
+ root = fnldir (Memc[rejfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[rejfile+root],
+ DEF_LENDEFNAME) == 0 || (root == strlen (Memc[rejfile])))
+ call dp_outname (Memc[image], Memc[outfname], "nrj",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[rejfile], Memc[outfname], SZ_FNAME)
+ if (DP_TEXT(dao) == YES)
+ rejfd = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ else
+ rejfd = tbtopn (Memc[outfname], NEW_FILE, 0)
+ }
+ call dp_sets (dao, OUTREJFILE, Memc[outfname])
+
+ # Do the PSF fitting.
+ call dp_nphot (dao, im, grp, nst, rejfd, ap_text)
+
+ # Close the input image.
+ call imunmap (im)
+
+ # Close the group file.
+ if (ap_text)
+ call close (grp)
+ else
+ call tbtclo (grp)
+
+ # Close the PSF image.
+ call imunmap (psfim)
+
+ # Close the output photometry file.
+ if (DP_TEXT(dao) == YES)
+ call close (nst)
+ else
+ call tbtclo (nst)
+
+ # Close the output rejections file.
+ if (rejfd != NULL) {
+ if (DP_TEXT(dao) == YES)
+ call close (rejfd)
+ else
+ call tbtclo (rejfd)
+ }
+
+ # Uncache memory.
+ call fixmem (old_size)
+
+ }
+
+ # Close the image/file lists.
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (rlist)
+
+ # Close the nstar structure.
+ call dp_nsclose (dao)
+
+ # Close the PSF structure.
+ call dp_fitclose (dao)
+
+ # Close the photometry structure.
+ call dp_apclose (dao)
+
+ # Free the daophot structure.
+ call dp_free (dao)
+
+ call sfree(sp)
+end
diff --git a/noao/digiphot/daophot/peak.par b/noao/digiphot/daophot/peak.par
new file mode 100644
index 00000000..e3600d38
--- /dev/null
+++ b/noao/digiphot/daophot/peak.par
@@ -0,0 +1,17 @@
+# Parameters for the PEAK task
+
+image,f,a,,,,"Image corresponding to photometry"
+photfile,f,a,default,,,"Input photometry file (default: image.mag.?)"
+psfimage,f,a,default,,,"PSF image (default: image.psf.?)"
+peakfile,f,a,"default",,,"Output photometry file (default: image.pk.?)"
+rejfile,f,a,"default",,,"Output rejections file (default: image.rej.?)"
+datapars,pset,h,"",,,Data dependent parameters
+daopars,pset,h,"",,,Psf fitting parameters
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+wcspsf,s,h,)_.wcspsf,,,"The psf coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the input image pixels in memory?"
+verify,b,h,)_.verify,,,Verify critical peak parameters?
+update,b,h,)_.update,,,Update critical peak parameters?
+verbose,b,h,)_.verbose,,,Print peak messages?
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/peak/dpmempk.x b/noao/digiphot/daophot/peak/dpmempk.x
new file mode 100644
index 00000000..97c7ff48
--- /dev/null
+++ b/noao/digiphot/daophot/peak/dpmempk.x
@@ -0,0 +1,72 @@
+include "../lib/daophotdef.h"
+include "../lib/peakdef.h"
+
+
+# DP_PKSETUP -- Initialize the PEAK fitting structure.
+
+procedure dp_pksetup (dao)
+
+pointer dao # pointer to the daophot structure
+
+pointer peak
+
+begin
+ call malloc (DP_PEAK(dao), LEN_PKSTRUCT, TY_STRUCT)
+ peak = DP_PEAK(dao)
+
+ DP_PKNTERM(peak) = 0
+ DP_PKCLAMP(peak) = NULL
+ DP_PKNORMAL(peak) = NULL
+ DP_PKRESID(peak) = NULL
+ DP_PKDERIV(peak) = NULL
+ DP_PKRESULT(peak) = NULL
+ DP_PKOLDRESULT(peak) = NULL
+end
+
+
+# DP_MEMPK -- Allocate memory for the PEAK fitting arrays.
+
+procedure dp_mempk (dao, nterm)
+
+pointer dao # pointer to the daophot structure
+int nterm # the number of terms to be fit
+
+pointer peak
+
+begin
+ peak = DP_PEAK(dao)
+
+ call malloc (DP_PKCLAMP(peak), nterm, TY_REAL)
+ call malloc (DP_PKNORMAL(peak), nterm * nterm, TY_REAL)
+ call malloc (DP_PKRESID(peak), nterm * nterm, TY_REAL)
+ call malloc (DP_PKDERIV(peak), nterm * nterm, TY_REAL)
+ call malloc (DP_PKRESULT(peak), nterm * nterm, TY_REAL)
+ call malloc (DP_PKOLDRESULT(peak), nterm * nterm, TY_REAL)
+ DP_PKNTERM(peak) = nterm
+end
+
+
+# DP_PKCLOSE -- Free the PEAK fitting structure.
+
+procedure dp_pkclose (dao)
+
+pointer dao # pointer to the daophot structure
+
+pointer peak
+
+begin
+ peak = DP_PEAK(dao)
+ if (DP_PKCLAMP(peak) != NULL)
+ call mfree (DP_PKCLAMP(peak), TY_REAL)
+ if (DP_PKNORMAL(peak) != NULL)
+ call mfree (DP_PKNORMAL(peak), TY_REAL)
+ if (DP_PKRESID(peak) != NULL)
+ call mfree (DP_PKRESID(peak), TY_REAL)
+ if (DP_PKDERIV(peak) != NULL)
+ call mfree (DP_PKDERIV(peak), TY_REAL)
+ if (DP_PKRESULT(peak) != NULL)
+ call mfree (DP_PKRESULT(peak), TY_REAL)
+ if (DP_PKOLDRESULT(peak) != NULL)
+ call mfree (DP_PKOLDRESULT(peak), TY_REAL)
+ call mfree (peak, TY_STRUCT)
+end
diff --git a/noao/digiphot/daophot/peak/dppeakphot.x b/noao/digiphot/daophot/peak/dppeakphot.x
new file mode 100644
index 00000000..182b10d8
--- /dev/null
+++ b/noao/digiphot/daophot/peak/dppeakphot.x
@@ -0,0 +1,277 @@
+include <imhdr.h>
+include <tbset.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/peakdef.h"
+
+
+# DP_PEAKPHOT -- Fit the PSF to a single star.
+
+procedure dp_peakphot (dao, im, tp, tpout, tprej, ap_text)
+
+pointer dao # pointer to the daophot structure
+pointer im # the input image descriptor
+int tp # the input photometry file descriptor
+int tpout # the ouput photometry file descriptor
+int tprej # the rejections file descriptor
+bool ap_text # which style of photometry
+
+real rel_bright, xold, yold, x, y, dx, dy, mag, sky, errmag
+real chi, sharp, radius, itx, ity, otx, oty
+pointer psffit, key, sp, subim, colpoint, indices, fields, perror
+int id, in_nrow, instar, lowx, lowy, nxpix, nypix, niter, out_nrow
+int rout_nrow, nterm, ier, plen
+
+int tbpsta(), dp_rrphot(), dp_pkfit(), dp_gpkerr()
+pointer dp_gsubrast()
+
+begin
+ # Get the daophot pointers.
+ psffit = DP_PSFFIT (dao)
+
+ # Store the original fitting radius.
+ radius = DP_FITRAD(dao)
+
+ # Check that the fitting radius is less than the psf radius.
+ DP_FITRAD(dao) = min (DP_FITRAD(dao), DP_PSFRAD(dao))
+ DP_SFITRAD(dao) = DP_FITRAD(dao) * DP_SCALE(dao)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (indices, NAPPAR, TY_INT)
+ call salloc (fields, SZ_LINE, TY_CHAR)
+ call salloc (colpoint, PK_NOUTCOL, TY_INT)
+ call salloc (perror, SZ_FNAME, TY_CHAR)
+
+ # Initialze the output table.
+ if (DP_TEXT(dao) == YES) {
+ call dp_xnewpeak (dao, tpout)
+ if (tprej != NULL)
+ call dp_xnewpeak (dao, tprej)
+ } else {
+ call dp_tnewpeak (dao, tpout, Memi[colpoint])
+ if (tprej != NULL)
+ call dp_tnewpeak (dao, tprej, Memi[colpoint])
+ }
+
+ # Intialize the input table.
+ if (ap_text) {
+ call pt_kyinit (key)
+ Memi[indices] = DP_PAPID
+ Memi[indices+1] = DP_PAPXCEN
+ Memi[indices+2] = DP_PAPYCEN
+ Memi[indices+3] = DP_PAPMAG1
+ Memi[indices+4] = DP_PAPSKY
+ call dp_gappsf (Memi[indices], Memc[fields], NAPRESULT)
+ in_nrow = 0
+ } else {
+ call dp_tpkinit (tp, Memi[indices])
+ in_nrow = tbpsta (tp, TBL_NROWS)
+ }
+
+ # Initialize the photometry file reading code.
+ instar = 0
+
+ # Initialize the fitting code.
+ if (DP_RECENTER(dao) == YES)
+ nterm = 3
+ else
+ nterm = 1
+ if (DP_FITSKY(dao) == YES)
+ nterm = nterm + 1
+ call dp_mempk (dao, nterm)
+
+ out_nrow = 0
+ rout_nrow = 0
+ repeat {
+
+ # Read in the photometry for a single star.
+ if (dp_rrphot (tp, key, Memc[fields], Memi[indices], id, itx,
+ ity, sky, mag, instar, in_nrow) == EOF)
+ break
+
+ # Convert to and from logical coordinates.
+ call dp_win (dao, im, itx, ity, x, y, 1)
+ call dp_wout (dao, im, x, y, otx, oty, 1)
+
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (
+ "Star: %5d X: %8.2f Y: %8.2f Mag: %8.2f Sky: %8.2f\n")
+ call pargi (id)
+ call pargr (otx)
+ call pargr (oty)
+ call pargr (mag)
+ call pargr (sky)
+ }
+
+ # Check that the center is defined.
+ if (IS_INDEFR(x) || IS_INDEFR(y)) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (
+ "\tWarning: X and/or Y for star %d are undefined\n")
+ call pargi (id)
+ }
+ next
+ }
+
+ # Read in the subraster.
+ subim = dp_gsubrast (im, x, y, DP_FITRAD(dao), lowx, lowy,
+ nxpix, nypix)
+ if (subim == NULL) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (
+ "\tWarning: Cannot read in image data for star %d\n")
+ call pargi (id)
+ }
+ next
+ }
+
+ # Save the old x and y values for use with the variable psf
+ # option.
+ xold = x
+ yold = y
+ call dp_wpsf (dao, im, xold, yold, xold, yold, 1)
+
+ # Compute the relative centers and the relative brightness and
+ # fit the star.
+ if (IS_INDEFR(sky)) {
+
+ ier = PKERR_INDEFSKY
+
+ } else {
+
+ x = x - lowx + 1.0
+ y = y - lowy + 1.0
+ dx = (xold - 1.0) / DP_PSFX(psffit) - 1.0
+ dy = (yold - 1.0) / DP_PSFY(psffit) - 1.0
+ if (IS_INDEFR(mag))
+ mag = DP_PSFMAG (psffit) + DELTA_MAG
+ rel_bright = DAO_RELBRIGHT (psffit, mag)
+ ier = dp_pkfit (dao, Memr[subim], nxpix, nypix, DP_FITRAD(dao),
+ x, y, dx, dy, rel_bright, sky, errmag, chi, sharp, niter)
+ x = x + lowx - 1.0
+ y = y + lowy - 1.0
+ }
+
+ call dp_wout (dao, im, x, y, otx, oty, 1)
+
+ if (ier != PKERR_OK) {
+
+ # Set fitting parameters to INDEF.
+ mag = INDEFR
+ niter = 0
+ errmag = INDEFR
+ chi = INDEFR
+ sharp = INDEFR
+
+ if (DP_VERBOSE(dao) == YES) {
+ switch (ier) {
+ case PKERR_INDEFSKY:
+ call printf (
+ "\tWarning: The sky value for star %d is undefined\n")
+ call pargi (id)
+ case PKERR_NOPIX:
+ call printf (
+ "\tWarning: Too few pixels to fit star %d\n")
+ call pargi (id)
+ case PKERR_SINGULAR:
+ call printf (
+ "\tWarning: Singular matrix computed for star %d\n")
+ call pargi (id)
+ case PKERR_FAINT:
+ call printf ("\tWarning: Star %d too faint\n")
+ call pargi (id)
+ default:
+ call printf (
+ "\tWarning: Unknown error detected for star %d\n")
+ call pargi (id)
+ }
+ }
+
+ } else {
+
+ # Compute the results.
+ mag = DP_PSFMAG (psffit) - 2.5 * log10 (rel_bright)
+ errmag = 1.085736 * errmag / rel_bright
+ if (errmag >= 2.0)
+ errmag = INDEFR
+
+ if (DP_VERBOSE (dao) == YES) {
+ call printf (
+ "\tFIT: Star: %5d X: %8.2f Y: %8.2f Mag: %8.2f Sky =%8.2f\n")
+ call pargi (id)
+ call pargr (otx)
+ call pargr (oty)
+ call pargr (mag)
+ call pargr (sky)
+ }
+ }
+
+ # Get the error code.
+ plen = dp_gpkerr (ier, Memc[perror], SZ_FNAME)
+
+ # Now write the results to the output photometry or rejections
+ # file.
+ if (DP_TEXT(dao) == YES) {
+ if ((tprej != NULL) && (ier != PKERR_OK))
+ call dp_xpkwrite (tprej, id, otx, oty, mag, errmag, sky,
+ niter, chi, sharp, ier, Memc[perror], plen)
+ else
+ call dp_xpkwrite (tpout, id, otx, oty, mag, errmag, sky,
+ niter, chi, sharp, ier, Memc[perror], plen)
+ } else {
+ if ((tprej != NULL) && (ier != PKERR_OK)) {
+ rout_nrow = rout_nrow + 1
+ call dp_tpkwrite (tprej, Memi[colpoint], id, otx, oty, mag,
+ errmag, sky, niter, chi, sharp, ier,
+ Memc[perror], plen, rout_nrow)
+ } else {
+ out_nrow = out_nrow + 1
+ call dp_tpkwrite (tpout, Memi[colpoint], id, otx, oty, mag,
+ errmag, sky, niter, chi, sharp, ier, Memc[perror],
+ plen, out_nrow)
+ }
+ }
+ }
+
+ # Free the text file descriptor.
+ if (ap_text)
+ call pt_kyfree (key)
+
+ # Restore the original fitting radius.
+ DP_FITRAD(dao) = radius
+ DP_SFITRAD(dao) = DP_FITRAD(dao) * DP_SCALE(dao)
+
+ call sfree (sp)
+end
+
+
+# DP_GPKERR -- Set the PEAK task error code string.
+
+int procedure dp_gpkerr (ier, perror, maxch)
+
+int ier # the integer error code
+char perror # the output error code string
+int maxch # the maximum size of the error code string
+
+int plen
+int gstrcpy()
+
+begin
+ switch (ier) {
+ case PKERR_OK:
+ plen = gstrcpy ("No_error", perror, maxch)
+ case PKERR_INDEFSKY:
+ plen = gstrcpy ("Bad_sky", perror, maxch)
+ case PKERR_NOPIX:
+ plen = gstrcpy ("Npix_too_few", perror, maxch)
+ case PKERR_SINGULAR:
+ plen = gstrcpy ("Singular", perror, maxch)
+ case PKERR_FAINT:
+ plen = gstrcpy ("Too_faint", perror, maxch)
+ default:
+ plen = gstrcpy ("No_error", perror, maxch)
+ }
+
+ return (plen)
+end
diff --git a/noao/digiphot/daophot/peak/dppkconfirm.x b/noao/digiphot/daophot/peak/dppkconfirm.x
new file mode 100644
index 00000000..c7dc6333
--- /dev/null
+++ b/noao/digiphot/daophot/peak/dppkconfirm.x
@@ -0,0 +1,25 @@
+# DP_PKCONFIRM -- Procedure to confirm the critical peak parameters.
+
+procedure dp_pkconfirm (dao)
+
+pointer dao # pointer to the daophot structure
+
+begin
+ call printf ("\n")
+
+ # Confirm recentering and sky fitting.
+ call dp_vrecenter (dao)
+ call dp_vfitsky (dao)
+
+ # Confirm the psf radius.
+ call dp_vpsfrad (dao)
+
+ # Confirm the fitting radius.
+ call dp_vfitrad (dao)
+
+ # Confirm the minimum and maximum good data values.
+ call dp_vdatamin (dao)
+ call dp_vdatamax (dao)
+
+ call printf ("\n")
+end
diff --git a/noao/digiphot/daophot/peak/dppkfit.x b/noao/digiphot/daophot/peak/dppkfit.x
new file mode 100644
index 00000000..7818100c
--- /dev/null
+++ b/noao/digiphot/daophot/peak/dppkfit.x
@@ -0,0 +1,411 @@
+include <mach.h>
+include "../lib/daophotdef.h"
+include "../lib/peakdef.h"
+
+# DP_PKFIT -- Do the actual fit.
+
+int procedure dp_pkfit (dao, subim, nx, ny, radius, x, y, dx, dy, rel_bright,
+ sky, errmag, chi, sharp, iter)
+
+pointer dao # pointer to the DAOPHOT Structure
+real subim[nx,ny] # pointer to the image subraster
+int nx, ny # size of the image subraster
+real radius # the fitting radius
+real x, y # initial estimate of the stellar position
+real dx, dy # distance of star from the psf position
+real rel_bright # initial estimate of stellar brightness
+real sky # the sky value associated with this star
+real errmag # error estimate for this star
+real chi # estimated goodness of fit parameter
+real sharp # broadness of the profile compared to the PSF
+int iter # number of iterations needed for a fit.
+
+bool clip, redo
+int i, flag, npix
+pointer psffit, peak
+real ronoise, numer, denom, chiold, sum_weight, noise, wcrit
+int dp_fitbuild()
+
+begin
+ # Get the pointer to the PSF structure.
+ psffit = DP_PSFFIT (dao)
+ peak = DP_PEAK(dao)
+
+ # Initialize the parameters which control the fit.
+
+ chiold = 1.0
+ sharp = INDEFR
+ clip = false
+ ronoise = (DP_READNOISE(dao) / DP_PHOTADU(dao)) ** 2
+
+ call amovkr (1.0, Memr[DP_PKCLAMP(peak)], DP_PKNTERM(peak))
+ call amovkr (0.0, Memr[DP_PKOLDRESULT(peak)], DP_PKNTERM(peak))
+
+ # Iterate until a solution is found.
+
+ for (iter = 1; iter <= DP_MAXITER(dao); iter = iter + 1) {
+
+ # Initialize the matrices and vectors required by the fit.
+
+ chi = 0.0
+ numer = 0.0
+ denom = 0.0
+ sum_weight = 0.0
+ call aclrr (Memr[DP_PKRESID(peak)], DP_PKNTERM(peak))
+ call aclrr (Memr[DP_PKNORMAL(peak)], DP_PKNTERM(peak) *
+ DP_PKNTERM(peak))
+
+ # Set up the critical error limit.
+ if (iter >= WCRIT_NMAX)
+ wcrit = WCRIT_MAX
+ else if (iter >= WCRIT_NMED)
+ wcrit = WCRIT_MED
+ else if (iter >= WCRIT_NMIN)
+ wcrit = WCRIT_MIN
+ else
+ wcrit = MAX_REAL
+
+
+ # Build up the vector of residuals and the normal matrix.
+
+ npix = dp_fitbuild (dao, subim, nx, ny, radius, x, y, dx, dy,
+ rel_bright, sky, chiold, chi, clip, iter,
+ Memr[DP_PKCLAMP(peak)], Memr[DP_PKNORMAL(peak)],
+ Memr[DP_PKRESID(peak)], Memr[DP_PKDERIV(peak)],
+ DP_PKNTERM[(peak)], numer, denom, sum_weight)
+
+ # Return if the iteration was unsuccessful.
+
+ if (npix < MIN_NPIX)
+ return (PKERR_NOPIX)
+
+ # Invert the matrix. Return if inversion was unsuccessful or
+ # if any of the diagonal elements are less or equal to 0.0.
+
+ call invers (Memr[DP_PKNORMAL(peak)], DP_PKNTERM(peak),
+ DP_PKNTERM(peak), flag)
+ if (flag != 0)
+ return (PKERR_SINGULAR)
+ do i = 1, DP_PKNTERM(peak) {
+ if (Memr[DP_PKNORMAL(peak)+(i-1)*DP_PKNTERM(peak)+i-1] <= 0.0)
+ return (PKERR_SINGULAR)
+ }
+ # Solve the matrix.
+
+ call mvmul (Memr[DP_PKNORMAL(peak)], DP_PKNTERM(peak),
+ DP_PKNTERM(peak), Memr[DP_PKRESID(peak)],
+ Memr[DP_PKRESULT(peak)])
+
+ # In the beginning the brightness of the star will not be
+ # permitted to change by more than two magnitudes per
+ # iteration (that is to say if the estimate is getting
+ # brighter, it may not get brighter by more than 525%
+ # per iteration, and if it is getting fainter, it may not
+ # get fainter by more than 84% per iteration). The x and y
+ # coordinates of the centroid will be allowed to change by
+ # no more than one-half pixel per iteration. Any time
+ # that a parameter correction changes sign, the maximum
+ # permissible change in that parameter will be reduced
+ # by a factor of 2.
+
+ # Perform the sign check.
+
+ do i = 1, DP_PKNTERM(peak) {
+ if ((Memr[DP_PKOLDRESULT(peak)+i-1] *
+ Memr[DP_PKRESULT(peak)+i-1]) < 0.0)
+ Memr[DP_PKCLAMP(peak)+i-1] = 0.5 *
+ Memr[DP_PKCLAMP(peak)+i-1]
+ else
+ Memr[DP_PKCLAMP(peak)+i-1] = min (1.0, 1.1 *
+ Memr[DP_PKCLAMP(peak)+i-1])
+ Memr[DP_PKOLDRESULT(peak)+i-1] = Memr[DP_PKRESULT(peak)+i-1]
+ }
+
+ # Compute the new x, y, sky, and magnitude.
+ rel_bright = rel_bright + Memr[DP_PKRESULT(peak)] /
+ (1.0 + max (Memr[DP_PKRESULT(peak)] /
+ (MAX_DELTA_BRIGHTER * rel_bright), -Memr[DP_PKRESULT(peak)] /
+ (MAX_DELTA_FAINTER * rel_bright)) / Memr[DP_PKCLAMP(peak)])
+
+ # Return if the star becomes too faint)
+ if (rel_bright < MIN_REL_BRIGHT)
+ return (PKERR_FAINT)
+
+ if (DP_RECENTER(dao) == YES) {
+ x = x + Memr[DP_PKRESULT(peak)+1] / (1.0 +
+ abs (Memr[DP_PKRESULT(peak)+1]) / (MAX_DELTA_PIX *
+ Memr[DP_PKCLAMP(peak)+1]))
+ y = y + Memr[DP_PKRESULT(peak)+2] / (1.0 +
+ abs (Memr[DP_PKRESULT(peak)+2]) / (MAX_DELTA_PIX *
+ Memr[DP_PKCLAMP(peak)+2]))
+ }
+
+ if (DP_FITSKY(dao) == YES) {
+ noise = sqrt ((abs (sky / DP_PHOTADU(dao)) + ronoise))
+ sky = sky + max (-3.0 * noise, min (Memr[DP_PKRESULT(peak)+
+ DP_PKNTERM(peak)-1], 3.0 * noise))
+ }
+
+ # Force at least one iteration before checking for convergence.
+ if (iter <= 1)
+ next
+
+ # Start on the assumption the fit has converged.
+
+ redo = false
+
+ # Check for convergence. If the most recent computed correction
+ # to the brightness is larger than 0.1% of the brightness or
+ # 0.05 * sigma of the brightness whichever is larger, convergence
+ # has not been achieved.
+
+ errmag = chiold * sqrt (Memr[DP_PKNORMAL(peak)])
+ if (clip) {
+ if (abs (Memr[DP_PKRESULT(peak)]) > max ((MAX_NEW_ERRMAG *
+ errmag), (MAX_NEW_RELBRIGHT1 * rel_bright))) {
+ redo = true
+ } else {
+ if (DP_RECENTER(dao) == YES) {
+ if (max (abs (Memr[DP_PKRESULT(peak)+1]),
+ abs (Memr[DP_PKRESULT(peak)+2])) > MAX_PIXERR1)
+ redo = true
+ }
+ if (DP_FITSKY(dao) == YES) {
+ if (abs (Memr[DP_PKRESULT(peak)+DP_PKNTERM(peak)-1]) >
+ 1.0e-4 * sky)
+ redo = true
+ }
+ }
+ } else {
+ if (abs (Memr[DP_PKRESULT(peak)]) > max (errmag,
+ (MAX_NEW_RELBRIGHT2 * rel_bright))) {
+ redo = true
+ } else {
+ if (DP_RECENTER(dao) == YES) {
+ if (max (abs (Memr[DP_PKRESULT(peak)+1]),
+ abs (Memr[DP_PKRESULT(peak)+2])) > MAX_PIXERR2)
+ redo = true
+ }
+ if (DP_FITSKY(dao) == YES) {
+ if (abs (Memr[DP_PKRESULT(peak)+DP_PKNTERM(peak)-1]) >
+ 1.0e-4 * sky)
+ redo = true
+ }
+ }
+ }
+ if (redo)
+ next
+
+ if ((iter < DP_MAXITER(dao)) && (! clip)) {
+ if (DP_CLIPEXP(dao) > 0)
+ clip = true
+ call aclrr (Memr[DP_PKOLDRESULT(peak)], DP_PKNTERM(peak))
+ call amaxkr (Memr[DP_PKCLAMP(peak)], MAX_CLAMPFACTOR,
+ Memr[DP_PKCLAMP(peak)], DP_PKNTERM(peak))
+ } else {
+ sharp = 1.4427 * Memr[DP_PSFPARS(psffit)] *
+ Memr[DP_PSFPARS(psffit)+1] * numer / (DP_PSFHEIGHT(psffit) *
+ rel_bright * denom)
+ if (sharp <= MIN_SHARP || sharp >= MAX_SHARP)
+ sharp = INDEFR
+ break
+ }
+ }
+
+ if (iter > DP_MAXITER(dao))
+ iter = iter - 1
+ if ((errmag / rel_bright) >= wcrit)
+ return (PKERR_FAINT)
+ else
+ return (PKERR_OK)
+end
+
+
+# DP_FITBUILD -- Build the normal and vector of residuals for the fit.
+
+int procedure dp_fitbuild (dao, subim, nx, ny, radius, x, y, xfrom_psf,
+ yfrom_psf, rel_bright, sky, chiold, chi, clip, iter, clamp, normal,
+ resid, deriv, nterm, numer, denom, sum_weight)
+
+pointer dao # pointer to the DAOPHOT Structure
+real subim[nx,ny] # subimage containing star
+int nx, ny # size of the image subraster
+real radius # the fitting radius
+real x, y # initial estimate of the position
+real xfrom_psf, yfrom_psf # distance from the psf star
+real rel_bright # initial estimate of stellar brightness
+real sky # the sky value associated with this star
+real chiold # previous estimate of gof
+real chi # estimated goodness of fit parameter
+bool clip # clip the weights ?
+int iter # current iteration number
+real clamp[ARB] # clamp array
+real normal[nterm,ARB] # normal matrix
+real resid[ARB] # residual matrix
+real deriv[ARB] # derivative matrix
+int nterm # the number of terms to be fit
+real numer, denom # used in sharpness calculation
+real sum_weight # sum of the weights
+
+int i, j, ix, iy, lowx, lowy, highx, highy, npix
+pointer psffit
+real fitradsq, pererr, peakerr, datamin, datamax, read_noise
+real dx, dy, dxsq, dysq, radsq, dvdx, dvdy, d_pixval
+real pred_pixval, sigma, sigmasq, relerr, weight
+real rhosq, pixval, dfdsig
+
+real dp_usepsf()
+
+begin
+ # Get the pointer to the PSF structure.
+ psffit = DP_PSFFIT (dao)
+
+ # Set up some constants.
+ fitradsq = radius * radius
+ read_noise = (DP_READNOISE(dao) / DP_PHOTADU(dao)) ** 2
+ pererr = 0.01 * DP_FLATERR(dao)
+ peakerr = 0.01 * DP_PROFERR(dao) /
+ (Memr[DP_PSFPARS(psffit)] * Memr[DP_PSFPARS(psffit)+1])
+ if (IS_INDEFR (DP_MINGDATA(dao)))
+ datamin = -MAX_REAL
+ else
+ datamin = DP_MINGDATA(dao)
+ if (IS_INDEFR (DP_MAXGDATA(dao)))
+ datamax = MAX_REAL
+ else
+ datamax = DP_MAXGDATA(dao)
+
+ # Define the size of the subraster to be used in the fit.
+ lowx = max (1, int (x - radius))
+ lowy = max (1, int (y - radius))
+ highx = min (nx, int (x + radius) + 1)
+ highy = min (ny, int (y + radius) + 1)
+
+ npix = 0
+ do iy = lowy, highy {
+
+ dy = real (iy) - y
+ dysq = dy * dy
+
+ do ix = lowx, highx {
+
+ # Is this pixel in the good data range.
+ pixval = subim[ix,iy]
+ if (pixval < datamin || pixval > datamax)
+ next
+
+ # Is this pixel inside the fitting radius?
+ dx = real(ix) - x
+ dxsq = dx * dx
+ radsq = (dxsq + dysq) / fitradsq
+ if ((1.0 - radsq) <= PEAK_EPSILONR)
+ next
+
+ # We have a good pixel within the fitting radius.
+ deriv[1] = dp_usepsf (DP_PSFUNCTION(psffit), dx, dy,
+ DP_PSFHEIGHT(psffit), Memr[DP_PSFPARS(psffit)],
+ Memr[DP_PSFLUT(psffit)], DP_PSFSIZE(psffit),
+ DP_NVLTABLE(psffit), DP_NFEXTABLE(psffit), xfrom_psf,
+ yfrom_psf, dvdx, dvdy)
+ if (((rel_bright * deriv[1] + sky) > datamax) && (iter >= 3))
+ next
+ if (DP_RECENTER(dao) == YES) {
+ deriv[2] = rel_bright * dvdx
+ deriv[3] = rel_bright * dvdy
+ }
+ if (DP_FITSKY(dao) == YES)
+ deriv[nterm] = 1.0
+
+ # Get the residual from the PSF fit and the pixel
+ # intensity as predicted by the fit
+ d_pixval = (pixval - sky) - rel_bright * deriv[1]
+ pred_pixval = max (0.0, pixval - d_pixval)
+
+ # Calculate the anticipated error in the intensity of
+ # in this pixel including READOUT noise, photon statistics
+ # and the error of interpolating within the PSF.
+
+ sigmasq = pred_pixval / DP_PHOTADU (dao) + read_noise +
+ (pererr * pred_pixval) ** 2 + (peakerr *
+ (pred_pixval - sky)) ** 2
+ if (sigmasq <= 0.0)
+ next
+ sigma = sqrt (sigmasq)
+ relerr = abs (d_pixval / sigma)
+
+ # Compute the radial wweighting function.
+ weight = 5.0 / (5.0 + radsq / (1.0 - radsq))
+
+ # Now add this pixel into the quantities which go to make
+ # up the sharpness index.
+ rhosq = dxsq / Memr[DP_PSFPARS(psffit)] ** 2 + dysq /
+ Memr[DP_PSFPARS(psffit)+1] ** 2
+
+ # Include in the sharpness calculation only those pixels
+ # which are within NCORE_SIGMASQ core-sigmasq of the
+ # centroid. This saves time and floating underflows
+ # bu excluding pixels which contribute less than one
+ # part in a million to the fit.
+
+ if (rhosq <= NCORE_SIGMASQ) {
+ rhosq = 0.6931472 * rhosq
+ dfdsig = exp (-rhosq) * (rhosq - 1.0)
+ #pred_pixval = max (0.0, pixval - sky) + sky
+ numer = numer + dfdsig * d_pixval / sigmasq
+ denom = denom + (dfdsig ** 2) / sigmasq
+ }
+
+
+ # Derive the weight of this pixel. First of all the weight
+ # depends on the distance of the pixel from the centroid of
+ # the star --- it is determined from a function which is very
+ # nearly unity for radii much smaller than the fitting radius,
+ # and which goes to zero for radii very near the fitting
+ # radius. Then reject any pixels with 10 sigma residuals
+ # after the first iteration.
+
+ chi = chi + weight * relerr
+ sum_weight = sum_weight + weight
+
+ # Now the weight is scaled to the inverse square of the
+ # expected mean error.
+
+ weight = weight / sigmasq
+
+ # Reduce the weight of a bad pixel. A pixel having a residual
+ # of 2.5 sigma gets reduced to half weight; a pixel having
+ # a residual of of 5.0 sigma gets weight 1/257.
+
+ if (clip)
+ weight = weight / (1.0 + (relerr / (DP_CLIPRANGE(dao) *
+ chiold)) ** DP_CLIPEXP(dao))
+
+ # Now add this pixel into the vector of residuals
+ # and the normal matrix.
+ do i = 1, nterm {
+ resid[i] = resid[i] + d_pixval * deriv[i] * weight
+ do j = 1, nterm {
+ normal[i,j] = normal[i,j] + deriv[i] * deriv[j] *
+ weight
+ }
+ }
+
+ npix = npix + 1
+ }
+ }
+
+ # Compute the goodness of fit index CHI. CHI is pulled toward its
+ # expected value of unity before being stored in CHIOLD to keep the
+ # statistics of a small number of pixels from dominating the error
+ # analysis.
+
+ if (sum_weight > nterm) {
+ chi = CHI_NORM * chi / sqrt (sum_weight * (sum_weight - nterm))
+ chiold = ((sum_weight - MIN_SUMWT) * chi + MIN_SUMWT) / sum_weight
+ } else {
+ chi = 1.0
+ chiold = 1.0
+ }
+
+ return (npix)
+end
diff --git a/noao/digiphot/daophot/peak/dppkwrite.x b/noao/digiphot/daophot/peak/dppkwrite.x
new file mode 100644
index 00000000..97f770bf
--- /dev/null
+++ b/noao/digiphot/daophot/peak/dppkwrite.x
@@ -0,0 +1,365 @@
+include <tbset.h>
+include <time.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/peakdef.h"
+
+# DP_TNEWPEAK -- Create a new output PEAK ST table.
+
+procedure dp_tnewpeak (dao, tp, colpoint)
+
+pointer dao # pointer to the daophot strucuture
+pointer tp # pointer to the output table
+int colpoint[ARB] # array of column pointers
+
+int i
+pointer sp, colnames, colunits, colformat, col_dtype, col_len
+
+begin
+ # Allocate space for the table definition.
+ call smark (sp)
+ call salloc (colnames, PK_NOUTCOL * (SZ_COLNAME + 1), TY_CHAR)
+ call salloc (colunits, PK_NOUTCOL * (SZ_COLUNITS + 1), TY_CHAR)
+ call salloc (colformat, PK_NOUTCOL * (SZ_COLFMT + 1), TY_CHAR)
+ call salloc (col_dtype, PK_NOUTCOL, TY_INT)
+ call salloc (col_len, PK_NOUTCOL, TY_INT)
+
+ # Set up the column definitions.
+ call strcpy (ID, Memc[colnames], SZ_COLNAME)
+ call strcpy (XCENTER, Memc[colnames+SZ_COLNAME+1], SZ_COLNAME)
+ call strcpy (YCENTER, Memc[colnames+2*SZ_COLNAME+2], SZ_COLNAME)
+ call strcpy (MAG, Memc[colnames+3*SZ_COLNAME+3], SZ_COLNAME)
+ call strcpy (MAGERR, Memc[colnames+4*SZ_COLNAME+4], SZ_COLNAME)
+ call strcpy (SKY, Memc[colnames+5*SZ_COLNAME+5], SZ_COLNAME)
+ call strcpy (NITER, Memc[colnames+6*SZ_COLNAME+6], SZ_COLNAME)
+ call strcpy (SHARP, Memc[colnames+7*SZ_COLNAME+7], SZ_COLNAME)
+ call strcpy (CHI, Memc[colnames+8*SZ_COLNAME+8], SZ_COLNAME)
+ call strcpy (PIER, Memc[colnames+9*SZ_COLNAME+9], SZ_COLNAME)
+ call strcpy (PERROR, Memc[colnames+10*SZ_COLNAME+10], SZ_COLNAME)
+
+ # Define the column formats.
+ call strcpy ("%6d", Memc[colformat], SZ_COLFMT)
+ call strcpy ("%10.3f", Memc[colformat+SZ_COLFMT+1], SZ_COLFMT)
+ call strcpy ("%10.3f", Memc[colformat+2*SZ_COLFMT+2], SZ_COLFMT)
+ call strcpy ("%12.3f", Memc[colformat+3*SZ_COLFMT+3], SZ_COLFMT)
+ call strcpy ("%14.3f", Memc[colformat+4*SZ_COLFMT+4], SZ_COLFMT)
+ call strcpy ("%15.7g", Memc[colformat+5*SZ_COLFMT+5], SZ_COLFMT)
+ call strcpy ("%12.3f", Memc[colformat+6*SZ_COLFMT+6], SZ_COLFMT)
+ call strcpy ("%12.3f", Memc[colformat+7*SZ_COLFMT+7], SZ_COLFMT)
+ call strcpy ("%12.3f", Memc[colformat+8*SZ_COLFMT+8], SZ_COLFMT)
+ call strcpy ("%6d", Memc[colformat+9*SZ_COLFMT+9], SZ_COLFMT)
+ call strcpy ("%13s", Memc[colformat+10*SZ_COLFMT+10], SZ_COLFMT)
+
+ # Define the column units.
+ call strcpy ("NUMBER", Memc[colunits], SZ_COLUNITS)
+ call strcpy ("PIXELS", Memc[colunits+SZ_COLUNITS+1], SZ_COLUNITS)
+ call strcpy ("PIXELS", Memc[colunits+2*SZ_COLUNITS+2], SZ_COLUNITS)
+ call strcpy ("MAGNITUDES", Memc[colunits+3*SZ_COLUNITS+3], SZ_COLUNITS)
+ call strcpy ("MAGNITUDES", Memc[colunits+4*SZ_COLUNITS+4], SZ_COLUNITS)
+ call strcpy ("ADU", Memc[colunits+5*SZ_COLUNITS+5], SZ_COLUNITS)
+ call strcpy ("NUMBER", Memc[colunits+6*SZ_COLUNITS+6], SZ_COLUNITS)
+ call strcpy ("NUMBER", Memc[colunits+7*SZ_COLUNITS+7], SZ_COLUNITS)
+ call strcpy ("NUMBER", Memc[colunits+8*SZ_COLUNITS+8], SZ_COLUNITS)
+ call strcpy ("NUMBER", Memc[colunits+9*SZ_COLUNITS+9], SZ_COLUNITS)
+ call strcpy ("PERRORS", Memc[colunits+10*SZ_COLUNITS+10], SZ_COLUNITS)
+
+ # Define the column data types.
+ Memi[col_dtype] = TY_INT
+ Memi[col_dtype+1] = TY_REAL
+ Memi[col_dtype+2] = TY_REAL
+ Memi[col_dtype+3] = TY_REAL
+ Memi[col_dtype+4] = TY_REAL
+ Memi[col_dtype+5] = TY_REAL
+ Memi[col_dtype+6] = TY_INT
+ Memi[col_dtype+7] = TY_REAL
+ Memi[col_dtype+8] = TY_REAL
+ Memi[col_dtype+9] = TY_INT
+ Memi[col_dtype+10] = -13
+
+ # Define the column lengths.
+ do i = 1, PK_NOUTCOL
+ Memi[col_len+i-1] = 1
+
+ # Define and create the table.
+ call tbcdef (tp, colpoint, Memc[colnames], Memc[colunits],
+ Memc[colformat], Memi[col_dtype], Memi[col_len], PK_NOUTCOL)
+ call tbtcre (tp)
+
+ # Write out some header parameters.
+ call dp_tpeakpars (dao, tp)
+
+ call sfree (sp)
+end
+
+
+define PK_NAME1STR "#N%4tID%10tXCENTER%20tYCENTER%30tMAG%42tMERR%56tMSKY%71t\
+NITER%80t\\\n"
+define PK_UNIT1STR "#U%4t##%10tpixels%20tpixels%30tmagnitudes%42t\
+magnitudes%56tcounts%71t##%80t\\\n"
+define PK_FORMAT1STR "#F%4t%%-9d%10t%%-10.3f%20t%%-10.3f%30t%%-12.3f%42t\
+%%-14.3f%56t%%-15.7g%71t%%-6d%80t \n"
+
+define PK_NAME2STR "#N%12tSHARPNESS%24tCHI%36tPIER%42tPERROR%80t\\\n"
+define PK_UNIT2STR "#U%12t##%24t##%36t##%42tperrors%80t\\\n"
+define PK_FORMAT2STR "#F%12t%%-23.3f%24t%%-12.3f%36t%%-6d%42t%%-13s%80t \n"
+
+
+# DP_XNEWPEAK -- Create a new PEAK output text file.
+
+procedure dp_xnewpeak (dao, tp)
+
+pointer dao # pointer to the daophot structure
+int tp # the output file descriptor
+
+begin
+ # Write out some header parameters.
+ call dp_xpeakpars (dao, tp)
+
+ # Print out the banner file.
+ call fprintf (tp, "#\n")
+ call fprintf (tp, PK_NAME1STR)
+ call fprintf (tp, PK_UNIT1STR)
+ call fprintf (tp, PK_FORMAT1STR)
+ call fprintf (tp, "#\n")
+ call fprintf (tp, PK_NAME2STR)
+ call fprintf (tp, PK_UNIT2STR)
+ call fprintf (tp, PK_FORMAT2STR)
+ call fprintf (tp, "#\n")
+end
+
+
+# DP_TPEAKPARS -- Add parameters to the header of the PEAK ST table.
+
+procedure dp_tpeakpars (dao, tp)
+
+pointer dao # pointer to the daophot structure
+pointer tp # pointer to the output table
+
+pointer sp, psffit, outstr, date, time
+bool itob()
+int envfind()
+
+begin
+ # Define some daophot pointers.
+ psffit = DP_PSFFIT(dao)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+ call salloc (date, SZ_DATE, TY_CHAR)
+ call salloc (time, SZ_DATE, TY_CHAR)
+
+ # Write the id.
+ if (envfind ("version", Memc[outstr], SZ_LINE) <= 0)
+ call strcpy ("NOAO/IRAF", Memc[outstr], SZ_LINE)
+ call dp_rmwhite (Memc[outstr], Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "IRAF", Memc[outstr])
+ if (envfind ("userid", Memc[outstr], SZ_LINE) <= 0)
+ call tbhadt (tp, "USER", Memc[outstr])
+ call gethost (Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "HOST", Memc[outstr])
+ call dp_date (Memc[date], Memc[time], SZ_DATE)
+ call tbhadt (tp, "DATE", Memc[date])
+ call tbhadt (tp, "TIME", Memc[time])
+ call tbhadt (tp, "PACKAGE", "daophot")
+ call tbhadt (tp, "TASK", "peak")
+
+ # Write out the files names.
+ call dp_imroot (DP_INIMAGE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "IMAGE", Memc[outstr])
+ call dp_froot (DP_INPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "PHOTFILE", Memc[outstr])
+ call dp_imroot (DP_PSFIMAGE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "PSFIMAGE", Memc[outstr])
+ call dp_froot (DP_OUTPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "PEAKFILE", Memc[outstr])
+ if (DP_OUTREJFILE(dao) == EOS)
+ call tbhadt (tp, "REJFILE", "\"\"")
+ else {
+ call dp_froot (DP_OUTREJFILE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "REJFILE", Memc[outstr])
+ }
+
+ # Define the data characteristics.
+ call tbhadr (tp, "SCALE", DP_SCALE(dao))
+ call tbhadr (tp, "DATAMIN", DP_MINGDATA(dao))
+ call tbhadr (tp, "DATAMAX", DP_MAXGDATA(dao))
+ call tbhadr (tp, "GAIN", DP_PHOTADU(dao))
+ call tbhadr (tp, "READNOISE", DP_READNOISE(dao))
+
+ # Define the observing parameters.
+ call tbhadt (tp, "OTIME", DP_OTIME(dao))
+ call tbhadr (tp, "XAIRMASS", DP_XAIRMASS(dao))
+ call tbhadt (tp, "IFILTER", DP_IFILTER(dao))
+
+ # Define the fitting parameters.
+ call tbhadb (tp, "RECENTER", itob (DP_RECENTER(dao)))
+ call tbhadb (tp, "FITSKY", itob (DP_FITSKY(dao)))
+ call tbhadr (tp, "PSFRAD", DP_SPSFRAD(dao))
+ call tbhadr (tp, "FITRAD", DP_SFITRAD(dao))
+ call tbhadr (tp, "PSFMAG", DP_PSFMAG(psffit))
+ call tbhadi (tp, "MAXITER", DP_MAXITER(dao))
+ call tbhadr (tp, "FLATERROR", DP_FLATERR(dao))
+ call tbhadr (tp, "PROFERROR", DP_PROFERR(dao))
+ call tbhadi (tp, "CLIPEXP", DP_CLIPEXP(dao))
+ call tbhadr (tp, "CLIPRANGE", DP_CLIPRANGE(dao))
+ #call tbhadi (tp, "MAXNSTAR", DP_MAXNSTAR(dao))
+
+ call sfree(sp)
+end
+
+
+# DP_XPEAKPARS -- Add parameters to the header of the output PEAK text file.
+
+procedure dp_xpeakpars (dao, tp)
+
+pointer dao # pointer to the daophot structure
+int tp # the output file descriptor
+
+pointer sp, psffit, outstr, date, time
+bool itob()
+int envfind()
+
+begin
+ # Define some daophot pointers.
+ psffit = DP_PSFFIT(dao)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+ call salloc (date, SZ_DATE, TY_CHAR)
+ call salloc (time, SZ_DATE, TY_CHAR)
+
+ # Write the id.
+ if (envfind ("version", Memc[outstr], SZ_LINE) <= 0)
+ call strcpy ("NOAO/IRAF", Memc[outstr], SZ_LINE)
+ call dp_rmwhite (Memc[outstr], Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "IRAF", Memc[outstr], "version", "")
+ if (envfind ("userid", Memc[outstr], SZ_LINE) <= 0)
+ call dp_sparam (tp, "USER", Memc[outstr], "name", "")
+ call gethost (Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "HOST", Memc[outstr], "computer", "")
+ call dp_date (Memc[date], Memc[time], SZ_DATE)
+ call dp_sparam (tp, "DATE", Memc[date], "yyyy-mm-dd", "")
+ call dp_sparam (tp, "TIME", Memc[time], "hh:mm:ss", "")
+ call dp_sparam (tp, "PACKAGE", "daophot", "name", "")
+ call dp_sparam (tp, "TASK", "peak", "name", "")
+
+ # Write out the files names.
+ call dp_imroot (DP_INIMAGE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "IMAGE", Memc[outstr], "imagename", "")
+ call dp_froot (DP_INPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "PHOTFILE", Memc[outstr], "filename", "")
+ call dp_imroot (DP_PSFIMAGE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "PSFIMAGE", Memc[outstr], "imagename", "")
+ call dp_froot (DP_OUTPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "PEAKFILE", Memc[outstr], "filename", "")
+
+ if (DP_OUTREJFILE(dao) == EOS)
+ call dp_sparam (tp, "REJFILE", "\"\"", "filename", "")
+ else {
+ call dp_froot (DP_OUTREJFILE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "REJFILE", Memc[outstr], "filename", "")
+ }
+
+ # Define the data characteristics.
+ call dp_rparam (tp, "SCALE", DP_SCALE(dao), "units/pix", "")
+ call dp_rparam (tp, "DATAMIN", DP_MINGDATA(dao), "counts", "")
+ call dp_rparam (tp, "DATAMAX", DP_MAXGDATA(dao), "counts", "")
+ call dp_rparam (tp, "GAIN", DP_PHOTADU(dao), "e-/adu", "")
+ call dp_rparam (tp, "READNOISE", DP_READNOISE(dao), "electrons", "")
+
+ # Define the observing parameters.
+ call dp_sparam (tp, "OTIME", DP_OTIME(dao), "timeunit", "")
+ call dp_rparam (tp, "XAIRMASS", DP_XAIRMASS(dao), "number", "")
+ call dp_sparam (tp, "IFILTER", DP_IFILTER(dao), "filter", "")
+
+ # Define the fitting parameters.
+ call dp_bparam (tp, "RECENTER", itob (DP_RECENTER(dao)), "switch", "")
+ call dp_bparam (tp, "FITSKY", itob (DP_FITSKY(dao)), "switch", "")
+ call dp_rparam (tp, "PSFRAD", DP_SPSFRAD(dao), "scaleunit", "")
+ call dp_rparam (tp, "FITRAD", DP_SFITRAD(dao), "scaleunit", "")
+ call dp_rparam (tp, "PSFMAG", DP_PSFMAG(psffit), "magnitudes", "")
+ call dp_iparam (tp, "MAXITER", DP_MAXITER(dao), "number", "")
+ call dp_rparam (tp, "FLATERROR", DP_FLATERR(dao), "percentage", "")
+ call dp_rparam (tp, "PROFERROR", DP_PROFERR(dao), "percentage", "")
+ call dp_iparam (tp, "CLIPEXP", DP_CLIPEXP(dao), "number", "")
+ call dp_rparam (tp, "CLIPRANGE", DP_CLIPRANGE(dao), "sigma", "")
+ #call dp_iparam (tp, "MAXNSTAR", DP_MAXNSTAR(dao), "number", "")
+
+ call sfree(sp)
+end
+
+
+# DP_TPKWRITE -- Write the output photometry record to a PEAK ST table.
+
+procedure dp_tpkwrite (tpout, colpoint, id, x, y, mag, errmag, sky, niter, chi,
+ sharp, pier, perror, plen, star)
+
+pointer tpout # pointer to the output table
+int colpoint[ARB] # array of column pointers
+int id # id of the star
+real x, y # position of the star
+real mag # magnitude of the star
+real errmag # error magnitude of the star
+real sky # value of sky
+int niter # number of iterations
+real chi # chi squared value
+real sharp # sharpness characteristic
+int pier # the error code
+char perror[ARB] # the error string
+int plen # the length of the error code string
+int star # row number
+
+begin
+ call tbrpti (tpout, colpoint[1], id, 1, star)
+ call tbrptr (tpout, colpoint[2], x, 1, star)
+ call tbrptr (tpout, colpoint[3], y, 1, star)
+ call tbrptr (tpout, colpoint[4], mag, 1, star)
+ call tbrptr (tpout, colpoint[5], errmag, 1, star)
+ call tbrptr (tpout, colpoint[6], sky, 1, star)
+ call tbrpti (tpout, colpoint[7], niter, 1, star)
+ call tbrptr (tpout, colpoint[8], sharp, 1, star)
+ call tbrptr (tpout, colpoint[9], chi, 1, star)
+ call tbrpti (tpout, colpoint[10], pier, 1, star)
+ call tbrptt (tpout, colpoint[11], perror, plen, 1, star)
+end
+
+
+define PK_DATA1STR "%-9d%10t%-10.3f%20t%-10.3f%30t%-12.3f%42t%-14.3f%56t\
+%-15.7g%71t%-6d%80t\\\n"
+define PK_DATA2STR "%12t%-12.3f%24t%-12.3f%36t%-6d%42t%-13.13s%80t \n"
+
+# DP_XPKWRITE -- Write the output photometry record to a PEAK text file.
+
+procedure dp_xpkwrite (tpout, id, x, y, mag, errmag, sky, niter, chi, sharp,
+ pier, perror, plen)
+
+int tpout # the output file descriptor
+int id # id of the star
+real x, y # position of the star
+real mag # magnitude of the star
+real errmag # error magnitude of the star
+real sky # value of sky
+int niter # number of iterations
+real chi # chi squared value
+real sharp # sharpness characteristic
+int pier # the error code
+char perror[ARB] # the error string
+int plen # the length of the error code string
+
+begin
+ call fprintf (tpout, PK_DATA1STR)
+ call pargi (id)
+ call pargr (x)
+ call pargr (y)
+ call pargr (mag)
+ call pargr (errmag)
+ call pargr (sky)
+ call pargi (niter)
+ call fprintf (tpout, PK_DATA2STR)
+ call pargr (sharp)
+ call pargr (chi)
+ call pargi (pier)
+ call pargstr (perror)
+end
diff --git a/noao/digiphot/daophot/peak/dprrphot.x b/noao/digiphot/daophot/peak/dprrphot.x
new file mode 100644
index 00000000..36aed88f
--- /dev/null
+++ b/noao/digiphot/daophot/peak/dprrphot.x
@@ -0,0 +1,98 @@
+include "../lib/apseldef.h"
+
+# DP_TPKINIT -- Procedure to initialize for reading the "standard" fields from
+# a photometry table. The "standard" fields being ID, X, Y, MAG, ERR, and SKY
+
+procedure dp_tpkinit (tp, colpoint)
+
+pointer tp # the table descriptor
+pointer colpoint[ARB] # the column descriptor
+
+begin
+ # Get the results one by one
+ # First the ID
+ call tbcfnd (tp, ID, colpoint[1], 1)
+ if (colpoint[1] == NULL) {
+ call eprintf ("Column %s not found\n")
+ call pargstr (ID)
+ }
+
+ # Then the position
+ call tbcfnd (tp, XCENTER, colpoint[2], 1)
+ if (colpoint[2] == NULL) {
+ call eprintf ("Column %s not found\n")
+ call pargstr (XCENTER)
+ }
+
+ call tbcfnd (tp, YCENTER, colpoint[3], 1)
+ if (colpoint[3] == NULL) {
+ call eprintf ("Column %s not found\n")
+ call pargstr (YCENTER)
+ }
+
+ # Now the Magnitude
+ call tbcfnd (tp, MAG, colpoint[4], 1)
+ if (colpoint[4] == NULL) # No column
+ call tbcfnd (tp, APMAG, colpoint[4], 1)
+ if (colpoint[4] == NULL) {
+ call eprintf ("Column %s not found\n")
+ call pargstr (APMAG)
+ }
+
+ # The sky
+ call tbcfnd (tp, SKY, colpoint[5], 1)
+ if (colpoint[5] == NULL)
+ call tbcfnd (tp, SKY, colpoint[5], 1)
+ if (colpoint[5] == NULL) {
+ call eprintf ("Column %s not found\n")
+ call pargstr (SKY)
+ }
+end
+
+
+# DP_RRPHOT -- Fetch the photometry for a single star from either a
+# table or a text photometry file.
+
+int procedure dp_rrphot (tp, key, fields, indices, id, x, y, sky, mag,
+ instar, nrow)
+
+int tp # the input file descriptor
+pointer key # pointer to text apphot structure
+char fields[ARB] # character fields
+int indices[ARB] # columns pointers
+int id # star id
+real x # x center value
+real y # y center value
+real sky # sky value
+real mag # magnitude
+int instar # current record
+int nrow # maximum number of rows for ST table
+
+bool nullflag
+int nrec
+int dp_apsel()
+
+begin
+ # If nrow is 0 the file file is a text file otherwise it is a table.
+
+ if (nrow == 0) {
+
+ nrec = dp_apsel (key, tp, fields, indices, id, x, y, sky, mag)
+ if (nrec != EOF)
+ instar = instar + 1
+
+ } else if ((instar + 1) <= nrow) {
+
+ instar = instar + 1
+ call tbrgti (tp, indices[1], id, nullflag, 1, instar)
+ call tbrgtr (tp, indices[2], x, nullflag, 1, instar)
+ call tbrgtr (tp, indices[3], y, nullflag, 1, instar)
+ call tbrgtr (tp, indices[4], mag, nullflag, 1, instar)
+ call tbrgtr (tp, indices[5], sky, nullflag, 1, instar)
+ nrec = instar
+
+ } else
+ nrec = EOF
+
+ return (nrec)
+end
diff --git a/noao/digiphot/daophot/peak/mkpkg b/noao/digiphot/daophot/peak/mkpkg
new file mode 100644
index 00000000..f3570728
--- /dev/null
+++ b/noao/digiphot/daophot/peak/mkpkg
@@ -0,0 +1,22 @@
+# PEAK task
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ dpmempk.x ../lib/daophotdef.h ../lib/peakdef.h
+ dppeakphot.x <imhdr.h> <tbset.h> \
+ ../lib/daophotdef.h ../lib/apseldef.h \
+ ../lib/peakdef.h
+ dppkconfirm.x
+ dppkfit.x <mach.h> ../lib/daophotdef.h \
+ ../lib/peakdef.h
+ dppkwrite.x <tbset.h> <time.h> \
+ ../lib/daophotdef.h ../lib/apseldef.h \
+ ../lib/peakdef.h
+ dprrphot.x ../lib/apseldef.h
+ t_peak.x <fset.h> <imhdr.h> \
+ ../lib/daophotdef.h
+ ;
diff --git a/noao/digiphot/daophot/peak/t_peak.x b/noao/digiphot/daophot/peak/t_peak.x
new file mode 100644
index 00000000..2022fe16
--- /dev/null
+++ b/noao/digiphot/daophot/peak/t_peak.x
@@ -0,0 +1,299 @@
+include <fset.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+
+# T_PEAK -- Procedure to fit the PSF to single stars.
+
+procedure t_peak ()
+
+pointer image # name of the image
+pointer photfile # input photometry file
+pointer psfimage # the PSF image
+pointer peakfile # output PEAK photometry file
+pointer rejfile # output PEAK rejections file
+
+pointer sp, im, psfim, outfname, dao, str
+int apd, root, verbose, verify, cache, update, pkfd, rejfd
+int imlist, limlist, alist, lalist, pimlist, lpimlist, olist, lolist
+int rlist, lrlist, wcs, req_size, old_size, buf_size, memstat
+bool ap_text
+
+pointer immap(), tbtopn()
+int open(), fnldir(), strlen(), strncmp(), fstati(), btoi()
+int access(), imtopen(), imtlen(), imtgetim(), fntopnb(), fntlenb()
+int fntgfnb(), clgwrd(), sizeof(), dp_memstat()
+bool clgetb(), itob()
+
+begin
+ # Set the standard output to flush on newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get some working memory.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (photfile, SZ_FNAME, TY_CHAR)
+ call salloc (psfimage, SZ_FNAME, TY_CHAR)
+ call salloc (peakfile, SZ_FNAME, TY_CHAR)
+ call salloc (rejfile, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Get the various task parameters
+ call clgstr ("image", Memc[image], SZ_FNAME)
+ call clgstr ("photfile", Memc[photfile], SZ_FNAME)
+ call clgstr ("psfimage", Memc[psfimage], SZ_FNAME)
+ call clgstr ("peakfile", Memc[peakfile], SZ_FNAME)
+ call clgstr ("rejfile", Memc[rejfile], SZ_FNAME)
+ verbose = btoi (clgetb ("verbose"))
+ verify = btoi (clgetb ("verify"))
+ update = btoi (clgetb ("update"))
+ cache = btoi (clgetb ("cache"))
+
+ # Get the lists.
+ imlist = imtopen (Memc[image])
+ limlist = imtlen (imlist)
+ alist = fntopnb (Memc[photfile], NO)
+ lalist = fntlenb (alist)
+ pimlist = imtopen (Memc[psfimage])
+ lpimlist = imtlen (pimlist)
+ olist = fntopnb (Memc[peakfile], NO)
+ lolist = fntlenb (olist)
+ rlist = fntopnb (Memc[rejfile], NO)
+ lrlist = fntlenb (rlist)
+
+ # Test that the lengths of the photometry file, psf image, and
+ # output file lists are the same as the length of the input image
+ # list.
+
+ if ((limlist != lalist) && (strncmp (Memc[photfile],
+ DEF_DEFNAME, DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (rlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatable image and input photometry file list lengths")
+ }
+
+ if ((limlist != lpimlist) && (strncmp (Memc[psfimage],
+ DEF_DEFNAME, DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (rlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatable image and psf image list lengths")
+ }
+
+ if ((limlist != lolist) && (strncmp (Memc[peakfile],
+ DEF_DEFNAME, DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (rlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatable image and output photometry file list lengths")
+ }
+
+ if ((lrlist != 0) && (limlist != lolist) && (strncmp (Memc[rejfile],
+ DEF_DEFNAME, DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (rlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatable image and rejections file list lengths")
+ }
+
+ # Initialize the DAOPHOT structure, and get the pset parameters.
+ call dp_gppars (dao)
+ call dp_seti (dao, VERBOSE, verbose)
+
+ # Verify the standard algorithm parameters.
+ if (verify == YES) {
+ call dp_pkconfirm (dao)
+ if (update == YES)
+ call dp_pppars (dao)
+ }
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_FNAME, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_FNAME, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSOUT, wcs)
+ wcs = clgwrd ("wcspsf", Memc[str], SZ_FNAME, WCSPSFSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the psf coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSPSF, wcs)
+
+ # Initialize the PSF structure.
+ call dp_fitsetup (dao)
+
+ # Initialize the PEAK structure.
+ call dp_pksetup (dao)
+
+ # Loop over the list of images.
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open the image.
+ im = immap (Memc[image], READ_ONLY, 0)
+ call dp_imkeys (dao, im)
+ call dp_sets (dao, INIMAGE, Memc[image])
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = dp_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call dp_pcache (im, INDEFI, buf_size)
+
+ # Open the input photometry file.
+ if (fntgfnb (alist, Memc[photfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[photfile], SZ_FNAME)
+ root = fnldir (Memc[photfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[photfile+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[photfile]))
+ call dp_inname (Memc[image], Memc[outfname], "mag",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[photfile], Memc[outfname], SZ_FNAME)
+ ap_text = itob (access (Memc[outfname], 0, TEXT_FILE))
+ if (ap_text)
+ apd = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ else
+ apd = tbtopn (Memc[outfname], READ_ONLY, 0)
+ call dp_sets (dao, INPHOTFILE, Memc[outfname])
+
+ # Read in the PSF function.
+ if (imtgetim (pimlist, Memc[psfimage], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[psfimage], SZ_FNAME)
+ root = fnldir (Memc[psfimage], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[psfimage+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[psfimage]))
+ call dp_iimname (Memc[image], Memc[outfname], "psf",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[psfimage], Memc[outfname], SZ_FNAME)
+ psfim = immap (Memc[outfname], READ_ONLY, 0)
+ call dp_readpsf (dao, psfim)
+ call dp_sets (dao, PSFIMAGE, Memc[outfname])
+
+ # Open the output photometry file. If the output is "default",
+ # dir$default or a directory specification then the extension .pk
+ # is added to the image name and a suitable version number is
+ # appended to the output name.
+
+ if (fntgfnb (olist, Memc[peakfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[peakfile], SZ_FNAME)
+ root = fnldir (Memc[peakfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[peakfile + root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[peakfile]))
+ call dp_outname (Memc[image], Memc[outfname], "pk",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[peakfile], Memc[outfname], SZ_FNAME)
+ if (DP_TEXT(dao) == YES)
+ pkfd = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ else
+ pkfd = tbtopn (Memc[outfname], NEW_FILE, 0)
+ call dp_sets (dao, OUTPHOTFILE, Memc[outfname])
+
+ # Open the output rejections file if any are defined. If the
+ # output is "default", dir$default or a directory specification
+ # then the extension .prj is added to the image name and a
+ # suitable version number is appended to the output file name.
+
+ if (lrlist <= 0) {
+ rejfd = NULL
+ Memc[outfname] = EOS
+ } else {
+ if (fntgfnb (rlist, Memc[rejfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[rejfile], SZ_FNAME)
+ root = fnldir (Memc[rejfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[rejfile+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[rejfile]))
+ call dp_outname (Memc[image], Memc[outfname], "prj",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[rejfile], Memc[outfname], SZ_FNAME)
+ if (DP_TEXT(dao) == YES)
+ rejfd = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ else
+ rejfd = tbtopn (Memc[outfname], NEW_FILE, 0)
+ }
+ call dp_sets (dao, OUTREJFILE, Memc[outfname])
+
+ # Now go and do the PSF fitting.
+ call dp_peakphot (dao, im, apd, pkfd, rejfd, ap_text)
+
+ # Close the input image.
+ call imunmap (im)
+
+ # Close the input photometry file.
+ if (ap_text)
+ call close (apd)
+ else
+ call tbtclo (apd)
+
+ # Close the PSF image.
+ call imunmap (psfim)
+
+ # Close the output photometry file.
+ if (DP_TEXT(dao) == YES)
+ call close (pkfd)
+ else
+ call tbtclo (pkfd)
+
+ # Close the output rejections file.
+ if (rejfd != NULL) {
+ if (DP_TEXT(dao) == YES)
+ call close (rejfd)
+ else
+ call tbtclo (rejfd)
+ }
+
+ # Uncache memory.
+ call fixmem (old_size)
+
+ }
+
+ # Close the image/file lists.
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (rlist)
+
+ # Free the PEAK structure.
+ call dp_pkclose (dao)
+
+ # Free the PSF structure.
+ call dp_fitclose (dao)
+
+ # Free the daophot structure.
+ call dp_free (dao)
+
+ call sfree(sp)
+end
diff --git a/noao/digiphot/daophot/pexamine.par b/noao/digiphot/daophot/pexamine.par
new file mode 100644
index 00000000..7b3d133a
--- /dev/null
+++ b/noao/digiphot/daophot/pexamine.par
@@ -0,0 +1,20 @@
+# The PEXAMINE task parameter set
+
+input,s,a,,,,"Name of the input catalog"
+output,s,a,"",,,"Name of the edited output catalog"
+image,s,a,"",,,Name of the image corresponding to the input catalog
+deletions,s,h,"",,,"Name of the output catalog for deleted entries"
+photcolumns,s,h,"daophot",,,"Names of the standard photometry columns"
+xcolumn,s,h,mag,,,"Catalog column which is the X axis of X-Y plot"
+ycolumn,s,h,merr,,,"Catalog column which is the Y axis of X-Y plot"
+hcolumn,s,h,mag,,,"Catalog column which is to be binned"
+xposcolumn,s,h,"xcenter",,,"Name of the x coordinate column"
+yposcolumn,s,h,"ycenter",,,"Name of the y coordinate column"
+usercolumns,s,h,"",,,"Names of additional user selected columns"
+first_star,i,h,1,1,,First star in the catalog to load
+max_nstars,i,h,10000,1,,Maximum number of stars to load
+use_display,b,h,yes,,,Use the image display?
+match_radius,r,h,2.0,,,Matching radius for positional coincidence on display
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor [x y wcs] key [cmd]"
+graphics,s,h,)_.graphics,,,The graphics device
diff --git a/noao/digiphot/daophot/pfmerge.par b/noao/digiphot/daophot/pfmerge.par
new file mode 100644
index 00000000..90ef9507
--- /dev/null
+++ b/noao/digiphot/daophot/pfmerge.par
@@ -0,0 +1,6 @@
+# Parameters for the PFMERGE task
+
+inphotfiles,f,a,,,,"List of input photometry files to be merged"
+outphotfile,f,a,,,,"Output photometry file"
+verbose,b,h,)_.verbose,,,Print pfmerge messages?
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/phot.par b/noao/digiphot/daophot/phot.par
new file mode 100644
index 00000000..99f1896d
--- /dev/null
+++ b/noao/digiphot/daophot/phot.par
@@ -0,0 +1,24 @@
+# PHOT parameters
+
+image,f,a,,,,"Input image(s)"
+coords,f,a,"default",,,"Input coordinate list(s) (default: image.coo.?)"
+output,f,a,"default",,,"Output photometry file(s) (default: image.mag.?)"
+skyfile,f,a,"",,,"Input sky value file(s)"
+plotfile,f,h,"",,,"Output plot metacode file"
+datapars,pset,h,"",,,"Data dependent parameters"
+centerpars,pset,h,"",,,"Centering parameters"
+fitskypars,pset,h,"",,,"Sky fitting parameters"
+photpars,pset,h,"",,,"Photometry parameters"
+interactive,b,h,no,,,"Interactive mode?"
+radplots,b,h,no,,,Plot the radial profiles?
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor: [x y wcs] key [cmd]"
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the input image pixels in memory?"
+verify,b,h,)_.verify,,,"Verify critical phot parameters?"
+update,b,h,)_.update,,,"Update critical phot parameters?"
+verbose,b,h,)_.verbose,,,"Print phot messages?"
+graphics,s,h,)_.graphics,,,"Graphics device"
+display,s,h,)_.display,,,"Display device"
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/photpars.par b/noao/digiphot/daophot/photpars.par
new file mode 100644
index 00000000..bf25672c
--- /dev/null
+++ b/noao/digiphot/daophot/photpars.par
@@ -0,0 +1,7 @@
+# PHOTPARS Parameter File
+
+weighting,s,h,constant,"|constant|",,Photometric weighting scheme
+apertures,s,h,"3.",,,List of aperture radii in scale units
+zmag,r,h,25.,,,Zero point of magnitude scale
+mkapert,b,h,no,,,Draw apertures on the display
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/psf.par b/noao/digiphot/daophot/psf.par
new file mode 100644
index 00000000..888dbeb9
--- /dev/null
+++ b/noao/digiphot/daophot/psf.par
@@ -0,0 +1,27 @@
+# Parameters for the PSF task
+
+image,f,a,,,,"Input image(s) for which to build PSF"
+photfile,f,a,default,,,"Input photometry file(s) (default: image.mag.?)"
+pstfile,f,a,"",,,"Input psf star list(s) (default: image.pst.?)"
+psfimage,f,a,default,,,"Output PSF image(s) (default: image.psf.?)"
+opstfile,f,a,default,,,"Output PSF star list(s) (default: image.pst.?)"
+groupfile,f,a,default,,,"Output PSF star group file(s) (default: image.psg.?)"
+plotfile,f,h,"",,,"Output plot metacode file"
+datapars,pset,h,"",,,"Data dependent parameters"
+daopars,pset,h,"",,,"Psf fitting parameters"
+matchbyid,b,h,yes,,,"Match psf star list to photometry file(s) by id number?"
+interactive,b,h,yes,,,"Compute the psf interactively?"
+mkstars,b,h,no,,,"Mark deleted and accepted psf stars?"
+showplots,b,h,yes,,,"Show plots of PSF stars?"
+plottype,s,h,"mesh","|mesh|contour|radial|",,"Default plot type (mesh|contour|radial)"
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor: [x y wcs] key [cmd]"
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the input image pixels in memory?"
+verify,b,h,)_.verify,,,"Verify critical psf parameters?"
+update,b,h,)_.update,,,"Update critical psf parameters?"
+verbose,b,h,)_.verbose,,,"Print psf messages?"
+graphics,s,h,)_.graphics,,,"Graphics device"
+display,s,h,)_.display,,,"Display device"
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/psf/README b/noao/digiphot/daophot/psf/README
new file mode 100644
index 00000000..4d390489
--- /dev/null
+++ b/noao/digiphot/daophot/psf/README
@@ -0,0 +1,2 @@
+This directory contains the routines for making up the PSF to be used by
+the fitting routines in the PSF.
diff --git a/noao/digiphot/daophot/psf/dpaddstar.x b/noao/digiphot/daophot/psf/dpaddstar.x
new file mode 100644
index 00000000..c723a2b3
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dpaddstar.x
@@ -0,0 +1,188 @@
+include <mach.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+include "../lib/psfdef.h"
+
+# DP_ADDSTAR -- Add the star at the given position to the PSF if it exists and
+# passes the selection criteria.
+
+int procedure dp_addstar (dao, im, x, y, mag, idnum, gd, mgd, showplots)
+
+pointer dao # pointer to daophot structure
+pointer im # pointer to image
+real x, y # position of proposed PSF star
+real mag # mag of proposed PSF star
+int idnum # id number of desired star
+pointer gd # pointer to the graphics stream
+pointer mgd # pointer to the metacode descriptor
+bool showplots # show plots?
+
+real tx, ty, logood, higood
+pointer srim
+int x1, x2, y1, y2, starnum, saturated
+bool star_ok
+
+real dp_statr(), dp_pstatr()
+pointer dp_psubrast()
+int dp_locstar(), dp_idstar(), dp_stati(), dp_pstati()
+
+begin
+ # Convert coordinates for display.
+ if (showplots)
+ call dp_ltov (im, x, y, tx, ty, 1)
+ else
+ call dp_wout (dao, im, x, y, tx, ty, 1)
+
+ # Check that the position of the star is within the image.
+ if (idnum == 0 && (x < 1.0 || x > real (IM_LEN(im,1)) || y < 1.0 || y >
+ real (IM_LEN(im,2)))) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("Star at %g,%g is outside the image\n")
+ call pargr (tx)
+ call pargr (ty)
+ }
+ return (ERR)
+ }
+
+ # Find the star in the aperture photometry list
+ if (idnum == 0)
+ starnum = dp_locstar (dao, im, x, y)
+ else
+ starnum = dp_idstar (dao, im, idnum)
+ if (starnum == 0) {
+ if (DP_VERBOSE(dao) == YES) {
+ if (idnum > 0) {
+ call printf ("Star %d not found in the photometry file\n")
+ call pargi (idnum)
+ } else {
+ call printf (
+ "Star at %g,%g not found in the photometry file\n")
+ call pargr (tx)
+ call pargr (ty)
+ }
+ }
+ return (ERR)
+ } else if (starnum < 0) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (
+ "Star %d is too near the edge of the image\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+ return (ERR)
+ } else if (starnum <= dp_pstati (dao, PNUM)) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("Star %d is already a PSF star\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+ return (ERR)
+ }
+
+ # Check for INDEF valued sky.
+ if (IS_INDEFR (dp_pstatr (dao, CUR_PSFSKY))) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("Star %d has an undefined sky value\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+ return (ERR)
+ }
+
+
+ logood = dp_statr (dao, MINGDATA)
+ if (IS_INDEFR(logood))
+ logood = -MAX_REAL
+ higood = dp_statr (dao, MAXGDATA)
+ if (IS_INDEFR(higood))
+ higood = MAX_REAL
+
+ # Get the data subraster, check for saturation and bad pixels,
+ # and compute the min and max data values inside the subraster.
+ srim = dp_psubrast (dao, im, logood, higood, x1, x2, y1, y2, saturated)
+ if (srim == NULL) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (
+ "Star %d has low bad pixels inside fitrad\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+ return (ERR)
+ }
+
+ # Check for saturation.
+ if (saturated == YES && dp_stati (dao, SATURATED) == NO) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (
+ "Star %d has high bad pixels inside fitrad\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+ call mfree (srim, TY_REAL)
+ return (ERR)
+ }
+
+ # Now let's look at the extracted subraster.
+ if (showplots) {
+ call dp_showpsf (dao, im, Memr[srim], (x2 - x1 + 1), (y2 - y1 + 1),
+ x1, y1, gd, star_ok)
+ } else if (saturated == YES) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (
+ "Warning: Star %d contains high bad pixels inside fitrad\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+ star_ok = true
+ } else if (dp_pstatr (dao, CUR_PSFMIN) < logood || dp_pstatr (dao,
+ CUR_PSFMAX) > higood) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (
+ "Warning: Star %d contains bad pixels outside fitrad\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+ star_ok = true
+ } else
+ star_ok = true
+
+ # The star is rejected by the user.
+ if (! star_ok) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("Star %d rejected by user\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+ call mfree (srim, TY_REAL)
+ return (ERR)
+ }
+
+ # Save the plot in the metacode file.
+ if (mgd != NULL)
+ call dp_plotpsf (dao, im, Memr[srim], (x2 - x1 + 1), (y2 - y1 + 1),
+ x1, y1, mgd)
+
+ # Add the star to the PSF star list by swapping its position with the
+ # position of the star currently in PNUM + 1.
+ call dp_aplswap (dao, dp_pstati (dao, CUR_PSF), dp_pstati (dao,
+ PNUM) + 1)
+
+ # Increment the number of psf stars.
+ call dp_pseti (dao, PNUM, dp_pstati (dao, PNUM) + 1)
+
+ # Reallocate the fitting array space.
+ call dp_lmempsf (dao)
+
+ # Enter the new initial values.
+ call dp_xyhpsf (dao, dp_pstati (dao, PNUM), mag, saturated)
+
+ # Print message.
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("Star %d has been added to the PSF star list\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ call dp_ltov (im, dp_pstatr (dao, CUR_PSFX),
+ dp_pstatr(dao, CUR_PSFY), tx, ty, 1)
+ call printf (
+ "\tX: %7.2f Y: %7.2f Mag: %7.3f Dmin: %g Dmax: %g\n")
+ call pargr (tx)
+ call pargr (ty)
+ call pargr (dp_pstatr (dao, CUR_PSFMAG))
+ call pargr (dp_pstatr (dao, CUR_PSFMIN))
+ call pargr (dp_pstatr (dao, CUR_PSFMAX))
+ }
+
+ call mfree (srim, TY_REAL)
+ return (OK)
+end
diff --git a/noao/digiphot/daophot/psf/dpcontpsf.x b/noao/digiphot/daophot/psf/dpcontpsf.x
new file mode 100644
index 00000000..27b6bdfc
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dpcontpsf.x
@@ -0,0 +1,449 @@
+include <error.h>
+include <mach.h>
+include <gset.h>
+include <config.h>
+include <xwhen.h>
+include <fset.h>
+include "../lib/daophotdef.h"
+include "../lib/psfdef.h"
+
+define DUMMY 6
+define XCEN 0.5
+define YCEN 0.52
+define EDGE1 0.1
+define EDGE2 0.93
+define SZ_LABEL 10
+define SZ_FMT 20
+
+# DP_CONTPSF -- Draw a contour plot of a data subraster containing. The
+# data floor and ceiling are set by the user, but the contour interval
+# is chosen by the routine.
+
+procedure dp_contpsf (dao, subras, ncols, nlines, title, gp)
+
+pointer dao # pointer to DAOPHOT structure
+real subras[ncols,nlines] # data subraster
+int ncols, nlines # dimesnions of subraster
+char title[ARB] # title string
+pointer gp # pointer to graphics descriptor
+
+bool perimeter
+char system_id[SZ_LINE], label[SZ_LINE]
+int epa, status, old_onint, tcojmp[LEN_JUMPBUF]
+int wkid, nset, ncontours, dashpat, nhi
+pointer sp, temp, psf
+real interval, floor, ceiling, zero, finc, ybot
+real vx1, vx2, vy1, vy2, wx1, wx2, wy1, wy2
+real first_col, last_col, first_row, last_row
+
+bool fp_equalr()
+extern dp_conint()
+common /tcocom/ tcojmp
+
+int first
+int isizel, isizem, isizep, nrep, ncrt, ilab, nulbll, ioffd
+int ioffm, isolid, nla, nlm
+real xlt, ybt, side, ext, hold[5]
+common /conflg/ first
+common /conre4/ isizel, isizem , isizep, nrep, ncrt, ilab, nulbll,
+ ioffd, ext, ioffm, isolid, nla, nlm, xlt, ybt, side
+common /noaolb/ hold
+
+begin
+ # Get the pointer to the DAOPHOT PSF fitting substructure.
+ psf = DP_PSF (dao)
+
+ # First of all, intialize conrec's block data before altering any
+ # parameters in common.
+ first = 1
+ call conbd
+
+ # Set local variables.
+ zero = 0.0
+ floor = DP_CFLOOR (psf)
+ ceiling = DP_CCEILING (psf)
+ nhi = -1
+ dashpat = 528
+
+ # Suppress the contour labelling by setting the common
+ # parameter "ilab" to zero.
+ ilab = 0
+
+ # The floor and ceiling are in absolute units, but the zero shift is
+ # applied first, so correct the numbers for the zero shift. Zero is
+ # a special number for the floor and ceiling, so do not change value
+ # if set to zero.
+
+ if (abs (floor) > EPSILON)
+ floor = floor - zero
+ if (abs (ceiling) > EPSILON)
+ ceiling = ceiling - zero
+
+ # User can specify either the number of contours or the contour
+ # interval, or let conrec pick a nice number. Set ncontours to 0
+ # and encode the FINC param expected by conrec.
+
+ ncontours = 0
+ if (ncontours <= 0) {
+ interval = 0
+ if (interval <= 0)
+ finc = 0
+ else
+ finc = interval
+ } else
+ finc = - abs (ncontours)
+
+ # Make a copy of the data and do the contouring on this.
+ call smark (sp)
+ call salloc (temp, ncols * nlines, TY_REAL)
+ call amovr (subras, Memr[temp], nlines * ncols)
+
+ first_col = 1.0
+ last_col = real (ncols)
+ first_row = 1.0
+ last_row = real (nlines)
+
+ # Apply the zero point shift.
+ if (abs (zero) > EPSILON)
+ call asubkr (Memr[temp], zero, Memr[temp], ncols * nlines)
+
+ # Open device and make contour plot.
+ call gopks (STDERR)
+ wkid = 1
+ call gclear (gp)
+ call gopwk (wkid, DUMMY, gp)
+ call gacwk (wkid)
+
+ # The viewport can be set by the user. If not, the viewport is
+ # assumed to be centered on the device. In either case, the
+ # viewport to window mapping is established in dp_map_viewport
+ # and conrec's automatic mapping scheme is avoided by setting nset=1.
+ vx1 = 0.10
+ vx2 = 0.90
+ vy1 = 0.10
+ vy2 = 0.90
+ call dp_map_viewport (gp, ncols, nlines, vx1, vx2, vy1, vy2, false)
+ nset = 1
+
+ perimeter = TRUE
+ if (perimeter)
+ # Suppress conrec's plot label generation.
+ ioffm = 1
+ else {
+ # Draw plain old conrec perimeter, set ioffm = 0 to enable label.
+ ioffm = 0
+ call perim (ncols - 1, 1, nlines - 1, 1)
+ }
+
+ # Install interrupt exception handler.
+ call zlocpr (dp_conint, epa)
+ call xwhen (X_INT, epa, old_onint)
+
+ # Make the contour plot. If an interrupt occurs ZSVJMP is reeentered
+ # with an error status.
+ call zsvjmp (tcojmp, status)
+ if (status == OK) {
+ call conrec (Memr[temp], ncols, ncols, nlines, floor, ceiling,
+ finc, nset, nhi, -dashpat)
+ } else {
+ call gcancel (gp)
+ call fseti (STDOUT, F_CANCEL, OK)
+ }
+
+ # Now find window and output text string title. The window is
+ # set to the full image coordinates for labelling.
+ call gswind (gp, first_col, last_col, first_row, last_row)
+ if (perimeter)
+ call dp_cperimeter (gp)
+
+ call ggview (gp, wx1, wx2, wy1, wy2)
+ call gseti (gp, G_WCS, 0)
+ ybot = min (wy2 + .06, 0.99)
+ call gtext (gp, (wx1 + wx2) / 2.0, ybot, title, "h=c;v=t;f=b;s=.7")
+
+ # Add system id banner to plot.
+ call gseti (gp, G_CLIP, NO)
+ call sysid (system_id, SZ_LINE)
+ ybot = max (wy1 - 0.08, 0.01)
+ call gtext (gp, (wx1+wx2)/2.0, ybot, system_id, "h=c;v=b;s=.5")
+
+ if (perimeter) {
+ if (fp_equalr (hold(5), 1.0)) {
+ call sprintf (label, SZ_LINE,
+ "contoured from %g to %g, interval = %g")
+ call pargr (hold(1))
+ call pargr (hold(2))
+ call pargr (hold(3))
+ } else {
+ call sprintf (label, SZ_LINE,
+ "contoured from %g to %g, interval = %g, labels scaled by %g")
+ call pargr (hold(1))
+ call pargr (hold(2))
+ call pargr (hold(3))
+ call pargr (hold(5))
+ }
+ ybot = max (wy1 - 0.06, .03)
+ call gtext (gp, (wx1 + wx2) / 2.0, ybot, label, "h=c;v=b;s=.6")
+ }
+
+ call gswind (gp, first_col, last_col, first_row, last_row)
+ call gdawk (wkid)
+ call gclks ()
+ call sfree (sp)
+end
+
+
+# DP_CONINT -- Interrupt handler for the task contour. Branches back to
+# ZSVJMP in the main routine to permit shutdown without an error message.
+
+procedure dp_conint (vex, next_handler)
+
+int vex # virtual exception
+int next_handler # not used
+
+int tcojmp[LEN_JUMPBUF]
+common /tcocom/ tcojmp
+
+begin
+ call xer_reset()
+ call zdojmp (tcojmp, vex)
+end
+
+
+# DP_CPERIMETER -- draw and annotate the axes drawn around the perimeter
+# of the image pixels. The viewport and window have been set by
+# the calling procedure. Plotting is done in window coordinates.
+# This procedure is called by both crtpict and the ncar plotting routines
+# contour and hafton.
+
+procedure dp_cperimeter (gp)
+
+pointer gp # graphics descriptor
+real xs, xe, ys, ye # WCS coordinates of pixel window
+
+char label[SZ_LABEL], fmt1[SZ_FMT], fmt2[SZ_FMT], fmt3[SZ_FMT], fmt4[SZ_FMT]
+int i, first_col, last_col, first_tick, last_tick, bias
+int nchar, first_row, last_row, cnt_step, cnt_label
+real dist, kk, col, row, dx, dy, sz_char, cw, xsz, label_pos
+real xdist, ydist, xspace, yspace, k[3]
+bool ggetb()
+int itoc()
+real ggetr()
+data k/1.0,2.0,3.0/
+errchk ggwind, gseti, gctran, gline, gtext, itoc
+
+begin
+ # First, get window coordinates and turn off clipping.
+ call ggwind (gp, xs, xe, ys, ye)
+ call gseti (gp, G_CLIP, NO)
+
+ # A readable character width seems to be about 1.mm. A readable
+ # perimeter seperation seems to be about .80mm. If the physical
+ # size of the output device is contained in the graphcap file, the
+ # NDC sizes of these measurements can be determined. If not,
+ # the separation between perimeter axes equals one quarter character
+ # width or one quarter percent of frame, which ever is larger, and
+ # the character size is set to 0.40.
+
+ cw = max (ggetr (gp, "cw"), 0.01)
+ if (ggetb (gp, "xs")) {
+ xsz = ggetr (gp, "xs")
+ dist = .80 / (xsz * 1000.)
+ sz_char = dist / cw
+ } else {
+ # Get character width and calculate perimeter separation.
+ dist = cw * 0.25
+ sz_char = 0.40
+ }
+
+ # Convert distance to user coordinates.
+ call ggscale (gp, xs, ys, dx, dy)
+ xdist = dist * dx
+ ydist = dist * dy
+
+ # Generate four possible format strings for gtext.
+ call sprintf (fmt1, SZ_LINE, "h=c;v=t;s=%.2f")
+ call pargr (sz_char)
+ call sprintf (fmt2, SZ_LINE, "h=c;v=b;s=%.2f")
+ call pargr (sz_char)
+ call sprintf (fmt3, SZ_LINE, "h=r;v=c;s=%.2f")
+ call pargr (sz_char)
+ call sprintf (fmt4, SZ_LINE, "h=l;v=c;s=%.2f")
+ call pargr (sz_char)
+
+ # Draw inner and outer perimeter
+ kk = k[1]
+ do i = 1, 2 {
+ xspace = kk * xdist
+ yspace = kk * ydist
+ call gline (gp, xs - xspace, ys - yspace, xe + xspace, ys - yspace)
+ call gline (gp, xe + xspace, ys - yspace, xe + xspace, ye + yspace)
+ call gline (gp, xe + xspace, ye + yspace, xs - xspace, ye + yspace)
+ call gline (gp, xs - xspace, ye + yspace, xs - xspace, ys - yspace)
+ kk = k[2]
+ }
+
+ # Now draw x axis tick marks, along both the bottom and top of
+ # the picture. First find the endpoint integer pixels.
+
+ first_col = int (xs)
+ last_col = int (xe)
+
+ # Determine increments of ticks and tick labels for x axis.
+ cnt_step = 1
+ cnt_label = 10
+ if (last_col - first_col > 256) {
+ cnt_step = 10
+ cnt_label = 100
+ } else if (last_col - first_col < 26) {
+ cnt_step = 1
+ cnt_label = 1
+ }
+
+ first_tick = first_col
+ bias = mod (first_tick, cnt_step)
+ last_tick = last_col + bias
+
+ do i = first_tick, last_tick, cnt_step {
+ col = real (i - bias)
+ call gline (gp, col, ys - k[1] * ydist, col, ys - k[2] * ydist)
+ call gline (gp, col, ye + k[1] * ydist, col, ye + k[2] * ydist)
+
+ if (mod ((i - bias), cnt_label) == 0) {
+
+ # Label tick mark; calculate number of characters needed.
+ nchar = 3
+ if (int (col) == 0)
+ nchar = 1
+ if (int (col) >= 1000)
+ nchar = 4
+ if (itoc (int(col), label, nchar) <= 0)
+ label[1] = EOS
+
+ # Position label slightly below outer perimeter. Seperation
+ # is twenty percent of a character width, in WCS.
+ label_pos = ys - (k[2] * ydist + (cw * 0.20 * dy))
+ call gtext (gp, col, label_pos, label, fmt1)
+
+ # Position label slightly above outer perimeter.
+ label_pos = ye + (k[2] * ydist + (cw * 0.20 * dy))
+ call gtext (gp, col, label_pos, label, fmt2)
+ }
+ }
+
+ # Label the y axis tick marks along the left and right sides of the
+ # picture. First find the integer pixel endpoints.
+
+ first_row = int (ys)
+ last_row = int (ye)
+
+ # Determine increments of ticks and tick labels for y axis.
+ cnt_step = 1
+ cnt_label = 10
+ if (last_row - first_row > 256) {
+ cnt_step = 10
+ cnt_label = 100
+ } else if (last_row - first_row < 26) {
+ cnt_step = 1
+ cnt_label = 1
+ }
+
+ first_tick = first_row
+ bias = mod (first_tick, cnt_step)
+ last_tick = last_row + bias
+
+ do i = first_tick, last_tick, cnt_step {
+ row = real (i - bias)
+ call gline (gp, xs - k[1] * xdist, row, xs - k[2] * xdist, row)
+ call gline (gp, xe + k[1] * xdist, row, xe + k[2] * xdist, row)
+
+ if (mod ((i - bias), cnt_label) == 0) {
+
+ # Label tick mark; calculate number of characters needed
+ nchar = 3
+ if (int (row) == 0)
+ nchar = 1
+ else if (int (row) >= 1000)
+ nchar = 4
+ if (itoc (int(row), label, nchar) <= 0)
+ label[1] = EOS
+
+ # Position label slightly to the left of outer perimeter.
+ # Separation twenty percent of a character width, in WCS.
+ label_pos = xs - (k[2] * xdist + (cw * 0.20 * dx))
+ call gtext (gp, label_pos, row, label, fmt3)
+
+ # Position label slightly to the right of outer perimeter.
+ label_pos = xe + (k[2] * xdist + (cw * 0.20 * dx))
+ call gtext (gp, label_pos, row, label, fmt4)
+ }
+ }
+end
+
+
+# DP_MAP_VIEWPORT -- Set device viewport for contour and hafton plots. If not
+# specified by user, a default viewport centered on the device is used.
+
+procedure dp_map_viewport (gp, ncols, nlines, ux1, ux2, uy1, uy2, fill)
+
+pointer gp # graphics pointer
+int ncols # number of image cols
+int nlines # number of image lines
+real ux1, ux2, uy1, uy2 # NDC coordinates of requested viewort
+bool fill # fill viewport (vs enforce unity aspect ratio?)
+
+real ncolsr, nlinesr, ratio, aspect_ratio
+real x1, x2, y1, y2, ext, xdis, ydis
+data ext /0.25/
+bool fp_equalr()
+real ggetr()
+
+begin
+ ncolsr = real (ncols)
+ nlinesr = real (nlines)
+ if (fp_equalr (ux1, 0.0) && fp_equalr (ux2, 0.0) &&
+ fp_equalr (uy1, 0.0) && fp_equalr (uy2, 0.0)) {
+
+ x1 = EDGE1
+ x2 = EDGE2
+ y1 = EDGE1
+ y2 = EDGE2
+
+ # Calculate optimum viewport, as in NCAR's conrec, hafton.
+ ratio = min (ncolsr, nlinesr) / max (ncolsr, nlinesr)
+ if (ratio >= ext) {
+ if (ncols > nlines)
+ y2 = (y2 - y1) * nlinesr / ncolsr + y1
+ else
+ x2 = (x2 - x1) * ncolsr / nlinesr + x1
+ }
+
+ xdis = x2 - x1
+ ydis = y2 - y1
+
+ # So far, the viewport has been calculated so that equal numbers of
+ # image pixels map to equal distances in NDC space, regardless of
+ # the aspect ratio of the device. If the parameter "fill" has been
+ # set to no, the user wants to compensate for a non-unity aspect
+ # ratio and make equal numbers of image pixels map to into the same
+ # physical distance on the device, not the same NDC distance.
+
+ if (! fill) {
+ aspect_ratio = ggetr (gp, "ar")
+ if (fp_equalr (aspect_ratio, 0.0))
+ aspect_ratio = 1.0
+ xdis = xdis * aspect_ratio
+ }
+
+ ux1 = XCEN - (xdis / 2.0)
+ ux2 = XCEN + (xdis / 2.0)
+ uy1 = YCEN - (ydis / 2.0)
+ uy2 = YCEN + (ydis / 2.0)
+ }
+
+ # Set window and viewport for WCS 1.
+ call gseti (gp, G_WCS, 1)
+ call gsview (gp, ux1, ux2, uy1, uy2)
+ call gswind (gp, 1.0, ncolsr, 1.0, nlinesr)
+ call set (ux1, ux2, uy1, uy2, 1.0, ncolsr, 1.0, nlinesr, 1)
+end
diff --git a/noao/digiphot/daophot/psf/dpdelstar.x b/noao/digiphot/daophot/psf/dpdelstar.x
new file mode 100644
index 00000000..22ba579f
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dpdelstar.x
@@ -0,0 +1,112 @@
+include <imhdr.h>
+include <mach.h>
+include "../lib/daophotdef.h"
+include "../lib/psfdef.h"
+
+# DP_DELSTAR -- Delete the star at the given position from the list of PSF
+# stars if it exists and passes the selection criteria.
+
+int procedure dp_delstar (dao, im, x, y, idnum, gd, showplots)
+
+pointer dao # pointer to daophot structure
+pointer im # pointer to image
+real x, y # position of proposed PSF star
+int idnum # id number of desired star
+pointer gd # pointer to the graphics stream
+bool showplots # show plots?
+
+real tx, ty
+pointer srim
+int starnum, saturated, x1, x2, y1, y2
+bool star_ok
+
+pointer dp_psubrast()
+int dp_locstar(), dp_idstar(), dp_pstati()
+
+begin
+ # Convert coordinates for display.
+ if (showplots)
+ call dp_ltov (im, x, y, tx, ty, 1)
+ else
+ call dp_wout (dao, im, x, y, tx, ty, 1)
+
+ # Check that the position of the star is within the image.
+ if (idnum == 0 && (x < 1.0 || x > real (IM_LEN(im,1)) || y < 1.0 || y >
+ real (IM_LEN(im,2)))) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("Star at %g,%g is outside the image\n")
+ call pargr (tx)
+ call pargr (ty)
+ }
+ return (ERR)
+ }
+
+ # Find the star in the aperture photometry list.
+ if (idnum == 0)
+ starnum = dp_locstar (dao, im, x, y)
+ else
+ starnum = dp_idstar (dao, im, idnum)
+ if (starnum == 0) {
+ if (DP_VERBOSE(dao) == YES) {
+ if (idnum > 0) {
+ call printf ("Star %d not found in the photometry file\n")
+ call pargi (idnum)
+ } else {
+ call printf (
+ "Star at %g,%g not found in the photometry file\n")
+ call pargr (tx)
+ call pargr (ty)
+ }
+ }
+ return (ERR)
+ } else if (starnum < 0 || starnum > dp_pstati (dao, PNUM)) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ( "Star %d not found in the PSF star list\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+ return (ERR)
+ }
+
+ # Get the data subraster, check for bad pixels and compute the min
+ # and max.
+ if (showplots) {
+ srim = dp_psubrast (dao, im, -MAX_REAL, MAX_REAL, x1, x2,
+ y1, y2, saturated)
+ if (srim == NULL) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("Star %d error reading data subraster\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+ star_ok = false
+ } else {
+ call dp_showpsf (dao, im, Memr[srim], (x2 - x1 + 1),
+ (y2 - y1 + 1), x1, y1, gd, star_ok)
+ call mfree (srim, TY_REAL)
+ }
+ } else
+ star_ok = true
+
+ if (star_ok) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("PSF star %d saved by user\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+ return (ERR)
+ }
+
+ # Delete the star from the list by moving it to the position
+ # currently occupied by PNUM and moving everything else up.
+ call dp_pfreorder (dao, dp_pstati (dao, CUR_PSF), dp_pstati (dao,
+ PNUM))
+
+ # Decrement the number of psf stars.
+ call dp_pseti (dao, PNUM, dp_pstati(dao, PNUM) - 1)
+
+ # Print message.
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("Star %d has been deleted from the PSF star list\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+
+ return (OK)
+end
diff --git a/noao/digiphot/daophot/psf/dpfitpsf.x b/noao/digiphot/daophot/psf/dpfitpsf.x
new file mode 100644
index 00000000..2b1c6bbc
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dpfitpsf.x
@@ -0,0 +1,1693 @@
+include <mach.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/psfdef.h"
+include "../lib/peakdef.h"
+
+# DP_FITPSF -- Compute the PSF function.
+
+int procedure dp_fitpsf (dao, im, errmsg, maxch)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+char errmsg[ARB] # string containing error message
+int maxch # max characters in errmsg
+
+int nfunc, func
+pointer sp, flist, fstr, psf, psffit
+int dp_pstati(), dp_unsatstar(), dp_fitana(), dp_ifitana()
+int dp_fitlt(), dp_fctdecode(), dp_strwrd(), strdic()
+
+begin
+ # Get some daophot pointers.
+ psf = DP_PSF(dao)
+ psffit = DP_PSFFIT(dao)
+
+ # Test to see if there are any psf stars.
+ if (dp_pstati (dao, PNUM) <= 0) {
+ call sprintf (errmsg, maxch, "The PSF star list is empty")
+ return (ERR)
+ }
+
+ # Test to see if there are any unsaturated stars. At the same time
+ # make sure that the first star is unsaturated.
+ if (dp_unsatstar (dao) <= 0) {
+ call sprintf (errmsg, maxch,
+ "There are no unsaturated PSF stars")
+ return (ERR)
+ }
+
+ # Determine the analytic function.
+ call smark (sp)
+ call salloc (flist, SZ_FNAME, TY_CHAR)
+ call salloc (fstr, SZ_FNAME, TY_CHAR)
+ call dp_stats (dao, FUNCLIST, Memc[flist], SZ_FNAME)
+ nfunc = dp_fctdecode (Memc[flist], Memc[fstr], SZ_FNAME)
+ func = dp_strwrd (1, Memc[fstr], SZ_FNAME, Memc[flist])
+ func = strdic (Memc[fstr], Memc[fstr], SZ_LINE, FCTN_FTYPES)
+
+ # Compute the analytic part of the PSF function.
+ if (nfunc > 1 || func == FCTN_AUTO) {
+
+ # Loop over all the analytic functions.
+ if (func == FCTN_AUTO) {
+ call strcpy (FCTN_FTYPES, Memc[flist], SZ_FNAME)
+ nfunc = FCTN_NFTYPES
+ }
+
+ # Find the best fitting analytic function.
+ if (dp_ifitana (dao, im, Memc[flist], nfunc) == ERR) {
+ call sprintf (errmsg, maxch,
+ "Analytic function solution failed to converge")
+ call sfree (sp)
+ return (ERR)
+ } else if (DP_VERBOSE(dao) == YES)
+ call dp_listpars (dao)
+
+ } else {
+
+ # Save the analytic function for the new fit.
+ call strcpy (Memc[fstr], DP_FUNCTION(dao), SZ_LINE)
+
+ # Initialize the parameters.
+ call dp_reinit (dao)
+
+ # Fit the analytic part of the function.
+ if (dp_fitana (dao, im, Memr[DP_PXCEN(psf)], Memr[DP_PYCEN(psf)],
+ Memr[DP_PH(psf)], Memi[DP_PSAT(psf)], DP_PNUM(psf)) == ERR) {
+ call sprintf (errmsg, maxch,
+ "Analytic function solution failed to converge")
+ call sfree (sp)
+ return (ERR)
+ } else if (DP_VERBOSE(dao) == YES) {
+ call printf ("\nFitting function %s norm scatter: %g\n")
+ call pargstr (DP_FUNCTION(dao))
+ call pargr (DP_PSIGANA(psf))
+ call dp_listpars (dao)
+ }
+ }
+ call sfree (sp)
+
+ # Compute the look-up table.
+ if (dp_fitlt (dao, im) == ERR) {
+ call sprintf (errmsg, maxch,
+ "Too few stars to compute PSF lookup tables")
+ return (ERR)
+ } else if (DP_VERBOSE(dao) == YES) {
+ call printf ("\nComputed %d lookup table(s)\n")
+ call pargi (DP_NVLTABLE(psffit)+DP_NFEXTABLE(psffit))
+ }
+
+ return (OK)
+end
+
+
+# DP_UNSATSTAR -- Make sure there is at least one unsaturated star.
+
+int procedure dp_unsatstar (dao)
+
+pointer dao # pointer to the daophot structure
+
+int i, first_unsat, nstar
+pointer psf
+
+begin
+ psf = DP_PSF(dao)
+ first_unsat = 0
+
+ nstar = 0
+ do i = 1, DP_PNUM(psf) {
+ if (Memi[DP_PSAT(psf)+i-1] == YES)
+ next
+ nstar = nstar + 1
+ if (first_unsat == 0)
+ first_unsat = i
+ }
+
+ if (first_unsat > 1)
+ call dp_pfswap (dao, 1, first_unsat)
+
+ return (nstar)
+end
+
+
+# DP_REINIT -- Reinitialize the psf function parameters.
+
+procedure dp_reinit (dao)
+
+pointer dao # pointer to the daophot structure
+
+pointer psffit
+bool streq()
+
+begin
+ psffit = DP_PSFFIT(dao)
+
+ # Define the psf function.
+ if (streq (DP_FUNCTION(dao), "gauss"))
+ DP_PSFUNCTION(psffit) = FCTN_GAUSS
+ else if (streq (DP_FUNCTION(dao), "moffat25"))
+ DP_PSFUNCTION(psffit) = FCTN_MOFFAT25
+ else if (streq (DP_FUNCTION(dao), "moffat15"))
+ DP_PSFUNCTION(psffit) = FCTN_MOFFAT15
+ else if (streq (DP_FUNCTION(dao), "penny1"))
+ DP_PSFUNCTION(psffit) = FCTN_PENNY1
+ else if (streq (DP_FUNCTION(dao), "penny2"))
+ DP_PSFUNCTION(psffit) = FCTN_PENNY2
+ else if (streq (DP_FUNCTION(dao), "lorentz"))
+ DP_PSFUNCTION(psffit) = FCTN_LORENTZ
+ else
+ call error (0, "Unknown PSF function\n")
+
+ switch (DP_VARORDER(dao)) {
+ case -1:
+ DP_NVLTABLE(psffit) = 0
+ case 0:
+ DP_NVLTABLE(psffit) = 1
+ case 1:
+ DP_NVLTABLE(psffit) = 3
+ case 2:
+ DP_NVLTABLE(psffit) = 6
+ }
+ if (DP_FEXPAND(dao) == NO)
+ DP_NFEXTABLE(psffit) = 0
+ else
+ DP_NFEXTABLE(psffit) = 5
+
+ # Set the initial values of the function parameters.
+ switch (DP_PSFUNCTION(psffit)) {
+ case FCTN_GAUSS:
+ DP_PSFNPARS(psffit) = 2
+ Memr[DP_PSFPARS(psffit)] = DP_FWHMPSF(dao) / 2.0
+ Memr[DP_PSFPARS(psffit)+1] = DP_FWHMPSF(dao) / 2.0
+ case FCTN_MOFFAT25:
+ DP_PSFNPARS(psffit) = 3
+ Memr[DP_PSFPARS(psffit)] = DP_FWHMPSF(dao) / 2.0
+ Memr[DP_PSFPARS(psffit)+1] = DP_FWHMPSF(dao) / 2.0
+ Memr[DP_PSFPARS(psffit)+2] = 0.0
+ Memr[DP_PSFPARS(psffit)+3] = 2.5
+ case FCTN_MOFFAT15:
+ DP_PSFNPARS(psffit) = 3
+ Memr[DP_PSFPARS(psffit)] = DP_FWHMPSF(dao) / 2.0
+ Memr[DP_PSFPARS(psffit)+1] = DP_FWHMPSF(dao) / 2.0
+ Memr[DP_PSFPARS(psffit)+2] = 0.0
+ Memr[DP_PSFPARS(psffit)+3] = 1.5
+ case FCTN_PENNY1:
+ DP_PSFNPARS(psffit) = 4
+ Memr[DP_PSFPARS(psffit)] = DP_FWHMPSF(dao) / 2.0
+ Memr[DP_PSFPARS(psffit)+1] = DP_FWHMPSF(dao) / 2.0
+ Memr[DP_PSFPARS(psffit)+2] = 0.75
+ Memr[DP_PSFPARS(psffit)+3] = 0.0
+ case FCTN_PENNY2:
+ DP_PSFNPARS(psffit) = 5
+ Memr[DP_PSFPARS(psffit)] = DP_FWHMPSF(dao) / 2.0
+ Memr[DP_PSFPARS(psffit)+1] = DP_FWHMPSF(dao) / 2.0
+ Memr[DP_PSFPARS(psffit)+2] = 0.75
+ Memr[DP_PSFPARS(psffit)+3] = 0.0
+ Memr[DP_PSFPARS(psffit)+4] = 0.0
+ case FCTN_LORENTZ:
+ DP_PSFNPARS(psffit) = 3
+ Memr[DP_PSFPARS(psffit)] = DP_FWHMPSF(dao) / 2.0
+ Memr[DP_PSFPARS(psffit)+1] = DP_FWHMPSF(dao) / 2.0
+ Memr[DP_PSFPARS(psffit)+2] = 0.0
+ default:
+ call error (0, "Unknown PSF function\n")
+ }
+end
+
+
+# DP_IFITANA -- Fit the PSF stars to each of the analytic functions in
+# turn to determine which one gives the best fit.
+
+int procedure dp_ifitana (dao, im, funclist, nfunc)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+char funclist # the list of functions to be fit
+int nfunc # number of functions
+
+int i, psftype, npars
+pointer psf, psffit, sp, fstr, func
+pointer ixtmp, iytmp, ihtmp, istmp, xtmp, ytmp, htmp, ptmp, stmp
+real osig, osum, height, dhdxc, dhdyc, junk, ofactor, factor
+int dp_strwrd(), strdic(), dp_fitana()
+real dp_profile()
+
+begin
+ # Get some pointers.
+ psf = DP_PSF(dao)
+ psffit = DP_PSFFIT(dao)
+
+ # Allocate some temporary storage space.
+ call smark (sp)
+ call salloc (fstr, SZ_FNAME, TY_CHAR)
+ call salloc (func, SZ_FNAME, TY_CHAR)
+
+ call salloc (ixtmp, DP_PNUM(psf), TY_REAL)
+ call salloc (iytmp, DP_PNUM(psf), TY_REAL)
+ call salloc (ihtmp, DP_PNUM(psf), TY_REAL)
+ call salloc (istmp, DP_PNUM(psf), TY_INT)
+
+ call salloc (xtmp, DP_PNUM(psf), TY_REAL)
+ call salloc (ytmp, DP_PNUM(psf), TY_REAL)
+ call salloc (htmp, DP_PNUM(psf), TY_REAL)
+ call salloc (stmp, DP_PNUM(psf), TY_INT)
+ call salloc (ptmp, MAX_NFCTNPARS, TY_REAL)
+
+ # Initialize.
+ call strcpy (DP_FUNCTION(dao), Memc[func], SZ_FNAME)
+ npars = 0
+ osig = MAX_REAL
+ call amovr (Memr[DP_PXCEN(psf)], Memr[ixtmp], DP_PNUM(psf))
+ call amovr (Memr[DP_PYCEN(psf)], Memr[iytmp], DP_PNUM(psf))
+ call amovr (Memr[DP_PH(psf)], Memr[ihtmp], DP_PNUM(psf))
+ call amovi (Memi[DP_PSAT(psf)], Memi[istmp], DP_PNUM(psf))
+ ofactor = dp_profile (DP_PSFUNCTION(psffit), 0.0, 0.0,
+ Memr[DP_PSFPARS(psffit)], dhdxc, dhdyc, junk, 0)
+
+ factor = 1
+ do i = 1, nfunc {
+
+ # Get the function name and set it.
+ if (dp_strwrd (i, Memc[fstr], SZ_FNAME, funclist) <= 0)
+ next
+ if (strdic (Memc[fstr], Memc[fstr], SZ_FNAME, FCTN_FTYPES) <= 0)
+ next
+ call strcpy (Memc[fstr], DP_FUNCTION(dao), SZ_FNAME)
+
+ # Start from the same initial state.
+ call dp_reinit (dao)
+ call amovr (Memr[ixtmp], Memr[xtmp], DP_PNUM(psf))
+ call amovr (Memr[iytmp], Memr[ytmp], DP_PNUM(psf))
+ if (i == 1)
+ call amovr (Memr[ihtmp], Memr[htmp], DP_PNUM(psf))
+ else {
+ factor = ofactor / dp_profile (DP_PSFUNCTION(psffit), 0.0, 0.0,
+ Memr[DP_PSFPARS(psffit)], dhdxc, dhdyc, junk, 0)
+ call amulkr (Memr[ihtmp], factor, Memr[htmp], DP_PNUM(psf))
+ }
+ call amovi (Memi[istmp], Memi[stmp], DP_PNUM(psf))
+
+ call printf ("Trying function %s norm scatter = ")
+ call pargstr (Memc[fstr])
+
+ # Do the fit.
+ if (dp_fitana (dao, im, Memr[xtmp], Memr[ytmp], Memr[htmp],
+ Memi[stmp], DP_PNUM(psf)) == ERR) {
+ call printf ("error\n")
+ next
+ } else {
+ call printf ("%g\n")
+ call pargr (DP_PSIGANA(psf))
+ }
+
+ # Save the better fit.
+ if (DP_PSIGANA(psf) < osig) {
+ call strcpy (Memc[fstr], Memc[func], SZ_FNAME)
+ psftype = DP_PSFUNCTION(psffit)
+ height = DP_PSFHEIGHT(psffit)
+ npars = DP_PSFNPARS(psffit)
+ call amovr (Memr[DP_PSFPARS(psffit)], Memr[ptmp],
+ MAX_NFCTNPARS)
+ call amovr (Memr[xtmp], Memr[DP_PXCEN(psf)], DP_PNUM(psf))
+ call amovr (Memr[ytmp], Memr[DP_PYCEN(psf)], DP_PNUM(psf))
+ call amovr (Memr[htmp], Memr[DP_PH(psf)], DP_PNUM(psf))
+ call amovi (Memi[stmp], Memi[DP_PSAT(psf)], DP_PNUM(psf))
+ osig = DP_PSIGANA(psf)
+ osum = DP_PSUMANA(psf)
+ }
+ }
+
+ # Restore the best fit parameters.
+ if (npars > 0) {
+ call strcpy (Memc[func], DP_FUNCTION(dao), SZ_FNAME)
+ DP_PSFUNCTION(psffit) = psftype
+ DP_PSFHEIGHT(psffit) = height
+ DP_PSFNPARS(psffit) = npars
+ DP_PSIGANA(psf) = osig
+ DP_PSUMANA(psf) = osum
+ call amovr (Memr[ptmp], Memr[DP_PSFPARS(psffit)],
+ MAX_NFCTNPARS)
+ call printf ("Best fitting function is %s\n")
+ call pargstr (DP_FUNCTION(dao))
+ }
+
+ # Cleanup.
+ call sfree (sp)
+
+ if (npars > 0)
+ return (OK)
+ else
+ return (ERR)
+end
+
+
+# DP_FITANA -- Fit the analytic part of the psf function
+
+int procedure dp_fitana (dao, im, pxcen, pycen, ph, pstat, npsfstars)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+real pxcen[ARB] # x coordinates of the psf stars
+real pycen[ARB] # y coordinates of the psf stars
+real ph[ARB] # heights of the psf stars
+int pstat[ARB] # saturation status of psf stars
+int npsfstars # the number of psf stars
+
+int i, niter, istar, mpar, lx, ly, nx, ny, ier
+pointer apsel, psf, psffit, data
+real fitrad, rsq, oldchi, sumfree
+pointer imgs2r()
+
+begin
+ # Get the psf fitting structure pointer.
+ apsel = DP_APSEL(dao)
+ psf = DP_PSF(dao)
+ psffit = DP_PSFFIT(dao)
+
+ # Define some variables.
+ oldchi = 0.0
+ mpar = 2
+ fitrad = DP_FITRAD(dao)
+ rsq = fitrad ** 2
+
+ # Get some memory.
+ call dp_amempsf (dao)
+
+ # Initialize the fit.
+ call amovkr (0.5, Memr[DP_PCLAMP(psf)], DP_PSFNPARS(psffit))
+ call aclrr (Memr[DP_PZ(psf)], DP_PSFNPARS(psffit))
+ call aclrr (Memr[DP_POLD(psf)], DP_PSFNPARS(psffit))
+ Memr[DP_PCLAMP(psf)] = 2.0
+ Memr[DP_PCLAMP(psf)+1] = 2.0
+
+ call aclrr (Memr[DP_PXOLD(psf)], npsfstars)
+ call aclrr (Memr[DP_PYOLD(psf)], npsfstars)
+ call amovkr (1.0, Memr[DP_PXCLAMP(psf)], npsfstars)
+ call amovkr (1.0, Memr[DP_PYCLAMP(psf)], npsfstars)
+
+ # Iterate.
+ do niter = 1, MAX_NPSFITER {
+
+ # Initialize the current integration.
+ call aclrr (Memr[DP_PV(psf)], DP_PSFNPARS(psffit))
+ call aclrr (Memr[DP_PC(psf)], DP_PSFNPARS(psffit) *
+ DP_PSFNPARS(psffit))
+
+ # Loop over the stars.
+ DP_PSIGANA(psf) = 0.0
+ DP_PSUMANA(psf) = 0.0
+ do istar = 1, npsfstars {
+
+ # Test for saturation.
+ if (pstat[istar] == YES)
+ next
+
+ # Define the subraster to be read in.
+ lx = int (pxcen[istar] - fitrad) + 1
+ ly = int (pycen[istar] - fitrad) + 1
+ nx = (int (pxcen[istar] + fitrad) - lx) + 1
+ ny = (int (pycen[istar] + fitrad) - ly) + 1
+
+ # Is the star off the image?
+ if (lx > IM_LEN(im,1) || ly > IM_LEN(im,2) || (lx + nx - 1) <
+ 1 || (ly + ny - 1) < 1) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("Star %d is outside the image\n")
+ call pargi (Memi[DP_APID(apsel)+istar-1])
+ }
+ next
+ }
+
+ # Is the star too near the edge of the frame?
+ if (lx < 1 || ly < 1 || (lx + nx - 1) > IM_LEN(im,1) ||
+ (ly + ny - 1) > IM_LEN(im,2)) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (
+ "Star %d is too near the edge of the image\n")
+ call pargi (Memi[DP_APID(apsel)+istar-1])
+ }
+ next
+ }
+
+ # Read in the subraster.
+ data = imgs2r (im, lx, lx + nx - 1, ly, ly + ny - 1)
+
+ # Fit x, y, and height for the PSF star istar.
+ call dp_xyhiter (DP_PSFUNCTION(psffit),
+ Memr[DP_PSFPARS(psffit)], rsq, Memr[data], nx, ny, lx, ly,
+ pxcen[istar], pycen[istar],
+ Memr[DP_APMSKY(apsel)+istar-1], ph[istar],
+ Memr[DP_PXCLAMP(psf)+istar-1],
+ Memr[DP_PYCLAMP(psf)+istar-1], Memr[DP_PXOLD(psf)+istar-1],
+ Memr[DP_PYOLD(psf)+istar-1])
+
+ # Fit the parameters for the entire list of stars
+ call dp_paccum (DP_PSFUNCTION(psffit),
+ Memr[DP_PSFPARS(psffit)], DP_PSFNPARS(psffit), mpar, rsq,
+ Memr[data], nx, ny, lx, ly, pxcen[istar],
+ pycen[istar], Memr[DP_APMSKY(apsel)+istar-1],
+ ph[istar], niter, Memr[DP_PC(psf)],
+ Memr[DP_PV(psf)], Memr[DP_PTMP(psf)], DP_PSIGANA(psf),
+ DP_PSUMANA(psf))
+ }
+
+ # Invert the matrix and compute the new parameters.
+ call invers (Memr[DP_PC(psf)], DP_PSFNPARS(psffit), mpar, ier)
+ call mvmul (Memr[DP_PC(psf)], DP_PSFNPARS(psffit), mpar,
+ Memr[DP_PV(psf)], Memr[DP_PZ(psf)])
+
+ do i = 1, mpar {
+ if ((Memr[DP_PZ(psf)+i-1] * Memr[DP_POLD(psf)+i-1]) < 0.0)
+ Memr[DP_PCLAMP(psf)+i-1] = 0.5 *
+ Memr[DP_PCLAMP(psf)+i-1]
+ else
+ Memr[DP_PCLAMP(psf)+i-1] = 1.1 *
+ Memr[DP_PCLAMP(psf)+i-1]
+ }
+ call amovr (Memr[DP_PZ(psf)], Memr[DP_POLD(psf)], mpar)
+ call amulr (Memr[DP_PZ(psf)], Memr[DP_PCLAMP(psf)],
+ Memr[DP_PZ(psf)], mpar)
+
+ Memr[DP_PZ(psf)] = max (-0.1 * Memr[DP_PSFPARS(psffit)],
+ min (0.1 * Memr[DP_PSFPARS(psffit)], Memr[DP_PZ(psf)]))
+ Memr[DP_PZ(psf)+1] = max (-0.1 * Memr[DP_PSFPARS(psffit)+1],
+ min (0.1 * Memr[DP_PSFPARS(psffit)+1], Memr[DP_PZ(psf)+1]))
+ #if (mpar > 2)
+ #Memr[DP_PZ(psf)+2] = Memr[DP_PZ(psf)+2] /
+ #(1.0 + abs (Memr[DP_PZ(psf)+2]) /
+ #(min (0.1, 1.0 - abs (Memr[DP_PSFPARS(psffit)+2]))))
+ call aaddr (Memr[DP_PSFPARS(psffit)], Memr[DP_PZ(psf)],
+ Memr[DP_PSFPARS(psffit)], mpar)
+
+ # Check for convergence.
+ sumfree = DP_PSUMANA(psf) - real (mpar + 3 * npsfstars)
+ if (sumfree > 0.0 && DP_PSIGANA(psf) >= 0.0)
+ DP_PSIGANA(psf) = sqrt (DP_PSIGANA(psf) / sumfree)
+ else
+ DP_PSIGANA(psf) = 9.999
+
+ if (mpar == DP_PSFNPARS(psffit)) {
+ if (abs (oldchi / DP_PSIGANA(psf) - 1.0) < 1.0e-5) {
+ DP_PSFHEIGHT(psffit) = ph[1]
+ if (IS_INDEFR(Memr[DP_PMAG(psf)]))
+ DP_PSFMAG(psffit) = Memr[DP_APMAG(apsel)]
+ else
+ DP_PSFMAG(psffit) = Memr[DP_PMAG(psf)]
+ DP_PSFX(psffit) = real (IM_LEN(im,1) - 1) / 2.0
+ DP_PSFY(psffit) = real (IM_LEN(im,2) - 1) / 2.0
+ return (OK)
+ } else
+ oldchi = DP_PSIGANA(psf)
+ } else {
+ if (abs (oldchi / DP_PSIGANA(psf) - 1.0) < 1.0e-3) {
+ mpar = mpar + 1
+ oldchi = 0.0
+ } else
+ oldchi = DP_PSIGANA(psf)
+ }
+ }
+
+ return (ERR)
+end
+
+
+# DP_XYHITER -- Increment the initial x, y, and height values for a star.
+
+procedure dp_xyhiter (psftype, params, rsq, data, nx, ny, lx, ly, x, y, sky, h,
+ xclamp, yclamp, xold, yold)
+
+int psftype # analytic point spread function type
+real params[ARB] # current function parameter values
+real rsq # the fitting radius squared
+real data[nx,ARB] # the input image data
+int nx, ny # the dimensions of the input image data
+int lx, ly # the coordinates of the ll corner of the image data
+real x, y # the input/output stellar coordinates
+real sky # the input sky value
+real h # the input/output height value
+real xclamp, yclamp # the input/output clamping factors for x and y
+real xold, yold # the input/output x and y correction factors
+
+int i, j
+real dhn, dhd, dxn, dxd, dyn, dyd, dx, dy, wt, dhdxc, dhdyc, junk, p, dp
+real prod
+real dp_profile()
+
+begin
+ dhn = 0.0
+ dhd = 0.0
+ dxn = 0.0
+ dxd = 0.0
+ dyn = 0.0
+ dyd = 0.0
+
+ do j = 1, ny {
+ dy = real ((ly + j) - 1) - y
+ do i = 1, nx {
+ dx = real ((lx + i) - 1) - x
+ wt = (dx ** 2 + dy ** 2) / rsq
+ #if (wt >= 1.0)
+ if (wt >= 0.999998)
+ next
+ p = dp_profile (psftype, dx, dy, params, dhdxc, dhdyc, junk, 0)
+ dp = data[i,j] - h * p - sky
+ dhdxc = dhdxc * h
+ dhdyc = dhdyc * h
+ wt = 5.0 / (5.0 + (wt / (1.0 - wt)))
+ prod = wt * p
+ dhn = dhn + prod * dp
+ dhd = dhd + prod * p
+ prod = wt * dhdxc
+ dxn = dxn + prod * dp
+ dxd = dxd + prod * dhdxc
+ prod = wt * dhdyc
+ dyn = dyn + prod * dp
+ dyd = dyd + prod * dhdyc
+ }
+ }
+
+ h = h + (dhn / dhd)
+ dxn = dxn / dxd
+ if ((xold * dxn) < 0.0)
+ xclamp = 0.5 * xclamp
+ xold = dxn
+ x = x + (dxn / (1.0 + (abs(dxn) / xclamp)))
+ dyn = dyn / dyd
+ if ((yold * dyn) < 0.0)
+ yclamp = 0.5 * yclamp
+ yold = dyn
+ y = y + (dyn / (1.0 + (abs(dyn) / yclamp)))
+end
+
+
+# DP_PACCUM -- Accumulate the data for the parameter fit.
+
+procedure dp_paccum (psftype, params, npars, mpars, rsq, data, nx, ny, lx,
+ ly, x, y, sky, h, iter, c, v, temp, chi, sumwt)
+
+int psftype # analytic point spread function type
+real params[ARB] # current function parameter values
+int npars # number of function parameters
+int mpars # the number of active parameters
+real rsq # the fitting radius squared
+real data[nx,ARB] # the input image data
+int nx, ny # the dimensions of the input image data
+int lx, ly # the coordinates of the ll corner of the image data
+real x, y # the input/output stellar coordinates
+real sky # the input sky value
+real h # the input/output height value
+int iter # the current iteration
+real c[npars,ARB] # accumulation matrix
+real v[ARB] # accumulation vector
+real temp[ARB] # temporary storage vector
+real chi # the chi sum
+real sumwt # the number of points sum
+
+int i, j, k, l
+real peak, dx, dy, wt, dhdxc, dhdyc, p, dp
+real dp_profile()
+
+begin
+ peak = h * dp_profile (psftype, 0.0, 0.0, params, dhdxc, dhdyc, temp, 0)
+ do j = 1, ny {
+ dy = real ((ly + j) - 1) - y
+ do i = 1, nx {
+ dx = real ((lx + i) - 1) - x
+ wt = (dx ** 2 + dy ** 2) / rsq
+ #if (wt >= 1.0)
+ if (wt >= 0.999998)
+ next
+ p = dp_profile (psftype, dx, dy, params, dhdxc, dhdyc, temp, 1)
+ dp = data[i,j] - h * p - sky
+ do k = 1, mpars
+ temp[k] = h * temp[k]
+ chi = chi + (dp / peak) ** 2
+ sumwt = sumwt + 1.0
+ wt = 5.0 / (5.0 + (wt / (1.0 - wt)))
+ if (iter >= 4)
+ wt = wt / (1.0 + abs (20.0 * dp / peak))
+ do k = 1, mpars {
+ v[k] = v[k] + wt * dp * temp[k]
+ do l = 1, mpars {
+ c[l,k] = c[l,k] + wt * temp[l] * temp[k]
+ }
+ }
+ }
+ }
+end
+
+
+# DP_FITLT -- Given the analytic function compute the lookup tables.
+
+int procedure dp_fitlt (dao, im)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+
+int istar, nexp, lx, mx, ly, my, iter, nclean, ndata, fit_saturated, nfit
+int nunsat
+double volume
+pointer apsel, psf, psffit, sp, wimname, wim, data
+real datamin, datamax, sumfree, resid, dfdx, dfdy, junk
+int dp_dclean(), dp_resana(), dp_ltcompute(), dp_fsaturated()
+double dp_pnorm()
+pointer immap(), imps2r(), dp_subrast()
+real dp_profile(), dp_sweight()
+define fitsaturated_ 11
+
+begin
+ # Get some pointers.
+ apsel = DP_APSEL(dao)
+ psf = DP_PSF(dao)
+ psffit = DP_PSFFIT(dao)
+
+ # Check to see whether lookup tables are required.
+ nexp = DP_NVLTABLE(psffit) + DP_NFEXTABLE(psffit)
+ if (nexp <= 0)
+ return (OK)
+
+ # Return if there are too few stars to fit the lookup tables.
+ if (DP_PNUM(psf) < nexp)
+ return (ERR)
+
+ # Determine the number of saturated stars.
+ nunsat = 0
+ do istar = 1, DP_PNUM(psf) {
+ if (Memi[DP_PSAT(psf)+istar-1] == NO)
+ next
+ if ((Memr[DP_PH(psf)+istar-1] * dp_profile (DP_PSFUNCTION(psffit),
+ 0.0, 0.0, Memr[DP_PSFPARS(psffit)], dfdx, dfdy, junk, 0) +
+ Memr[DP_APMSKY(apsel)+istar-1]) <= datamax)
+ next
+ Memi[DP_PSAT(psf)+istar-1] = YES
+ Memr[DP_PH(psf)+istar-1] = INDEFR
+ nunsat = nunsat + 1
+ }
+ nunsat = DP_PNUM(psf) - nunsat
+
+ # Return if there are too few unsaturated psf stars to fit the lookup
+ # tables.
+ if (nunsat < nexp)
+ return (ERR)
+
+ # Allocate memory for computing lookup tables.
+ call dp_tmempsf (dao)
+
+ # Define some constants.
+ fit_saturated = DP_SATURATED(dao)
+ if (IS_INDEFR(DP_MINGDATA(dao)))
+ datamin = -MAX_REAL
+ else
+ datamin = DP_MINGDATA(dao)
+ if (IS_INDEFR(DP_MAXGDATA(dao)))
+ datamax = MAX_REAL
+ else
+ datamax = DP_MAXGDATA(dao)
+ sumfree = sqrt (DP_PSUMANA(psf) / (DP_PSUMANA(psf) - (nexp +
+ 3.0 * DP_PNUM(psf))))
+
+ # Get the image name.
+ call smark (sp)
+ call salloc (wimname, SZ_FNAME, TY_CHAR)
+ call mktemp ("tmp", Memc[wimname], SZ_FNAME)
+
+ # Open a temporary image to hold the weights.
+ wim = immap (Memc[wimname], NEW_IMAGE, 0)
+ IM_NDIM(wim) = 2
+ IM_LEN(wim,1) = DP_PNUM(psf)
+ IM_LEN(wim,2) = DP_PSFSIZE(psffit) * DP_PSFSIZE(psffit)
+ IM_PIXTYPE(wim) = TY_REAL
+
+ # Compute the constant part of the psf in preparation for normalizing
+ # the lookup tables.
+ if (nexp > 1)
+ call dp_pconst (DP_PSFUNCTION(psffit), Memr[DP_PSFPARS(psffit)],
+ Memr[DP_PH(psf)], Memr[DP_PCONST(psf)], DP_PSFSIZE(psffit))
+
+ nfit = 0
+
+fitsaturated_
+
+ # Compute the look-up table.
+ do iter = 1, DP_NCLEAN(dao) + 1 {
+
+ # Initialize the fitting arrays.
+ call aclrr (Memr[DP_PV(psf)], nexp)
+ call aclrr (Memr[DP_PC(psf)], nexp * nexp)
+ call aclrr (Memr[DP_PSUMN(psf)], DP_PSFSIZE(psffit) *
+ DP_PSFSIZE(psffit))
+ call aclrr (Memr[DP_PSUMSQ(psf)], DP_PSFSIZE(psffit) *
+ DP_PSFSIZE(psffit))
+ call aclrr (Memr[DP_PSFLUT(psffit)], nexp * DP_PSFSIZE(psffit) *
+ DP_PSFSIZE(psffit))
+
+ # Loop over the PSF stars.
+ do istar = 1, DP_PNUM(psf) {
+
+ # Get the weight image.
+ DP_PSUMW(psf) = imps2r (wim, istar, istar, 1,
+ DP_PSFSIZE(psffit) * DP_PSFSIZE(psffit))
+ call aclrr (Memr[DP_PSUMW(psf)], DP_PSFSIZE(psffit) *
+ DP_PSFSIZE(psffit))
+
+ # Skip saturated star?
+ if (IS_INDEFR(Memr[DP_PH(psf)+istar-1]))
+ next
+
+ # Get the data.
+ data = dp_subrast (im, Memr[DP_PXCEN(psf)+istar-1],
+ Memr[DP_PYCEN(psf)+istar-1], DP_PSFRAD(dao), lx, mx,
+ ly, my)
+
+ # Is the star off the image?
+ if (lx > IM_LEN(im,1) || ly > IM_LEN(im,2) || mx < 1 ||
+ my < 1) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("Star %d is outside the image\n")
+ call pargi (Memi[DP_APID(apsel)+istar-1])
+ }
+ next
+ }
+
+ # Clean bad pixels outside the fitting radius but inside
+ # the psf radius from the subraster.
+ nclean = dp_dclean (Memr[data], (mx - lx + 1), (my - ly + 1),
+ lx, ly, Memr[DP_PXCEN(psf)+istar-1], Memr[DP_PYCEN(psf)+
+ istar-1], DP_FITRAD(dao), datamin, datamax)
+
+ # Subtract the analytic part of the fit from the data
+ # and compute the normalized residual of the star.
+ ndata = dp_resana (im, DP_PSFUNCTION(psffit),
+ Memr[DP_PSFPARS(psffit)], Memr[data], (mx - lx + 1),
+ (my - ly + 1), lx, ly, Memr[DP_PXCEN(psf)],
+ Memr[DP_PYCEN(psf)], Memr[DP_APMSKY(apsel)],
+ Memr[DP_PH(psf)], DP_PNUM(psf), istar, DP_PSFRAD(dao),
+ DP_FITRAD(dao), datamax, resid)
+
+ # Compute the proper weight for the star.
+ if (IS_INDEFR(Memr[DP_PH(psf)+istar-1]) ||
+ Memr[DP_PH(psf)+istar-1] <= 0.0) {
+ Memr[DP_PWEIGHT(psf)+istar-1] = 0.0
+ } else if (Memi[DP_PSAT(psf)+istar-1] == YES) {
+ Memr[DP_PWEIGHT(psf)+istar-1] = 0.5 *
+ Memr[DP_PH(psf)+istar-1] / Memr[DP_PH(psf)]
+ } else {
+ Memr[DP_PWEIGHT(psf)+istar-1] = (Memr[DP_PH(psf)+
+ istar-1] / Memr[DP_PH(psf)]) * dp_sweight (resid,
+ sumfree, DP_PSIGANA(psf))
+ }
+
+ # Compute the expansion vector.
+ call dp_eaccum (Memr[DP_PXCEN(psf)+istar-1],
+ Memr[DP_PYCEN(psf)+istar-1], DP_PSFX(psffit),
+ DP_PSFY(psffit), Memr[DP_PTMP(psf)], DP_NVLTABLE(psffit),
+ DP_NFEXTABLE(psffit))
+
+ # Compute the contribution to the lookup table of the
+ # particular star.
+ call dp_ltinterp (Memr[data], (mx - lx + 1), (my - ly + 1),
+ lx, ly, Memr[DP_PXCEN(psf)+istar-1], Memr[DP_PYCEN(psf)+
+ istar-1], Memr[DP_APMSKY(apsel)+istar-1],
+ Memr[DP_PH(psf)+istar-1] / Memr[DP_PH(psf)],
+ Memr[DP_PWEIGHT(psf)+istar-1], Memr[DP_PSUMN(psf)],
+ Memr[DP_PSUMW(psf)], Memr[DP_PSUMSQ(psf)],
+ Memr[DP_PSIGMA(psf)], Memr[DP_POLDLUT(psf)],
+ Memr[DP_PTMP(psf)], Memr[DP_PSFLUT(psffit)], nexp,
+ DP_PSFSIZE(psffit), datamax, iter, DP_NCLEAN(dao) + 1)
+
+ call mfree (data, TY_REAL)
+ }
+
+ call imflush (wim)
+
+ # Compute the lookup table.
+ if (dp_ltcompute (Memr[DP_PXCEN(psf)], Memr[DP_PYCEN(psf)],
+ DP_PNUM(psf), DP_PSFX(psffit), DP_PSFY(psffit),
+ Memr[DP_PSUMN(psf)], wim, Memr[DP_PSFLUT(psffit)],
+ Memr[DP_PC(psf)], Memr[DP_PTMP(psf)], Memr[DP_PV(psf)],
+ nexp, DP_PSFSIZE(psffit), DP_NVLTABLE(psffit),
+ DP_NFEXTABLE(psffit)) == ERR) {
+ call sfree (sp)
+ return (ERR)
+ }
+
+
+ # Compute the standard deviation arrays for the next pass.
+ if (iter < (DP_NCLEAN(dao) + 1)) {
+ if (nunsat <= nexp)
+ break
+ call amovr (Memr[DP_PSFLUT(psffit)], Memr[DP_POLDLUT(psf)],
+ nexp * DP_PSFSIZE(psffit) * DP_PSFSIZE(psffit))
+ call dp_stdcompute (Memr[DP_PSUMN(psf)], Memr[DP_PSUMSQ(psf)],
+ Memr[DP_PSIGMA(psf)], DP_PSFSIZE(psffit),
+ DP_PSFSIZE(psffit), nexp)
+ }
+
+ }
+
+ if (nexp > 1) {
+
+ # Accumulate the v vector.
+ call dp_vaccum (Memr[DP_PXCEN(psf)], Memr[DP_PYCEN(psf)],
+ Memr[DP_PH(psf)], Memr[DP_PWEIGHT(psf)], DP_PNUM(psf),
+ DP_PSFX(psffit), DP_PSFY(psffit), Memr[DP_PTMP(psf)],
+ Memr[DP_PV(psf)], nexp, DP_NVLTABLE(psffit),
+ DP_NFEXTABLE(psffit))
+
+ # Compute the constant part of the psf.
+ volume = dp_pnorm (Memr[DP_PCONST(psf)], Memr[DP_PSIGMA(psf)],
+ DP_PSFSIZE(psffit))
+
+ # Normalize lookup tables.
+ call dp_ltnorm (Memr[DP_PCONST(psf)], Memr[DP_PV(psf)],
+ Memr[DP_PSFLUT(psffit)], Memr[DP_PSIGMA(psf)], nexp,
+ DP_PSFSIZE(psffit), volume)
+
+ }
+
+ # Make a copy of the psf.
+ call dp_pcopy (Memr[DP_PSFLUT(psffit)], Memr[DP_POLDLUT(psf)],
+ DP_PSFSIZE(psffit), DP_PSFSIZE(psffit), nexp)
+
+ # Include the saturated psf stars in the fit.
+ if (fit_saturated == YES) {
+ nfit = dp_fsaturated (dao, im, Memi[DP_APID(apsel)],
+ Memr[DP_PXCEN(psf)], Memr[DP_PYCEN(psf)], Memr[DP_PH(psf)],
+ Memr[DP_APMSKY(apsel)], Memi[DP_PSAT(psf)], DP_PNUM(psf))
+ fit_saturated = NO
+ if (nfit > 0) {
+ nunsat = nunsat + nfit
+ if (nexp > 1)
+ call aaddr (Memr[DP_PCONST(psf)], Memr[DP_POLDLUT(psf)],
+ Memr[DP_PCONST(psf)], DP_PSFSIZE(psffit) *
+ DP_PSFSIZE(psffit))
+ goto fitsaturated_
+ }
+ }
+
+ # Cleanup the temporary images and arrays.
+ call imunmap (wim)
+ call imdelete (Memc[wimname])
+ call sfree (sp)
+
+ return (OK)
+end
+
+
+# DP_DCLEAN -- Clean bad pixels that are outside the fitting radius from
+# the data. Note that the star must not be considered to be saturated to
+# arrive at this point.
+
+int procedure dp_dclean (data, nx, ny, lx, ly, x, y, fitrad, datamin, datamax)
+
+real data[nx,ARB] # the input image data
+int nx, ny # the dimensions of the input image data
+int lx, ly # the coordinates of the ll image corner
+real x, y # the input/output stellar coordinates
+real fitrad # the fitting radius
+real datamin # the min good data value
+real datamax # the max good data value
+
+bool redo
+int i, j, l, k, nclean
+real frad2, dy2, dr2, sumd, sumn
+
+begin
+ nclean = 0
+ repeat {
+
+ redo = false
+ frad2 = fitrad ** 2
+
+ do j = 1, ny {
+
+ dy2 = (real ((ly - 1) + j) - y) ** 2
+ if (dy2 < frad2)
+ next
+ do i = 1, nx {
+
+ if (data[i,j] >= datamin && data[i,j] <= datamax)
+ next
+ dr2 = dy2 + (real ((lx - 1) + i) - x) ** 2
+ if (dr2 < frad2)
+ next
+
+ sumd = 0.0
+ sumn = 0.0
+ do l = max (1, j-1), min (ny, j+2) {
+ do k = max (1, i-1), min (nx, i+2) {
+ if (data[k,l] < datamin || data[k,l] > datamax)
+ next
+ sumd = sumd + data[k,l]
+ sumn = sumn + 1.0
+ }
+ }
+ if (sumn < 2.5)
+ redo = true
+ else {
+ nclean = nclean + 1
+ data[i,j] = sumd / sumn
+ }
+ }
+ }
+
+ } until (! redo)
+
+ return (nclean)
+end
+
+
+# DP_RESANA -- Compute the residuals from the analytic function.
+
+int procedure dp_resana (im, psftype, params, data, nx, ny, lx, ly,
+ x, y, sky, h, nstar, psfstar, psfrad, fitrad, maxgdata, resid)
+
+pointer im # the input image descriptor
+int psftype # analytic point spread function type
+real params[ARB] # current function parameter values
+real data[nx,ARB] # the input image data
+int nx, ny # the dimensions of the input image data
+int lx, ly # the coordinates of the ll image corner
+real x[ARB] # the input x coords of the psf stars
+real y[ARB] # the input y coords of the psf stars
+real sky[ARB] # the input sky values of the psf stars
+real h[ARB] # the input height values of the psf stars
+int nstar # the number of psf stars
+int psfstar # the psf star in question
+real psfrad # the psf radius
+real fitrad # the fitting radius
+real maxgdata # the maximum good data value
+real resid # standard deviation of fit
+
+int i, j, istar, rx, ry, x1, x2, y1, y2, nresid
+real frad2, dx, dy, dy2, dr2, p, dhdxc, dhdyc, junk
+int dp_lsubrast()
+real dp_profile()
+
+begin
+ frad2 = fitrad ** 2
+ rx = lx + nx - 1
+ ry = ly + ny - 1
+
+ resid = 0.0
+ nresid = 0
+ do istar = 1, nstar {
+
+ # Check for saturation.
+ if (IS_INDEFR(h[istar]))
+ next
+
+ # Does the subraster of another PSF star overlap the current
+ # subraster ?.
+ if (dp_lsubrast (im, x[istar], y[istar], psfrad, x1, x2,
+ y1, y2) == ERR)
+ next
+ if (x2 < lx || y2 < ly || x1 > rx || y1 > ry)
+ next
+
+ # Check the limits of overlap.
+ if (x1 < lx)
+ x1 = lx
+ if (x2 > rx)
+ x2 = rx
+ if (y1 < ly)
+ y1 = ly
+ if (y2 > ry)
+ y2 = ry
+
+ # Subract off the analytic part of the fits and accumulate
+ # the residuals for the psf star.
+ do j = y1 - ly + 1, y2 - ly + 1 {
+ dy = real ((ly - 1) + j) - y[istar]
+ dy2 = dy ** 2
+ do i = x1 - lx + 1, x2 - lx + 1 {
+ if (data[i,j] > maxgdata)
+ next
+ dx = real ((lx - 1) + i) - x[istar]
+ p = dp_profile (psftype, dx, dy, params, dhdxc, dhdyc,
+ junk, 0)
+ data[i,j] = data[i,j] - h[istar] * p
+ if (istar != psfstar)
+ next
+ dr2 = dy2 + dx ** 2
+ if (dr2 >= frad2)
+ next
+ resid = resid + (data[i,j] - sky[istar]) ** 2
+ nresid = nresid + 1
+ }
+ }
+ }
+
+ if (nresid <= 0)
+ resid = 0.0
+ else
+ resid = sqrt (resid / nresid) / (h[psfstar] * dp_profile (psftype,
+ 0.0, 0.0, params, dhdxc, dhdyc, junk, 0))
+
+ return (nresid)
+end
+
+
+# DP_SWEIGHT -- Compute the weight for the star.
+
+real procedure dp_sweight (resid, sumfree, sumana)
+
+real resid # normalized residual wrt analytic fit
+real sumfree # number of degrees of freedom
+real sumana # number of points contributing to analytic fit
+
+real weight
+
+begin
+ weight = resid * sumfree / sumana
+ weight = 1.0 / (1.0 + (weight / 2.0) ** 2)
+ return (weight)
+end
+
+
+# DP_EACCUM -- Calcuate the expansion vector for a single PSF star.
+
+procedure dp_eaccum (x, y, xmid, ymid, junk, nvexp, nfexp)
+
+real x, y # the stellar coordinates
+real xmid, ymid # the psf coordinates
+real junk[ARB] # temporary storage vector
+int nvexp # the number of variable psf look-up tables
+int nfexp # the number of pixel expansion tables
+
+int j
+
+begin
+ # The variable psf terms.
+ switch (nvexp) {
+ case 1:
+ junk[1] = 1.0
+ case 3:
+ junk[1] = 1.0
+ junk[2] = ((x - 1.0) / xmid) - 1.0
+ junk[3] = ((y - 1.0) / ymid) - 1.0
+ case 6:
+ junk[1] = 1.0
+ junk[2] = ((x - 1.0) / xmid) - 1.0
+ junk[3] = ((y - 1.0) / ymid) - 1.0
+ junk[4] = (1.5 * (junk[2] ** 2)) - 0.5
+ junk[5] = junk[2] * junk[3]
+ junk[6] = (1.5 * (junk[3] ** 2)) - 0.5
+ }
+
+ # The fractional pixel expansion terms if any.
+ if (nfexp > 0) {
+ j = nvexp + 1
+ junk[j] = 2.0 * (x - real (nint(x)))
+ j = j + 1
+ junk[j] = 2.0 * (y - real (nint(y)))
+ j = j + 1
+ junk[j] = (1.5 * (junk[j-2] ** 2)) - 0.5
+ j = j + 1
+ junk[j] = junk[j-3] * junk[j-2]
+ j = j + 1
+ junk[j] = (1.5 * (junk[j-3] ** 2)) - 0.5
+ }
+
+end
+
+
+# DP_LTINTERP -- Compute the contribution to the lookup table of a single
+# PSF star.
+
+procedure dp_ltinterp (data, nx, ny, lx, ly, x, y, sky, hratio, weight, sumn,
+ sumw, sumsq, sig, old, temp, psflut, nexp, nxlut, maxgdata, iter, niter)
+
+real data[nx,ARB] # the input image data
+int nx, ny # the dimensions of the input image data
+int lx, ly # the coordinates of the ll image corner
+real x, y # the input/output stellar coordinates
+real sky # sky value for star
+real hratio # scale factor for star
+real weight # weight for the star
+real sumn[nxlut,ARB] # number of points
+real sumw[nxlut,ARB] # sum of the weights
+real sumsq[nxlut,ARB] # sum of the residuals
+real sig[nxlut,ARB] # residuals of previous iteration
+real old[nexp,nxlut,ARB] # old lookup table
+real temp[ARB] # the single star expansion vector
+real psflut[nexp,nxlut,ARB] # the psf lookup table
+int nexp, nxlut # the dimensions of the lookup table
+real maxgdata # maximum good data value
+int iter # the current iteration
+int niter # the maximum number of iterations
+
+bool omit
+int i, j, k, kx, ky, ii, jj, middle, jysq, irsq, midsq
+real jy, ix, dx, dy, diff, dfdx, dfdy, wt, oldsum
+real bicubic()
+
+begin
+ middle = (nxlut + 1) / 2
+ midsq = middle ** 2
+ do j = 1, nxlut {
+ jysq = (j - middle) ** 2
+ if (jysq > midsq)
+ next
+ jy = y + real (j - (nxlut + 1) / 2) / 2.0 - real (ly - 1)
+ ky = int (jy)
+ if (ky < 2 || (ky + 2) > ny)
+ next
+ dy = jy - real (ky)
+ do i = 1, nxlut {
+ irsq = jysq + (i - middle) ** 2
+ if (irsq > midsq)
+ next
+ ix = x + real (i - (nxlut + 1) / 2) / 2.0 - real (lx - 1)
+ kx = int (ix)
+ if (kx < 2 || (kx + 2) > nx)
+ next
+ omit = false
+ do jj = ky - 1, ky + 2 {
+ do ii = kx - 1, kx + 2 {
+ if (data[ii,jj] <= maxgdata)
+ next
+ omit = true
+ }
+ }
+ if (omit)
+ next
+ dx = ix - real (kx)
+ diff = (bicubic (data[kx-1,ky-1], nx, dx, dy, dfdx, dfdy) -
+ sky) / hratio
+ if (iter == 1 || sig[i,j] <= 0.0) {
+ wt = 1.0
+ } else {
+ oldsum = 0.0
+ do k = 1, nexp
+ oldsum = oldsum + old[k,i,j] * temp[k]
+ if ((iter - 1) <= max (3, (niter - 1) / 2))
+ wt = 1.0 / (1.0 + abs (diff - oldsum) / sig[i,j])
+ else
+ wt = 1.0 / (1.0 + ((diff - oldsum) / sig[i,j]) ** 2)
+ }
+ wt = wt * weight
+ sumn[i,j] = sumn[i,j] + 1.0
+ sumw[i,j] = wt
+ sumsq[i,j] = sumsq[i,j] + abs (diff)
+ psflut[1,i,j] = psflut[1,i,j] + wt * diff
+ if (nexp <= 1)
+ next
+ do k = 2, nexp
+ psflut[k,i,j] = psflut[k,i,j] + (temp[k] * wt * diff)
+ }
+ }
+end
+
+
+# DP_LTCOMPUTE -- Compute the lookup table.
+
+int procedure dp_ltcompute (x, y, npsf, xmid, ymid, sumn, wim, psflut, c,
+ junk, v, nexp, nxlut, nvexp, nfexp)
+
+real x[ARB] # array of psf star x coordinates
+real y[ARB] # array of psf star y coordinates
+int npsf # the number of psf stars
+real xmid, ymid # the mid-point of the psf
+real sumn[nxlut,ARB] # number of points
+pointer wim # pointer to the temporary weight image
+real psflut[nexp,nxlut,ARB] # the psf lookup table
+real c[nexp,ARB] # the expansion matrix
+real junk[ARB] # temporary junk vector
+real v[ARB] # temporary vector
+int nexp, nxlut # the size of the lookup table
+int nvexp, nfexp # size of the expansion look-up tables
+
+int i, j, k, l, line, istar, ier, middle, midsq, jysq, irsq
+pointer sumw
+real weight
+pointer imgs2r()
+
+begin
+ middle = (nxlut + 1) / 2
+ midsq = middle ** 2
+ do j = 1, nxlut {
+ jysq = (j - middle) ** 2
+ if (jysq > midsq)
+ next
+ do i = 1, nxlut {
+ irsq = (i - middle) ** 2 + jysq
+ if (irsq > midsq)
+ next
+ if (nint (sumn[i,j]) < nexp)
+ return (ERR)
+ line = i + (j - 1) * nxlut
+ sumw = imgs2r (wim, 1, npsf, line, line)
+ do k = 1, nexp
+ do l = 1, nexp
+ c[k,l] = 0.0
+ do istar = 1, npsf {
+ weight = Memr[sumw+istar-1]
+ if (weight <= 0.0)
+ next
+ call dp_eaccum (x[istar], y[istar], xmid, ymid, junk,
+ nvexp, nfexp)
+ do k = 1, nexp
+ do l = 1, nexp
+ c[k,l] = c[k,l] + weight * junk[k] * junk[l]
+ }
+ call invers (c, nexp, nexp, ier)
+ call mvmul (c, nexp, nexp, psflut[1,i,j], v)
+ do k = 1, nexp
+ psflut[k,i,j] = v[k]
+ }
+ }
+
+ return (OK)
+end
+
+
+# DP_STDCOMPUTE -- Estimate the standard deviation of the fit.
+
+procedure dp_stdcompute (sumn, sumsq, sigma, nx, ny, nexp)
+
+real sumn[nx,ARB] # number of point
+real sumsq[nx,ARB] # sum of the standard deviations
+real sigma[nx,ARB] # output standard deviation array
+int nx, ny # size of the arrays
+int nexp # number of expansion vectors
+
+int i, j
+
+begin
+ do j = 1, ny {
+ do i = 1, nx {
+ if (sumn[i,j] <= nexp)
+ sigma[i,j] = 0.0
+ else
+ sigma[i,j] = 1.2533 * sumsq[i,j] / sqrt (sumn[i,j] *
+ (sumn[i,j] - nexp))
+ }
+ }
+end
+
+
+# DP_VACCUM -- Accumulate the expansion vector.
+
+procedure dp_vaccum (x, y, h, weight, nstar, xmid, ymid, junk, avetrm,
+ nexp, nvexp, nfexp)
+
+real x[ARB] # the stellar x coordinates
+real y[ARB] # the stellar y coordinates
+real h[ARB] # the stellar heights
+real weight[ARB] # the stellar weights
+int nstar # number of stars
+real xmid, ymid # the psf coordinates
+real junk[ARB] # temporary storage vector
+real avetrm[ARB] # the expansion vector
+int nexp # the total number of expansion terms
+int nvexp # number of variable expansion terms
+int nfexp # number of fractional pixel expansion terms
+
+int k, j
+
+begin
+ # Zero the accumulation vector
+ do j = 1, nexp
+ avetrm[j] = 0.0
+
+ do k = 1, nstar {
+ if (IS_INDEFR(h[k]))
+ next
+
+ # The variable psf expansion terms.
+ switch (nvexp) {
+ case 1:
+ junk[1] = 1.0
+ case 3:
+ junk[1] = 1.0
+ junk[2] = ((x[k] - 1.0) / xmid) - 1.0
+ junk[3] = ((y[k] - 1.0) / ymid) - 1.0
+ case 6:
+ junk[1] = 1.0
+ junk[2] = ((x[k] - 1.0) / xmid) - 1.0
+ junk[3] = ((y[k] - 1.0) / ymid) - 1.0
+ junk[4] = (1.5 * (junk[2] ** 2)) - 0.5
+ junk[5] = junk[2] * junk[3]
+ junk[6] = (1.5 * (junk[3] ** 2)) - 0.5
+ }
+
+ # The fractional pixel expansion terms if any.
+ if (nfexp > 0) {
+ j = nvexp + 1
+ junk[j] = 2.0 * (x[k] - real (nint(x[k])))
+ j = j + 1
+ junk[j] = 2.0 * (y[k] - real (nint(y[k])))
+ j = j + 1
+ junk[j] = (1.5 * (junk[j-2] ** 2)) - 0.5
+ j = j + 1
+ junk[j] = junk[j-3] * junk[j-2]
+ j = j + 1
+ junk[j] = (1.5 * (junk[j-3] ** 2)) - 0.5
+ }
+
+ # Accumulate the expansion vector.
+ do j = 1, nexp
+ avetrm[j] = avetrm[j] + weight[k] * junk[j]
+ }
+
+ # Average the expansion vector.
+ do j = nexp, 1, -1
+ avetrm[j] = avetrm[j] / avetrm[1]
+end
+
+
+# DP_PCONST -- Compute the analytic part of the psf.
+
+procedure dp_pconst (psftype, params, hpsf1, ana, nxlut)
+
+int psftype # the type of analytic psf function
+real params[ARB] # the analytic parameters array
+real hpsf1 # the height of the psf function
+real ana[nxlut,ARB] # the computed analytic function
+int nxlut # the size of the constant lookup table
+
+int i, j, middle, midsq, dj2, dr2
+real dx, dy, dfdx, dfdy, junk
+real dp_profile()
+
+begin
+ # Compute the constant part of the psf.
+ middle = (nxlut + 1) / 2
+ midsq = middle ** 2
+ do j = 1, nxlut {
+ dj2 = (j - middle) ** 2
+ if (dj2 > midsq)
+ next
+ dy = real (j - middle) / 2.0
+ do i = 1, nxlut {
+ dr2 = (i - middle) ** 2 + dj2
+ if (dr2 > midsq)
+ next
+ dx = real (i - middle) / 2.0
+ ana[i,j] = hpsf1 * dp_profile (psftype, dx, dy, params,
+ dfdx, dfdy, junk, 0)
+ }
+ }
+end
+
+
+# DP_PNORM -- Compute the psf normalization parameters.
+
+double procedure dp_pnorm (ana, pixels, nxlut)
+
+real ana[nxlut,ARB] # the computed analytic function
+real pixels[ARB] # pixel storage array
+int nxlut # the size of the constant lookup table
+
+int i, j, middle, midsq, edgesq, npts, dj2, dr2
+double vol
+real median
+real pctile()
+
+begin
+ # Ensure that the profile which will be added and subtracted
+ # from the various lookup tables has a median value of zero
+ # around the rim
+
+ middle = (nxlut + 1) / 2
+ midsq = middle ** 2
+ edgesq = (middle - 2) ** 2
+ npts = 0
+ do j = 1, nxlut {
+ dj2 = (j - middle) ** 2
+ if (dj2 > midsq)
+ next
+ do i = 1, nxlut {
+ dr2 = (i - middle) ** 2 + dj2
+ if (dr2 > midsq)
+ next
+ if (dr2 < edgesq)
+ next
+ npts = npts + 1
+ pixels[npts] = ana[i,j]
+ }
+ }
+ median = pctile (pixels, npts, (npts+1) / 2)
+
+ vol = 0.0d0
+ do j = 1, nxlut {
+ dj2 = (j - middle) ** 2
+ if (dj2 > midsq)
+ next
+ do i = 1, nxlut {
+ dr2 = (i - middle) ** 2 + dj2
+ if (dr2 > midsq)
+ next
+ ana[i,j] = ana[i,j] - median
+ vol = vol + double (ana[i,j])
+ }
+ }
+
+ return (vol)
+end
+
+
+# DP_LTNORM -- Compute the final lookup table.
+
+procedure dp_ltnorm (ana, v, psflut, pixels, nexp, nxlut, volume)
+
+real ana[nxlut,ARB] # analytic part of the profile
+real v[ARB] # the expansion vector
+real psflut[nexp,nxlut,ARB] # the psf lookup table
+real pixels[ARB] # scratch array for determining median
+int nexp, nxlut # the size of the lookup table
+double volume # total flux in the constant psf
+
+int i, j, k, middle, midsq, edgesq, npts, dj2, dr2
+double sum
+real median, dmedian
+real pctile()
+
+begin
+ # Ensure that the psf which will be added and subtracted from the
+ # various lookup tables has a median value of zero around the rim.
+
+ middle = (nxlut + 1) / 2
+ midsq = middle ** 2
+ edgesq = (middle - 2) ** 2
+ do k = 2, nexp {
+
+ npts = 0
+ do j = 1, nxlut {
+ dj2 = (j - middle) ** 2
+ if (dj2 > midsq)
+ next
+ do i = 1, nxlut {
+ dr2 = (i - middle) ** 2 + dj2
+ if (dr2 > midsq)
+ next
+ if (dr2 < edgesq)
+ next
+ npts = npts + 1
+ pixels[npts] = psflut[k,i,j]
+ }
+ }
+
+ median = pctile (pixels, npts, (npts+1) / 2)
+ dmedian = v[k] * median
+
+ do j = 1, nxlut {
+ dj2 = (j - middle) ** 2
+ if (dj2 > midsq)
+ next
+ do i = 1, nxlut {
+ dr2 = (i - middle) ** 2 + dj2
+ if (dr2 > midsq)
+ next
+ psflut[k,i,j] = psflut[k,i,j] - median
+ psflut[1,i,j] = psflut[1,i,j] + dmedian
+ }
+ }
+ }
+
+ # Determine the net volume of each of the higher order PSF
+ # tables and force it to zero by subtracting a scaled copy
+ # of the constant psf. Scale the part that has been subtracted
+ # off by the mean polynomial term and add it in to the constant
+ # part of the psf so that at the centroid of the psf stars
+ # positions the psf remains unchanged.
+
+ do k = 2, nexp {
+
+ sum = 0.0d0
+ do j = 1, nxlut {
+ dj2 = (j - middle) ** 2
+ if (dj2 > midsq)
+ next
+ do i = 1, nxlut {
+ dr2 = (i - middle) ** 2 + dj2
+ if (dr2 > midsq)
+ next
+ sum = sum + double (psflut[k,i,j])
+ }
+ }
+
+ median = real (sum / volume)
+ dmedian = v[k] * median
+
+ do j = 1, nxlut {
+ dj2 = (j - middle) ** 2
+ if (dj2 > midsq)
+ next
+ do i = 1, nxlut {
+ dr2 = (i - middle) ** 2 + dj2
+ if (dr2 > midsq)
+ next
+ psflut[k,i,j] = psflut[k,i,j] - median * ana[i,j]
+ psflut[1,i,j] = psflut[1,i,j] + dmedian * ana[i,j]
+ }
+ }
+ }
+end
+
+
+# DP_FSATURATED -- Fit the saturated stars.
+
+int procedure dp_fsaturated (dao, im, id, xcen, ycen, h, sky, sat, nstars)
+
+pointer dao # pointer to the main daophot structure
+pointer im # pointer to the input image
+int id[ARB] # array of stellar ids
+real xcen[ARB] # array of stellar y coordinates
+real ycen[ARB] # array of stellar y coordinates
+real h[ARB] # array of stellar amplitudes
+real sky[ARB] # array of sky values
+int sat[ARB] # array of saturation indicators
+int nstars # number of stars
+
+int nfit, nsat, istar, lowx, lowy, nxpix, nypix, recenter, fitsky
+int clipexp, ier, niter
+pointer psf, psffit, subim, psflut
+real x, y, dx, dy, skyval, scale, errmag, chi, sharp, cliprange
+int dp_pkfit()
+pointer dp_gsubrast()
+
+begin
+ # Get some pointers.
+ psf = DP_PSF(dao)
+ psffit = DP_PSFFIT(dao)
+
+ # Allocate memory.
+ call dp_pksetup (dao)
+ call dp_mempk (dao, 3)
+
+ # Save the default values of some critical parameters.
+ recenter = DP_RECENTER(dao)
+ fitsky = DP_FITSKY(dao)
+ psflut = DP_PSFLUT(psffit)
+ clipexp = DP_CLIPEXP(dao)
+ cliprange = DP_CLIPRANGE(dao)
+
+ # Set some fitting parameters.
+ DP_RECENTER(dao) = YES
+ DP_FITSKY(dao) = NO
+ DP_CLIPEXP(dao) = 8
+ DP_CLIPRANGE(dao) = 2.5
+ DP_PSFLUT(psffit) = DP_POLDLUT(psf)
+
+ nfit = 0
+ nsat = 0
+ do istar = 1, nstars {
+
+ # Skip saturated stars.
+ if (sat[istar] == NO)
+ next
+ nsat = nsat + 1
+
+ # Get the data.
+ subim = dp_gsubrast (im, xcen[istar], ycen[istar], DP_PSFRAD(dao),
+ lowx, lowy, nxpix, nypix)
+ if (subim == NULL)
+ next
+
+ # Set the intial values for the fit parameters.
+ x = xcen[istar] - lowx + 1.0
+ y = ycen[istar] - lowy + 1.0
+ dx = (xcen[istar] - 1.0) / DP_PSFX(psffit) - 1.0
+ dy = (ycen[istar] - 1.0) / DP_PSFY(psffit) - 1.0
+ skyval = sky[istar]
+ scale = 3.0
+
+ # Fit the star.
+ ier = dp_pkfit (dao, Memr[subim], nxpix, nypix, 0.5 *
+ DP_PSFRAD(dao), x, y, dx, dy, scale, skyval, errmag, chi,
+ sharp, niter)
+
+ # Compute the fit parameters.
+ if (ier != PKERR_OK) {
+ scale = INDEFR
+ errmag = INDEFR
+ niter = 0
+ chi = INDEFR
+ sharp = INDEFR
+ } else {
+ nfit = nfit + 1
+ xcen[istar] = x + lowx - 1.0
+ ycen[istar] = y + lowy - 1.0
+ h[istar] = scale * h[1]
+ errmag = 1.085736 * errmag / scale
+ if (errmag >= 2.0)
+ errmag = INDEFR
+ scale = DP_PSFMAG(psffit) - 2.5 * log10 (scale)
+ }
+
+ if (DP_VERBOSE(dao) == YES) {
+ if (nsat == 1)
+ call printf ("\nFit for saturated stars\n")
+ call printf (
+ " %6d %7.2f %7.2f %8.3f %6.3f %3d %7.2f %7.2f\n")
+ call pargi (id[istar])
+ call pargr (xcen[istar])
+ call pargr (ycen[istar])
+ call pargr (scale)
+ call pargr (errmag)
+ call pargi (niter)
+ call pargr (chi)
+ call pargr (sharp)
+ }
+ }
+
+ if (DP_VERBOSE(dao) == YES && nsat > 0)
+ call printf ("\n")
+
+ # Restore the default values of some critical parameters.
+ DP_RECENTER(dao) = recenter
+ DP_FITSKY(dao) = fitsky
+ DP_CLIPEXP(dao) = clipexp
+ DP_CLIPRANGE(dao) = cliprange
+ DP_PSFLUT(psffit) = psflut
+
+ # Free memory.
+ call dp_pkclose (dao)
+
+ return (nfit)
+end
+
+
+# DP_PCOPY -- Make a copy of the psf in correct storage order.
+
+procedure dp_pcopy (inlut, outlut, nx, ny, nexp)
+
+real inlut[nexp,nx,ny] # the input look-up table
+real outlut[nx,ny,nexp] # the output look-up table
+int nx,ny,nexp # the size of the look-up table
+
+int k,i,j
+
+begin
+ do k = 1, nexp {
+ do j = 1, ny {
+ do i = 1, nx {
+ outlut[i,j,k] = inlut[k,i,j]
+ }
+ }
+ }
+end
diff --git a/noao/digiphot/daophot/psf/dpispstars.x b/noao/digiphot/daophot/psf/dpispstars.x
new file mode 100644
index 00000000..85a4c669
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dpispstars.x
@@ -0,0 +1,329 @@
+include <fset.h>
+include <ctype.h>
+include <gset.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/psfdef.h"
+
+define HELPFILE "daophot$psf/mkpsflist.key"
+
+# DP_IPFSTARS -- Construct a stellar PSF from one or more stars in an image
+# frame.
+
+int procedure dp_ipfstars (dao, im, maxnpsf, lolimit, radius, gd, mgd, id,
+ mkstars, interactive, showplots)
+
+pointer dao # pointer to DAOPHOT structure
+pointer im # pointer to IRAF image
+int maxnpsf # maximum number of psf stars
+real lolimit # lower magnitude limit for stars
+real radius # the confusion radius for good psf stars
+pointer gd # pointer to graphics descriptor
+pointer mgd # pointer to the metacode file
+pointer id # pointer to image display stream
+bool mkstars # marked the selected and deleted psf stars
+bool interactive # interactive mode
+bool showplots # show the plots
+
+int key, nxstar, wcs, idnum, istar, ip
+pointer apsel, sp, cmd, str
+real wx, wy
+
+real dp_pstatr()
+int clgcur(), dp_pqverify(), dp_locstar(), dp_idstar(), dp_nxstar()
+int dp_pstati(), ctoi(), dp_addstar(), dp_delstar()
+
+begin
+ # Get some pointers
+ apsel = DP_APSEL(dao)
+
+ # Allocate some working space.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Initialize some variables.
+ key = 'a'
+ nxstar = 0
+ call dp_pseti (dao, PNUM, 0)
+
+ # Begin to build the PSF.
+ while (clgcur ("icommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+
+ # Correct for tv coordinates if necessary.
+ call dp_vtol (im, wx, wy, wx, wy, 1)
+
+ switch (key) {
+
+ # Quit the interactive cursor loop.
+ case 'q':
+ if (interactive) {
+ if (dp_pqverify() == YES)
+ break
+ } else
+ break
+
+ # Print the help page.
+ case '?':
+ if (id == NULL)
+ call pagefile (HELPFILE, "")
+ else
+ call gpagefile (id, HELPFILE, "")
+
+ # Add next candidate star to the PSF.
+ case 'n':
+ if (dp_pstati (dao, PNUM) >= maxnpsf) {
+ call printf ("Number of psf stars is >= to maxnpsf\n")
+ next
+ }
+ idnum = dp_nxstar (Memi[DP_APID(apsel)], Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMSKY(apsel)],
+ Memr[DP_APMAG(apsel)], DP_APNUM(apsel), nxstar, lolimit,
+ radius)
+ if (idnum <= 0) {
+ call printf ("No more good psf stars in photometry list\n")
+ next
+ }
+ if (dp_addstar (dao, im, wx, wy, INDEFR, idnum, gd, mgd,
+ showplots) == ERR)
+ next
+ if (mkstars && id != NULL) {
+ call gmark (id, dp_pstatr (dao, CUR_PSFX), dp_pstatr (dao,
+ CUR_PSFY), GM_PLUS, -5.0, -5.0)
+ if (gd == id)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ # Add the star nearest the cursor position to the PSF.
+ case 'a':
+ if (dp_pstati (dao, PNUM) >= maxnpsf) {
+ call printf ("Number of psf stars is >= to maxnpsf\n")
+ next
+ }
+ if (dp_addstar (dao, im, wx, wy, INDEFR, 0, gd, mgd,
+ showplots) == ERR)
+ next
+ if (mkstars && id != NULL) {
+ call gmark (id, dp_pstatr (dao, CUR_PSFX), dp_pstatr (dao,
+ CUR_PSFY), GM_PLUS, -5.0, -5.0)
+ if (gd == id)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ # Delete the star nearest the cursor position from the PSF.
+ case 'd':
+ if (dp_delstar (dao, im, wx, wy, 0, gd, showplots) == ERR)
+ next
+ if (mkstars && id != NULL) {
+ call gmark (id, dp_pstatr (dao, CUR_PSFX), dp_pstatr (dao,
+ CUR_PSFY), GM_CROSS, -5.0, -5.0)
+ if (gd == id)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ # List all the current psf stars.
+ case 'l':
+ if (interactive)
+ call dp_listpsf (dao, im)
+
+ # Locate the star in the aperture photometry file and print out
+ # the photometry.
+ case 'p':
+ if (interactive)
+ istar = dp_locstar (dao, im, wx, wy)
+ else
+ next
+ if (istar > 0)
+ call dp_pshow (dao, im, istar)
+ else if (istar == 0)
+ call printf ("Star not found in the photometry file\n")
+ else
+ call printf (
+ "Star off or too near the edge of the image\n")
+
+ # Colon command mode.
+ case ':':
+ for (ip = 1; IS_WHITE(Memc[cmd+ip-1]); ip = ip + 1)
+ ;
+ switch (Memc[cmd+ip-1]) {
+
+ case 'p':
+ if (! interactive)
+ next
+ ip = ip + 1
+ if (ctoi (Memc[cmd], ip, idnum) <= 0)
+ istar = dp_locstar (dao, im, wx, wy)
+ else
+ istar = dp_idstar (dao, im, idnum)
+ if (istar > 0)
+ call dp_pshow (dao, im, istar)
+ else if (istar == 0)
+ call printf (
+ "Star not found in the photometry file\n")
+ else
+ call printf (
+ "Star is off or too near the edge of the image.\n")
+
+ case 'a':
+ if (dp_pstati (dao, PNUM) >= maxnpsf) {
+ call printf (
+ "Number of psf stars is >= to maxnpsf\n")
+ next
+ }
+ ip = ip + 1
+ if (ctoi (Memc[cmd], ip, idnum) <= 0)
+ idnum = 0
+ if (dp_addstar (dao, im, wx, wy, INDEFR, idnum, gd, mgd,
+ showplots) == ERR)
+ next
+ if (mkstars && id != NULL) {
+ call gmark (id, dp_pstatr (dao, CUR_PSFX),
+ dp_pstatr (dao, CUR_PSFY), GM_PLUS, -5.0, -5.0)
+ if (gd == id)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ case 'd':
+ ip = ip + 1
+ if (ctoi (Memc[cmd], ip, idnum) <= 0)
+ idnum = 0
+ if (dp_delstar (dao, im, wx, wy, idnum, gd, showplots) ==
+ ERR)
+ next
+ if (mkstars && id != NULL) {
+ call gmark (id, dp_pstatr (dao, CUR_PSFX),
+ dp_pstatr (dao, CUR_PSFY), GM_CROSS, -5.0, -5.0)
+ if (gd == id)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ default:
+ call printf ("Unknown keystroke command\n")
+ }
+
+ default:
+ call printf ("Unknown keystroke command\n")
+ }
+ }
+
+ # Free up memory.
+ call sfree (sp)
+
+ return (dp_pstati (dao, PNUM))
+end
+
+
+define QUERY "[Hit return to continue, q to quit]"
+
+# DP_PQVERIFY -- Print a message in the status line asking the user if they
+# really want to quit, returning YES if they really want to quit, NO otherwise.
+
+int procedure dp_pqverify ()
+
+int ch
+pointer tty
+int getci()
+pointer ttyodes()
+
+begin
+ # Open terminal and print query.
+ tty = ttyodes ("terminal")
+ call ttyclearln (STDOUT, tty)
+ call ttyso (STDOUT, tty, YES)
+ call printf (QUERY)
+ call flush (STDOUT)
+
+ # Get character.
+ call fseti (STDIN, F_RAW, YES)
+ if (getci (STDIN, ch) == EOF)
+ ;
+
+ # Reset and close terminal.
+ call fseti (STDIN, F_RAW, NO)
+ call ttyso (STDOUT, tty, NO)
+ call ttyclearln (STDOUT, tty)
+ call printf ("\n")
+ call flush (STDOUT)
+ call ttycdes (tty)
+
+ # Return YES for the quit command, otherwise NO.
+ if (ch == 'q') {
+ return (YES)
+ } else {
+ return (NO)
+ }
+end
+
+
+
+# DP_NXSTAR -- Select the next psf star form the photometry list.
+
+int procedure dp_nxstar (ids, xcen, ycen, sky, mag, nstar, nxstar, lolimit,
+ radius)
+
+int ids[ARB] # array of star ids
+real xcen[ARB] # array of x coordinates
+real ycen[ARB] # array of y coordinates
+real sky[ARB] # array of sky values
+real mag[ARB] # array of magnitudes
+int nstar # the number of stars
+int nxstar # the current star
+real lolimit # lower data limit
+real radius # minimum separation
+
+bool omit
+int istar, jstar
+real radsq, dy2, dr2
+
+begin
+ radsq = radius * radius
+
+ # Check the first star.
+ if ((mag[1] > lolimit) && (nxstar == 0)) {
+ nxstar = 1
+ return (ids[1])
+ }
+
+ # Loop over the candidate psf stars.
+ do istar = nxstar + 1, nstar {
+
+ # Test that the candidate psf stars are not saturated and
+ # are sufficiently far from the edge of the frame.
+
+ if (mag[istar] <= lolimit)
+ next
+
+ # Text that there are no brighter stars with a distance squared
+ # of radsq.
+ omit = false
+ do jstar = 1, istar - 1 {
+ dy2 = abs (ycen[jstar] - ycen[istar])
+ if (dy2 >= radius)
+ next
+ dr2 = (xcen[jstar] - xcen[istar]) ** 2 + dy2 ** 2
+ if (dr2 >= radsq)
+ next
+ omit = true
+ break
+ }
+
+ if (omit)
+ next
+
+ nxstar = istar
+ return (ids[istar])
+ }
+
+ return (0)
+end
diff --git a/noao/digiphot/daophot/psf/dplocstar.x b/noao/digiphot/daophot/psf/dplocstar.x
new file mode 100644
index 00000000..9925f44b
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dplocstar.x
@@ -0,0 +1,109 @@
+include <mach.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/psfdef.h"
+
+# DP_LOCSTAR -- Given an x,y position locate the star in the aperture
+# photometry list which is within a critical radius of the input position.
+
+int procedure dp_locstar (dao, im, x, y)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+real x, y # input position
+
+int i
+pointer psf, apsel
+real crit_rad, fitrad, rad, ax, ay
+
+begin
+ # Set up some constants.
+ psf = DP_PSF(dao)
+ apsel = DP_APSEL(dao)
+ crit_rad = DP_MATCHRAD(dao) * DP_MATCHRAD(dao)
+ fitrad = DP_FITRAD(dao)
+
+ # Search the list.
+ do i = 1, DP_APNUM(apsel) {
+
+ # Compute distance of star from the cursur position.
+ ax = Memr[DP_APXCEN(apsel)+i-1]
+ ay = Memr[DP_APYCEN(apsel)+i-1]
+ if (! IS_INDEFR(ax) && ! IS_INDEFR(ay))
+ rad = (ax - x) * (ax - x) + (ay - y) * (ay - y)
+ else
+ rad = MAX_REAL
+
+ # Found the star.
+ if (rad <= crit_rad) {
+
+ DP_CUR_PSF(psf) = i
+ DP_CUR_PSFID(psf) = Memi[DP_APID(apsel)+i-1]
+ DP_CUR_PSFX(psf) = ax
+ DP_CUR_PSFY(psf) = ay
+ DP_CUR_PSFSKY(psf) = Memr[DP_APMSKY(apsel)+i-1]
+ DP_CUR_PSFMAG(psf) = Memr[DP_APMAG(apsel)+i-1]
+
+ # Is the star too close to the edge ?
+ if (int (ax - fitrad) < 0 || int (ax + fitrad) > IM_LEN(im,1) ||
+ int (ay - fitrad) < 0 || int (ay + fitrad) > IM_LEN(im,2))
+ return (-i)
+ else
+ return (i)
+ }
+ }
+
+ return (0)
+end
+
+
+# DP_IDSTAR -- Given an id number locate the star in the aperture
+# photometry list.
+
+int procedure dp_idstar (dao, im, idnum)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+int idnum # id number from photometry list
+
+int i
+pointer psf, apsel
+real fitrad, x, y
+
+begin
+ # Set up some constants.
+ psf = DP_PSF(dao)
+ apsel = DP_APSEL(dao)
+ fitrad = DP_FITRAD(dao)
+
+ # Search the list.
+ do i = 1, DP_APNUM (apsel) {
+
+ # Test the id number.
+ if (idnum != Memi[DP_APID(apsel)+i-1])
+ next
+
+ # Found the star.
+ x = Memr[DP_APXCEN(apsel)+i-1]
+ y = Memr[DP_APYCEN(apsel)+i-1]
+ DP_CUR_PSF(psf) = i
+ DP_CUR_PSFID(psf) = Memi[DP_APID(apsel)+i-1]
+ DP_CUR_PSFX(psf) = Memr[DP_APXCEN(apsel)+i-1]
+ DP_CUR_PSFY(psf) = Memr[DP_APYCEN(apsel)+i-1]
+ DP_CUR_PSFSKY(psf) = Memr[DP_APMSKY(apsel)+i-1]
+ DP_CUR_PSFMAG(psf) = Memr[DP_APMAG(apsel)+i-1]
+
+ # Is the star too close to the edge ?
+ if (IS_INDEFR(x) || IS_INDEFR(y))
+ return (0)
+ else if (int (x - fitrad) < 0 || int (x + fitrad) >
+ IM_LEN(im,1) || int (y - fitrad) < 0 || int (y + fitrad) >
+ IM_LEN(im,2))
+ return (-i)
+ else
+ return (i)
+ }
+
+ return (0)
+end
diff --git a/noao/digiphot/daophot/psf/dpmempsf.x b/noao/digiphot/daophot/psf/dpmempsf.x
new file mode 100644
index 00000000..d198c778
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dpmempsf.x
@@ -0,0 +1,217 @@
+include "../lib/daophotdef.h"
+include "../lib/psfdef.h"
+
+
+# DP_PSFSETUP -- Procedure to set up the PSF parameters.
+
+procedure dp_psfsetup (dp)
+
+pointer dp # pointer to daophot structure
+
+pointer psf
+
+begin
+ # Allocate memory for the psf fitting structure.
+ call malloc (DP_PSF(dp), LEN_PSFSTRUCT, TY_STRUCT)
+ psf = DP_PSF(dp)
+
+ # Set the size of the data box t be extracted.
+ DP_LENUSERAREA(psf) = MIN_LENUSERAREA
+
+ # Initialize the psf fitting structure.
+ DP_PC(psf) = NULL
+ DP_PV(psf) = NULL
+ DP_PTMP(psf) = NULL
+ DP_PZ(psf) = NULL
+ DP_PCLAMP(psf) = NULL
+ DP_POLD(psf) = NULL
+ DP_PSIGANA(psf) = 0.0
+ DP_PSUMANA(psf) = 0.0
+
+ # Initialize the parameters for the current PSF star.
+ DP_CUR_PSF(psf) = 0
+ DP_CUR_PSFID(psf) = 0
+ DP_CUR_PSFX(psf) = INDEFR
+ DP_CUR_PSFY(psf) = INDEFR
+ DP_CUR_PSFSKY(psf) = INDEFR
+ DP_CUR_PSFMAG(psf) = INDEFR
+
+ # Initialize the PSF star list arrays.
+ DP_PNUM (psf) = 0
+ DP_PXCEN(psf) = NULL
+ DP_PYCEN(psf) = NULL
+ DP_PMAG(psf) = NULL
+ DP_PH(psf) = NULL
+ DP_PWEIGHT(psf) = NULL
+ DP_PSAT(psf) = NULL
+ DP_PXCLAMP(psf) = NULL
+ DP_PYCLAMP(psf) = NULL
+ DP_PXOLD(psf) = NULL
+ DP_PYOLD(psf) = NULL
+
+ # Initialize the look-up table arrays.
+ DP_PSUMN(psf) = NULL
+ DP_PSUMW(psf) = NULL
+ DP_PSUMSQ(psf) = NULL
+ DP_PSIGMA(psf) = NULL
+ DP_PCONST(psf) = NULL
+ DP_POLDLUT(psf) = NULL
+
+ # Allocate space for and initialize the plot sub-structure.
+ DP_PLOTTYPE(psf) = PSF_MESHPLOT
+ DP_MANGV(psf) = 30.
+ DP_MANGH(psf) = -30.
+ DP_MFLOOR(psf) = 0.
+ DP_MCEILING(psf) = 0.
+ DP_CFLOOR(psf) = 0.0
+ DP_CCEILING(psf) = 0.0
+end
+
+
+# DP_LMEMPSF -- Allocate memory required for fitting the list of psf stars.
+
+procedure dp_lmempsf (dao)
+
+pointer dao # pointer to daophot structure
+
+pointer psf
+
+begin
+ psf = DP_PSF(dao)
+ if (DP_PNUM(psf) > 0) {
+ call realloc (DP_PXCEN(psf), DP_PNUM(psf), TY_REAL)
+ call realloc (DP_PYCEN(psf), DP_PNUM(psf), TY_REAL)
+ call realloc (DP_PMAG(psf), DP_PNUM(psf), TY_REAL)
+ call realloc (DP_PH(psf), DP_PNUM(psf), TY_REAL)
+ call realloc (DP_PWEIGHT(psf), DP_PNUM(psf), TY_REAL)
+ call realloc (DP_PSAT(psf), DP_PNUM(psf), TY_INT)
+ call realloc (DP_PXCLAMP(psf), DP_PNUM(psf), TY_REAL)
+ call realloc (DP_PYCLAMP(psf), DP_PNUM(psf), TY_REAL)
+ call realloc (DP_PXOLD(psf), DP_PNUM(psf), TY_REAL)
+ call realloc (DP_PYOLD(psf), DP_PNUM(psf), TY_REAL)
+ }
+end
+
+
+# DP_AMEMPSF -- Allocate the memory required for fitting the analytic
+# PSF.
+
+procedure dp_amempsf (dao)
+
+pointer dao # pointer to daophot structure
+
+int npars
+pointer psf, psffit
+
+begin
+ psf = DP_PSF(dao)
+ psffit = DP_PSFFIT(dao)
+ npars = DP_PSFNPARS(psffit)
+
+ call realloc (DP_PC(psf), npars * npars, TY_REAL)
+ call realloc (DP_PV(psf), npars, TY_REAL)
+ call realloc (DP_PZ(psf), npars, TY_REAL)
+ call realloc (DP_PCLAMP(psf), npars, TY_REAL)
+ call realloc (DP_POLD(psf), npars, TY_REAL)
+ call realloc (DP_PTMP(psf), MAX_NFCTNPARS, TY_REAL)
+end
+
+
+# DP_TMEMPSF -- Allocate the memory required for fitting the lookup tables.
+
+procedure dp_tmempsf (dao)
+
+pointer dao # pointer to daophot structure
+
+int nexp
+pointer psf, psffit
+
+begin
+ psf = DP_PSF(dao)
+ psffit = DP_PSFFIT(dao)
+
+ nexp = DP_NVLTABLE(psffit) + DP_NFEXTABLE(psffit)
+ DP_PSFSIZE(psffit) = 2 * (nint (2.0 * DP_PSFRAD(dao)) + 1) + 1
+ DP_PSFRAD(dao) = (real (DP_PSFSIZE(psffit) - 1) / 2.0 - 1.0) / 2.0
+ DP_SPSFRAD(dao) = DP_PSFRAD(dao) * DP_SCALE(dao)
+ DP_RPSFRAD(dao) = DP_PSFRAD(dao) * DP_SCALE(dao)
+
+ call realloc (DP_PC(psf), nexp * nexp, TY_REAL)
+ call realloc (DP_PV(psf), nexp, TY_REAL)
+ call realloc (DP_PTMP(psf), nexp, TY_REAL)
+
+ call realloc (DP_PSUMN(psf), DP_PSFSIZE(psffit) * DP_PSFSIZE(psffit),
+ TY_REAL)
+ call realloc (DP_PSUMSQ(psf), DP_PSFSIZE(psffit) * DP_PSFSIZE(psffit),
+ TY_REAL)
+ call realloc (DP_PSIGMA(psf), DP_PSFSIZE(psffit) * DP_PSFSIZE(psffit),
+ TY_REAL)
+ call realloc (DP_POLDLUT(psf), nexp * DP_PSFSIZE(psffit) *
+ DP_PSFSIZE(psffit), TY_REAL)
+ if (nexp > 1)
+ call realloc (DP_PCONST(psf), DP_PSFSIZE(psffit) *
+ DP_PSFSIZE(psffit), TY_REAL)
+
+ call realloc (DP_PSFLUT(psffit), nexp * DP_PSFSIZE(psffit) *
+ DP_PSFSIZE(psffit), TY_REAL)
+end
+
+
+# DP_PSFCLOSE -- Procedure to set up the PSF parameters.
+
+procedure dp_psfclose (dp)
+
+pointer dp # pointer to daophot structure
+
+pointer psf
+
+begin
+ psf = DP_PSF(dp)
+
+ if (DP_PC(psf) != NULL)
+ call mfree (DP_PC(psf), TY_REAL)
+ if (DP_PV(psf) != NULL)
+ call mfree (DP_PV(psf), TY_REAL)
+ if (DP_PTMP(psf) != NULL)
+ call mfree (DP_PTMP(psf), TY_REAL)
+ if (DP_PZ(psf) != NULL)
+ call mfree (DP_PZ(psf), TY_REAL)
+ if (DP_PCLAMP(psf) != NULL)
+ call mfree (DP_PCLAMP(psf), TY_REAL)
+ if (DP_POLD(psf) != NULL)
+ call mfree (DP_POLD(psf), TY_REAL)
+
+ if (DP_PXCEN(psf) != NULL)
+ call mfree (DP_PXCEN(psf), TY_REAL)
+ if (DP_PYCEN(psf) != NULL)
+ call mfree (DP_PYCEN(psf), TY_REAL)
+ if (DP_PMAG(psf) != NULL)
+ call mfree (DP_PMAG(psf), TY_REAL)
+ if (DP_PH(psf) != NULL)
+ call mfree (DP_PH(psf), TY_REAL)
+ if (DP_PWEIGHT(psf) != NULL)
+ call mfree (DP_PWEIGHT(psf), TY_REAL)
+ if (DP_PSAT(psf) != NULL)
+ call mfree (DP_PSAT(psf), TY_INT)
+ if (DP_PXCLAMP(psf) != NULL)
+ call mfree (DP_PXCLAMP(psf), TY_REAL)
+ if (DP_PYCLAMP(psf) != NULL)
+ call mfree (DP_PYCLAMP(psf), TY_REAL)
+ if (DP_PXOLD(psf) != NULL)
+ call mfree (DP_PXOLD(psf), TY_REAL)
+ if (DP_PYOLD(psf) != NULL)
+ call mfree (DP_PYOLD(psf), TY_REAL)
+
+ if (DP_PSUMN(psf) != NULL)
+ call mfree (DP_PSUMN(psf), TY_REAL)
+ if (DP_PSUMSQ(psf) != NULL)
+ call mfree (DP_PSUMSQ(psf), TY_REAL)
+ if (DP_PSIGMA(psf) != NULL)
+ call mfree (DP_PSIGMA(psf), TY_REAL)
+ if (DP_PCONST(psf) != NULL)
+ call mfree (DP_PCONST(psf), TY_REAL)
+ if (DP_POLDLUT(psf) != NULL)
+ call mfree (DP_POLDLUT(psf), TY_REAL)
+
+ call mfree (psf, TY_STRUCT)
+end
diff --git a/noao/digiphot/daophot/psf/dpmkpsf.x b/noao/digiphot/daophot/psf/dpmkpsf.x
new file mode 100644
index 00000000..2af7dbed
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dpmkpsf.x
@@ -0,0 +1,361 @@
+include <gset.h>
+include <ctype.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/psfdef.h"
+
+define HELPFILE "daophot$psf/mkpsf.key"
+
+# DP_MKPSF -- Construct a stellar PSF from one or more stars in an image frame.
+
+procedure dp_mkpsf (dao, im, psfim, opst, psfgr, gd, mgd, id, mkstars,
+ interactive, showplots)
+
+pointer dao # pointer to the main daophot structure
+pointer im # pointer to the input image
+pointer psfim # pointer to the output psfimage
+int opst # the psf star list file descriptor
+int psfgr # the psf group file descriptor
+pointer gd # pointer to graphics descriptor
+pointer mgd # pointer to the metacode file
+pointer id # pointer to image display stream
+bool mkstars # mark the added and deleted psf stars
+bool interactive # interactive mode
+bool showplots # show the plots
+
+real wx, wy
+pointer apsel, sp, cmd, str
+int i, key, wcs, idnum, istar, ip, npsf, verbose
+bool psf_new, psf_computed, psf_written
+
+real dp_pstatr()
+int clgcur(), dp_qverify(), dp_locstar(), dp_idstar(), dp_stati()
+int dp_pstati(), ctoi(), dp_addstar(), dp_delstar(), dp_subpsf()
+int dp_fitpsf()
+bool dp_updatepsf()
+
+begin
+ # Get some pointers
+ apsel = DP_APSEL(dao)
+
+ # Allocate some working space.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Initialize some variables.
+ key = 'a'
+ if (dp_pstati (dao, PNUM) > 0)
+ psf_new = false
+ else
+ psf_new = true
+ psf_computed = false
+ psf_written = false
+
+ # Begin to build the PSF.
+ while (clgcur ("icommands", wx, wy, wcs, key, Memc[cmd], SZ_LINE) !=
+ EOF) {
+
+ # Convert coordinates if necessary.
+ call dp_vtol (im, wx, wy, wx, wy, 1)
+
+ switch (key) {
+
+ # Quit the interactive cursor loop.
+ case 'q':
+
+ if (interactive) {
+ if (dp_qverify (dao, im, psfim, opst, psfgr, psf_new,
+ psf_computed, psf_written) == NO)
+ next
+ } else if (dp_updatepsf (dao, im, psfim, opst, psfgr, psf_new,
+ psf_computed, psf_written)) {
+ psf_computed = true
+ psf_written = true
+ }
+
+ # Delete any empty psf and group files lying around.
+ if (! psf_written)
+ call dp_rmpsf (dao, psfim, opst, psfgr)
+
+ # Delete the PSF stars.
+ call dp_pseti (dao, PNUM, 0)
+
+ break
+
+ # Print the help page.
+ case '?':
+ if (id == NULL)
+ call pagefile (HELPFILE, "")
+ else
+ call gpagefile (id, HELPFILE, "")
+
+ # Add the star nearest the cursor position to the PSF.
+ case 'a':
+ if (dp_addstar (dao, im, wx, wy, INDEFR, 0, gd, mgd,
+ showplots) == ERR)
+ next
+ psf_new = false
+ psf_computed = false
+ psf_written = false
+ if (mkstars && id != NULL) {
+ call gmark (id, dp_pstatr (dao, CUR_PSFX), dp_pstatr (dao,
+ CUR_PSFY), GM_PLUS, -5.0, -5.0)
+ if (gd == id)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ # Subtract the star nearest the cursor position from the PSF
+ # using the current best fit.
+ case 's':
+ if (psf_new) {
+ call printf ("The PSF star list is empty\n")
+ next
+ }
+ if (! psf_computed) {
+ call printf ("The PSF is not uptodate\n")
+ next
+ }
+ if (dp_subpsf (dao, im, wx, wy, 0, gd, mgd, showplots) == ERR)
+ next
+ if (dp_pstati (dao, PNUM) <= 0)
+ psf_new = true
+ psf_computed = false
+ psf_written = false
+
+ # Delete the star nearest the cursor position from the PSF.
+ case 'd':
+ if (dp_delstar (dao, im, wx, wy, 0, gd, showplots) == ERR)
+ next
+ if (dp_pstati (dao, PNUM) <= 0)
+ psf_new = true
+ psf_computed = false
+ psf_written = false
+ if (mkstars && id != NULL) {
+ call gmark (id, dp_pstatr (dao, CUR_PSFX), dp_pstatr (dao,
+ CUR_PSFY), GM_CROSS, -5.0, -5.0)
+ if (gd == id)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ # List all the current psf stars.
+ case 'l':
+ if (interactive)
+ call dp_listpsf (dao, im)
+
+ # Fit the PSF.
+ case 'f':
+
+ # Reread the stars is necessary.
+ if (dp_pstati (dao, PNUM) > 0 && (psf_new || psf_computed)) {
+ npsf = dp_pstati (dao, PNUM)
+ call dp_pseti (dao, PNUM, 0)
+ call dp_reinit (dao)
+ verbose = dp_stati (dao, VERBOSE)
+ call dp_seti (dao, VERBOSE, NO)
+ do i = 1, npsf
+ if (dp_addstar (dao, im, wx, wy, INDEFR,
+ Memi[DP_APID(apsel)+i-1], gd, mgd,
+ false) == OK)
+ psf_new = false
+ call dp_seti (dao, VERBOSE, verbose)
+ }
+
+ # Fit the psf.
+ if (psf_new) {
+ call printf ("The PSF star list is empty\n")
+ } else if (dp_fitpsf (dao, im, Memc[str], SZ_LINE) == OK) {
+ psf_computed = true
+ } else {
+ call printf ("%s\n")
+ call pargstr (Memc[str])
+ }
+
+ # Review the fit.
+ case 'r':
+ if (psf_new) {
+ call printf ("The PSF star list is empty\n")
+ } else if (! psf_computed) {
+ call printf ("The PSF is not uptodate\n")
+ } else {
+ i = 1
+ repeat {
+ if (dp_subpsf (dao, im, wx, wy,
+ Memi[DP_APID(apsel)+i-1], gd, mgd,
+ showplots) == OK) {
+ if (dp_pstati (dao, PNUM) <= 0)
+ psf_new = true
+ psf_computed = false
+ psf_written = false
+ } else
+ i = i + 1
+ } until (i > dp_pstati(dao, PNUM))
+ }
+
+ # Rebuild the PSF from scratch.
+ case 'z':
+
+ # Print message.
+ if (interactive) {
+ call dp_stats (dao, OUTPHOTFILE, Memc[str], SZ_FNAME)
+ call printf (
+ "PSF star list, image, and output files deleted\n")
+ }
+
+ # Delete the previous psf an dgroup files if any.
+ call dp_rmpsf (dao, psfim, opst, psfgr)
+
+ # Delete the PSF stars.
+ call dp_pseti (dao, PNUM, 0)
+
+ # Reopen the psf image and group files.
+ call dp_oppsf (dao, psfim, opst, psfgr)
+
+ # Reset the reduction flags.
+ psf_new = true
+ psf_computed = false
+ psf_written = false
+
+ # Write out the PSF.
+ case 'w':
+ if (dp_updatepsf (dao, im, psfim, opst, psfgr, psf_new,
+ psf_computed, psf_written)) {
+ psf_computed = true
+ psf_written = true
+ }
+
+ # Locate the star in the aperture photometry file and print out
+ # the photometry.
+ case 'p':
+ if (interactive)
+ istar = dp_locstar (dao, im, wx, wy)
+ else
+ next
+ if (istar > 0)
+ call dp_pshow (dao, im, istar)
+ else if (istar == 0)
+ call printf ("Star not found in the photometry file.\n")
+ else
+ call printf (
+ "Star off or too near the edge of the image.\n")
+
+ # Command mode
+ case ':':
+ for (ip = 1; IS_WHITE(Memc[cmd+ip-1]); ip = ip + 1)
+ ;
+ switch (Memc[cmd+ip-1]) {
+
+ case 'p':
+ if (Memc[cmd+ip] != EOS && Memc[cmd+ip] != ' ') {
+ call dp_pcolon (dao, psfim, opst, psfgr, Memc[cmd],
+ psf_new, psf_computed, psf_written)
+ next
+ }
+ if (! interactive)
+ next
+ ip = ip + 1
+ if (ctoi (Memc[cmd], ip, idnum) <= 0)
+ istar = dp_locstar (dao, im, wx, wy)
+ else
+ istar = dp_idstar (dao, im, idnum)
+ if (istar > 0)
+ call dp_pshow (dao, im, istar)
+ else if (istar == 0)
+ call printf (
+ "Star not found in the photometry file\n")
+ else
+ call printf (
+ "Star is off or too near the edge of the image.\n")
+
+ case 'a':
+ if (Memc[cmd+ip] != EOS && Memc[cmd+ip] != ' ') {
+ call dp_pcolon (dao, psfim, opst, psfgr, Memc[cmd],
+ psf_new, psf_computed, psf_written)
+ next
+ }
+ ip = ip + 1
+ if (ctoi (Memc[cmd], ip, idnum) <= 0)
+ idnum = 0
+ if (dp_addstar (dao, im, wx, wy, INDEFR, idnum, gd, mgd,
+ showplots) == ERR)
+ next
+ psf_new = false
+ psf_computed = false
+ psf_written = false
+ if (mkstars && id != NULL) {
+ call gmark (id, dp_pstatr (dao, CUR_PSFX),
+ dp_pstatr (dao, CUR_PSFY), GM_PLUS, -5.0, -5.0)
+ if (gd == id)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ case 's':
+ if (Memc[cmd+ip] != EOS && Memc[cmd+ip] != ' ') {
+ call dp_pcolon (dao, psfim, opst, psfgr, Memc[cmd],
+ psf_new, psf_computed, psf_written)
+ next
+ }
+ ip = ip + 1
+ if (ctoi (Memc[cmd], ip, idnum) <= 0)
+ idnum = 0
+ if (! psf_computed) {
+ call printf ("The PSF has not been fit\n")
+ next
+ }
+ if (! psf_computed) {
+ call printf ("Warning: The PSF is not uptodate\n")
+ next
+ }
+ if (dp_subpsf (dao, im, wx, wy, idnum, gd, mgd,
+ showplots) == ERR)
+ next
+ if (dp_pstati (dao, PNUM) <= 0)
+ psf_new = true
+ psf_computed = false
+ psf_written = false
+
+ case 'd':
+ if (Memc[cmd+ip] != EOS && Memc[cmd+ip] != ' ') {
+ call dp_pcolon (dao, psfim, opst, psfgr, Memc[cmd],
+ psf_new, psf_computed, psf_written)
+ next
+ }
+ ip = ip + 1
+ if (ctoi (Memc[cmd], ip, idnum) <= 0)
+ idnum = 0
+ if (dp_delstar (dao, im, wx, wy, idnum, gd,
+ showplots) == ERR)
+ next
+ if (dp_pstati (dao, PNUM) <= 0)
+ psf_new = true
+ psf_computed = false
+ psf_written = false
+ if (mkstars && id != NULL) {
+ call gmark (id, dp_pstatr (dao, CUR_PSFX),
+ dp_pstatr (dao, CUR_PSFY), GM_CROSS, -5.0, -5.0)
+ if (gd == id)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ default:
+ call dp_pcolon (dao, psfim, opst, psfgr, Memc[cmd],
+ psf_new, psf_computed, psf_written)
+ }
+
+ default:
+ call printf ("Unknown keystroke command\n")
+ }
+ }
+
+ # Free up memory.
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/psf/dppcolon.x b/noao/digiphot/daophot/psf/dppcolon.x
new file mode 100644
index 00000000..9934f244
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dppcolon.x
@@ -0,0 +1,271 @@
+include "../lib/daophotdef.h"
+include "../lib/psfdef.h"
+
+# DP_PCOLON -- Process the PSF fitting colon commands.
+
+procedure dp_pcolon (dao, psfim, opst, psfgr, cmdstr, psf_new, psf_computed,
+ psf_written)
+
+pointer dao # pointer to the daophot structure
+pointer psfim # pointer to the output psf image
+int opst # the output psf star list file descriptor
+int psfgr # the output psf group file descriptor
+char cmdstr[ARB] # the input command string
+bool psf_new # is the psf star list defined ?
+bool psf_computed # has the psf been fit ?
+bool psf_written # has the psf been updated ?
+
+bool bval
+int ncmd, ival
+pointer sp, cmd, str1, str2, str3
+real rval
+
+bool itob()
+int strdic(), nscan(), btoi(), dp_stati(), open(), dp_fctdecode()
+int dp_pstati(), strlen()
+pointer immap(), tbtopn()
+real dp_statr()
+errchk immap(), open(), tbtopn()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (str1, SZ_LINE, TY_CHAR)
+ call salloc (str2, SZ_LINE, TY_CHAR)
+ call salloc (str3, SZ_LINE, TY_CHAR)
+
+ # Get the command.
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, PSF_CMDS)
+ switch (ncmd) {
+
+ case PSFCMD_PSFIMAGE:
+ call gargwrd (Memc[str1], SZ_LINE)
+ call gargwrd (Memc[str2], SZ_LINE)
+ call gargwrd (Memc[str3], SZ_LINE)
+ if (nscan() == 1) {
+ call dp_stats (dao, PSFIMAGE, Memc[str1], SZ_LINE)
+ call dp_stats (dao, OUTREJFILE, Memc[str2], SZ_LINE)
+ call dp_stats (dao, OUTPHOTFILE, Memc[str3], SZ_LINE)
+ call printf ("psfim = %s opstfile = %s grpfile = %s\n")
+ call pargstr (Memc[str1])
+ call pargstr (Memc[str2])
+ call pargstr (Memc[str3])
+ } else if (nscan() == 4) {
+ if (psfim != NULL)
+ call imunmap (psfim)
+ psfim = NULL
+ if (opst != NULL) {
+ if (dp_stati (dao, TEXT) == YES)
+ call close (opst)
+ else
+ call tbtclo (opst)
+ }
+ opst = NULL
+ if (psfgr != NULL) {
+ if (dp_stati (dao, TEXT) == YES)
+ call close (psfgr)
+ else
+ call tbtclo (psfgr)
+ }
+ psfgr = NULL
+ iferr {
+ psfim = immap (Memc[str1], NEW_IMAGE, dp_pstati (dao,
+ LENUSERAREA))
+ if (dp_stati (dao, TEXT) == YES)
+ opst = open (Memc[str2], NEW_FILE, TEXT_FILE)
+ else
+ opst = tbtopn (Memc[str2], NEW_FILE, 0)
+ if (dp_stati (dao, TEXT) == YES)
+ psfgr = open (Memc[str3], NEW_FILE, TEXT_FILE)
+ else
+ psfgr = tbtopn (Memc[str3], NEW_FILE, 0)
+ } then {
+ if (psfim != NULL)
+ call imunmap (psfim)
+ psfim = NULL
+ if (opst != NULL) {
+ if (dp_stati (dao, TEXT) == YES)
+ call close (opst)
+ else
+ call tbtclo (opst)
+ }
+ opst = NULL
+ if (psfgr != NULL) {
+ if (dp_stati (dao, TEXT) == YES)
+ call close (psfgr)
+ else
+ call tbtclo (psfgr)
+ }
+ psfgr = NULL
+ call dp_sets (dao, PSFIMAGE, "")
+ call dp_sets (dao, OUTREJFILE, "")
+ call dp_sets (dao, OUTPHOTFILE, "")
+ } else {
+ call dp_sets (dao, PSFIMAGE, Memc[str1])
+ call dp_sets (dao, OUTREJFILE, Memc[str2])
+ call dp_sets (dao, OUTPHOTFILE, Memc[str2])
+ }
+ psf_written = false
+ }
+
+ case PSFCMD_FUNCTION:
+ call gargwrd (Memc[str1], SZ_LINE)
+ if (nscan() == 1) {
+ call dp_stats (dao, FUNCLIST, Memc[str1], SZ_LINE)
+ call strcpy (Memc[str1+1], Memc[str2],
+ strlen (Memc[str1]) - 2)
+ call printf ("function = %s\n")
+ call pargstr (Memc[str2])
+ } else if (dp_fctdecode (Memc[str1], Memc[str2], SZ_FNAME) > 0) {
+ call dp_sets (dao, FUNCLIST, Memc[str2])
+ psf_computed = false
+ psf_written = false
+ }
+
+ case PSFCMD_VARORDER:
+ call gargi (ival)
+ if (nscan() == 1) {
+ call printf ("varorder = %d\n")
+ call pargi (dp_stati (dao, VARORDER))
+ } else if (ival >= -1 && ival <= 2) {
+ call dp_seti (dao, VARORDER, ival)
+ psf_computed = false
+ psf_written = false
+ }
+
+ case PSFCMD_FEXPAND:
+ call gargb (bval)
+ if (nscan() == 1) {
+ call printf ("fexpand = %b\n")
+ call pargb (itob (dp_stati (dao, FEXPAND)))
+ } else {
+ call dp_seti (dao, FEXPAND, btoi (bval))
+ psf_computed = false
+ psf_written = false
+ }
+
+ case PSFCMD_PSFRAD:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("psfrad = %g scale units\n")
+ call pargr (dp_statr (dao, SPSFRAD))
+ } else {
+ call dp_setr (dao, SPSFRAD, rval)
+ call dp_setr (dao, RPSFRAD, rval)
+ call dp_setr (dao, PSFRAD, rval / dp_statr (dao, SCALE))
+ psf_computed = false
+ psf_written = false
+ }
+
+ case PSFCMD_FITRAD:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("fitrad = %g scale units\n")
+ call pargr (dp_statr (dao, SFITRAD))
+ } else {
+ call dp_setr (dao, SFITRAD, rval)
+ call dp_setr (dao, FITRAD, rval / dp_statr (dao, SCALE))
+ psf_new = true
+ psf_computed = false
+ psf_written = false
+ }
+
+ case PSFCMD_MATCHRAD:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("matchrad = %g scale units\n")
+ call pargr (dp_statr (dao, SMATCHRAD))
+ } else {
+ call dp_setr (dao, SMATCHRAD, rval)
+ call dp_setr (dao, MATCHRAD, rval / dp_statr (dao, SCALE))
+ }
+
+ case PSFCMD_NCLEAN:
+ call gargi (ival)
+ if (nscan() == 1) {
+ call printf ("nclean = %d\n")
+ call pargi (dp_stati (dao, NCLEAN))
+ } else if (ival >= 0) {
+ call dp_seti (dao, NCLEAN, ival)
+ psf_computed = false
+ psf_written = false
+ }
+
+ case PSFCMD_SATURATED:
+ call gargb (bval)
+ if (nscan() == 1) {
+ call printf ("saturated = %b\n")
+ call pargb (itob (dp_stati (dao, SATURATED)))
+ } else {
+ call dp_seti (dao, SATURATED, btoi (bval))
+ psf_computed = false
+ psf_written = false
+ }
+
+ case PSFCMD_SCALE:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("scale = %g units per pixel\n")
+ call pargr (dp_statr (dao, SCALE))
+ } else {
+ call dp_setr (dao, FWHMPSF, dp_statr (dao, SFWHMPSF) / rval)
+ call dp_setr (dao, PSFRAD, dp_statr (dao, SPSFRAD) / rval)
+ call dp_setr (dao, FITRAD, dp_statr (dao, SFITRAD) / rval)
+ call dp_setr (dao, MATCHRAD, dp_statr (dao, SMATCHRAD) / rval)
+ call dp_setr (dao, SCALE, rval)
+ psf_new = true
+ psf_computed = false
+ psf_written = false
+ }
+
+ case PSFCMD_FWHMPSF:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("fwhmpsf = %g scale units\n")
+ call pargr (dp_statr (dao, SFWHMPSF))
+ } else {
+ call dp_setr (dao, SFWHMPSF, rval)
+ call dp_setr (dao, FWHMPSF, rval / dp_statr (dao, SCALE))
+ psf_computed = false
+ psf_written = false
+ }
+
+ case PSFCMD_DATAMIN:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("datamin = %g counts\n")
+ call pargr (dp_statr (dao, MINGDATA))
+ } else {
+ call dp_setr (dao, MINGDATA, rval)
+ psf_new = true
+ psf_computed = false
+ psf_written = false
+ }
+
+ case PSFCMD_DATAMAX:
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("datamax = %g counts\n")
+ call pargr (dp_statr (dao, MAXGDATA))
+ } else {
+ call dp_setr (dao, MAXGDATA, rval)
+ psf_new = true
+ psf_computed = false
+ psf_written = false
+ }
+
+ default:
+ call printf ("Unknown or ambiguous colon command\7\n")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/psf/dppconfirm.x b/noao/digiphot/daophot/psf/dppconfirm.x
new file mode 100644
index 00000000..092cfec3
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dppconfirm.x
@@ -0,0 +1,26 @@
+# DP_PCONFIRM -- Procedure to confirm the critical psf parameters.
+
+procedure dp_pconfirm (dao)
+
+pointer dao # pointer to the daophot structure
+
+begin
+ call printf ("\n")
+
+ # Verify the functional form of the psf.
+ call dp_vfunction(dao)
+ call dp_vvarorder (dao)
+ #call dp_vfexpand (dao)
+
+ # Confirm the psf radius.
+ call dp_vpsfrad (dao)
+
+ # Confirm the fitting radius.
+ call dp_vfitrad (dao)
+
+ # Confirm the minimum and maximum good data values.
+ call dp_vdatamin (dao)
+ call dp_vdatamax (dao)
+
+ call printf ("\n")
+end
diff --git a/noao/digiphot/daophot/psf/dpplotpsf.x b/noao/digiphot/daophot/psf/dpplotpsf.x
new file mode 100644
index 00000000..4b80c50f
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dpplotpsf.x
@@ -0,0 +1,49 @@
+include "../lib/daophotdef.h"
+include "../lib/psfdef.h"
+
+# DP_PLOTPSF -- Plot the psf using the default plot type.
+
+procedure dp_plotpsf (dao, im, subrast, ncols, nlines, x1, y1, gd)
+
+pointer dao # pointer to the daophot structure
+pointer im # the input image descriptor
+real subrast[ncols,nlines] # image subraster
+int ncols, nlines # dimensions of the subraster
+int x1, y1 # coordinates of the lower left corner
+pointer gd # pointer to the graphics stream
+
+real tx, ty
+pointer sp, title
+real dp_pstatr()
+int dp_pstati()
+
+begin
+ # Return if the graphics stream is undefined.
+ if (gd == NULL)
+ return
+
+ # Comvert the coordinates if necessary.
+ call dp_wout (dao, im, dp_pstatr(dao, CUR_PSFX), dp_pstatr(dao,
+ CUR_PSFY), tx, ty, 1)
+
+ # Construct the title.
+ call smark (sp)
+ call salloc (title, SZ_LINE, TY_CHAR)
+ call sprintf (Memc[title], SZ_LINE, "Star: %d X: %g Y: %g Mag: %g")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ call pargr (tx)
+ call pargr (ty)
+ call pargr (dp_pstatr (dao, CUR_PSFMAG))
+
+ # Initialize plot.
+ if (dp_pstati (dao, PLOTTYPE) == PSF_MESHPLOT)
+ call dp_surfpsf (dao, subrast, ncols, nlines, Memc[title], gd)
+ else if (dp_pstati (dao, PLOTTYPE) == PSF_CONTOURPLOT)
+ call dp_contpsf (dao, subrast, ncols, nlines, Memc[title], gd)
+ else if (dp_pstati (dao, PLOTTYPE) == PSF_RADIALPLOT)
+ call dp_radpsf (dao, subrast, ncols, nlines, x1, y1,
+ Memc[title], gd)
+
+ call gdeactivate (gd, 0)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/psf/dppset.x b/noao/digiphot/daophot/psf/dppset.x
new file mode 100644
index 00000000..d98b22bd
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dppset.x
@@ -0,0 +1,81 @@
+include "../lib/daophotdef.h"
+include "../lib/psfdef.h"
+
+# DP_PSETS -- Set a psf fitting string parameter.
+#
+#procedure dp_psets (dao, param, str)
+
+#pointer dao # pointer to daophot structure
+#int param # parameter
+#char str[ARB] # string value
+
+#begin
+# switch (param) {
+# default:
+# call error (0, "DP_PSETS: Unknown psf fitting string parameter")
+# }
+#end
+
+
+# DP_PSETI -- Set a daophot psf fitting integer parameter.
+
+procedure dp_pseti (dao, param, ival)
+
+pointer dao # pointer to daophot structure
+int param # parameter
+int ival # integer value
+
+pointer psf
+
+begin
+ psf = DP_PSF(dao)
+
+ switch (param) {
+ case CUR_PSF:
+ DP_CUR_PSF(psf) = ival
+ case CUR_PSFID:
+ DP_CUR_PSFID(psf) = ival
+ case PNUM:
+ DP_PNUM(psf) = ival
+ case PLOTTYPE:
+ DP_PLOTTYPE(psf) = ival
+ case LENUSERAREA:
+ DP_LENUSERAREA(psf) = ival
+ default:
+ call error (0, "DP_PSETI: Unknown integer psf fitting parameter")
+ }
+end
+
+
+# DP_PSETR -- Set a real psf fitting parameter.
+
+procedure dp_psetr (dao, param, rval)
+
+pointer dao # pointer to daophot structure
+int param # parameter
+real rval # real value
+
+pointer psf
+
+begin
+ psf = DP_PSF(dao)
+
+ switch (param) {
+ case CUR_PSFX:
+ DP_CUR_PSFX(psf) = rval
+ case CUR_PSFY:
+ DP_CUR_PSFY(psf) = rval
+ case CUR_PSFSKY:
+ DP_CUR_PSFSKY(psf) = rval
+ case CUR_PSFMAG:
+ DP_CUR_PSFMAG(psf) = rval
+ case CUR_PSFMIN:
+ DP_CUR_PSFMIN(psf) = rval
+ case CUR_PSFMAX:
+ DP_CUR_PSFMAX(psf) = rval
+ case CUR_PSFGMAX:
+ DP_CUR_PSFGMAX(psf) = rval
+ default:
+ call error (0, "DP_SETR: Unknown real psf fitting parameter")
+ }
+end
diff --git a/noao/digiphot/daophot/psf/dppsfutil.x b/noao/digiphot/daophot/psf/dppsfutil.x
new file mode 100644
index 00000000..17df56f6
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dppsfutil.x
@@ -0,0 +1,381 @@
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/psfdef.h"
+
+# DP_PFSWAP -- Swap two stars in the PSF star list.
+
+procedure dp_pfswap (dao, star1, star2)
+
+pointer dao # pointer to the daophot structure
+int star1 # index of first star to be swapped
+int star2 # index of second star to be swapped
+
+pointer apsel, psf
+
+begin
+ apsel = DP_APSEL(dao)
+ psf = DP_PSF(dao)
+ call dp_10swap (star1, star2, Memi[DP_APID(apsel)],
+ Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[DP_APMAG(apsel)], Memr[DP_APMSKY(apsel)], Memr[DP_PXCEN(psf)],
+ Memr[DP_PYCEN(psf)], Memr[DP_PH(psf)], Memr[DP_PMAG(psf)],
+ Memi[DP_PSAT(psf)])
+end
+
+
+# DP_PFREORDER -- Move a star in the PSF star list to the end of the
+# list.
+
+procedure dp_pfreorder (dao, star, nstars)
+
+pointer dao # pointer to the daophot structure
+int star # index of star to be deleted
+int nstars # index of second star to be swapped
+
+pointer apsel, psf
+
+begin
+ apsel = DP_APSEL(dao)
+ psf = DP_PSF(dao)
+ call dp_10reorder (star, Memi[DP_APID(apsel)], Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMAG(apsel)],
+ Memr[DP_APMSKY(apsel)], Memr[DP_PXCEN(psf)], Memr[DP_PYCEN(psf)],
+ Memr[DP_PH(psf)], Memr[DP_PMAG(psf)], Memi[DP_PSAT(psf)], nstars)
+end
+
+
+# DP_APLSWAP -- Swap two stars in the daophot photometry substructure.
+
+procedure dp_aplswap (dao, star1, star2)
+
+pointer dao # pointer to the daophot structure
+int star1 # index of first star to be swapped
+int star2 # index of second star to be swapped
+
+pointer apsel
+
+begin
+ apsel = DP_APSEL(dao)
+ call dp_5swap (star1, star2, Memi[DP_APID(apsel)],
+ Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[DP_APMAG(apsel)], Memr[DP_APMSKY(apsel)])
+end
+
+
+# DP_XYHPSF -- Compute the initial x, y, and height of the current PSF star.
+
+procedure dp_xyhpsf (dao, star, mag, saturated)
+
+pointer dao # pointer to the daophot structure
+int star # star for which x, y, h is to be computed
+real mag # magnitude of proposed psf star
+int saturated # is the star saturated
+
+pointer apsel, psf, psffit
+real dhdxc, dhdyc, junk
+real dp_profile()
+
+begin
+ apsel = DP_APSEL(dao)
+ psf = DP_PSF(dao)
+ psffit = DP_PSFFIT(dao)
+
+ Memr[DP_PXCEN(psf)+star-1] = Memr[DP_APXCEN(apsel)+star-1]
+ Memr[DP_PYCEN(psf)+star-1] = Memr[DP_APYCEN(apsel)+star-1]
+ if (saturated == YES)
+ Memr[DP_PH(psf)+star-1] = INDEFR
+ else
+ Memr[DP_PH(psf)+star-1] = (DP_CUR_PSFGMAX(psf) -
+ Memr[DP_APMSKY(apsel)+star-1]) /
+ dp_profile (DP_PSFUNCTION(psffit),
+ 0.0, 0.0, Memr[DP_PSFPARS(psffit)], dhdxc, dhdyc, junk, 0)
+ Memr[DP_PMAG(psf)+star-1] = mag
+ Memi[DP_PSAT(psf)+star-1] = saturated
+end
+
+
+# DP_LISTPSF -- List the PSF stars.
+
+procedure dp_listpsf (dao, im)
+
+pointer dao # pointer to the daophot structure
+pointer im # the input image descriptor
+
+real x, y
+pointer apsel, psf
+int i
+
+begin
+ apsel = DP_APSEL(dao)
+ psf = DP_PSF(dao)
+
+ call printf ("\nCurrent PSF star list\n")
+ do i = 1, DP_PNUM(psf) {
+ call dp_ltov (im, Memr[DP_APXCEN(apsel)+i-1],
+ Memr[DP_APYCEN(apsel)+i-1], x, y, 1)
+ call printf (
+ " Star: %4d X: %7.2f Y: %7.2f Mag: %7.2f Sky: %10.1f\n")
+ call pargi (Memi[DP_APID(apsel)+i-1])
+ call pargr (x)
+ call pargr (y)
+ call pargr (Memr[DP_APMAG(apsel)+i-1])
+ call pargr (Memr[DP_APMSKY(apsel)+i-1])
+ }
+ call printf ("\n")
+end
+
+
+# DP_LISTPARS -- List the analytic PSF parameters.
+
+procedure dp_listpars (dao)
+
+pointer dao # pointer to the daophot structure
+
+pointer psffit
+
+begin
+ psffit = DP_PSFFIT(dao)
+ call printf ("\nAnalytic PSF fit \n")
+ call printf (
+ " Function: %s X: %g Y: %g Height: %g Psfmag: %g\n")
+ call pargstr (DP_FUNCTION(dao))
+ call pargr (DP_PSFX(psffit))
+ call pargr (DP_PSFY(psffit))
+ call pargr (DP_PSFHEIGHT(psffit))
+ call pargr (DP_PSFMAG(psffit))
+
+ switch (DP_PSFUNCTION(psffit)) {
+ case FCTN_GAUSS:
+ call printf (" Par1: %g Par2: %g\n")
+ call pargr (Memr[DP_PSFPARS(psffit)])
+ call pargr (Memr[DP_PSFPARS(psffit)+1])
+ case FCTN_MOFFAT15:
+ call printf (
+ " Par1: %g Par2: %g XYterm: %g Moffat: %g\n")
+ call pargr (Memr[DP_PSFPARS(psffit)])
+ call pargr (Memr[DP_PSFPARS(psffit)+1])
+ call pargr (Memr[DP_PSFPARS(psffit)+2])
+ call pargr (1.5)
+ case FCTN_PENNY1:
+ call printf (" Par1: %g Par2: %g Par3: %g Par4: %g\n")
+ call pargr (Memr[DP_PSFPARS(psffit)])
+ call pargr (Memr[DP_PSFPARS(psffit)+1])
+ call pargr (Memr[DP_PSFPARS(psffit)+2])
+ call pargr (Memr[DP_PSFPARS(psffit)+3])
+ case FCTN_MOFFAT25:
+ call printf (
+ " Par1: %g Par2: %g XYterm: %g Moffat: %g\n")
+ call pargr (Memr[DP_PSFPARS(psffit)])
+ call pargr (Memr[DP_PSFPARS(psffit)+1])
+ call pargr (Memr[DP_PSFPARS(psffit)+2])
+ call pargr (2.5)
+ case FCTN_PENNY2:
+ call printf (
+ " Par1: %g Par2: %g Par3: %g Par4: %g Par5: %g\n")
+ call pargr (Memr[DP_PSFPARS(psffit)])
+ call pargr (Memr[DP_PSFPARS(psffit)+1])
+ call pargr (Memr[DP_PSFPARS(psffit)+2])
+ call pargr (Memr[DP_PSFPARS(psffit)+3])
+ call pargr (Memr[DP_PSFPARS(psffit)+4])
+ case FCTN_LORENTZ:
+ call printf (" Par1: %g Par2: %g Par3: %g\n")
+ call pargr (Memr[DP_PSFPARS(psffit)])
+ call pargr (Memr[DP_PSFPARS(psffit)+1])
+ call pargr (Memr[DP_PSFPARS(psffit)+2])
+ }
+end
+
+
+# DP_PSHOW -- Print photometry for the given star
+
+procedure dp_pshow (dao, im, istar)
+
+pointer dao # pointer to the main daophot descriptor
+pointer im # the input image descriptor
+int istar # star to be printed
+
+real x, y
+pointer apsel
+
+begin
+ apsel = DP_APSEL(dao)
+ call dp_ltov (im, Memr[DP_APXCEN(apsel)+istar-1],
+ Memr[DP_APYCEN(apsel)+istar-1], x, y, 1)
+ call printf (
+ "Star: %4d X: %7.2f Y: %7.2f Mag: %7.2f Sky: %10.1f\n")
+ call pargi (Memi[DP_APID(apsel)+istar-1])
+ call pargr (x)
+ call pargr (y)
+ call pargr (Memr[DP_APMAG(apsel)+istar-1])
+ call pargr (Memr[DP_APMSKY(apsel)+istar-1])
+end
+
+
+# DP_10REORDER -- Move a PSF star to the end of the list.
+
+procedure dp_10reorder (star, id, x, y, mag, sky, xfit, yfit, hfit, pmag,
+ sat, nstars)
+
+int star # star to be moved to the end of the list
+int id[ARB] # the ids of the stars
+real x[ARB] # the x positions of the stars
+real y[ARB] # the y positions of the stars
+real mag[ARB] # the magnitudes of the stars
+real sky[ARB] # the sky values of the stars
+real xfit[ARB] # the current x fit array
+real yfit[ARB] # the current y fit array
+real hfit[ARB] # the current height of the stars
+real pmag[ARB] # the psf star list magnitude
+int sat[ARB] # are the star saturated
+int nstars # number of stars in the list
+
+int i, ihold, sfhold
+real xhold, yhold, mhold, shold, xfhold, yfhold, hfhold, mfhold
+
+begin
+ ihold = id[star]
+ xhold = x[star]
+ yhold = y[star]
+ mhold = mag[star]
+ shold = sky[star]
+ xfhold = xfit[star]
+ yfhold = yfit[star]
+ hfhold = hfit[star]
+ mfhold = pmag[star]
+ sfhold = sat[star]
+
+ do i = star + 1, nstars {
+ id[i-1] = id[i]
+ x[i-1] = x[i]
+ y[i-1] = y[i]
+ mag[i-1] = mag[i]
+ sky[i-1] = sky[i]
+ xfit[i-1] = xfit[i]
+ yfit[i-1] = yfit[i]
+ hfit[i-1] = hfit[i]
+ pmag[i-1] = pmag[i]
+ sat[i-1] = sat[i]
+ }
+
+ id[nstars] = ihold
+ x[nstars] = xhold
+ y[nstars] = yhold
+ mag[nstars] = mhold
+ sky[nstars] = shold
+ xfit[nstars] = xfhold
+ yfit[nstars] = yfhold
+ hfit[nstars] = hfhold
+ pmag[nstars] = mfhold
+ sat[nstars] = sfhold
+end
+
+
+# DP_5SWAP -- Exchange the position of two stars in the APPHOT photometry
+# results.
+
+procedure dp_5swap (star1, star2, id, x, y, mag, sky)
+
+int star1, star2 # the indices of the two stars to exchange
+int id[ARB] # the ids of the stars
+real x[ARB] # the x postions of the stars
+real y[ARB] # the y positions of the stars
+real mag[ARB] # the magnitudes of the stars
+real sky[ARB] # the sky values of the stars
+
+int ihold
+real xhold, yhold, mhold, shold
+
+begin
+ ihold = id[star1]
+ xhold = x[star1]
+ yhold = y[star1]
+ mhold = mag[star1]
+ shold = sky[star1]
+
+ id[star1] = id[star2]
+ x[star1] = x[star2]
+ y[star1] = y[star2]
+ mag[star1] = mag[star2]
+ sky[star1] = sky[star2]
+
+ id[star2] = ihold
+ x[star2] = xhold
+ y[star2] = yhold
+ mag[star2] = mhold
+ sky[star2] = shold
+end
+
+
+# DP_10SWAP -- Exchange the position of two stars in the APPHOT photometry
+# and PSF fitting results.
+
+procedure dp_10swap (star1, star2, id, x, y, mag, sky, xfit, yfit, hfit, pmag,
+ sat)
+
+int star1, star2 # the indices of the two stars to exchange
+int id[ARB] # the ids of the stars
+real x[ARB] # the x postions of the stars
+real y[ARB] # the y positions of the stars
+real mag[ARB] # the magnitudes of the stars
+real sky[ARB] # the sky values of the stars
+real xfit[ARB] # the current x fit array
+real yfit[ARB] # the current y fit array
+real hfit[ARB] # the current height of the stars
+real pmag[ARB] # the psf star list magnitudes
+int sat[ARB] # are the star saturated
+
+int ihold, sfhold
+real xhold, yhold, mhold, shold, xfhold, yfhold, hfhold, mfhold
+
+begin
+ ihold = id[star1]
+ xhold = x[star1]
+ yhold = y[star1]
+ mhold = mag[star1]
+ shold = sky[star1]
+ xfhold = xfit[star1]
+ yfhold = yfit[star1]
+ hfhold = hfit[star1]
+ mfhold = pmag[star1]
+ sfhold = sat[star1]
+
+ id[star1] = id[star2]
+ x[star1] = x[star2]
+ y[star1] = y[star2]
+ mag[star1] = mag[star2]
+ sky[star1] = sky[star2]
+ xfit[star1] = xfit[star2]
+ yfit[star1] = yfit[star2]
+ hfit[star1] = hfit[star2]
+ pmag[star1] = pmag[star2]
+ sat[star1] = sat[star2]
+
+ id[star2] = ihold
+ x[star2] = xhold
+ y[star2] = yhold
+ mag[star2] = mhold
+ sky[star2] = shold
+ xfit[star2] = xfhold
+ yfit[star2] = yfhold
+ hfit[star2] = hfhold
+ pmag[star2] = mfhold
+ sat[star2] = sfhold
+end
+
+
+# DP_ISSAT -- Is the candidate PSF star saturated ?
+
+int procedure dp_issat (dao, starno)
+
+pointer dao # pointer to the daophot structure
+int starno # the star index number
+
+pointer psf
+
+begin
+ psf = DP_PSF(dao)
+ if (Memi[DP_PSAT(psf)+starno-1] == YES)
+ return (YES)
+ else
+ return (NO)
+end
diff --git a/noao/digiphot/daophot/psf/dppstat.x b/noao/digiphot/daophot/psf/dppstat.x
new file mode 100644
index 00000000..4b3f903f
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dppstat.x
@@ -0,0 +1,80 @@
+include "../lib/daophotdef.h"
+include "../lib/psfdef.h"
+#
+## DP_PSTATS -- Fetch a psf fitting string parameter.
+#
+#procedure dp_pstats (dao, param, str, maxch)
+#
+#pointer dao # pointer to daophot structure
+#int param # parameter
+#char str[ARB] # string value
+#int maxch # maximum number of characters
+#
+#begin
+# switch (param) {
+# default:
+# call error (0, "DP_PSTATS: Unknown psf fitting string parameter")
+# }
+#end
+#
+
+# DP_PSTATI -- Fetch a psf fitting integer parameter.
+
+int procedure dp_pstati (dao, param)
+
+pointer dao # pointer to daophot structure
+int param # parameter
+
+pointer psf
+
+begin
+ psf = DP_PSF(dao)
+
+ switch (param) {
+ case CUR_PSF:
+ return (DP_CUR_PSF(psf))
+ case CUR_PSFID:
+ return (DP_CUR_PSFID(psf))
+ case PNUM:
+ return (DP_PNUM(psf))
+ case PLOTTYPE:
+ return (DP_PLOTTYPE(psf))
+ case LENUSERAREA:
+ return (DP_LENUSERAREA(psf))
+ default:
+ call error (0, "DP_PSTATI: Unknown psf fitting integer parameter")
+ }
+end
+
+
+# DP_PSTATR -- Fetch a psf fitting real parameter.
+
+real procedure dp_pstatr (dao, param)
+
+pointer dao # pointer to daophot structure
+int param # parameter
+
+pointer psf
+
+begin
+ psf = DP_PSF(dao)
+
+ switch (param) {
+ case CUR_PSFX:
+ return (DP_CUR_PSFX(psf))
+ case CUR_PSFY:
+ return (DP_CUR_PSFY(psf))
+ case CUR_PSFSKY:
+ return (DP_CUR_PSFSKY(psf))
+ case CUR_PSFMAG:
+ return (DP_CUR_PSFMAG(psf))
+ case CUR_PSFMIN:
+ return (DP_CUR_PSFMIN(psf))
+ case CUR_PSFMAX:
+ return (DP_CUR_PSFMAX(psf))
+ case CUR_PSFGMAX:
+ return (DP_CUR_PSFGMAX(psf))
+ default:
+ call error (0, "DP_PSTATR: Unknown psf fitting parameter")
+ }
+end
diff --git a/noao/digiphot/daophot/psf/dppsubrast.x b/noao/digiphot/daophot/psf/dppsubrast.x
new file mode 100644
index 00000000..1fafb408
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dppsubrast.x
@@ -0,0 +1,172 @@
+include <mach.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+include "../lib/psfdef.h"
+
+# DP_PSUBRAST -- Fetch the prospective PSF star data and check it for bad
+# pixel values.
+
+pointer procedure dp_psubrast (dao, im, lowbad, highbad, x1, x2, y1, y2,
+ saturated)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+real lowbad, highbad # minimum and maximum good data values
+int x1, x2 # output x limits of the extracted subraster
+int y1, y2 # output y limits of the extracted subraster
+int saturated # is the star saturated ?
+
+pointer psf, buf
+real psfrad, fitrad
+int dp_chksr()
+pointer dp_subrast()
+
+begin
+ # Initialize.
+ psf = DP_PSF(dao)
+ buf = NULL
+ psfrad = DP_PSFRAD(dao)
+ fitrad = DP_FITRAD(dao)
+
+ # Get the data.
+ buf = dp_subrast (im, DP_CUR_PSFX(psf), DP_CUR_PSFY(psf), psfrad,
+ x1, x2, y1, y2)
+ if (buf == NULL)
+ return (NULL)
+
+ # Check for bad pixels in subraster, compute the min and max.
+ if (dp_chksr (DP_CUR_PSFX(psf), DP_CUR_PSFY(psf), Memr[buf],
+ x2 - x1 + 1, y2 - y1 + 1, x1, y1, psfrad, fitrad,
+ lowbad, highbad, saturated, DP_CUR_PSFMIN(psf),
+ DP_CUR_PSFMAX(psf), DP_CUR_PSFGMAX(psf)) == ERR) {
+ call mfree (buf, TY_REAL)
+ return (NULL)
+ }
+
+ return (buf)
+end
+
+
+# DL_LSUBRAST -- Give a valid PSF star compute the limits of the data to
+# be extracted around it.
+
+int procedure dp_lsubrast (im, xcen, ycen, radius, x1, x2, y1, y2)
+
+pointer im # input image descriptor
+real xcen, ycen # center of subraster
+real radius # radius of the box
+int x1, y1, x2, y2 # boundaries of subraster
+
+begin
+ # Calculate start position of extraction box.
+ x1 = int (xcen - radius) - 2
+ x2 = int (xcen + radius) + 3
+ y1 = int (ycen - radius) - 2
+ y2 = int (ycen + radius) + 3
+ if (x1 > IM_LEN(im,1) || x2 < 1 || y1 > IM_LEN(im,2) || y2 < 1)
+ return (ERR)
+
+ x1 = max (1, x1)
+ x2 = min (IM_LEN(im,1), x2)
+ y1 = max (1, y1)
+ y2 = min (IM_LEN(im,2), y2)
+ return (OK)
+end
+
+
+# DP_SUBRAST -- Given a valid PSF star extract the data around it.
+
+pointer procedure dp_subrast (im, xcen, ycen, radius, x1, x2, y1, y2)
+
+pointer im # input image descriptor
+real xcen, ycen # center of subraster
+real radius # radius of the box
+int x1, y1, x2, y2 # boundaries of subraster
+
+int j, ncols
+pointer buf, ptr, imbuf
+pointer imgs2r()
+
+begin
+ # Calculate start position of extraction box.
+ x1 = int (xcen - radius) - 2
+ x2 = int (xcen + radius) + 3
+ y1 = int (ycen - radius) - 2
+ y2 = int (ycen + radius) + 3
+ if (x1 > IM_LEN(im,1) || x2 < 1 || y1 > IM_LEN(im,2) || y2 < 1)
+ return (NULL)
+
+ x1 = max (1, x1)
+ x2 = min (IM_LEN(im,1), x2)
+ y1 = max (1, y1)
+ y2 = min (IM_LEN(im,2), y2)
+ call malloc (buf, (x2 - x1 + 1) * (y2 - y1 + 1), TY_REAL)
+
+ ptr = buf
+ ncols = x2 - x1 + 1
+ do j = y1, y2 {
+ imbuf = imgs2r (im, x1, x2, j, j)
+ call amovr (Memr[imbuf], Memr[ptr], ncols)
+ ptr = ptr + ncols
+ }
+
+ return (buf)
+end
+
+
+# DP_CHKSR -- Check the input subraster for bad pixels.
+
+int procedure dp_chksr (x, y, sr, xdim, ydim, x1, y1, psfrad, fitrad, lowbad,
+ highbad, saturated, dmin, dmax, gmax)
+
+real x, y # position of the star
+real sr[xdim,ydim] # the data subraster
+int xdim, ydim # the dimensions of the subraster
+int x1, y1 # the lower left hand coordinates of the array
+real psfrad # the psf radius
+real fitrad # the fitting radius
+real lowbad, highbad # the good data limits
+int saturated # is the star saturated
+real dmin, dmax # output data limits
+real gmax # maximum good data limit
+
+int i,j
+real pradsq, fradsq, dy2, r2
+
+begin
+ pradsq = psfrad * psfrad
+ fradsq = fitrad * fitrad
+ dmin = MAX_REAL
+ dmax = -MAX_REAL
+ gmax = -MAX_REAL
+ saturated = NO
+
+ # Loop through the pixels looking for bad values.
+ do j = 1, ydim {
+ dy2 = (y - (y1 + j -1)) ** 2
+ if (dy2 > pradsq)
+ next
+ do i = 1, xdim {
+ r2 = (x - (x1 + i - 1)) ** 2 + dy2
+ if (r2 > pradsq)
+ next
+ if (sr[i,j] < dmin)
+ dmin = sr[i,j]
+ if (sr[i,j] > dmax)
+ dmax = sr[i,j]
+ if (sr[i,j] < lowbad || sr[i,j] > highbad) {
+ if (r2 <= fradsq) {
+ if (sr[i,j] < lowbad)
+ return (ERR)
+ else if (saturated == NO)
+ saturated = YES
+ }
+ } else {
+ if (sr[i,j] > gmax)
+ gmax = sr[i,j]
+ }
+ }
+ }
+
+ return (OK)
+end
diff --git a/noao/digiphot/daophot/psf/dpptconfirm.x b/noao/digiphot/daophot/psf/dpptconfirm.x
new file mode 100644
index 00000000..21047440
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dpptconfirm.x
@@ -0,0 +1,21 @@
+# DP_PTCONFIRM -- Confirm the critical PSTSELECT parameters.
+
+procedure dp_ptconfirm (dao)
+
+pointer dao # pointer to the daophot structure
+
+begin
+ call printf ("\n")
+
+ # Confirm the psf radius.
+ call dp_vpsfrad (dao)
+
+ # Confirm the fitting radius.
+ call dp_vfitrad (dao)
+
+ # Confirm the data minimum and maximum values.
+ call dp_vdatamin (dao)
+ call dp_vdatamax (dao)
+
+ call printf ("\n")
+end
diff --git a/noao/digiphot/daophot/psf/dppwrtgrp.x b/noao/digiphot/daophot/psf/dppwrtgrp.x
new file mode 100644
index 00000000..e0aad167
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dppwrtgrp.x
@@ -0,0 +1,642 @@
+include <time.h>
+include <tbset.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/psfdef.h"
+
+
+# DP_WNEISTARS -- Identify the neighbour stars of the psf stars and write them
+# out in groups.
+
+procedure dp_wneistars (dao, im, psfgr)
+
+pointer dao # pointer to the daophot structure
+pointer im # the input image descriptor
+int psfgr # the output group file descriptor
+
+bool newfile
+int top_star, psf_star, nei1, nei2
+pointer psf
+int dp_neistars()
+
+begin
+ psf = DP_PSF(dao)
+ newfile = true
+ top_star = DP_PNUM(psf) + 1
+ do psf_star = 1, DP_PNUM(psf) {
+ if (dp_neistars (dao, psf_star, top_star, nei1, nei2) <= 0)
+ ;
+ call dp_pwrtgrp (dao, im, psfgr, psf_star, nei1, nei2, newfile)
+ if (newfile)
+ newfile = false
+ }
+end
+
+
+# DP_NEISTARS -- Identify the neighbours and friends of the neighbours for
+# an individual PSF star.
+
+int procedure dp_neistars (dao, psf_star, top_star, nei1, nei2)
+
+pointer dao # pointer to the daophot structure
+int psf_star # the psf star in question
+int top_star # pointer to the current top_star
+int nei1, nei2 # pointer to to the list of neighbours
+
+int j, nei_star
+pointer apsel
+real rsq1, rsq2, rsq
+
+begin
+ # Define some pointers
+ apsel = DP_APSEL(dao)
+
+ # These are thhe values used by daophot ii. I have decided to keep
+ # the old values because I have kept the old grouping algorithm.
+ #rsq1 = (1.5 * DP_PSFRAD(dao) + 2.0 * DP_FITRAD(dao) + 1.0) ** 2
+ #rsq2 = (2.0 * DP_FITRAD(dao) + 1.0) ** 2
+
+ rsq1 = (DP_PSFRAD(dao) + 2.0 * DP_FITRAD(dao) + 1.0) ** 2
+ rsq2 = (2.0 * DP_FITRAD(dao)) ** 2
+
+ # Find the neighbour stars for a given psf star. This step is the
+ # same as the daophot ii step although I am using a smaller critical
+ # radius.
+
+ nei1 = top_star
+ for (j = top_star; j <= DP_APNUM(apsel); j = j + 1) {
+ rsq = (Memr[DP_APXCEN(apsel)+j-1] -
+ Memr[DP_APSEL(apsel)+psf_star-1]) ** 2 +
+ (Memr[DP_APYCEN(apsel)+j-1] -
+ Memr[DP_APYCEN(apsel)+psf_star-1]) ** 2
+ if (rsq > rsq1)
+ next
+ call dp_5swap (j, top_star, Memi[DP_APID(apsel)],
+ Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[DP_APMAG(apsel)], Memr[DP_APMSKY(apsel)])
+ top_star = top_star +1
+ }
+ nei2 = top_star - 1
+
+ # Find the friends of the neighbor stars. I do this on a per psf
+ # star basis. I do not find friends of all the neighbor stars
+ # only the neighbour stars for a particular psf star. This is
+ # because I found the daophot ii algorithm could produce too
+ # may odd stars.
+
+ do nei_star = nei1, nei2 {
+ for (j = top_star; j <= DP_APNUM(apsel); j = j + 1) {
+ rsq = (Memr[DP_APXCEN(apsel)+j-1] -
+ Memr[DP_APSEL(apsel)+nei_star-1]) ** 2 +
+ (Memr[DP_APYCEN(apsel)+j-1] -
+ Memr[DP_APYCEN(apsel)+nei_star-1]) ** 2
+ if (rsq > rsq2)
+ next
+ call dp_5swap (j, top_star, Memi[DP_APID(apsel)],
+ Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[DP_APMAG(apsel)], Memr[DP_APMSKY(apsel)])
+ top_star = top_star +1
+ }
+ }
+ nei2 = top_star - 1
+
+ return (nei2 - nei1 + 1)
+end
+
+
+# DP_PWRTGRP -- Add a group to the PSF output group file.
+
+procedure dp_pwrtgrp (dao, im, psfgr, psf_star, nei1_star, nei2_star, new_table)
+
+pointer dao # the pointer to the daophot structure
+pointer im # the input image descriptor
+int psfgr # the group file descriptor
+int psf_star # the psf star index
+int nei1_star, nei2_star # the first and last neighbour star indices
+bool new_table # should a new table be created
+
+int group
+
+begin
+ # Chexk to see if the PSF group file is open.
+ if (psfgr == NULL)
+ return
+
+ # Create the table.
+ if (new_table) {
+
+ # Initialize.
+ group = 1
+
+ # Make a new group.
+ if (DP_TEXT(dao) == YES)
+ call dp_pxnewgrp (dao, im, psfgr, psf_star, nei1_star,
+ nei2_star, group)
+ else
+ call dp_ptnewgrp (dao, im, psfgr, psf_star, nei1_star,
+ nei2_star, group)
+
+ } else {
+
+ # Increment.
+ group = group + 1
+
+ # Add to the file.
+ if (DP_TEXT(dao) == YES)
+ call dp_pxaddgrp (dao, im, psfgr, psf_star, nei1_star,
+ nei2_star, group)
+ else
+ call dp_ptaddgrp (dao, im, psfgr, psf_star, nei1_star,
+ nei2_star, group)
+ }
+
+end
+
+
+define NCOLUMN 5
+
+# DP_WPLIST -- Write the list of psf stars to the output psf star list.
+
+procedure dp_wplist (dao, im, opst)
+
+pointer dao # pointer to the daophot structure
+pointer im # the input image descriptor
+int opst # the output psf star list descriptor
+
+pointer apsel, psf, sp, ocolpoint, tx, ty
+int dp_stati()
+bool itob()
+
+begin
+ # Get some daophot pointers.
+ apsel = DP_APSEL(dao)
+ psf = DP_PSF(dao)
+
+ # Allocate some working memory.
+ call smark (sp)
+ call salloc (ocolpoint, NCOLUMN, TY_POINTER)
+ call salloc (tx, DP_PNUM(psf), TY_REAL)
+ call salloc (ty, DP_PNUM(psf), TY_REAL)
+
+ # Initialize the output file.
+ if (dp_stati (dao, TEXT) == YES) {
+ call dp_pxgrppars (dao, opst)
+ call dp_xpbanner (opst)
+ } else {
+ call dp_tpdefcol (opst, Memi[ocolpoint])
+ call dp_ptgrppars (dao, opst)
+ }
+
+ # Write out the stars.
+ call dp_wout (dao, im, Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[tx], Memr[ty], DP_PNUM(psf))
+ call dp_wpstars (opst, Memi[ocolpoint], itob (dp_stati (dao, TEXT)),
+ Memi[DP_APID(apsel)], Memr[tx], Memr[ty], Memr[DP_APMAG(apsel)],
+ Memr[DP_APMSKY(apsel)], DP_PNUM(psf))
+
+ # Free memory.
+ call sfree (sp)
+end
+
+
+define PGR_NAMESTR "#N%4tID%10tGROUP%16tXCENTER%26tYCENTER%36tMAG%48t\
+MSKY%80t\\\n"
+define PGR_UNITSTR "#U%4t##%10t##%16tpixels%26tpixels%36tmagnitudes%48t\
+counts%80t\\\n"
+define PGR_FORMATSTR "#F%4t%%-9d%10t%%-6d%16t%%-10.3f%26t%%-10.3f%36t\
+%%-12.3f%48t%%-15.7g%80t \n"
+define PGR_DATASTR "%-9d%10t%-6d%16t%-10.3f%26t%-10.3f%36t%-12.3f%48t\
+%-15.7g%80t \n"
+
+# DP_PXNEWGRP -- Create a new PSF output group text file and write the
+# first group to it.
+
+procedure dp_pxnewgrp (dao, im, tp, psf_star, nei1_star, nei2_star, group)
+
+pointer dao # pointer to the daophot structure.
+pointer im # pointer to the input image
+int tp # the output file descriptor
+int psf_star # the psf star index
+int nei1_star, nei2_star # the first and last neighbour star indices
+int group # current group
+
+real tx, ty
+pointer apsel
+int i
+
+begin
+ # Check to see if the PSF group file is open.
+ if (tp == NULL)
+ return
+
+ # Define some pointers.
+ apsel = DP_APSEL(dao)
+
+ # Write out the header parameters.
+ call dp_pxgrppars (dao, tp)
+
+ # Set up the column definitions.
+ call fprintf (tp, "#\n")
+ call fprintf (tp, PGR_NAMESTR)
+ call fprintf (tp, PGR_UNITSTR)
+ call fprintf (tp, PGR_FORMATSTR)
+ call fprintf (tp, "#\n")
+
+ # Write out the psf star.
+ call dp_wout (dao, im, Memr[DP_APXCEN(apsel)+psf_star-1],
+ Memr[DP_APYCEN(apsel)+psf_star-1], tx, ty, 1)
+ call fprintf (tp, PGR_DATASTR)
+ call pargi (Memi[DP_APID(apsel)+psf_star-1])
+ call pargi (group)
+ call pargr (tx)
+ call pargr (ty)
+ call pargr (Memr[DP_APMAG(apsel)+psf_star-1])
+ call pargr (Memr[DP_APMSKY(apsel)+psf_star-1])
+
+ # Write out the neighbour stars.
+ do i = nei1_star, nei2_star {
+ call dp_wout (dao, im, Memr[DP_APXCEN(apsel)+i-1],
+ Memr[DP_APYCEN(apsel)+i-1], tx, ty, 1)
+ call fprintf (tp, PGR_DATASTR)
+ call pargi (Memi[DP_APID(apsel)+i-1])
+ call pargi (group)
+ call pargr (tx)
+ call pargr (ty)
+ call pargr (Memr[DP_APMAG(apsel)+i-1])
+ call pargr (Memr[DP_APMSKY(apsel)+i-1])
+ }
+end
+
+
+# DP_PTNEWGRP -- Create a new PSF output group ST table and add to a new
+# group to it.
+
+procedure dp_ptnewgrp (dao, im, tp, psf_star, nei1_star, nei2_star, group)
+
+pointer dao # pointer to the daophot structure.
+pointer im # the input image descriptor
+pointer tp # pointer to table
+int psf_star # the psf star index
+int nei1_star, nei2_star # the first and last psf star indices
+int group # current group
+
+real tx, ty
+pointer sp, colnames, colunits, colformat, coldtype, collen, colpoint
+pointer apsel
+int i, j, row
+
+begin
+ # Check to see if the PSF group file is open.
+ if (tp == NULL)
+ return
+
+ # Define some pointers.
+ apsel = DP_APSEL(dao)
+
+ # Allocate space for table definition.
+ call smark (sp)
+ call salloc (colpoint, PSF_NOUTCOLS, TY_INT)
+ call salloc (colnames, PSF_NOUTCOLS * (SZ_COLNAME + 1), TY_CHAR)
+ call salloc (colunits, PSF_NOUTCOLS * (SZ_COLUNITS + 1), TY_CHAR)
+ call salloc (colformat, PSF_NOUTCOLS * (SZ_COLFMT + 1), TY_CHAR)
+ call salloc (coldtype, PSF_NOUTCOLS, TY_INT)
+ call salloc (collen, PSF_NOUTCOLS, TY_INT)
+
+ # Set up the column definitions.
+ call strcpy (ID, Memc[colnames], SZ_COLNAME)
+ call strcpy (GROUP, Memc[colnames+SZ_COLNAME+1], SZ_COLNAME)
+ call strcpy (XCENTER, Memc[colnames+2*SZ_COLNAME+2], SZ_COLNAME)
+ call strcpy (YCENTER, Memc[colnames+3*SZ_COLNAME+3], SZ_COLNAME)
+ call strcpy (MAG, Memc[colnames+4*SZ_COLNAME+4], SZ_COLNAME)
+ call strcpy (SKY, Memc[colnames+5*SZ_COLNAME+5], SZ_COLNAME)
+
+ # Set up the format definitions.
+ call strcpy ("%6d", Memc[colformat], SZ_COLFMT)
+ call strcpy ("%6d", Memc[colformat+SZ_COLFMT+1], SZ_COLFMT)
+ call strcpy ("%10.2f", Memc[colformat+2*SZ_COLFMT+2], SZ_COLFMT)
+ call strcpy ("%10.2f", Memc[colformat+3*SZ_COLFMT+3], SZ_COLFMT)
+ call strcpy ("%12.3f", Memc[colformat+4*SZ_COLFMT+4], SZ_COLFMT)
+ call strcpy ("%15.7g", Memc[colformat+5*SZ_COLFMT+5], SZ_COLFMT)
+
+ # Define the column units.
+ call strcpy ("NUMBER", Memc[colunits], SZ_COLUNITS)
+ call strcpy ("NUMBER", Memc[colunits+SZ_COLUNITS+1], SZ_COLUNITS)
+ call strcpy ("PIXELS", Memc[colunits+2*SZ_COLUNITS+2], SZ_COLUNITS)
+ call strcpy ("PIXELS", Memc[colunits+3*SZ_COLUNITS+3], SZ_COLUNITS)
+ call strcpy ("MAGNITUDES", Memc[colunits+4*SZ_COLUNITS+4], SZ_COLUNITS)
+ call strcpy ("COUNTS", Memc[colunits+5*SZ_COLUNITS+5], SZ_COLUNITS)
+
+ # Define the datatypes of the columns.
+ Memi[coldtype] = TY_INT
+ Memi[coldtype+1] = TY_INT
+ Memi[coldtype+2] = TY_REAL
+ Memi[coldtype+3] = TY_REAL
+ Memi[coldtype+4] = TY_REAL
+ Memi[coldtype+5] = TY_REAL
+
+ # Initialize the column length parameter.
+ do i = 1, PSF_NOUTCOLS {
+ j = i - 1
+ Memi[collen+j] = 1
+ }
+
+ # Define the table.
+ call tbcdef (tp, Memi[colpoint], Memc[colnames], Memc[colunits],
+ Memc[colformat], Memi[coldtype], Memi[collen], PSF_NOUTCOLS)
+
+ # Create the table.
+ call tbtcre (tp)
+
+ # Write out the psf star.
+ call dp_wout (dao, im, Memr[DP_APXCEN(apsel)+psf_star-1],
+ Memr[DP_APYCEN(apsel)+psf_star-1], tx, ty, 1)
+ call tbrpti (tp, Memi[colpoint], Memi[DP_APID(apsel)+psf_star-1], 1, 1)
+ call tbrpti (tp, Memi[colpoint+1], group, 1, 1)
+ call tbrptr (tp, Memi[colpoint+2], tx, 1, 1)
+ call tbrptr (tp, Memi[colpoint+3], ty, 1, 1)
+ call tbrptr (tp, Memi[colpoint+4], Memr[DP_APMAG(apsel)+psf_star-1],
+ 1, 1)
+ call tbrptr (tp, Memi[colpoint+5], Memr[DP_APMSKY(apsel)+psf_star-1],
+ 1, 1)
+
+ # Now write out the group.
+ row = 2
+ do i = nei1_star, nei2_star {
+ call dp_wout (dao, im, Memr[DP_APXCEN(apsel)+i-1],
+ Memr[DP_APYCEN(apsel)+i-1], tx, ty, 1)
+ call tbrpti (tp, Memi[colpoint], Memi[DP_APID(apsel)+i-1], 1, row)
+ call tbrpti (tp, Memi[colpoint+1], group, 1, row)
+ call tbrptr (tp, Memi[colpoint+2], tx, 1, row)
+ call tbrptr (tp, Memi[colpoint+3], ty, 1, row)
+ call tbrptr (tp, Memi[colpoint+4], Memr[DP_APMAG(apsel)+i-1],
+ 1, row)
+ call tbrptr (tp, Memi[colpoint+5], Memr[DP_APMSKY(apsel)+i-1],
+ 1, row)
+ row = row + 1
+ }
+
+ # Add the header parameters to the table.
+ call dp_ptgrppars (dao, tp)
+
+ call sfree (sp)
+end
+
+
+# DP_PTGRPPARS -- Add parameters to the header of the output PSF group ST
+# table.
+
+procedure dp_ptgrppars (dao, tp)
+
+pointer dao # pointer to the daophot structure
+pointer tp # pointer to the table
+
+pointer sp, outstr, date, time
+int envfind()
+
+begin
+ # Check to see if the PSF group file is open.
+ if (tp == NULL)
+ return
+
+ # Allocate workin space.
+ call smark (sp)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+ call salloc (date, SZ_DATE, TY_CHAR)
+ call salloc (time, SZ_DATE, TY_CHAR)
+
+ # Write the task and date identifiers.
+ if (envfind ("version", Memc[outstr], SZ_LINE) <= 0)
+ call strcpy ("NOAO/IRAF", Memc[outstr], SZ_LINE)
+ call dp_rmwhite (Memc[outstr], Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "IRAF", Memc[outstr])
+ if (envfind ("userid", Memc[outstr], SZ_LINE) > 0)
+ call tbhadt (tp, "USER", Memc[outstr])
+ call gethost (Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "HOST", Memc[outstr])
+ call dp_date (Memc[date], Memc[time], SZ_DATE)
+ call tbhadt (tp, "DATE", Memc[date])
+ call tbhadt (tp, "TIME", Memc[time])
+
+ # Define the package and task.
+ call tbhadt (tp, "PACKAGE", "daophot")
+ call tbhadt (tp, "TASK", "psf")
+
+ # Define the input and output files.
+ call dp_imroot (DP_INIMAGE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "IMAGE", Memc[outstr])
+
+ call dp_froot (DP_INPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "PHOTFILE", Memc[outstr])
+ if (DP_COORDS(dao) == EOS)
+ call tbhadt (tp, "PSTFILE", "\"\"")
+ else {
+ call dp_froot (DP_COORDS(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "PSTFILE", Memc[outstr])
+ }
+ call dp_imroot (DP_PSFIMAGE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "PSFIMAGE", DP_PSFIMAGE(dao))
+ call dp_froot (DP_OUTREJFILE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "OPSTFILE", Memc[outstr])
+ call dp_froot (DP_OUTPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call tbhadt (tp, "GRPSFILE", Memc[outstr])
+
+ # Data dependent parameters.
+ call tbhadr (tp, "SCALE", DP_SCALE(dao))
+
+ # Observing parameters.
+ call tbhadt (tp, "OTIME", DP_OTIME(dao))
+ call tbhadt (tp, "IFILTER", DP_IFILTER(dao))
+ call tbhadr (tp, "XAIRMASS", DP_XAIRMASS(dao))
+
+ # Grouping parameters.
+ call tbhadr (tp, "PSFRAD", DP_SPSFRAD(dao))
+ call tbhadr (tp, "FITRAD", DP_SFITRAD(dao))
+
+ call sfree(sp)
+end
+
+
+# DP_PXGRPPARS -- Add parameters to the header of the output PSF group text
+# file.
+
+procedure dp_pxgrppars (dao, tp)
+
+pointer dao # pointer to the daophot structure
+int tp # the output file descriptor
+
+pointer sp, outstr, date, time
+int envfind()
+
+begin
+ # Check to see if the PSF group file is open.
+ if (tp == NULL)
+ return
+
+ # Allocate workin space.
+ call smark (sp)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+ call salloc (date, SZ_DATE, TY_CHAR)
+ call salloc (time, SZ_DATE, TY_CHAR)
+
+ # Write the task and date identifiers.
+ if (envfind ("version", Memc[outstr], SZ_LINE) <= 0)
+ call strcpy ("NOAO/IRAF", Memc[outstr], SZ_LINE)
+ call dp_rmwhite (Memc[outstr], Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "IRAF", Memc[outstr], "version", "")
+ if (envfind ("userid", Memc[outstr], SZ_LINE) > 0)
+ call dp_sparam (tp, "USER", Memc[outstr], "name", "")
+ call gethost (Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "HOST", Memc[outstr], "computer", "")
+ call dp_date (Memc[date], Memc[time], SZ_DATE)
+ call dp_sparam (tp, "DATE", Memc[date], "yyyy-mm-dd", "")
+ call dp_sparam (tp, "TIME", Memc[time], "hh:mm:ss", "")
+
+ # Define the package and task.
+ call dp_sparam (tp, "PACKAGE", "daophot", "name", "")
+ call dp_sparam (tp, "TASK", "psf", "name", "")
+
+ # Define the input and output files.
+ call dp_imroot (DP_INIMAGE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "IMAGE", Memc[outstr], "imagename", "")
+ call dp_froot (DP_INPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "PHOTFILE", Memc[outstr], "filename", "")
+ if (DP_COORDS(dao) == EOS)
+ call dp_sparam (tp, "PSTFILE", "\"\"", "filename", "")
+ else {
+ call dp_froot (DP_COORDS(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "PSTFILE", Memc[outstr], "filename", "")
+ }
+ call dp_imroot (DP_PSFIMAGE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "PSFIMAGE", Memc[outstr], "imagename", "")
+ call dp_froot (DP_OUTPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "GRPSFILE", Memc[outstr], "filename", "")
+ call dp_froot (DP_OUTREJFILE(dao), Memc[outstr], SZ_LINE)
+ call dp_sparam (tp, "OPSTFILE", Memc[outstr], "filename", "")
+
+ # Define the data dependent parameters.
+ call dp_rparam (tp, "SCALE", DP_SCALE(dao), "units/pix", "")
+
+ # Observing parameters.
+ call dp_sparam (tp, "OTIME", DP_OTIME(dao), "timeunit", "")
+ call dp_sparam (tp, "IFILTER", DP_IFILTER(dao), "filter", "")
+ call dp_rparam (tp, "XAIRMASS", DP_XAIRMASS(dao), "number", "")
+
+ # Grouping parameters.
+ call dp_rparam (tp, "PSFRAD", DP_SPSFRAD(dao), "scaleunit", "")
+ call dp_rparam (tp, "FITRAD", DP_SFITRAD(dao), "scaleunit", "")
+
+ call sfree(sp)
+end
+
+
+# DP_PXADDGRP -- Add a new group to the existing PSF output group text file.
+
+procedure dp_pxaddgrp (dao, im, tp, psf_star, nei1_star, nei2_star, group)
+
+pointer dao # pointer to daophot structure
+pointer im # the input image descriptor
+int tp # the output file descriptor
+int psf_star # the psf star index
+int nei1_star, nei2_star # the first and last neighbour star indices
+int group # current group
+
+real tx, ty
+pointer apsel
+int i
+
+begin
+ # Check to see if the PSF group file is open.
+ if (tp == NULL)
+ return
+
+ # Get some daophot pointers.
+ apsel = DP_APSEL(dao)
+
+ # Write out the psf star.
+ call dp_wout (dao, im, Memr[DP_APXCEN(apsel)+psf_star-1],
+ Memr[DP_APYCEN(apsel)+psf_star-1], tx, ty, 1)
+ call fprintf (tp, PGR_DATASTR)
+ call pargi (Memi[DP_APID(apsel)+psf_star-1])
+ call pargi (group)
+ call pargr (tx)
+ call pargr (ty)
+ call pargr (Memr[DP_APMAG(apsel)+psf_star-1])
+ call pargr (Memr[DP_APMSKY(apsel)+psf_star-1])
+
+ # Now write out the group.
+ do i = nei1_star, nei2_star {
+ call dp_wout (dao, im, Memr[DP_APXCEN(apsel)+i-1],
+ Memr[DP_APYCEN(apsel)+i-1], tx, ty, 1)
+ call fprintf (tp, PGR_DATASTR)
+ call pargi (Memi[DP_APID(apsel)+i-1])
+ call pargi (group)
+ call pargr (tx)
+ call pargr (ty)
+ call pargr (Memr[DP_APMAG(apsel)+i-1])
+ call pargr (Memr[DP_APMSKY(apsel)+i-1])
+ }
+end
+
+
+# DP_PTADDGRP -- Add a new group to the existing PSF output group ST table.
+
+procedure dp_ptaddgrp (dao, im, tp, psf_star, nei1_star, nei2_star, group)
+
+pointer dao # pointer to daophot structure
+pointer im # the input image descriptor
+pointer tp # pointer to output table
+int psf_star # the psf star index
+int nei1_star, nei2_star # the first and last neighbor star indices
+int group # current group
+
+real tx, ty
+pointer apsel, sp, colpoint
+int i, nrows
+int tbpsta()
+
+begin
+ # Check to see if the PSF group file is open.
+ if (tp == NULL)
+ return
+
+ # Allocate space for the column pointers.
+ call smark (sp)
+ call salloc (colpoint, PSF_NOUTCOLS, TY_INT)
+
+ # Get some daophot pointers.
+ apsel = DP_APSEL(dao)
+
+ # Find the number of rows in the table and add on at the end.
+ nrows = tbpsta (tp, TBL_NROWS)
+
+ # Write out the psf star
+ call dp_wout (dao, im, Memr[DP_APXCEN(apsel)+psf_star-1],
+ Memr[DP_APYCEN(apsel)+psf_star-1], tx, ty, 1)
+ nrows = nrows + 1
+ call tbrpti (tp, Memi[colpoint], Memi[DP_APID(apsel)+psf_star-1],
+ 1, nrows)
+ call tbrpti (tp, Memi[colpoint+1], group, 1, nrows)
+ call tbrptr (tp, Memi[colpoint+2], tx, 1, nrows)
+ call tbrptr (tp, Memi[colpoint+3], ty, 1, nrows)
+ call tbrptr (tp, Memi[colpoint+4], Memr[DP_APMAG(apsel)+psf_star-1],
+ 1, nrows)
+ call tbrptr (tp, Memi[colpoint+5], Memr[DP_APMSKY(apsel)+psf_star-1],
+ 1, nrows)
+
+ # Now write out the group.
+ do i = nei1_star, nei2_star {
+ nrows = nrows + 1
+ call dp_wout (dao, im, Memr[DP_APXCEN(apsel)+i-1],
+ Memr[DP_APYCEN(apsel)+i-1], tx, ty, 1)
+ call tbrpti (tp, Memi[colpoint], Memi[DP_APID(apsel)+i-1], 1, nrows)
+ call tbrpti (tp, Memi[colpoint+1], group, 1, nrows)
+ call tbrptr (tp, Memi[colpoint+2], tx, 1, nrows)
+ call tbrptr (tp, Memi[colpoint+3], ty, 1, nrows)
+ call tbrptr (tp, Memi[colpoint+4], Memr[DP_APMAG(apsel)+i-1], 1,
+ nrows)
+ call tbrptr (tp, Memi[colpoint+5], Memr[DP_APMSKY(apsel)+i-1], 1,
+ nrows)
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/psf/dppwselmer.x b/noao/digiphot/daophot/psf/dppwselmer.x
new file mode 100644
index 00000000..24684b67
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dppwselmer.x
@@ -0,0 +1,220 @@
+include <tbset.h>
+include "../lib/apseldef.h"
+
+define NCOLUMN 5
+
+define PS_DATA1STR "%-9d%10t%-10.3f%20t%-10.3f%30t%-12.3f%42t%-15.7g%80t \n"
+
+# DP_XPSELMER -- Write the output photometry record to a text file.
+
+procedure dp_xpselmer (tpout, id, x, y, mag, sky)
+
+pointer tpout # pointer to the output table
+int id # id of the star
+real x, y # position of the star
+real mag # magnitude of the star
+real sky # value of sky
+
+begin
+ call fprintf (tpout, PS_DATA1STR)
+ call pargi (id)
+ call pargr (x)
+ call pargr (y)
+ call pargr (mag)
+ call pargr (sky)
+end
+
+
+# DP_TPSELMER -- Write out the PSF stars into an ST Table.
+
+procedure dp_tpselmer (tp_out, id, x, y, mag, sky, colpoint, row)
+
+int tp_out # the output table descriptor
+int id # the object id
+real x # the object x coordinate
+real y # the object y coordinate
+real mag # the object mangitude
+real sky # the object sky value
+int colpoint[ARB] # the column pointers
+int row # current table row
+
+begin
+ # Write out the data.
+ call tbrpti (tp_out, colpoint[1], id, 1, row)
+ call tbrptr (tp_out, colpoint[2], x, 1, row)
+ call tbrptr (tp_out, colpoint[3], y, 1, row)
+ call tbrptr (tp_out, colpoint[4], mag, 1, row)
+ call tbrptr (tp_out, colpoint[5], sky, 1, row)
+end
+
+
+# DP_XPSELPARS -- Add various parameters to the header of the photometry table.
+
+procedure dp_xpselpars (tp, image, maxnpsf, scale, psfrad, fitrad)
+
+pointer tp # pointer to the table
+char image[ARB] # input image name
+int maxnpsf # maximum number of psfstars
+real scale # the image scale
+real psfrad # the psf radius
+real fitrad # the fitting radius
+
+pointer sp, str
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Add the image name nad maxnpsf parameters.
+ call dp_imroot (image, Memc[str], SZ_FNAME)
+ call dp_sparam (tp, "IMAGE", Memc[str], "imagename", "")
+ call dp_iparam (tp, "MAXNPSF", maxnpsf, "number", "")
+ call dp_rparam (tp, "NEWSCALE", scale, "units", "")
+ call dp_rparam (tp, "PSFRAD", psfrad, "scaleunit", "")
+ call dp_rparam (tp, "FITRAD", fitrad, "scaleunit", "")
+
+ call sfree (sp)
+end
+
+
+define PS_NAME1STR "#N%4tID%10tXCENTER%20tYCENTER%30tMAG%42tMSKY%80t\\\n"
+define PS_UNIT1STR "#U%4t##%10tpixels%20tpixels%30tmagnitudes%42tcounts\
+%80t\\\n"
+define PS_FORMAT1STR "#F%4t%%-9d%10t%%-10.3f%20t%%-10.3f%30t%%-12.3f%42t\
+%%-15.7g%80t \n"
+
+# DP_XPBANNER -- Create a new text file banner.
+
+procedure dp_xpbanner (tp)
+
+pointer tp # pointer to the output file
+
+begin
+ # Print out the banner file.
+ call fprintf (tp, "#\n")
+ call fprintf (tp, PS_NAME1STR)
+ call fprintf (tp, PS_UNIT1STR)
+ call fprintf (tp, PS_FORMAT1STR)
+ call fprintf (tp, "#\n")
+end
+
+
+# DP_TPDEFCOL -- Define the columns for the output table
+
+procedure dp_tpdefcol (tp, colpoint)
+
+pointer tp # pointer to the output table
+int colpoint[ARB] # array of column pointers
+
+int i
+pointer sp, colnames, colunits, colformat, col_dtype, col_len
+
+begin
+ # Allocate space for the table definition.
+ call smark (sp)
+ call salloc (colnames, NCOLUMN * (SZ_COLNAME + 1), TY_CHAR)
+ call salloc (colunits, NCOLUMN * (SZ_COLUNITS + 1), TY_CHAR)
+ call salloc (colformat, NCOLUMN * (SZ_COLFMT + 1), TY_CHAR)
+ call salloc (col_dtype, NCOLUMN, TY_INT)
+ call salloc (col_len, NCOLUMN, TY_INT)
+
+ # Set up the column definitions.
+ call strcpy (ID, Memc[colnames], SZ_COLNAME)
+ call strcpy (XCENTER, Memc[colnames+SZ_COLNAME+1], SZ_COLNAME)
+ call strcpy (YCENTER, Memc[colnames+2*SZ_COLNAME+2], SZ_COLNAME)
+ call strcpy (MAG, Memc[colnames+3*SZ_COLNAME+3], SZ_COLNAME)
+ call strcpy (SKY, Memc[colnames+4*SZ_COLNAME+4], SZ_COLNAME)
+
+ # Define the column formats.
+ call strcpy ("%6d", Memc[colformat], SZ_COLFMT)
+ call strcpy ("10.3f", Memc[colformat+SZ_COLFMT+1], SZ_COLFMT)
+ call strcpy ("10.3f", Memc[colformat+2*SZ_COLFMT+2], SZ_COLFMT)
+ call strcpy ("12.3f", Memc[colformat+3*SZ_COLFMT+3], SZ_COLFMT)
+ call strcpy ("15.7g", Memc[colformat+4*SZ_COLFMT+4], SZ_COLFMT)
+
+ # Define the column units.
+ call strcpy ("NUMBER", Memc[colunits], SZ_COLUNITS)
+ call strcpy ("PIXELS", Memc[colunits+SZ_COLUNITS+1], SZ_COLUNITS)
+ call strcpy ("PIXELS", Memc[colunits+2*SZ_COLUNITS+2], SZ_COLUNITS)
+ call strcpy ("MAGNITUDES", Memc[colunits+3*SZ_COLUNITS+3], SZ_COLUNITS)
+ call strcpy ("ADU", Memc[colunits+4*SZ_COLUNITS+4], SZ_COLUNITS)
+
+ # Define the column data types.
+ Memi[col_dtype] = TY_INT
+ Memi[col_dtype+1] = TY_REAL
+ Memi[col_dtype+2] = TY_REAL
+ Memi[col_dtype+3] = TY_REAL
+ Memi[col_dtype+4] = TY_REAL
+
+ # Define the column lengths.
+ do i = 1, NCOLUMN
+ Memi[col_len+i-1] = 1
+
+ # Define and create the table.
+ call tbcdef (tp, colpoint, Memc[colnames], Memc[colunits],
+ Memc[colformat], Memi[col_dtype], Memi[col_len], NCOLUMN)
+ call tbtcre (tp)
+
+ call sfree (sp)
+end
+
+
+# DP_TPSELPARS -- Add various parameters to the header of the photometry table.
+
+procedure dp_tpselpars (tp, image, maxnpsf, scale, psfrad, fitrad)
+
+pointer tp # pointer to the table
+char image[ARB] # the input image name
+int maxnpsf # maximum number of psf stars
+real scale # the image scale
+real psfrad # the psf radius
+real fitrad # the fitting radius
+
+pointer sp, str
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Add the min_group and max_group parameters.
+ call dp_imroot (image, Memc[str], SZ_FNAME)
+ call tbhadt (tp, "IMAGE", Memc[str])
+ call tbhadi (tp, "MAXNPSF", maxnpsf)
+ call tbhadr (tp, "SCALE", scale)
+ call tbhadr (tp, "PSFRAD", psfrad)
+ call tbhadr (tp, "FITRAD", fitrad)
+
+ call sfree (sp)
+end
+
+
+# DP_WPSTARS -- Write the psf stars to the output file.
+
+procedure dp_wpstars (tp_out, colpoint, text_file, ids, xcen, ycen, mag,
+ sky, npsf)
+
+int tp_out # the output file descriptor
+int colpoint[ARB] # array of column pointers
+bool text_file # is the output file a text file
+int ids[ARB] # array of star ids
+real xcen[ARB] # array of x coordinates
+real ycen[ARB] # array of y coordinates
+real mag[ARB] # array of magnitudes
+real sky[ARB] # array of sky values
+int npsf # the number of stars
+
+int istar, row
+
+begin
+ row = 0
+ do istar = 1, npsf {
+ if (text_file)
+ call dp_xpselmer (tp_out, ids[istar], xcen[istar], ycen[istar],
+ mag[istar], sky[istar])
+ else {
+ row = row + 1
+ call dp_tpselmer (tp_out, ids[istar], xcen[istar], ycen[istar],
+ mag[istar], sky[istar], colpoint, row)
+ }
+ }
+end
diff --git a/noao/digiphot/daophot/psf/dpqverify.x b/noao/digiphot/daophot/psf/dpqverify.x
new file mode 100644
index 00000000..6fff239f
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dpqverify.x
@@ -0,0 +1,68 @@
+include <fset.h>
+
+define QUERY "[Hit return to continue, q to quit, w to force update of PSF]"
+
+# DP_QVERIFY -- Print a message in the status line asking the user if they
+# really want to quit, returning YES if they really want to quit, NO otherwise.
+
+int procedure dp_qverify (dao, im, psfim, opst, psfgr, psf_new, psf_computed,
+ psf_written)
+
+pointer dao # pointer to the daophot structure
+pointer im # the input image descriptor
+pointer psfim # the output psf image descriptor
+int opst # the output psf star list file descriptor
+int psfgr # the output psf group file descriptor
+bool psf_new # has the psf star list been defined ?
+bool psf_computed # is the psf fit defined ?
+bool psf_written # has the psf been saved ?
+
+int ch
+pointer tty
+bool dp_updatepsf()
+int getci()
+pointer ttyodes()
+
+begin
+ # Print status warning message.
+ if (psf_new)
+ call printf ("Warning: The PSF star list is undefined.\n")
+ else if (! psf_computed)
+ call printf ("Warning: The PSF fit is not current.\n")
+ else if (! psf_written)
+ call printf ("Warning: The PSF has not been saved.\n")
+
+ # Open terminal and print query.
+ tty = ttyodes ("terminal")
+ call ttyclearln (STDOUT, tty)
+ call ttyso (STDOUT, tty, YES)
+ call printf (QUERY)
+ call flush (STDOUT)
+
+ # Get character.
+ call fseti (STDIN, F_RAW, YES)
+ if (getci (STDIN, ch) == EOF)
+ ;
+
+ # Reset and close terminal.
+ call fseti (STDIN, F_RAW, NO)
+ call ttyso (STDOUT, tty, NO)
+ call ttyclearln (STDOUT, tty)
+ call printf ("\n")
+ call flush (STDOUT)
+ call ttycdes (tty)
+
+ # Return YES for the quit command, otherwise NO.
+ if (ch == 'q') {
+ return (YES)
+ } else if (ch == 'w') {
+ if (dp_updatepsf (dao, im, psfim, opst, psfgr, psf_new,
+ psf_computed, psf_written)) {
+ psf_computed = true
+ psf_written = true
+ }
+ return (NO)
+ } else {
+ return (NO)
+ }
+end
diff --git a/noao/digiphot/daophot/psf/dpradpsf.x b/noao/digiphot/daophot/psf/dpradpsf.x
new file mode 100644
index 00000000..7e649e7e
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dpradpsf.x
@@ -0,0 +1,75 @@
+include <gset.h>
+include "../lib/daophotdef.h"
+include "../lib/psfdef.h"
+
+define FRACTION 0.10
+
+# DP_RADPSF -- Draw a radial profile plot of a data subraster containing a
+# candidate psf star.
+
+procedure dp_radpsf (dao, subras, ncols, nlines, x1, y1, title, gp)
+
+pointer dao # pointer to DAOPHOT structure
+real subras[ncols,nlines] # data subraster
+int ncols, nlines # dimesnions of subraster
+int x1, y1 # coordinates of left hand corner
+char title[ARB] # title string
+pointer gp # pointer to graphics descriptor
+
+int npts
+pointer psf, sp, radius, intensity, str
+real ymin, ymax, r1, r2, i1, i2
+int dp_rivectors()
+
+begin
+ # Get the pointer to the DAOPHOT PSF fitting substructure.
+ psf = DP_PSF (dao)
+
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (radius, ncols * nlines, TY_REAL)
+ call salloc (intensity, ncols * nlines, TY_REAL)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Compute the radial profile.
+ npts = dp_rivectors (subras, ncols, nlines, x1, y1, DP_CUR_PSFX(psf),
+ DP_CUR_PSFY(psf), DP_PSFRAD(dao), Memr[radius], Memr[intensity])
+ call alimr (Memr[intensity], npts, ymin, ymax)
+
+ # Make the plot.
+ call gclear (gp)
+ r1 = -FRACTION * DP_PSFRAD(dao)
+ r2 = DP_PSFRAD(dao) + FRACTION * DP_PSFRAD(dao)
+ i1 = ymin - FRACTION * (ymax - ymin)
+ i2 = ymax + FRACTION * (ymax - ymin)
+ call gswind (gp, r1, r2, i1, i2)
+ call glabax (gp, title, "Radius (pixels)", "Intensity (counts)")
+ call gpmark (gp, Memr[radius], Memr[intensity], npts, GM_PLUS, 1.0,
+ 1.0)
+
+ # Mark the zero radius line.
+ call gamove (gp, 0.0, i1)
+ call gadraw (gp, 0.0, i2)
+
+ # Mark the sky level.
+ call gamove (gp, r1, DP_CUR_PSFSKY(psf))
+ call gadraw (gp, r2, DP_CUR_PSFSKY(psf))
+
+ # Mark the half-width at half-maximum.
+ call gamove (gp, DP_FWHMPSF(dao) / 2.0, i1)
+ call gadraw (gp, DP_FWHMPSF(dao) / 2.0, i2)
+ call sprintf (Memc[str], SZ_LINE, "Half-width half-maximum = %0.2f")
+ call pargr (DP_FWHMPSF(dao) / 2.0)
+ call gtext (gp, DP_FWHMPSF(dao) / 2.0, i2, Memc[str],
+ "q=h;u=180;v=t;p=r")
+
+ # Mark the fitting radius.
+ call gamove (gp, DP_FITRAD(dao), i1)
+ call gadraw (gp, DP_FITRAD(dao), i2)
+ call sprintf (Memc[str], SZ_LINE, "Fitting radius = %0.2f")
+ call pargr (DP_FITRAD(dao))
+ call gtext (gp, DP_FITRAD(dao), i2, Memc[str], "q=h;u=180;v=t;p=r")
+
+ call gflush (gp)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/psf/dprmpsf.x b/noao/digiphot/daophot/psf/dprmpsf.x
new file mode 100644
index 00000000..dd76c4d4
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dprmpsf.x
@@ -0,0 +1,156 @@
+include <imhdr.h>
+include <fset.h>
+include "../lib/daophotdef.h"
+include "../lib/psfdef.h"
+
+
+# DP_OPPSF -- Open the current psf image and the psf group file.
+
+procedure dp_oppsf (dao, psfim, opst, psfgr)
+
+pointer dao # pointer to the daophot structure
+pointer psfim # pointer to the psf image
+int opst # the psf star list descriptor
+int psfgr # the psf group file descriptor
+
+pointer sp, str
+int open(), dp_stati(), dp_pstati()
+pointer immap(), tbtopn()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Reopen the PSF star and group files.
+ call dp_stats (dao, OUTREJFILE, Memc[str], SZ_FNAME)
+ if (dp_stati (dao, TEXT) == YES)
+ opst = open (Memc[str], NEW_FILE, TEXT_FILE)
+ else
+ opst = tbtopn (Memc[str], NEW_FILE, 0)
+ call dp_stats (dao, OUTPHOTFILE, Memc[str], SZ_FNAME)
+ if (dp_stati (dao, TEXT) == YES)
+ psfgr = open (Memc[str], NEW_FILE, TEXT_FILE)
+ else
+ psfgr = tbtopn (Memc[str], NEW_FILE, 0)
+
+ # Reopen the psf image.
+ call dp_stats (dao, PSFIMAGE, Memc[str], SZ_FNAME)
+ psfim = immap (Memc[str], NEW_IMAGE, dp_pstati (dao, LENUSERAREA))
+
+ call sfree (sp)
+end
+
+
+# DP_UPDATEPSF -- Update the psf on disk.
+
+bool procedure dp_updatepsf (dao, im, psfim, opst, psfgr, psf_new, psf_current,
+ psf_written)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+pointer psfim # pointer to the psf image
+int opst # the psf star list file descriptor
+int psfgr # the psf group file descriptor
+bool psf_new # is the psf star list defined ?
+bool psf_current # is the psf fit uptodate
+bool psf_written # has the psf been saved on disk
+
+bool update
+pointer sp, str
+int dp_fitpsf()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ update = false
+ if (psfim == NULL) {
+ call printf ("Warning: The PSF image is undefined\n")
+ } else if (psfgr == NULL) {
+ call printf ("Warning: The PSF group file is undefined\n")
+ } else if (psf_new) {
+ call printf ("Warning: The PSF star list is undefined\n")
+ } else if (! psf_current) {
+ if (dp_fitpsf (dao, im, Memc[str], SZ_LINE) == OK) {
+ call dp_writepsf (dao, im, psfim)
+ call dp_wplist (dao, im, opst)
+ call dp_wneistars (dao, im, psfgr)
+ update = true
+ } else {
+ call printf ("%s\n")
+ call pargstr (Memc[str])
+ }
+ } else if (! psf_written) {
+ call dp_writepsf (dao, im, psfim)
+ call dp_wplist (dao, im, opst)
+ call dp_wneistars (dao, im, psfgr)
+ update = true
+ }
+
+ if (DP_VERBOSE(dao) == YES && update) {
+ call printf ("\nWriting PSF image %s\n")
+ call pargstr (IM_HDRFILE (psfim))
+ call dp_stats (dao, OUTREJFILE, Memc[str], SZ_FNAME)
+ call printf ("Writing output PSF star list %s\n")
+ call pargstr (Memc[str])
+ call dp_stats (dao, OUTPHOTFILE, Memc[str], SZ_FNAME)
+ call printf ("Writing output PSF star group file %s\n")
+ call pargstr (Memc[str])
+ }
+
+ call sfree (sp)
+
+ return (update)
+end
+
+
+# DP_RMPSF -- Close and delete the psf image and the psf group file.
+
+procedure dp_rmpsf (dao, psfim, opst, psfgr)
+
+pointer dao # pointer to the daophot structure
+pointer psfim # pointer to the psf image
+int opst # the psf star list file descriptor
+int psfgr # the psf group file descriptor
+
+pointer sp, temp
+int dp_stati(), access()
+
+begin
+ call smark (sp)
+ call salloc (temp, SZ_FNAME, TY_CHAR)
+
+ # Delete the psf star file. The access check is necessary because
+ # an empty tables file is automatically deleted by the system.
+ if (dp_stati (dao, TEXT) == YES) {
+ call fstats (opst, F_FILENAME, Memc[temp], SZ_FNAME)
+ call close (opst)
+ } else {
+ call tbtnam (opst, Memc[temp], SZ_FNAME)
+ call tbtclo (opst)
+ }
+ if (access (Memc[temp], 0, 0) == YES)
+ call delete (Memc[temp])
+ opst = NULL
+
+ # Delete the neighbours file. The access check is necessary because
+ # an empty tables file is automatically deleted by the system.
+ if (dp_stati (dao, TEXT) == YES) {
+ call fstats (psfgr, F_FILENAME, Memc[temp], SZ_FNAME)
+ call close (psfgr)
+ } else {
+ call tbtnam (psfgr, Memc[temp], SZ_FNAME)
+ call tbtclo (psfgr)
+ }
+ if (access (Memc[temp], 0, 0) == YES)
+ call delete (Memc[temp])
+ psfgr = NULL
+
+ # Delete the PSF image.
+ call strcpy (IM_HDRFILE(psfim), Memc[temp], SZ_FNAME)
+ call imunmap (psfim)
+ call imdelete (Memc[temp])
+ psfim = NULL
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/psf/dprstars.x b/noao/digiphot/daophot/psf/dprstars.x
new file mode 100644
index 00000000..21ca67d1
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dprstars.x
@@ -0,0 +1,156 @@
+include <gset.h>
+include <tbset.h>
+include "../lib/apseldef.h"
+include "../lib/psfdef.h"
+
+
+# DP_RPSTARS -- Read in the IDS and x and y positions of the PSF stars.
+
+procedure dp_rpstars (dao, im, pst, text_file, gd, mgd, id, mkstars,
+ matchbyid, showplots)
+
+pointer dao # pointer to the daophot structure
+pointer im # the input image descriptor
+int pst # the psf star list file descriptor
+bool text_file # text or table file ?
+pointer gd # the graphics descriptor
+pointer mgd # the plot file descriptor
+pointer id # the display device descriptor
+bool mkstars # mark the stars added to the psf
+bool matchbyid # match psf stars by id or position
+bool showplots # show the psf star plots
+
+real x, y, mag, rjunk
+pointer sp, fields, indices, key
+int i, nrow, idno
+real dp_pstatr()
+int tbpsta(), dp_apsel(), dp_addstar()
+
+begin
+ call smark (sp)
+ call salloc (fields, SZ_LINE, TY_CHAR)
+ call salloc (indices, PSF_NINCOLS, TY_INT)
+
+ if (text_file) {
+ call pt_kyinit (key)
+ Memi[indices] = DP_PAPID
+ Memi[indices+1] = DP_PAPXCEN
+ Memi[indices+2] = DP_PAPYCEN
+ Memi[indices+3] = DP_PAPMAG1
+ call dp_gappsf (Memi[indices], Memc[fields], PSF_NINCOLS)
+ } else {
+ call dp_tptinit (pst, Memi[indices])
+ nrow = tbpsta (pst, TBL_NROWS)
+ }
+
+ i = 1
+ repeat {
+
+ # Read the next star.
+
+ if (text_file) {
+ if (dp_apsel (key, pst, Memc[fields], Memi[indices], idno,
+ x, y, rjunk, mag) == EOF)
+ break
+ } else {
+ if (i > nrow)
+ break
+ call dp_tptread (pst, Memi[indices], idno, x, y, mag, i)
+ }
+
+ call dp_win (dao, im, x, y, x, y, 1)
+
+ # Add it to the PSF star list.
+ if (idno > 0) {
+ if (matchbyid) {
+ if (dp_addstar (dao, im, x, y, mag, idno, gd, mgd,
+ showplots) == OK) {
+ if (mkstars && id != NULL) {
+ call gmark (id, dp_pstatr(dao, CUR_PSFX),
+ dp_pstatr(dao, CUR_PSFY), GM_PLUS, -5.0, -5.0)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+
+ }
+ } else {
+ if (dp_addstar (dao, im, x, y, INDEFR, 0, gd, mgd,
+ showplots) == OK) {
+ if (mkstars && id != NULL) {
+ call gmark (id, dp_pstatr(dao, CUR_PSFX),
+ dp_pstatr(dao, CUR_PSFY), GM_PLUS, -5.0, -5.0)
+ if (id == gd)
+ call gflush (id)
+ else
+ call gframe (id)
+ }
+ }
+ }
+ }
+
+ i = i + 1
+ }
+
+ if (text_file)
+ call pt_kyfree (key)
+ call sfree (sp)
+end
+
+
+# DP_TPTINIT -- Set up the input psf star list ST table column pointers.
+
+procedure dp_tptinit (pst, column)
+
+int pst # the psf star list file descriptor
+int column[ARB] # array of column pointers
+
+begin
+ call tbcfnd (pst, ID, column[1], 1)
+ if (column[1] == NULL)
+ call tbcfnd (pst, "ID", column[1], 1)
+ if (column[1] == NULL)
+ call error (0, "Error reading ID column from PSF star file\n")
+
+ call tbcfnd (pst, XCENTER, column[2], 1)
+ if (column[2] == NULL)
+ call tbcfnd (pst, "XCENTER", column[2], 1)
+ if (column[2] == NULL)
+ call error (0, "Error reading XCENTER column from PSF star file\n")
+
+ call tbcfnd (pst, YCENTER, column[3], 1)
+ if (column[3] == NULL)
+ call tbcfnd (pst, "YCENTER", column[3], 1)
+ if (column[3] == NULL)
+ call error (0, "Error reading YCENTER column from PSF star file\n")
+
+ call tbcfnd (pst, MAG, column[4], 1)
+ if (column[4] == NULL)
+ call tbcfnd (pst, APMAG, column[4], 1)
+ if (column[4] == NULL)
+ call error (0, "Error reading MAG column from PSF star file\n")
+end
+
+
+# DP_TPTREAD -- Read the id from an ST table.
+
+procedure dp_tptread (pst, column, idno, x, y, mag, rowno)
+
+pointer pst # pointer to the ST table
+int column[ARB] # array of column pointers
+int idno # the output id number
+real x, y # the output x and y position
+real mag # the output magnitude
+int rowno # the row number
+
+bool nullflag
+
+begin
+ call tbrgti (pst, column[1], idno, nullflag, 1, rowno)
+ if (nullflag)
+ idno = 0
+ call tbrgtr (pst, column[2], x, nullflag, 1, rowno)
+ call tbrgtr (pst, column[3], y, nullflag, 1, rowno)
+ call tbrgtr (pst, column[4], mag, nullflag, 1, rowno)
+end
diff --git a/noao/digiphot/daophot/psf/dpshowpsf.x b/noao/digiphot/daophot/psf/dpshowpsf.x
new file mode 100644
index 00000000..ec5a7766
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dpshowpsf.x
@@ -0,0 +1,287 @@
+include <mach.h>
+include <ctype.h>
+include "../lib/daophotdef.h"
+include "../lib/psfdef.h"
+
+define HELPFILE "daophot$psf/showpsf.key"
+
+# DP_SHOWPSF -- Interactively make surface and/or contour plots of the
+# data subraster around the current PSF star.
+
+procedure dp_showpsf (dao, im, subrast, ncols, nlines, x1, y1, gd, star_ok)
+
+pointer dao # pointer to DAOPHOT structure
+pointer im # the input image descriptor
+real subrast[ncols,nlines] # image subraster
+int ncols, nlines # dimensions of the subraster
+int x1, y1 # coordinates of left hand corner
+pointer gd # pointer to the graphics stream
+bool star_ok # true if PSF star ok
+
+real hibad, wx, wy, rval
+pointer sp, cmd, title, psf
+int wcs, key, ip
+bool do_replot
+
+int clgcur(), ctor()
+
+begin
+ # Return if the graphics stream is undefined.
+ if (gd == NULL)
+ return
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (title, SZ_LINE, TY_CHAR)
+
+ # Initialize various daophot pointers.
+ psf = DP_PSF (dao)
+
+ # Initialize the contour plot parameters.
+ DP_CCEILING (psf) = 0.0
+ DP_CFLOOR (psf) = 0.0
+
+ # Define the hibad parameter.
+ hibad = DP_MAXGDATA(dao)
+ if (IS_INDEFR(hibad))
+ hibad = MAX_REAL
+
+ # Create the plot title.
+ call dp_ltov (im, DP_CUR_PSFX(psf), DP_CUR_PSFY(psf), wx, wy, 1)
+ call sprintf (Memc[title], SZ_LINE, "Star: %d X: %g Y: %g Mag: %g\n")
+ call pargi (DP_CUR_PSFID(psf))
+ call pargr (wx)
+ call pargr (wy)
+ call pargr (DP_CUR_PSFMAG(psf))
+
+ # Initialize plot.
+ if (DP_PLOTTYPE(psf) == PSF_MESHPLOT)
+ call dp_surfpsf (dao, subrast, ncols, nlines, Memc[title], gd)
+ else if (DP_PLOTTYPE(psf) == PSF_CONTOURPLOT)
+ call dp_contpsf (dao, subrast, ncols, nlines, Memc[title], gd)
+ else if (DP_PLOTTYPE(psf) == PSF_RADIALPLOT)
+ call dp_radpsf (dao, subrast, ncols, nlines, x1, y1, Memc[title],
+ gd)
+
+ if (DP_CUR_PSFMAX(psf) > hibad)
+ call printf ("Warning: Star is probably saturated\n")
+ do_replot = false
+
+ while (clgcur ("gcommands", wx, wy, wcs, key, Memc[cmd],
+ SZ_LINE) != EOF) {
+
+ switch (key) {
+
+ # Print the help page
+ case '?':
+ if (gd == NULL)
+ call pagefile (HELPFILE, "")
+ else
+ call gpagefile (gd, HELPFILE, "")
+
+ # Print out the photometry for the star.
+ case 'p':
+ call printf ("Star: %d Mag: %7.2f Coords: %7.2f %7.2f\n")
+ call pargi (DP_CUR_PSFID(psf))
+ call pargr (DP_CUR_PSFMAG(psf))
+ call pargr (DP_CUR_PSFX(psf))
+ call pargr (DP_CUR_PSFY(psf))
+
+ # Print out the plot parameters.
+ case 't':
+ if (DP_PLOTTYPE(psf) == PSF_MESHPLOT) {
+ call printf ("Surface plot: angv = %6.1f angh = %6.1f ")
+ call pargr (DP_MANGV(psf))
+ call pargr (DP_MANGH(psf))
+ call printf (" Minimum: %7.1f Maximum: %7.1f\n")
+ call pargr (DP_CUR_PSFMIN(psf))
+ call pargr (DP_CUR_PSFMAX(psf))
+ } else if (DP_PLOTTYPE(psf) == PSF_CONTOURPLOT) {
+ call printf ("Contour plot: floor = %6.1f ceil = %6.1f ")
+ call pargr (DP_CFLOOR(psf))
+ call pargr (DP_CCEILING(psf))
+ call printf (" Minimum: %7.1f Maximum: %7.1f\n")
+ call pargr (DP_CUR_PSFMIN(psf))
+ call pargr (DP_CUR_PSFMAX(psf))
+ } else if (DP_PLOTTYPE(psf) == PSF_RADIALPLOT) {
+ call printf (
+ "Profile plot: Minimum: %7.1f Maximum: %7.1f\n")
+ call pargr (DP_CUR_PSFMIN(psf))
+ call pargr (DP_CUR_PSFMAX(psf))
+ } else
+ call printf ("Unknown plot type.\n")
+
+ # Accept star and quit cursor loop.
+ case 'a':
+ star_ok = true
+ break
+
+ # Star rejected
+ case 'd':
+ star_ok = false
+ break
+
+ # Increase vertical viewing angle of mesh plot by 15 degrees.
+ case 'n':
+ if (DP_PLOTTYPE(psf) == PSF_MESHPLOT) {
+ DP_MANGV (psf) = DP_MANGV (psf) + 15.
+ do_replot = true
+ } else
+ call printf ("This key only active for mesh plots.\n")
+
+ # Decrease vertical viewing angle of mesh plot by 15 degrees.
+ case 's':
+ if (DP_PLOTTYPE(psf) == PSF_MESHPLOT) {
+ DP_MANGV (psf) = DP_MANGV (psf) - 15.
+ do_replot = true
+ } else
+ call printf ("This key only active for mesh plots.\n")
+
+ # Decrease horizontal viewing angle of mesh plot by 15 degrees.
+ case 'w':
+ if (DP_PLOTTYPE(psf) == PSF_MESHPLOT) {
+ DP_MANGH (psf) = DP_MANGH (psf) - 15.
+ do_replot = true
+ } else
+ call printf ("This key only active for mesh plots.\n")
+
+ # Increase horizontal viewing angle of mesh plot by 15 degrees.
+ case 'e':
+ if (DP_PLOTTYPE(psf) == PSF_MESHPLOT) {
+ DP_MANGH (psf) = DP_MANGH (psf) + 15.
+ do_replot = true
+ } else
+ call printf ("This key only active for mesh plots.\n")
+
+ # Plot the default mesh plot.
+ case 'm':
+ DP_PLOTTYPE(psf) = PSF_MESHPLOT
+ DP_MANGV (psf) = 30.
+ DP_MANGH (psf) = -30.
+ DP_MFLOOR(psf) = 0.0
+ DP_MCEILING(psf) = 0.0
+ do_replot = true
+
+ # Plot the default contour plots.
+ case 'c':
+ DP_PLOTTYPE(psf) = PSF_CONTOURPLOT
+ DP_CFLOOR(psf) = 0.0
+ DP_CCEILING(psf) = 0.0
+ do_replot = true
+
+ # Plot the radial profile plots.
+ case 'r':
+ DP_PLOTTYPE(psf) = PSF_RADIALPLOT
+ do_replot = true
+
+ # Command mode.
+ case ':':
+ for (ip=1; IS_WHITE (Memc[cmd+ip-1]); ip=ip+1)
+ ;
+
+ switch (Memc[cmd+ip-1]) {
+
+ # Set surface plot and angles
+ case 'm':
+ DP_PLOTTYPE(psf) = PSF_MESHPLOT
+ ip = ip + 1
+ if (ctor (Memc[cmd], ip, DP_MANGV(psf)) <= 0)
+ DP_MANGV(psf) = 30.
+ if (ctor (Memc[cmd], ip, DP_MANGH(psf)) <= 0)
+ DP_MANGH(psf) = -30.
+ do_replot = true
+
+ case 'c':
+ # Set surface contour and levels
+ DP_PLOTTYPE(psf) = PSF_CONTOURPLOT
+ ip = ip + 1
+ if (ctor (Memc[cmd], ip, DP_CFLOOR(psf)) <= 0)
+ DP_CFLOOR(psf) = 0.0
+ if (ctor (Memc[cmd], ip, DP_CCEILING(psf)) <= 0)
+ DP_CCEILING(psf) = 0.0
+ do_replot = true
+
+ case 'r':
+ # PLot radial profile.
+ DP_PLOTTYPE(psf) = PSF_RADIALPLOT
+ do_replot = true
+
+ # Set vertical angle
+ case 'v':
+ ip = ip + 1
+ if (ctor (Memc[cmd], ip, rval) <= 0) {
+ call printf (
+ "Surface plot vertical viewing angle: %g\n")
+ call pargr (DP_MANGV(psf))
+ } else {
+ DP_MANGV(psf) = rval
+ if (DP_PLOTTYPE(psf) == PSF_MESHPLOT)
+ do_replot = true
+ }
+
+ # Set horizontal angle
+ case 'h':
+ ip = ip + 1
+ if (ctor (Memc[cmd], ip, rval) <= 0) {
+ call printf (
+ "Surface plot horizontal viewing angle: %g\n")
+ call pargr (DP_MANGH(psf))
+ } else {
+ DP_MANGH(psf) = rval
+ if (DP_PLOTTYPE(psf) == PSF_MESHPLOT)
+ do_replot = true
+ }
+
+ # Set the floor value.
+ case 'l':
+ ip = ip + 1
+ if (ctor (Memc[cmd], ip, rval) <= 0) {
+ call printf (
+ "Contour plot floor value: %g\n")
+ call pargr (DP_CFLOOR(psf))
+ } else {
+ DP_CFLOOR(psf) = rval
+ if (DP_PLOTTYPE(psf) == PSF_CONTOURPLOT)
+ do_replot = true
+ }
+
+ # Set the ceiling value.
+ case 'u':
+ ip = ip + 1
+ if (ctor (Memc[cmd], ip, rval) <= 0) {
+ call printf (
+ "Contour plot ceiling value: %g\n")
+ call pargr (DP_CCEILING(psf))
+ } else {
+ DP_CCEILING(psf) = rval
+ if (DP_PLOTTYPE(psf) == PSF_CONTOURPLOT)
+ do_replot = true
+ }
+
+ default:
+ call printf ("Unknown keystroke or cursor command.\007\n")
+ }
+
+ default:
+ call printf ("Unknown keystroke or cursor command.\007\n")
+ }
+
+ # Replot the data.
+ if (do_replot) {
+ if (DP_PLOTTYPE(psf) == PSF_MESHPLOT)
+ call dp_surfpsf (dao, subrast, ncols, nlines, Memc[title],
+ gd)
+ else if (DP_PLOTTYPE(psf) == PSF_CONTOURPLOT)
+ call dp_contpsf (dao, subrast, ncols, nlines, Memc[title],
+ gd)
+ else if (DP_PLOTTYPE(psf) == PSF_RADIALPLOT)
+ call dp_radpsf (dao, subrast, ncols, nlines, x1, y1,
+ Memc[title], gd)
+ do_replot = false
+ }
+ }
+
+ call gdeactivate (gd, 0)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/psf/dpspstars.x b/noao/digiphot/daophot/psf/dpspstars.x
new file mode 100644
index 00000000..69b14933
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dpspstars.x
@@ -0,0 +1,194 @@
+include <mach.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/psfdef.h"
+
+define NCOLUMN 5
+
+# DP_GPSTARS -- Select the psf stars.
+
+procedure dp_gpstars (dao, im, tp_in, tp_out, text_file, maxnpsf, gd, mgd, id,
+ mkstars, interactive, use_cmdfile)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+int tp_in # the input file descriptor
+int tp_out # the output file descriptor
+bool text_file # text or table file
+int maxnpsf # the maximum number of psf stars
+pointer gd # pointer to the graphics stream
+pointer mgd # pointer to the plot metacode file
+pointer id # pointer to the image display stream
+bool mkstars # mark the accepted and deleted stars
+bool interactive # interactive mode
+bool use_cmdfile # cursor command file mode
+
+int ier, npsf
+pointer apsel, sp, ocolpoint, index
+real radius
+int dp_pfstars(), dp_ipfstars()
+
+begin
+ # Get some daophot pointers.
+ apsel = DP_APSEL(dao)
+
+ # Define the radius for determining proximity.
+ radius = DP_PSFRAD(dao) + DP_FITRAD(dao) + 2.0
+
+ # Allocate some working memory.
+ call smark (sp)
+ call salloc (ocolpoint, NCOLUMN, TY_POINTER)
+ call salloc (index, DP_APNUM(apsel), TY_INT)
+
+ # Initialize the output file.
+ if (text_file) {
+ call seek (tp_in, BOF)
+ call dp_apheader (tp_in, tp_out)
+ call dp_xpselpars (tp_out, DP_INIMAGE(dao), maxnpsf, DP_SCALE(dao),
+ DP_SPSFRAD(dao), DP_SFITRAD(dao))
+ call dp_xpbanner (tp_out)
+ } else {
+ call dp_tpdefcol (tp_out, Memi[ocolpoint])
+ call tbhcal (tp_in, tp_out)
+ call dp_tpselpars (tp_out, DP_INIMAGE(dao), maxnpsf, DP_SCALE(dao),
+ DP_SPSFRAD(dao), DP_SFITRAD(dao))
+ }
+
+ # Change all the INDEFS to a large negative number.
+ call dp_chindef (Memr[DP_APMAG(apsel)], Memr[DP_APMAG(apsel)],
+ DP_APNUM(apsel), -MAX_REAL)
+
+ # Sort the stars.
+ call quick (Memr[DP_APMAG(apsel)], DP_APNUM(apsel), Memi[index], ier)
+ call dp_irectify (Memi[DP_APID(apsel)], Memi[index], DP_APNUM(apsel))
+ call dp_rectify (Memr[DP_APXCEN(apsel)], Memi[index], DP_APNUM(apsel))
+ call dp_rectify (Memr[DP_APYCEN(apsel)], Memi[index], DP_APNUM(apsel))
+ call dp_rectify (Memr[DP_APMSKY(apsel)], Memi[index], DP_APNUM(apsel))
+
+ # Select the stars and write them to the output file.
+ if (use_cmdfile)
+ npsf = dp_ipfstars (dao, im, maxnpsf, -MAX_REAL, radius, gd,
+ mgd, id, mkstars, false, false)
+ else if (interactive)
+ npsf = dp_ipfstars (dao, im, maxnpsf, -MAX_REAL, radius, gd,
+ mgd, id, mkstars, true, true)
+ else
+ npsf = dp_pfstars (dao, im, Memi[DP_APID(apsel)],
+ Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[DP_APMAG(apsel)], Memr[DP_APMSKY(apsel)],
+ DP_APNUM(apsel), maxnpsf, -MAX_REAL, radius, mgd)
+
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("\nTotal of %d PSF stars selected\n")
+ call pargi (npsf)
+ }
+
+ # Write out the stars.
+ call dp_wout (dao, im, Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)], npsf)
+ call dp_wpstars (tp_out, Memi[ocolpoint], text_file,
+ Memi[DP_APID(apsel)], Memr[DP_APXCEN(apsel)],
+ Memr[DP_APYCEN(apsel)], Memr[DP_APMAG(apsel)],
+ Memr[DP_APMSKY(apsel)], npsf)
+
+ # Free memory.
+ call sfree (sp)
+end
+
+
+# DP_CHINDEF -- Change all the INDEFS to a legal number which is a lower limit.
+
+procedure dp_chindef (a, b, npix, lolimit)
+
+real a[ARB] # the input array.
+real b[ARB] # the output array.
+int npix # number of points
+real lolimit # the lower limit
+
+int i
+
+begin
+ do i = 1, npix {
+ if (IS_INDEFR(a[i]))
+ b[i] = lolimit
+ else
+ b[i] = a[i]
+ }
+end
+
+
+# DP_PFSTARS -- Select the psf stars.
+
+int procedure dp_pfstars (dao, im, ids, xcen, ycen, mag, sky, nstar, maxnpsf,
+ lolimit, radius, mgd)
+
+pointer dao # pointer to the daophot structure
+pointer im # pointer to the input image
+int ids[ARB] # array of star ids
+real xcen[ARB] # array of x coordinates
+real ycen[ARB] # array of y coordinates
+real mag[ARB] # array of magnitudes
+real sky[ARB] # array of sky values
+int nstar # the number of stars
+int maxnpsf # the maximum number of psf stars
+real lolimit # lower data limit
+real radius # minimum separation
+pointer mgd # pointer to the plot metacode file
+
+bool omit
+int istar, jstar, npsf
+real radsq, dy2, dr2
+int dp_addstar()
+
+begin
+ # Initialize the list.
+ call dp_pseti (dao, PNUM, 0)
+
+ # Set the radius.
+ radsq = radius * radius
+
+ # Get the first star.
+ if ((mag[1] > lolimit) && (dp_addstar (dao, im, xcen[1], ycen[1],
+ INDEFR, ids[1], NULL, mgd, false)) == OK) {
+ npsf = 1
+ } else
+ npsf = 0
+
+ # Loop over the candidate psf stars.
+ do istar = 2, nstar {
+
+ # Test for the maximum number of psf stars.
+ if (npsf >= maxnpsf)
+ break
+
+ # Test that the candidate psf stars are not saturated and
+ # are sufficiently far from the edge of the frame.
+
+ if (mag[istar] <= lolimit)
+ next
+
+ # Text that there are no brighter stars with a distance squared
+ # of radsq.
+ omit = false
+ do jstar = 1, istar - 1 {
+ dy2 = abs (ycen[jstar] - ycen[istar])
+ if (dy2 >= radius)
+ next
+ dr2 = (xcen[jstar] - xcen[istar]) ** 2 + dy2 ** 2
+ if (dr2 >= radsq)
+ next
+ omit = true
+ break
+ }
+
+ if (omit)
+ next
+
+ if (dp_addstar (dao, im, xcen[istar], ycen[istar], INDEFR,
+ ids[istar], NULL, mgd, false) == ERR)
+ next
+ npsf = npsf + 1
+ }
+
+ return (npsf)
+end
diff --git a/noao/digiphot/daophot/psf/dpsubpsf.x b/noao/digiphot/daophot/psf/dpsubpsf.x
new file mode 100644
index 00000000..8f15867a
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dpsubpsf.x
@@ -0,0 +1,183 @@
+include <mach.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+include "../lib/psfdef.h"
+
+# DP_SUBPSF -- Add the star at the given position to the PSF if it exists and
+# passes the selection criteria.
+
+int procedure dp_subpsf (dao, im, x, y, idnum, gd, mgd, showplots)
+
+pointer dao # pointer to daophot structure
+pointer im # pointer to image
+real x, y # position of proposed PSF star
+int idnum # id number of desired star
+pointer gd # pointer to the graphics stream
+pointer mgd # pointer to the metacode descriptor
+bool showplots # show plots?
+
+real tx, ty
+pointer srim
+int x1, x2, y1, y2, starnum, saturated
+bool star_ok
+
+real dp_statr()
+pointer dp_psubrast()
+int dp_locstar(), dp_idstar(), dp_pstati(), dp_issat()
+
+begin
+ # Convert coordinates for display.
+ if (showplots)
+ call dp_ltov (im, x, y, tx, ty, 1)
+ else
+ call dp_wout (dao, im, x, y, tx, ty, 1)
+
+ # Check that the position of the star is within the image.
+ if (idnum == 0 && (x < 1.0 || x > real (IM_LEN(im,1)) || y < 1.0 || y >
+ real (IM_LEN(im,2)))) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("Star at %g,%g is outside the image\n")
+ call pargr (tx)
+ call pargr (ty)
+ }
+ return (ERR)
+ }
+
+ # Find the star in the aperture photometry list
+ if (idnum == 0)
+ starnum = dp_locstar (dao, im, x, y)
+ else
+ starnum = dp_idstar (dao, im, idnum)
+ if (starnum == 0) {
+ if (DP_VERBOSE(dao) == YES) {
+ if (idnum > 0) {
+ call printf ("Star %d not found in the photometry file\n")
+ call pargi (idnum)
+ } else {
+ call printf (
+ "Star at %g,%g not found in the photometry file\n")
+ call pargr (tx)
+ call pargr (ty)
+ }
+ }
+ return (ERR)
+ } else if (starnum < 0 || starnum > dp_pstati (dao, PNUM)) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("Star %d not found in the PSF star list\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+ return (ERR)
+ }
+
+ # Check to see if the star is saturated.
+ if (dp_issat (dao, starnum) == YES) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("Star %d is saturated\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+ return (ERR)
+ }
+
+ # Get the data subraster, check for saturation and bad pixels,
+ # and compute the min and max data values inside the subraster.
+ srim = dp_psubrast (dao, im, -MAX_REAL, MAX_REAL, x1, x2, y1, y2,
+ saturated)
+ if (srim == NULL) {
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("Star %d error reading data subraster\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+ return (ERR)
+ }
+
+ # Now let us do the subtraction.
+ call dp_spstar (dao, Memr[srim], (x2 - x1 + 1), (y2 - y1 + 1),
+ x1, y1, starnum, dp_statr (dao, PSFRAD) ** 2)
+
+ # Now let's look at the extracted subraster.
+ if (showplots) {
+ call dp_showpsf (dao, im, Memr[srim], (x2 - x1 + 1), (y2 - y1 + 1),
+ x1, y1, gd, star_ok)
+ } else
+ star_ok = true
+
+ if (star_ok) {
+ if (mgd != NULL)
+ call dp_plotpsf (dao, im, Memr[srim], (x2 - x1 + 1),
+ (y2 - y1 + 1), x1, y1, mgd)
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("PSF star %d saved by user\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+ call mfree (srim, TY_REAL)
+ return (ERR)
+ }
+
+ # Delete the star from the list by moving it to the position
+ # currently occupied by PNUM and moving everything else up.
+ call dp_pfreorder (dao, dp_pstati (dao, CUR_PSF),
+ dp_pstati (dao, PNUM))
+
+ # Decrement the list of psf stars.
+ call dp_pseti (dao, PNUM, dp_pstati (dao, PNUM) - 1)
+
+ # Print message.
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("Star %d has been deleted from the PSF star list\n")
+ call pargi (dp_pstati (dao, CUR_PSFID))
+ }
+
+ call mfree (srim, TY_REAL)
+ return (OK)
+end
+
+
+# DP_SPSTAR -- Subtract the fitted star from the data subraster.
+
+procedure dp_spstar (dao, data, nx, ny, x1, y1, starno, psfradsq)
+
+pointer dao # pointer to the daophot structure
+real data[nx,ARB] # the data subraster
+int nx, ny # the dimensions of the data subraster
+int x1, y1 # the coordinates of the ll pixel
+int starno # the index of the star in question
+real psfradsq # the psf radius squared
+
+int i, j
+pointer psf, psffit
+real xstar, ystar, scale, deltax, deltay, dx, dy, dysq, rsq, svdx, svdy
+real dp_usepsf()
+
+begin
+ # Define some daophot pointers
+ psf = DP_PSF(dao)
+ psffit = DP_PSFFIT(dao)
+
+ # Get the star position and scale factor.
+ xstar = Memr[DP_PXCEN(psf)+starno-1]
+ ystar = Memr[DP_PYCEN(psf)+starno-1]
+ deltax = (xstar - 1.0) / DP_PSFX(psffit) - 1.0
+ deltay = (ystar - 1.0) / DP_PSFY(psffit) - 1.0
+ xstar = xstar - x1 + 1
+ ystar = ystar - y1 + 1
+ scale = Memr[DP_PH(psf)+starno-1] / Memr[DP_PH(psf)]
+
+ do j = 1, ny {
+ dy = real (j) - ystar
+ dysq = dy ** 2
+ do i = 1, nx {
+ dx = real (i) - xstar
+ rsq = dx ** 2 + dysq
+ if (rsq >= psfradsq)
+ next
+ data[i,j] = data[i,j] - scale *
+ dp_usepsf (DP_PSFUNCTION(psffit), dx, dy,
+ DP_PSFHEIGHT(psffit), Memr[DP_PSFPARS(psffit)],
+ Memr[DP_POLDLUT(psf)], DP_PSFSIZE(psffit),
+ DP_NVLTABLE(psffit), DP_NFEXTABLE(psffit),
+ deltax, deltay, svdx, svdy)
+ }
+ }
+
+ call alimr (data, nx * ny, DP_CUR_PSFMIN(psf), DP_CUR_PSFMAX(psf))
+end
diff --git a/noao/digiphot/daophot/psf/dpsurfpsf.x b/noao/digiphot/daophot/psf/dpsurfpsf.x
new file mode 100644
index 00000000..de4e9d6e
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dpsurfpsf.x
@@ -0,0 +1,437 @@
+include <fset.h>
+include <mach.h>
+include <error.h>
+include <gset.h>
+include <config.h>
+include <xwhen.h>
+include "../lib/daophotdef.h"
+include "../lib/psfdef.h"
+
+define DUMMY 6
+
+# DP_SURFPSF -- Draw a perspective view of a subraster with a given altitude
+# and azimuth of the viewing angle. Floor and ceiling constraints may be
+# applied to the data before plotting.
+
+procedure dp_surfpsf (dao, subras, ncols, nlines, title, gd)
+
+pointer dao # pointer to DAOPHOT structure
+real subras[ncols,nlines] # pointer to subraster
+int ncols, nlines # dimensions of subraster
+char title[ARB] # title string
+pointer gd # pointer to graphics stream
+
+char sysidstr[SZ_LINE]
+int first, wkid, epa, status, old_onint, tsujmp[LEN_JUMPBUF]
+pointer sp, temp, work, psf
+real angh, angv, imcols, imlines, floor, ceiling, vpx1, vpx2, vpy1, vpy2
+
+extern dp_sonint()
+common /tsucom/ tsujmp
+common /noaovp/ vpx1, vpx2, vpy1, vpy2
+common /frstfg/ first
+
+begin
+ # Get the psf fitting substructure pointer.
+ psf = DP_PSF(dao)
+
+ # Initialize surface common blocks before changing any parameters.
+ first = 1
+ call srfabd ()
+
+ # Set local variables.
+ angh = DP_MANGH (psf)
+ angv = DP_MANGV (psf)
+ floor = DP_MFLOOR (psf)
+ ceiling = DP_MCEILING (psf)
+ floor = min (floor, ceiling)
+ ceiling = max (floor, ceiling)
+
+ # Allow room for axes and labels.
+ vpx1 = 0.10
+ vpx2 = 0.90
+ vpy1 = 0.10
+ vpy2 = 0.90
+
+ # Make a copy of the subraster so we can subtract the zero level.
+ imcols = real (ncols)
+ imlines = real (nlines)
+ call smark (sp)
+ call salloc (temp, ncols * nlines, TY_REAL)
+ call amovr (subras, Memr[temp], nlines * ncols)
+
+ # Allocate the working storage needed by EZSRFC.
+ call malloc (work, 2 * (2 * ncols * nlines + ncols + nlines), TY_REAL)
+
+ # Take off floor and ceiling if enabled (nonzero).
+ call dp_slimits (Memr[temp], ncols, nlines, floor, ceiling)
+
+ # Set up the titles and the viewport.
+ call gopks (STDERR)
+ wkid = 1
+ call gclear (gd)
+ call gopwk (wkid, DUMMY, gd)
+ call gacwk (wkid)
+ call gtext (gd, 0.5, .96, title, "s=0.8;f=b;h=c")
+ call sysid (sysidstr, SZ_LINE)
+ call gtext (gd, 0.5, .04, sysidstr, "h=c;v=b;s=.5")
+ call set (vpx1, vpx2, vpy1, vpy2, 1.0, 1024., 1.0, 1024., 1)
+
+ # Install interrupt exception handler.
+ call zlocpr (dp_sonint, epa)
+ call xwhen (X_INT, epa, old_onint)
+
+ # Plot the surface.
+ call zsvjmp (tsujmp, status)
+ if (status == OK)
+ call ezsrfc (Memr[temp], ncols, nlines, angh, angv, Memr[work])
+ else {
+ call gcancel (gd)
+ call fseti (STDOUT, F_CANCEL, OK)
+ }
+
+ # Draw the perimeter.
+ call gswind (gd, 1.0, imcols, 1.0, imlines)
+ call gseti (gd, G_CLIP, NO)
+ call dp_sperimeter (gd, Memr[temp], ncols, nlines, angh, angv)
+
+ # Clean up.
+ call gdawk (wkid)
+ call gclks ()
+ call mfree (work, TY_REAL)
+ call sfree (sp)
+end
+
+
+# DP_SONINT -- Interrupt handler for the task surface. Branches back to ZSVJMP
+# in the main routine to permit shutdown without an error message.
+
+procedure dp_sonint (vex, next_handler)
+
+int vex # virtual exception
+int next_handler # not used
+
+int tsujmp[LEN_JUMPBUF]
+common /tsucom/ tsujmp
+
+begin
+ call xer_reset()
+ call zdojmp (tsujmp, vex)
+end
+
+
+# DP_SLIMITS -- Apply the floor and ceiling constraints to the subraster.
+# If either value is exactly zero, it is not applied.
+
+procedure dp_slimits (ras, m, n, floor, ceiling)
+
+real ras[m,n]
+int m, n
+real floor, ceiling
+int i
+
+begin
+ do i = 1, n {
+ if (floor != 0)
+ call amaxkr (ras[1,i], floor, ras[1,i], m)
+ if (ceiling != 0)
+ call aminkr (ras[1,i], ceiling, ras[1,i], m)
+ }
+end
+
+
+define SZ_TLABEL 10
+
+# DP_SPERIMETER -- draw and label axes around the surface plot.
+
+procedure dp_sperimeter (gp, z, ncols, nlines, angh, angv)
+
+pointer gp # Graphics pointer
+int ncols # Number of image columns
+int nlines # Number of image lines
+real z[ncols, nlines] # Array of intensity values
+real angh # Angle of horizontal inclination
+real angv # Angle of vertical inclination
+
+pointer sp, x_val, y_val, kvec
+char tlabel[SZ_TLABEL]
+real xmin, ymin, delta, fact1, flo, hi, xcen, ycen
+real x1_perim, x2_perim, y1_perim, y2_perim, z1, z2
+real wc1, wc2, wl1, wl2, del
+int i, j
+int itoc()
+data fact1 /2.0/
+real vpx1, vpx2, vpy1, vpy2
+common /noaovp/ vpx1, vpx2, vpy1, vpy2
+
+begin
+ call smark (sp)
+ call salloc (x_val, ncols + 2, TY_REAL)
+ call salloc (y_val, nlines + 2, TY_REAL)
+ call salloc (kvec, max (ncols, nlines) + 2, TY_REAL)
+
+ # Get window coordinates set up in calling procedure.
+ call ggwind (gp, wc1, wc2, wl1, wl2)
+
+ # Set up window, viewport for output. The coordinates returned
+ # from trn32s are in the range [1-1024].
+ call set (vpx1, vpx2, vpy1, vpy2, 1.0, 1024., 1.0, 1024., 1)
+
+ # Find range of z for determining perspective.
+ flo = MAX_REAL
+ hi = -flo
+ do j = 1, nlines {
+ call alimr (z[1,j], ncols, z1, z2)
+ flo = min (flo, z1)
+ hi = max (hi, z2)
+ }
+
+ # Set up linear endpoints and spacing as used in surface.
+
+ delta = (hi-flo) / (max (ncols,nlines) -1.) * fact1
+ xmin = -(real (ncols/2) * delta + real (mod (ncols+1, 2)) * delta)
+ ymin = -(real (nlines/2) * delta + real (mod (nlines+1, 2)) * delta)
+ del = 2.0 * delta
+
+ # The perimeter is separated from the surface plot by the
+ # width of delta.
+
+ x1_perim = xmin - delta
+ y1_perim = ymin - delta
+ x2_perim = xmin + (real (ncols) * delta)
+ y2_perim = ymin + (real (nlines) * delta)
+
+ # Set up linear arrays over full perimeter range
+ do i = 1, ncols + 2
+ Memr[x_val+i-1] = x1_perim + (i-1) * delta
+ do i = 1, nlines + 2
+ Memr[y_val+i-1] = y1_perim + (i-1) * delta
+
+ # Draw and label axes and tick marks.
+ # It is important that frame has not been called after calling srface.
+ # First to draw the perimeter. Which axes get drawn depends on the
+ # values of angh and angv. Get angles in the range [-180, 180].
+
+ if (angh > 180.)
+ angh = angh - 360.
+ else if (angh < -180.)
+ angh = angh + 360.
+
+ if (angv > 180.)
+ angv = angv - 360.
+ else if (angv < -180.)
+ angv = angv + 360.
+
+ # Calculate positions for the axis labels
+ xcen = 0.5 * (x1_perim + x2_perim)
+ ycen = 0.5 * (y1_perim + y2_perim)
+
+ if (angh >= 0) {
+ if (angv >= 0) {
+ # Case 1: xy rotation positive, looking down from above mid z.
+
+ # First draw x axis.
+ call amovkr (y2_perim, Memr[kvec], ncols + 2)
+ call dp_draw_axis (Memr[x_val+1], Memr[kvec], flo, ncols + 1)
+ call dp_label_axis (xcen, y2_perim+del, flo, "X-AXIS", -1, -2)
+ call dp_draw_ticksx (Memr[x_val+1], y2_perim, y2_perim+delta,
+ flo, ncols)
+ call dp_label_axis (xmin, y2_perim+del, flo, "1", -1, -2)
+ if (itoc (int (wc2), tlabel, SZ_TLABEL) <= 0)
+ tlabel[1] = EOS
+ call dp_label_axis (Memr[x_val+ncols], y2_perim+del, flo,
+ tlabel, -1, -2)
+
+ # Now draw y axis.
+ call amovkr (x2_perim, Memr[kvec], nlines + 2)
+ call dp_draw_axis (Memr[kvec], Memr[y_val+1], flo, nlines + 1)
+ call dp_label_axis (x2_perim+del, ycen, flo, "Y-AXIS", 2, -1)
+ call dp_draw_ticksy (x2_perim, x2_perim+delta, Memr[y_val+1],
+ flo, nlines)
+ call dp_label_axis (x2_perim+del, ymin, flo, "1", 2, -1)
+ if (itoc (int (wl2), tlabel, SZ_TLABEL) <= 0)
+ tlabel[1] = EOS
+ call dp_label_axis (x2_perim+del, Memr[y_val+nlines], flo,
+ tlabel, 2, -1)
+
+ } else {
+ # Case 2: xy rotation positive, looking up from below mid z.
+
+ # First draw x axis.
+ call amovkr (y1_perim, Memr[kvec], ncols + 2)
+ call dp_draw_axis (Memr[x_val], Memr[kvec], flo, ncols + 1)
+ call dp_label_axis (xcen, y1_perim-del, flo, "X-AXIS", -1, 2)
+ call dp_draw_ticksx (Memr[x_val+1], y1_perim, y1_perim-delta,
+ flo, ncols)
+ call dp_label_axis (xmin, y1_perim-del, flo, "1", -1, 2)
+ if (itoc (int (wc2), tlabel, SZ_TLABEL) <= 0)
+ tlabel[1] = EOS
+ call dp_label_axis (Memr[x_val+ncols], y1_perim-del, flo,
+ tlabel, -1, 2)
+
+ # Now draw y axis.
+ call amovkr (x1_perim, Memr[kvec], nlines + 2)
+ call dp_draw_axis (Memr[kvec], Memr[y_val], flo, nlines + 1)
+ call dp_label_axis (x1_perim-del, ycen, flo, "Y-AXIS", 2, 1)
+ call dp_draw_ticksy (x1_perim, x1_perim-delta, Memr[y_val+1],
+ flo, nlines)
+ call dp_label_axis (x1_perim-del, ymin, flo, "1", 2, 1)
+ if (itoc (int (wl2), tlabel, SZ_TLABEL) <= 0)
+ tlabel[1] = EOS
+ call dp_label_axis (x1_perim-del, Memr[y_val+nlines], flo,
+ tlabel, 2, 1)
+ }
+ }
+
+ if (angh < 0) {
+ if (angv > 0) {
+
+ # Case 3: xy rotation negative, looking down from above mid z
+ # (default). First draw x axis.
+ call amovkr (y1_perim, Memr[kvec], ncols + 2)
+ call dp_draw_axis (Memr[x_val+1], Memr[kvec], flo, ncols + 1)
+ call dp_label_axis (xcen, y1_perim-del, flo, "X-AXIS", 1, 2)
+ call dp_draw_ticksx (Memr[x_val+1], y1_perim, y1_perim-delta,
+ flo, ncols)
+ call dp_label_axis (xmin, y1_perim-del, flo, "1", 1, 2)
+ if (itoc (int (wc2), tlabel, SZ_TLABEL) <= 0)
+ tlabel[1] = EOS
+ call dp_label_axis (Memr[x_val+ncols], y1_perim-del, flo,
+ tlabel, 1, 2)
+
+ # Now draw y axis.
+ call amovkr (x2_perim, Memr[kvec], nlines + 2)
+ call dp_draw_axis (Memr[kvec], Memr[y_val], flo, nlines + 1)
+ call dp_label_axis (x2_perim+del, ycen, flo, "Y-AXIS", 2, -1)
+ call dp_draw_ticksy (x2_perim, x2_perim+delta, Memr[y_val+1],
+ flo, nlines)
+ call dp_label_axis (x2_perim+del, ymin, flo, "1", 2, -1)
+ if (itoc (int (wl2), tlabel, SZ_TLABEL) <= 0)
+ tlabel[1] = EOS
+ call dp_label_axis (x2_perim+del, Memr[y_val+nlines], flo,
+ tlabel, 2, -1)
+ } else {
+
+ # Case 4: xy rotation negative, looking up from below mid z.
+ # First draw x axis.
+ call amovkr (y2_perim, Memr[kvec], ncols + 2)
+ call dp_draw_axis (Memr[x_val], Memr[kvec], flo, ncols + 1)
+ call dp_label_axis (xcen, y2_perim+del, flo, "X-AXIS", 1, -2)
+ call dp_draw_ticksx (Memr[x_val+1], y2_perim, y2_perim+delta,
+ flo, ncols)
+ call dp_label_axis (xmin, y2_perim+del, flo, "1", 1, -2)
+ if (itoc (int (wc2), tlabel, SZ_TLABEL) <= 0)
+ tlabel[1] = EOS
+ call dp_label_axis (Memr[x_val+ncols], y2_perim+del, flo,
+ tlabel, 1, -2)
+
+ # Now draw y axis.
+ call amovkr (x1_perim, Memr[kvec], nlines + 2)
+ call dp_draw_axis (Memr[kvec], Memr[y_val+1], flo, nlines + 1)
+ call dp_label_axis (x1_perim-del, ycen, flo, "Y-AXIS", 2, 1)
+ call dp_draw_ticksy (x1_perim, x1_perim-delta, Memr[y_val+1],
+ flo, nlines)
+ call dp_label_axis (x1_perim-del, ymin, flo, "1", 2, 1)
+ if (itoc (int (wl2), tlabel, SZ_TLABEL) <= 0)
+ tlabel[1] = EOS
+ call dp_label_axis (x1_perim-del, Memr[y_val+nlines], flo,
+ tlabel, 2, 1)
+ }
+ }
+
+ # Flush plotit buffer before returning.
+ call plotit (0, 0, 2)
+ call sfree (sp)
+end
+
+
+# DP_DRAW_AXIS -- Draw the axes around the surface plot.
+
+procedure dp_draw_axis (xvals, yvals, zval, nvals)
+
+int nvals
+real xvals[nvals]
+real yvals[nvals]
+real zval
+pointer sp, xt, yt
+int i
+real dum
+
+begin
+ call smark (sp)
+ call salloc (xt, nvals, TY_REAL)
+ call salloc (yt, nvals, TY_REAL)
+
+ do i = 1, nvals
+ call trn32s (xvals[i], yvals[i], zval, Memr[xt+i-1], Memr[yt+i-1],
+ dum, 1)
+ call gpl (nvals, Memr[xt], Memr[yt])
+ call sfree (sp)
+end
+
+
+define CSIZE 24
+
+
+# DP_LABEL_AXIS -- Draw the axes labels.
+
+procedure dp_label_axis (xval, yval, zval, sppstr, path, up)
+
+real xval
+real yval
+real zval
+char sppstr[SZ_LINE]
+int path
+int up
+
+int nchars
+int strlen()
+% character*64 fstr
+
+begin
+ nchars = strlen (sppstr)
+% call f77pak (sppstr, fstr, 64)
+ call pwrzs (xval, yval, zval, fstr, nchars, CSIZE, path, up, 0)
+end
+
+
+# DP_DRAW_TICKS -- Draw the x tick marks.
+
+procedure dp_draw_ticksx (x, y1, y2, zval, nvals)
+
+int nvals
+real x[nvals]
+real y1, y2
+real zval
+
+int i
+real tkx[2], tky[2], dum
+
+begin
+ do i = 1, nvals {
+ call trn32s (x[i], y1, zval, tkx[1], tky[1], dum, 1)
+ call trn32s (x[i], y2, zval, tkx[2], tky[2], dum, 1)
+ call gpl (2, tkx[1], tky[1])
+ }
+end
+
+
+# DP_DRAW_TICKSY -- Draw the y tick marks.
+
+procedure dp_draw_ticksy (x1, x2, y, zval, nvals)
+
+int nvals
+real x1, x2
+real y[nvals]
+real zval
+
+int i
+real tkx[2], tky[2], dum
+
+begin
+ do i = 1, nvals {
+ call trn32s (x1, y[i], zval, tkx[1], tky[1], dum, 1)
+ call trn32s (x2, y[i], zval, tkx[2], tky[2], dum, 1)
+ call gpl (2, tkx[1], tky[1])
+ }
+end
diff --git a/noao/digiphot/daophot/psf/dpwritepsf.x b/noao/digiphot/daophot/psf/dpwritepsf.x
new file mode 100644
index 00000000..239e4faf
--- /dev/null
+++ b/noao/digiphot/daophot/psf/dpwritepsf.x
@@ -0,0 +1,270 @@
+include <time.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/psfdef.h"
+
+# DP_WRITEPSF -- Write out the PSF into an IRAF image.
+
+procedure dp_writepsf (dao, im, psfim)
+
+pointer dao # pointer to the daophot structure
+pointer im # the input image descriptor
+pointer psfim # pointer to the output psf image
+
+begin
+ # Check that the psfimage is open.
+ if (psfim == NULL)
+ return
+
+ # Write out the id and fitting parameters.
+ call dp_widpars (dao, psfim)
+
+ # Write out the psf function definition parameters.
+ call dp_wfuncpars (dao, psfim)
+
+ # Write out the list of PSF stars.
+ call dp_wstars (dao, im, psfim)
+
+ # Write out the lookup table.
+ call dp_wlt (dao, psfim)
+end
+
+
+# DP_WIDPARS -- Add the id and fitting parameters to the PSF image header
+
+procedure dp_widpars (dao, psfim)
+
+pointer dao # pointer to the daophot structure
+pointer psfim # the psf image descriptor
+
+pointer sp, outstr, date, time
+bool itob()
+int envfind()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+ call salloc (date, SZ_DATE, TY_CHAR)
+ call salloc (time, SZ_DATE, TY_CHAR)
+
+ # Record IRAF version, user, host, date, time, package and task.
+ if (envfind ("version", Memc[outstr], SZ_LINE) <= 0)
+ call strcpy ("IRAF", Memc[outstr], SZ_LINE)
+ call dp_rmwhite (Memc[outstr], Memc[outstr], SZ_LINE)
+ call imastr (psfim, "IRAF", Memc[outstr])
+ call gethost (Memc[outstr], SZ_LINE)
+ call imastr (psfim, "HOST", Memc[outstr])
+ if (envfind ("userid", Memc[outstr], SZ_LINE) <= 0)
+ Memc[outstr] = EOS
+ call imastr (psfim, "USER", Memc[outstr])
+ call dp_date (Memc[date], Memc[time], SZ_DATE)
+ call imastr (psfim, "DATE", Memc[date])
+ call imastr (psfim, "TIME", Memc[time])
+
+ # Write out the package, task, and input/output file names.
+ call imastr (psfim, "PACKAGE", "daophot")
+ call imastr (psfim, "TASK", "psf")
+ call dp_imroot (DP_INIMAGE(dao), Memc[outstr], SZ_LINE)
+ call imastr (psfim, "IMAGE", Memc[outstr])
+ call dp_froot (DP_INPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call imastr (psfim, "PHOTFILE", Memc[outstr])
+ call dp_froot (DP_COORDS(dao), Memc[outstr], SZ_LINE)
+ call imastr (psfim, "PSTFILE", Memc[outstr])
+ call dp_imroot (DP_PSFIMAGE(dao), Memc[outstr], SZ_LINE)
+ call imastr (psfim, "PSFIMAGE", Memc[outstr])
+ call dp_froot (DP_OUTREJFILE(dao), Memc[outstr], SZ_LINE)
+ call imastr (psfim, "OPSTFILE", Memc[outstr])
+ call dp_froot (DP_OUTPHOTFILE(dao), Memc[outstr], SZ_LINE)
+ call imastr (psfim, "GRPSFILE", Memc[outstr])
+
+ # Add information about fitting parameters.
+ call imaddr (psfim, "SCALE", DP_SCALE(dao))
+ call imaddr (psfim, "PSFRAD", DP_SPSFRAD (dao))
+ call imaddr (psfim, "FITRAD", DP_SFITRAD(dao))
+ call imaddr (psfim, "DATAMIN", DP_MINGDATA(dao))
+ call imaddr (psfim, "DATAMAX", DP_MAXGDATA(dao))
+ call imaddi (psfim, "NCLEAN", DP_NCLEAN(dao))
+ call imaddb (psfim, "USESAT", itob (DP_SATURATED(dao)))
+
+ # Define the image title.
+ call sprintf (IM_TITLE(psfim), SZ_IMTITLE, "PSF for image: %s")
+ call pargstr (DP_INIMAGE(dao))
+
+ call sfree (sp)
+end
+
+
+# DP_WFUNCPARS -- Write out the the parameters of the PSF function
+# to the PSF image.
+
+procedure dp_wfuncpars (dao, psfim)
+
+pointer dao # pointer to the daophot structure
+pointer psfim # image descriptor
+
+int i
+pointer sp, str, psffit
+bool itob()
+
+begin
+ psffit = DP_PSFFIT(dao)
+
+ call imastr (psfim, "FUNCTION", DP_FUNCTION(dao))
+ call imaddr (psfim, "PSFX", DP_PSFX(psffit))
+ call imaddr (psfim, "PSFY", DP_PSFY(psffit))
+ call imaddr (psfim, "PSFHEIGHT", DP_PSFHEIGHT(psffit))
+ call imaddr (psfim, "PSFMAG", DP_PSFMAG (psffit))
+
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ switch (DP_PSFUNCTION(psffit)) {
+ case FCTN_MOFFAT25:
+ call imaddi (psfim, "NPARS", DP_PSFNPARS(psffit)+1)
+ do i = 1, DP_PSFNPARS(psffit) {
+ call sprintf (Memc[str], SZ_FNAME, "PAR%d")
+ call pargi (i)
+ call imaddr (psfim, Memc[str], Memr[DP_PSFPARS(psffit)+i-1])
+ }
+ call sprintf (Memc[str], SZ_FNAME, "PAR%d")
+ call pargi (DP_PSFNPARS(psffit)+1)
+ call imaddr (psfim, Memc[str], 2.5)
+ case FCTN_MOFFAT15:
+ call imaddi (psfim, "NPARS", DP_PSFNPARS(psffit)+1)
+ do i = 1, DP_PSFNPARS(psffit) {
+ call sprintf (Memc[str], SZ_FNAME, "PAR%d")
+ call pargi (i)
+ call imaddr (psfim, Memc[str], Memr[DP_PSFPARS(psffit)+i-1])
+ }
+ call sprintf (Memc[str], SZ_FNAME, "PAR%d")
+ call pargi (DP_PSFNPARS(psffit)+1)
+ call imaddr (psfim, Memc[str], 1.5)
+ default:
+ call imaddi (psfim, "NPARS", DP_PSFNPARS(psffit))
+ do i = 1, DP_PSFNPARS(psffit) {
+ call sprintf (Memc[str], SZ_FNAME, "PAR%d")
+ call pargi (i)
+ call imaddr (psfim, Memc[str], Memr[DP_PSFPARS(psffit)+i-1])
+ }
+ }
+
+ call imaddi (psfim, "VARORDER", DP_VARORDER(dao))
+ call imaddb (psfim, "FEXPAND", itob (DP_FEXPAND(dao)))
+
+ call sfree (sp)
+end
+
+
+# DP_WSTARS -- Write out the PSF star list to the PSF image.
+
+procedure dp_wstars (dao, im, psfim)
+
+pointer dao # pointer to the daophot descriptor
+pointer im # the input image descriptor
+pointer psfim # the psfimage descriptor
+
+real tx, ty
+pointer apsel, psf, sp, str
+int i
+
+begin
+ apsel = DP_APSEL(dao)
+ psf = DP_PSF(dao)
+
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Write out the number of PSF stars.
+ call sprintf (Memc[str], SZ_FNAME, "NPSFSTAR")
+ call imaddi (psfim, Memc[str], DP_PNUM(psf))
+
+ # Write out the ids of all the PSF stars.
+ do i = 1, DP_PNUM(psf) {
+
+ call dp_wout (dao, im, Memr[DP_APXCEN(apsel)+i-1],
+ Memr[DP_APYCEN(apsel)+i-1], tx, ty, 1)
+ call sprintf (Memc[str], SZ_FNAME, "ID%d")
+ call pargi (i)
+ call imaddi (psfim, Memc[str], Memi[DP_APID(apsel)+i-1])
+
+ call sprintf (Memc[str], SZ_FNAME, "X%d")
+ call pargi (i)
+ call imaddr (psfim, Memc[str], tx)
+
+ call sprintf (Memc[str], SZ_FNAME, "Y%d")
+ call pargi (i)
+ call imaddr (psfim, Memc[str], ty)
+
+ call sprintf (Memc[str], SZ_FNAME, "MAG%d")
+ call pargi (i)
+ call imaddr (psfim, Memc[str], Memr[DP_APMAG(apsel)+i-1])
+ }
+
+ call sfree (sp)
+end
+
+
+# DP_WLT -- Write out the PSF lookup table to the output PSF image.
+
+procedure dp_wlt (dao, psfim)
+
+pointer dao # pointer to DAO Structure
+pointer psfim # image descriptor
+
+int nexp
+pointer psffit
+
+begin
+ psffit = DP_PSFFIT(dao)
+ nexp = DP_NVLTABLE(psffit) + DP_NFEXTABLE(psffit)
+
+ IM_PIXTYPE(psfim) = TY_REAL
+ if (nexp == 0) {
+ IM_NDIM(psfim) = 0
+ } else if (nexp == 1) {
+ IM_NDIM(psfim) = 2
+ IM_LEN(psfim,1) = DP_PSFSIZE(psffit)
+ IM_LEN(psfim,2) = DP_PSFSIZE(psffit)
+ } else {
+ IM_NDIM(psfim) = 3
+ IM_LEN(psfim,1) = DP_PSFSIZE(psffit)
+ IM_LEN(psfim,2) = DP_PSFSIZE(psffit)
+ IM_LEN(psfim,3) = nexp
+ }
+
+ if (nexp > 0)
+ call dp_wltim (psfim, Memr[DP_PSFLUT(psffit)], DP_PSFSIZE(psffit),
+ DP_PSFSIZE(psffit), nexp)
+end
+
+
+# DP_WLTIM -- Write the lookup tables into the image pixels.
+
+procedure dp_wltim (psfim, psflut, nxlut, nylut, nexp)
+
+pointer psfim # image descriptor
+real psflut[nexp,nxlut,ARB] # the psf lookup table
+int nxlut, nylut,nexp # the dimensions of the psf look-up table
+
+int i, j, k
+pointer sp, v, buf
+int impnlr()
+
+begin
+ call smark (sp)
+ call salloc (v, IM_MAXDIM, TY_LONG)
+
+ call amovkl (long(1), Meml[v], IM_MAXDIM)
+ do k = 1, nexp {
+ do j = 1, nylut {
+ if (impnlr (psfim, buf, Meml[v]) == EOF)
+ ;
+ do i = 1, nxlut
+ Memr[buf+i-1] = psflut[k,i,j]
+ }
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/psf/mkpkg b/noao/digiphot/daophot/psf/mkpkg
new file mode 100644
index 00000000..5dd38047
--- /dev/null
+++ b/noao/digiphot/daophot/psf/mkpkg
@@ -0,0 +1,70 @@
+# PSF task
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ dpaddstar.x <imhdr.h> <mach.h> \
+ ../lib/daophotdef.h ../lib/psfdef.h
+ dpcontpsf.x <error.h> <mach.h> \
+ <gset.h> <config.h> \
+ <xwhen.h> <fset.h> \
+ ../lib/daophotdef.h ../lib/psfdef.h
+ dpdelstar.x <imhdr.h> ../lib/daophotdef.h \
+ ../lib/psfdef.h <mach.h>
+ dpfitpsf.x <mach.h> <imhdr.h> \
+ ../lib/daophotdef.h ../lib/apseldef.h \
+ ../lib/psfdef.h ../lib/peakdef.h
+ dplocstar.x <mach.h> <imhdr.h> \
+ ../lib/daophotdef.h ../lib/apseldef.h \
+ ../lib/psfdef.h
+ dpispstars.x <fset.h> <ctype.h> \
+ <gset.h> ../lib/daophotdef.h \
+ ../lib/apseldef.h ../lib/psfdef.h
+ dppcolon.x ../lib/daophotdef.h ../lib/psfdef.h
+ dpqverify.x <fset.h>
+ dpmempsf.x ../lib/daophotdef.h ../lib/psfdef.h
+ dpmkpsf.x <imhdr.h> <ctype.h> \
+ <gset.h> ../lib/daophotdef.h \
+ ../lib/apseldef.h ../lib/psfdef.h
+ dppconfirm.x
+ dppsfutil.x ../lib/daophotdef.h ../lib/apseldef.h \
+ ../lib/psfdef.h
+ dpplotpsf.x ../lib/daophotdef.h ../lib/psfdef.h
+ dppset.x ../lib/daophotdef.h ../lib/psfdef.h
+ dppstat.x ../lib/daophotdef.h ../lib/psfdef.h
+ dppsubrast.x <mach.h> <imhdr.h> \
+ ../lib/daophotdef.h ../lib/psfdef.h
+ dpptconfirm.x
+ dppwrtgrp.x <time.h> <tbset.h> \
+ ../lib/daophotdef.h ../lib/apseldef.h \
+ ../lib/psfdef.h
+ dppwselmer.x <tbset.h> ../lib/apseldef.h
+ dpradpsf.x <gset.h> ../lib/daophotdef.h \
+ ../lib/psfdef.h
+ dprmpsf.x <fset.h> <imhdr.h> \
+ ../lib/daophotdef.h ../lib/psfdef.h
+ dprstars.x <gset.h> <tbset.h> \
+ ../lib/apseldef.h ../lib/psfdef.h
+ dpshowpsf.x <mach.h> <ctype.h> \
+ ../lib/daophotdef.h ../lib/psfdef.h
+ dpspstars.x <mach.h> ../lib/daophotdef.h \
+ ../lib/apseldef.h ../lib/psfdef.h
+ dpsubpsf.x <mach.h> <imhdr.h> \
+ ../lib/daophotdef.h ../lib/psfdef.h
+ dpsurfpsf.x <error.h> <mach.h> \
+ <gset.h> <config.h> \
+ <xwhen.h> <fset.h> \
+ ../lib/daophotdef.h ../lib/psfdef.h
+ dpwritepsf.x <time.h> <imhdr.h> \
+ ../lib/daophotdef.h ../lib/apseldef.h \
+ ../lib/psfdef.h
+ t_psf.x <fset.h> <gset.h> \
+ <imhdr.h> ../lib/daophotdef.h \
+ ../lib/apseldef.h ../lib/psfdef.h
+ t_pstselect.x <fset.h> <gset.h> \
+ <imhdr.h> ../lib/daophotdef.h \
+ ../lib/apseldef.h ../lib/psfdef.h
+ ;
diff --git a/noao/digiphot/daophot/psf/mkpsf.key b/noao/digiphot/daophot/psf/mkpsf.key
new file mode 100644
index 00000000..ed511025
--- /dev/null
+++ b/noao/digiphot/daophot/psf/mkpsf.key
@@ -0,0 +1,40 @@
+ Keystroke Commands
+
+? Print help
+p Print photometry for star nearest the cursor
+l List the current psf stars
+a Add star nearest cursor to psf star list
+f Fit the psf
+r Review the fit for all the psf stars
+s Subtract fitted psf from psf star nearest cursor
+d Delete psf star nearest cursor from psf star list
+w Write the psf to the psf image
+z Rebuild the psf from scratch
+q Quit task
+
+ Colon Commands
+
+:p [n] Print photometry for star n
+:a [n] Add star n to psf star list
+:d [n] Delete star n from psf star list
+:s [n] Subtract fitted psf from psf star n
+
+ Colon Parameter Editing Commands
+
+# Data dependent parameters which affect the psf computation
+
+:scale [value] Show/set the image scale (units / pixel)
+:fwhmpsf [value] Show/set the fwhm of psf (scale units)
+:datamin [value] Show/set the minimum good data value (counts)
+:datamax [value] Show/set the maximum good data value (counts)
+:matchrad [value] Show/set matching radius (scale units)
+
+# Psf computation parameters
+
+:psfimage [name,name] Show/set the psf image and groupfile
+:function [string] Show/set the analytic psf function
+:varorder [integer] Show/set order of psf function variability
+:nclean [integer] Show/set number of cleaning iterations
+:saturated [y/n] Show/set the use saturated star flag
+:psfrad [value] Show/set the psf radius (scale units)
+:fitrad [value] Show/set the fitting radius (scale units)
diff --git a/noao/digiphot/daophot/psf/mkpsflist.key b/noao/digiphot/daophot/psf/mkpsflist.key
new file mode 100644
index 00000000..0ed43c8a
--- /dev/null
+++ b/noao/digiphot/daophot/psf/mkpsflist.key
@@ -0,0 +1,15 @@
+ Keystroke Commands
+
+? Print help
+p Print photometry for star nearest the cursor
+l List the current psf stars
+n Select the next good candidate psf star from the list
+a Add star nearest cursor to psf star list
+d Delete psf star nearest cursor from psf star list
+q Quit task
+
+ Colon Commands
+
+:p [n] Print photometry for star n
+:a [n] Add star n to psf star list
+:d [n] Delete star n from psf star list
diff --git a/noao/digiphot/daophot/psf/showpsf.key b/noao/digiphot/daophot/psf/showpsf.key
new file mode 100644
index 00000000..7551477e
--- /dev/null
+++ b/noao/digiphot/daophot/psf/showpsf.key
@@ -0,0 +1,24 @@
+ Interactive Graphics Keystroke Commands
+
+? Print help
+p Print the photometry for this star
+t Print the plot parameters and data minimum and maximum
+a Accept star and proceed
+d Reject star and select another with image cursor
+m Plot the default mesh plot for this star
+n Increase vertical angle by 15 degrees (mesh plot only)
+s Decrease vertical angle by 15 degrees (mesh plot only)
+w Decrease horizontal angle by 15 degrees (mesh plot only)
+e Increase horizontal angle by 15 degrees (mesh plot only)
+c Plot the default contour plot for this star
+r Plot the radial profile for this star
+
+
+ Colon Graphics Commands
+
+:m [val] [val] Set the mesh plot vertical and horizontal viewing angles
+:v [val] Set the mesh plot vertical viewing angle
+:h [val] Set the mesh plot horizontal viewing angle
+:c [val] [val] Set the contour plot floor and ceiling levels
+:l [value] Set the contour plot floor level
+:u [value] Set the contour plot ceiling level
diff --git a/noao/digiphot/daophot/psf/t_psf.x b/noao/digiphot/daophot/psf/t_psf.x
new file mode 100644
index 00000000..b7444b3e
--- /dev/null
+++ b/noao/digiphot/daophot/psf/t_psf.x
@@ -0,0 +1,509 @@
+include <fset.h>
+include <imhdr.h>
+include <gset.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/psfdef.h"
+
+# T_PSF -- Generate a point spread function from one or more stars in the
+# image frame.
+
+procedure t_psf ()
+
+pointer image # the input image
+pointer photfile # input aperture photometry file
+pointer pstarfile # input psf star file
+pointer psfimage # output psf image
+pointer groupfile # output psf group file
+pointer opstfile # output psf star file
+pointer graphics # pointer to graphics device name
+pointer plotfile # pointer to plotfile name
+int cache # cache the input image pixels
+pointer display # pointer to display device name
+bool matchbyid # match psf stars by id or position
+bool interactive # the mode of task operation
+bool showplots # display plots of the psf stars
+pointer plottype # type of psf plot
+bool mkstars # mark deleted and accepted psf stars
+
+pointer sp, im, apd, psfim, dao, mgd, gd, id
+pointer outfname, curfile, str
+int imlist, limlist, alist, lalist, clist, lclist, pimlist, lpimlist
+int olist, lolist, oclist, loclist, up, verify, update, wcs
+int root, min_lenuserarea, pltype, pfd, pst, psfgr, opst
+int req_size, old_size, buf_size, memstat
+bool ap_text, pst_text
+
+pointer immap(), tbtopn(), gopen()
+int fnldir(), strlen(), strncmp(), btoi(), envfind(), ctoi(), clgwrd()
+int strdic(), open(), access(), fstati(), dp_stati(), dp_pstati()
+int imtopen(), imtlen(), imtgetim(), fntopnb(), fntlenb(), fntgfnb()
+int sizeof(), dp_memstat()
+bool streq(), clgetb(), itob(), dp_updatepsf()
+errchk gopen
+
+begin
+ # Set the standard output to flush on newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get some working memory.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (photfile, SZ_FNAME, TY_CHAR)
+ call salloc (pstarfile, SZ_FNAME, TY_CHAR)
+ call salloc (psfimage, SZ_FNAME, TY_CHAR)
+ call salloc (groupfile, SZ_FNAME, TY_CHAR)
+ call salloc (opstfile, SZ_FNAME, TY_CHAR)
+ call salloc (plottype, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+ call salloc (display, SZ_FNAME, TY_CHAR)
+ call salloc (plotfile, SZ_FNAME, TY_CHAR)
+ call salloc (curfile, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Get the various task parameters.
+ call clgstr ("image", Memc[image], SZ_FNAME)
+ call clgstr ("photfile", Memc[photfile], SZ_FNAME)
+ call clgstr ("pstfile", Memc[pstarfile], SZ_FNAME)
+ call clgstr ("psfimage", Memc[psfimage], SZ_FNAME)
+ call clgstr ("opstfile", Memc[opstfile], SZ_FNAME)
+ call clgstr ("groupfile", Memc[groupfile], SZ_FNAME)
+ cache = btoi (clgetb ("cache"))
+ verify = btoi (clgetb ("verify"))
+ update = btoi (clgetb ("update"))
+
+ # Get the lists.
+ imlist = imtopen (Memc[image])
+ limlist = imtlen (imlist)
+ alist = fntopnb (Memc[photfile], NO)
+ lalist = fntlenb (alist)
+ clist = fntopnb (Memc[pstarfile], NO)
+ lclist = fntlenb (clist)
+ pimlist = imtopen (Memc[psfimage])
+ lpimlist = imtlen (pimlist)
+ olist = fntopnb (Memc[groupfile], NO)
+ lolist = fntlenb (olist)
+ oclist = fntopnb (Memc[opstfile], NO)
+ loclist = fntlenb (oclist)
+
+ # Test that the lengths of the photometry file, psf image, and
+ # output file lists are the same as the length of the input image
+ # list.
+
+ # Compare the image and photometry file list lengths.
+ if ((limlist != lalist) && (strncmp (Memc[photfile],
+ DEF_DEFNAME, DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call fntclsb (clist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (oclist)
+ call sfree (sp)
+ call error (0,
+ "Incompatable image and photometry file list lengths")
+ }
+
+ # Compare the image and psf star list lengths.
+ if ((lclist != 0) && (limlist != lclist) && (strncmp (Memc[pstarfile],
+ DEF_DEFNAME, DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call fntclsb (clist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (oclist)
+ call sfree (sp)
+ call error (0,
+ "Incompatable image and psf star file list lengths")
+ }
+
+ # Compare the image and psf image list lengths.
+ if ((limlist != lpimlist) && (strncmp (Memc[psfimage],
+ DEF_DEFNAME, DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call fntclsb (clist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (oclist)
+ call sfree (sp)
+ call error (0,
+ "Incompatable image and psf file list lengths")
+ }
+
+ # Compare the image and groupfile list lengths.
+ if ((limlist != lolist) && (strncmp (Memc[groupfile],
+ DEF_DEFNAME, DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call fntclsb (clist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (oclist)
+ call sfree (sp)
+ call error (0,
+ "Incompatable image and group file list lengths")
+ }
+
+ # Compare the image and output pstfile list lengths.
+ if ((limlist != loclist) && (strncmp (Memc[opstfile],
+ DEF_DEFNAME, DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call fntclsb (clist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (oclist)
+ call sfree (sp)
+ call error (0,
+ "Incompatable image and output psf file list lengths")
+ }
+
+ # Initialize DAOPHOT main structure, get pset parameters.
+ call dp_gppars (dao)
+
+ # Verify the critical parameters and update if appropriate.
+ if (verify == YES) {
+ call dp_pconfirm (dao)
+ if (update == YES)
+ call dp_pppars (dao)
+ }
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_FNAME, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_FNAME, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSOUT, wcs)
+
+ # Initialize the photometry structure.
+ call dp_apselsetup (dao)
+
+ # Initialize the PSF structure.
+ call dp_fitsetup (dao)
+
+ # Intialize the PSF fitting structure.
+ call dp_psfsetup (dao)
+
+ # Matching algorithm for stars in the psf star list.
+ matchbyid = clgetb ("matchbyid")
+
+ # Is the task interactive or not?
+ call clgstr ("icommands.p_filename", Memc[curfile], SZ_FNAME)
+ if (Memc[curfile] == EOS)
+ interactive = clgetb ("interactive")
+ else
+ interactive = false
+
+ # Get the graphics, display and plot file devices.
+ call clgstr ("graphics", Memc[graphics], SZ_FNAME)
+ call clgstr ("display", Memc[display], SZ_FNAME)
+ call clgstr ("plottype", Memc[plottype], SZ_FNAME)
+ call clgstr ("plotfile", Memc[plotfile], SZ_FNAME)
+
+ # Open graphics and display devices if appropriate.
+ if (interactive) {
+ call dp_seti (dao, VERBOSE, YES)
+ showplots = clgetb ("showplots")
+ if (Memc[graphics] == EOS)
+ gd = NULL
+ else {
+ iferr {
+ gd = gopen (Memc[graphics], APPEND+AW_DEFER, STDGRAPH)
+ } then {
+ call eprintf (
+ "Warning: Error opening graphics device. \n")
+ gd = NULL
+ }
+ }
+ if (Memc[display] == EOS)
+ id = NULL
+ else if (streq (Memc[graphics], Memc[display]))
+ id = gd
+ else {
+ iferr {
+ id = gopen (Memc[display], APPEND, STDIMAGE)
+ } then {
+ call eprintf (
+ "Warning: Graphics overlay not available for display device.\n")
+ id = NULL
+ }
+ }
+ if (id != NULL)
+ mkstars = clgetb ("mkstars")
+ else
+ mkstars = false
+ } else {
+ gd = NULL
+ id = NULL
+ call dp_seti (dao, VERBOSE, btoi (clgetb ("verbose")))
+ showplots = false
+ mkstars = false
+ }
+
+ # Open the plot file.
+ if (Memc[plotfile] == EOS)
+ pfd = NULL
+ else
+ pfd = open (Memc[plotfile], APPEND, BINARY_FILE)
+ if (pfd != NULL)
+ mgd = gopen (Memc[graphics], NEW_FILE, pfd)
+ else
+ mgd = NULL
+
+ # Set the default plot type.
+ pltype = strdic (Memc[plottype], Memc[plottype], SZ_FNAME, PSF_PLOTS)
+ call dp_pseti (dao, PLOTTYPE, pltype)
+
+ # Loop over the list of images.
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open input image
+ im = immap (Memc[image], READ_ONLY, 0)
+ call dp_imkeys (dao, im)
+ call dp_sets (dao, INIMAGE, Memc[image])
+
+ # Set up the display coordinate system.
+ if ((id != NULL) && (id != gd))
+ call dp_gswv (id, Memc[image], im, 4)
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = dp_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call dp_pcache (im, INDEFI, buf_size)
+
+ # Open the input photometry list and store the descriptor.
+ # PSF can read either an APPHOT PHOT file or an ST TABLE
+ # file.
+
+ if (fntgfnb (alist, Memc[photfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[photfile], SZ_FNAME)
+ root = fnldir (Memc[photfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[photfile+root], DEF_LENDEFNAME) ==
+ 0 || root == strlen (Memc[photfile]))
+ call dp_inname (Memc[image], Memc[outfname], "mag",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[photfile], Memc[outfname], SZ_FNAME)
+ ap_text = itob (access (Memc[outfname], 0, TEXT_FILE))
+ if (ap_text)
+ apd = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ else
+ apd = tbtopn (Memc[outfname], READ_ONLY, 0)
+ call dp_wgetapert (dao, im, apd, dp_stati (dao, MAXNSTAR), ap_text)
+ call dp_sets (dao, INPHOTFILE, Memc[outfname])
+
+ # Open the input photometry list and store the descriptor.
+ # PSF can read either an APPHOT PHOT file or an ST TABLE
+ # file.
+
+ if (lclist == 0) {
+ pst = NULL
+ Memc[outfname] = EOS
+ } else {
+ if (fntgfnb (clist, Memc[pstarfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[pstarfile], SZ_FNAME)
+ root = fnldir (Memc[pstarfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[pstarfile+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[pstarfile]))
+ call dp_inname (Memc[image], Memc[outfname], "pst",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[pstarfile], Memc[outfname], SZ_FNAME)
+ pst_text = itob (access (Memc[outfname], 0, TEXT_FILE))
+ if (pst_text)
+ pst = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ else
+ pst = tbtopn (Memc[outfname], READ_ONLY, 0)
+ }
+ call dp_sets (dao, COORDS, Memc[outfname])
+
+ # Open output image containing PSF, output file containing list
+ # of PSF stars actually used, and the file for PSF neighbors
+ # If the output is "default", dir$default or a directory
+ # specification then the extension "psf" is added to the PSF image
+ # and "psg" to the neighbors file. A suitable version number is
+ # added to the output name as well. Check that there is enough
+ # space in the image header user area to hold many PSF stars.
+
+ if (imtgetim (pimlist, Memc[psfimage], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[psfimage], SZ_FNAME)
+ root = fnldir (Memc[psfimage], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[psfimage + root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[psfimage])) {
+ call dp_oimname (Memc[image], Memc[outfname], "psf",
+ Memc[outfname], SZ_FNAME)
+ } else
+ call strcpy (Memc[psfimage], Memc[outfname], SZ_FNAME)
+ if (envfind ("min_lenuserarea", Memc[str], SZ_FNAME) > 0) {
+ up = 1
+ if (ctoi (Memc[str], up, min_lenuserarea) <= 0)
+ min_lenuserarea = MIN_LENUSERAREA
+ else
+ min_lenuserarea = max (MIN_LENUSERAREA, min_lenuserarea)
+ } else
+ min_lenuserarea = MIN_LENUSERAREA
+ call dp_pseti (dao, LENUSERAREA, min_lenuserarea)
+ psfim = immap (Memc[outfname], NEW_IMAGE, min_lenuserarea)
+ call dp_sets (dao, PSFIMAGE, Memc[outfname])
+
+ if (fntgfnb (olist, Memc[groupfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[groupfile], SZ_FNAME)
+ root = fnldir (Memc[groupfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[groupfile + root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[groupfile])) {
+ call dp_outname (Memc[image], Memc[outfname], "psg",
+ Memc[outfname], SZ_FNAME)
+ } else
+ call strcpy (Memc[groupfile], Memc[outfname], SZ_FNAME)
+ if (dp_stati (dao, TEXT) == YES)
+ psfgr = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ else
+ psfgr = tbtopn (Memc[outfname], NEW_FILE, 0)
+ call dp_sets (dao, OUTPHOTFILE, Memc[outfname])
+
+
+ if (fntgfnb (oclist, Memc[opstfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[opstfile], SZ_FNAME)
+ root = fnldir (Memc[opstfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[opstfile+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[opstfile])) {
+ call dp_outname (Memc[image], Memc[outfname], "pst",
+ Memc[outfname], SZ_FNAME)
+ } else
+ call strcpy (Memc[opstfile], Memc[outfname], SZ_FNAME)
+ if (dp_stati (dao, TEXT) == YES)
+ opst = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ else
+ opst = tbtopn (Memc[outfname], NEW_FILE, 0)
+ call dp_sets (dao, OUTREJFILE, Memc[outfname])
+
+ # Print banner.
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("\nComputing PSF for image: %s\n")
+ call pargstr (Memc[image])
+ call dp_stats (dao, INPHOTFILE, Memc[str], SZ_FNAME)
+ call printf ("%d stars read from %s\n\n")
+ call pargi (dp_stati (dao, APNUM))
+ call pargstr (Memc[str])
+ }
+
+ # Read in the PSF star list.
+ call dp_pseti (dao, PNUM, 0)
+ if (pst != NULL) {
+ call dp_rpstars (dao, im, pst, pst_text, gd, mgd, id, mkstars,
+ matchbyid, showplots)
+ if (DP_VERBOSE(dao) == YES) {
+ call dp_stats (dao, COORDS, Memc[str], SZ_FNAME)
+ call printf ("\n%d PSF stars read from %s\n\n")
+ call pargi (dp_pstati (dao, PNUM))
+ call pargstr (Memc[str])
+ }
+ }
+
+ # Make the PSF.
+ if (Memc[curfile] != EOS)
+ call dp_mkpsf (dao, im, psfim, opst, psfgr, gd, mgd, id, false,
+ false, false)
+ else if (interactive)
+ call dp_mkpsf (dao, im, psfim, opst, psfgr, gd, mgd, id,
+ mkstars, true, true)
+ else if (! dp_updatepsf (dao, im, psfim, opst, psfgr, false, false,
+ false))
+ call dp_rmpsf (dao, psfim, opst, psfgr)
+
+ # Close the input image.
+ call imunmap (im)
+
+ # Close the input photometry file.
+ if (apd != NULL) {
+ if (ap_text)
+ call close (apd)
+ else
+ call tbtclo (apd)
+ }
+
+ # Close the input psf star file.
+ if (pst != NULL) {
+ if (pst_text)
+ call close (pst)
+ else
+ call tbtclo (pst)
+ }
+
+ # Close PSF image.
+ if (psfim != NULL)
+ call imunmap (psfim)
+
+ # Close the output PSF star file.
+ if (opst != NULL) {
+ if (dp_stati (dao, TEXT) == YES)
+ call close (opst)
+ else
+ call tbtclo (opst)
+ }
+
+ # Close the group file.
+ if (psfgr != NULL) {
+ if (dp_stati (dao, TEXT) == YES)
+ call close (psfgr)
+ else
+ call tbtclo (psfgr)
+ }
+
+ # Uncache memory.
+ call fixmem (old_size)
+ }
+
+ # Close up the graphics and display streams.
+ if (id == gd && id != NULL)
+ call gclose (id)
+ else {
+ if (gd != NULL)
+ call gclose (gd)
+ if (id != NULL)
+ call gclose (id)
+ }
+
+ # Close the metacode plot files.
+ if (mgd != NULL)
+ call gclose (mgd)
+ if (pfd != NULL)
+ call close (pfd)
+
+ # Close the image / file lists.
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call fntclsb (clist)
+ call imtclose (pimlist)
+ call fntclsb (olist)
+ call fntclsb (oclist)
+
+ # Free the photometry structure.
+ call dp_apclose (dao)
+
+ # Free the PSF fitting structure.
+ call dp_psfclose (dao)
+
+ # Free the PSF structure.
+ call dp_fitclose (dao)
+
+ # Close up the daophot structures.
+ call dp_free (dao)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/psf/t_pstselect.x b/noao/digiphot/daophot/psf/t_pstselect.x
new file mode 100644
index 00000000..497ab374
--- /dev/null
+++ b/noao/digiphot/daophot/psf/t_pstselect.x
@@ -0,0 +1,329 @@
+include <fset.h>
+include <imhdr.h>
+include <gset.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+include "../lib/psfdef.h"
+
+# T_PSTSELECT -- Select good candidate PSF stars from a DAOPHOT photometry
+# file.
+
+procedure t_pstselect ()
+
+pointer image # input image
+pointer photfile # input rough photometry
+pointer pstfile # output PSTFILE table
+int maxnpsf # maximimum number of psf stars
+pointer plotfile # pointer to the plot metacode file
+bool interactive # interactive mode
+pointer plottype # default plot type
+int cache # cache the input image pixels
+int verify # verify the critical parameters
+int update # update the critical parameters
+pointer graphics # the graphics device
+pointer display # the display device
+bool mkstars # mark deleted and accepted psf stars
+
+pointer sp, pfd, dao, outfname, curfile, str, im, gd, id, mgd
+int imlist, limlist, alist, lalist, olist, lolist, root, apd, pmgd, pltype
+int wcs, req_size, old_size, buf_size, memstat()
+bool ap_text
+
+pointer immap(), gopen()
+int tbtopn(), open(), fnldir(), strlen(), strncmp(), fstati(), btoi()
+int access(), fntopnb(), fntlenb(), clgeti(), imtopen(), imtlen()
+int fntgfnb(), imtgetim(), strdic(), dp_stati(), clgwrd(), sizeof()
+int dp_memstat()
+bool clgetb(), itob(), streq()
+
+errchk gopen()
+
+begin
+ # Set the standard output to flush on newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get some working memory.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (photfile, SZ_FNAME, TY_CHAR)
+ call salloc (pstfile, SZ_FNAME, TY_CHAR)
+ call salloc (plotfile, SZ_FNAME, TY_CHAR)
+ call salloc (plottype, SZ_FNAME, TY_CHAR)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+ call salloc (display, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (curfile, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Get the various task parameters.
+ call clgstr ("image", Memc[image], SZ_FNAME)
+ call clgstr ("photfile", Memc[photfile], SZ_FNAME)
+ call clgstr ("pstfile", Memc[pstfile], SZ_FNAME)
+ maxnpsf = clgeti ("maxnpsf")
+ cache = btoi (clgetb ("cache"))
+ verify = btoi (clgetb ("verify"))
+ update = btoi (clgetb ("update"))
+
+ # Get the lists.
+ imlist = imtopen (Memc[image])
+ limlist = imtlen (imlist)
+ alist = fntopnb (Memc[photfile], NO)
+ lalist = fntlenb (alist)
+ olist = fntopnb (Memc[pstfile], NO)
+ lolist = fntlenb (olist)
+
+ # Test that the lengths of the photometry file and psf star file
+ # lists are the same as the input image list.
+
+ if ((limlist != lalist) && (strncmp (Memc[photfile], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call fntclsb (olist)
+ call sfree (sp)
+ call error (0,
+ "Incompatable image and photometry file list lengths\n")
+ }
+
+ if ((limlist != lolist) && (strncmp (Memc[pstfile], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call fntclsb (olist)
+ call sfree (sp)
+ call error (0,
+ "Incompatable image and photometry file list lengths\n")
+ }
+
+ # Initialize the DAOPHOT structure, and get the pset parameters.
+ call dp_gppars (dao)
+
+ # Confirm the parameters.
+ if (verify == YES) {
+ call dp_ptconfirm (dao)
+ if (update == YES)
+ call dp_pppars (dao)
+ }
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_LINE, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_LINE, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSOUT, wcs)
+
+ # Initialize the photometry structure.
+ call dp_apsetup (dao)
+
+ # Initialize the PSF fitting structure.
+ call dp_psfsetup (dao)
+
+ # Initialize the PSF structure.
+ call dp_fitsetup (dao)
+
+ # Is the task interactive or not?
+ call clgstr ("icommands.p_filename", Memc[curfile], SZ_FNAME)
+ if (Memc[curfile] == EOS)
+ interactive = clgetb ("interactive")
+ else
+ interactive = false
+
+ # Get the graphics display and plot file devices.
+ call clgstr ("graphics", Memc[graphics], SZ_FNAME)
+ call clgstr ("display", Memc[display], SZ_FNAME)
+ call clgstr ("plottype", Memc[plottype], SZ_FNAME)
+ call clgstr ("plotfile", Memc[plotfile], SZ_FNAME)
+
+ # Open graphics and display devices if appropriate.
+ if (interactive) {
+ call dp_seti (dao, VERBOSE, YES)
+ if (Memc[graphics] == EOS)
+ gd = NULL
+ else {
+ iferr {
+ gd = gopen (Memc[graphics], APPEND+AW_DEFER, STDGRAPH)
+ } then {
+ call eprintf ("Warning: Error opening graphics device\n")
+ gd = NULL
+ }
+ }
+ if (Memc[display] == EOS)
+ id = NULL
+ else if (streq (Memc[graphics], Memc[display])) {
+ id = gd
+ } else {
+ iferr {
+ id = gopen (Memc[display], APPEND, STDIMAGE)
+ } then {
+ call eprintf (
+ "Warning: Graphics overlay not available for display device\n")
+ id = NULL
+ }
+ }
+ if (id != NULL)
+ mkstars = clgetb ("mkstars")
+ else
+ mkstars = false
+ } else {
+ gd = NULL
+ id = NULL
+ call dp_seti (dao, VERBOSE, btoi (clgetb ("verbose")))
+ mkstars = false
+ }
+
+ # Open the plot file.
+ if (Memc[plotfile] == EOS)
+ pmgd = NULL
+ else
+ pmgd = open (Memc[plotfile], APPEND, BINARY_FILE)
+ if (pmgd != NULL)
+ mgd = gopen (Memc[graphics], NEW_FILE, pmgd)
+ else
+ mgd = NULL
+
+ # Set the default plot type.
+ pltype = strdic (Memc[plottype], Memc[plottype], SZ_FNAME, PSF_PLOTS)
+ call dp_pseti (dao, PLOTTYPE, pltype)
+
+ # Loop over the list of input files
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open the input image.
+ im = immap (Memc[image], READ_ONLY, 0)
+ call dp_imkeys (dao, im)
+ call dp_sets (dao, INIMAGE, Memc[image])
+
+ # Set up the display coordinate system.
+ if ((id != NULL) && (id != gd))
+ call dp_gswv (id, Memc[image], im, 4)
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * IM_LEN(im,1) * IM_LEN(im,2) *
+ sizeof (IM_PIXTYPE(im))
+ memstat = dp_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call dp_pcache (im, INDEFI, buf_size)
+
+ # Open the input photometry table and read in the photometry.
+ if (fntgfnb (alist, Memc[photfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[photfile], SZ_FNAME)
+ root = fnldir (Memc[photfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[photfile+root], DEF_LENDEFNAME) ==
+ 0 || root == strlen (Memc[photfile]))
+ call dp_inname (Memc[image], Memc[outfname], "mag",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[photfile], Memc[outfname], SZ_FNAME)
+ ap_text = itob (access (Memc[outfname], 0, TEXT_FILE))
+ if (ap_text)
+ apd = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ else
+ apd = tbtopn (Memc[outfname], READ_ONLY, 0)
+ call dp_wgetapert (dao, im, apd, DP_MAXNSTAR(dao), ap_text)
+ call dp_sets (dao, INPHOTFILE, Memc[outfname])
+
+ # Open the output PSTSELECT file. If the output is "default",
+ # dir$default or a directory specification then the extension .pst
+ # is added to the image name and a suitable version number is
+ # appended to the output name.
+
+ if (fntgfnb (olist, Memc[pstfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[pstfile], SZ_FNAME)
+ root = fnldir (Memc[pstfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[pstfile + root], DEF_LENDEFNAME) ==
+ 0 || root == strlen (Memc[pstfile]))
+ call dp_outname (Memc[image], Memc[outfname], "pst",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[pstfile], Memc[outfname], SZ_FNAME)
+ if (ap_text)
+ pfd = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+ else
+ pfd = tbtopn (Memc[outfname], NEW_FILE, 0)
+ call dp_sets (dao, OUTPHOTFILE, Memc[outfname])
+
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("\nSelecting PSF stars for image %s\n")
+ call pargstr (Memc[image])
+ call dp_stats (dao, INPHOTFILE, Memc[outfname], SZ_FNAME)
+ call printf ("\t%d stars read from file %s\n\n")
+ call pargi (dp_stati (dao, APNUM))
+ call pargstr (Memc[outfname])
+ }
+
+ # Now select the PSF stars.
+ if (Memc[curfile] != EOS)
+ call dp_gpstars (dao, im, apd, pfd, ap_text, maxnpsf, NULL,
+ mgd, NULL, false, false, true)
+ else if (interactive)
+ call dp_gpstars (dao, im, apd, pfd, ap_text, maxnpsf, gd, mgd,
+ id, mkstars, true, false)
+ else
+ call dp_gpstars (dao, im, apd, pfd, ap_text, maxnpsf, NULL,
+ mgd, NULL, false, false, false)
+
+ # Close the input image.
+ call imunmap (im)
+
+ # Close the photometry file.
+ if (ap_text)
+ call close (apd)
+ else
+ call tbtclo (apd)
+
+ # Close the output table.
+ if (ap_text)
+ call close (pfd)
+ else
+ call tbtclo (pfd)
+
+ # Uncache memory.
+ call fixmem (old_size)
+
+ }
+
+ # Close up the graphics and display streams.
+ if (id == gd && id != NULL)
+ call gclose (id)
+ else {
+ if (gd != NULL)
+ call gclose (gd)
+ if (id != NULL)
+ call gclose (id)
+ }
+
+ # Close the metacode plot files.
+ if (mgd != NULL)
+ call gclose (mgd)
+ if (pmgd != NULL)
+ call close (pmgd)
+
+ # Close the image/file lists.
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call fntclsb (olist)
+
+ # Close the PSF structure.
+ call dp_fitclose (dao)
+
+ # Close the PSF fitting structure.
+ call dp_psfclose (dao)
+
+ # Free the photometry structure.
+ call dp_apclose (dao)
+
+ # Free the daophot structure.
+ call dp_free (dao)
+
+ call sfree(sp)
+end
diff --git a/noao/digiphot/daophot/pstselect.par b/noao/digiphot/daophot/pstselect.par
new file mode 100644
index 00000000..555d23f4
--- /dev/null
+++ b/noao/digiphot/daophot/pstselect.par
@@ -0,0 +1,23 @@
+# Parameters for the PSTSELECT task
+
+image,f,a,,,,"Image for which to build psf star list"
+photfile,f,a,default,,,"Photometry file (default: image.mag.?)"
+pstfile,f,a,"default",,,"Output psf star list file (default: image.pst.?)"
+maxnpsf,i,a,25,1,,"Maximum number of psf stars"
+mkstars,b,h,no,,,"Mark deleted and accepted psf stars"
+plotfile,s,h,"",,,"Output plot metacode file"
+datapars,pset,h,"",,,"Data dependent parameters"
+daopars,pset,h,"",,,"Psf fitting parameters"
+interactive,b,h,no,,,"Select psf stars interactively?"
+plottype,s,h,mesh,"|mesh|contour|radial",,"Default plot type (mesh|contour|radial)"
+icommands,*imcur,h,"",,,"Image cursor: [x y wcs] key [cmd]"
+gcommands,*gcur,h,"",,,"Graphics cursor: [x y wcs] key [cmd]"
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the input image pixels in memory?"
+verify,b,h,)_.verify,,,"Verify critical pstselect parameters?"
+update,b,h,)_.update,,,"Update critical pstselect parameters?"
+verbose,b,h,)_.verbose,,,"Print pstselect messages?"
+graphics,s,h,)_.graphics,,,"Graphics device"
+display,s,h,)_.display,,,"Image display device"
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/seepsf.par b/noao/digiphot/daophot/seepsf.par
new file mode 100644
index 00000000..25a4faea
--- /dev/null
+++ b/noao/digiphot/daophot/seepsf.par
@@ -0,0 +1,9 @@
+# Parameters for the SEEPSF task
+
+psfimage,f,a,,,,"PSF image name"
+image,f,a,,,,"Output image name"
+dimension,i,h,INDEF,,,"Dimension of the output PSF image"
+xpsf,r,h,INDEF,,,"X distance from the PSF star"
+ypsf,r,h,INDEF,,,"Y distance from the PSF star"
+magnitude,r,h,INDEF,,,"Magnitude of the PSF star"
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/seepsf/dpmkimage.x b/noao/digiphot/daophot/seepsf/dpmkimage.x
new file mode 100644
index 00000000..3be872c9
--- /dev/null
+++ b/noao/digiphot/daophot/seepsf/dpmkimage.x
@@ -0,0 +1,110 @@
+include <imhdr.h>
+include "../lib/daophotdef.h"
+
+# DP_MKIMAGE -- Make an image from the PSF.
+
+procedure dp_mkimage (dao, im_psf, im_out, dimen, xpsf, ypsf, magnitude)
+
+pointer dao # pointer to the DAOPHOT structure
+pointer im_psf # pointer to the psf image descriptor
+pointer im_out # pointer to the image descriptor
+int dimen # size of the image (square)
+real xpsf # x position of the psf
+real ypsf # y position of the psf
+real magnitude # magnitude of the PSF
+
+int i, j, psf_size, im_size
+pointer psffit, pixels, pixel
+real psfrad, dxfrom_psf, dyfrom_psf, dvdx, dvdy, start, delta, dx, dy, scale
+real dysq, drsq, psfradsq
+pointer imps2r()
+real imgetr(), dp_usepsf()
+errchk imgetr()
+
+begin
+ # Get the other pointers.
+ psffit = DP_PSFFIT (dao)
+ if (DP_PSFSIZE(psffit) > 0)
+ psfrad = (real (DP_PSFSIZE(psffit) - 1) / 2.0 - 1.0) / 2.0
+ else {
+ iferr {
+ scale = imgetr (im_psf, "SCALE")
+ } then {
+ psfrad = imgetr (im_psf, "PSFRAD")
+ } else {
+ psfrad = imgetr (im_psf, "PSFRAD") / scale
+ }
+ }
+ psfradsq = psfrad ** 2
+ psf_size = 2 * int (psfrad) + 1
+
+ IM_NDIM(imout) = 2
+ if (IS_INDEFI(dimen)) {
+ IM_LEN(im_out, 1) = psf_size
+ IM_LEN(im_out, 2) = psf_size
+ im_size = psf_size
+ } else {
+ IM_LEN(im_out, 1) = dimen
+ IM_LEN(im_out, 2) = dimen
+ im_size = dimen
+ }
+ IM_PIXTYPE(im_out) = TY_REAL
+
+ if (IS_INDEFR(xpsf)) {
+ dx = DP_PSFX(psffit)
+ dxfrom_psf = (DP_PSFX(psffit) - 1.0) / DP_PSFX(psffit) - 1.0
+ } else {
+ dx = xpsf
+ dxfrom_psf = (xpsf - 1.0) / DP_PSFX(psffit) - 1.0
+ }
+ if (IS_INDEFR(ypsf)) {
+ dy = DP_PSFY(psffit)
+ dyfrom_psf = (DP_PSFY(psffit) - 1.0) / DP_PSFY(psffit) - 1.0
+ } else {
+ dy = ypsf
+ dyfrom_psf = (ypsf - 1.0) / DP_PSFY(psffit) - 1.0
+ }
+
+ if (IS_INDEFR (magnitude)) {
+ scale = 1.0
+ } else {
+ scale = DAO_RELBRIGHT (psffit, magnitude)
+ }
+
+ call sprintf (IM_TITLE(im_out), SZ_IMTITLE,
+ "PSF evaluated at X: %.2f Y: %.2f Mag: %.3f")
+ call pargr (dx)
+ call pargr (dy)
+ if (IS_INDEFR(magnitude))
+ call pargr (DP_PSFMAG(psffit))
+ else
+ call pargr (magnitude)
+
+ # Get the image buffer and evaluate the PSF.
+ pixels = imps2r (im_out, 1, int (IM_LEN (im_out, 1)), 1,
+ int (IM_LEN (im_out, 2)))
+
+ # Get the starting coordinates and interpolation interval.
+ start = - (psf_size - 1) / 2.0
+ delta = real (psf_size - 1) / real (im_size - 1)
+
+ # Evaluate the pixels.
+ pixel = pixels
+ do j = 1, im_size {
+ dy = start + delta * (j - 1)
+ dysq = dy ** 2
+ do i = 1, im_size {
+ dx = start + delta * (i - 1)
+ drsq = dx ** 2 + dysq
+ if (drsq >= psfradsq)
+ Memr[pixel] = 0.0
+ else
+ Memr[pixel] = scale * dp_usepsf (DP_PSFUNCTION(psffit),
+ dx, dy, DP_PSFHEIGHT(psffit), Memr[DP_PSFPARS(psffit)],
+ Memr[DP_PSFLUT(psffit)], DP_PSFSIZE(psffit),
+ DP_NVLTABLE(psffit), DP_NFEXTABLE(psffit), dxfrom_psf,
+ dyfrom_psf, dvdx, dvdy)
+ pixel = pixel + 1
+ }
+ }
+end
diff --git a/noao/digiphot/daophot/seepsf/mkpkg b/noao/digiphot/daophot/seepsf/mkpkg
new file mode 100644
index 00000000..f8f23f29
--- /dev/null
+++ b/noao/digiphot/daophot/seepsf/mkpkg
@@ -0,0 +1,11 @@
+# SEEPSF task
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ dpmkimage.x <imhdr.h> ../lib/daophotdef.h
+ t_seepsf.x <fset.h>
+ ;
diff --git a/noao/digiphot/daophot/seepsf/t_seepsf.x b/noao/digiphot/daophot/seepsf/t_seepsf.x
new file mode 100644
index 00000000..e104121c
--- /dev/null
+++ b/noao/digiphot/daophot/seepsf/t_seepsf.x
@@ -0,0 +1,91 @@
+include <fset.h>
+
+# T_SEEPSF -- Produce the PSF in image scale coordinates.
+
+procedure t_seepsf ()
+
+pointer psfimage # name of the input PSF
+pointer image # name of the output image
+int dimen # size of the image
+real magnitude # magnitude of star
+
+int psffd, pimlist, lpimlist, imlist, limlist
+pointer im, sp, dao
+real xpsf, ypsf
+
+int clgeti(), fstati(), imtopen(), imtlen(), imtgetim()
+real clgetr()
+pointer immap()
+
+begin
+ # Set the standard output to flush on newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get some memory.
+ call smark (sp)
+ call salloc (psfimage, SZ_FNAME, TY_CHAR)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+
+ # Get the various task parameters.
+ call clgstr ("psfimage", Memc[psfimage], SZ_FNAME)
+ call clgstr ("image", Memc[image], SZ_FNAME)
+ dimen = clgeti ("dimension")
+ if (! IS_INDEFI(dimen)) {
+ if (mod (dimen, 2) == 0)
+ dimen = dimen + 1
+ }
+ xpsf = clgetr ("xpsf")
+ ypsf = clgetr ("ypsf")
+ magnitude = clgetr ("magnitude")
+
+ # Get the lists.
+ pimlist = imtopen (Memc[psfimage])
+ lpimlist = imtlen (pimlist)
+ imlist = imtopen (Memc[image])
+ limlist = imtlen (imlist)
+
+ # Check the list lengths for equality.
+ if (lpimlist != limlist) {
+ call imtclose (pimlist)
+ call imtclose (imlist)
+ call sfree (sp)
+ call error (0,
+ "The psf and output image lengths are imcompatibale")
+ }
+
+ # Initialize the daophot structure and get the pset parameters.
+ call dp_init (dao)
+ call dp_fitsetup (dao)
+
+ # Loop over the input images
+ while ((imtgetim (pimlist, Memc[psfimage], SZ_FNAME) != EOF) &&
+ (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF)) {
+
+ # Open the psfimage.
+ psffd = immap (Memc[psfimage], READ_ONLY, 0)
+
+ # Open the output image.
+ im = immap (Memc[image], NEW_COPY, psffd)
+
+ # Read the PSF.
+ call dp_readpsf (dao, psffd)
+
+ # Make PSF image.
+ call dp_mkimage (dao, psffd, im, dimen, xpsf, ypsf, magnitude)
+
+ # Close the PSF image and the output image.
+ call imunmap (psffd)
+ call imunmap (im)
+ }
+
+ # Close the daophot structure.
+ call dp_fitclose (dao)
+ call dp_free (dao)
+
+ # Close the lists
+ call imtclose (pimlist)
+ call imtclose (imlist)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/select/dpgwselect.x b/noao/digiphot/daophot/select/dpgwselect.x
new file mode 100644
index 00000000..dcaafece
--- /dev/null
+++ b/noao/digiphot/daophot/select/dpgwselect.x
@@ -0,0 +1,141 @@
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+
+define NCOLUMN 6
+
+define GR_DATASTR "%-9d%10t%-6d%16t%-10.3f%26t%-10.3f%36t%-12.3f%48t%-15.7g%80t \n"
+
+# DP_XWRTSELECT -- Write out the groups into an ST Table.
+
+procedure dp_xwrtselect (dao, grp, ngroup, group_id)
+
+pointer dao # pointer to the daophot structure
+pointer grp # pointer to group output file
+int ngroup # number in the group
+int group_id # the id of the group
+
+int i
+pointer apsel
+
+begin
+ # Get the daophot pointer.
+ apsel = DP_APSEL(dao)
+
+ # Write out the data.
+ do i = 1, ngroup {
+ call fprintf (grp, GR_DATASTR)
+ call pargi (group_id)
+ call pargi (Memi[DP_APID(apsel)+i-1])
+ call pargr (Memr[DP_APXCEN(apsel)+i-1])
+ call pargr (Memr[DP_APYCEN(apsel)+i-1])
+ call pargr (Memr[DP_APMAG(apsel)+i-1])
+ call pargr (Memr[DP_APMSKY(apsel)+i-1])
+ }
+end
+
+
+# DP_TWRTSELECT -- Write out the groups into an ST Table.
+
+procedure dp_twrtselect (dao, grp, colpoint, ngroup, cur_group, row)
+
+pointer dao # pointer to the daophot structure
+pointer grp # pointer to group output file
+pointer colpoint[ARB] # column pointers
+int ngroup # number in group
+int cur_group # current group
+
+int i, row
+pointer apsel
+
+begin
+ # Get the daophot pointer.
+ apsel = DP_APSEL(dao)
+
+ # Write out the data.
+ do i = 1, ngroup {
+ row = row + 1
+ call tbrpti (grp, colpoint[1], Memi[DP_APID(apsel)+i-1], 1, row)
+ call tbrpti (grp, colpoint[2], cur_group, 1, row)
+ call tbrptr (grp, colpoint[3], Memr[DP_APXCEN(apsel)+i-1], 1, row)
+ call tbrptr (grp, colpoint[4], Memr[DP_APYCEN(apsel)+i-1], 1, row)
+ call tbrptr (grp, colpoint[5], Memr[DP_APMAG(apsel)+i-1], 1, row)
+ call tbrptr (grp, colpoint[6], Memr[DP_APMSKY(apsel)+i-1], 1, row)
+
+ }
+end
+
+
+# DP_XGSELPARS -- Add various parameters to the header of the group table.
+
+procedure dp_xgselpars (tp, min_group, max_group)
+
+pointer tp # pointer to the table
+int min_group # minimum group size
+int max_group # maximum group size
+
+begin
+ # Add the min_group and max_group parameters.
+ call dp_iparam (tp, "MINSZGROUP", min_group, "number", "")
+ call dp_iparam (tp, "MAXSZGROUP", max_group, "number", "")
+end
+
+
+# DP_TGSELCOL -- Set the column pointers for the output file.
+
+procedure dp_tgselcol (tp, colpoints)
+
+pointer tp # table pointer
+pointer colpoints[ARB] # column pointers
+
+begin
+ call tbcfnd (tp, ID, colpoints[1], 1)
+ if (colpoints[1] == NULL)
+ call tbcfnd (tp, "ID", colpoints[1], 1)
+ if (colpoints[1] == NULL)
+ call printf ("Error reading ID.\n")
+
+ call tbcfnd (tp, GROUP, colpoints[2], 1)
+ if (colpoints[2] == NULL)
+ call tbcfnd (tp, "GROUP", colpoints[2], 1)
+ if (colpoints[2] == NULL)
+ call printf ("Error reading GROUP.\n")
+
+ call tbcfnd (tp, XCENTER, colpoints[3], 1)
+ if (colpoints[3] == NULL)
+ call tbcfnd (tp, "XCENTER", colpoints[3], 1)
+ if (colpoints[3] == NULL)
+ call printf ("Error reading XCENTER.\n")
+
+ call tbcfnd (tp, YCENTER, colpoints[4], 1)
+ if (colpoints[4] == NULL)
+ call tbcfnd (tp, "YCENTER", colpoints[4], 1)
+ if (colpoints[4] == NULL)
+ call printf ("Error reading YCENTER.\n")
+
+ call tbcfnd (tp, MAG, colpoints[5], 1)
+ if (colpoints[5] == NULL)
+ call tbcfnd (tp, APMAG, colpoints[5], 1)
+ if (colpoints[5] == NULL)
+ call printf ("Error reading MAG.\n")
+
+ call tbcfnd (tp, SKY, colpoints[6], 1)
+ if (colpoints[6] == NULL)
+ call tbcfnd (tp, SKY, colpoints[6], 1)
+ if (colpoints[6] == NULL)
+ call printf ("Error reading SKY.\n")
+end
+
+
+# DP_TGSELPARS -- Add various parameters to the header of the group table.
+
+procedure dp_tgselpars (tp, min_group, max_group)
+
+pointer tp # pointer to the table
+int min_group # minimum group size
+int max_group # maximum group size
+
+begin
+ # Add the min_group and max_group parameters.
+ call tbhadi (tp, "MINSZGROUP", min_group)
+ call tbhadi (tp, "MAXSZGROUP", max_group)
+end
diff --git a/noao/digiphot/daophot/select/dppfmerge.x b/noao/digiphot/daophot/select/dppfmerge.x
new file mode 100644
index 00000000..1d48cfba
--- /dev/null
+++ b/noao/digiphot/daophot/select/dppfmerge.x
@@ -0,0 +1,81 @@
+include <tbset.h>
+include "../lib/apseldef.h"
+
+# DP_PFMERGE -- Read the input photometry file, extract the fields ID,
+# XCENTER, YCENTER, MAG, and MSKY from each input record and add these
+# records to the output file.
+
+define NCOLUMN 5
+
+procedure dp_pfmerge (infd, outfd, in_text, out_text, first_file)
+
+int infd # the input file descriptor
+int outfd # the output file descriptor
+int in_text # input text file ?
+int out_text # output text file ?
+int first_file # first file ?
+
+int nrow, instar, outstar, id
+pointer sp, indices, fields, ocolpoint, key
+real x, y, mag, sky
+int tbpsta(), dp_rrphot()
+
+begin
+ # Allocate some memory.
+ call smark (sp)
+ call salloc (indices, NAPPAR, TY_INT)
+ call salloc (fields, SZ_LINE, TY_CHAR)
+ call salloc (ocolpoint, NCOLUMN, TY_POINTER)
+
+ # Initialize the output file.
+ if (first_file == YES) {
+ if (out_text == YES) {
+ call seek (infd, BOF)
+ call dp_apheader (infd, outfd)
+ call dp_xpbanner (outfd)
+ } else {
+ call dp_tpdefcol (outfd, Memi[ocolpoint])
+ call tbhcal (infd, outfd)
+ }
+ outstar = 0
+ }
+
+ # Initialize the input file
+ if (in_text == YES) {
+ call pt_kyinit (key)
+ Memi[indices] = DP_PAPID
+ Memi[indices+1] = DP_PAPXCEN
+ Memi[indices+2] = DP_PAPYCEN
+ Memi[indices+3] = DP_PAPMAG1
+ Memi[indices+4] = DP_PAPSKY
+ call dp_gappsf (Memi[indices], Memc[fields], NAPRESULT)
+ nrow = 0
+ } else {
+ call dp_tpkinit (infd, Memi[indices])
+ nrow = tbpsta (infd, TBL_NROWS)
+ }
+
+ # Loop over the stars.
+ instar = 0
+ repeat {
+
+ # Read the input record.
+ if (dp_rrphot (infd, key, Memc[fields], Memi[indices], id,
+ x, y, sky, mag, instar, nrow) == EOF)
+ break
+
+ # Write the output record.
+ outstar = outstar + 1
+ if (out_text == YES)
+ call dp_xpselmer (outfd, id, x, y, mag, sky)
+ else
+ call dp_tpselmer (outfd, id, x, y, mag, sky, Memi[ocolpoint],
+ outstar)
+ }
+
+
+ if (in_text == YES)
+ call pt_kyfree (key)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/select/dpsgroup.x b/noao/digiphot/daophot/select/dpsgroup.x
new file mode 100644
index 00000000..02b77ee7
--- /dev/null
+++ b/noao/digiphot/daophot/select/dpsgroup.x
@@ -0,0 +1,95 @@
+include <tbset.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+
+define NCOLUMN 6
+
+# DP_SGROUP -- Read in each group from the input file and write it to the
+# output file if its size is between min_group and max_group.
+
+procedure dp_sgroup (dao, tp_in, tp_out, text_file, min_group, max_group)
+
+pointer dao # pointer to the daophot structure
+pointer tp_in # the input file descriptor
+pointer tp_out # the output file descriptor
+bool text_file # text or table file
+int min_group # minimum sized group to extract
+int max_group # maximum sized group to extract
+
+int nrow_in_table, output_row, in_record, ngroup, cur_group
+pointer sp, indices, fields, key, icolpoint, ocolpoint
+int tbpsta(), dp_ggroup()
+
+begin
+ # Allocate some working memory.
+ call smark (sp)
+ call salloc (icolpoint, NAPGROUP, TY_POINTER)
+ call salloc (indices, NAPGROUP, TY_INT)
+ call salloc (fields, SZ_LINE, TY_CHAR)
+ call salloc (ocolpoint, NCOLUMN, TY_POINTER)
+
+ # Allocate some memory for reading in the group.
+ call dp_gnindices (Memi[indices])
+ call dp_memapsel (dao, Memi[indices], NAPPAR, max_group + 1)
+
+ # Initialize the output file.
+ if (text_file) {
+ call dp_apheader (tp_in, tp_out)
+ call dp_xgselpars (tp_out, min_group, max_group)
+ call dp_apbanner (tp_in, tp_out)
+ } else {
+ call tbtcre (tp_out)
+ call tbhcal (tp_in, tp_out)
+ call dp_tgselcol (tp_out, Memi[ocolpoint])
+ call dp_tgselpars (tp_out, min_group, max_group)
+ }
+
+ # Initialize the input file.
+ if (text_file) {
+ call pt_kyinit (key)
+ call dp_gnstpsf (Memi[indices], Memc[fields], NAPGROUP)
+ nrow_in_table = 0
+ } else {
+ key = NULL
+ call dp_tnsinit (tp_in, Memi[icolpoint])
+ nrow_in_table = tbpsta (tp_in, TBL_NROWS)
+ }
+
+ # Initialize the output record counter.
+ output_row = 0
+
+ # Initialize the input record counter.
+ in_record = 1
+
+ repeat {
+
+ # Read in the group.
+ ngroup = dp_ggroup (dao, tp_in, key, Memc[fields], Memi[indices],
+ Memi[icolpoint], nrow_in_table, max_group, in_record,
+ cur_group)
+ if (ngroup <= 0)
+ break
+ if (ngroup < min_group || ngroup > max_group)
+ next
+
+ # Print a message to the terminal.
+ if (DP_VERBOSE(dao) == YES) {
+ call printf ("Selecting group: %6d of %6d star(s)\n")
+ call pargi (cur_group)
+ call pargi (ngroup)
+ }
+
+ # Write the group to the output file.
+ if (text_file)
+ call dp_xwrtselect (dao, tp_out, ngroup, cur_group)
+ else
+ call dp_twrtselect (dao, tp_out, Memi[ocolpoint], ngroup,
+ cur_group, output_row)
+ }
+
+ if (text_file)
+ call pt_kyfree (key)
+
+ # Free memory.
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/select/mkpkg b/noao/digiphot/daophot/select/mkpkg
new file mode 100644
index 00000000..38c8bb67
--- /dev/null
+++ b/noao/digiphot/daophot/select/mkpkg
@@ -0,0 +1,15 @@
+# GRPSELECT and PFMERGE tasks
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ dppfmerge.x <tbset.h> ../lib/apseldef.h
+ dpsgroup.x <tbset.h> ../lib/daophotdef.h \
+ ../lib/apseldef.h
+ dpgwselect.x ../lib/apseldef.h ../lib/daophotdef.h
+ t_grpselect.x <fset.h> ../lib/daophotdef.h
+ t_pfmerge.x <fset.h>
+ ;
diff --git a/noao/digiphot/daophot/select/t_grpselect.x b/noao/digiphot/daophot/select/t_grpselect.x
new file mode 100644
index 00000000..89377270
--- /dev/null
+++ b/noao/digiphot/daophot/select/t_grpselect.x
@@ -0,0 +1,105 @@
+include <fset.h>
+include "../lib/daophotdef.h"
+
+# T_GRPSELECT -- Select groups from a GROUP file on the basis of the size
+# of the group. Only groups of the sizes specified are copied into the
+# output table.
+
+procedure t_grpselect ()
+
+pointer ingroup # the input GROUP file
+pointer outgroup # the output GROUP file
+int min_group # the minimum group size
+int max_group # the maximum group size
+
+bool gr_text
+int ilist, lilist, olist, lolist, verbose
+pointer sp, tp_in, tp_out, dao
+
+bool clgetb(), itob()
+int open(), tbtopn(), clgeti(), fstati(), btoi(), access()
+int fntopnb(), fntlenb(), fntgfnb()
+
+begin
+ # Set the standard output to flush on newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get some memory.
+ call smark (sp)
+ call salloc (ingroup, SZ_FNAME, TY_CHAR)
+ call salloc (outgroup, SZ_FNAME, TY_CHAR)
+
+ # Get the various task parameters.
+ call clgstr ("ingroupfile", Memc[ingroup], SZ_FNAME)
+ call clgstr ("outgroupfile", Memc[outgroup], SZ_FNAME)
+ min_group = clgeti ("min_group")
+ max_group = clgeti ("max_group")
+ verbose = btoi (clgetb ("verbose"))
+
+ # Open the daophot structure.
+ call dp_init (dao)
+
+ # Open the photometry structure.
+ call dp_apsetup (dao)
+
+ # Set some parameters.
+ call dp_seti (dao, VERBOSE, verbose)
+
+ # Get the lists.
+ ilist = fntopnb (Memc[ingroup], NO)
+ lilist = fntlenb (ilist)
+ olist = fntopnb (Memc[outgroup], NO)
+ lolist = fntlenb (olist)
+
+ # Check the list lengths.
+ if (lilist != lolist) {
+ call fntclsb (ilist)
+ call fntclsb (olist)
+ call sfree (sp)
+ call error (0,
+ "The input and output list lengths are not compatible")
+ }
+
+ # Loop over the files.
+ while ((fntgfnb (ilist, Memc[ingroup], SZ_FNAME) != EOF) &&
+ (fntgfnb (olist, Memc[outgroup], SZ_FNAME) != EOF)) {
+
+ # Open the input file.
+ gr_text = itob (access (Memc[ingroup], 0, TEXT_FILE))
+ if (gr_text)
+ tp_in = open (Memc[ingroup], READ_ONLY, TEXT_FILE)
+ else
+ tp_in = tbtopn (Memc[ingroup], READ_ONLY, 0)
+
+ # Open an output file of the same type as the input file.
+ if (gr_text)
+ tp_out = open (Memc[outgroup], NEW_FILE, TEXT_FILE)
+ else
+ tp_out = tbtopn (Memc[outgroup], NEW_COPY, tp_in)
+
+ # Read in the groups and select by group size.
+ call dp_sgroup (dao, tp_in, tp_out, gr_text, min_group, max_group)
+
+ # Close the input and output files.
+ if (gr_text) {
+ call close (tp_in)
+ call close (tp_out)
+ } else {
+ call tbtclo (tp_in)
+ call tbtclo (tp_out)
+ }
+ }
+
+ # Close the lists.
+ call fntclsb (ilist)
+ call fntclsb (olist)
+
+ # Free the photometry structure.
+ call dp_apclose (dao)
+
+ # Free the daophot structure.
+ call dp_free (dao)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/select/t_pfmerge.x b/noao/digiphot/daophot/select/t_pfmerge.x
new file mode 100644
index 00000000..f9f096e1
--- /dev/null
+++ b/noao/digiphot/daophot/select/t_pfmerge.x
@@ -0,0 +1,110 @@
+include <fset.h>
+
+# T_PFMERGE -- Merge photometry files written by PHOT, PSF, PEAK, GROUP,
+# NSTAR or ALLSTAR into one photometry file. The fields ID, XCENTER,
+# YCENTER, MAG, and MKSKY are read from each input file and written
+# without change to the output file. The input files may be text files or
+# binary ST tables files. The output file will have the same file type as the
+# the first input file. The header of the output file will be the header
+# of the first input file.
+
+procedure t_pfmerge ()
+
+pointer inphotfiles # the input photometry files
+pointer outphotfile # the output photometry file
+bool verbose # verbose output ?
+
+int plist, lplist, infd, outfd, first_file, in_text, out_text
+pointer sp, infname
+bool clgetb()
+int fstati(), fntopnb(), fntlenb(), fntgfnb(), access(), open()
+pointer tbtopn()
+
+begin
+ # Set the standard output to flush on newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get some working memory.
+ call smark (sp)
+ call salloc (inphotfiles, SZ_FNAME, TY_CHAR)
+ call salloc (outphotfile, SZ_FNAME, TY_CHAR)
+ call salloc (infname, SZ_FNAME, TY_CHAR)
+
+ # Get the various task parameters.
+ call clgstr ("inphotfiles", Memc[inphotfiles], SZ_FNAME)
+ call clgstr ("outphotfile", Memc[outphotfile], SZ_FNAME)
+ verbose = clgetb ("verbose")
+
+ # Open the input file list and determine the file type of the first
+ # file.
+ plist = fntopnb (Memc[inphotfiles], NO)
+ lplist = fntlenb (plist)
+ if (lplist <= 0) {
+ call fntclsb (plist)
+ call sfree (sp)
+ return
+ }
+ if (fntgfnb (plist, Memc[infname], SZ_FNAME) == EOF) {
+ call fntclsb (plist)
+ call sfree (sp)
+ return
+ } else {
+ out_text = access (Memc[infname], 0, TEXT_FILE)
+ call fntrewb (plist)
+ }
+
+ # Open the output file.
+ if (out_text == YES)
+ outfd = open (Memc[outphotfile], NEW_FILE, TEXT_FILE)
+ else
+ outfd = tbtopn (Memc[outphotfile], NEW_FILE, 0)
+
+ # Loop over the list of input files
+ first_file = YES
+ while (fntgfnb (plist, Memc[infname], SZ_FNAME) != EOF) {
+
+ # Print message.
+ if (verbose) {
+ call printf ("Merging photometry file %s into %s\n")
+ call pargstr (Memc[infname])
+ call pargstr (Memc[outphotfile])
+ }
+
+ # Open the input file.
+ in_text = access (Memc[infname], 0, TEXT_FILE)
+ if (verbose && (in_text != out_text)) {
+ if (in_text == YES)
+ call eprintf ("File %s is not an ST table file.\n")
+ else
+ call eprintf ("File %s is not a text file.\n")
+ call pargstr (Memc[infname])
+ }
+ if (in_text == YES)
+ infd = open (Memc[infname], READ_ONLY, TEXT_FILE)
+ else
+ infd = tbtopn (Memc[infname], READ_ONLY, 0)
+
+ # Now merge the files.
+ call dp_pfmerge (infd, outfd, in_text, out_text, first_file)
+
+ # Close the photometry file.
+ if (in_text == YES)
+ call close (infd)
+ else
+ call tbtclo (infd)
+
+ first_file = NO
+ }
+
+ # Close the output file.
+ if (out_text == YES)
+ call close (outfd)
+ else
+ call tbtclo (outfd)
+
+ # Close the input file list.
+ call fntclsb (plist)
+
+ call sfree(sp)
+end
diff --git a/noao/digiphot/daophot/setimpars.cl b/noao/digiphot/daophot/setimpars.cl
new file mode 100644
index 00000000..57b1c57b
--- /dev/null
+++ b/noao/digiphot/daophot/setimpars.cl
@@ -0,0 +1,276 @@
+# SETIMPARS -- Initialize the DAOPHOT task and pset parameters.
+
+procedure setimpars (image, restore, update)
+
+string image {prompt="Image name"}
+bool restore {yes, prompt="Restore the last saved parameter set ?"}
+bool update {yes, prompt="Update the last saved parameter set ?"}
+bool review {no,
+ prompt="Review the parameters before saving ?"}
+file parfile {"", prompt="Input algorithm parameters file"}
+file datapars {"", prompt="The input data dependent parameters file"}
+file findpars {"",
+ prompt="The input object detection parameters file"}
+file centerpars {"", prompt="The input centering parameters file"}
+file fitskypars {"", prompt="The input sky fitting parameters file"}
+file photpars {"",
+ prompt="The input aperture photometry parameters file"}
+file daopars {"", prompt="The input psf fitting parameters file"}
+bool unlearn {no,
+ prompt="Unlearn the current algorithm parameters ?"}
+
+begin
+ # Define some temporary variables.
+ bool trestore, tupdate
+ string timage, tinparfile, toutparfile, tpars, tfile1, tfile2
+
+ # Read in the image name.
+ timage = image
+ trestore = restore
+ tupdate = update
+ print ("Setting parameters for image ", timage, " ...")
+
+ # Set the input image name.
+ addstar.image = timage
+ allstar.image = timage
+ daoedit.image = timage
+ daofind.image = timage
+ group.image = timage
+ nstar.image = timage
+ peak.image = timage
+ pexamine.image = timage
+ phot.image = timage
+ psf.image = timage
+ pstselect.image = timage
+ substar.image = timage
+
+ # Set the input coordinate / sky files back to their defaults.
+ phot.skyfile = ""
+
+ # Set the input photometry files back to their defaults.
+ addstar.photfile = ""
+ addstar.simple_text = no
+ allstar.photfile = "default"
+ group.photfile = "default"
+ grpselect.ingroupfile = ""
+ nstar.groupfile = "default"
+ peak.photfile = "default"
+ phot.coords = "default"
+ psf.photfile = "default"
+ psf.pstfile = ""
+ pstselect.photfile = "default"
+ substar.photfile = "default"
+
+ # Set the psfimage back to the default.
+ addstar.psfimage = "default"
+ allstar.psfimage = "default"
+ group.psfimage = "default"
+ nstar.psfimage = "default"
+ peak.psfimage = "default"
+ seepsf.psfimage = ""
+ substar.psfimage = "default"
+
+ # Set the output photometry file names to the default.
+ allstar.allstarfile = "default"
+ allstar.rejfile = "default"
+ daofind.output = "default"
+ group.groupfile = "default"
+ grpselect.outgroupfile = ""
+ nstar.nstarfile = "default"
+ nstar.rejfile = "default"
+ peak.peakfile = "default"
+ peak.rejfile = "default"
+ phot.output = "default"
+ psf.groupfile = "default"
+ psf.opstfile = "default"
+ pstselect.pstfile = "default"
+
+ # Set the output images back to the default.
+ addstar.addimage = "default"
+ allstar.subimage = "default"
+ daofind.starmap = ""
+ daofind.skymap = ""
+ psf.psfimage = "default"
+ seepsf.image = ""
+ substar.subimage = "default"
+
+ # Set any output plot files back to the default.
+ phot.plotfile = ""
+ pstselect.plotfile = ""
+ psf.plotfile = ""
+
+ # Get the input parameter file name.
+ tinparfile = parfile
+ if (tinparfile == "") {
+ if (access (timage // ".pars") && trestore)
+ tinparfile = timage // ".pars"
+ } else if (! access (tinparfile)) {
+ print ("File ", tinparfile, " does not exist ...")
+ return
+ }
+
+ # Read in the input parameters.
+
+ if (tinparfile != "") {
+
+ print ("Reading algorithm parameters from file ",
+ tinparfile, " ...")
+ cl (< tinparfile)
+
+ } else {
+
+ tpars = datapars
+ if (access (tpars)) {
+ print ("Reading datapars parameters from file ", tpars, " ...")
+ tfile1 = mktemp ("tmp$pars")
+ tfile2 = mktemp ("tmp$pars")
+ dparam (tpars, > tfile1)
+ list = tfile1
+ while (fscan (list, line) != EOF) {
+ if (substr (line, 1, 5) != "# EOF")
+ print ("datapars.", line, >> tfile2)
+ }
+ cl (< tfile2)
+ delete (tfile1 // "," // tfile2, verify-, default_action+,
+ allversions+, subfiles+, go_ahead+, >& "dev$null")
+ } else if (unlearn) {
+ print ("Reading default datapars parameters from disk ...")
+ unlearn ("daophot.datapars")
+ } else {
+ print ("Reading current datapars parameters from disk ...")
+ }
+
+ tpars = findpars
+ if (access (tpars)) {
+ print ("Reading findpars parameters from file ", tpars, " ...")
+ tfile1 = mktemp ("tmp$pars")
+ tfile2 = mktemp ("tmp$pars")
+ dparam (tpars, > tfile1)
+ list = tfile1
+ while (fscan (list, line) != EOF) {
+ if (substr (line, 1, 5) != "# EOF")
+ print ("findpars.", line, >> tfile2)
+ }
+ cl (< tfile2)
+ delete (tfile1 // "," // tfile2, verify-, default_action+,
+ allversions+, subfiles+, go_ahead+, >& "dev$null")
+ } else if (unlearn) {
+ print ("Reading default findpars parameters from disk ...")
+ unlearn ("daophot.findpars")
+ } else {
+ print ("Reading current findpars parameters from disk ...")
+ }
+
+ tpars = centerpars
+ if (access (tpars)) {
+ print ("Reading centerpars parameters from file ", tpars,
+ " ...")
+ tfile1 = mktemp ("tmp$pars")
+ tfile2 = mktemp ("tmp$pars")
+ dparam (tpars, > tfile1)
+ list = tfile1
+ while (fscan (list, line) != EOF) {
+ if (substr (line, 1, 5) != "# EOF")
+ print ("centerpars.", line, >> tfile2)
+ }
+ cl (< tfile2)
+ delete (tfile1 // "," // tfile2, verify-, default_action+,
+ allversions+, subfiles+, go_ahead+, >& "dev$null")
+ } else if (unlearn) {
+ unlearn ("daophot.centerpars")
+ print ("Reading default centerpars parameters from disk ...")
+ } else {
+ print ("Reading current centerpars parameters from disk ...")
+ }
+
+ tpars = fitskypars
+ if (access (tpars)) {
+ print ("Reading fitskypars parameters from file ", tpars,
+ " ...")
+ tfile1 = mktemp ("tmp$pars")
+ tfile2 = mktemp ("tmp$pars")
+ dparam (tpars, > tfile1)
+ list = tfile1
+ while (fscan (list, line) != EOF) {
+ if (substr (line, 1, 5) != "# EOF")
+ print ("fitskypars.", line, >> tfile2)
+ }
+ cl (< tfile2)
+ delete (tfile1 // "," // tfile2, verify-, default_action+,
+ allversions+, subfiles+, go_ahead+, >& "dev$null")
+ } else if (unlearn) {
+ unlearn ("daophot.fitskypars")
+ print ("Reading default fitskypars parameters from disk ...")
+ } else {
+ print ("Reading current fitskypars parameters from disk ...")
+ }
+
+ tpars = photpars
+ if (access (tpars)) {
+ print ("Reading photpars parameters from file ", tpars,
+ " ...")
+ tfile1 = mktemp ("tmp$pars")
+ tfile2 = mktemp ("tmp$pars")
+ dparam (tpars, > tfile1)
+ list = tfile1
+ while (fscan (list, line) != EOF) {
+ if (substr (line, 1, 5) != "# EOF")
+ print ("photpars.", line, >> tfile2)
+ }
+ cl (< tfile2)
+ delete (tfile1 // "," // tfile2, verify-, default_action+,
+ allversions+, subfiles+, go_ahead+, >& "dev$null")
+ } else if (unlearn) {
+ unlearn ("daophot.photpars")
+ print ("Reading default photpars parameters from disk ...")
+ } else {
+ print ("Reading current photpars parameters from disk ...")
+ }
+
+ tpars = daopars
+ if (access (tpars)) {
+ print ("Reading psf fitting parameters from file ", tpars,
+ " ...")
+ tfile1 = mktemp ("tmp$pars")
+ tfile2 = mktemp ("tmp$pars")
+ dparam (tpars, > tfile1)
+ list = tfile1
+ while (fscan (list, line) != EOF) {
+ if (substr (line, 1, 5) != "# EOF")
+ print ("daopars.", line, >> tfile2)
+ }
+ cl (< tfile2)
+ delete (tfile1 // "," // tfile2, verify-, default_action+,
+ allversions+, subfiles+, go_ahead+, >& "dev$null")
+ } else if (unlearn) {
+ unlearn ("daophot.daopars")
+ print ("Reading default daopars parameters from disk ...")
+ } else {
+ print ("Reading current daopars parameters from disk ...")
+ }
+ }
+
+ # Review the current values for the algorithm parameters.
+ if (review) {
+ eparam ("datapars")
+ eparam ("findpars")
+ eparam ("centerpars")
+ eparam ("fitskypars")
+ eparam ("photpars")
+ eparam ("daopars")
+ }
+
+ # Update the output parameter file.
+ toutparfile = timage // ".pars"
+ if (tupdate) {
+ if (access (toutparfile)) {
+ print ("Updating image parameter file ", toutparfile, " ...")
+ delete (toutparfile, verify-, default_action+, allversions+,
+ subfiles+, go_ahead+, >& "dev$null")
+ } else {
+ print ("Creating image parameter file ", toutparfile, " ...")
+ }
+ dparam ("datapars", "findpars", "centerpars", "fitskypars",
+ "photpars", "daopars", > toutparfile)
+ }
+end
diff --git a/noao/digiphot/daophot/substar.par b/noao/digiphot/daophot/substar.par
new file mode 100644
index 00000000..db9947be
--- /dev/null
+++ b/noao/digiphot/daophot/substar.par
@@ -0,0 +1,17 @@
+# SUBSTAR Parameters
+
+image,f,a,,,,"Image corresponding to photometry file"
+photfile,f,a,default,,,"Input photometry file (default: image.nst.?)"
+exfile,f,a,,,,"Input exclude file (default: image.pst.?)"
+psfimage,f,a,default,,,"PSF image (default: image.psf.?)"
+subimage,f,a,"default",,,"Subtracted image (default: image.sub.?)"
+datapars,pset,h,"",,,Data dependent parameters
+daopars,pset,h,"",,,Psf fitting parameters
+wcsin,s,h,)_.wcsin,,,"The input coordinate system (logical,tv,physical,world)"
+wcsout,s,h,)_.wcsout,,,"The output coordinate system (logical,tv,physical)"
+wcspsf,s,h,)_.wcspsf,,,"The psf coordinate system (logical,tv,physical)"
+cache,b,h,)_.cache,,,"Cache the image pixels?"
+verify,b,h,)_.verify,,,Verify critical substar parameters?
+update,b,h,)_.update,,,Update critical substar parameters?
+verbose,b,h,)_.verbose,,,Print substar messages?
+mode,s,h,'ql'
diff --git a/noao/digiphot/daophot/substar/dpgimbufr.x b/noao/digiphot/daophot/substar/dpgimbufr.x
new file mode 100644
index 00000000..d4fac359
--- /dev/null
+++ b/noao/digiphot/daophot/substar/dpgimbufr.x
@@ -0,0 +1,137 @@
+include <imhdr.h>
+
+# DP_GIMBUFR -- Maintain buffer of image lines. A new buffer is created when
+# the buffer pointer is null. No changing of buffer size is allowed, although
+# this should be added. The minimum number of image reads is used.
+
+define flush_ 91
+
+procedure dp_gimbufr (inim, outim, line1, line2, buf, flush)
+
+pointer inim # input image pointer
+pointer outim # output image pointer
+int line1 # first image line of buffer
+int line2 # last image line of buffer
+pointer buf # buffer
+bool flush # flush the current contents of the buffer
+
+int i, ncols, nlines, llast1, llast2, nllast, lp, lout
+pointer buf1, buf2
+pointer imgl2r(), impl2r()
+
+begin
+ nlines = line2 - line1 + 1
+ ncols = IM_LEN (inim, 1)
+ lp = 0
+
+ if (flush)
+ goto flush_
+
+ # If the buffer pointer is undefined then allocate memory for the
+ # buffer. If the number of columns or lines requested changes
+ # reallocate the buffer. Initialize the last line values to force
+ # a full buffer image read.
+
+ if (buf == NULL) {
+ call malloc (buf, ncols * nlines, TY_REAL)
+ #llast1 = line1 - nlines
+ #llast2 = line2 - nlines
+ llast1 = 0
+ llast2 = 0
+ } else if ((nlines > nllast)) {
+ call eprintf ("Buffer requested is larger than previous one\n")
+ return
+ }
+
+ #call printf ("line1=%d line2=%d llast1=%d llast2=%d\n")
+ #call pargi (line1)
+ #call pargi (line2)
+ #call pargi (llast1)
+ #call pargi (llast2)
+
+ # Write out the lines that are not needed any more.
+ if (line1 > llast1 && llast1 > 0) {
+ buf2 = buf
+ lout = min (llast2, line1 - 1)
+ do i = llast1, lout{
+ buf1 = impl2r (outim, i)
+ call amovr (Memr[buf2], Memr[buf1], ncols)
+ #call printf ("Writing line: %d\n")
+ #call pargi (i)
+ buf2 = buf2 + ncols
+ }
+ }
+
+ # Write out any skipped image lines.
+ if (line1 > llast2) {
+ do i = llast2 + 1, line1 - 1 {
+ buf2 = imgl2r (inim, i)
+ buf1 = impl2r (outim, i)
+ call amovr (Memr[buf2], Memr[buf1], ncols)
+ #call printf ("Copying line: %d\n")
+ #call pargi (i)
+ }
+ }
+
+ # Now move the remaining lines to the begining of the buffer.
+ if (llast2 >= line1 ) {
+ buf2 = buf + ncols * (line1 - llast1)
+ buf1 = buf
+ do i = line1, llast2 {
+ lp = lp + 1
+ call amovr (Memr[buf2], Memr[buf1], ncols)
+ #call printf ("Moving line: %d\n")
+ #call pargi (i)
+ buf2 = buf2 + ncols
+ buf1 = buf1 + ncols
+ }
+ }
+
+ # Read only the image lines with are different from the last buffer.
+ buf1 = buf + ncols * lp
+ lout = max (line1, llast2 + 1)
+ do i = lout, line2 {
+ #call printf ("Reading line: %d\n")
+ #call pargi (i)
+ buf2 = imgl2r (inim, i)
+ call amovr (Memr[buf2], Memr[buf1], ncols)
+ buf1 = buf1 + ncols
+ }
+
+ # Save the buffer parameters.
+ llast1 = line1
+ llast2 = line2
+ nllast = nlines
+
+ # Quit
+ return
+
+flush_
+ # If requested to flush the current contents of the buffer we
+ # write out lines llast1 to llast2 and then set buf == NULL.
+
+ # Flush the data buffer.
+ if (buf != NULL) {
+ buf2 = buf
+ do i = llast1, llast2 {
+ buf1 = impl2r (outim, i)
+ call amovr (Memr[buf2], Memr[buf1], ncols)
+ #call printf ("Writing line: %d\n")
+ #call pargi (i)
+ buf2 = buf2 + ncols
+ }
+ }
+
+ # Copy any remaining image lines.
+ do i = llast2 + 1, IM_LEN(inim,2) {
+ buf2 = imgl2r (inim, i)
+ buf1 = impl2r (outim, i)
+ call amovr (Memr[buf2], Memr[buf1], ncols)
+ #call printf ("Copying line: %d\n")
+ #call pargi (i)
+ }
+
+ call mfree (buf, TY_REAL)
+ buf = NULL
+ nllast = 0
+end
diff --git a/noao/digiphot/daophot/substar/dprestars.x b/noao/digiphot/daophot/substar/dprestars.x
new file mode 100644
index 00000000..3b317960
--- /dev/null
+++ b/noao/digiphot/daophot/substar/dprestars.x
@@ -0,0 +1,116 @@
+include <tbset.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+
+
+# DP_RESTARS -- Read in the IDS of the stars to be excluded, find these stars
+# in the photometry list, and set their magnitudes to INDEF.
+
+int procedure dp_restars (dao, im, ext, text_file)
+
+pointer dao # pointer to the daophot structure
+pointer im # the input image descriptor
+int ext # the exclude list file descriptor
+bool text_file # text or table file ?
+
+real tx, ty, rjunk
+pointer apsel, sp, fields, indices, key
+int i, nrow, idno, nexcl, starno
+int tbpsta(), dp_apsel(), dp_exfind()
+
+begin
+ # Get some pointers.
+ apsel = DP_APSEL(dao)
+
+ # Get some working space.
+ call smark (sp)
+ call salloc (fields, SZ_LINE, TY_CHAR)
+ call salloc (indices, 1, TY_INT)
+
+ # Initialize the read.
+ if (text_file) {
+ call pt_kyinit (key)
+ Memi[indices] = DP_PAPID
+ call dp_gappsf (Memi[indices], Memc[fields], 1)
+ } else {
+ call dp_tptinit (ext, Memi[indices])
+ nrow = tbpsta (ext, TBL_NROWS)
+ }
+
+ i = 1
+ nexcl = 0
+ repeat {
+
+ # Read the next star.
+ if (text_file) {
+ if (dp_apsel (key, ext, Memc[fields], Memi[indices], idno,
+ rjunk, rjunk, rjunk, rjunk) == EOF)
+ break
+ } else {
+ if (i > nrow)
+ break
+ call dp_tptread (ext, Memi[indices], idno, rjunk, rjunk, rjunk,
+ i)
+ }
+
+ # Subtract star from the photometry list.
+ if (idno > 0) {
+ starno = dp_exfind (Memi[DP_APID(apsel)],
+ Memr[DP_APXCEN(apsel)], Memr[DP_APYCEN(apsel)],
+ Memr[DP_APMAG(apsel)], DP_APNUM(apsel), idno)
+ if (starno > 0) {
+ if (DP_VERBOSE(dao) == YES) {
+ call dp_wout (dao, im, Memr[DP_APXCEN(apsel)+starno-1],
+ Memr[DP_APYCEN(apsel)+starno-1], tx, ty, 1)
+ call printf (
+ "EXCLUDING - Star:%5d X =%8.2f Y =%8.2f Mag =%8.2f\n")
+ call pargi (Memi[DP_APID(apsel)+starno-1])
+ call pargr (tx)
+ call pargr (ty)
+ call pargr (Memr[DP_APMAG(apsel)+starno-1])
+ }
+ nexcl = nexcl + 1
+ } else if (DP_VERBOSE(dao) == YES) {
+ call printf ("EXCLUDING - Star:%5d not found\n")
+ call pargi (idno)
+ }
+ }
+
+ i = i + 1
+ }
+
+ if (text_file)
+ call pt_kyfree (key)
+ call sfree (sp)
+
+ return (nexcl)
+end
+
+
+# DP_EXFIND -- Find the star to be exclude in the photometry list.
+
+int procedure dp_exfind (ids, xcen, ycen, mags, nstars, idex)
+
+int ids[ARB] # array of stellar ids
+real xcen[ARB] # array of x coordinates
+real ycen[ARB] # array of y coordinates
+real mags[ARB] # array of magnitudes
+int nstars # number of stars in photometry list
+int idex # id of star to be excluded
+
+int i, found
+
+begin
+ found = 0
+ do i = 1, nstars {
+ if (ids[i] != idex)
+ next
+ found = i
+ break
+ }
+
+ if (found > 0)
+ mags[i] = INDEFR
+
+ return (found)
+end
diff --git a/noao/digiphot/daophot/substar/dpsconfirm.x b/noao/digiphot/daophot/substar/dpsconfirm.x
new file mode 100644
index 00000000..3ed5bc27
--- /dev/null
+++ b/noao/digiphot/daophot/substar/dpsconfirm.x
@@ -0,0 +1,18 @@
+# DP_SCONFIRM -- Procedure to confirm the critical substar parameters.
+
+procedure dp_sconfirm (dao)
+
+pointer dao # pointer to the daophot structure
+
+begin
+ call printf ("\n")
+
+ # Confirm the psf radius.
+ call dp_vpsfrad (dao)
+
+ # Confirm the minimum and maximum good data values.
+ call dp_vdatamin (dao)
+ call dp_vdatamax (dao)
+
+ call printf ("\n")
+end
diff --git a/noao/digiphot/daophot/substar/dpsubstar.x b/noao/digiphot/daophot/substar/dpsubstar.x
new file mode 100644
index 00000000..b33358dc
--- /dev/null
+++ b/noao/digiphot/daophot/substar/dpsubstar.x
@@ -0,0 +1,200 @@
+include <mach.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+include "../lib/apseldef.h"
+
+define EXPAND 8
+
+# DP_SUBSTAR -- Subtract the scaled and shifted PSF from the data
+
+procedure dp_substar (dao, inim, exfd, ex_text, outim)
+
+pointer dao # pointer to the DAOPHOT structure
+pointer inim # pointer to the input image
+int exfd # exclude file descriptor
+bool ex_text # text or table exclude file
+pointer outim # pointer to the output image
+
+real pradius, psfradsq, x, y, dxfrom_psf, dyfrom_psf, mag, tx, ty
+real rel_bright, maxgdata
+pointer apsel, psffit, buf, sp, index
+int i, id, line1, line2, nline_buf, x1, x2, y1, y2
+int lowy, highy, offset, nstars, ier
+int dp_restars()
+
+begin
+ # Get the daophot pointers.
+ apsel = DP_APSEL (dao)
+ psffit = DP_PSFFIT (dao)
+
+ # Exit gracefully if there are no stars.
+ #if (DP_APNUM(apsel) <= 0) {
+ #call printf ("The number of stars in the photometry list is %d\n")
+ #call pargi (DP_APNUM(apsel))
+ #return
+ #}
+
+ # Check for stars to be excluded.
+ if (exfd != NULL) {
+ if (dp_restars (dao, inim, exfd, ex_text) <= 0)
+ ;
+ }
+
+ # Compute the size of subraster to read from the PSF image.
+ if (DP_PSFSIZE(dao) == 0)
+ pradius = DP_PSFRAD(dao)
+ else
+ pradius = (real (DP_PSFSIZE(psffit) - 1) / 2.0 - 1.0) / 2.0
+ psfradsq = pradius * pradius
+
+ # Set the maximum good bad limit.
+ if (IS_INDEFR (DP_MAXGDATA(dao)))
+ maxgdata = MAX_REAL
+ else
+ maxgdata = DP_MAXGDATA(dao)
+
+ # Get some working memory.
+ call smark (sp)
+ call salloc (index, DP_APNUM (apsel), TY_INT)
+
+ # Sort the photometry on increasing Y.
+ if (DP_APNUM(apsel) > 0)
+ call quick (Memr[DP_APYCEN(apsel)], DP_APNUM(apsel), Memi[index],
+ ier)
+
+ # Initialize the boundary of the buffer.
+ buf = NULL
+ line1 = 0
+ line2 = 0
+ nline_buf = EXPAND * pradius
+
+ nstars = 0
+ do i = 1, DP_APNUM (apsel) {
+
+ # Get the data for the next star.
+ offset = Memi[index+i-1] - 1
+ x = Memr[DP_APXCEN(apsel)+offset]
+ y = Memr[DP_APYCEN(apsel)+i-1]
+ id = Memi[DP_APID(apsel)+offset]
+ mag = Memr[DP_APMAG (apsel)+offset]
+ call dp_wpsf (dao, inim, x, y, dxfrom_psf, dyfrom_psf, 1)
+ dxfrom_psf = (dxfrom_psf - 1.0) / DP_PSFX(psffit) - 1.0
+ dyfrom_psf = (dyfrom_psf - 1.0) / DP_PSFY(psffit) - 1.0
+
+ # Reject star is the magnitude is INDEF.
+ if (IS_INDEFR(x) || IS_INDEFR(y) || IS_INDEFR(mag)) {
+ if (DP_VERBOSE(dao) == YES) {
+ if (IS_INDEFR(x) || IS_INDEFR(y)) {
+ tx = x
+ ty = y
+ } else
+ call dp_wout (dao, inim, x, y, tx, ty, 1)
+ call printf (
+ "REJECTING - Star:%5d X =%8.2f Y =%8.2f Mag =%8.2f\n")
+ call pargi (id)
+ call pargr (tx)
+ call pargr (ty)
+ call pargr (mag)
+ }
+ next
+ }
+
+ # Print out the verbose message.
+ if (DP_VERBOSE(dao) == YES) {
+ call dp_wout (dao, inim, x, y, tx, ty, 1)
+ call printf (
+ "SUBTRACTING - Star:%5d X =%8.2f Y =%8.2f Mag =%8.2f\n")
+ call pargi (id)
+ call pargr (tx)
+ call pargr (ty)
+ call pargr (mag)
+ }
+
+ # Determine the range of lines required.
+ lowy = max (1, int (y - pradius) + 1)
+ highy = min (IM_LEN (inim, 2), int (y + pradius))
+ if (highy > line2) {
+ line1 = max (1, lowy)
+ line2 = min (line1 + nline_buf, IM_LEN (inim, 2))
+ call dp_gimbufr (inim, outim, line1, line2, buf, false)
+ }
+
+ # Change coordinates to reference frame of buffer.
+ y = y - line1 + 1.0
+ y1 = max (1, int (y - pradius) + 1)
+ y2 = min (line2 - line1 + 1, int (y + pradius))
+ x1 = max (1, int (x - pradius) + 1)
+ x2 = min (IM_LEN (inim, 1), int (x + pradius))
+
+ # Computee the relative brightness.
+ rel_bright = DAO_RELBRIGHT (psffit, mag)
+
+ # Subtract this star.
+ call dp_sstar (dao, Memr[buf], int (IM_LEN(inim,1)), nline_buf,
+ x1, x2, y1, y2, x, y, psfradsq, rel_bright, dxfrom_psf,
+ dyfrom_psf, maxgdata)
+
+ nstars = nstars + 1
+ }
+
+ # Flush the remaining lines in the image buffer.
+ call dp_gimbufr (inim, outim, y1, y2, buf, true)
+
+ # Summarize data on the number of stars subtracted.
+ if (DP_VERBOSE(dao) == YES) {
+ call printf (
+ "\nA total of %d stars were subtracted out of a possible %d\n")
+ call pargi (nstars)
+ call pargi (DP_APNUM(apsel))
+ }
+
+ # Free memory.
+ call sfree (sp)
+end
+
+
+# DP_SSTAR -- Subtract the star from the image.
+
+procedure dp_sstar (dao, data, nx, ny, x1, x2, y1, y2, xstar, ystar, psfradsq,
+ rel_bright, dxfrom_psf, dyfrom_psf, maxgdata)
+
+pointer dao # pointer to the daophot structure
+real data[nx,ny] # sata buffer
+int nx, ny # size of buffer
+int x1, x2, y1, y2 # area of interest
+real xstar, ystar # position of star to subtract
+real psfradsq # PSF radius ** 2
+real rel_bright # relative brightness of star
+real dxfrom_psf, dyfrom_psf # not currently used
+real maxgdata # maximum good data
+
+int ix, iy
+pointer psffit
+real dx, dy, dxsq, dysq, radsq, dvdx, dvdy
+real dp_usepsf()
+
+begin
+ psffit = DP_PSFFIT(dao)
+ do iy = y1, y2 {
+ dy = real (iy) - ystar
+ dysq = dy * dy
+ do ix = x1, x2 {
+ if (data[ix,iy] > maxgdata)
+ next
+ dx = real (ix) - xstar
+ dxsq = dx * dx
+ radsq = dxsq + dysq
+ if (radsq >= psfradsq) {
+ if (dx > 0.0)
+ break
+ next
+ }
+ data[ix,iy] = data[ix,iy] - rel_bright *
+ dp_usepsf (DP_PSFUNCTION(psffit), dx, dy,
+ DP_PSFHEIGHT(psffit), Memr[DP_PSFPARS(psffit)],
+ Memr[DP_PSFLUT(psffit)], DP_PSFSIZE(psffit),
+ DP_NVLTABLE(psffit), DP_NFEXTABLE(psffit),
+ dxfrom_psf, dyfrom_psf, dvdx, dvdy)
+ }
+ }
+end
diff --git a/noao/digiphot/daophot/substar/mkpkg b/noao/digiphot/daophot/substar/mkpkg
new file mode 100644
index 00000000..d51cf73e
--- /dev/null
+++ b/noao/digiphot/daophot/substar/mkpkg
@@ -0,0 +1,17 @@
+# SUBSTAR task
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ dpsconfirm.x
+ dpsubstar.x <mach.h> <imhdr.h> \
+ ../lib/daophotdef.h ../lib/apseldef.h
+ dpgimbufr.x <imhdr.h>
+ dprestars.x <tbset.h> ../lib/daophotdef.h \
+ ../lib/apseldef.h
+ t_substar.x <fset.h> <imhdr.h> \
+ ../lib/daophotdef.h
+ ;
diff --git a/noao/digiphot/daophot/substar/t_substar.x b/noao/digiphot/daophot/substar/t_substar.x
new file mode 100644
index 00000000..11ffc72b
--- /dev/null
+++ b/noao/digiphot/daophot/substar/t_substar.x
@@ -0,0 +1,286 @@
+include <fset.h>
+include <imhdr.h>
+include "../lib/daophotdef.h"
+
+# T_SUBSTAR -- Procedure to subtract DAOPHOT photometry from an image.
+
+procedure t_substar ()
+
+pointer image # name of the image
+pointer photfile # input photometry file
+pointer exfile # input exclude file
+pointer psfimage # name of the output PSF
+pointer subimage # subtracted image
+
+pointer sp, input, output, dao, outfname, str
+int psffd, photfd, root, verify, update, wcs
+int imlist, limlist, alist, lalist, pimlist, lpimlist, simlist, lsimlist
+int exfd, elist, lelist, cache, req_size, old_size, buf_size, memstat
+bool ap_text, ex_text
+
+pointer immap(), tbtopn()
+int open(), fnldir(), strlen(), strncmp(), access(), fstati(), btoi()
+int imtopen(), imtlen(), imtgetim(), fntopnb(), fntlenb(), fntgfnb()
+int clgwrd(), sizeof(), dp_memstat()
+bool clgetb(), itob()
+
+begin
+ # Set the standard output to flush on newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get some working memory.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (photfile, SZ_FNAME, TY_CHAR)
+ call salloc (exfile, SZ_FNAME, TY_CHAR)
+ call salloc (psfimage, SZ_FNAME, TY_CHAR)
+ call salloc (subimage, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Get the various task parameters.
+ call clgstr ("image", Memc[image], SZ_FNAME)
+ call clgstr ("photfile", Memc[photfile], SZ_FNAME)
+ call clgstr ("exfile", Memc[exfile], SZ_FNAME)
+ call clgstr ("psfimage", Memc[psfimage], SZ_FNAME)
+ call clgstr ("subimage", Memc[subimage], SZ_FNAME)
+ verify = btoi (clgetb ("verify"))
+ update = btoi (clgetb ("update"))
+ cache = btoi (clgetb ("cache"))
+
+ # Get the lists.
+ imlist = imtopen (Memc[image])
+ limlist = imtlen (imlist)
+ alist = fntopnb (Memc[photfile], NO)
+ lalist = fntlenb (alist)
+ elist = fntopnb (Memc[exfile], NO)
+ lelist = fntlenb (elist)
+ pimlist = imtopen (Memc[psfimage])
+ lpimlist = imtlen (pimlist)
+ simlist = imtopen (Memc[subimage])
+ lsimlist = imtlen (simlist)
+
+ # Test that the lengths of the photometry file, psf image and
+ # subtracted image lists are the same as the length of the input
+ # image list.
+
+ if ((limlist != lalist) && (strncmp (Memc[photfile], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call fntclsb (elist)
+ call imtclose (pimlist)
+ call imtclose (simlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatible image and photometry file list lengths")
+ }
+
+ if ((lelist != 0) && (limlist != lelist) && (strncmp (Memc[exfile],
+ DEF_DEFNAME, DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call fntclsb (elist)
+ call imtclose (pimlist)
+ call imtclose (simlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatible image and exclude file list lengths")
+ }
+
+ if ((limlist != lpimlist) && (strncmp (Memc[psfimage], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call fntclsb (elist)
+ call imtclose (pimlist)
+ call imtclose (simlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatible image and psf file list lengths")
+ }
+
+ if ((limlist != lsimlist) && (strncmp (Memc[subimage], DEF_DEFNAME,
+ DEF_LENDEFNAME) != 0)) {
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call fntclsb (elist)
+ call imtclose (pimlist)
+ call imtclose (simlist)
+ call sfree (sp)
+ call error (0,
+ "Incompatible image and subtracted image list lengths")
+ }
+
+ # Initialize the DAOPHOT structure and get the pset parameters.
+ call dp_gppars (dao)
+ call dp_seti (dao, VERBOSE, btoi (clgetb ("verbose")))
+
+ # Verify the critical parameters.
+ if (verify == YES) {
+ call dp_sconfirm (dao)
+ if (update == YES)
+ call dp_pppars (dao)
+ }
+
+ # Get the wcs information.
+ wcs = clgwrd ("wcsin", Memc[str], SZ_FNAME, WCSINSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the input coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSIN, wcs)
+ wcs = clgwrd ("wcsout", Memc[str], SZ_FNAME, WCSOUTSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the output coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSOUT, wcs)
+ wcs = clgwrd ("wcspsf", Memc[str], SZ_FNAME, WCSPSFSTR)
+ if (wcs <= 0) {
+ call eprintf (
+ "Warning: Setting the psf coordinate system to logical\n")
+ wcs = WCS_LOGICAL
+ }
+ call dp_seti (dao, WCSPSF, wcs)
+
+
+ # Initialize the PSF structure.
+ call dp_fitsetup (dao)
+
+ # Initialize the star list.
+ call dp_apselsetup (dao)
+
+ # Loop over the images
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open input and output images
+ input = immap (Memc[image], READ_ONLY, 0)
+ call dp_sets (dao, INIMAGE, Memc[image])
+
+ # Cache the input image pixels.
+ req_size = MEMFUDGE * (2 * IM_LEN(input,1) * IM_LEN(input,2) *
+ sizeof (IM_PIXTYPE(input)))
+ memstat = dp_memstat (cache, req_size, old_size)
+ if (memstat == YES)
+ call dp_pcache (input, INDEFI, buf_size)
+
+ # If the output image name is DEF_DEFNAME, dir$default or a
+ # directory specification then the extension "sub" is added to
+ # the image name and a suitable version number is appended to the
+ # output name.
+
+ if (imtgetim (simlist, Memc[subimage], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[subimage], SZ_FNAME)
+ root = fnldir (Memc[subimage], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[subimage + root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[subimage])) {
+ call dp_oimname (Memc[image], Memc[outfname], "sub",
+ Memc[outfname], SZ_FNAME)
+ output = immap (Memc[outfname], NEW_COPY, input)
+ } else {
+ call strcpy (Memc[subimage], Memc[outfname], SZ_FNAME)
+ output = immap (Memc[outfname], NEW_COPY, input)
+ }
+ call dp_sets (dao, OUTIMAGE, Memc[outfname])
+ if (memstat == YES)
+ call dp_pcache (output, INDEFI, buf_size)
+
+ # Open input photometry table and read in the photometry.
+ if (fntgfnb (alist, Memc[photfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[photfile], SZ_FNAME)
+ root = fnldir (Memc[photfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[photfile+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[photfile]))
+ call dp_inname (Memc[image], Memc[outfname], "nst",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[photfile], Memc[outfname], SZ_FNAME)
+ ap_text = itob (access (Memc[outfname], 0, TEXT_FILE))
+ if (ap_text)
+ photfd = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ else
+ photfd = tbtopn (Memc[outfname], READ_ONLY, 0)
+ call dp_wgetapert (dao, input, photfd, DP_MAXNSTAR(dao), ap_text)
+ call dp_sets (dao, INPHOTFILE, Memc[outfname])
+
+ # Open the input exclude file.
+ if (lelist == 0) {
+ exfd = NULL
+ Memc[outfname] = EOS
+ } else {
+ if (fntgfnb (elist, Memc[exfile], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[exfile], SZ_FNAME)
+ root = fnldir (Memc[exfile], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[exfile+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[exfile]))
+ call dp_inname (Memc[image], Memc[outfname], "pst",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[exfile], Memc[outfname], SZ_FNAME)
+ ex_text = itob (access (Memc[outfname], 0, TEXT_FILE))
+ if (ex_text)
+ exfd = open (Memc[outfname], READ_ONLY, TEXT_FILE)
+ else
+ exfd = tbtopn (Memc[outfname], READ_ONLY, 0)
+ }
+ call dp_sets (dao, COORDS, Memc[outfname])
+
+ # Read in the PSF
+ if (imtgetim (pimlist, Memc[psfimage], SZ_FNAME) == EOF)
+ call strcpy (DEF_DEFNAME, Memc[psfimage], SZ_FNAME)
+ root = fnldir (Memc[psfimage], Memc[outfname], SZ_FNAME)
+ if (strncmp (DEF_DEFNAME, Memc[psfimage+root],
+ DEF_LENDEFNAME) == 0 || root == strlen (Memc[psfimage]))
+ call dp_iimname (Memc[image], Memc[outfname], "psf",
+ Memc[outfname], SZ_FNAME)
+ else
+ call strcpy (Memc[psfimage], Memc[outfname], SZ_FNAME)
+ psffd = immap (Memc[outfname], READ_ONLY, 0)
+ call dp_readpsf (dao, psffd)
+ call dp_sets (dao, PSFIMAGE, Memc[outfname])
+
+ # Now go and subtract those stars!
+ call dp_substar (dao, input, exfd, ex_text, output)
+
+ # Close the input and output images.
+ call imunmap (input)
+ call imunmap (output)
+
+ # Close the photometry file.
+ if (ap_text)
+ call close (photfd)
+ else
+ call tbtclo (photfd)
+
+ # Close the exclude file.
+ if (ex_text)
+ call close (exfd)
+ else
+ call tbtclo (exfd)
+
+ # Close the PSF image.
+ call imunmap (psffd)
+
+ # Uncache memory
+ call fixmem (old_size)
+
+ }
+
+ # Close the lists.
+ call imtclose (imlist)
+ call fntclsb (alist)
+ call fntclsb (elist)
+ call imtclose (pimlist)
+ call imtclose (simlist)
+
+ # Free the daophot structures.
+ call dp_apclose (dao)
+ call dp_fitclose (dao)
+ call dp_free (dao)
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/daophot/test/cmds.dat b/noao/digiphot/daophot/test/cmds.dat
new file mode 100644
index 00000000..2a4bbdbf
--- /dev/null
+++ b/noao/digiphot/daophot/test/cmds.dat
@@ -0,0 +1,4 @@
+:a 10
+f
+w
+q
diff --git a/noao/digiphot/daophot/test/fits3.fits b/noao/digiphot/daophot/test/fits3.fits
new file mode 100644
index 00000000..ff7938e7
--- /dev/null
+++ b/noao/digiphot/daophot/test/fits3.fits
Binary files differ
diff --git a/noao/digiphot/daophot/x_daophot.x b/noao/digiphot/daophot/x_daophot.x
new file mode 100644
index 00000000..b9c2c627
--- /dev/null
+++ b/noao/digiphot/daophot/x_daophot.x
@@ -0,0 +1,14 @@
+# Task statements for the daophot package
+
+task addstar = t_addstar,
+ allstar = t_allstar,
+ daoedit = t_daoedit,
+ group = t_group,
+ grpselect = t_grpselect,
+ nstar = t_nstar,
+ peak = t_peak,
+ pfmerge = t_pfmerge,
+ psf = t_psf,
+ pstselect = t_pstselect,
+ seepsf = t_seepsf,
+ substar = t_substar
diff --git a/noao/digiphot/digiphot.cl b/noao/digiphot/digiphot.cl
new file mode 100644
index 00000000..af7171bc
--- /dev/null
+++ b/noao/digiphot/digiphot.cl
@@ -0,0 +1,15 @@
+#{ DIGIPHOT -- Digital photometric reduction package.
+
+set apphot = "digiphot$apphot/"
+set daophot = "digiphot$daophot/"
+set photcal = "digiphot$photcal/"
+set ptools = "digiphot$ptools/"
+
+package digiphot
+
+task apphot.pkg = apphot$apphot.cl
+task daophot.pkg = daophot$daophot.cl
+task photcal.pkg = photcal$photcal.cl
+task ptools.pkg = ptools$ptools.cl
+
+clbye()
diff --git a/noao/digiphot/digiphot.hd b/noao/digiphot/digiphot.hd
new file mode 100644
index 00000000..bd725960
--- /dev/null
+++ b/noao/digiphot/digiphot.hd
@@ -0,0 +1,30 @@
+# Help directory for the DIGIPHOT package.
+
+$apphot = "noao$digiphot/apphot/"
+$daophot = "noao$digiphot/daophot/"
+$photcal = "noao$digiphot/photcal/"
+$ptools = "noao$digiphot/ptools/"
+
+apphot men=apphot$apphot.men,
+ hlp=..,
+ sys=apphot$apphot.hlp,
+ pkg=apphot$apphot.hd,
+ src=apphot$apphot.cl
+
+daophot men=daophot$daophot.men,
+ hlp=..,
+ sys=daophot$daophot.hlp,
+ pkg=daophot$daophot.hd,
+ src=daophot$daophot.cl
+
+photcal men=photcal$photcal.men,
+ hlp=..,
+ sys=photcal$photcal.hlp,
+ pkg=photcal$photcal.hd,
+ src=photcal$photcal.cl
+
+ptools men=ptools$ptools.men,
+ hlp=..,
+ sys=ptools$ptools.hlp,
+ pkg=ptools$ptools.hd,
+ src=ptools$ptools.cl
diff --git a/noao/digiphot/digiphot.men b/noao/digiphot/digiphot.men
new file mode 100644
index 00000000..5b48015d
--- /dev/null
+++ b/noao/digiphot/digiphot.men
@@ -0,0 +1,4 @@
+ apphot - Aperture Photometry Package
+ daophot - Dao Crowded-Field Photometry Package
+ photcal - Photometric Calibration Package
+ ptools - Photometry Tools Package
diff --git a/noao/digiphot/digiphot.par b/noao/digiphot/digiphot.par
new file mode 100644
index 00000000..c8dc32b1
--- /dev/null
+++ b/noao/digiphot/digiphot.par
@@ -0,0 +1,4 @@
+# DIGIPHOT package parameter file.
+
+version,s,h,"Aug91"
+mode,s,h,ql
diff --git a/noao/digiphot/lib/mkpkg b/noao/digiphot/lib/mkpkg
new file mode 100644
index 00000000..4e879108
--- /dev/null
+++ b/noao/digiphot/lib/mkpkg
@@ -0,0 +1,11 @@
+# Make the local DIGIPHOT libraries
+
+relink:
+update:
+
+$update libpttables.a
+$exit
+
+libpttables.a:
+ @pttables
+ ;
diff --git a/noao/digiphot/lib/ptkeysdef.h b/noao/digiphot/lib/ptkeysdef.h
new file mode 100644
index 00000000..9cb005ea
--- /dev/null
+++ b/noao/digiphot/lib/ptkeysdef.h
@@ -0,0 +1,77 @@
+# Header file for apselect keywords
+
+define LEN_KEYSTRUCT 30
+
+# numbers of keys
+
+define KY_NKEYS Memi[$1] # total number of keys
+define KY_NPKEYS Memi[$1+1] # number of parameter keys
+define KY_NSTORE Memi[$1+2] # amount of storage space for keys
+#define KY_NOKEYS Memi[$1+3] # number of defined keys before table
+
+# keyword strings
+
+define LEN_KWORDS Memi[$1+4] # length of the keyword string
+define KY_WORDS Memi[$1+5] # pointer to the keywords string
+define KY_VALUES Memi[$1+6] # pointer to the values string
+define KY_UNITS Memi[$1+7] # pointer to the units string
+define KY_FORMATS Memi[$1+8] # pointer to the format string
+
+# indices
+
+define KY_PTRS Memi[$1+9] # pointer to values array
+define KY_NELEMS Memi[$1+10] # pointer to number of elems array
+define KY_TYPES Memi[$1+11] # pointer to the keyword data type array
+define KY_KINDICES Memi[$1+12] # pointer to the keyword indices
+define KY_UINDICES Memi[$1+13] # pointer to the unit indices
+define KY_FINDICES Memi[$1+14] # pointer to the format indices
+define KY_NPLINE Memi[$1+15] # pointer to values per line array
+define KY_NCONTINUE Memi[$1+16] # pointer to max no of continuations
+
+# select buffers
+
+define KY_NSELECT Memi[$1+18] # number of selected keys
+define KY_SELECT Memi[$1+19] # indices to selected fields
+define KY_ELEM_SELECT Memi[$1+20] # index of element to be selected
+define KY_LEN_SELECT Memi[$1+21] # lengths of the selected fields
+define KY_NAME_SELECT Memi[$1+22] # pointer to string of selected names
+define KY_UNIT_SELECT Memi[$1+23] # pointer to string of selected units
+define KY_FMT_SELECT Memi[$1+24] # pointer to string of selected formats
+
+
+# test for apphot/daophot database format
+
+define KY_CHAR_IRAF "^\#K IRAF"
+
+# some important character strings
+
+define KY_CHAR_KEYWORD "#K "
+define KY_CHAR_NAME "#N "
+define KY_CHAR_UNITS "#U "
+define KY_CHAR_FORMAT "#F "
+define KY_LEN_STR 3
+
+define KY_CHAR_POUND '#'
+define KY_CHAR_NEWLINE '\n'
+define KY_CHAR_CONT '\\'
+
+
+# some useful constants
+
+define KY_SZPAR 23 # assumed number of chars in a parameter
+define KY_NPARS 50 # initial guess at number of parameters
+define KY_NLINES 20 # maximum number of lines per record
+
+define KY_MAXNKEYWORDS 150 # maximum number of keywords.
+#define KY_MAXNNAMES 150 # maximum number of column names
+define KY_MAXNRANGES 150 # maximum number of reanges
+
+# names of parameter which can be extracted from the keys database
+
+define KY_INDEX 1
+define KY_DATATYPE 2
+define KY_LENGTH 3
+define KY_ELEMENT 4
+define KY_NUMELEMS 5
+define KY_UNITSTR 6
+define KY_FMTSTR 7
diff --git a/noao/digiphot/lib/pttables/Revisions b/noao/digiphot/lib/pttables/Revisions
new file mode 100644
index 00000000..4fce2c60
--- /dev/null
+++ b/noao/digiphot/lib/pttables/Revisions
@@ -0,0 +1,10 @@
+.help revisions Jun94 noao.digiphot.pttables
+.nf
+pttables/ptkeywords.x
+ Fixed a memory allocation bug which occured when the number of
+ header keywords was greater the 50. A pointer array was not being
+ correctly updated after memory reallocation.
+
+ (Davis, Feb 2, 1994)
+
+.endhelp
diff --git a/noao/digiphot/lib/pttables/mkpkg b/noao/digiphot/lib/pttables/mkpkg
new file mode 100644
index 00000000..af6f7827
--- /dev/null
+++ b/noao/digiphot/lib/pttables/mkpkg
@@ -0,0 +1,19 @@
+# Pttables library
+
+$checkout libpttables.a ".."
+$update libpttables.a
+$checkin libpttables.a ".."
+$exit
+
+libpttables.a:
+ ptchoose.x ../ptkeysdef.h
+ ptfmkrec.x ../ptkeysdef.h
+ ptgetop.x ../ptkeysdef.h <evexpr.h>
+ ptgnfn.x ../ptkeysdef.h <ctype.h> <syserr.h>
+ pthdrs.x ../ptkeysdef.h
+ ptkeywords.x ../ptkeysdef.h
+ ptkid.x
+ ptkstat.x ../ptkeysdef.h
+ ptmkrec.x ../ptkeysdef.h
+ ptranges.x
+ ;
diff --git a/noao/digiphot/lib/pttables/ptchoose.x b/noao/digiphot/lib/pttables/ptchoose.x
new file mode 100644
index 00000000..18a35195
--- /dev/null
+++ b/noao/digiphot/lib/pttables/ptchoose.x
@@ -0,0 +1,164 @@
+include "../ptkeysdef.h"
+
+# PT_CHOOSE -- Determine which fields are to be selected.
+
+int procedure pt_choose (key, fields)
+
+pointer key # pointer to key structure
+char fields[ARB] # fields to be evaluated
+
+int max_nkeys, nkeys, index, elems, nelems, element, len
+pointer list, sp, kname, uname, fname, aranges, ranges, rangeset
+pointer nop, uop, fop
+int pt_gnfn(), pt_ranges(), strdic(), decode_ranges(), get_next_number()
+int pt_kstati()
+pointer pt_ofnl()
+real asumi()
+
+begin
+ # Allocate buffer space
+ call smark (sp)
+ call salloc (kname, KY_SZPAR, TY_CHAR)
+ call salloc (uname, KY_SZPAR, TY_CHAR)
+ call salloc (fname, KY_SZPAR, TY_CHAR)
+ call salloc (aranges, SZ_FNAME, TY_CHAR)
+ call salloc (ranges, SZ_FNAME, TY_CHAR)
+ call salloc (rangeset, 3 * KY_MAXNRANGES + 1, TY_INT)
+
+ # Allocate space for the select buffers. Space equal to the number
+ # of keys in the database is allocated. Allowance must be made for
+ # array subsripts.
+
+ max_nkeys = int (asumi (Memi[KY_NELEMS(key)], KY_NKEYS(key))) + 1
+
+ if (KY_SELECT(key) != NULL)
+ call mfree (KY_SELECT(key), TY_INT)
+ call malloc (KY_SELECT(key), max_nkeys, TY_INT)
+ if (KY_ELEM_SELECT(key) != NULL)
+ call mfree (KY_ELEM_SELECT(key), TY_INT)
+ call malloc (KY_ELEM_SELECT(key), max_nkeys, TY_INT)
+ if (KY_LEN_SELECT(key) != NULL)
+ call mfree (KY_LEN_SELECT(key), TY_INT)
+ call malloc (KY_LEN_SELECT(key), max_nkeys, TY_INT)
+
+ if (KY_NAME_SELECT(key) != NULL)
+ call mfree (KY_NAME_SELECT(key), TY_CHAR)
+ call malloc (KY_NAME_SELECT(key), max_nkeys * KY_SZPAR, TY_CHAR)
+ if (KY_UNIT_SELECT(key) != NULL)
+ call mfree (KY_UNIT_SELECT(key), TY_CHAR)
+ call malloc (KY_UNIT_SELECT(key), max_nkeys * KY_SZPAR, TY_CHAR)
+ if (KY_FMT_SELECT(key) != NULL)
+ call mfree (KY_FMT_SELECT(key), TY_CHAR)
+ call malloc (KY_FMT_SELECT(key), max_nkeys * KY_SZPAR, TY_CHAR)
+
+ nop = KY_NAME_SELECT(key)
+ uop = KY_UNIT_SELECT(key)
+ fop = KY_FMT_SELECT(key)
+ nkeys = 0
+
+ # Loop through the fields list.
+ list = pt_ofnl (key, fields)
+ while (pt_gnfn (list, Memc[kname], Memc[aranges], KY_SZPAR) != EOF) {
+
+ # Find the field name and the ranges.
+ index = strdic (Memc[kname], Memc[kname], KY_SZPAR,
+ Memc[KY_WORDS(key)])
+ if (pt_ranges (Memc[aranges], Memc[ranges], element,
+ SZ_FNAME) == ERR)
+ call error (0, "Cannot decode apphot range string")
+ if (index == 0)
+ next
+
+ # Get the length, format and the units strings.
+ nelems = pt_kstati (key, Memc[kname], KY_NUMELEMS)
+ len = pt_kstati (key, Memc[kname], KY_LENGTH)
+ call pt_kstats (key, Memc[kname], KY_UNITSTR, Memc[uname],
+ KY_SZPAR)
+ call pt_kstats (key, Memc[kname], KY_FMTSTR, Memc[fname],
+ KY_SZPAR)
+
+ # Load the fields.
+ if (nelems == 1) {
+
+ Memi[KY_SELECT(key)+nkeys] = index
+ Memi[KY_ELEM_SELECT(key)+nkeys] = 1
+ Memi[KY_LEN_SELECT(key)+nkeys] = len
+
+ call sprintf (Memc[nop], len, "%*.*s")
+ call pargi (-len)
+ call pargi (len)
+ call pargstr (Memc[kname])
+ nop = nop + len
+
+ call sprintf (Memc[uop], len, "%*.*s")
+ call pargi (-len)
+ call pargi (len)
+ call pargstr (Memc[uname])
+ uop = uop + len
+
+ call sprintf (Memc[fop], len, "%*.*s")
+ call pargi (-len)
+ call pargi (len)
+ call pargstr (Memc[fname])
+ fop = fop + len
+
+ nkeys = nkeys + 1
+
+ } else {
+
+ if (Memc[ranges] == EOS) {
+ call sprintf (Memc[ranges], SZ_FNAME, "1-%d")
+ call pargi (nelems)
+ }
+ if (decode_ranges (Memc[ranges], Memi[rangeset], KY_MAXNRANGES,
+ elems) == ERR)
+ call error (0, "Cannot decode ranges string")
+
+ elems = 0
+ while (get_next_number (Memi[rangeset], elems) != EOF) {
+
+ if (elems < 1 || elems > nelems)
+ break
+ Memi[KY_SELECT(key)+nkeys] = index
+ Memi[KY_ELEM_SELECT(key)+nkeys] = elems
+ Memi[KY_LEN_SELECT(key)+nkeys] = len
+
+ call sprintf (Memc[nop], max_nkeys * KY_SZPAR, "%s%*.*d")
+ call pargstr (Memc[kname])
+ call pargi (-len)
+ call pargi (len)
+ call pargi (elems)
+ nop = nop + len
+
+ call sprintf (Memc[uop], len, "%*.*s")
+ call pargi (-len)
+ call pargi (len)
+ call pargstr (Memc[uname])
+ uop = uop + len
+
+ call sprintf (Memc[fop], len, "%*.*s")
+ call pargi (-len)
+ call pargi (len)
+ call pargstr (Memc[fname])
+ fop = fop + len
+
+ nkeys = nkeys + 1
+ }
+ }
+ }
+
+ # Reallocate the select buffer space.
+ KY_NSELECT(key) = nkeys
+ call realloc (KY_SELECT(key), KY_NSELECT(key), TY_INT)
+ call realloc (KY_ELEM_SELECT(key), KY_NSELECT(key), TY_INT)
+ call realloc (KY_LEN_SELECT(key), KY_NSELECT(key), TY_INT)
+ call realloc (KY_NAME_SELECT(key), KY_NSELECT(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_UNIT_SELECT(key), KY_NSELECT(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_FMT_SELECT(key), KY_NSELECT(key) * KY_SZPAR, TY_CHAR)
+
+ # Free list storage space.
+ call pt_cfnl (list)
+ call sfree (sp)
+
+ return (nkeys)
+end
diff --git a/noao/digiphot/lib/pttables/ptfmkrec.x b/noao/digiphot/lib/pttables/ptfmkrec.x
new file mode 100644
index 00000000..3f7dcc84
--- /dev/null
+++ b/noao/digiphot/lib/pttables/ptfmkrec.x
@@ -0,0 +1,102 @@
+include "../ptkeysdef.h"
+
+# PT_FMKREC -- Construct the output record and mark the place of the
+# requested field.
+
+int procedure pt_fmkrec (key, field, element, line, nchars, first_rec,
+ recptr, ncontinue)
+
+pointer key # pointer to record structure
+int field # the index of the requested field
+int element # the requested element of the field
+char line[ARB] # input line
+int nchars # length of line array
+int first_rec # first record read
+int recptr # line per record index
+int ncontinue # number of unique lines per record
+
+int i, cip, nokeys, nckeys, nkeys, nper_line, len_move, offset
+pointer op
+
+begin
+ # Initialize the offset.
+ offset = 0
+
+ # Reinitialize if this is the start of a new record.
+ if (recptr == 1)
+ nokeys = KY_NPKEYS(key)
+
+ # Check repeat character.
+ if (line[nchars-2] == '*')
+ ncontinue = ncontinue + 1
+ else
+ ncontinue = 0
+
+ # Fill in the record.
+ cip = 1
+ if (ncontinue < 1) {
+
+ nper_line = Memi[KY_NPLINE(key)+recptr-1]
+ nkeys = nokeys + nper_line
+ call amovki (int(1), Memi[KY_NELEMS(key)+nokeys], nper_line)
+
+ len_move = 0
+ do i = nokeys + 1, nkeys {
+ if (field == i)
+ offset = cip + len_move
+ len_move = len_move + Memi[KY_KINDICES(key)+i-1]
+ }
+ op = Memi[KY_PTRS(key)+nokeys]
+ call amovc (line[cip], Memc[op], len_move)
+
+ cip = cip + len_move
+ recptr = recptr + 1
+ nokeys = nkeys
+
+ } else if (ncontinue == 1) {
+
+ nckeys = nokeys + 1
+ nkeys = nokeys + Memi[KY_NPLINE(key)+recptr-1]
+
+ if (first_rec == YES) {
+ Memi[KY_NCONTINUE(key)+recptr-1] = KY_NLINES
+ do i = nckeys, nkeys
+ call malloc (Memi[KY_PTRS(key)+i-1], KY_NLINES *
+ Memi[KY_KINDICES(key)+i-1], TY_CHAR)
+ }
+
+ do i = nckeys, nkeys {
+ if ((field == i) && (element == 1))
+ offset = cip
+ call amovc (line[cip], Memc[Memi[KY_PTRS(key)+i-1]],
+ Memi[KY_KINDICES(key)+i-1])
+ cip = cip + Memi[KY_KINDICES(key)+i-1]
+ }
+
+ nokeys = nkeys
+ recptr = recptr + 1
+
+ } else {
+
+ if (ncontinue > Memi[KY_NCONTINUE(key)+recptr-2]) {
+ Memi[KY_NCONTINUE(key)+recptr-2] = Memi[KY_NCONTINUE(key)+
+ recptr-2] + KY_NLINES
+ do i = nckeys, nkeys
+ call realloc (Memi[KY_PTRS(key)+i-1],
+ Memi[KY_NCONTINUE(key)+recptr-2] *
+ Memi[KY_KINDICES(key)+i-1], TY_CHAR)
+ }
+
+ do i = nckeys, nkeys {
+ op = Memi[KY_PTRS(key)+i-1] + (ncontinue - 1) *
+ Memi[KY_KINDICES(key)+i-1]
+ if ((field == i) && (element == ncontinue))
+ offset = cip
+ call amovc (line[cip], Memc[op], Memi[KY_KINDICES(key)+i-1])
+ Memi[KY_NELEMS(key)+i-1] = ncontinue
+ cip = cip + Memi[KY_KINDICES(key)+i-1]
+ }
+ }
+
+ return (offset)
+end
diff --git a/noao/digiphot/lib/pttables/ptgetop.x b/noao/digiphot/lib/pttables/ptgetop.x
new file mode 100644
index 00000000..c2697767
--- /dev/null
+++ b/noao/digiphot/lib/pttables/ptgetop.x
@@ -0,0 +1,112 @@
+include <evexpr.h>
+include "../ptkeysdef.h"
+
+# PT_GETOP -- Procedure to fetch an apphot operand for evexpr.
+
+procedure pt_getop (operand, o)
+
+char operand[ARB] # operand name
+pointer o # operand output
+
+pointer apkey
+common /kycommon/ apkey
+errchk pt_getfield()
+
+begin
+ call pt_getfield (apkey, operand, o)
+end
+
+
+# PT_APSET -- Porcedure to pass the apphot structure in a common block.
+
+procedure pt_apset (key)
+
+pointer key # apphot strucuture
+
+pointer apkey
+common /kycommon/ apkey
+
+begin
+ apkey = key
+end
+
+
+# PT_GETFIELD -- Procedure to select an apphot field.
+
+procedure pt_getfield (key, field, o)
+
+pointer key # pointer to select strucuture
+char field[ARB] # field to evaluated
+pointer o # operand
+
+int type, maxnelems, nelems
+pointer sp, root, ranges, list
+bool pt_kybool()
+int pt_kytype(), pt_kyinteger(), decode_ranges()
+real pt_kyreal()
+errchk pt_kytype(), pt_kybool(), pt_kyreal(), pt_kystr()
+
+begin
+ call smark (sp)
+ call salloc (root, SZ_FNAME, TY_CHAR)
+ call salloc (ranges, SZ_FNAME, TY_CHAR)
+ call salloc (list, 3 * KY_MAXNRANGES + 1, TY_INT)
+
+ # Select the field.
+ call strupr (field)
+ type = pt_kytype (key, field, Memc[root], Memc[ranges], maxnelems)
+ if (Memc[ranges] == EOS) {
+ nelems = 1
+ Memi[list] = 1
+ } else if (decode_ranges (Memc[ranges], Memi[list], KY_MAXNRANGES,
+ nelems) == ERR) {
+ call sfree (sp)
+ call error (0, "Cannot decode range string")
+ }
+
+ # Decode the value.
+ switch (type) {
+ case TY_BOOL:
+ if (nelems == 1) {
+ call xev_initop (o, 0, TY_BOOL)
+ O_VALB(o) = pt_kybool (key, Memc[root], Memi[list])
+ } else {
+ call sfree (sp)
+ call eprintf ("Error decoding boolean field array: %s\n")
+ call pargstr (field)
+ call error (0, "Boolean arrays not allowed in expressions.")
+ }
+ case TY_INT:
+ if (nelems == 1) {
+ call xev_initop (o, 0, TY_INT)
+ O_VALI(o) = pt_kyinteger (key, Memc[root], Memi[list])
+ } else {
+ call sfree (sp)
+ call eprintf ("Error decoding integer field array: %s\n")
+ call pargstr (field)
+ call error (0, "Integer arrays not allowed in expressions.")
+ }
+ case TY_REAL:
+ if (nelems == 1) {
+ call xev_initop (o, 0, TY_REAL)
+ O_VALR(o) = pt_kyreal (key, Memc[root], Memi[list])
+ } else {
+ call sfree (sp)
+ call eprintf ("Error decoding real array field: %s\n")
+ call pargstr (field)
+ call error (0, "Real arrays not allowed in expressions.")
+ }
+ default:
+ if (nelems == 1) {
+ call xev_initop (o, SZ_LINE, TY_CHAR)
+ call pt_kystr (key, Memc[root], Memi[list], O_VALC(o), SZ_LINE)
+ } else {
+ call eprintf ("Error decoding char array field: %s\n")
+ call sfree (sp)
+ call pargstr (field)
+ call error (0, "Character arrays not allowed in expressions.")
+ }
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/lib/pttables/ptgnfn.x b/noao/digiphot/lib/pttables/ptgnfn.x
new file mode 100644
index 00000000..f3d4ddcb
--- /dev/null
+++ b/noao/digiphot/lib/pttables/ptgnfn.x
@@ -0,0 +1,239 @@
+include <syserr.h>
+include <ctype.h>
+include "../ptkeysdef.h"
+
+define MAX_FIELDS 128
+define SZ_SBUF 1024
+define LEN_FNSTRUCT (10 + MAX_FIELDS)
+
+define FN_NENTRIES Memi[$1] # number of field names in list
+define FN_NEXT Memi[$1+1] # next string to be returned
+define FN_SBUF Memi[$1+2] # pointer to string buffer
+define FN_STRP Memi[$1+10+$2-1] # array of str ptrs
+
+define FN_FIELDNAME Memc[FN_STRP($1,$2)] # reference a string
+
+
+# PT_OFNL -- Procedure to decode the template.
+
+pointer procedure pt_ofnl (ap, template)
+
+pointer ap # image descriptor
+char template[ARB] # field name template
+
+int tp, nstr, ch, junk
+pointer sp, ip, op, rop, fn, pattern, patcode, ranges, nextch
+int patmake(), patmatch()
+errchk syserr
+
+begin
+ call smark (sp)
+ call salloc (pattern, SZ_FNAME, TY_CHAR)
+ call salloc (patcode, SZ_LINE, TY_CHAR)
+ call salloc (ranges, SZ_FNAME, TY_CHAR)
+
+ # Allocate field list descriptor and initialize.
+ call calloc (fn, LEN_FNSTRUCT, TY_STRUCT)
+ call malloc (FN_SBUF(fn), SZ_SBUF, TY_CHAR)
+ nextch = FN_SBUF(fn)
+ nstr = 0
+ tp = 1
+
+ # Extract each comma delimited template, expand upon the aphot
+ # database and add strings to list.
+
+ while (template[tp] != EOS && template[tp] != '\n') {
+
+ # Advance to next field.
+ while (IS_WHITE(template[tp]) || template[tp] == ',')
+ tp = tp + 1
+
+ # Extract pattern. Enclose pattern in {} so that the match will
+ # be case insensitive.
+
+ op = pattern
+ Memc[op] = '^'
+ op = op + 1
+ Memc[op] = '{'
+ op = op + 1
+
+ # Fetch the pattern.
+ ch = template[tp]
+ while (! (IS_WHITE(ch) || ch == '\n' || ch == ',' || ch == '[' ||
+ ch == EOS)) {
+
+ # Map "*" into "?*".
+ if (ch == '*') {
+ Memc[op] = '?'
+ op = op + 1
+ }
+
+ # Update.
+ Memc[op] = ch
+ op = op + 1
+ tp = tp + 1
+ ch = template[tp]
+ }
+
+ # Decode ranges.
+ if (ch == '[') {
+ rop = ranges
+ while (! (ch == '\n' || ch == EOS || ch == ']')) {
+ Memc[rop] = ch
+ rop = rop + 1
+ tp = tp + 1
+ ch = template[tp]
+ }
+ Memc[rop] = ']'
+ rop = rop + 1
+ tp = tp + 1
+ ch = template[tp]
+ while (ch != EOS && ch != '\n' && ch != ',' && IS_DIGIT(ch)) {
+ Memc[rop] = ch
+ tp = tp + 1
+ ch = template[tp]
+ rop = rop + 1
+ }
+ Memc[rop] = EOS
+ } else
+ Memc[ranges] = EOS
+
+ # Close off the pattern.
+ Memc[op] = '}'
+ op = op + 1
+ Memc[op] = EOS
+
+ # Encode the pattern.
+ junk = patmake (Memc[pattern], Memc[patcode], SZ_LINE)
+
+ # Scan database and extract all field names matching the
+ # pattern.
+
+ for (ip = KY_WORDS(ap) + 1; Memc[ip] != EOS; ip = ip + 1) {
+
+ # Put key in list if it matches.
+ if (patmatch (Memc[ip], Memc[patcode]) > 0) {
+ call pt_fnputkey (Memc[ip], Memc[ranges], FN_STRP(fn,1),
+ nstr, nextch, FN_SBUF(fn))
+ }
+
+ # Advance to the next record.
+ while (Memc[ip] != ',' && Memc[ip] != EOS)
+ ip = ip + 1
+
+ # Quit if you hit EOS
+ if (Memc[ip] == EOS)
+ break
+ }
+ }
+
+ FN_NENTRIES(fn) = nstr
+ FN_NEXT(fn) = 1
+ call sfree (sp)
+ return (fn)
+end
+
+
+# PT_GNFN -- Get the next field name matching the given template from the
+# apphot data base.
+
+int procedure pt_gnfn (fn, outstr, ranges, maxch)
+
+pointer fn # field name list descriptor
+char outstr[ARB] # output string
+char ranges[ARB] # ranges string
+int maxch # maximum number of characters
+
+char left_bkt
+int strnum, findex, nchars
+int gstrcpy(), stridx()
+data left_bkt /'['/
+
+begin
+ # Initialize.
+ ranges[1] = EOS
+ outstr[1] = EOS
+
+ # Check that there is an entry
+ strnum = FN_NEXT(fn)
+ if (strnum > FN_NENTRIES(fn))
+ return (EOF)
+
+ # Get the next field name.
+ nchars = gstrcpy (FN_FIELDNAME(fn,strnum), outstr, maxch)
+
+ # Get the ranges string.
+ findex = stridx (left_bkt, outstr)
+ if (findex > 0) {
+ call strcpy (outstr[findex], ranges, maxch)
+ outstr[findex] = EOS
+ }
+
+ # Increment counter.
+ FN_NEXT(fn) = strnum + 1
+
+ return (nchars)
+end
+
+
+# PT_CFNL -- Procedure to close the list.
+
+procedure pt_cfnl (fn)
+
+pointer fn # field name list descriptor
+
+begin
+ call mfree (FN_SBUF(fn), TY_CHAR)
+ call mfree (fn, TY_STRUCT)
+end
+
+
+
+# PT_FNPUTKEY -- Put a keyword into the keyword list.
+
+procedure pt_fnputkey (key, ranges, strp, nstr, nextch, sbuf)
+
+char key[ARB] # keyword name (etc.)
+char ranges[ARB] # list of ranges
+pointer strp[ARB] # array of string pointers
+int nstr # current number of strings
+pointer nextch # next available char in string buffer
+pointer sbuf # string buffer
+
+int ch, ip, rip
+errchk syserr
+
+begin
+ # Check size of string buffer.
+ nstr = nstr + 1
+ if (nstr > MAX_FIELDS)
+ call error (0, "There too many fields in the input template")
+
+ # Initialize.
+ strp[nstr] = nextch
+ ip = 1
+ ch = key[ip]
+
+ # Append keyword to the string buffer.
+ while (ch != ',' && ch != ' ' && ch != EOS) {
+ Memc[nextch] = ch
+ nextch = nextch + 1
+ if (nextch >= sbuf + SZ_SBUF)
+ call error (0, "There too many fields in the input template")
+ ip = ip + 1
+ ch = key[ip]
+ }
+
+ # Get the ranges information.
+ rip = 1
+ while (ranges[rip] != EOS) {
+ Memc[nextch] = ranges[rip]
+ nextch = nextch + 1
+ if (nextch >= sbuf + SZ_SBUF)
+ call error (0, "There too many fields in the input template")
+ rip = rip + 1
+ }
+
+ Memc[nextch] = EOS
+ nextch = nextch + 1
+end
diff --git a/noao/digiphot/lib/pttables/pthdrs.x b/noao/digiphot/lib/pttables/pthdrs.x
new file mode 100644
index 00000000..d3aeecf6
--- /dev/null
+++ b/noao/digiphot/lib/pttables/pthdrs.x
@@ -0,0 +1,235 @@
+include "../ptkeysdef.h"
+
+# PT_KNAME -- Procedure to add a name to the keyword structure
+
+procedure pt_kname (key, line, nchars, nunique)
+
+pointer key # pointer to keyword structure
+char line[ARB] # line to be decoded
+int nchars # number of characters in the line
+int nunique # number of #N lines
+
+int nkeys, onstore
+long optr
+pointer sp, id, keyword, temp
+int nscan(), strdic()
+
+begin
+ # Store the old number of keywords and the old values pointer.
+ onstore = KY_NSTORE(key)
+ optr = KY_VALUES(key)
+
+ # Check the buffer sizes.
+ if ((KY_NKEYS(key) + 1) > KY_NSTORE(key)) {
+ KY_NSTORE(key) = KY_NSTORE(key) + KY_NPARS
+ call realloc (KY_WORDS(key), KY_NSTORE(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_VALUES(key), KY_NSTORE(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_UNITS(key), KY_NSTORE(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_FORMATS(key), KY_NSTORE(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_TYPES(key), KY_NSTORE(key), TY_INT)
+ call realloc (KY_KINDICES(key), KY_NSTORE(key), TY_INT)
+ call realloc (KY_UINDICES(key), KY_NSTORE(key), TY_INT)
+ call realloc (KY_FINDICES(key), KY_NSTORE(key) + 1, TY_INT)
+ call realloc (KY_NELEMS(key), KY_NSTORE(key), TY_INT)
+ call aclri (Memi[KY_NELEMS(key)+onstore], KY_NSTORE(key) - onstore)
+ #lshift = KY_VALUES(key) - optr
+ call realloc (KY_PTRS(key), KY_NSTORE(key), TY_INT)
+ call aaddki (Memi[KY_PTRS(key)], KY_VALUES(key)- optr,
+ Memi[KY_PTRS(key)], onstore)
+ call amovki (NULL, Memi[KY_PTRS(key)+onstore], KY_NSTORE(key) -
+ onstore)
+ }
+
+ # Check the available space.
+ if (nunique > KY_NLINES) {
+ call realloc (KY_NPLINE(key), nunique, TY_INT)
+ call realloc (KY_NCONTINUE(key), nunique, TY_INT)
+ }
+
+ # Allocate space for the keywords.
+ call smark (sp)
+ call salloc (id, KY_SZPAR, TY_CHAR)
+ call salloc (keyword, KY_SZPAR, TY_CHAR)
+ call salloc (temp, KY_SZPAR, TY_CHAR)
+
+ # Scan the string and remove the id.
+ call sscan (line)
+ call gargwrd (Memc[id], KY_SZPAR)
+ if (nscan() != 1) {
+ call sfree (sp)
+ return
+ }
+
+ # Loop over the keywords.
+ nkeys = 0
+ call gargwrd (Memc[keyword], KY_SZPAR)
+ while (Memc[keyword] != EOS && Memc[keyword] != '\\') {
+ if (strdic (Memc[keyword], Memc[temp], KY_SZPAR,
+ Memc[KY_WORDS(key)]) == 0) {
+ nkeys = nkeys + 1
+ call pt_kykeywrd (Memc[keyword], KY_SZPAR, LEN_KWORDS(key),
+ Memc[KY_WORDS(key)])
+ }
+ call gargwrd (Memc[keyword], KY_SZPAR)
+ }
+
+ # Update.
+ #if (nunique == 1)
+ #KY_NOKEYS(key) = KY_NKEYS(key)
+ Memi[KY_NPLINE(key)+nunique-1] = nkeys
+ Memi[KY_NCONTINUE(key)+nunique-1] = 0
+ KY_NKEYS(key) = KY_NKEYS(key) + nkeys
+
+ call sfree (sp)
+end
+
+
+# PT_KNUNITS -- Procedure to add a unit name to the keyword structure.
+
+procedure pt_knunits (key, line, nchars, uunique)
+
+pointer key # pointer to keyword structure
+char line[ARB] # line to be decoded
+int nchars # number of characters in the line
+int uunique # number of #U lines
+
+int nkeys, onstore
+long optr
+pointer sp, id, units, temp
+int nscan()
+
+begin
+ # If there are no unique names for this line quit.
+ if (Memi[KY_NPLINE(key)+uunique-1] <= 0)
+ return
+
+ # Store old number of keywords and old values pointer.
+ onstore = KY_NSTORE(key)
+ optr = KY_VALUES(key)
+
+ # Check the buffer sizes.
+ if ((KY_NKEYS(key) + 1) > KY_NSTORE(key)) {
+ KY_NSTORE(key) = KY_NSTORE(key) + KY_NPARS
+ call realloc (KY_WORDS(key), KY_NSTORE(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_VALUES(key), KY_NSTORE(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_UNITS(key), KY_NSTORE(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_FORMATS(key), KY_NSTORE(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_TYPES(key), KY_NSTORE(key), TY_INT)
+ call realloc (KY_KINDICES(key), KY_NSTORE(key), TY_INT)
+ call realloc (KY_UINDICES(key), KY_NSTORE(key), TY_INT)
+ call realloc (KY_FINDICES(key), KY_NSTORE(key) + 1, TY_INT)
+ call realloc (KY_NELEMS(key), KY_NSTORE(key), TY_INT)
+ call aclri (Memi[KY_NELEMS(key)+onstore], KY_NSTORE(key) - onstore)
+ #lshift = KY_VALUES(key) - optr
+ call realloc (KY_PTRS(key), KY_NSTORE(key), TY_INT)
+ call aaddki (Memi[KY_PTRS(key)], KY_VALUES(key) - optr,
+ Memi[KY_PTRS(key)], onstore)
+ call amovki (NULL, Memi[KY_PTRS(key)+onstore], KY_NSTORE(key) -
+ onstore)
+ }
+
+ # Allocate space for the units.
+ call smark (sp)
+ call salloc (id, KY_SZPAR, TY_CHAR)
+ call salloc (units, KY_SZPAR, TY_CHAR)
+ call salloc (temp, KY_SZPAR, TY_CHAR)
+
+ # Scan the string and decode the elements.
+ call sscan (line)
+ call gargwrd (Memc[id], KY_SZPAR)
+
+ # Remove the id.
+ if (nscan() != 1) {
+ call sfree (sp)
+ return
+ }
+
+ # Loop over the units string.
+ if (uunique == 1)
+ nkeys = KY_NPKEYS(key)
+ call gargwrd (Memc[units], KY_SZPAR)
+ while (Memc[units] != EOS && Memc[units] != '\\') {
+ call pt_kyunits (Memc[units], KY_SZPAR, Memc[KY_UNITS(key)],
+ Memi[KY_UINDICES(key)], nkeys + 1)
+ nkeys = nkeys + 1
+ call gargwrd (Memc[units], KY_SZPAR)
+ }
+
+ call sfree (sp)
+end
+
+
+# PT_KNFORMATS -- Procedure to add a format to the keyword structure.
+
+procedure pt_knformats (key, line, nchars, funique)
+
+pointer key # pointer to keyword structure
+char line[ARB] # line to be decoded
+int nchars # number of characters in the line
+int funique # number of format lines
+
+int nkeys, onstore
+long optr
+pointer sp, id, format, temp
+int nscan()
+
+begin
+ # If there are no unique names for this line quit.
+ if (Memi[KY_NPLINE(key)+funique-1] <= 0)
+ return
+
+ # Store the old number of keywords and the old values pointer.
+ onstore = KY_NSTORE(key)
+ optr = KY_VALUES(key)
+
+ # Check the buffer sizes.
+ if ((KY_NKEYS(key) + 1) > KY_NSTORE(key)) {
+ KY_NSTORE(key) = KY_NSTORE(key) + KY_NPARS
+ call realloc (KY_WORDS(key), KY_NSTORE(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_VALUES(key), KY_NSTORE(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_UNITS(key), KY_NSTORE(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_FORMATS(key), KY_NSTORE(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_TYPES(key), KY_NSTORE(key), TY_INT)
+ call realloc (KY_KINDICES(key), KY_NSTORE(key), TY_INT)
+ call realloc (KY_UINDICES(key), KY_NSTORE(key), TY_INT)
+ call realloc (KY_FINDICES(key), KY_NSTORE(key) + 1, TY_INT)
+ call realloc (KY_NELEMS(key), KY_NSTORE(key), TY_INT)
+ call aclri (Memi[KY_NELEMS(key)+onstore], KY_NSTORE(key) - onstore)
+ #lshift = KY_VALUES(key) - optr
+ call realloc (KY_PTRS(key), KY_NSTORE(key), TY_INT)
+ call aaddki (Memi[KY_PTRS(key)], KY_VALUES(key) - optr,
+ Memi[KY_PTRS(key)], onstore)
+ call amovki (NULL, Memi[KY_PTRS(key)+onstore], KY_NSTORE(key) -
+ onstore)
+ }
+
+ # Allocate space for the keywords.
+ call smark (sp)
+ call salloc (id, KY_SZPAR, TY_CHAR)
+ call salloc (format, KY_SZPAR, TY_CHAR)
+ call salloc (temp, KY_SZPAR, TY_CHAR)
+
+ # Scan the string and decode the elements.
+ call sscan (line)
+ call gargwrd (Memc[id], KY_SZPAR)
+
+ # Remove the id.
+ if (nscan() != 1) {
+ call sfree (sp)
+ return
+ }
+
+ # Loop over the formats.
+ if (funique == 1)
+ nkeys = KY_NPKEYS(key)
+ call gargwrd (Memc[format], KY_SZPAR)
+ while (Memc[format] != EOS && Memc[format] != '\\') {
+ call pt_kyformat (Memc[format], KY_SZPAR, Memc[KY_FORMATS(key)],
+ Memi[KY_FINDICES(key)], Memi[KY_TYPES(key)], Memi[KY_PTRS(key)],
+ Memi[KY_KINDICES(key)], nkeys + 1)
+ nkeys = nkeys + 1
+ call gargwrd (Memc[format], KY_SZPAR)
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/lib/pttables/ptkeywords.x b/noao/digiphot/lib/pttables/ptkeywords.x
new file mode 100644
index 00000000..c636b8fd
--- /dev/null
+++ b/noao/digiphot/lib/pttables/ptkeywords.x
@@ -0,0 +1,615 @@
+include "../ptkeysdef.h"
+
+# PT_KYINIT -- Initilize the keyword structure.
+
+procedure pt_kyinit (key)
+
+pointer key # pointer to the keys structure
+
+begin
+ # Allocate space for structure and initialize constants.
+ call malloc (key, LEN_KEYSTRUCT, TY_STRUCT)
+ KY_NKEYS(key) = 0
+ KY_NPKEYS(key) = 0
+ KY_NSTORE(key) = KY_NPARS
+ LEN_KWORDS(key) = 0
+
+ # Allocate space for the string buffers.
+ call malloc (KY_WORDS(key), KY_SZPAR * KY_NPARS, TY_CHAR)
+ call malloc (KY_VALUES(key), KY_SZPAR * KY_NPARS, TY_CHAR)
+ call malloc (KY_UNITS(key), KY_SZPAR * KY_NPARS, TY_CHAR)
+ call malloc (KY_FORMATS(key), KY_SZPAR * KY_NPARS, TY_CHAR)
+
+ # Allocate space for the indices buffers and initialize.
+ call malloc (KY_PTRS(key), KY_NPARS, TY_INT)
+ call malloc (KY_KINDICES(key), KY_NPARS, TY_INT)
+ call malloc (KY_UINDICES(key), KY_NPARS, TY_INT)
+ call malloc (KY_FINDICES(key), KY_NPARS + 1, TY_INT)
+ call calloc (KY_NELEMS(key), KY_NPARS, TY_INT)
+ call malloc (KY_TYPES(key), KY_NPARS, TY_INT)
+ call calloc (KY_NPLINE(key), KY_NLINES, TY_INT)
+ call calloc (KY_NCONTINUE(key), KY_NLINES, TY_INT)
+ Memi[KY_PTRS(key)] = KY_VALUES(key)
+ call amovki (NULL, Memi[KY_PTRS(key)+1], KY_NPARS - 1)
+
+ # Initialize the select buffers.
+ KY_SELECT(key) = NULL
+ KY_ELEM_SELECT(key) = NULL
+ KY_LEN_SELECT(key) = NULL
+ KY_NAME_SELECT(key) = NULL
+ KY_UNIT_SELECT(key) = NULL
+ KY_FMT_SELECT(key) = NULL
+
+ # Initilize the strings.
+ Memc[KY_WORDS(key)] = EOS
+ Memc[KY_VALUES(key)] = EOS
+ Memc[KY_UNITS(key)] = EOS
+ Memc[KY_FORMATS(key)] = EOS
+end
+
+
+# PT_KYFREE -- Procedure to free the keywords structure.
+
+procedure pt_kyfree (key)
+
+pointer key # pointer to keyword structure
+
+int i
+pointer ptr
+
+begin
+ # Free the string buffers.
+ if (KY_WORDS(key) != NULL)
+ call mfree (KY_WORDS(key), TY_CHAR)
+ if (KY_VALUES(key) != NULL)
+ call mfree (KY_VALUES(key), TY_CHAR)
+ if (KY_UNITS(key) != NULL)
+ call mfree (KY_UNITS(key), TY_CHAR)
+ if (KY_FORMATS(key) != NULL)
+ call mfree (KY_FORMATS(key), TY_CHAR)
+
+ # Free the indices buffers.
+ if (KY_TYPES(key) != NULL)
+ call mfree (KY_TYPES(key), TY_INT)
+ if (KY_KINDICES(key) != NULL)
+ call mfree (KY_KINDICES(key), TY_INT)
+ if (KY_UINDICES(key) != NULL)
+ call mfree (KY_UINDICES(key), TY_INT)
+ if (KY_FINDICES(key) != NULL)
+ call mfree (KY_FINDICES(key), TY_INT)
+ if (KY_PTRS(key) != NULL) {
+ do i = 1, KY_NSTORE(key) {
+ ptr = Memi[KY_PTRS(key)+i-1]
+ if (ptr != NULL && Memi[KY_NELEMS(key)+i-1] > 1)
+ call mfree (ptr, TY_CHAR)
+ }
+ call mfree (KY_PTRS(key), TY_INT)
+ }
+ if (KY_NELEMS(key) != NULL)
+ call mfree (KY_NELEMS(key), TY_INT)
+ if (KY_NPLINE(key) != NULL)
+ call mfree (KY_NPLINE(key), TY_INT)
+ if (KY_NCONTINUE(key) != NULL)
+ call mfree (KY_NCONTINUE(key), TY_INT)
+
+ # Free the select buffers.
+ if (KY_SELECT(key) != NULL)
+ call mfree (KY_SELECT(key), TY_INT)
+ if (KY_ELEM_SELECT(key) != NULL)
+ call mfree (KY_ELEM_SELECT(key), TY_INT)
+ if (KY_LEN_SELECT(key) != NULL)
+ call mfree (KY_LEN_SELECT(key), TY_INT)
+ if (KY_NAME_SELECT(key) != NULL)
+ call mfree (KY_NAME_SELECT(key), TY_CHAR)
+ if (KY_UNIT_SELECT(key) != NULL)
+ call mfree (KY_UNIT_SELECT(key), TY_CHAR)
+ if (KY_FMT_SELECT(key) != NULL)
+ call mfree (KY_FMT_SELECT(key), TY_CHAR)
+
+ call mfree (key, TY_STRUCT)
+end
+
+
+# PT_KYADD -- Procedure to add a parameter to the keyword structure.
+
+procedure pt_kyadd (key, line, nchars)
+
+pointer key # pointer to keyword structure
+char line[ARB] # line to be decoded
+int nchars # number of characters in the line
+
+int index, onstore
+long optr
+pointer sp, id, keyword, equals, value, units, format, temp
+int nscan(), strdic()
+
+begin
+ # Check the buffer sizes.
+ onstore = KY_NSTORE(key)
+ optr = KY_VALUES(key)
+ if ((KY_NKEYS(key) + 1) > KY_NSTORE(key)) {
+ KY_NSTORE(key) = KY_NSTORE(key) + KY_NPARS
+ call realloc (KY_WORDS(key), KY_NSTORE(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_VALUES(key), KY_NSTORE(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_UNITS(key), KY_NSTORE(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_FORMATS(key), KY_NSTORE(key) * KY_SZPAR, TY_CHAR)
+ call realloc (KY_NELEMS(key), KY_NSTORE(key), TY_INT)
+ call aclri (Memi[KY_NELEMS(key)+onstore], KY_NSTORE(key) - onstore)
+ call realloc (KY_PTRS(key), KY_NSTORE(key), TY_INT)
+ call aaddki (Memi[KY_PTRS(key)], KY_VALUES(key) - optr,
+ Memi[KY_PTRS(key)], onstore)
+ call amovki (NULL, Memi[KY_PTRS(key)+onstore], KY_NSTORE(key) -
+ onstore)
+ call realloc (KY_TYPES(key), KY_NSTORE(key), TY_INT)
+ call realloc (KY_KINDICES(key), KY_NSTORE(key), TY_INT)
+ call realloc (KY_UINDICES(key), KY_NSTORE(key), TY_INT)
+ call realloc (KY_FINDICES(key), KY_NSTORE(key) + 1, TY_INT)
+ }
+
+ # Allocate space for the keywords.
+ call smark (sp)
+ call salloc (id, KY_SZPAR, TY_CHAR)
+ call salloc (keyword, KY_SZPAR, TY_CHAR)
+ call salloc (equals, KY_SZPAR, TY_CHAR)
+ call salloc (value, KY_SZPAR, TY_CHAR)
+ call salloc (units, KY_SZPAR, TY_CHAR)
+ call salloc (format, KY_SZPAR, TY_CHAR)
+ call salloc (temp, KY_SZPAR, TY_CHAR)
+
+ # Scan the string and decode the elements.
+ call sscan (line)
+ call gargwrd (Memc[id], KY_SZPAR)
+ call gargwrd (Memc[keyword], KY_SZPAR)
+ call gargwrd (Memc[equals], KY_SZPAR)
+ call gargwrd (Memc[value], KY_SZPAR)
+ call gargwrd (Memc[units], KY_SZPAR)
+ call gargwrd (Memc[format], KY_SZPAR)
+
+ # Return if insufficient number of elements.
+ if (nscan() < 6) {
+ call sfree (sp)
+ return
+ }
+
+ # Add the parameters.
+ index = strdic (Memc[keyword], Memc[temp], KY_SZPAR,
+ Memc[KY_WORDS(key)])
+ if (index == 0) {
+ KY_NPKEYS(key) = KY_NPKEYS(key) + 1
+ KY_NKEYS(key) = KY_NKEYS(key) + 1
+ Memi[KY_NELEMS(key)+KY_NKEYS(key)-1] = 1
+ call pt_kykeywrd (Memc[keyword], KY_SZPAR, LEN_KWORDS(key),
+ Memc[KY_WORDS(key)])
+ call pt_kyunits (Memc[units], KY_SZPAR, Memc[KY_UNITS(key)],
+ Memi[KY_UINDICES(key)], KY_NKEYS(key))
+ call pt_kyformat (Memc[format], KY_SZPAR, Memc[KY_FORMATS(key)],
+ Memi[KY_FINDICES(key)], Memi[KY_TYPES(key)], Memi[KY_PTRS(key)],
+ Memi[KY_KINDICES(key)], KY_NKEYS(key))
+ call pt_kyvalue (Memc[value], KY_SZPAR, Memc[KY_VALUES(key)],
+ Memi[KY_PTRS(key)], Memi[KY_KINDICES(key)], KY_NKEYS(key))
+ } else
+ call pt_kyaddval (Memc[value], KY_SZPAR, Memc[KY_VALUES(key)],
+ Memi[KY_PTRS(key)], Memi[KY_KINDICES(key)], index)
+
+ call sfree (sp)
+end
+
+
+# PT_KYKEYWRD -- Procedure to encode a single keyword into the keyword
+# dictionary.
+
+procedure pt_kykeywrd (keyword, maxch, klength, kdic)
+
+char keyword[ARB] # the keyword to be added to the list
+int maxch # maximum length of keyword
+int klength # the current length of the dictionary
+char kdic[ARB] # the keyword dictionary
+
+int kp, ip
+
+begin
+ # Insert leading , for record delimiter.
+ kp = klength + 1
+ if (kp == 1) {
+ kdic[kp] = ','
+ kp = kp + 1
+ }
+
+ # Copy the keyword.
+ for (ip = 1; ip <= maxch && keyword[ip] != EOS; ip = ip + 1) {
+ kdic[kp] = keyword[ip]
+ kp = kp + 1
+ }
+ kdic[kp] = ','
+ kdic[kp+1] = EOS
+
+ klength = kp
+end
+
+
+# PT_KYUNITS -- Procedure to add a units name to the units string.
+
+procedure pt_kyunits (ustr, maxch, units, uindices, nkey)
+
+char ustr[ARB] # units string
+int maxch # max length of units string
+char units[ARB] # units string
+int uindices[ARB] # units indices
+int nkey # current unit
+
+int ip, up
+
+begin
+ # Get initial position.
+ if (nkey == 1)
+ up = 1
+ else
+ up = uindices[nkey-1] + 1
+
+ # Copy the units string.
+ for (ip = 1; ip <= maxch && ustr[ip] != EOS; ip = ip + 1) {
+ units[up] = ustr[ip]
+ up = up + 1
+ }
+ units[up] = EOS
+
+ uindices[nkey] = up - 1
+end
+
+
+# PT_KYFORMAT -- Procedure to encode the formats and field widths.
+
+procedure pt_kyformat (fstr, maxch, formats, findices, types, ptrs, fields,
+ key)
+
+char fstr[ARB] # format string
+int maxch # maximum number of characters
+char formats[ARB] # format string
+int findices[ARB] # string pointers
+int types[ARB] # data type of key
+pointer ptrs[ARB] # array of pointers
+int fields[ARB] # integer field widths
+int key # key number
+
+char cjunk
+int ip, fp, fwidth, junk, ftype
+int pt_kyfstr(), strlen()
+
+begin
+ # Set the pointer.
+ if (key > 1)
+ ptrs[key] = ptrs[key-1] + fields[key-1]
+
+ # Find the initial position.
+ if (key == 1)
+ fp = 1
+ else
+ fp = findices[key-1] + 1
+
+ # Crack the format string.
+ if (pt_kyfstr (fstr, fwidth, junk, ftype, cjunk) == ERR) {
+ fields[key] = KY_SZPAR
+ types[key] = TY_CHAR
+ #if (key > 1)
+ #ptrs[key] = ptrs[key-1] + fwidth
+ call sprintf (formats[fp], maxch, "%s%ds")
+ call pargstr ("%")
+ call pargi (-KY_SZPAR)
+ fp = fp + strlen (formats[fp])
+ } else {
+ fields[key] = fwidth
+ types[key] = ftype
+ #if (key > 1)
+ #ptrs[key] = ptrs[key-1] + fields[key-1]
+ for (ip = 1; ip <= maxch && fstr[ip] != EOS; ip = ip + 1) {
+ formats[fp] = fstr[ip]
+ fp = fp + 1
+ }
+ formats[fp] = EOS
+ }
+
+ findices[key] = fp - 1
+end
+
+
+# PT_KYVALUE -- Procedure to store the parameter value.
+
+procedure pt_kyvalue (vstr, maxch, values, ptrs, kindices, key)
+
+char vstr[ARB] # value string
+int maxch # maximum number of characters
+char values[ARB] # values string
+pointer ptrs[ARB] # array of pointers
+int kindices[ARB] # storage points in the string
+int key # parameter
+
+int ip, vp
+
+begin
+ # Find the initial position.
+ if (key == 1)
+ vp = 1
+ else
+ vp = ptrs[key] - ptrs[1] + 1
+
+ # Copy the value string.
+ for (ip = 1; ip <= maxch && vstr[ip] != EOS; ip = ip + 1) {
+ values[vp] = vstr[ip]
+ vp = vp + 1
+ }
+ for (; ip <= kindices[key]; ip = ip + 1) {
+ values[vp] = ' '
+ vp = vp + 1
+ }
+ values[vp] = EOS
+end
+
+
+# PT_KYADDVAL -- Change the value of an existing keyword.
+
+procedure pt_kyaddval (vstr, maxch, values, ptrs, kindices, key)
+
+char vstr[ARB] # value string
+int maxch # maximum number of characters
+char values[ARB] # values string
+pointer ptrs[ARB] # array of pointers
+int kindices[ARB] # storage points in the string
+int key # parameter
+
+int ip, vp
+
+begin
+ # Find the initial position.
+ if (key == 1)
+ vp = 1
+ else
+ vp = ptrs[key] - ptrs[1] + 1
+
+ # Insert the new value.
+ for (ip = 1; ip <= maxch && vstr[ip] != EOS; ip = ip + 1) {
+ values[vp] = vstr[ip]
+ vp = vp + 1
+ }
+ for (; ip <= kindices[key]; ip = ip + 1) {
+ values[vp] = ' '
+ vp = vp + 1
+ }
+end
+
+
+# PT_KYFSTR -- Procedure to decode the format string.
+
+int procedure pt_kyfstr (fstr, width, precision, type, ctype)
+
+char fstr[ARB] # format string
+int width # field width
+int precision # precision
+int type # data type
+char ctype # char format type
+
+int ip
+int ctoi
+
+begin
+ if (fstr[1] != '%')
+ return (ERR)
+
+ # Get the field width.
+ ip = 2
+ if (ctoi (fstr, ip, width) == ERR)
+ return (ERR)
+ width = abs (width)
+
+ # Get the precision.
+ if (fstr[ip] == '.')
+ ip = ip + 1
+ if (ctoi (fstr, ip, precision) == ERR)
+ precision = 0
+
+ # Get the datatype.
+ if (fstr[ip] == 'f' || fstr[ip] == 'g') {
+ type = TY_REAL
+ ctype = fstr[ip]
+ } else if (fstr[ip] == 'd') {
+ type = TY_INT
+ ctype = 'd'
+ } else if (fstr[ip] == 's') {
+ type = TY_CHAR
+ ctype = 's'
+ } else if (fstr[ip] == 'b') {
+ type = TY_BOOL
+ ctype = 'b'
+ } else
+ return (ERR)
+ return (OK)
+end
+
+
+# PT_KYTYPE -- Procedure to get the data type of a field.
+
+int procedure pt_kytype (key, field, root, ranges, maxels)
+
+pointer key # pointer to field strucuture
+char field[ARB] # field for which type is to be extracted
+char root[ARB] # root variable name
+char ranges[ARB] # range of selected elements
+int maxels # maximum number of elements
+
+char left_bkt, right_bkt
+int findex, lindex, index
+pointer sp, temp
+int stridx(), strdic()
+data left_bkt /'['/, right_bkt /']'/
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (temp, SZ_FNAME, TY_CHAR)
+ root[1] = EOS
+ ranges[1] = EOS
+
+ # Get the root name.
+ findex = stridx (left_bkt, field)
+ if (findex == 0)
+ call strcpy (field, root, SZ_FNAME)
+ else
+ call strcpy (field, root, findex - 1)
+
+ # Find the appropriate keyword.
+ index = strdic (root, Memc[temp], SZ_LINE, Memc[KY_WORDS(key)])
+ call sfree (sp)
+
+ # Return the root, ranges and type.
+ if (index != 0) {
+ maxels = Memi[KY_NELEMS(key)+index-1]
+ lindex = stridx (right_bkt, field)
+ if ((lindex - findex - 1) > 0)
+ call strcpy (field[findex+1], ranges, lindex - findex - 1)
+ if (ranges[1] == EOS && maxels > 1)
+ call sprintf (ranges, SZ_FNAME, "1-%d")
+ call pargi (maxels)
+ return (Memi[KY_TYPES(key)+index-1])
+ } else
+ call error (0, "Unknown keyword in expression")
+end
+
+
+# PT_KYBOOL -- Procedure to get a boolean parameter.
+
+bool procedure pt_kybool (key, field, element)
+
+pointer key # pointer to keys structure
+char field[ARB] # parameter name
+int element # element of int array
+
+int index
+pointer sp, temp, ptr
+int strmatch()
+pointer strdic()
+
+begin
+ call smark (sp)
+ call salloc (temp, SZ_LINE, TY_CHAR)
+ index = strdic (field, Memc[temp], SZ_LINE, Memc[KY_WORDS(key)])
+ call sfree (sp)
+
+ if (index != 0) {
+ if (Memi[KY_NELEMS(key)+index-1] == 1)
+ ptr = Memi[KY_PTRS(key)+index-1]
+ else
+ ptr = Memi[KY_PTRS(key)+index-1] + (element - 1) *
+ Memi[KY_KINDICES(key)+index-1]
+ if (strmatch (Memc[ptr], "yes") == 0)
+ return (false)
+ else
+ return (true)
+ } else
+ call error (0, "Unknown boolean keyword in expression")
+end
+
+
+# PT_KYINTEGER -- Procedure to get an integer parameter.
+
+int procedure pt_kyinteger (key, field, element)
+
+pointer key # pointer to keys structure
+char field[ARB] # parameter name
+int element # element of int array
+
+int index, ip, ival
+pointer sp, temp, ptr
+int ctoi()
+pointer strdic()
+
+begin
+ call smark (sp)
+ call salloc (temp, SZ_LINE, TY_CHAR)
+ index = strdic (field, Memc[temp], SZ_LINE, Memc[KY_WORDS(key)])
+ call sfree (sp)
+
+ if (index != 0) {
+ if (Memi[KY_NELEMS(key)+index-1] == 1)
+ ptr = Memi[KY_PTRS(key)+index-1]
+ else
+ ptr = Memi[KY_PTRS(key)+index-1] + (element - 1) *
+ Memi[KY_KINDICES(key)+index-1]
+ ip = 1
+ if (ctoi (Memc[ptr], ip, ival) == 0)
+ call error (0, "Cannot decode integer parameter")
+ else
+ return (ival)
+ } else
+ call error (0, "Unknown integer keyword in expression")
+end
+
+
+# PT_KYREAL -- Procedure to get a real parameter.
+
+real procedure pt_kyreal (key, field, element)
+
+pointer key # pointer to keys structure
+char field[ARB] # parameter name
+int element # which element to extract
+
+int index, ip
+pointer sp, temp, ptr
+real rval
+int ctor()
+pointer strdic()
+
+begin
+ call smark (sp)
+ call salloc (temp, SZ_LINE, TY_CHAR)
+ index = strdic (field, Memc[temp], SZ_LINE, Memc[KY_WORDS(key)])
+ call sfree (sp)
+
+ if (index != 0) {
+ if (Memi[KY_NELEMS(key)+index-1] == 1)
+ ptr = Memi[KY_PTRS(key)+index-1]
+ else
+ ptr = Memi[KY_PTRS(key)+index-1] + (element - 1) *
+ Memi[KY_KINDICES(key)+index-1]
+ ip = 1
+ if (ctor (Memc[ptr], ip, rval) <= 0)
+ call error (0, "Cannot decode real parameter")
+ else
+ return (rval)
+ } else
+ call error (0, "Unknown real keyword in expression")
+end
+
+
+# PT_KYSTR -- Procedure to get a string parameter.
+
+procedure pt_kystr (key, field, element, str, maxch)
+
+pointer key # pointer to keys structure
+char field[ARB] # parameter name
+int element # element of the array
+char str[ARB] # output string
+int maxch # maximum number of character
+
+int index, nk
+pointer sp, temp, ptr
+pointer strdic()
+
+begin
+ call smark (sp)
+ call salloc (temp, SZ_LINE, TY_CHAR)
+ index = strdic (field, Memc[temp], SZ_LINE, Memc[KY_WORDS(key)])
+ call sfree (sp)
+
+ if (index != 0) {
+ if (Memi[KY_NELEMS(key)+index-1] == 1)
+ ptr = Memi[KY_PTRS(key)+index-1]
+ else
+ ptr = Memi[KY_PTRS(key)+index-1] + (element - 1) *
+ Memi[KY_KINDICES(key)+index-1]
+ for (; Memc[ptr] == ' ';)
+ ptr = ptr + 1
+ for (nk = 0; Memc[ptr+nk] != ' '; nk = nk + 1)
+ ;
+ call strcpy (Memc[ptr], str, min (nk, maxch))
+ } else
+ call error (0, "Unknown string keyword in expression")
+end
diff --git a/noao/digiphot/lib/pttables/ptkid.x b/noao/digiphot/lib/pttables/ptkid.x
new file mode 100644
index 00000000..8b4aafcb
--- /dev/null
+++ b/noao/digiphot/lib/pttables/ptkid.x
@@ -0,0 +1,26 @@
+# PT_KID -- Decode a column specification into a name and an element.
+
+procedure pt_kid (column, name, element)
+
+char column[ARB] # column name
+char name[ARB] # column name
+int element # column element
+
+char left_bracket
+int index
+int stridx(), ctoi()
+data left_bracket /'['/
+
+begin
+ # Get the proper name in upper case and strip off and subscript.
+ call strcpy (column, name, SZ_FNAME)
+ call strupr (name)
+ index = stridx (left_bracket, name)
+ if (index > 0) {
+ name[index] = EOS
+ index = index + 1
+ if (ctoi (column, index, element) < 0)
+ element = 1
+ } else
+ element = 1
+end
diff --git a/noao/digiphot/lib/pttables/ptkstat.x b/noao/digiphot/lib/pttables/ptkstat.x
new file mode 100644
index 00000000..077afaf6
--- /dev/null
+++ b/noao/digiphot/lib/pttables/ptkstat.x
@@ -0,0 +1,137 @@
+include "../ptkeysdef.h"
+
+# PT_KSTATI -- Get an integer parameter from the keyword structure.
+
+int procedure pt_kstati (key, column, parameter)
+
+pointer key # pointer to the database strucuture
+char column[ARB] # column name
+int parameter # parameter to be returned
+
+char left_bracket
+int index, element, value
+pointer sp, kname
+int strdic(), stridx(), ctoi()
+data left_bracket /'['/
+
+begin
+ call smark (sp)
+ call salloc (kname, KY_SZPAR, TY_CHAR)
+
+ # Get the proper name in upper case and strip off the subscript.
+ call strcpy (column, Memc[kname], KY_SZPAR)
+ call strupr (Memc[kname])
+ index = stridx (left_bracket, Memc[kname])
+ if (index > 0) {
+ Memc[kname+index-1] = EOS
+ index = index + 1
+ if (ctoi (column, index, element) < 0)
+ element = 1
+ } else
+ element = 1
+
+ # Find the field.
+ index = strdic (Memc[kname], Memc[kname], KY_SZPAR, Memc[KY_WORDS(key)])
+
+ # Fetch the parameter.
+ switch (parameter) {
+ case KY_INDEX:
+ value = index
+ case KY_DATATYPE:
+ if (index > 0)
+ value = Memi[KY_TYPES(key)+index-1]
+ else
+ value = INDEFI
+ case KY_LENGTH:
+ if (index > 0)
+ value = Memi[KY_KINDICES(key)+index-1]
+ else
+ value = INDEFI
+ case KY_ELEMENT:
+ if (index <= 0)
+ value = INDEFI
+ else if (element >= 1 && element <= Memi[KY_NELEMS(key)+index-1])
+ value = element
+ else
+ value = INDEFI
+ case KY_NUMELEMS:
+ value = Memi[KY_NELEMS(key)+index-1]
+ default:
+ value = INDEFI
+ }
+
+ call sfree (sp)
+
+ return (value)
+end
+
+
+# PT_KSTATS -- Get a string parameter from the keyword structure.
+
+procedure pt_kstats (key, column, parameter, str, maxch)
+
+pointer key # pointer to the database strucuture
+char column[ARB] # column name
+int parameter # parameter to be returned
+char str[ARB] # output string
+int maxch # maximum number of characters
+
+char left_bracket
+int index, element, ip, len
+pointer sp, kname
+int strdic(), stridx(), ctoi()
+data left_bracket /'['/
+
+begin
+ call smark (sp)
+ call salloc (kname, KY_SZPAR, TY_CHAR)
+
+ # Get the proper name in upper case and strip off the subscript.
+ call strcpy (column, Memc[kname], KY_SZPAR)
+ call strupr (Memc[kname])
+ index = stridx (left_bracket, Memc[kname])
+ if (index > 0) {
+ Memc[kname+index-1] = EOS
+ index = index + 1
+ if (ctoi (column, index, element) < 0)
+ element = 1
+ } else
+ element = 1
+
+ # Find the field.
+ index = strdic (Memc[kname], Memc[kname], KY_SZPAR, Memc[KY_WORDS(key)])
+
+ # Fetch the parameter.
+ switch (parameter) {
+ case KY_UNITSTR:
+ if (index <= 0) {
+ str[1] = EOS
+ } else if (index == 1) {
+ ip = 1
+ len = Memi[KY_UINDICES(key)]
+ call strcpy (Memc[KY_UNITS(key)+ip-1], str, len)
+ } else {
+ ip = Memi[KY_UINDICES(key)+index-2] + 1
+ len = Memi[KY_UINDICES(key)+index-1] -
+ Memi[KY_UINDICES(key)+index-2]
+ call strcpy (Memc[KY_UNITS(key)+ip-1], str, len)
+ }
+ case KY_FMTSTR:
+ if (index <= 0) {
+ str[1] = EOS
+ } else if (index == 1) {
+ ip = 1
+ len = Memi[KY_FINDICES(key)]
+ call strcpy (Memc[KY_FORMATS(key)+ip-1], str, len)
+ } else {
+ ip = Memi[KY_FINDICES(key)+index-2] + 1
+ len = Memi[KY_FINDICES(key)+index-1] -
+ Memi[KY_FINDICES(key)+index-2]
+ call strcpy (Memc[KY_FORMATS(key)+ip-1], str, len)
+ }
+ default:
+ str[1] = EOS
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/lib/pttables/ptmkrec.x b/noao/digiphot/lib/pttables/ptmkrec.x
new file mode 100644
index 00000000..a091812f
--- /dev/null
+++ b/noao/digiphot/lib/pttables/ptmkrec.x
@@ -0,0 +1,86 @@
+include "../ptkeysdef.h"
+
+# PT_MKREC -- Construct the output record.
+
+procedure pt_mkrec (key, line, nchars, first_rec, recptr, ncontinue)
+
+pointer key # pointer to record structure
+char line[ARB] # input line
+int nchars # length of line array
+int first_rec # first record read
+int recptr # line per record index
+int ncontinue # number of unique lines per record
+
+int i, cip, nokeys, nckeys, nkeys, nper_line, len_move
+pointer op
+
+begin
+ # Reinitialize if this is the start of a new record.
+ if (recptr == 1)
+ nokeys = KY_NPKEYS(key)
+
+ # Check repeat character.
+ if (line[nchars-2] == '*')
+ ncontinue = ncontinue + 1
+ else
+ ncontinue = 0
+
+ # Fill in the record.
+ cip = 1
+ if (ncontinue < 1) {
+
+ nper_line = Memi[KY_NPLINE(key)+recptr-1]
+ nkeys = nokeys + nper_line
+ call amovki (int(1), Memi[KY_NELEMS(key)+nokeys], nper_line)
+
+ len_move = 0
+ do i = nokeys + 1, nkeys
+ len_move = len_move + Memi[KY_KINDICES(key)+i-1]
+ op = Memi[KY_PTRS(key)+nokeys]
+ call amovc (line[cip], Memc[op], len_move)
+
+ cip = cip + len_move
+ recptr = recptr + 1
+ nokeys = nkeys
+
+ } else if (ncontinue == 1) {
+
+ nckeys = nokeys + 1
+ nkeys = nokeys + Memi[KY_NPLINE(key)+recptr-1]
+
+ if (first_rec == YES) {
+ Memi[KY_NCONTINUE(key)+recptr-1] = KY_NLINES
+ do i = nckeys, nkeys
+ call malloc (Memi[KY_PTRS(key)+i-1], KY_NLINES *
+ Memi[KY_KINDICES(key)+i-1], TY_CHAR)
+ }
+
+ do i = nckeys, nkeys {
+ call amovc (line[cip], Memc[Memi[KY_PTRS(key)+i-1]],
+ Memi[KY_KINDICES(key)+i-1])
+ cip = cip + Memi[KY_KINDICES(key)+i-1]
+ }
+
+ nokeys = nkeys
+ recptr = recptr + 1
+
+ } else {
+
+ if (ncontinue > Memi[KY_NCONTINUE(key)+recptr-2]) {
+ Memi[KY_NCONTINUE(key)+recptr-2] = Memi[KY_NCONTINUE(key)+
+ recptr-2] + KY_NLINES
+ do i = nckeys, nkeys
+ call realloc (Memi[KY_PTRS(key)+i-1],
+ Memi[KY_NCONTINUE(key)+recptr-2] *
+ Memi[KY_KINDICES(key)+i-1], TY_CHAR)
+ }
+
+ do i = nckeys, nkeys {
+ op = Memi[KY_PTRS(key)+i-1] + (ncontinue - 1) *
+ Memi[KY_KINDICES(key)+i-1]
+ call amovc (line[cip], Memc[op], Memi[KY_KINDICES(key)+i-1])
+ Memi[KY_NELEMS(key)+i-1] = ncontinue
+ cip = cip + Memi[KY_KINDICES(key)+i-1]
+ }
+ }
+end
diff --git a/noao/digiphot/lib/pttables/ptranges.x b/noao/digiphot/lib/pttables/ptranges.x
new file mode 100644
index 00000000..7f37de19
--- /dev/null
+++ b/noao/digiphot/lib/pttables/ptranges.x
@@ -0,0 +1,38 @@
+# PT_RANGES -- Procedure to convert apphot ranges to the format expected
+# by the xtools ranges package.
+
+int procedure pt_ranges (aranges, ranges, element, maxch)
+
+char aranges[ARB] # input ranges
+char ranges[ARB] # output ranges
+int element # range element
+int maxch # maximum number of characters in ranges
+
+char left_bkt, right_bkt
+int findex, lindex, nchars, ip
+int stridx(), ctoi()
+data left_bkt /'['/, right_bkt /']'/
+
+begin
+ # Test for existence of ranges.
+ element = 1
+ ranges[1] = EOS
+ if (aranges[1] == EOS)
+ return (OK)
+
+ # Test for range delimiters.
+ findex = stridx (left_bkt, aranges)
+ lindex = stridx (right_bkt, aranges)
+ if (findex == 0 || lindex == 0 || (lindex <= findex + 1))
+ return (ERR)
+
+ # Compute the element selection.
+ ip = 1
+ nchars = ctoi (aranges[findex+1], ip, element)
+ if (nchars == 0)
+ element = 1
+
+ # Copy the ranges portion.
+ call strcpy (aranges[findex+1], ranges, lindex - findex - 1)
+ return (OK)
+end
diff --git a/noao/digiphot/mkpkg b/noao/digiphot/mkpkg
new file mode 100644
index 00000000..3e51f04c
--- /dev/null
+++ b/noao/digiphot/mkpkg
@@ -0,0 +1,14 @@
+# Make the DIGIPHOT package.
+
+update:
+ $echo "---------------- DIGIPHOT.LIB ---------------------"
+ $call update@lib
+ $echo "---------------- DIGIPHOT.APPHOT ------------------"
+ $call update@apphot
+ $echo "---------------- DIGIPHOT.DAOPHOT -----------------"
+ $call update@daophot
+ $echo "---------------- DIGIPHOT.PHOTCAL -----------------"
+ $call update@photcal
+ $echo "---------------- DIGIPHOT.PTOOLS ------------------"
+ $call update@ptools
+ ;
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
diff --git a/noao/digiphot/ptools/README b/noao/digiphot/ptools/README
new file mode 100644
index 00000000..2a2e5597
--- /dev/null
+++ b/noao/digiphot/ptools/README
@@ -0,0 +1,23 @@
+ The Photometry Tools Package
+ -------------------------------
+
+The ptools package contains routines which perform oerations on the
+text database files and/or ST binary tables files produced by the APPHOT
+and DAOPHOT packages, and scripts which make the fact that any given database
+is a table or a text file transparent to the user.
+
+The ptools directory structure is listed below. The .h files are all in lib
+as many of them are shared by several tasks.
+
+ |-pconvert------routines to the pconvert task
+ |-doc-----------ptools documentation
+|-ptools-----|-lib-----------ptools definitions or .h files
+ |-pexamine------routines specific to the pexamine task
+ |-ptutils-------routines specific to miscellneous utility tasks
+ |-txtools-------routines specific to the text file operators
+ |-test----------directory of test data
+
+
+Lindsey Davis
+NOAO IRAF GROUP
+August 1991
diff --git a/noao/digiphot/ptools/Revisions b/noao/digiphot/ptools/Revisions
new file mode 100644
index 00000000..14287582
--- /dev/null
+++ b/noao/digiphot/ptools/Revisions
@@ -0,0 +1,395 @@
+.help revisions Jan90 noao.digiphot.ptools
+.nf
+
+ptools$pconvert/ptdeftable.x
+ pt_kstati() was being declared pointer instead of int (7/13/09, MJF)
+
+ptools$pexamine/ptsetup.x
+ pt_getnames() was declared a pointer instead of int (7/12/09, MJF)
+
+ptools$pconvert/ptconvert.x
+ptools$pconvert/txtools/ptxcalc.x
+ptools$pconvert/txtools/ptxdump.x
+ptools$pconvert/txtools/ptxselect.x
+ Added missing xev_freeop calls to the pconvert, txcalc, txdump, and
+ txselect tasks so that memory is released if any of the input operands
+ are strings.
+
+ (Davis, March 6, 2002)
+
+
+ptools$mkpkg
+ Modified the mkpkg procedures to pick up user compile and link flags.
+
+ (Davis, June 17, 1999)
+
+ptools$ptools.cl
+ Modified the package cl script to check and see if the tables package is
+ already loaded before checking to see if it exists and then loading it.
+
+ (Davis, August 1, 1998)
+
+ptools$pdump.cl
+ Modified the way the pdump 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)
+
+ptools$pconcat.cl
+ Added a missing "cache ("istable")" statement that could cause trouble
+ if the pconcat script was called from a backgroound job.
+
+ (Davis, July 28, 1997)
+
+ptools$txtools/t_txselect.x
+ Changed the maximimum size of the expression to be evaluated from
+ SZ_FNAME to SZ_LINE which is what it was supposed to be.
+
+ (Davis, May 25, 1996)
+
+ptools$tbdump.cl
+ If the input file was an ST binary table file and the expression parameter
+ was not equal to "yes", the intermediate tables file was not being deleted
+ when the tbdump and pdump tasks terminated. The problem was due to the
+ ".tab" extension that was added to the tables name but not sensed by
+ the delete command. I switched the delete command to a tdelete command
+ and everything worked fine.
+
+ (Davis, Nov 2, 1995)
+
+ptools/pexamine/pexmine.h
+ptools/pexamine/ptcolon.x
+ The rinner and router colon commands were incorrectly coded as rin and
+ rout colon commands in the pexamine.h file. The :router command was also
+ incorrectly writing back its results into the rinner parameter.
+
+ (Davis, May 1, 1995)
+
+ptools/ptutils/t_tbcrename.x
+ptools/ptutils/t_tbkeycol.x
+ Add several new checks for input text files to avoid a problem with
+ a text file being opened as a binary table. This problem prably appeared
+ when tables was modified to support simple text files (tables 1.3.3 for
+ sure, proably 1.3.2 as well, not sure before that).
+
+ (Davis, March 21, 1995)
+
+
+ptools/tbconcat.cl
+ Add a test for the existence of the ttools.keypar.silent parameter
+ for backwards compatability between tables 1.3.3 and 1.3.2.
+
+ (Davis, Feb 25, 1995)
+
+ptools/pexamine/ptplot.x
+ An off the end of the array computation error in the routine pt_hplot
+ was causing an invalid floating point operation on the Dec Alpha when
+ the user tried to plot the histogram of an array,
+
+ (Davis, Feb 23, 1995)
+
+ptools/pconvert/ptdeftable.x
+ Modified the pconvert task so that header space is preallocated rather
+ than added as needed. This significantly speeds up the task performance
+ by decreasing the number of disk writes required. This change was
+ made in response to a suggestion from PHil Hodge at ST.
+
+ (Davis, Feb 2, 1995)
+
+ptools/txtools/t_txcalc.x
+ptools/txtools/ptxcalc.x
+ptools/tbcalc.cl
+ptools/pcalc.cl
+ptools/doc/pcalc.hlp
+ptools/doc/tbcalc.hlp
+ptools/doc/txcalc.hlp
+ Added the tasks txcalc, tbcalc, and pcalc to the ptools package.
+ This tasks perform arithmetic operations on the fields or columns
+ of photometry files written with apphot or daophot tasks.
+
+ (Davis, May 31 1993)
+
+ptools/pexamine
+ Fixed numerous small bugs in the pexamine task including: 1)
+ unclear error messages if the default x-y or histogram plot columns could
+ not be found on task startup 2) initialization bug that could cause
+ the output edited catalog to be written incorrectly on the
+ second or higher run of pexamine, 3) added a 5% buffer around all
+ the plots so the user can see the plotted data better, 4) added
+ the standard deviation of the sky to the standard apphot columns, 5)
+ a misleading error message in the colon command to change the
+ default histogram column.
+
+ (Davis, May 22 1993)
+
+ptools/ptutils/t_istable.x
+ Modified the istable task, which is called by the pconcat, pdump,
+ prenumber, pselect, and psort script tasks so that it could deal
+ correctly with the fact that legal tables files might be text files.
+
+ (Davis, May 12 1993)
+
+ptools/pdump.cl
+ptools/pttest.cl
+ptools/tbdump.cl
+ptools/tbrenumber.cl
+ Added an expression parameter to the pdump task.
+
+ (Davis, Feb 25, 1993)
+
+ptools/tbrenumber.cl
+ptools/prenumber.cl
+ Modified the tbrenumber and prenumber scripts so they can use
+ the tables 1.2.1 version of tcalc as well as the 1.2 version.
+ The parameters verbose and harmless present in the 1.2 version
+ were removed from the 1.2.1 version.
+
+ (Davis, June 1, 1992)
+
+ptools$pexamine/ptplot.x
+ 1. The error message "Star not found" would persist after a star
+ was successfully found because no status line message was printed
+ out after a succesful find operation.
+
+ (Davis, April 7, 1992)
+
+ptools$tbdump.cl
+ptools$tbrenumber.cl
+ptools$prenumber.cl
+ 1. Changed the name of the pagwidth parameter to pwidth the call to the
+ ttools package task tdump because the parameter was renamed in the
+ version 1.2 of tables.
+
+ 2. Changed the value of the tcalc equals parameter from ":ROWNUM"
+ to "rownum" in calls to tcalc made by the tbrenumber and prenumber
+ tasks.
+
+ (Davis, February 28, 1992)
+
+ptools$ptools.cl
+ptools$ptools.hd
+ptools$ptools.men
+ptools$x_ptools.x
+ptools$pappend.cl
+ptools$pdump.cl
+ptools$prenumber.cl
+ptools$pselect.cl
+ptools$psort.cl
+ptools$pconvert/t_pconvert.x
+ptools$doc/pappend.hlp
+ptools$doc/pdump.hlp
+ptools$doc/prenumber.hlp
+ptools$doc/pselect.hlp
+ptools$doc/psort.hlp
+ptools$doc/pconvert.hlp
+ Changed the name of the append task to pappend.
+ Changed the name of the dump task to pdump.
+ Changed the name of the renumber task to prenumber.
+ Changed the name of the select task to pselect.
+ Changed the name of the sort task to psort.
+ Changed the name of the convert task to pconvert.
+
+ (Davis, October 8, 1991)
+
+ptools$pttest.cl
+ptools$doc/pttest.hlp
+ Added the new task pttest to the ptools package. Pttest runs basic tests
+ on the ptools package.
+
+ (Davis, October 8, 1991)
+
+ptools$pexamine/ptplot.x
+ Changed the status line message so that it is printed only when the
+ first plot is made or new data is read in.
+
+ (Davis, October 7, 1991)
+
+ *** Applied the results of spplint to the ptools package.
+
+ptools$convert/t_convert.x
+ Removed 2 extra arguments from the strupr call.
+ This could be a problem in the old testphot.
+
+ptools$convert/ptconvert.x
+ Changed an illegal logical NOT construct to an integer == NO construct.
+ This was not a problem in the old testphot.
+
+ Removed unused variable record form the pt_convert routine.
+
+ptools$convert/ptdeftable.x
+ Removed an extra argument from the pt_gnfn call. This routine has
+ changed and this bug was not a problem in the old testphot..
+
+ptools$pexamine/ptgetphot.x
+ Removed an extra argument from the pt_gnfn call. This routine has
+ changed. Pexamine did not exist in the old testphot so this was not
+ a problem.
+
+ptools$pexamine/ptplot.x
+ Removed an extra argument from the pt_gnfn call. This routine has
+ changed. Pexamine did not exist in the old testphot so this was not
+ a problem.
+
+ Removed an extra argument from pt_rxydata. This routine has changed.
+ Pexamine did not exist in the old testphot so this was not a problem.
+
+ Removed unused variables x1, y1 from the pt_gcur routine.
+
+ptools$pexamine/ptcolon.x
+ Removed an extra argument for a clgetr command.
+ Pexamine did not exist in the old testphot so this was not a problem.
+
+ptools$txtools/t_txdump.x
+ Removed two extra arguments from the call to strupr. This could have
+ been a problem in the old testphot.
+
+ptools$txtools/ptxdump.x
+ Changed an illegal logical NOT construct to an integer == NO construct.
+ This was not a problem in the old testphot.
+
+ptools$txtools/ptxselect.x
+ Changed an illegal logical NOT construct to an integer == NO construct.
+ This was not a problem in the old testphot.
+
+ptools$txtools/ptsortnum.x
+ Removed unused argument colwidth from the pt_colsort routine.
+
+ Davis, October 3, 1991
+
+
+ptools$renumber.cl
+ptools$tbrenumber.cl
+ Changed the calls to the tables tcalc task to include all the hidden
+ parameters.
+
+ Davis, October 1, 1991
+
+ptools$
+ 1. Deleted the append, dump, renumber, select and sort sub-directories
+ and consolidated then into the txtools sub-directory.
+
+ 2. Several small files were eliminated by concantenating them into other
+ existing files in txtools, pexamine, and convert.
+
+ 3. Changed the way selected keywords are stored in the text database
+ data structures. The index, instead of the pointer is stored. This removes
+ potential problems with reallocating the record structures, when the
+ test database files contain variable-sized records. All the text database
+ tools were affected, as were a couple of files in daophot.
+
+ 4. Modified txdump, txrenumber, txselect, txsort and pexamine so that they
+ could correctly deal with variable-sized records instead of crashing,
+ if a given record was larger than the first record in the file.
+
+ 5. Completely rewrote convert.
+
+ 6. Added an offset parameter to pexamine so that the user can elect
+ to read portions of an input photometry catalog into memory for plotting
+ and examining.
+
+ Davis, August 13, 1991
+
+ptools$
+ 1. Renamed the hidden tcolrename task need for the photcal preprocessors to
+ tbcrename in conformance with the new standards.
+
+ 2. Added a help page for tbcrename.
+
+ Davis, May 24, 1991
+
+ptools$
+ 1. Renamed the hidden tkeycol task need for the photcal preprocessors to
+ tbkeycol in conformance with the new standards.
+
+ Davis, May 24, 1991
+
+ptools$renumber/t_txrenumber.x
+ 1. The txrenumber task will now accept a list of images.
+
+ Davis, May 24, 1991
+
+ptools$
+ 1. The ptools package now loads the tables package on startup.
+
+ 2. The tasks tappend, tdump, trenumber, tselect, and tsort have now become
+ tbappend, tbdump, tbrenumber, tbselect and tbsort. These tasks work
+ on binary tables files. All are now scripts which call a tables
+ package task. All 5 tasks now operate on lists of tables files.
+
+ Davis, May 24, 1991
+
+ptools$pttables/ptkeywords.x
+ptools$pttables/ptconvert.x
+ 1. Fixed a problem with embedded blanks in string parameters in the
+ apphot/daophot database files. The format and units string were not being
+ correctly read because the second part of the value string was being read
+ into the units string, the units string was being read into the filter
+ string etc. This was only a problem for keywords (#K) because they
+ are read in free format. It was not a problem for columns (#N).
+ The format will now default to %-20s if it can not be decoded
+ and only the first part of the string will be kept. The units string
+ will be incorrect. There may be a more elegant solution
+ later but this fix will work for now.
+
+ Davis, Apr 2, 1991
+
+ptools$pttables/ptmkrec.x
+ 1. All of the ptools tasks which operate on text files convert, txappend,
+ txdump, txrenumber, txselect, txsort and pexamine have been modfied
+ to be more efficient. Calls to strmatch have been replaced by calls
+ to strncmp. Convert, txdump and txselect no longer call the expression
+ evaluator if the expression is a simple "yes" string.
+
+ 2. Ptmkrec has been modified to be more efficient for the simple case
+ where there is only a single aperture.
+
+ Davis, Mar 29, 1991
+
+ptools$
+ 1. Added the new hidden task tkeycol to the ptools package. Tkeycol
+ converts ST table header keywords into new ST table columns. It is not
+ intended to be seen directly by the user but will be used in some
+ of the preprocessing scripts in the photcal package.
+
+ 2. Added the new hidden task tcolrename to the ptools package. Tcolrename
+ renames selected columns in a list of ST tables. It is not intended to
+ be seen directly by the user but will be used in some of the preprocessing
+ scripts in the ptools package.
+
+ Davis, Mar 2, 1991
+
+ptools$convert/ptconvert.x
+ Convert was preallocating space for 150 columns in the output table. In
+ rare cases where the user had a large number of apertures (20 or so)
+ in a phot text file convert could overwrite memory and crash the task.
+
+ Davis, Oct 4, 1990
+
+ptools$tvmark/
+ Removed tvmark from ptools since it is duplicated in proto.
+
+ Davis, Jul 9, 1990
+
+ptools$convert/ptdeftable.x
+ Corrected a bug in the convert task wherein the code was trying to
+ load a string quantity into a boolean parameter. This caused the
+ code to crash on Orion was worked ok on the sparc station.
+
+ Davis, Jun 7, 1990
+
+ptools$pttables/tappend.cl
+ Removed two harmless debugging statements from the tappend.cl script.
+
+ Davis, Jan 8, 1989
+
+ptools$pttables/pthdrs.x
+ An off the end of the array access error was occurring for the format and
+ units string in the case where the header was duplicated in an input
+ text database file. This bug sometimes caused meomory corruption errors
+ in several of the daophot tasks and in the ptools tasks txsort, txdump,
+ txrenumber and txselect.
+
+ Davis, Jan 5, 1989
+.endhelp
diff --git a/noao/digiphot/ptools/cntrplot.par b/noao/digiphot/ptools/cntrplot.par
new file mode 100644
index 00000000..4381f07b
--- /dev/null
+++ b/noao/digiphot/ptools/cntrplot.par
@@ -0,0 +1,21 @@
+# The PEXAMINE task contour plotting parameters
+
+ncolumns,i,h,21,2,,Number of columns
+nlines,i,h,21,2,,Number of lines
+floor,r,h,INDEF,,,"Minimum value to be contoured (INDEF if none)"
+ceiling,r,h,INDEF,,,"Maximum value to be contoured (INDEF if none)"
+zero,r,h,0.,,,"Greyscale value of zero contour"
+ncontours,i,h,5,,,"Number of contours to be drawn (0 for default)"
+interval,r,h,0.,,,"Contour interval (0 for default)"
+nhi,i,h,-1,,,"Hi/low marking option: -1=omit, 0=mark h/l, 1=mark each pix"
+dashpat,i,h,528,,,"Bit pattern for generating dashed lines"
+label,b,h,no,,,"Label major contours with their values ?"
+box,b,h,yes,,,Draw box around periphery of window ?
+ticklabels,b,h,Yes,,,Label tick marks ?
+majrx,i,h,5,,,Number of major divisions along x grid
+minrx,i,h,5,,,Number of minor divisions along x grid
+majry,i,h,5,,,Number of major divisions along y grid
+minry,i,h,5,,,Number of minor divisions along y grid
+round,b,h,no,,,Round axes to nice values ?
+fill,b,h,no,,,Fill viewport vs enforce unity aspect ratio ?
+banner,b,h,yes,,,Standard banner?
diff --git a/noao/digiphot/ptools/doc/istable.hlp b/noao/digiphot/ptools/doc/istable.hlp
new file mode 100644
index 00000000..3a08376c
--- /dev/null
+++ b/noao/digiphot/ptools/doc/istable.hlp
@@ -0,0 +1,64 @@
+.help istable Aug91 noao.ptools.digiphot
+.ih
+NAME
+istable -- determine the status of a file
+
+.ih
+USAGE
+istable infile
+
+.ih
+PARAMETERS
+
+.ls infile
+The name of the input file whose status is to be determined.
+.le
+.ls table = no
+An output variable which is "yes" if \fIinfile\fR is an STSDAS table
+and "no" otherwise.
+.le
+.ls text = no
+An output variable which is "yes" if \fIinfile\fR is an APPHOT/DAOPHOT
+text database and "no" otherwise.
+.le
+.ls other = no
+An output variable which is "yes" if \fIinfile\fR is neither of the
+above and "no" otherwise.
+.le
+
+.ih
+DESCRIPTION
+ISTABLE is a very simple task which determines whether a specified
+input file is an STSDAS table, an APPHOT/DAOPHOT text database file or
+neither of the above. ISTABLE first tries to open the input file as an
+STSDAS table. If successful ISTABLE returns "yes" in the
+variable \fItable\fR and "no" in \fItext\fR and \fIother\fR. Otherwise
+ISTABLE tries to open the input file as an APPHOT/DAOPHOT text database
+file by checking for the "#K IRAF" keyword.
+If the check is positive ISTABLE return "yes" in
+the variable \fItext\fR and "no" in \fItable\fR and \fIother\fR. If the input
+file is neither an STSDAS table or an APPHOT/DAOPHOT text database
+ISTABLE returns "yes" in the variable \fIother\fR and "no" in \fItext\fR
+and \fItable\fR.
+
+.ih
+EXAMPLES
+
+1. Determine whether the file n4147.mag.1 is an STSDAS table.
+
+.nf
+ pt> istable n4147.mag
+ pt> =istable.table
+
+ ... answer will appear on the screen
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+Users should be wary of running ISTABLE in background as the output
+CL parameters may not be properly updated.
+.ih
+SEE ALSO
+.endhelp
diff --git a/noao/digiphot/ptools/doc/pcalc.hlp b/noao/digiphot/ptools/doc/pcalc.hlp
new file mode 100644
index 00000000..36d06229
--- /dev/null
+++ b/noao/digiphot/ptools/doc/pcalc.hlp
@@ -0,0 +1,86 @@
+.help pcalc May93 noao.digiphot.ptools
+.ih
+NAME
+pcalc - perform an arithmetic operation on a field in a list of apphot/daophot
+databases
+.ih
+USAGE
+pcalc infiles field value
+.ih
+PARAMETERS
+.ls infiles
+The APPHOT/DAOPHOT database(s) containing the field to be recomputed.
+.le
+.ls field
+The field to be recomputed. Field must be an integer or real field
+in the input file(s).
+.le
+.ls value
+The arithmetic expression used to recompute the specified field.
+Value may be an integer or real expression but must match the data
+type of field. The functions real and int may be used to do type
+conversions.
+.le
+
+.ih
+DESCRIPTION
+
+PCALC reads in the values of the \fIfield\fR keyword
+from a set of APPHOT/DAOPHOT databases, replaces the old values
+with new values equal to the value of the arithmetic expression \fIvalue\fR,
+and updates the databases(s).
+
+PCALC is script task which calls TXCALC is the input file is an
+APPHOT/DAOPHOT text database or TBCLAC if APPHOT/DAOPHOT is a tables
+database.
+If the input file is a text database, the expression \fIvalue\fR consists
+of variables which are the field names
+specified by the #N keywords or the parameters specified by the
+#K keywords in the APPHOT/DAOPHOT text databases.
+Only keywords beginning with #N can actually be replaced.
+If the input file is an ST tables database, the expression \fIvalue\fR
+consists of the table column names.
+
+The supported
+arithmetic operators and functions are briefly described below.
+
+.nf
+addition + subtraction -
+multiplication * division /
+negation - exponentiation **
+absolute value abs(x) cosine cos(x)
+sine sin(x) tangent tan(x)
+arc cosine acos(x) arc sine asin(x)
+arc tangent atan(x) arc tangent atan2(x,y)
+exponential exp(x) square root sqrt(x)
+natural log log(x) common log log10(x)
+minimum min(x,y) maximum max(x,y)
+convert to integer int(x) convert to real real(x)
+nearest integer nint(x) modulo mod(x)
+.fi
+
+.ih
+EXAMPLES
+
+1. Change the XCENTER and YCENTER fields to XCENTER + 5.4 and YCENTER + 10.3
+respectively in a file produced by the apphot package center task.
+
+.nf
+ pt> pcalc m92.ctr.1 xcenter "xcenter+5.4"
+ pt> pcalc m92.ctr.1 ycenter "ycenter+10.3"
+.fi
+
+2. Add a constant to the computed magnitudes produced by nstar.
+
+.nf
+ pt> pcalc n4147.nst.2 mag "mag+3.457"
+.fi
+
+.ih
+BUGS
+TXCALC does not allow arrays in the expression field.
+
+.ih
+SEE ALSO
+ptools.tbcalc,tables.tcalc,ptools.pcalc
+.endhelp
diff --git a/noao/digiphot/ptools/doc/pconcat.hlp b/noao/digiphot/ptools/doc/pconcat.hlp
new file mode 100644
index 00000000..f96d9bab
--- /dev/null
+++ b/noao/digiphot/ptools/doc/pconcat.hlp
@@ -0,0 +1,50 @@
+.help pconcat Dec92 noao.digiphot.ptools
+.ih
+NAME
+pconcat -- concatenate a list of APPHOT/DAOPHOT databases
+.ih
+USAGE
+pconcat infiles outfile
+.ih
+PARAMETERS
+.ls infiles
+The list of APPHOT/DAOPHOT databases to be concatenated.
+.le
+.ls outfile
+The name of the output APPHOT/DAOPHOT database.
+.le
+.ls task = "TASK"
+The name of the keywords whose value is the name of the task which wrote
+the database.
+.le
+.ih
+DESCRIPTION
+PCONCAT is a simple task which accepts a list of APPHOT/DAOPHOT
+database files and concatenates them into one resultant output file.
+PCONCAT checks that all the file are indeed APPHOT/DAOPHOT
+database files and that they were all written by the same task before
+performing the concatenation.
+
+PCONCAT is a simple script which call TXCONCAT in the PTOOLS package
+if the input files are text database files or TBCONCAT in the PTOOLS package
+if the input files are STSDAS database files. TBCONCAT is itself a script
+which call the TABLES package task TMERGE to do the actual work.
+
+.ih
+EXAMPLES
+
+1. Concatenate a list of DAOPHOT package task GROUP output database files
+into a single output file.
+
+.nf
+ pt> pconcat m92r.grp.1,m92r.grp.2,m92r.grp.3 m92rall.grp.1
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+ptools.txconcat,ptools.tbconcat,tables.tmerge,concatenate
+.endhelp
diff --git a/noao/digiphot/ptools/doc/pconvert.hlp b/noao/digiphot/ptools/doc/pconvert.hlp
new file mode 100644
index 00000000..ca3db8e7
--- /dev/null
+++ b/noao/digiphot/ptools/doc/pconvert.hlp
@@ -0,0 +1,153 @@
+.help pconvert Aug91 noao.digiphot.ptools
+.ih
+NAME
+pconvert -- convert an APPHOT/DAOPHOT text database into an STSDAS table
+.ih
+USAGE
+pconvert textfile table fields
+.ih
+PARAMETERS
+.ls textfile
+The APPHOT/DAOPHOT text database which is to be converted into an
+APPHOT/DAOPHOT STSDAS table database.
+.le
+.ls table
+The name of the output STSDAS table database.
+.le
+.ls fields = "*"
+Template defining the fields to be selected from each record. By default
+all the fields are output. Fields
+are specified by using the names defined in the APPHOT/DAOPHOT text
+database by the
+#N entries. Upper or lower case and minimum match abbreviations are
+permissible. For those fields which have multiple entries such as
+magnitude, an individual value can be referenced by specifying an array
+index, e.g. MAG[2] or several values can be selected by specifying a
+range of elements, e.g. MAG[1-4].
+.le
+.ls expr = yes
+The boolean expression, evaluated independently for each record,
+which serves as a selection criterion. By default all records are selected.
+.le
+.ls append = no
+If append is yes then the converted APPHOT/DAOPHOT text file is appended to an
+existing output STSDAS table database.
+.le
+.ih
+DESCRIPTION
+PCONVERT selects a subset of the fields from each record of an
+APPHOT/DAOPHOT text database and writes these into an STSDAS tabl database.
+The #K keyword parameters in the text database are
+stored as header parameters in the STSDAS table while the selected fields
+are stored in fields (columns) with the names specified by the text
+database #N keywords, units specified
+by the #U keywords, and print format specified by the #F keywords.
+
+The output records are selected on the basis of the boolean
+expression \fIexpr\fR whose variables are the field (column) names
+specified by the #N keywords in the APPHOT/DAOPHOT text database.
+If after substituting the values associated
+with a particular record into the field name variables the
+expression evaluates to yes, that record is included in the output table.
+
+The supported
+operators and functions are briefly described below. A detailed description
+of the boolean expression evaluator and its syntax can be found
+in the manual page for the IMAGES package HEDIT task.
+
+The following logical operators can be used in the boolean expression.
+
+.nf
+ equal == not equal !=
+ less than < less than or equal <=
+ greater than > greater than or equal >=
+ or || and &&
+ negation ! pattern match ?=
+ concatenation //
+.fi
+
+The pattern match character ?= takes a
+string expression as its first argument and a pattern as its second argument.
+The result is yes if the pattern is contained in the string expression.
+Patterns are strings which may contain pattern matching meta-characters.
+The meta-characters themselves can be matched by preceeding them with the escape
+character. The meta-characters are described below.
+
+.nf
+ beginning of string ^ end of string $
+ one character ? zero or more characters *
+ white space # escape character \
+ ignore case { end ignore case }
+ begin character class [ end character class ]
+ not, in char class ^ range, in char class -
+.fi
+
+The boolean expression may also include arithmetic operators and functions.
+The following arithmetic operators and functions are supported.
+
+.nf
+addition + subtraction -
+multiplication * division /
+negation - exponentiation **
+absolute value abs(x) cosine cos(x)
+sine sin(x) tangent tan(x)
+arc cosine acos(x) arc sine asin(x)
+arc tangent atan(x) arc tangent atan2(x,y)
+exponential exp(x) square root sqrt(x)
+natural log log(x) common log log10(x)
+minimum min(x,y) maximum max(x,y)
+convert to integer int(x) convert to real real(x)
+nearest integer nint(x) modulo mod(x)
+.fi
+
+
+If the append parameter is "yes" then the converted input text database is
+appended to the specified output table. When appending to a table each of the
+output fields must already exist in the output table.
+
+.ih
+EXAMPLES
+
+1. Convert the text output from the DAOPHOT PHOT task in the file n4147.mag.1
+to an STSDAS table, selecting only the fields ID, XCENTER, YCENTER,
+MAG,and MSKY ncessary for input to the DAOPHOT fitting routines.
+Put the output in an STSDAS table named n4147.tmag.1.
+
+.nf
+ pt> pconvert n4147.mag.1 n4147.tmag.1 "ID,XCENTER,YCENTER,MAG,MSKY"
+.fi
+
+If there were 4 magnitude fields in n4147.mag.1
+then there would be 4 columns in the output table with names of
+MAG[1], MAG[2], MAG[3] and MAG[4]
+
+
+2. Convert the same file as in example 1. but append the output to
+ n4147.tmag.1 and only select records with YCENTER <= 200.0.
+
+.nf
+ pt> pconvert n4147.mag.1 n4147.tmag.1 "ID,XCENTER,YCENTER,MAG,MSKY" \
+ expr="YCENTER < 200.0" append+
+
+.fi
+
+3. Convert all the records in the NSTAR text database n4147.nst.1 to
+ an STSDAS table.
+
+ pt> pconvert n4147.nst.1 n4147.tnst.1 "*"
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+Changes in the values of the #K keyword quantities which are permitted by
+the APPHOT/DAOPHOT text database format will be lost in the conversion to
+STSDAS table format which does not permit such changes. For example users
+who have
+set up and run PHOT interactively and changed the values of the parameters
+after writing the first record to the text database will see only the initial
+values of the #K keywords in the STSDAS table headers after conversion.
+.ih
+SEE ALSO
+images.hedit
+.endhelp
diff --git a/noao/digiphot/ptools/doc/pdump.hlp b/noao/digiphot/ptools/doc/pdump.hlp
new file mode 100644
index 00000000..d37a87e6
--- /dev/null
+++ b/noao/digiphot/ptools/doc/pdump.hlp
@@ -0,0 +1,178 @@
+.help pdump Feb93 noao.digiphot.ptools
+.ih
+NAME
+pdump - print fields from an APPHOT/DAOPHOT database
+.ih
+USAGE
+pdump infiles fields expr
+.ih
+PARAMETERS
+.ls infiles
+The APPHOT/DAOPHOT databases containing the fields to be dumped.
+.le
+.ls fields
+A template defining the fields to be dumped from each record.
+In the case of APPHOT/DAOPHOT text databases, the fields are specified by
+keywords defined by the
+#K and #N entries in the database. Upper or lower case and minimum match
+abbreviations are permissible. Some fields such as "mag" may have
+multiple entries. An individual entry can be referenced by specifying an
+array index, e.g. "MAG[2]" or several values can be selected by
+specifying a range of elements, e.g. "MAG[1-3]".
+In the case of STSDAS table APPHOT/DAOPHOT databases the fields are the
+column names. Names must be spelled in full but upper or lower case is allowed.
+In the case of STSDAS table databases, it may be necessary to escape the
+leading square bracket so that field "MAG[2]" would be referred to as
+"MAG\[2]". The fields are output in
+the order in which they are specified in the template.
+.le
+.ls expr
+The boolean expression to be evaluated once per record.
+Only the fields in those records for which the boolean expression
+evaluates to yes are printed.
+If \fIexpr\fR = "yes", the specified fields in all the records are
+printed.
+.le
+.ls headers = no
+Dump the APPHOT/DAOPHOT database field headers. The selected
+fields are printed on the standard output, preceded by the parameters list,
+if \fIparameters\fR = yes, and the keyword, units,
+and format information.
+.le
+.ls parameters = yes
+Print the keyword parameters records on the
+standard output if \fIheaders\fR = yes.
+.le
+
+.ih
+DESCRIPTION
+PDUMP selects a subset of fields specified by the \fIfields\fR
+parameter from an APPHOT/DAOPHOT database or a list of databases
+and prints the results on the standard output.
+If \fIheaders\fR = no, the output is in simple list format
+with adjacent fields
+separated by whitespace. The fields are printed in the order in
+which they appear in \fIields\fR. If \fIheaders\fR = yes, the
+selected fields are printed on the standard output, preceded by
+the parameter list, if \fIparameters\fR = yes, and the keyword, units,
+and format information.
+Newlines will not be inserted in the output if the input database
+was an APPHOT/DAOPHOT text file, so users should take
+care not specify so many output fields as to exceed the IRAF text file
+line limit of 161 characters.
+Newlines will be inserted if the original database was an
+STSDAS table.
+
+PDUMP is a simple CL script which calls TXDUMP if the APPHOT/DAOPHOT
+database was a text file and TBDUMP if it was an STSDAS table.
+Although the parameters of TBDUMP and TXDUMP have been tailored to
+make the two tasks appear as similar as possible each task
+offers some capabilities that the other does not. In some
+situations users may wish to use the individual tasks instead of the
+generic script.
+
+The output records are selected on the basis of an input boolean
+expression \fIexpr\fR whose variables are the field names
+specified by the #N keywords or the parameters specified by the
+#K keywords in the APPHOT/DAOPHOT text database or the column names
+in an ST tables database.
+If after substituting the values associated
+with a particular record into the field name variables the
+expression evaluates
+to yes, that record is included in the output table.
+
+The supported
+operators and functions are briefly described below. A detailed description
+of the boolean expression evaluator and its syntax can be found
+in the manual page for the IMAGES package HEDIT task.
+
+The following logical operators can be used in the boolean expression.
+
+.nf
+ equal == not equal !=
+ less than < less than or equal <=
+ greater than > greater than or equal >=
+ or || and &&
+ negation ! pattern match ?=
+ concatenation //
+.fi
+
+The pattern match character ?= takes a
+string expression as its first argument and a pattern as its second argument.
+The result is yes if the pattern is contained in the string expression.
+Patterns are strings which may contain pattern matching meta-characters.
+The meta-characters themselves can be matched by preceeding them with the escape
+character. The meta-characters listed below.
+
+.nf
+ beginning of string ^ end of string $
+ one character ? zero or more characters *
+ white space # escape character \
+ ignore case { end ignore case }
+ begin character class [ end character class ]
+ not, in char class ^ range, in char class -
+.fi
+
+The expression may also include arithmetic operators and functions.
+The following arithmetic operators and functions are supported.
+
+.nf
+addition + subtraction -
+multiplication * division /
+negation - exponentiation **
+absolute value abs(x) cosine cos(x)
+sine sin(x) tangent tan(x)
+arc cosine acos(x) arc sine asin(x)
+arc tangent atan(x) arc tangent atan2(x,y)
+exponential exp(x) square root sqrt(x)
+natural log log(x) common log log10(x)
+minimum min(x,y) maximum max(x,y)
+convert to integer int(x) convert to real real(x)
+nearest integer nint(x) modulo mod(x)
+.fi
+.ih
+EXAMPLES
+
+1. Select the fields XCENTER and YCENTER from the output of the APPHOT
+CENTER task.
+
+.nf
+ pt> pdump image.ctr.3 "XCENTER,YCENTER" yes
+.fi
+
+2. Select the fields XCENTER and YCENTER from the output of the APPHOT
+CENTER task for all records with YCENTER > 100.0.
+
+.nf
+ pt> pdump image.ctr.3 "XCENTER,YCENTER" "YCENTER > 100.0"
+.fi
+
+3. Select the fields ID, XCENTER, YCENTER and the first three magnitudes
+from the output of the APPHOT PHOT task. In the case of STSDAS table
+databases it may be necessary to escape the leading square bracket.
+
+.nf
+ pt> pdump image.mag.3 "ID,XCEN,YCEN,MAG[1],MAG[2],MAG[3]" yes
+
+ or
+
+ pt> pdump image.mag.3 "ID,XCEN,YCEN,MAG\[1],MAG\[2],MAG\[3]" yes
+.fi
+
+
+4. Select the ID, XCENTER, YCENTER, MSKY and MAG fields from the output
+of the DAOPHOT NSTAR task. Print the headers and parameters as well.
+
+.nf
+ pt> pdump image.nst.3 "ID,XCENTER,YCENTER,MSKY,MAG" \
+ yes headers+ parameters+
+.fi
+
+.ih
+BUGS
+Users should not dump more fields than fill a 161 character textline
+as IRAF does not currently fully support longer text lines.
+.ih
+SEE ALSO
+ptools.txdump,ptools.tbdump,tables.tdump
+.endhelp
diff --git a/noao/digiphot/ptools/doc/pexamine.hlp b/noao/digiphot/ptools/doc/pexamine.hlp
new file mode 100644
index 00000000..20289d26
--- /dev/null
+++ b/noao/digiphot/ptools/doc/pexamine.hlp
@@ -0,0 +1,835 @@
+.help pexamine Aug91 noao.digiphot.ptools
+.ih
+NAME
+pexamine -- interactively examine or edit a photometry catalog
+.ih
+USAGE
+pexamine input output image
+.ih
+PARAMETERS
+.ls input
+The name of the input photometry catalog. \fIInput\fR may be either an
+APPHOT/DAOPHOT text database file or an STSDAS binary table database.
+.le
+.ls output
+The name of the edited output catalog. \fIOutput\fR is either an
+APPHOT/DAOPHOT text database or an STSDAS binary table database
+depending on the file type of \fIinput\fR. If \fIoutput\fR = "" no output
+catalog is written.
+.le
+.ls image
+The name of the input image corresponding to the input photometry
+catalog. If \fIimage\fR is "" no image will be attached to PEXAMINE
+and some interactive catalog examining commands will not be available.
+All the catalog editing commands however are still available.
+.le
+.ls deletions = ""
+The name of an optional output deletions photometry catalog. \fIDeletions\fR
+is either an APPHOT/DAOPHOT text database or an STSDAS binary
+table database depending on the file type of \fIinput\fR. If \fIdeletions\fR
+is "" no deletions file is written.
+.le
+.ls photcolumns = "daophot"
+The list of standard photometry columns that are loaded when pexamine is
+run. The options are listed below.
+.ls "daophot"
+The standard columns for the DAOPHOT package. The current list is GROUP, ID,
+XCENTER, YCENTER, MSKY, MAG, MERR, CHI, SHARP and NITER.
+If any of these
+columns are multi-valued, (as in the case of magnitudes measured through
+more than one aperture), the first value is selected.
+The standard list may easily be extended at user request.
+.le
+.ls "apphot"
+The standard columns for the APPHOT package. The current list is ID,
+XCENTER, YCENTER, MSKY, MAG, and MERR.
+If any of these
+columns are multi-valued, (as in the case of magnitudes measured through
+more than one aperture), the first value is selected.
+The standard list may easily be extended at user request.
+.le
+.ls user list
+A user supplied list of standard columns.
+Column names are listed in full in either upper or
+lower case letters, separated by commas. If more than one value of
+a multi-valued column is requested
+the individual values
+must be listed separately as in the following example
+ID, XCENTER, YCENTER, MAG[1], MERR[1], MAG[2], MERR[2].
+.le
+
+\fIPhotcolumns\fR can be changed interactively from within PEXAMINE at
+the cost of rereading the database.
+.le
+.ls xcolumn = "mag" (magnitude), ycolumn = "merr" (magnitude error)
+The names of the two columns which define the default X-Y plot.
+\fIXcolumn\fR and \fIycolumn\fR must be listed in \fIphotcolumns\fR or
+\fIusercolumns\fR but may be changed interactively by the user.
+If either \fIxcolumn\fR or \fIycolumn\fR is a multi-valued quantity
+and more than one value is listed in \fIphotcolumns\fR or \fIusercolumns\fR
+then the desired value number must be specified explicitly in, e.g.
+MAG[2] or MERR[2].
+.le
+.ls hcolumn = "mag" (magnitude)
+The name of the column which defines the default histogram plot.
+\fIHcolumn\fR must be listed in \fIphotcolumns\fR or
+\fIusercolumns\fR but may be changed interactively by the user.
+If \fIhcolumn\fR is a multi-valued quantity and more than one value is
+listed in \fIphotcolumns\fR or \fIusercolumns\fR then the desired value
+must be specified explicitly in \fIhcolumn\fR, e.g. MAG[2].
+.le
+.ls xposcolumn = "xcenter", yposcolumn = "ycenter"
+The names of the two columns which define the X and Y coordinates in
+\fIimage\fR of the objects in the catalog. This information is
+required if the image display and image cursor are to be used to visually
+identify objects in the image with objects in the catalog or if plots
+of image data are requested. \fIXposcolumn\fR and \fIyposcolumn\fR must
+be listed in \fIphotcolumns\fR or \fIusercolumns\fR but may
+be changed interactively by the user.
+.le
+.ls usercolumns = ""
+The list of columns loaded into memory in addition to the
+standard photometry columns \fIphotcolumns\fR. The column
+names are listed in full in upper or lower case letters and separated by
+commas.
+\fIUsercolumns\fR can be changed interactively from within PEXAMINE at
+the cost of rereading the database.
+.le
+.ls max_nstars = 3000
+The maximum number of objects that are loaded into memory at task
+startup time, beginning at object \fIfirst_star\fR. If there are more
+than \fImax_nstars\fR in the catalog only the first \fImax_nstars\fR
+objects are read in.
+.le
+.ls first_star = 1
+The index of the first object to be read out of the catalog.
+.le
+.ls match_radius = 2.0
+The tolerance in pixels to be used for matching objects in the catalog with
+objects marked on the display with the image cursor.
+.le
+.ls graphics = "stdgraph"
+The default graphics device.
+.le
+.ls gcommands = ""
+The graphics cursor. If null the standard graphics cursor is used whenever
+graphics cursor input is requested. A cursor file in the appropriate
+format may be substituted by specifying the name of the file.
+.le
+.ls icommands = ""
+The image display cursor. If null the standard image cursor is used whenever
+image cursor input is requested. A cursor file in the appropriate
+format may be substituted by specifying the name of the file.
+Also the image cursor may be changed to query the graphics device or the
+terminal by setting the environment variable "stdimcur" to "stdgraph"
+or "text" respectively.
+.le
+.ls use_display = yes
+Use the image display? Users without access to an image display should
+set \fIuse_display\fR to "no".
+.le
+
+.ih
+PLOTTING PARAMETERS
+
+PEXAMINE supports five types of plots 1) an X-Y column plot
+2) a histogram column plot 3) a radial profile plot 4) a surface
+plot and 5) a contour plot.
+Each supported plot type has its own parameter set which
+controls the appearance of the plot.
+The names of the five parameter sets are listed below.
+
+.nf
+ cntrplot Parameters for the contour plot
+ histplot Parameters for the column histogram plot
+ radplot Parameters for radial profile plot
+ surfplot Parameters for surface plot
+ xyplot Parameters for the X-Y column plot
+.fi
+
+The same parameters dealing with graph formats occur in many of the parameter
+sets while some are specific only to one parameter set. In the
+summary below those common to more than one parameter set are shown
+only once. The characters in parenthesis are the graph key prefixes
+for the parameter sets in which the parameter occurs.
+
+.ls angh = -33., angv = 25. (s)
+Horizontal and vertical viewing angles in degrees for surface plots.
+.le
+.ls axes = yes (s)
+Draw axes along the edge of surface plots?
+.le
+.ls banner = yes (chrsx)
+Add a standard banner to a graph? The standard banner includes the
+IRAF user and host identification and the date and time.
+.le
+.ls box = yes (chrx)
+Draw graph box and axes?
+.le
+.ls ceiling = INDEF (cs)
+Ceiling data value for contour and surface plots. A value of INDEF does
+not apply a ceiling. In contour plots a value of 0. also does not
+apply a ceiling.
+.le
+.ls dashpat = 528 (c)
+Dash pattern for negative contours.
+.le
+.ls fill = no (yes) (c) (hrx)
+Fill the output viewport regardless of the device aspect ratio?
+.le
+.ls floor = INDEF (cs)
+Floor data value for contour and surface plots. A value of INDEF does
+not apply a floor. In contour plots a value of 0. also does not
+apply a floor.
+.le
+.ls grid = no (rx)
+Draw grid lines at major tick marks?
+.le
+.ls interval = 0.0 (c)
+Contour interval. If 0.0, a contour interval is chosen which places 20 to 30
+contours spanning the intensity range of the image.
+.le
+.ls label= no (c)
+Label the major contours in the contour plot?
+.le
+.ls logx = no, logy = no (rx) (hrx)
+Plot the x or y axis logarithmically? The default for histogram plots is
+to plot the y axis logarithmically.
+.le
+.ls majrx=5, minrx=5, majry=5, minry=5 (chrx)
+Maximum number of major tick marks on each axis and number of minor tick marks
+between major tick marks.
+.le
+.ls marker = "box" (rx)
+Marker to be drawn. Markers are "point", "box",
+"cross", "plus", "circle", "hline", "vline" or "diamond".
+.le
+.ls nbins = 512 (h)
+The number of bins in, or resolution of, histogram plots.
+.le
+.ls ncolumns = 21, nlines = 21 (cs)
+Number of columns and lines used in contour and surface plots.
+.le
+.ls ncontours = 5 (c)
+Number of contours to be drawn. If 0, the contour interval may be specified,
+otherwise 20 to 30 nicely spaced contours are drawn. A maximum of 40 contours
+can be drawn.
+.le
+.ls nhi = -1 (c)
+If -1, highs and lows are not marked. If 0, highs and lows are marked
+on the plot. If 1, the intensity of each pixel is marked on the plot.
+.le
+.ls rinner = 0, router = 8
+The inner and outer radius of the region whose radial profile is to
+be plotted.
+.le
+.ls round = no (chrx)
+Extend the axes up to "nice" values?
+.le
+.ls szmarker = 1 (rx)
+Size of mark except for points. A positive size less than 1 specifies
+a fraction of the device size. Values of 1, 2, 3, and 4 signify
+default sizes of increasing size.
+.le
+.ls ticklabels = yes (chrx)
+Label the tick marks?
+.le
+.ls top_closed = no (h)
+Include z2 in the top histogram bin? Each bin of the histogram is a
+subinterval that is half open at the top. \fITop_closed\fR decides whether
+those pixels with values equal to z2 are to be counted in the histogram. If
+\fItop_closed\fR is yes, the top bin will be larger than the other bins.
+.le
+.ls x1 = INDEF, x2 = INDEF, y1 = INDEF, y2 = INDEF (hrx)
+Range of graph along each axis. If INDEF the range is determined from
+the data range. The default y1 for histogram plots is 0.
+.le
+.ls zero = 0. (c)
+Greyscale value of the zero contour, i.e., the value of a zero point shift
+to be applied to the image data before plotting. Does not affect the values
+of the floor and ceiling parameters.
+.le
+.ls z1 = INDEF, z2 = INDEF (h)
+Range of pixel values to be used in histogram. INDEF values default to
+the range in the region being histogrammed.
+.le
+
+.ih
+DESCRIPTION
+
+PEXAMINE is a general purpose tool for interactively examining and editing
+photometry catalogs produced by the APPHOT or DAOPHOT packages. It is
+intended to aid the user in assessing the accuracy of the photometry,
+in diagnosing problems with particular catalog objects,
+in searching the photometry data for relationships
+between the computed quantities, and in editing the catalog based on
+those observed relationships. PEXAMINE is intended to complement the
+more batch oriented editing facilities of the PSELECT task.
+
+PEXAMINE takes the input catalog \fIinput\fR and the corresponding
+image \fIimage\fR (if defined) and produces an output catalog of selected
+objects \fIoutput\fR (if defined) and an output catalog of deleted objects
+\fIdeletions\fR (if defined). The input catalog may be either an
+APPHOT/DAOPHOT text database or an ST binary table database.
+The file type of the output catalogs \fIoutput\fR and \fIdeletions\fR
+is the same as that of \fIinput\fR.
+
+READING IN THE DATA
+
+PEXAMINE reads the column data specified by \fIphotcolumns\fR and
+\fIusercolumns\fR for up to \fImax_nstars\fR into memory. If there are
+more than \fImax_nstars\fR in the input catalog only the data for the
+first \fImax_nstars\fR is read. The \fIphotcolumns\fR parameter
+defines the list of standard photometry columns to be loaded. If
+"daophot" or "apphot" is selected then the standard columns
+are GROUP, ID, XCENTER, YCENTER, MSKY, MAG, MERR, CHI, SHARP and NITER
+and ID, XCENTER, YCENTER, MSKY, MAG and MERR respectively.
+Otherwise the user must set \fIphotcolumns\fR to his or her own preferred
+list of standard photometry columns. Non-standard columns may also be
+specified using the parameter \fIusercolumns\fR.
+Valid column lists contain the full names of the specified columns
+in upper or lower case letters, separated by commas.
+Either \fIphotcolumns\fR or
+\fIusercolumns\fR may be redefined interactively by the user after
+the task has started up, but only at the
+expense of rereading the data from \fIinput\fR.
+
+PEXAMINE will fail to load a specified column if that column is
+not in the photometry database, is of a datatype other than
+integer or real, or adding that column would exceed the maximum
+number of columns limit currently set at twenty. The user can
+interactively examine the list of requested and loaded standard
+photometry columns, as well as list all the columns in the input
+after the task has started up.
+
+GRAPHICS AND IMAGE COMMAND MODE
+
+PEXAMINE accepts commands either from the graphics cursor \fIgcommands\fR
+(graphics command mode) or the image display cursor \fIicommands\fR
+if available (image command mode).
+PEXAMINE starts up in graphics command mode, but all the
+interactive commands are accessible from both modes and the user can
+switch modes at any time assuming that the \fIuse_display\fR parameter
+to "yes".
+
+PEXAMINE interprets the cursor position in graphics mode
+differently from how it interprets it in image command mode.
+In graphics command mode the cursor coordinates are the position
+of the cursor in the current plot, whereas in image command mode they
+are the x and y coordinates of the cursor in the displayed image.
+For example, if the user issues a command to PEXAMINE to locate the object
+in the catalog nearest the point in the current X-Y plot marked by
+the graphics cursor, PEXAMINE does so by searching
+the data for the object whose values of \fIxcolumn\fR and \fIycolumn\fR
+most closely match those of the current cursor position.
+If the user issues a command to PEXAMINE to locate the
+object in the catalog corresponding to the object marked on the image
+display with the image cursor,
+PEXAMINE does so by searching the data for
+the object whose values of \fIxposcolumn\fR and \fIyposcoumn\fR
+most closely match and fall within \fImatch_radius\fR of the current
+cursor position.
+
+Input to PEXAMINE is through single keystroke commands or colon
+commands. Keystroke commands are simple commands that may
+optionally use the cursor position but otherwise require no arguments.
+The PEXAMINE keystroke commands fall into three categories, basic
+commands, data examining commands and data editing commands, all
+described in detail in the following sections. Colon commands
+take an optional argument and function differently depending on
+the presence or absence of that argument. When the argument is absent
+colon commands are used to display the
+current value of a parameter or list of parameters. When the argument is
+present they change their current value to that argument.
+The basic colon commands are described in detail below.
+
+BASIC KEYSTROKE COMMANDS
+
+These keystroke commands are used to display the help page, switch from
+graphics to image command mode and quit the task.
+
+.ls ?
+Page through the help for the PEXAMINE task
+.le
+.ls :
+Execute a PEXAMINE colon command.
+.le
+.ls g
+Change to graphics command mode. Throughout PEXAMINE graphics command mode
+is the default. All PEXAMINE commands are available in graphics command
+mode.
+.le
+.ls i
+Change to image command mode.
+All the PEXAMINE commands are available in image command mode.
+However if \fIuse_display\fR is no and the image
+cursor has not been aliased to the standard input or a text file
+image command mode is disabled.
+.le
+.ls q
+Quit PEXAMINE without writing an output catalog.
+PEXAMINE queries the user for confirmation of this option.
+.le
+.ls e
+Quit PEXAMINE and write the output catalog.
+.le
+
+DATA EXAMINING COMMANDS
+
+The data examining commands fall into two categories, those that examine
+the catalog data including 'l' (catalog listing), 'o' (object listing),
+'x' (Y column versus X column plot) and 'h' (histogram column plot)
+commands, and those which examine the image data around specific catalog
+objects including 'r' (radial profile plotting), 's' (surface plotting),
+'c' (contour plotting) and 'm' (pixel dumping). The latter group
+require that \fIimage\fR be defined. A brief summary of each data
+examining command is given below.
+.ls l
+Print out the name, datatype, and units for all the columns in the input
+catalog. The list command can be used to check the contents of the input
+catalog and/or determine why a particular column was not loaded.
+.le
+.ls o
+Print out the names and values of the stored columns of the object
+nearest the cursor. In graphics mode the current plot type must be
+X-Y. In image command mode the object nearest the cursor must also be
+no more than \fImatch-radius\fR pixels away from the image cursor to be
+found. If an object is found and the current plot type is X-Y
+the graphics cursor is moved to the position of the selected object
+in the X-Y plot.
+.le
+.ls x
+Plot the data in \fIycolumn\fR versus the data in \fIxcolumn\fR excluding
+any already deleted points and identifying objects marked for deletion
+with a cross. X-Y plotting is undefined if \fIxcolumn\fR or \fIycolumn\fR
+is undefined.
+.le
+.ls h
+Plot the histogram of the data in \fIhcolumn\fR excluding any already
+deleted points and those marked for deletion. Histogram plotting is
+disabled if \fIhcolumn\fR is undefined.
+.le
+.ls r
+Plot the radial profile of the object nearest the cursor including
+only pixels within a distance of \fIrinner\fR and \fIrouter\fR of
+the object center. Radial profile plotting is disabled if \fIimage\fR
+or \fIxposcolumn\fR or \fIyposcolumn\fR is undefined.
+.le
+.ls s
+Plot the surface plot of the object nearest the cursor including
+only pixels within an image section \fIncols\fR by \fInlines\fR
+around the object center. Surface plotting is disabled if \fIimage\fR
+or \fIxposcolumn\fR or \fIyposcolumn\fR is undefined.
+.le
+.ls c
+Plot the contour plot of the object nearest the cursor including
+only pixels within an image section \fIncols\fR by \fInlines\fR
+around the object center. Contour plotting is disabled if \fIimage\fR
+or \fIxposcolumn\fR or \fIyposcolumn\fR is undefined.
+.le
+.ls m
+Dump the pixel values of a grid of 10 by 10 pixels around the object
+nearest the cursor. Pixel value dumping is disabled if \fIimage\fR
+or \fIxposcolumn\fR or \fIyposcolumn\fR is undefined.
+.le
+.ls p
+Replot the current graph.
+.le
+
+DATA EDITING COMMANDS
+
+Data points can be deleted from the catalog in either graphics command
+mode or image
+command mode. In graphics command mode the
+graphics cursor and either the X-Y or histogram plot is used to delete points.
+In image command mode the image cursor and the displayed
+image are used to delete points. A data point has three possible states
+good, marked for deletion and deleted.
+Any one of the keystroke commands 'd' (delete point), '(' (delete points
+with x less than x cursor), ')' (delete points with x greater than x cursor,
+'^' (delete points with y > y cursor), 'v' (delete points with y < y cursor)
+or 'b' (delete points in a box) can be used to mark points for deletion.
+The 'f' key is used to actually delete the points and replot the data.
+In between marking the points for deletion and actually deleting the marked
+points the 't' (toggle) key can be used to undelete the last set marked.
+The full list of the data editing keystroke commands is given below.
+
+.ls z
+Undelete not just unmark all the data points replot.
+.le
+.ls f
+Delete points marked for deletion and replot. Points marked for deletion
+but not actually deleted will be written to the output catalog and not
+written to the deletions catalog.
+.le
+.ls d
+Mark the point nearest the cursor for deletion.
+.le
+.ls u
+Undelete the marked point nearest the cursor.
+.le
+.ls (
+Mark all points with x values less than the x value of the cursor for
+deletion. In graphics command mode points can only be marked for deletion if
+the current plot type is "xyplot" or "histplot". In image command
+mode \fIxposcolumn\fR and \fIyposcolumn\fR must be defined before
+points can be marked for deletion.
+.le
+.ls )
+Mark all points with x values greater than the x value of the cursor for
+deletion. In graphics command mode points can only be marked for deletion if
+the current plot type is "xyplot" or "histplot". In image command
+mode \fIxposcolumn\fR and \fIyposcolumn\fR must be defined before
+points can be marked for deletion.
+.le
+.ls v
+Mark all points with y values less than the y value of the cursor for
+deletion. In graphics command mode points can only be marked for deletion if
+the current plot type is "xyplot". In image command
+mode \fIxposcolumn\fR and \fIyposcolumn\fR must be defined before
+points can be marked for deletion.
+.le
+.ls ^
+Mark all points with y values greater than the y value of the cursor for
+deletion. In graphics command mode points can only be marked for deletion if
+the current plot type is "xyplot". In image command
+mode \fIxposcolumn\fR and \fIyposcolumn\fR must be defined before
+points can be marked for deletion.
+.le
+.ls b
+Mark all points within a box whose lower left and upper right hand corners
+are marked by the cursor for deletion.
+In graphics mode points can only be marked for deletion if the current
+plot type is "xyplot". In image command mode \fIxposcolumn\fR and
+\fIyposcolumn\fR must be defined before points can be marked for
+deletion.
+.le
+.ls t
+Toggle between marking points for deletion or undeletion. The default
+is to mark points for deletion.
+.le
+
+BASIC COLON COMMANDS
+
+All the PEXAMINE parameters can be changed interactively with colon
+commands, including those which determine which data is read in,
+which data is plotted and the parameters of each plot. A brief description
+of the basic commands is given here. The full list is given in the
+following section.
+
+.ls :photcolumns [col1,col2,...]
+Show or set the list of requested standard photometry columns and the list
+of loaded
+photometry columns. If the user supplies a new list of columns the data will be
+reread from disk.
+.le
+.ls :usercolumns [col1,col2,...]
+Show or set the list of requested user columns and the list of loaded
+user columns. If the user supplies a new list of columns the data will be
+reread from disk.
+.le
+.ls :xcolumn [colname]
+Show or set the name of the column to be plotted along the x axis of the
+X-Y plot.
+.le
+.ls :ycolumn [colname]
+Show or set the name of the column to be plotted along the y axis of the
+X-Y plot.
+.le
+.ls :hcolumn [colname]
+Show or set the name of the column to be whose histogram is to be plotted.
+.le
+.ls :eparam [cntrplot/histplot/radplot/surfplot/xyplot]
+Review or edit the list of parameters for the various plot types.
+.le
+.ls :unlearn [cntrplot/histplot/radplot/surfplot/xyplot]
+Return the list of parameters for the various plot types to their default
+values.
+.le
+.ls :x y key cmd
+Execute any defined keystroke "key" supplying the appropriate x and y
+value in place of the cursor position. In graphics command mode the x
+and y position are assumed to be the position in the current graph.
+In image command mode the x and y position are assumed to be the x and
+y coordinate in the image display.
+.le
+
+.ih
+COMMANDS
+
+.nf
+ PEXAMINE Interactive Cursor Keystroke Commands
+
+ Basic Commands
+
+? Print help for the PEXAMINE task
+: PEXAMINE colon commands
+g Activate the graphics cursor
+i Activate the image cursor
+e Exit PEXAMINE and save the edited catalog
+q Quit PEXAMINE and discard the edited catalog
+
+ Data Examining Commands
+
+l List the name, datatype and units for all columns in the catalog
+o Print out the names and values of the stored columns for the
+ object nearest the cursor
+x Replot the current y column versus the current x column
+h Replot the current histogram
+r Plot the radial profile of the object nearest the cursor
+s Plot the surface of the object nearest the cursor
+c Plot the contour plot of the object nearest the cursor
+m Print the data values of the object nearest the cursor
+p Replot the current graph
+
+ Data Editing Commands
+
+z Reinitialize the data by removing all deletions and replot
+d Mark the point nearest the cursor for deletion
+u Undelete the marked point nearest the cursor
+t Toggle between marking points for deletion or undeletion
+( Mark points with X < X (cursor) for deletion or undeletion
+) Mark points with X > X (cursor) for deletion or undeletion
+v Mark points with Y < Y (cursor) for deletion or undeletion
+^ Mark points with Y > Y (cursor) for deletion or undeletion
+b Mark points inside a box for deletion or undeletion
+f Actually delete the marked points and replot
+
+
+ PEXAMINE Interactive Colon Commands
+
+:xcolumn [name] Show/set the X-Y plot X axis quantity
+:ycolumn [name] Show/set the X-Y plot Y axis quantity
+:hcolumn [name] Show/set the histogram plot quantity
+:photcolumns [col1,col2,...] Show/set the list of photometry columns
+:usercolumns [col1,col2,...] Show/set the list of user columns
+:delete [yes/no] Delete or undelete points
+:eparam [x/h/r/s/c] Edit/unlearn the specified plot pset
+ or
+:unlearn
+
+
+ PEXAMINE Interactive X-Y Plotting Commands
+
+:x1 [value] Left world x-coord if not autoscaling
+:x2 [value] Right world x-coord if not autoscaling
+:y1 [value] Lower world y-coord if not autoscaling
+:y2 [value] Upper world y-coord if not autoscaling
+:szmarker [value] Marker size
+:marker [point|box|plus|cross|circle|diamond|hline|vline] Marker type
+:logx [yes/no] Log scale the x axis?
+:logy [yes/no] Log scale the y axis?
+:box [yes/no] Draw box around periphery of window?
+:ticklabels [yes/no] Label tick marks?
+:grid [yes/no] Draw grid lines at major tick marks?
+:majrx [value] Number of major divisions along x axis
+:minrx [value] Number of minor divisions along x axis
+:majry [value] Number of major divisions along y axis
+:minry [value] Number of minor divisions along y axis
+:round [yes/no] Round axes to nice values?
+:fill [yes/no] Fill viewport vs enforce unity aspect ratio?
+
+
+ PEXAMINE Interactive Histogram Plotting Commands
+
+:nbins [value] Number of bins in the histogram
+:z1 [value] Minimum histogram intensity
+:z2 [value] Maximum histogram intensity
+:top_closed [y/n] Include z in the top bin?
+:x1 [value] Left world x-coord if not autoscaling
+:x2 [value] Right world x-coord if not autoscaling
+:y1 [value] Lower world y-coord if not autoscaling
+:y2 [value] Upper world y-coord if not autoscaling
+:logy [yes/no] Log scale the y axis?
+:box [yes/no] Draw box around periphery of window?
+:ticklabels [yes/no] Label tick marks?
+:majrx [value] Number of major divisions along x axis
+:minrx [value] Number of minor divisions along x axis
+:majry [value] Number of major divisions along y axis
+:minry [value] Number of minor divisions along y axis
+:round [yes/no] Round axes to nice values?
+:fill [yes/no] Fill viewport vs enforce unity aspect ratio?
+
+ PEXAMINE Interactive Radial Profile Plotting Commands
+
+:rinner [value] Inner radius of the region to be plotted
+:router [value] Outer radius of the region to be plotted
+:x1 [value] Left world x-coord if not autoscaling
+:x2 [value] Right world x-coord if not autoscaling
+:y1 [value] Lower world y-coord if not autoscaling
+:y2 [value] Upper world y-coord if not autoscaling
+:szmarker [value] Marker size
+:marker [point|box|plus|cross|circle|diamond|hline|vline] Marker type
+:logx [yes/no] Log scale the x axis?
+:logy [yes/no] Log scale the y axis?
+:box [yes/no] Draw box around periphery of window?
+:ticklabels [yes/no] Label tick marks?
+:grid [yes/no] Draw grid lines at major tick marks?
+:majrx [value] Number of major divisions along x axis
+:minrx [value] Number of minor divisions along x axis
+:majry [value] Number of major divisions along y axis
+:minry [value] Number of minor divisions along y axis
+:round [yes/no] Round axes to nice values?
+:fill [yes/no] Fill viewport vs enforce unity aspect ratio?
+
+
+ PEXAMINE Interactive Surface Plotting Commands
+
+:ncolumns [value] Number of columns to be plotted
+:nlines [value] Number of lines to be plotted
+:axes [yes/no] Draw axes?
+:angh [value] Horizontal viewing angle
+:angv [value] Vertical viewing angle
+:floor [value] Minimum value to be plotted
+:ceiling [value] Maximum value to be plotted
+
+
+ PEXAMINE Interactive Contour Plotting Commands
+
+:ncolumns [value] Number of columns to be plotted
+:nlines [value] Number of lines to be plotted
+:floor [value] Minimum value to be plotted
+:ceiling [value] Maximum value to be plotted
+:zero [value] Greyscale value of zero contour
+:ncontours [value] Number of contours to be drawn
+:interval [value] Contour interval
+:nhi [value] Hi/low marking option
+:dashpat [value] Bit pattern for generating dashed lines
+:label [yes/no] Label major contours with their values?
+:box [yes/no] Draw box around periphery of window?
+:ticklabels [yes/no] Label tick marks?
+:majrx [value] Number of major divisions along x axis
+:minrx [value] Number of minor divisions along x axis
+:majry [value] Number of major divisions along y axis
+:minry [value] Number of minor divisions along y axis
+:round [yes/no] Round axes to nice values?
+:fill [yes/no] Fill viewport vs enforce unity aspect ratio?
+.fi
+
+.ih
+EXAMPLES
+
+1. Examine and edit an APPHOT aperture photometry catalog and a DAOPHOT
+allstar catalog without either attaching the associated image or using the
+image display.
+
+.nf
+ pt> pexamine m92.mag.1 m92.mag.ed use_display-
+
+ ... a plot of magnitude error versus magnitude appears on
+ the screen and the graphics cursor comes up ready to accept
+ commands
+
+ ... the user sees a generally smooth trend of increasing
+ magnitude error with increasing magnitude except for a
+ single deviant point at the bright end of the plot
+
+ ... the user decides to remove the deviant point using the
+ 'd' keystroke command to mark the point and the 'f'
+ keystroke command to actually delete and replot the graph
+
+ ... after examining the plot further the user decides to delete
+ all objects for which the magnitude error is > 0.1 magnitudes
+ using the '^' keystroke command, followed by the 'f'
+ keystroke command to actually replot and delete the data.
+
+ ... after deciding that this new plot is satisfactory the user
+ issues the 'e' keystroke command to exit pexamine and save
+ the good data in m92.mag.ed
+
+ pt> pexamine m92.als.1 m92.als.ed use_display-
+
+ ... a plot of magnitude error versus magnitude appears on the
+ screen and the graphics cursor comes up ready to accept
+ commands
+
+ ... after looking at the plot the user decides that what they
+ really want to see is a plot of the goodness of fit parameter
+ chi versus magnitude
+
+ ... the user issues the colon command :ycol chi followed by 'p'
+ keystroke command to replot the data
+
+ ... the user sees a generally smooth trend of increasing
+ chi with increasing magnitude
+
+ ... after examining the plot further the user decides to delete
+ all objects for which the chi value > 2.0 and the
+ magnitude is > 25 using the '^' key and ')' keystroke
+ commands followed by 'f' to save the deletions and replot
+ the data
+
+ ... after deciding that this new plot is satisfactory the user
+ issues the 'e' keystroke command to exit pexamine and save
+ the good data in m92.als.ed
+.fi
+
+2. Examine and edit a DAOPHOT allstar catalog using the subtracted image, the
+original image and the image display.
+
+.nf
+ pt> display image.sub 1
+
+ ... display the subtracted image
+
+ pt> pexamine orionk.als.1 orionk.als.ed image xcol=mag ycol=chi
+
+ ... a plot of the goodness of fit versus magnitude appears
+ on the terminal and the graphics cursor comes up ready to
+ accept commands
+
+ ... the user notices some very anomalous chi values and decides
+ to see if these correspond to objects which have poor
+ subtraction on the displayed image
+
+ ... the user switches to image command mode by tapping the 'i'
+ key, moves to the first poorly subtracted object and taps
+ the 'o' key
+
+ ... a list of the values of the loaded columns including chi
+ appears in the text window , the program switches to graphics
+ mode and places the graphics cursor on the corresponding
+ point in the X-Y plot
+
+ ... the point in question indeed has a very high chi value
+ and the user decides to try and investigate the reason for the
+ anomalous value
+
+ ... the user taps the 'r' key to get a radial profile of the
+ object in the original image
+
+ ... after carefully examining the profile it appears that the
+ object's profile is too broad and that it is not a star
+
+ ... the user switches back to the X-Y plot with the 'x' key,
+ marks the point with the 'd' key and saves the deletions
+ and replots with the 'f' key.
+
+ ... the user goes back to image command mode with the 'i' key
+ and begins investigating the next object
+
+ ... finally after examining the image and making all the changes
+ the user decides to quit and save the changes with the 'e' key
+
+.fi
+
+.ih
+TIME REQUIREMENTS
+
+.ih
+BUGS
+If the display device is on a remote resource the first image cursor
+request will cause PEXAMINE to hang. The remote resource is expecting
+the appropriate password which the user must type in to cause the
+the image cursor to appear. The normal password prompt is
+not being issued or flushed to the terminal. The solution to the problem
+is to put the password in the .irafhosts file
+
+INDEF valued points cannot be accessed by
+PEXAMINE. INDEF valued points should be removed from the input catalog
+with PSELECT prior to entering PEXAMINE.
+
+.ih
+SEE ALSO
+ptools.pselect, ptools.txselect,ptools.tselect
+.endhelp
diff --git a/noao/digiphot/ptools/doc/prenumber.hlp b/noao/digiphot/ptools/doc/prenumber.hlp
new file mode 100644
index 00000000..1dcc4ed9
--- /dev/null
+++ b/noao/digiphot/ptools/doc/prenumber.hlp
@@ -0,0 +1,59 @@
+.help prenumber May93 noao.digiphot.ptools
+.ih
+NAME
+prenumber -- renumber an APPHOT/DAOPHOT database
+.ih
+USAGE
+renumber infile
+.ih
+PARAMETERS
+.ls infile
+The APPHOT/DAOPHOT database to be renumbered.
+.le
+.ls id = "ID"
+The name of the keyword whose value is the sequence number of the object
+.le
+.ls idoffset = 0
+An integer offset to be added to the id numbers of the stars in
+the output renumbered photometry file. If idoffset is > 0, the output
+id numbers will run from 1 + idoffset to N + idoffset instead of from 1 to N.
+in the database.
+.le
+
+.ih
+DESCRIPTION
+PRENUMBER is a simple task which accepts an APPHOT/DAOPHOT
+database file and renumbers the objects in the file from 1 + idoffset
+to N + idoffset,
+where N is the number of objects in the database. A renumber operation is
+often performed
+after an append operation to insure that the database objects have unique id
+numbers or after a sort to put the id numbers in order.
+
+PRENUMBER is a script which executes TXRENUMBER if the APPHOT/DAOPHOT
+database is a text database or TCALC if the file is an STSDAS table
+database.
+.ih
+EXAMPLES
+
+1. Renumber a sorted NSTAR database that has been sorted on magnitude.
+
+.nf
+ pt> prenumber m92r.nst.1
+.fi
+
+2. Renumber a PHOT photometry file of extra stars so as to ensure the
+stars' id numbers are greater than 4000.
+
+.nf
+ pt> prenumber m92r.mag.extra idoffset=4000
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+ptools.txrenumber,ptools.tbrenumber,tables.tcalc
+.endhelp
diff --git a/noao/digiphot/ptools/doc/pselect.hlp b/noao/digiphot/ptools/doc/pselect.hlp
new file mode 100644
index 00000000..92d4f163
--- /dev/null
+++ b/noao/digiphot/ptools/doc/pselect.hlp
@@ -0,0 +1,130 @@
+.help pselect Aug91 noao.digiphot.ptools
+.ih
+NAME
+pselect - select records from an APPHOT/DAOPHOT database
+.ih
+USAGE
+pselect infiles outfiles expr
+.ih
+PARAMETERS
+.ls infiles
+The APPHOT/DAOPHOT databases containing the records from which the
+selection is to be made.
+.le
+.ls outfiles
+The output APPHOT/DAOPHOT databases containing the selected records.
+.le
+.ls expr
+The boolean expression to be evaluated. The expression
+is evaluated once for each record. If \fIexpr\fR = yes,
+a copy is made of the input file.
+.le
+
+.ih
+DESCRIPTION
+PSELECT selects a subset of the records
+from an APPHOT/DAOPHOT database or a list of databases
+and writes the new records out to another database or list of
+databases.
+
+The output records are selected on the basis of an input boolean
+expression \fIexpr\fR whose variables are in the case of text
+databases the field names
+specified by the #N keywords or the parameters specified by the
+#K keywords and in the case of an STSDAS table database the
+column names.
+If after substituting the values associated
+with a particular record into the field name variables the
+expression evaluates
+to yes, that record is included in the output database.
+
+The supported
+operators and functions are briefly described below. A detailed description
+of the boolean expression evaluator and its syntax can be found
+in the manual page for the IMAGES package HEDIT task.
+
+The following logical operators can be used in the boolean expression.
+
+.nf
+ equal == not equal !=
+ less than < less than or equal <=
+ greater than > greater than or equal >=
+ or || and &&
+ negation ! pattern match ?=
+ concatenation //
+.fi
+
+The pattern match character ?= takes a
+string expression as its first argument and a pattern as its second argument.
+The result is yes if the pattern is contained in the string expression.
+Patterns are strings which may contain pattern matching meta-characters.
+The meta-characters themselves can be matched by preceeding them with the escape
+character. The meta-characters are listed below.
+
+.nf
+ beginning of string ^ end of string $
+ one character ? zero or more characters *
+ white space # escape character \
+ ignore case { end ignore case }
+ begin character class [ end character class ]
+ not, in char class ^ range, in char class -
+.fi
+
+The boolean expression may also include arithmetic operators and functions.
+The following arithmetic operators and functions are supported.
+
+.nf
+addition + subtraction -
+multiplication * division /
+negation - exponentiation **
+absolute value abs(x) cosine cos(x)
+sine sin(x) tangent tan(x)
+arc cosine acos(x) arc sine asin(x)
+arc tangent atan(x) arc tangent atan2(x,y)
+exponential exp(x) square root sqrt(x)
+natural log log(x) common log log10(x)
+minimum min(x,y) maximum max(x,y)
+convert to integer int(x) convert to real real(x)
+nearest integer nint(x) modulo mod(x)
+.fi
+
+.ih
+EXAMPLES
+
+1. Select the records from the output of the APPHOT CENTER task for
+which 100. <= XCENTER <= 200. and 300. <= YCENTER <= 400.
+
+.nf
+ pt> pselect m92.ctr.3 m92out \
+ "XCE >= 100. && XCE <= 200. && YCE >= 300. && YCE <= 400."
+.fi
+
+2. Select the records from the output of the APPHOT PHOT task for which
+the first magnitude is not equal to INDEF. In the case of the
+an STSDAS table database it may be necessary to escape the
+leading square bracket.
+
+.nf
+ pt> pselect n4147.mag.3 n4147out "MAG[1] != INDEF"
+
+ or
+
+ pt> pselect n4147.mag.3 n4147out "MAG\[1] != INDEF"
+.fi
+
+3. Select the records from the output of the DAOPHOT ALLSTAR task
+for which CHI <= 5.0 and MERR <= .10 magnitudes.
+
+.nf
+ pt> pselect m92b.al.2 m92out "CHI <= 5.0 && MERR <= 1.0"
+.fi
+
+.ih
+BUGS
+Array valued fields in text databases are not allowed in the expression
+field.
+
+.ih
+SEE ALSO
+images.hedit,ptools.tbselect,tables.tselect,ptools.txselect
+.endhelp
diff --git a/noao/digiphot/ptools/doc/psort.hlp b/noao/digiphot/ptools/doc/psort.hlp
new file mode 100644
index 00000000..806448c9
--- /dev/null
+++ b/noao/digiphot/ptools/doc/psort.hlp
@@ -0,0 +1,64 @@
+.help psort Aug91 noao.digiphot.ptools
+.ih
+NAME
+psort -- sort an APPHOT/DAOPHOT database file
+.ih
+USAGE
+psort infiles field
+.ih
+PARAMETERS
+.ls infiles
+The input APPHOT/DAOPHOT databases to be sorted. The sort is performed in place.
+.le
+.ls field
+The field to be sorted on. If the input file is a text database,
+\fIfield\fR may be any quantity defined by
+the APPHOT/DAOPHOT #K and #N keywords. If the input file is an STSDAS
+table database \fIfield\fR may be any column name. \fIField\fR may be
+of type integer or real, in which case a numeric sort is performed,
+boolean, in which case the boolean constant "no" is assumed to have a
+smaller value than "yes", or character in which case an alphabetic sort
+is performed.
+.le
+.ls ascend = yes
+Sort in increasing value order.
+.le
+.ih
+DESCRIPTION
+PSORT is a simple task which accepts an APPHOT/DAOPHOT database file
+and sorts it in place based on the value of the selected quantity
+\fIfield\fR. By default the sort is in increasing order of the value
+of field, but a reverse sort can be performed by
+setting \fIascend\fR = no.
+
+If \fIfield\fR is a real or integer the sort is numeric, if boolean
+the constant "no" is assumed to have a smaller value than "yes", if
+character the sort is alphabetic.
+
+PSORT is a simple CL script which call TXSORT if the input database is
+a text file and TSORT if the input database is a text file.
+.ih
+EXAMPLES
+
+1. Sort the output of the APPHOT task PHOT in increasing order of
+the y coordinate.
+
+.nf
+ pt> psort m92.mag.1 YCENTER
+.fi
+
+2. Sort the output of the DAOPHOT task ALLSTAR in increasing order of
+magnitude.
+
+.nf
+ pt> psort m92.al.1 MAG
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+ptools.txsort,tables.tsort,ptools.tbsort
+.endhelp
diff --git a/noao/digiphot/ptools/doc/pttest.hlp b/noao/digiphot/ptools/doc/pttest.hlp
new file mode 100644
index 00000000..3329e017
--- /dev/null
+++ b/noao/digiphot/ptools/doc/pttest.hlp
@@ -0,0 +1,78 @@
+.help pttest Oct91 noao.digiphot.ptools
+.ih
+NAME
+pttest -- run basic tests on the ptools package tasks
+.ih
+USAGE
+pttest rootname
+.ih
+PARAMETERS
+.ls rootname
+The root name of the output test files. The actual test files are stored in
+in the PTOOLS package test directory. If the test files already exist
+PTTEST will exit with a warning message.
+.le
+.ls ptlogfile = ""
+The name of the output log file. By default all the output is logged in a file
+called \fIrootname.log"\fR. If the log file already exists PTTEST will
+exit with a warning message.
+.le
+.ls ptplotfile = ""
+The name of the output plot file. By default all the graphics output is
+logged in a file called \fIrootname.plot"\fR. If the plot file already exists
+PTTEST will exit with a warning message.
+.le
+
+.ih
+DESCRIPTION
+
+PTTEST is a simple script which exercises each of the major tasks in the
+PTOOLS package in turn. At startup PTTEST reads a small set of text files
+stored in the PTOOLS test subdirectory and creates copies of them in
+the user's working directory. PTTEST initializes the PTTOLS package by
+returning
+all the parameters to their default state, runs each of the PTOOLS
+tasks in non-interactive mode, spools the text output to the file
+\fIptlogfile\fR, and the graphics output from the PEXAMINE task to the plot
+metacode file \fIptplotfile\fR.
+
+Some of PTOOLS tasks which PTTEST attempts to test are in the STSDAS TABLES
+package. If this package is not available a warning message will appear
+on the screen and this part of the PTTEST script will be skipped.
+The TABLES external addon package is available from ST.
+
+.ih
+EXAMPLES
+
+1. Check to see that all the PTOOLS tasks are functioning correctly.
+.nf
+ da> ptools
+
+ ... load the ptools package
+
+ da> pttest testit
+
+ ... run the test script
+
+ da> lprint testit.log
+
+ ... print the text output
+
+ da> gkidir testit.plot
+
+ ... list the contents of the plot file
+
+ da> gkiextract testit.plot 1-N | stdplot
+
+ ... send the plots to the plotter
+
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+tables
+.endhelp
diff --git a/noao/digiphot/ptools/doc/tbcalc.hlp b/noao/digiphot/ptools/doc/tbcalc.hlp
new file mode 100644
index 00000000..9e0f83b9
--- /dev/null
+++ b/noao/digiphot/ptools/doc/tbcalc.hlp
@@ -0,0 +1,79 @@
+.help tbcalc May93 noao.digiphot.ptools
+.ih
+NAME
+tbcalc - perform an arithmetic operation on a column in a list of apphot/daophot
+ ST tables databases
+.ih
+USAGE
+tbcalc textfiles column value
+.ih
+PARAMETERS
+.ls textfiles
+The APPHOT/DAOPHOT ST tables database(s) containing the column to be recomputed.
+.le
+.ls column
+The column to be recomputed. Column must be an integer or real column
+in the input file(s).
+.le
+.ls value
+The arithmetic expression used to recompute the specified column.
+Value may be an integer or real expression but must match the data
+type of column.
+.le
+
+.ih
+DESCRIPTION
+
+TBCALC reads in the value of the \fIcolumn\fR
+from a set of APPHOT/DAOPHOT ST tables databases, replaces it with a new
+value specified by the arithmetic expression \fIvalue\fR,
+and updates the ST tables databases(s).
+
+The expression \fIvalue\fR consists of variables which are column names
+in the APPHOT/DAOPHOT ST tables database.
+TBCALC uses the TABLES package task TCALC to actually perform the
+arithmetic operation.
+
+The supported
+arithmetic operators and functions are briefly described below.
+
+.nf
+addition + subtraction -
+multiplication * division /
+negation - exponentiation **
+absolute value abs(x) cosine cos(x)
+sine sin(x) tangent tan(x)
+arc cosine acos(x) arc sine asin(x)
+arc tangent atan(x) arc tangent atan2(x,y)
+exponential exp(x) square root sqrt(x)
+natural log log(x) common log log10(x)
+minimum min(x,y) maximum max(x,y)
+convert to integer int(x) convert to real real(x)
+nearest integer nint(x) modulo mod(x)
+.fi
+
+.ih
+EXAMPLES
+
+1. Change the XCENTER and YCENTER fields to XCENTER + 5.4 and YCENTER + 10.3
+respectively in a file produced by the daophot package allstar task.
+
+.nf
+ pt> tbcalc m92.als.1 xcenter "xcenter+5.4"
+ pt> tbcalc m92.als.1 ycenter "ycenter+10.3"
+.fi
+
+2. Add a constant to the computed magnitudes produced by the daophot
+package nstar task.
+
+.nf
+ pt> tbcalc n4147.nst.2 mag "mag+3.457"
+.fi
+
+.ih
+BUGS
+
+.ih
+SEE ALSO
+ptools.txcalc,tables.tcalc,ptools.pcalc
+.endhelp
diff --git a/noao/digiphot/ptools/doc/tbconcat.hlp b/noao/digiphot/ptools/doc/tbconcat.hlp
new file mode 100644
index 00000000..846b8f6e
--- /dev/null
+++ b/noao/digiphot/ptools/doc/tbconcat.hlp
@@ -0,0 +1,49 @@
+.help tbconcat Dec92 noao.digiphot.ptools
+.ih
+NAME
+tbconcat -- concatenate a list of APPHOT/DAOPHOT STSDAS databases
+.ih
+USAGE
+tbconcat tables outtable
+.ih
+PARAMETERS
+.ls tables
+The list of APPHOT/DAOPHOT STSDAS databases to be concatenated.
+.le
+.ls outtable
+The name of the output APPHOT/DAOPHOT STSDAS database.
+.le
+.ls task = "TASK"
+The name of the keyword whose value is the name of the task which wrote
+the database.
+.le
+.ih
+DESCRIPTION
+TBCONCAT is a simple task which accepts a list of APPHOT/DAOPHOT STSDAS
+database files and concatenates them into one resultant database.
+TBCONCAT checks that all the file are indeed APPHOT/DAOPHOT STSDAS
+database files and that they were all written by the same task before
+performing the concatenation.
+
+TBCONCAT is a simple script built around the STSDAS TABLES package
+task TMERGE. Users should consult the manual page for TMERGE for
+more details about the inner working of the task.
+
+.ih
+EXAMPLES
+
+1. Concatenate a list of DAOPHOT package GROUP output tables into a
+single file.
+
+.nf
+ pt> tbconcat m92r.grp.1,m92r.grp.2,m92r.grp.3 m92rall.grp.1
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+ptools.txconcat,ptools.pconcat,tables.tmerge,concatenate
+.endhelp
diff --git a/noao/digiphot/ptools/doc/tbcrename.hlp b/noao/digiphot/ptools/doc/tbcrename.hlp
new file mode 100644
index 00000000..47d4fd3f
--- /dev/null
+++ b/noao/digiphot/ptools/doc/tbcrename.hlp
@@ -0,0 +1,50 @@
+.help tbcrename Aug91 noao.digiphot.ptools
+.ih
+NAME
+tbcrename -- rename selected columns in a list of table
+
+.ih
+USAGE
+tbcrename tables columns names
+
+.ih
+PARAMETERS
+
+.ls table
+The list of input tables files.
+.le
+.ls columns
+The list of columns separated by commas whose names are to be changed.
+.le
+.ls names
+The list of new column names separated by commas.
+.le
+
+.ih
+DESCRIPTION
+
+TBCRENAME takes a list of ST tables \fItables\fR and changes the names
+of selected columns \fIcolumns\fR to the names specified in \fInames\fR.
+If the input file is not an ST table or the column does not exist
+no action is taken. Otherwise the specified column is renamed.
+
+.ih
+EXAMPLES
+
+1. For the list of ST tables in tablelist, rename the columns "MAG,MERR"
+to "MAG[1],MERR[1]". Note the use of '\' to escape the pattern matching
+meta-character '['.
+
+.nf
+ pt> tbcrename @tablelist "MAG,MERR" "MAG\[1],MERR\[1]"
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+Since the contents of the ST table are altered the user must have
+write permission on the table in order to run TBCRENAME.
+.ih
+SEE ALSO
+.endhelp
diff --git a/noao/digiphot/ptools/doc/tbdump.hlp b/noao/digiphot/ptools/doc/tbdump.hlp
new file mode 100644
index 00000000..3cb5eac4
--- /dev/null
+++ b/noao/digiphot/ptools/doc/tbdump.hlp
@@ -0,0 +1,193 @@
+.help tbdump Feb93 noao.digiphot.ptools
+.ih
+NAME
+tbdump -- print fields (columns) from a list of APPHOT/DAOPHOT STSDAS table
+ databases
+.ih
+USAGE
+tbdump tables columns expr
+.ih
+PARAMETERS
+.ls tables
+The name of the APPHOT/DAOPHOT table database(s) to be dumped.
+.le
+.ls columns
+The template specifying the names of the columns to be dumped.
+A null or blank string means
+dump all columns. A column template consists of a list
+of either column names or column patterns containing the usual pattern matching
+meta-characters. The names or patterns are separated by commas or white space.
+Column names must be spelled in full but may be upper or lower case.
+The columns list can be placed in a file and the name of the file preceded
+by an '@' character given in place of the column template.
+If the first non-white character in the column template
+is the negation character '~', the output will contain those columns
+NOT named in the remainder of the column template.
+.le
+.ls expr
+The boolean expression to be evaluated once per record.
+Only the fields in those records for which the boolean expression
+evaluates to yes are printed.
+If \fIexpr\fR = "yes", the specified columns in all the records are
+printed.
+.le
+.ls datafile = STDOUT
+If \fIDatafile\fR is not null ("") then the table data will be written
+to an output file with this name. By default the table data is written
+on the standard output.
+\fIDatafile\fR will not be created if the table is empty.
+.le
+.ls cdfile = ""
+If \fICdfile\fR is not null ("") then the column definitions will be written
+to an output file with this name.
+The column definitions consist of the column name, data type (R, D, I, B,
+or C), print format, and units.
+.le
+.ls pfile = ""
+If \fIPfile\fR is not null ("") then the header parameters will be written
+to an output file with this name.
+\fIPfile\fR will not be created if there are no header parameters.
+.le
+.ls rows = "-"
+\fIRows\fR is a string which may be used to specify ranges of rows which are
+to be dumped. The default of "-" means dump all rows. The first
+ten rows could be specified as \fIrows\fR = "1-10" or just \fIrows\fR = "-10".
+To dump the first ten rows and all rows from 900 through the last,
+use \fIrows\fR = "-10,900-". \fIRows\fR = "1,3,7,23" will print only
+those four rows. It is not an error to specify rows larger than the largest
+row number as they will simply be ignored.
+See the help for RANGES in XTOOLS for further information.
+.le
+.ls pagwidth = 158
+The width of the output for printing the table data. If any of the columns
+to be printed is wider than this an error message will be displayed, and
+the data will not be dumped. The width of each character column is
+increased by two to include a pair of enclosing quotes.
+.le
+.ih
+DESCRIPTION
+This task converts selected records from an APPHOT/DAOPHOT STSDAS table
+database to ASCII format
+and by default prints the result on the standard output.
+TBDUMP output does not include row numbers or column names.
+The TABLES package task TPRINT can be used for more readable output.
+
+The PTOOLS version of TBDUMP described here is
+actually a combination of the STSDAS TABLES package tasks TSELECT and TDUMP.
+
+The three primary uses for TBDUMP are to format STSDAS tables for input to
+applications
+which expect simple text input, allow editing that would be
+difficult or impossible with the TABLES package TEDIT task, such as
+global substitutions,
+and facilitate copying a table over a network to another computer.
+For the latter two applications the table can be dumped to three separate files
+containing column definitions, header parameters, and table data,
+edited, column data types changed, etc.
+The TABLES package TCREATE can be used to create a new table from the three
+ASCII files produced by TBDUMP.
+By default only the column data is dumped.
+
+TBDUMP queries for the columns to be dumped. If \fIcolumns\fR is null ("")
+then all the columns are dumped.
+All the rows are dumped by default, but ranges of
+rows may be specified with the \fIrows\fR parameter.
+If the table is wider than will fit on a page,
+the output will consist of more than one line per row of the table,
+but all the columns will be printed before moving on to the next row.
+This is in contrast to TPRINT,
+which prints all rows for those columns that will fit on a page,
+then prints all rows for the next set of columns, etc.
+Character columns with multiple words are printed with enclosing quotes.
+
+The TABLES package TLCOL task (with TLCOL.NLIST=1) may be used to generate
+a list of
+column names so there is no question about spelling or case. This list may
+be edited to rearrange the names and/or delete some, the list
+file preceded by an '@' and used as the value of the \fIcolumns\fR
+parameter.
+
+The output records are selected on the basis of an input boolean
+expression \fIexpr\fR whose variables are the tables column names.
+If after substituting the values associated
+with a particular record into the field name variables the
+expression evaluates
+to yes, that record is included in the output table.
+
+The supported
+operators and functions are briefly described below. A detailed description
+of the boolean expression evaluator and its syntax can be found
+in the manual page for the IMAGES package HEDIT task.
+
+The following logical operators can be used in the boolean expression.
+
+.nf
+ equal == not equal !=
+ less than < less than or equal <=
+ greater than > greater than or equal >=
+ or || and &&
+ negation ! pattern match ?=
+ concatenation //
+.fi
+
+The pattern match character ?= takes a
+string expression as its first argument and a pattern as its second argument.
+The result is yes if the pattern is contained in the string expression.
+Patterns are strings which may contain pattern matching meta-characters.
+The meta-characters themselves can be matched by preceeding them with the escape
+character. The meta-characters listed below.
+
+.nf
+ beginning of string ^ end of string $
+ one character ? zero or more characters *
+ white space # escape character \
+ ignore case { end ignore case }
+ begin character class [ end character class ]
+ not, in char class ^ range, in char class -
+.fi
+
+The expression may also include arithmetic operators and functions.
+The following arithmetic operators and functions are supported.
+
+.nf
+addition + subtraction -
+multiplication * division /
+negation - exponentiation **
+absolute value abs(x) cosine cos(x)
+sine sin(x) tangent tan(x)
+arc cosine acos(x) arc sine asin(x)
+arc tangent atan(x) arc tangent atan2(x,y)
+exponential exp(x) square root sqrt(x)
+natural log log(x) common log log10(x)
+minimum min(x,y) maximum max(x,y)
+convert to integer int(x) convert to real real(x)
+nearest integer nint(x) modulo mod(x)
+.fi
+.ih
+EXAMPLES
+.nf
+1. Dump the "ID", "MAG" and "MAGERR" columns of the DAOPHOT package NSTAR
+output to the standard output.
+
+ pt> tbdump n4147.nst.1 "ID,MAG,MAGERR" yes
+
+2. Dump the "ID", "MAG", and "MAGERR" columns of the above file for records
+which have "MAG <= 20.0".
+
+ pt> tbdump n4147.nst.1 "ID,MAG,MAGERR" "MAG <= 20.0"
+
+3. Dump the "MAG" and "MAGERR" columns of the above file and pipe the
+result to graph.
+
+ pt> tbdump n4147.nst.1 "MAG,MAGERR" yes | graph STDIN
+
+4. Dump all the columns in the first 100 rows of the above file.
+
+ pt> tbdump n4147.nst.1 "" yes rows="1-100"
+.fi
+.ih
+BUGS
+.ih
+SEE ALSO
+tables.tdump,tables.tprint,tables.tlcol,tables.tcreate,ptools.txdump,ptools.pdump
+.endhelp
diff --git a/noao/digiphot/ptools/doc/tbkeycol.hlp b/noao/digiphot/ptools/doc/tbkeycol.hlp
new file mode 100644
index 00000000..0c79b882
--- /dev/null
+++ b/noao/digiphot/ptools/doc/tbkeycol.hlp
@@ -0,0 +1,50 @@
+.help tbkeycol Aug91 noao.ptools.digiphot
+.ih
+NAME
+tbkeycol -- create new table columns from table header keywords
+
+.ih
+USAGE
+tbkeycol table keywords
+
+.ih
+PARAMETERS
+
+.ls table
+The list of input ST tables.
+.le
+.ls keywords
+The list of ST table header keywords, separated by commas, whose values will be
+copied into the newly created ST table columns.
+.le
+
+.ih
+DESCRIPTION
+
+TBKEYCOL takes a list of ST tables \fItable\fR and copies the values of the
+header keywords \fIkeywords\fR into newly created columns of the same name.
+If the input file is not an ST table, an output column of the same name as the
+keyword already exists, or the keyword does not exist, no action is
+taken. Otherwise a new column of the same name as the keyword is created,
+and the value of the keyword is copied into all rows of the table.
+
+.ih
+EXAMPLES
+
+1. For the list of ST tables in tablelist, copy the values of the header
+keywords "IMAGE", "ITIME", "IFILTER", and "XAIRMASS" into table columns
+of the same name.
+
+.nf
+ pt> tbkeycol @tablelist "IMAGE,ITIME,IFILTER,XAIRMASS"
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+Since the structure of the ST table is altered the user must have
+write permission on the table in order to run TBKEYCOL.
+.ih
+SEE ALSO
+.endhelp
diff --git a/noao/digiphot/ptools/doc/tbrenumber.hlp b/noao/digiphot/ptools/doc/tbrenumber.hlp
new file mode 100644
index 00000000..55c50770
--- /dev/null
+++ b/noao/digiphot/ptools/doc/tbrenumber.hlp
@@ -0,0 +1,54 @@
+.help tbrenumber May93 noao.digiphot.ptools
+.ih
+NAME
+tbrenumber -- renumber a list of APPHOT/DAOPHOT STSDAS table database(s)
+.ih
+USAGE
+tbrenumber tables
+.ih
+PARAMETERS
+.ls tables
+The list of APPHOT/DAOPHOT STSDAS table databases to be renumbered.
+.le
+.ls idoffset = 0
+An integer offset to be added to the id numbers of the stars in
+the output renumbered photometry file. If idoffset is > 0, the output
+id numbers will run from 1 + idoffset to N + idoffset instead of from 1 to N.
+.le
+.ls id = "ID"
+The name of the keyword whose value is the sequence number of the object
+in the database.
+.le
+.ih
+DESCRIPTION
+TBRENUMBER is a simple script task which accepts an APPHOT/DAOPHOT STSDAS
+table database and renumbers the objects from 1 + idoffset to N + idoffset,
+where N is the number
+of objects in the database. TBRENUMBER calls the TABLES package TCALC task
+to actually do the work.
+
+.ih
+EXAMPLES
+
+1. Renumber a concatenated NSTAR photometry file that has been written with
+TBCONCAT.
+
+.nf
+ pt> tbrenumber m92r.nst
+.fi
+
+2. Renumber a PHOT photometry file of extra stars so as to ensure the
+stars' id numbers are greater than 4000.
+
+.nf
+ pt> tbrenumber m92r.mag.extra idoffset=4000
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+ptools.txrenumber,ptools.prenumber,tables.tcalc
+.endhelp
diff --git a/noao/digiphot/ptools/doc/tbselect.hlp b/noao/digiphot/ptools/doc/tbselect.hlp
new file mode 100644
index 00000000..1a4ad6f4
--- /dev/null
+++ b/noao/digiphot/ptools/doc/tbselect.hlp
@@ -0,0 +1,107 @@
+.help tbselect Aug91 noao.digiphot.ptools
+.ih
+NAME
+tbselect -- create a new APPHOT/DAOPHOT table database from selected rows
+of an old APPHOT/DAOPHOT table database
+.ih
+USAGE
+tbselect intable outtable expr
+.ih
+PARAMETERS
+.ls intable
+The list of APPHOT/DAOPHOT STSDAS table databases from which rows are
+copied.
+.le
+.ls outtable
+The list of output APPHOT/DAOPHOT table databases to contain the copied rows.
+The number of output tables must equal the number of input tables.
+.le
+.ls expr
+The boolean expression which determines which rows are copied to the new
+table. \fIExpr\fR is evaluated once for each input row of data.
+If \fIexpr\fR is "yes" a copy is made of the old input table.
+.le
+.ih
+DESCRIPTION
+TSELECT creates a new APPHOT/DAOPHOT table database containing a subset of
+the rows in the old table database.
+The rows are selected on the basis of an input boolean expression whose
+variables are table column names.
+If after substituting the values associated
+with a particular row into the column name variables the expression evaluates
+to yes, that row is included in the output table.
+
+The supported
+operators and functions are briefly described below. A detailed description
+of the boolean expression evaluator and its syntax can be found
+in the manual page for the IMAGES package HEDIT task.
+
+The following logical operators can be used in the expression.
+
+.nf
+ equal == not equal !=
+ less than < less than or equal <=
+ greater than > greater than or equal >=
+ or || and &&
+ negation ! pattern match ?=
+ concatenation //
+.fi
+
+The pattern match character ?= takes a
+string expression as its first argument and a pattern as its second argument.
+The result is yes if the pattern is contained in the string expression.
+Patterns are strings which may contain pattern matching meta-characters.
+The meta-characters themselves can be matched by preceeding them with the escape
+character. The meta-characters are listed below.
+
+.nf
+ beginning of string ^ end of string $
+ one character ? zero or more characters *
+ white space # escape character \
+ ignore case { end ignore case }
+ begin character class [ end character class ]
+ not, in char class ^ range, in char class -
+.fi
+
+The expression may also include arithmetic operators and functions.
+The following arithmetic operators and functions are supported.
+
+.nf
+addition + subtraction -
+multiplication * division /
+negation - exponentiation **
+absolute value abs(x) cosine cos(x)
+sine sin(x) tangent tan(x)
+arc cosine acos(x) arc sine asin(x)
+arc tangent atan(x) arc tangent atan2(x,y)
+exponential exp(x) square root sqrt(x)
+natural log log(x) common log log10(x)
+minimum min(x,y) maximum max(x,y)
+convert to integer int(x) convert to real real(x)
+nearest integer nint(x) modulo mod(x)
+.fi
+.ih
+EXAMPLES
+
+1. Extract all stars brighter than twentieth magnitude from an
+the output of the DAOPHOT ALLSTAR task and create a new database.
+
+.nf
+ pt> tbselect m92.al.1 m92out "MAG <= 20.0"
+.fi
+
+2. Create a new database from the output of the DAOPHOT NSTAR task by
+removing all INDEF valued magnitudes.
+
+.nf
+ pt> tbselect n2264b.nst.1 n2264out "MAG != INDEF"
+
+.fi
+.ih
+BUGS
+Column names must be set off from operators by blanks in the expression so
+that they can be correctly parsed by the expression evaluator.
+.ih
+SEE ALSO
+ptools.txselect,tables.tselect,ptools.tbselect
+.endhelp
diff --git a/noao/digiphot/ptools/doc/tbsort.hlp b/noao/digiphot/ptools/doc/tbsort.hlp
new file mode 100644
index 00000000..6812868a
--- /dev/null
+++ b/noao/digiphot/ptools/doc/tbsort.hlp
@@ -0,0 +1,78 @@
+.help tbsort Aug91 noao.digiphot.ptools
+.ih
+NAME
+tbsort -- sort an APPHOT/DAOPHOT STSDAS table database on one or more columns
+.ih
+USAGE
+tbsort table columns
+.ih
+PARAMETERS
+.ls table
+The list of APPHOT/DAOPHOT table databases to be sorted in-place.
+All tables are sorted on the same column or columns.
+.le
+.ls columns
+The list of columns to sort on. A column template consists of a list of
+either column names, or column patterns containing the usual pattern matching
+meta-characters. The names or patterns are separated by commas or white space.
+The list can be placed in a file and the name of the file preceeded by a
+'@' can be given in place of the column template.
+.le
+.ls ascend = yes
+If \fIascend\fR = yes, the table is sorted in ascending value order, with the
+first
+row containing the smallest value of the sorted column. Otherwise, the table
+is sorted in descending order, with the largest value first.
+.le
+.ls casesens = yes
+If \fIcasesens\fR = yes, sorts on character columns are case sensitive,
+with upper case letters preceding lower case in the sort.
+Otherwise, the sort is case insensitive.
+.le
+.ih
+DESCRIPTION
+TBSORT sorts an APPHOT/DAOPHOT STSDAS table database.
+TBSORT operates in place so
+a copy of the unsorted table must be made with the TABLES
+package TCOPY task in order to preserve the original table.
+The column or columns to sort on are specified by the parameter
+\fIcolumns\fR, which is a list of column names or column name patterns
+separated by
+commas. The most significant column name is the first in the list. Subsequent
+columns are used to break ties. There are two flags, \fIascend\fR
+and \fIcasesens\fR. If \fIascend\fR is yes,
+the first row in the output table holds the smallest value if
+the sorted column is numeric or the first string in alphabetic order if the
+sorted column is a character string. If \fIcasesens\fR is yes,
+upper case characters
+precede lower case characters in sort order. Otherwise, case is not significant
+in determining the sort order. No precedes yes when sorting a boolean column
+in ascending order. Null table elements always are last in the sort, regardless
+of whether \fIascend\fR is yes or no.
+
+TBSORT is identical to the TABLES package sort with the exception that
+it has its own copy of the default parameter set so that users
+can modify the parameters independently of the TBSORT task in TABLES.
+.ih
+EXAMPLES
+
+1. Sort the output of the DAOPHOT ALLSTAR task in increasing order of
+magnitude.
+
+.nf
+ pt> tbsort m92.al.1 MAG
+.fi
+
+2. Sort the output of the DAOPHOT task NSTAR in increasing order of
+the y position.
+
+.nf
+ pt> tbsort m92.nst.1 YCENTER
+.fi
+
+.ih
+BUGS
+.ih
+SEE ALSO
+ptools.txsort,ptools.psort,tables.tbsort
+.endhelp
diff --git a/noao/digiphot/ptools/doc/txcalc.hlp b/noao/digiphot/ptools/doc/txcalc.hlp
new file mode 100644
index 00000000..747adabd
--- /dev/null
+++ b/noao/digiphot/ptools/doc/txcalc.hlp
@@ -0,0 +1,80 @@
+.help txcalc May93 noao.digiphot.ptools
+.ih
+NAME
+txcalc - perform an arithmetic operation on a field in a list of apphot/daophot
+ text databases
+.ih
+USAGE
+txcalc textfiles field value
+.ih
+PARAMETERS
+.ls textfiles
+The APPHOT/DAOPHOT text database(s) containing the field to be recomputed.
+.le
+.ls field
+The field to be recomputed. Field must be an integer or real field
+in the input file(s).
+.le
+.ls value
+The arithmetic expression used to recompute the specified field.
+Value may be an integer or real expression but must match the data
+type of field. The functions real and int may be used to do type
+conversions.
+.le
+
+.ih
+DESCRIPTION
+
+TXCALC reads in the values of the \fIfield\fR keyword
+from a set of APPHOT/DAOPHOT text databases, replaces the old values
+with new values equal to the value of the arithmetic expression \fIvalue\fR,
+and updates the text databases(s).
+
+The expression \fIvalue\fR consists of variables which are the field names
+specified by the #N keywords or the parameters specified by the
+#K keywords in the APPHOT/DAOPHOT text databases.
+Only keywords beginning with #N can actually be replaced.
+
+The supported
+arithmetic operators and functions are briefly described below.
+
+.nf
+addition + subtraction -
+multiplication * division /
+negation - exponentiation **
+absolute value abs(x) cosine cos(x)
+sine sin(x) tangent tan(x)
+arc cosine acos(x) arc sine asin(x)
+arc tangent atan(x) arc tangent atan2(x,y)
+exponential exp(x) square root sqrt(x)
+natural log log(x) common log log10(x)
+minimum min(x,y) maximum max(x,y)
+convert to integer int(x) convert to real real(x)
+nearest integer nint(x) modulo mod(x)
+.fi
+
+.ih
+EXAMPLES
+
+1. Change the XCENTER and YCENTER fields to XCENTER + 5.4 and YCENTER + 10.3
+respectively in a file produced by the apphot package center task.
+
+.nf
+ pt> txcalc m92.ctr.1 xcenter "xcenter+5.4"
+ pt> txcalc m92.ctr.1 ycenter "ycenter+10.3"
+.fi
+
+2. Add a constant to the computed magnitudes produced by nstar.
+
+.nf
+ pt> txcalc n4147.nst.2 mag "mag+3.457"
+.fi
+
+.ih
+BUGS
+TXCALC does not allow arrays in the expression field.
+
+.ih
+SEE ALSO
+ptools.tbcalc,tables.tcalc,ptools.pcalc
+.endhelp
diff --git a/noao/digiphot/ptools/doc/txconcat.hlp b/noao/digiphot/ptools/doc/txconcat.hlp
new file mode 100644
index 00000000..87516f72
--- /dev/null
+++ b/noao/digiphot/ptools/doc/txconcat.hlp
@@ -0,0 +1,45 @@
+.help txconcat Dec92 noao.digiphot.ptools
+.ih
+NAME
+txconcat -- concatenate a list of APPHOT/DAOPHOT text databases
+.ih
+USAGE
+txconcat textfiles outfile
+.ih
+PARAMETERS
+.ls textfiles
+The list of APPHOT/DAOPHOT text databases to be concatenated.
+.le
+.ls outfile
+The name of the output APPHOT/DAOPHOT text database.
+.le
+.ls task = "TASK"
+The name of the keywords whose value is the name of the task which wrote
+the database.
+.le
+.ih
+DESCRIPTION
+TXCONCAT is a simple task which accepts a list of APPHOT/DAOPHOT text
+database files and concatenates them into one resultant output file.
+TXCONCAT checks that all the file are indeed APPHOT/DAOPHOT text
+database files and that they were all written by the same task before
+performing the concatenation.
+
+.ih
+EXAMPLES
+
+1. Concatenate a list of DAOPHOT PHOT task result files into a single
+output file.
+
+.nf
+ pt> txconcat m92r.mag.1,m92r.mag.2,m92r.mag.3 m92rall.mag.1
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+ptools.tbconcat,ptools.pconcat,tables.tmerge,concatenate
+.endhelp
diff --git a/noao/digiphot/ptools/doc/txdump.hlp b/noao/digiphot/ptools/doc/txdump.hlp
new file mode 100644
index 00000000..bd432afb
--- /dev/null
+++ b/noao/digiphot/ptools/doc/txdump.hlp
@@ -0,0 +1,167 @@
+.help txdump Aug91 noao.digiphot.ptools
+.ih
+NAME
+txdump - print fields from selected records in an APPHOT/DAOPHOT text database
+.ih
+USAGE
+txdump textfiles fields expr
+.ih
+PARAMETERS
+.ls textfiles
+The APPHOT/DAOPHOT text database whose fields from selected records are to
+be printed.
+.le
+.ls fields
+A template defining the fields to be printed from each selected record.
+The fields are specified by keywords defined in the text database output
+files #K and #N entries. Upper or lower case and minimum match
+abbreviations are permissible. Some fields such as "mag" may have
+multiple entries. An individual entry can be referenced by specifying an
+array index, e.g. "mag[2]" or several values can be selected by
+specifying a range of elements, e.g. "mag[1-3]". The fields are output in
+the order in which they are specified in the template.
+.le
+.ls expr
+The boolean expression to be evaluated once per record.
+Only the fields in those records for which the boolean expression
+evaluates to yes are printed.
+If \fIexpr\fR = "yes", the specified fields in all the records are
+printed.
+.le
+.ls headers = no
+Preserve the APPHOT/DAOPHOT text database output format. The selected
+fields are printed on the standard output, preceded by parameters list,
+if \fIparameters\fR = yes, and the keyword, units,
+and format information, exactly as they appear in the text database.
+.le
+.ls parameters = yes
+Print the keyword parameters records in APPHOT/DAOPHOT format on the
+standard output if \fIheaders\fR = yes.
+.le
+
+.ih
+DESCRIPTION
+\fITXDUMP\fR selects a subset of fields specified by the \fIfields\fR
+parameter from an APPHOT/DAOPHOT text database or a list of databases by
+evaluating a boolean expression supplied by the user and prints the
+results on the standard output.
+If \fIheaders\fR = no, the resultant output is in simple list format
+with all the specified fields in one line of text and adjacent fields
+separated by whitespace. The fields are printed in the order in
+which they appear in \fIexpr\fR. If \fIheaders\fR = yes, the
+selected fields are printed on the standard output, preceded by
+the parameter list, if \fIparameters\fR = yes, and the keyword, units,
+and format information, exactly as they appear in the text database.
+Newlines will not be inserted in the output so users should take
+care not to exceed the IRAF text file line limit of 161 characters.
+
+The output records are selected on the basis of an input boolean
+expression \fIexpr\fR whose variables are the field names
+specified by the #N keywords or the parameters specified by the
+#K keywords in the APPHOT/DAOPHOT text database.
+If after substituting the values associated
+with a particular record into the field name variables the
+expression evaluates
+to yes, that record is included in the output table.
+
+The supported
+operators and functions are briefly described below. A detailed description
+of the boolean expression evaluator and its syntax can be found
+in the manual page for the IMAGES package HEDIT task.
+
+The following logical operators can be used in the boolean expression.
+
+.nf
+ equal == not equal !=
+ less than < less than or equal <=
+ greater than > greater than or equal >=
+ or || and &&
+ negation ! pattern match ?=
+ concatenation //
+.fi
+
+The pattern match character ?= takes a
+string expression as its first argument and a pattern as its second argument.
+The result is yes if the pattern is contained in the string expression.
+Patterns are strings which may contain pattern matching meta-characters.
+The meta-characters themselves can be matched by preceeding them with the escape
+character. The meta-characters listed below.
+
+.nf
+ beginning of string ^ end of string $
+ one character ? zero or more characters *
+ white space # escape character \
+ ignore case { end ignore case }
+ begin character class [ end character class ]
+ not, in char class ^ range, in char class -
+.fi
+
+The expression may also include arithmetic operators and functions.
+The following arithmetic operators and functions are supported.
+
+.nf
+addition + subtraction -
+multiplication * division /
+negation - exponentiation **
+absolute value abs(x) cosine cos(x)
+sine sin(x) tangent tan(x)
+arc cosine acos(x) arc sine asin(x)
+arc tangent atan(x) arc tangent atan2(x,y)
+exponential exp(x) square root sqrt(x)
+natural log log(x) common log log10(x)
+minimum min(x,y) maximum max(x,y)
+convert to integer int(x) convert to real real(x)
+nearest integer nint(x) modulo mod(x)
+.fi
+
+.ih
+EXAMPLES
+
+1. Print the fields XCENTER and YCENTER from the output of the APPHOT
+CENTER task.
+
+.nf
+ pt> txdump image.ctr.1 XCENTER,YCENTER yes
+.fi
+
+2. Select the fields ID, XCENTER, YCENTER and the first three magnitudes
+MAG{1-3] from the output of the APPHOT PHOT task.
+
+.nf
+ pt> txdump image.mag.2 "ID,XCEN,YCEN,MAG[1-3]" yes
+.fi
+
+3. Print all fields for all records in the above file with a magnitude
+through the first aperture of less than 20.0.
+
+.nf
+ pt> txdump image.mag.2 * "MAG[1] < 20.0"
+.fi
+
+4. Print the id and all magnitudes for which magnitudes 1 and 2 are < 20.0
+from a file which is the output of the APPHOT PHOT task.
+
+.nf
+ pt> txdump image.mag.3 ID,MAG "MAG[1] < 20.0 && MAG[2] < 20.0"
+.fi
+
+5. Select the ID, XCENTER, YCENTER, MSKY and MAG fields from the output
+ of the DAOPHOT NSTAR task for records where the magnitude is not
+ INDEF, while preserving the format of the text database so it
+ is suitable for input into a rerun of NSTAR.
+
+.nf
+ pt> txdump image.nst.1 "ID,XCENTER,YCENTER,MSKY,MAG" \
+ "MAG[1] != INDEF" headers+
+.fi
+
+.ih
+BUGS
+TXDUMP does not allow arrays in the expression field.
+
+Users should not dump more fields than fill a 161 character textline
+as IRAF does not currently fully support longer text lines.
+.ih
+SEE ALSO
+images.hedit,ptools.tbdump,tables.tdump,ptools.pdump
+.endhelp
diff --git a/noao/digiphot/ptools/doc/txrenumber.hlp b/noao/digiphot/ptools/doc/txrenumber.hlp
new file mode 100644
index 00000000..67ac5a42
--- /dev/null
+++ b/noao/digiphot/ptools/doc/txrenumber.hlp
@@ -0,0 +1,59 @@
+.help txrenumber May93 noao.digiphot.ptools
+.ih
+NAME
+txrenumber -- renumber a list of APPHOT/DAOPHOT text database
+.ih
+USAGE
+txrenumber textfiles
+.ih
+PARAMETERS
+.ls textfiles
+The APPHOT/DAOPHOT text database to be renumbered.
+.le
+.ls idoffset = 0
+An integer offset to be added to the id numbers of the stars in
+the output renumbered photometry file. If idoffset is > 0, the output
+id numbers will run from 1 + idoffset to N + idoffset instead of from 1 to N.
+.le
+.ls id = "ID"
+The name of the keyword whose value is the sequence number of the object in
+the list. After renumbering the original values of the \fIid\fR are replaced
+by numbers 1 through N, where N is the total number of objects in the list.
+The id keyword must denote an integer quantity.
+.le
+.ih
+DESCRIPTION
+TXRENUMBER is a simple task which accepts an APPHOT/DAOPHOT text
+database file and renumbers all the objects in the file beginning
+with 1 and ending with the number of objects in the file.
+The renumber operation is performed in place. The original
+values of the \fIid\fR field are replaced by numbers 1 + idoffset
+through N + idoffset
+where N is the total number of objects in the list.
+A renumber operation is typically performed after another
+list operation such as TXCONCAT or TXSORT.
+
+.ih
+EXAMPLES
+
+1. Renumber the stars in a concatenated file produced by TXCONCAT.
+
+.nf
+ pt> txrenumber m92rall.mag.1
+.fi
+
+2. Renumber a PHOT photometry file of extra stars so as to ensure the
+stars' id numbers are greater than 4000.
+
+.nf
+ pt> txrenumber m92r.mag.extra idoffset=4000
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+ptools.tbrenumber,ptools.prenumber,tables.tcalc
+.endhelp
diff --git a/noao/digiphot/ptools/doc/txselect.hlp b/noao/digiphot/ptools/doc/txselect.hlp
new file mode 100644
index 00000000..b80357ea
--- /dev/null
+++ b/noao/digiphot/ptools/doc/txselect.hlp
@@ -0,0 +1,121 @@
+.help txselect Aug91 noao.digiphot.ptools
+.ih
+NAME
+txselect - select records from an APPHOT/DAOPHOT text database
+.ih
+USAGE
+txselect textfiles outfiles expr
+.ih
+PARAMETERS
+.ls textfiles
+The APPHOT/DAOPHOT text database(s) containing the records from which the
+selection is to be made.
+.le
+.ls outfiles
+The output APPHOT/DAOPHOT text database(s) containing the selected records.
+.le
+.ls expr
+The boolean expression to be evaluated once for each record.
+Each input record for which \fIexpr\fR evaluates as "yes" will be
+written to the output file.
+If \fIexpr\fR = yes, a copy is made of the input file.
+.le
+
+.ih
+DESCRIPTION
+TXSELECT selects a subset of the records
+from a set of APPHOT/DAOPHOT text databases
+and writes the new records out to another set of text databases.
+
+The output records are selected on the basis of an input boolean
+expression \fIexpr\fR whose variables are the field names
+specified by the #N keywords or the parameters specified by the
+#K keywords in the APPHOT/DAOPHOT text database.
+If after substituting the values associated
+with a particular record into the field name variables the
+expression evaluates
+to yes, that record is included in the output database.
+
+The supported
+operators and functions are briefly described below. A detailed description
+of the boolean expression evaluator and its syntax can be found
+in the manual page for the IMAGES package HEDIT task.
+
+The following logical operators can be used in the boolean expression.
+
+.nf
+ equal == not equal !=
+ less than < less than or equal <=
+ greater than > greater than or equal >=
+ or || and &&
+ negation ! pattern match ?=
+ concatenation //
+.fi
+
+The pattern match character ?= takes a
+string expression as its first argument and a pattern as its second argument.
+The result is yes if the pattern is contained in the string expression.
+Patterns are strings which may contain pattern matching meta-characters.
+The meta-characters themselves can be matched by preceeding them with the escape
+character. The meta-characters listed below.
+
+.nf
+ beginning of string ^ end of string $
+ one character ? zero or more characters *
+ white space # escape character \
+ ignore case { end ignore case }
+ begin character class [ end character class ]
+ not, in char class ^ range, in char class -
+.fi
+
+The boolean expression may also include arithmetic operators and functions.
+The following arithmetic operators and functions are supported.
+
+.nf
+addition + subtraction -
+multiplication * division /
+negation - exponentiation **
+absolute value abs(x) cosine cos(x)
+sine sin(x) tangent tan(x)
+arc cosine acos(x) arc sine asin(x)
+arc tangent atan(x) arc tangent atan2(x,y)
+exponential exp(x) square root sqrt(x)
+natural log log(x) common log log10(x)
+minimum min(x,y) maximum max(x,y)
+convert to integer int(x) convert to real real(x)
+nearest integer nint(x) modulo mod(x)
+.fi
+
+.ih
+EXAMPLES
+
+1. Select the records from the output of the APPHOT CENTER task for
+which 100. <= XCENTER <= 200. and 300. <= YCENTER <= 400.
+
+.nf
+ pt> txselect m92.ctr.1 m92out \
+ "XCE >= 100. && XCE <= 200. && YCE >= 300. && YCE <= 400."
+.fi
+
+2. Select the records from the output of the APPHOT PHOT task for which
+the first magnitude is not equal to INDEF.
+
+.nf
+ pt> txselect n4147.mag.2 n4147out "MAG[1] != INDEF"
+.fi
+
+3. Select the records from the output of the DAOPHOT ALLSTAR task
+ for which CHI <= 5.0 and MERR <= .10 magnitudes.
+
+.nf
+ pt> txselect m92b.al.1 m92out "CHI <= 5.0 && MERR <= 1.0"
+.fi
+
+.ih
+BUGS
+TXSELECT does not allow arrays in the expression field.
+
+.ih
+SEE ALSO
+images.hselect,images.hedit,ptools.tbselect,tables.tselect,ptools.pselect
+.endhelp
diff --git a/noao/digiphot/ptools/doc/txsort.hlp b/noao/digiphot/ptools/doc/txsort.hlp
new file mode 100644
index 00000000..b9a324fd
--- /dev/null
+++ b/noao/digiphot/ptools/doc/txsort.hlp
@@ -0,0 +1,61 @@
+.help txsort Aug91 noao.digiphot.ptools
+.ih
+NAME
+txsort -- sort a list of APPHOT/DAOPHOT text database file(s)
+.ih
+USAGE
+txsort textfile field
+.ih
+PARAMETERS
+.ls textfiles
+The input APPHOT/DAOPHOT text database(s) to be sorted.
+The sort is performed in place.
+.le
+.ls field
+The field to be sorted on. \fIField\fR may be any quantity defined by
+the APPHOT/DAOPHOT #K and #N keywords. The keywords may be
+of type integer or real, in which case a numeric sort is performed,
+boolean, in which case the boolean constant "no" has a smaller value
+than "yes", or character in which case an alphabetic sort is performed.
+.le
+.ls ascend = yes
+Sort in increasing value order.
+.le
+.ih
+DESCRIPTION
+TXSORT is a simple task which accepts a list of APPHOT/DAOPHOT text
+database files
+and sorts them in place based on the value of the selected field
+specifier \fIfield\fR. By default the sort is performed in increasing order
+of the value
+of \fIfield\fR, but a reverse sort can be performed by
+setting \fIascend\fR = "no".
+
+If \fIfield\fR is a real or integer quantity the sort is numeric; if boolean
+the boolean constant "no" is assumed to have a smaller value than "yes"; if
+character the sort is alphabetic.
+.ih
+EXAMPLES
+
+1. Sort the output of the APPHOT task PHOT in increasing order of
+the y position.
+
+.nf
+ pt> txsort m92.mag.1 YCENTER
+.fi
+
+2. Sort the output of the DAOPHOT task ALLSTAR in increasing order of
+ magnitude.
+
+.nf
+ pt> txsort m92.al.1 MAG
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+ptools.tbsort,tables.tsort,ptools.psort,sort
+.endhelp
diff --git a/noao/digiphot/ptools/histplot.par b/noao/digiphot/ptools/histplot.par
new file mode 100644
index 00000000..59148ea9
--- /dev/null
+++ b/noao/digiphot/ptools/histplot.par
@@ -0,0 +1,20 @@
+# The PEXAMINE task histogram plotting task parameters
+
+nbins,i,h,10,1,,Number of bins in histogram
+z1,r,h,INDEF,,,Minimum histogram intensity
+z2,r,h,INDEF,,,Maximum histogram intensity
+top_closed,b,h,yes,,,Include z2 in the top bin?
+x1,r,h,INDEF,,,Left world X-coord if not autoscaling
+x2,r,h,INDEF,,,Right world X-coord if not autoscaling
+y1,r,h,INDEF,,,Lower world Y-coord if not autoscaling
+y2,r,h,INDEF,,,Upper world Y-coord if not autoscaling
+logy,b,h,yes,,,Log scale the y axis ?
+box,b,h,yes,,,Draw box around periphery of window ?
+ticklabels,b,h,yes,,,Label tick marks ?
+majrx,i,h,5,,,Number of major divisions along x axis
+minrx,i,h,5,,,Number of minor divisions along x axis
+majry,i,h,5,,,Number of major divisions along y axis
+minry,i,h,5,,,Number of minor divisions along y axis
+round,b,h,no,,,Round axes to nice values ?
+fill,b,h,yes,,,Fill viewport vs enforce unity aspect ratio ?
+banner,b,h,yes,,,Standard banner ?
diff --git a/noao/digiphot/ptools/istable.par b/noao/digiphot/ptools/istable.par
new file mode 100644
index 00000000..fa135764
--- /dev/null
+++ b/noao/digiphot/ptools/istable.par
@@ -0,0 +1,7 @@
+# ISTABLE Parameters
+
+infile,s,a,,,,Input file
+table,b,h,no,,,Is the file a tables file ?
+text,b,h,no,,,Is the file a text database file ?
+other,b,h,no,,,Is the file neither a tables or a text database file ?
+mode,s,h,"ql",,,Mode of task
diff --git a/noao/digiphot/ptools/lib/strip.ptoolsx b/noao/digiphot/ptools/lib/strip.ptoolsx
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/noao/digiphot/ptools/lib/strip.ptoolsx
diff --git a/noao/digiphot/ptools/lib/warning.dat b/noao/digiphot/ptools/lib/warning.dat
new file mode 100644
index 00000000..a27f7da2
--- /dev/null
+++ b/noao/digiphot/ptools/lib/warning.dat
@@ -0,0 +1,12 @@
+
+
+ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+ WARNING FROM THE PTOOLS PACKAGE LOADER
+ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+
+ The SDAS external package TABLES required by some of the PTOOLS
+ tasks is not available. The tasks TBAPPEND, TBDUMP, TBRENUMBER,
+ TBSELECT, and TBSORT will not run. The tasks PAPPEND, PDUMP,
+ PRENUMBER, PSELECT and PSORT will run only on APPHOT/DAOPHOT
+ output files written in the default text format, not on files
+ written in ST tables format.
diff --git a/noao/digiphot/ptools/mkpkg b/noao/digiphot/ptools/mkpkg
new file mode 100644
index 00000000..b8a75eaa
--- /dev/null
+++ b/noao/digiphot/ptools/mkpkg
@@ -0,0 +1,38 @@
+# PTOOLSX libraries
+
+$call relink
+$exit
+
+update:
+ $call relink
+ $call install
+ ;
+
+relink:
+ $omake x_ptools.x
+ !mkpkg -p noao trelink XF="$(XFLAGS)" LF="$(LFLAGS)"
+ ;
+
+linkonly:
+ !mkpkg -p noao trelink XF="$(XFLAGS)" LF="$(LFLAGS)"
+ $call install
+ ;
+
+install:
+ $move xx_ptools.e noaobin$x_ptools.e
+ ;
+
+trelink:
+ $set LIBS = "-lds -lncar -lgks -lxtools -ltbtables"
+ $set XFLAGS = "$(XFLAGS) $(XF)"
+ $set LFLAGS = "$(LFLAGS) $(LF)"
+ $update libpkg.a
+ $link x_ptools.o libpkg.a ../lib/libpttables.a $(LIBS) -o xx_ptools.e
+ ;
+
+libpkg.a:
+ @pconvert
+ @pexamine
+ @ptutils
+ @txtools
+ ;
diff --git a/noao/digiphot/ptools/pcalc.cl b/noao/digiphot/ptools/pcalc.cl
new file mode 100644
index 00000000..494e7ee7
--- /dev/null
+++ b/noao/digiphot/ptools/pcalc.cl
@@ -0,0 +1,50 @@
+# PCALC - Recompute a column of an APPHOT/DAOPHOT database using an
+# arithmetic expression.
+
+procedure pcalc (infile, field, value)
+
+string infile {prompt="Input apphot/daophot databases(s)"}
+string field {prompt="Field to be edited"}
+string value {prompt="New value or expression for field"}
+
+struct *inlist
+
+begin
+ # Local variable declarations.
+ file tmpin
+ string in, tfield, tvalue, inname
+
+ # Cache the istable parameters.
+ cache ("istable")
+
+ # Get the positional parameters.
+ in = infile
+ tfield = field
+ tvalue = value
+
+ # Expand the file list names.
+ tmpin = mktemp ("tmp$")
+ files (in, sort=no, > tmpin)
+
+ # Loop over each file in the input and output lists selecting records.
+ inlist = tmpin
+ while (fscan (inlist, inname) != EOF) {
+ istable (inname)
+ if (istable.table) {
+ if (defpar ("tcalc.verbose") || defpar ("tcalc.harmless")) {
+ tcalc (inname, tfield, tvalue, datatype="real",
+ colunits="", colfmt="", verbose=no, harmless=0.1)
+ } else {
+ tcalc (inname, tfield, tvalue, datatype="real",
+ colunits="", colfmt="")
+ }
+ } else if (istable.text) {
+ txcalc (inname, tfield, tvalue)
+ } else {
+ print ("Cannot run PCALC on file: " // inname)
+ }
+ }
+ inlist = ""
+
+ delete (tmpin, ver-, >& "dev$null")
+end
diff --git a/noao/digiphot/ptools/pconcat.cl b/noao/digiphot/ptools/pconcat.cl
new file mode 100644
index 00000000..7d098eee
--- /dev/null
+++ b/noao/digiphot/ptools/pconcat.cl
@@ -0,0 +1,56 @@
+# PCONCAT -- Concatenate a list of apphot/daophot databases into a single
+# output database. The input files must either be all text files or all data
+# files. PCONCAT checks that the input files were all created by the same
+# task.
+
+procedure pconcat (infiles, outfile)
+
+file infiles {prompt = "Input apphot/daophot database(s) to be concatenated"}
+file outfile {prompt = "Output apphot/daophot database"}
+string task {"TASK", prompt="Task name keyword"}
+
+struct *inlist
+
+begin
+ # Declare local variables.
+ bool table, text, other
+ file in, out
+ string tmpin, inname
+
+ # Cache the istable parameters.
+ cache ("istable")
+
+ # Get the positional parameters.
+ in = infiles
+ out = outfile
+
+ # Make a file lists.
+ tmpin = mktemp ("tmp$")
+ files (in, sort=no, > tmpin)
+
+ # Check to see whether the first file is a text database or a table.
+
+ inlist = tmpin
+ if (fscan (inlist, inname) != EOF) {
+ istable (inname)
+ table = istable.table
+ text = istable.text
+ other = istable.other
+ } else {
+ table = no
+ text = no
+ other = no
+ }
+ delete (tmpin, ver-, >& "dev$null")
+ inlist = ""
+
+ # Do the actual appending.
+ if (table)
+ tbconcat (in, out, task=task)
+ else if (text)
+ txconcat (in, out, task=task)
+ else if (access (inname))
+ print ("File " // inname // " is not an APPHOT/DAOPHOT database")
+ else
+ print ("File " // inname // " does not exist")
+end
diff --git a/noao/digiphot/ptools/pconvert.par b/noao/digiphot/ptools/pconvert.par
new file mode 100644
index 00000000..eb3fdd0c
--- /dev/null
+++ b/noao/digiphot/ptools/pconvert.par
@@ -0,0 +1,8 @@
+# CONVERT Parameters
+
+textfile,s,a,,,,Input apphot/daophot text database
+table,s,a,,,,Output apphot/daophot table database
+fields,s,a,"*",,,Fields to be extracted
+expr,s,h,yes,,,Boolean expression used for record selection
+append,b,h,no,,,Append to existing table ?
+mode,s,h,"ql",,,Mode of task
diff --git a/noao/digiphot/ptools/pconvert/mkpkg b/noao/digiphot/ptools/pconvert/mkpkg
new file mode 100644
index 00000000..362576cb
--- /dev/null
+++ b/noao/digiphot/ptools/pconvert/mkpkg
@@ -0,0 +1,14 @@
+# PCONVERT task
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ ptconvert.x <error.h> <evexpr.h> \
+ <tbset.h> ../../lib/ptkeysdef.h
+ ptdeftable.x ../../lib/ptkeysdef.h <tbset.h> <ctype.h>
+ ptstrwrd.x
+ t_pconvert.x <fset.h>
+ ;
diff --git a/noao/digiphot/ptools/pconvert/ptconvert.x b/noao/digiphot/ptools/pconvert/ptconvert.x
new file mode 100644
index 00000000..8ac97ac8
--- /dev/null
+++ b/noao/digiphot/ptools/pconvert/ptconvert.x
@@ -0,0 +1,236 @@
+include <error.h>
+include <evexpr.h>
+include <tbset.h>
+include "../../lib/ptkeysdef.h"
+
+# PT_APCONVERT -- Procedure to select records from a text file in pseudo list
+# format.
+
+procedure pt_convert (fd, td, fields, expr, append)
+
+int fd # text file descriptor
+int td # table file descriptor
+char fields[ARB] # fields to be output
+char expr[ARB] # boolean expression to be evaluated
+int append # append to an existing table
+
+bool oexpr
+int nchars, nunique, uunique, funique, ncontinue, recptr, rownum
+int ntotkeys, first_rec, printall, table_defined
+pointer sp, line, colpoints, key, o
+
+bool streq()
+extern pt_getop ()
+int getline(), strncmp(), tbpsta(), pt_deftable(), pt_apptable()
+pointer evexpr(), locpr()
+real asumi()
+
+begin
+
+ # Allocate temporary working space.
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+
+ # Initialize the keys structure.
+ call pt_kyinit (key)
+
+ # Initialize the counters.
+ nunique = 0
+ uunique = 0
+ funique = 0
+
+ # Initalize the record reading code.
+ table_defined = NO
+ first_rec = YES
+ recptr = 1
+ ncontinue = 0
+
+ # Initialize the expression evaluator.
+ o = NULL
+ if (streq (expr, "yes")) {
+ oexpr = true
+ printall = YES
+ } else {
+ oexpr = false
+ printall = NO
+ }
+
+ # Initialize the pointer for writing rows.
+ if (append == YES)
+ rownum = tbpsta (td, TBL_NROWS)
+ else
+ rownum = 0
+
+ # Loop over the text file records.
+ nchars = getline (fd, Memc[line])
+ while (nchars != EOF) {
+
+ # Determine the type of record.
+ if (Memc[line] == KY_CHAR_POUND) {
+ if (strncmp (Memc[line], KY_CHAR_KEYWORD, KY_LEN_STR) == 0) {
+ call pt_kyadd (key, Memc[line], nchars)
+ } else if (strncmp (Memc[line], KY_CHAR_NAME,
+ KY_LEN_STR) == 0) {
+ nunique = nunique + 1
+ call pt_kname (key, Memc[line], nchars, nunique)
+ } else if (strncmp (Memc[line], KY_CHAR_UNITS,
+ KY_LEN_STR) == 0) {
+ uunique = uunique + 1
+ call pt_knunits (key, Memc[line], nchars, uunique)
+ } else if (strncmp (Memc[line], KY_CHAR_FORMAT,
+ KY_LEN_STR) == 0) {
+ funique = funique + 1
+ call pt_knformats (key, Memc[line], nchars, funique)
+ }
+
+ } else if (Memc[line] == KY_CHAR_NEWLINE) {
+ # skip blank lines
+
+ } else {
+
+ # Construct the table record.
+ call pt_mkrec (key, Memc[line], nchars, first_rec, recptr,
+ ncontinue)
+
+ # Construct output record when there is no continuation char.
+ if (Memc[line+nchars-2] != KY_CHAR_CONT) {
+
+ # Construct the output table if not defined.
+ if (table_defined == NO) {
+
+ # Compute the maximum number of keys.
+ ntotkeys = nint (asumi (Memi[KY_NELEMS(key)],
+ KY_NKEYS(key)))
+
+ # Allocate space for the column pointers.
+ call salloc (colpoints, ntotkeys, TY_INT)
+
+ # Initialize the table.
+ if (append == NO) {
+ if (pt_deftable (td, key, fields,
+ Memi[colpoints]) <= 0)
+ break
+ } else if (append == YES) {
+ if (pt_apptable (td, key, fields,
+ Memi[colpoints]) <= 0)
+ break
+ }
+
+ table_defined = YES
+ }
+
+ # Evaluate the expression.
+ iferr {
+ if (printall == NO) {
+ call pt_apset (key)
+ o = evexpr (expr, locpr (pt_getop), 0)
+ if (O_TYPE(o) != TY_BOOL)
+ call error (0, "Expression must be a boolean")
+ oexpr = O_VALB(o)
+ }
+ } then {
+ call erract (EA_WARN)
+ call xev_freeop (o)
+ call mfree (o, TY_STRUCT)
+ break
+ }
+
+ # Construct the output record.
+ if (oexpr) {
+ rownum = rownum + 1
+ call pt_putrec (td, Memi[colpoints], key, rownum)
+ }
+
+ # Get ready for next record.
+ ncontinue = 0
+ recptr = 1
+ first_rec = NO
+ if (o != NULL) {
+ call xev_freeop (o)
+ call mfree (o, TY_STRUCT)
+ }
+ }
+ }
+
+ # Read the next line.
+ nchars = getline (fd, Memc[line])
+ }
+
+ # Free the keys structure.
+ call pt_kyfree (key)
+ call sfree (sp)
+end
+
+
+# PT_PUTREC -- Add a row to the table.
+
+procedure pt_putrec (td, colpoints, key, rownum)
+
+pointer td # table descriptor
+pointer colpoints[ARB] # pointers for columns
+pointer key # key structure
+int rownum # row number
+
+int i, index, elem, kip, maxch, n, nk, ncols
+int number, datatype, lendata, lenfmt, ival
+pointer sp, colname, colunits, colfmt, str
+real rval
+bool streq()
+int ctor(), ctoi()
+
+begin
+ call smark (sp)
+ call salloc (colname, SZ_COLNAME+1, TY_CHAR)
+ call salloc (colunits, SZ_PARREC+1, TY_CHAR)
+ call salloc (colfmt, SZ_PARREC+1, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # For each selected field move into the table
+ ncols = 0
+ do i = 1, KY_NSELECT(key) {
+
+ # Get the pointer to the desired value.
+ index = Memi[KY_SELECT(key)+i-1]
+ elem = Memi[KY_ELEM_SELECT(key)+i-1]
+ maxch = Memi[KY_LEN_SELECT(key)+i-1]
+ kip = Memi[KY_PTRS(key)+index-1] + (elem - 1) * maxch
+
+ # Trim leading and trailing whitespace from the value and
+ # copy value to output buffer.
+
+ for (n = 0; Memc[kip] == ' '; n = n + 1)
+ kip = kip + 1
+ for (nk = 0; Memc[kip+nk] != ' ' && n <= maxch; nk = nk + 1)
+ n = n + 1
+ call strcpy (Memc[kip], Memc[str], nk)
+
+ # Find info about this column.
+ ncols = ncols + 1
+ call tbcinf (colpoints[ncols], number, Memc[colname],
+ Memc[colunits], Memc[colfmt], datatype, lendata, lenfmt)
+
+ # Move the selected value into the column.
+ kip = 1
+ switch (datatype) {
+ case TY_INT:
+ if (ctoi (Memc[str], kip, ival) <= 0)
+ call tbrpti (td, colpoints[ncols], INDEFI, 1, rownum)
+ else
+ call tbrpti (td, colpoints[ncols], ival, 1, rownum)
+ case TY_REAL:
+ if (ctor (Memc[str], kip, rval) <= 0)
+ call tbrptr (td, colpoints[ncols], INDEFR, 1, rownum)
+ else
+ call tbrptr (td, colpoints[ncols], rval, 1, rownum)
+ case TY_BOOL:
+ if (streq ("yes", Memc[str]))
+ call tbrptb (td, colpoints[ncols], true, 1, rownum)
+ else
+ call tbrptb (td, colpoints[ncols], false, 1, rownum)
+ default:
+ call tbrptt (td, colpoints[ncols], Memc[str], nk, 1, rownum)
+ }
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/ptools/pconvert/ptdeftable.x b/noao/digiphot/ptools/pconvert/ptdeftable.x
new file mode 100644
index 00000000..86fb2c35
--- /dev/null
+++ b/noao/digiphot/ptools/pconvert/ptdeftable.x
@@ -0,0 +1,375 @@
+#include <ctype.h>
+include <tbset.h>
+include "../../lib/ptkeysdef.h"
+
+# PT_DEFTABLE -- Set up and create the table for the conversion of
+# the APPHOT text file.
+
+int procedure pt_deftable (td, key, fields, columns)
+
+pointer td # output table descriptor
+pointer key # key structure
+char fields[ARB] # fields to be output to the table
+int columns[ARB] # pointer to array of column pointers
+
+int ncols
+int pt_defcols()
+
+begin
+ # Define the table columns.
+ ncols = pt_defcols (td, key, fields, columns)
+ if (ncols <= 0)
+ return (0)
+
+ # Define the table header.
+ call pt_defheader (td, key)
+
+ return (ncols)
+end
+
+
+# PT_DEFHEADER -- Define the header structure.
+
+procedure pt_defheader (td, key)
+
+pointer td # table descriptor
+pointer key # pointer to the keys structure
+
+int i, index, type, len, ival, ip
+pointer sp, kname, value, ptr
+real rval
+bool streq()
+int pt_strwrd(), pt_kstati(), ctoi(), ctor()
+
+begin
+ call smark (sp)
+ call salloc (kname, SZ_KEYWORD, TY_CHAR)
+ call salloc (value, KY_SZPAR, TY_CHAR)
+
+ # Define the columns determining datatype from the format string.
+ do i = 1, KY_NPKEYS(key) {
+
+ index = pt_strwrd (i, Memc[kname], SZ_KEYWORD, Memc[KY_WORDS(key)])
+ if (index <= 0)
+ next
+
+ ptr = Memi[KY_PTRS(key)+index-1]
+ len = pt_kstati (key, Memc[kname], KY_LENGTH)
+ call strcpy (Memc[ptr], Memc[value], len)
+ type = pt_kstati (key, Memc[kname], KY_DATATYPE)
+
+ switch (type) {
+ case TY_INT:
+ ip = 1
+ if (ctoi (Memc[value], ip, ival) <= 0)
+ call tbhadi (td, Memc[kname], INDEFI)
+ else
+ call tbhadi (td, Memc[kname], ival)
+ case TY_REAL:
+ ip = 1
+ if (ctor (Memc[value], ip, rval) <= 0)
+ call tbhadr (td, Memc[kname], INDEFR)
+ else
+ call tbhadr (td, Memc[kname], rval)
+ case TY_BOOL:
+ if (streq ("yes", Memc[value]))
+ call tbhadb (td, Memc[kname], true)
+ else
+ call tbhadb (td, Memc[kname], false)
+ default:
+ call tbhadt (td, Memc[kname], Memc[value])
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# PT_DEFCOLS -- Define the data columns to be output.
+
+int procedure pt_defcols (td, key, fields, columns)
+
+pointer td # table Descriptor
+pointer key # key structure
+char fields[ARB] # fields selected
+pointer columns[ARB] # array of pointers for columns
+
+int max_nkeys, index, ncols, element, nelems, type, len
+pointer sp, kname, aranges, ranges, rangeset, colname, colunits, colformat
+pointer list
+
+int pt_gnfn(), strdic(), pt_ranges(), get_next_number()
+int decode_ranges(), pt_kstati()
+pointer pt_ofnl()
+real asumi()
+errchk tbcdef()
+
+begin
+ # Allocate working space.
+
+ call smark (sp)
+ call salloc (kname, KY_SZPAR, TY_CHAR)
+ call salloc (aranges, SZ_FNAME, TY_CHAR)
+ call salloc (ranges, SZ_FNAME, TY_CHAR)
+ call salloc (rangeset, 3 * KY_MAXNRANGES, TY_INT)
+
+ call salloc (colname, SZ_COLNAME, TY_CHAR)
+ call salloc (colunits, SZ_COLUNITS, TY_CHAR)
+ call salloc (colformat, SZ_COLFMT, TY_CHAR)
+
+ # Initialize the select buffers. The select keyword, format
+ # and units string buffers are not necessary in this application.
+
+ max_nkeys = nint (asumi (Memi[KY_NELEMS(key)], KY_NKEYS(key)))
+ if (KY_SELECT(key) != NULL)
+ call mfree (KY_SELECT(key), TY_INT)
+ call malloc (KY_SELECT(key), max_nkeys, TY_INT)
+ if (KY_ELEM_SELECT(key) != NULL)
+ call mfree (KY_ELEM_SELECT(key), TY_INT)
+ call malloc (KY_ELEM_SELECT(key), max_nkeys, TY_INT)
+ if (KY_LEN_SELECT(key) != NULL)
+ call mfree (KY_LEN_SELECT(key), TY_INT)
+ call malloc (KY_LEN_SELECT(key), max_nkeys, TY_INT)
+
+ # Initialize the number of columns.
+ ncols = 0
+
+ # Open the list of fields.
+ list = pt_ofnl (key, fields)
+
+ # Loop over the fields.
+ while (pt_gnfn (list, Memc[kname], Memc[aranges], KY_SZPAR) != EOF) {
+
+ # Find location of the field in the keyword dictionary and
+ # expand the ranges string if it is defined.
+ index = strdic (Memc[kname], Memc[kname], KY_SZPAR,
+ Memc[KY_WORDS(key)])
+ if (pt_ranges (Memc[aranges], Memc[ranges], element, SZ_LINE) ==
+ ERR)
+ call error (0, "Cannot decode DAOPHOT range string")
+
+ # The field was not found.
+ if (index == 0) {
+ next
+
+ # Reject keyword fields.
+ } else if (index <= KY_NPKEYS (key)) {
+ next
+
+ # The field is single valued.
+ } else if (Memi[KY_NELEMS(key)+index-1] == 1) {
+
+ # Enter the pointers into the select buffer.
+ Memi[KY_SELECT(key)+ncols] = index
+ Memi[KY_ELEM_SELECT(key)+ncols] = 1
+ len = pt_kstati (key, Memc[kname], KY_LENGTH)
+ Memi[KY_LEN_SELECT(key)+ncols] = len
+ ncols = ncols + 1
+
+ # Get the column name, the units and the formats.
+ call strcpy (Memc[kname], Memc[colname], SZ_COLNAME)
+ call pt_kstats (key, Memc[kname], KY_UNITSTR, Memc[colunits],
+ SZ_COLUNITS)
+ call pt_kstats (key, Memc[kname], KY_FMTSTR, Memc[colformat],
+ SZ_COLFMT)
+
+ # Create the column determining the datatype from the
+ # format string.
+ type = pt_kstati (key, Memc[kname], KY_DATATYPE)
+ if (type != TY_CHAR)
+ call tbcdef (td, columns[ncols], Memc[colname],
+ Memc[colunits], Memc[colformat], type, 1, 1)
+ else
+ call tbcdef (td, columns[ncols], Memc[colname],
+ Memc[colunits], Memc[colformat], -len, 1, 1)
+
+ # The field is multi-valued.
+ } else {
+
+ if (Memc[ranges] == EOS) {
+ call sprintf (Memc[ranges], SZ_FNAME, "1-%d")
+ call pargi (Memi[KY_NELEMS(key)+index-1])
+ }
+ if (decode_ranges (Memc[ranges], Memi[rangeset], KY_MAXNRANGES,
+ nelems) == ERR)
+ call error (0, "Cannot decode ranges string")
+
+ nelems = 0
+ while (get_next_number (Memi[rangeset], nelems) != EOF) {
+ if (nelems < 1 || nelems > Memi[KY_NELEMS(key)+index-1])
+ break
+
+ len = pt_kstati (key, Memc[kname], KY_LENGTH)
+ Memi[KY_SELECT(key)+ncols] = index
+ Memi[KY_ELEM_SELECT(key)+ncols] = nelems
+ Memi[KY_LEN_SELECT(key)+ncols] = len
+ ncols = ncols + 1
+
+ # Get the column name, units and format.
+ call sprintf (Memc[colname], SZ_COLNAME, "%s[%d]")
+ call pargstr (Memc[kname])
+ call pargi (nelems)
+ call pt_kstats (key, Memc[kname], KY_UNITSTR,
+ Memc[colunits], SZ_COLUNITS)
+ call pt_kstats (key, Memc[kname], KY_FMTSTR,
+ Memc[colformat], SZ_COLFMT)
+
+ # Create the column determining the datatype from the
+ # format string.
+ type = pt_kstati (key, Memc[kname], KY_DATATYPE)
+ if (type != TY_CHAR)
+ call tbcdef (td, columns[ncols], Memc[colname],
+ Memc[colunits], Memc[colformat], type, 1, 1)
+ else
+ call tbcdef (td, columns[ncols], Memc[colname],
+ Memc[colunits], Memc[colformat], -len, 1, 1)
+ }
+ }
+ }
+
+ # Create the table.
+ call tbpset (td, TBL_MAXPAR, KY_NPKEYS(key))
+ call tbtcre (td)
+
+ # Free the space
+ call pt_cfnl (list)
+ call sfree (sp)
+
+ # Reallocate select buffer space
+ KY_NSELECT(key) = ncols
+ call realloc (KY_SELECT(key), KY_NSELECT(key), TY_INT)
+ call realloc (KY_ELEM_SELECT(key), KY_NSELECT(key), TY_INT)
+ call realloc (KY_LEN_SELECT(key), KY_NSELECT(key), TY_INT)
+
+ return (ncols)
+end
+
+
+# PT_APPTABLE -- Find the array of column pointers for appending to an
+# existing ST table.
+
+int procedure pt_apptable (td, key, fields, columns)
+
+pointer td # the table descriptor
+pointer key # key structure
+char fields[ARB] # string containing fields to include in table
+pointer columns[ARB] # Array of pointers for columns
+
+int max_nkeys, index, ncols, element, nelems
+pointer list, sp, kname, aranges, ranges, rangeset, colname
+int pt_gnfn(), strdic(), pt_ranges(), get_next_number(), decode_ranges()
+int pt_kstati()
+pointer pt_ofnl()
+real asumi()
+
+begin
+ # Allocate buffer space.
+ call smark (sp)
+ call salloc (kname, KY_SZPAR, TY_CHAR)
+ call salloc (aranges, SZ_FNAME, TY_CHAR)
+ call salloc (ranges, SZ_FNAME, TY_CHAR)
+ call salloc (rangeset, 3 * KY_MAXNRANGES, TY_INT)
+ call salloc (colname, SZ_COLNAME, TY_CHAR)
+
+ # Initialize the select buffers. The select keyword, format
+ # and units string buffers are not necessary in this application.
+
+ max_nkeys = nint (asumi (Memi[KY_NELEMS(key)], KY_NKEYS(key)))
+ max_nkeys = nint (asumi (Memi[KY_NELEMS(key)], KY_NKEYS(key)))
+ if (KY_SELECT(key) != NULL)
+ call mfree (KY_SELECT(key), TY_INT)
+ call malloc (KY_SELECT(key), max_nkeys, TY_INT)
+ if (KY_ELEM_SELECT(key) != NULL)
+ call mfree (KY_ELEM_SELECT(key), TY_INT)
+ call malloc (KY_ELEM_SELECT(key), max_nkeys, TY_INT)
+ if (KY_LEN_SELECT(key) != NULL)
+ call mfree (KY_LEN_SELECT(key), TY_INT)
+ call malloc (KY_LEN_SELECT(key), max_nkeys, TY_INT)
+
+ # Initialize the number of columns.
+ ncols = 0
+
+ # Initialize the list of fields.
+ ncols = 0
+ list = pt_ofnl (key, fields)
+
+ # Loop over the fields.
+ while (pt_gnfn (list, Memc[kname], Memc[aranges], KY_SZPAR) != EOF) {
+
+ # Find the column.
+ index = strdic (Memc[kname], Memc[kname], KY_SZPAR,
+ Memc[KY_WORDS(key)])
+ if (pt_ranges (Memc[aranges], Memc[ranges], element,
+ SZ_LINE) == ERR)
+ call error (0, "Cannot decode DAOPHOT range string")
+
+ # Skip if the column does exist in the text database.
+ if (index == 0)
+ next
+
+ # Skip the header keywords.
+ else if (index <= KY_NPKEYS (key))
+ next
+
+ # Convert single-valued elements.
+ else if (Memi[KY_NELEMS(key)+index-1] == 1) {
+
+ call strcpy (Memc[kname], Memc[colname], SZ_COLNAME)
+ call tbcfnd (td, Memc[colname], columns[ncols+1], 1)
+ if (columns[ncols+1] == NULL) {
+ call eprintf ("Column %s not found\n")
+ call pargstr (Memc[colname])
+ } else {
+ Memi[KY_SELECT(key)+ncols] = index
+ Memi[KY_ELEM_SELECT(key)+ncols] = 1
+ Memi[KY_LEN_SELECT(key)+ncols] = pt_kstati (key,
+ Memc[kname], KY_LENGTH)
+ ncols = ncols + 1
+ }
+
+ # Convert multivalued elements.
+ } else {
+
+ if (Memc[ranges] == EOS) {
+ call sprintf (Memc[ranges], SZ_FNAME, "1-%d")
+ call pargi (Memi[KY_NELEMS(key)+index-1])
+ }
+ if (decode_ranges (Memc[ranges], Memi[rangeset], KY_MAXNRANGES,
+ nelems) == ERR)
+ call error (0, "Cannot decode ranges string")
+
+ nelems = 0
+ while (get_next_number (Memi[rangeset], nelems) != EOF) {
+ if (nelems < 1 || nelems > Memi[KY_NELEMS(key)+index-1])
+ break
+ call sprintf (Memc[colname], SZ_COLNAME, "%s[%d]")
+ call pargstr (Memc[kname])
+ call pargi (nelems)
+ call tbcfnd (td, Memc[colname], columns[ncols+1], 1)
+ if (columns[ncols+1] == NULL) {
+ call eprintf ("Column %s not found\n")
+ call pargstr (Memc[colname])
+ } else {
+ Memi[KY_SELECT(key)+ncols] = index
+ Memi[KY_ELEM_SELECT(key)+ncols] = nelems
+ Memi[KY_LEN_SELECT(key)+ncols] = pt_kstati (key,
+ Memc[kname], KY_LENGTH)
+ ncols = ncols + 1
+ }
+
+ }
+ }
+ }
+
+ # Free the space
+ call pt_cfnl (list)
+ call sfree (sp)
+
+ # Reallocate select buffer space
+ KY_NSELECT(key) = ncols
+ call realloc (KY_SELECT(key), KY_NSELECT(key), TY_INT)
+ call realloc (KY_ELEM_SELECT(key), KY_NSELECT(key), TY_INT)
+ call realloc (KY_LEN_SELECT(key), KY_NSELECT(key), TY_INT)
+
+ return (ncols)
+end
diff --git a/noao/digiphot/ptools/pconvert/ptstrwrd.x b/noao/digiphot/ptools/pconvert/ptstrwrd.x
new file mode 100644
index 00000000..31a9974b
--- /dev/null
+++ b/noao/digiphot/ptools/pconvert/ptstrwrd.x
@@ -0,0 +1,51 @@
+# PT_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 pt_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/ptools/pconvert/t_pconvert.x b/noao/digiphot/ptools/pconvert/t_pconvert.x
new file mode 100644
index 00000000..fafcbf5f
--- /dev/null
+++ b/noao/digiphot/ptools/pconvert/t_pconvert.x
@@ -0,0 +1,53 @@
+include <fset.h>
+
+# T_PCONVERT -- Procedure to convert the records within a text file into
+# an STSDAS Table.
+
+procedure t_pconvert ()
+
+pointer text # pointer to name of text file
+pointer fields # pointer list of fields
+pointer table # pointer to STSDAS table
+pointer expr # Pointer to boolean expression
+int append # open file in append mode
+
+int fd, td
+pointer sp
+bool clgetb()
+int open(), btoi(), fstati(), tbtopn()
+
+begin
+
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (text, SZ_LINE, TY_CHAR)
+ call salloc (fields, SZ_LINE, TY_CHAR)
+ call salloc (table, SZ_LINE, TY_CHAR)
+ call salloc (expr, SZ_LINE, TY_CHAR)
+
+ # Get the parameters.
+ call clgstr ("textfile", Memc[text], SZ_LINE)
+ call clgstr ("table", Memc[table], SZ_LINE)
+ call clgstr ("fields", Memc[fields], SZ_LINE)
+ call strupr (Memc[fields])
+ call clgstr ("expr", Memc[expr], SZ_LINE)
+ append = btoi (clgetb ("append"))
+
+ # Open the table.
+ fd = open (Memc[text], READ_ONLY, TEXT_FILE)
+ if (append == YES)
+ td = tbtopn (Memc[table], READ_WRITE, 0)
+ else
+ td = tbtopn (Memc[table], NEW_FILE, 0)
+
+ # Select records.
+ call pt_convert (fd, td, Memc[fields], Memc[expr], append)
+
+ # Close up.
+ call close (fd)
+ call tbtclo (td)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/ptools/pdump.cl b/noao/digiphot/ptools/pdump.cl
new file mode 100644
index 00000000..5ac4b5fd
--- /dev/null
+++ b/noao/digiphot/ptools/pdump.cl
@@ -0,0 +1,83 @@
+# PDUMP - Select fields from an ST table or an APPHOT/DAOPHOT text file
+# and dump to a text file.
+
+procedure pdump (infiles, fields, expr)
+
+string infiles {prompt="Input apphot/daophot databases(s)"}
+string fields {prompt="Fields to be extracted"}
+string expr {"yes", prompt="Boolean expression"}
+bool headers {no, prompt="Print field headers?"}
+bool parameters {yes, prompt="Print parameters?"}
+
+struct *inlist
+
+begin
+ # Local variable declarations.
+ file tmpin, texpr
+ int nin, tpagwidth
+ string in, col, inname, hfile, pfile
+
+ # Cache the istable parameters.
+ cache ("istable")
+
+ # Get the positional parameters.
+ in = infiles
+ col = fields
+ texpr = expr
+
+ # Make temporary names.
+ tmpin = mktemp ("tmp$")
+
+ # Expand the file list names.
+ files (in, sort=no, > tmpin)
+
+ # Compute the length of the input list.
+ inlist = tmpin
+ for (nin = 0; fscan (inlist, inname) != EOF; nin = nin + 1)
+ ;
+ inlist = ""
+
+ # Delete the temporary files.
+ delete (tmpin, ver-, >& "dev$null")
+
+ # Expand the file list names.
+ files (in, sort=no, > tmpin)
+
+ if (headers) {
+ hfile = "STDOUT"
+ if (parameters)
+ pfile = "STDOUT"
+ else
+ pfile = ""
+ } else {
+ hfile = ""
+ pfile = ""
+ }
+
+ # Loop over each file in the input list selecting records.
+ inlist = tmpin
+ while (fscan (inlist, inname) != EOF) {
+ istable (inname)
+ if (istable.table) {
+
+ # Adjust pagination for TDUMP.
+ #tpagwidth = tdump.pwidth.p_max
+ tdump.pwidth.p_max = 1023
+
+ tbdump (inname, col, texpr, cdfile=hfile, pfile=pfile,
+ datafile="STDOUT", rows="-", pagwidth=1023)
+
+ # Reset pagination for TDUMP.
+ #tdump.pwidth.p_max = tpagwidth
+
+ } else if (istable.text) {
+ txdump (inname, col, texpr, headers=headers,
+ parameters=parameters)
+ } else {
+ print ("ERROR: Cannot run PDUMP on file: " // inname)
+ }
+ }
+
+ delete (tmpin, ver-, >& "dev$null")
+ inlist = ""
+end
diff --git a/noao/digiphot/ptools/pexamine.par b/noao/digiphot/ptools/pexamine.par
new file mode 100644
index 00000000..50dd0e75
--- /dev/null
+++ b/noao/digiphot/ptools/pexamine.par
@@ -0,0 +1,20 @@
+# The PEXAMINE task parameter set
+
+input,s,a,,,,"Name of the input catalog"
+output,s,a,"",,,"Name of the edited output catalog"
+image,s,a,"",,,Name of the image corresponding to the input catalog
+deletions,s,h,"",,,"Name of the output catalog for deleted entries"
+photcolumns,s,h,"daophot",,,"Names of the standard photometry columns"
+xcolumn,s,h,mag,,,"Catalog column which is the X axis of X-Y plot"
+ycolumn,s,h,merr,,,"Catalog column which is the Y axis of X-Y plot"
+hcolumn,s,h,mag,,,"Catalog column which is to be binned"
+xposcolumn,s,h,"xcenter",,,"Name of the x coordinate column"
+yposcolumn,s,h,"ycenter",,,"Name of the y coordinate column"
+usercolumns,s,h,"",,,"Names of additional user selected columns"
+max_nstars,i,h,5000,1,,Maximum number of stars to load
+first_star,i,h,1,1,,First star in the catalog to load
+match_radius,r,h,2.0,,,Matching radius for positional coincidence on display
+graphics,s,h,"stdgraph",,,The graphics device
+gcommands,*gcur,h,"",,,Graphics cursor commands
+icommands,*imcur,h,"",,,Image cursor commands
+use_display,b,h,yes,,,Use the image display ?
diff --git a/noao/digiphot/ptools/pexamine/mkpkg b/noao/digiphot/ptools/pexamine/mkpkg
new file mode 100644
index 00000000..b2aa7dd8
--- /dev/null
+++ b/noao/digiphot/ptools/pexamine/mkpkg
@@ -0,0 +1,21 @@
+# The mkpkg file for the PEXAMINE task.
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ ptahgmr.x <mach.h> pexamine.h
+ ptalimr.x <mach.h>
+ ptcolon.x <gset.h> pexamine.h
+ ptdelete.x <gset.h> <mach.h> pexamine.h
+ ptgetphot.x <tbset.h> ../../lib/ptkeysdef.h pexamine.h
+ ptimplot.x <imhdr.h> <math.h> <gset.h> <mach.h>
+ ptplot.x <error.h> <fset.h> <tbset.h> <gset.h> <mach.h> \
+ <ctype.h> ../../lib/ptkeysdef.h pexamine.h
+ ptrddata.x ../../lib/ptkeysdef.h pexamine.h
+ ptsetup.x <error.h> pexamine.h <ctotok.h>
+ ptwtfile.x ../../lib/ptkeysdef.h pexamine.h
+ t_pexamine.x <error.h> <fset.h> pexamine.h
+ ;
diff --git a/noao/digiphot/ptools/pexamine/pexamine.h b/noao/digiphot/ptools/pexamine/pexamine.h
new file mode 100644
index 00000000..138ff1f4
--- /dev/null
+++ b/noao/digiphot/ptools/pexamine/pexamine.h
@@ -0,0 +1,115 @@
+# The PEXAMINE structure definitions.
+
+# Define the task termination conditions.
+
+define PX_QUIT 0
+define PX_EXIT 1
+
+# Define the delete indices
+
+define PX_GOOD 0
+define PX_DELETE 1
+define PX_MARK 2
+
+# Define some useful constants.
+
+define PX_SZCOLNAME 19 # the maximum length of a column name
+define PX_MAXNCOLS 20 # the maximum number of columns
+
+# Define the default photometry columns.
+
+define PX_DAOCOLS ",GROUP,ID,XCENTER,YCENTER,MSKY,STDEV,MAG,MERR,NITER,\
+CHI,SHARPNESS,ROUNDNESS"
+define PX_APCOLS ",ID,XCENTER,YCENTER,MSKY,STDEV,MAG,MERR,"
+
+# Define the structure.
+
+define LEN_PXSTRUCT (15 + 10 * PX_SZCOLNAME + 10)
+
+define PX_RNPHOT Memi[$1] # number of req'd photometry columns
+define PX_RNUSER Memi[$1+1] # number of req'd user columns
+define PX_RNCOLS Memi[$1+2] # total number of req'd columns
+define PX_RCOLNAMES Memi[$1+3] # ptr to list of req'd column names
+define PX_NPHOT Memi[$1+4] # number of photometry columns
+define PX_NUSER Memi[$1+5] # number of user columns
+define PX_NCOLS Memi[$1+6] # total number of stored columns
+define PX_COLNAMES Memi[$1+7] # ptr to list of stored column names
+define PX_COLPTRS Memi[$1+8] # ptr to array of stored column pointers
+
+define PX_RXCOLNAME Memc[P2C($1+10)] # the req'd x column
+define PX_RYCOLNAME Memc[P2C($1+10+PX_SZCOLNAME+1)] # the req'd y column
+define PX_XCOLNAME Memc[P2C($1+10+2*PX_SZCOLNAME+2)] # the x column
+define PX_YCOLNAME Memc[P2C($1+10+3*PX_SZCOLNAME+3)] # the y column
+define PX_RXPOSNAME Memc[P2C($1+10+4*PX_SZCOLNAME+4)] # the req'd xp column
+define PX_RYPOSNAME Memc[P2C($1+10+5*PX_SZCOLNAME+5)] # the req'd yp column
+define PX_XPOSNAME Memc[P2C($1+10+6*PX_SZCOLNAME+6)] # the x coord column
+define PX_YPOSNAME Memc[P2C($1+10+7*PX_SZCOLNAME+7)] # the y coord column
+define PX_RHCOLNAME Memc[P2C($1+10+8*PX_SZCOLNAME+8)] # the req'd hgm column
+define PX_HCOLNAME Memc[P2C($1+10+9*PX_SZCOLNAME+9)] # the hgm column
+
+# Define the colon commands arguments
+
+define PX_PCMDS "|photcolumns|usercolumns|xcolumn|ycolumn|hcolumn|xposcolumn|\
+yposcolumn|eparam|unlearn|x1|x2|y1|y2|marker|szmarker|grid|logx|logy|box|\
+ticklabels|majrx|minrx|majry|minry|round|fill|nbins|z1|z2|top_closed|rinner|\
+router|ncolumns|nlines|axes|angh|angv|floor|ceiling|zero|ncontours|interval|\
+nhi|dashpat|label|delete|"
+
+define PX_PCMD_PHOTCOLUMNS 1
+define PX_PCMD_USERCOLUMNS 2
+define PX_PCMD_XCOLUMN 3
+define PX_PCMD_YCOLUMN 4
+define PX_PCMD_HCOLUMN 5
+define PX_PCMD_XPOSCOLUMN 6
+define PX_PCMD_YPOSCOLUMN 7
+define PX_PCMD_EDIT 8
+define PX_PCMD_UNLEARN 9
+define PX_PCMD_X1 10
+define PX_PCMD_X2 11
+define PX_PCMD_Y1 12
+define PX_PCMD_Y2 13
+define PX_PCMD_MARKER 14
+define PX_PCMD_SZMARKER 15
+define PX_PCMD_GRID 16
+define PX_PCMD_LOGX 17
+define PX_PCMD_LOGY 18
+define PX_PCMD_BOX 19
+define PX_PCMD_TICKLABELS 20
+define PX_PCMD_MAJRX 21
+define PX_PCMD_MINRX 22
+define PX_PCMD_MAJRY 23
+define PX_PCMD_MINRY 24
+define PX_PCMD_ROUND 25
+define PX_PCMD_FILL 26
+define PX_PCMD_NBINS 27
+define PX_PCMD_Z1 28
+define PX_PCMD_Z2 29
+define PX_PCMD_TOP_CLOSED 30
+define PX_PCMD_RIN 31
+define PX_PCMD_ROUT 32
+define PX_PCMD_NCOLUMNS 33
+define PX_PCMD_NLINES 34
+define PX_PCMD_AXES 35
+define PX_PCMD_ANGH 36
+define PX_PCMD_ANGV 37
+define PX_PCMD_FLOOR 38
+define PX_PCMD_CEILING 39
+define PX_PCMD_ZERO 40
+define PX_PCMD_NCONTOURS 41
+define PX_PCMD_INTERVAL 42
+define PX_PCMD_NHI 43
+define PX_PCMD_DASHPAT 44
+define PX_PCMD_LABEL 45
+define PX_PCMD_DELETE 46
+
+# Define the plot types
+
+define PX_PLOTTYPES "|xyplot|histplot|radplot|surfplot|cntrplot|"
+
+define PX_XYPLOT 1
+define PX_HISTPLOT 2
+define PX_RADPLOT 3
+define PX_SURFPLOT 4
+define PX_CNTRPLOT 5
+
+define PX_MARKERS "|point|box|plus|cross|circle|hline|vline|diamond|"
diff --git a/noao/digiphot/ptools/pexamine/pexamine.key b/noao/digiphot/ptools/pexamine/pexamine.key
new file mode 100644
index 00000000..892e0542
--- /dev/null
+++ b/noao/digiphot/ptools/pexamine/pexamine.key
@@ -0,0 +1,146 @@
+ PEXAMINE Interactive Cursor Keystroke Commands
+
+ Basic Commands
+
+? Print help for the PEXAMINE task
+: PEXAMINE colon commands
+g Activate the graphics cursor
+i Activate the image cursor
+e Exit PEXAMINE and save the edited catalog
+q Quit PEXAMINE and discard the edited catalog
+
+ Data Examining Commands
+
+l List the name, datatype and units for all columns in the catalog
+o Print out the names and values of the stored columns for the
+ object nearest the cursor
+x Replot the current y column versus the current x column
+h Replot the current histogram
+r Plot the radial profile of the object nearest the cursor
+s Plot the surface of the object nearest the cursor
+c Plot the contour plot of the object nearest the cursor
+m Print the data values of the object nearest the cursor
+p Replot the current graph
+
+ Data Editing Commands
+
+z Reinitialize the data by removing all deletions and replot
+d Mark the point nearest the cursor for deletion
+u Undelete the marked point nearest the cursor
+t Toggle between marking points for deletion or undeletion
+( Mark points with X < X (cursor) for deletion or undeletion
+) Mark points with X > X (cursor) for deletion or undeletion
+v Mark points with Y < Y (cursor) for deletion or undeletion
+^ Mark points with Y > Y (cursor) for deletion or undeletion
+b Mark points inside a box for deletion or undeletion
+f Actually delete the marked points and replot
+
+
+ PEXAMINE Interactive Colon Commands
+
+:xcolumn [name] Show/set the X-Y plot X axis quantity
+:ycolumn [name] Show/set the X-Y plot Y axis quantity
+:hcolumn [name] Show/set the histogram plot quantity
+:photcolumns [col1,col2,...] Show/set the list of photometry columns
+:usercolumns [col1,col2,...] Show/set the list of user columns
+:delete [yes/no] Delete or undelete points
+:eparam [x/h/r/s/c] Edit/unlearn the specified plot pset
+ or
+:unlearn
+
+
+ PEXAMINE Interactive X-Y Plotting Commands
+
+:x1 [value] Left world x-coord if not autoscaling
+:x2 [value] Right world x-coord if not autoscaling
+:y1 [value] Lower world y-coord if not autoscaling
+:y2 [value] Upper world y-coord if not autoscaling
+:szmarker [value] Marker size
+:marker [point|box|plus|cross|circle|diamond|hline|vline] Marker type
+:logx [yes/no] Log scale the x axis?
+:logy [yes/no] Log scale the y axis?
+:box [yes/no] Draw box around periphery of window?
+:ticklabels [yes/no] Label tick marks?
+:grid [yes/no] Draw grid lines at major tick marks?
+:majrx [value] Number of major divisions along x axis
+:minrx [value] Number of minor divisions along x axis
+:majry [value] Number of major divisions along y axis
+:minry [value] Number of minor divisions along y axis
+:round [yes/no] Round axes to nice values?
+:fill [yes/no] Fill viewport vs enforce unity aspect ratio?
+
+
+ PEXAMINE Interactive Histogram Plotting Commands
+
+:nbins [value] Number of bins in the histogram
+:z1 [value] Minimum histogram intensity
+:z2 [value] Maximum histogram intensity
+:top_closed [y/n] Include z in the top bin?
+:x1 [value] Left world x-coord if not autoscaling
+:x2 [value] Right world x-coord if not autoscaling
+:y1 [value] Lower world y-coord if not autoscaling
+:y2 [value] Upper world y-coord if not autoscaling
+:logy [yes/no] Log scale the y axis?
+:box [yes/no] Draw box around periphery of window?
+:ticklabels [yes/no] Label tick marks?
+:majrx [value] Number of major divisions along x axis
+:minrx [value] Number of minor divisions along x axis
+:majry [value] Number of major divisions along y axis
+:minry [value] Number of minor divisions along y axis
+:round [yes/no] Round axes to nice values?
+:fill [yes/no] Fill viewport vs enforce unity aspect ratio?
+
+ PEXAMINE Interactive Radial Profile Plotting Commands
+
+:rinner [value] Inner radius of the region to be plotted
+:router [value] Outer radius of the region to be plotted
+:x1 [value] Left world x-coord if not autoscaling
+:x2 [value] Right world x-coord if not autoscaling
+:y1 [value] Lower world y-coord if not autoscaling
+:y2 [value] Upper world y-coord if not autoscaling
+:szmarker [value] Marker size
+:marker [point|box|plus|cross|circle|diamond|hline|vline] Marker type
+:logx [yes/no] Log scale the x axis?
+:logy [yes/no] Log scale the y axis?
+:box [yes/no] Draw box around periphery of window?
+:ticklabels [yes/no] Label tick marks?
+:grid [yes/no] Draw grid lines at major tick marks?
+:majrx [value] Number of major divisions along x axis
+:minrx [value] Number of minor divisions along x axis
+:majry [value] Number of major divisions along y axis
+:minry [value] Number of minor divisions along y axis
+:round [yes/no] Round axes to nice values?
+:fill [yes/no] Fill viewport vs enforce unity aspect ratio?
+
+
+ PEXAMINE Interactive Surface Plotting Commands
+
+:ncolumns [value] Number of columns to be plotted
+:nlines [value] Number of lines to be plotted
+:axes [yes/no] Draw axes?
+:angh [value] Horizontal viewing angle
+:angv [value] Vertical viewing angle
+:floor [value] Minimum value to be plotted
+:ceiling [value] Maximum value to be plotted
+
+
+ PEXAMINE Interactive Contour Plotting Commands
+
+:ncolumns [value] Number of columns to be plotted
+:nlines [value] Number of lines to be plotted
+:floor [value] Minimum value to be plotted
+:ceiling [value] Maximum value to be plotted
+:zero [value] Greyscale value of zero contour
+:ncontours [value] Number of contours to be drawn
+:interval [value] Contour interval
+:nhi [value] Hi/low marking option
+:dashpat [value] Bit pattern for generating dashed lines
+:label [yes/no] Label major contours with their values?
+:box [yes/no] Draw box around periphery of window?
+:ticklabels [yes/no] Label tick marks?
+:majrx [value] Number of major divisions along x axis
+:minrx [value] Number of minor divisions along x axis
+:majry [value] Number of major divisions along y axis
+:minry [value] Number of minor divisions along y axis
+:round [yes/no] Round axes to nice values?
+:fill [yes/no] Fill viewport vs enforce unity aspect ratio?
diff --git a/noao/digiphot/ptools/pexamine/ptahgmr.x b/noao/digiphot/ptools/pexamine/ptahgmr.x
new file mode 100644
index 00000000..acf303b5
--- /dev/null
+++ b/noao/digiphot/ptools/pexamine/ptahgmr.x
@@ -0,0 +1,44 @@
+include <mach.h>
+include "pexamine.h"
+
+# PT_AHGMR -- Accumulate the histogram of the input vector. The output vector
+# HGM (the histogram) should be cleared prior to the first call. Delete
+# points or points marked for deletion are not included in the plot.
+
+procedure pt_ahgmr (data, delete, npix, hgm, nbins, z1, z2)
+
+real data[ARB] # data vector
+int delete[ARB] # deletions array
+int npix # number of pixels
+int hgm[ARB] # output histogram
+int nbins # number of bins in histogram
+real z1, z2 # greyscale values of first and last bins
+
+real z
+real dz
+int bin, i
+
+begin
+ dz = real (nbins - 1) / real (z2 - z1)
+ if (abs (dz - 1.0) < (EPSILONR * 2.0)) {
+ do i = 1, npix {
+ if ((delete[i] == PX_DELETE) || (delete[i] == PX_MARK))
+ next
+ z = data[i]
+ if (z >= z1 && z <= z2) {
+ bin = int (z - z1) + 1
+ hgm[bin] = hgm[bin] + 1
+ }
+ }
+ } else {
+ do i = 1, npix {
+ if ((delete[i] == PX_DELETE) || (delete[i] == PX_MARK))
+ next
+ z = data[i]
+ if (z >= z1 && z <= z2) {
+ bin = int ((z - z1) * dz) + 1
+ hgm[bin] = hgm[bin] + 1
+ }
+ }
+ }
+end
diff --git a/noao/digiphot/ptools/pexamine/ptalimr.x b/noao/digiphot/ptools/pexamine/ptalimr.x
new file mode 100644
index 00000000..614b2099
--- /dev/null
+++ b/noao/digiphot/ptools/pexamine/ptalimr.x
@@ -0,0 +1,35 @@
+include <mach.h>
+
+# PT_ALIMR -- Compute the limits (minimum and maximum values) of a vector
+# after rejecting any INDEF valued points.
+
+procedure pt_alimr (a, npix, minval, maxval)
+
+real a[ARB] # the input array
+int npix # the number of points
+real minval, maxval # the minimum and maximum value
+
+int i, ngood
+real value
+
+begin
+ minval = MAX_REAL
+ maxval = -MAX_REAL
+ ngood = 0
+
+ do i = 1, npix {
+ value = a[i]
+ if (IS_INDEFR(value))
+ next
+ ngood = ngood + 1
+ if (value < minval)
+ minval = value
+ if (value > maxval)
+ maxval = value
+ }
+
+ if (ngood == 0) {
+ minval = INDEFR
+ maxval = INDEFR
+ }
+end
diff --git a/noao/digiphot/ptools/pexamine/ptcolon.x b/noao/digiphot/ptools/pexamine/ptcolon.x
new file mode 100644
index 00000000..df2a29ae
--- /dev/null
+++ b/noao/digiphot/ptools/pexamine/ptcolon.x
@@ -0,0 +1,668 @@
+include <gset.h>
+include "pexamine.h"
+
+# PT_COLON -- Execute PEXAMINE colon commands.
+
+procedure pt_colon (px, gd, cmdstr, newdata, newxy, newhist, newcoords,
+ newplot, plottype, undelete)
+
+pointer px # pointer to the pexamine structure
+pointer gd # pointer to the graphics stream
+char cmdstr[ARB] # the colon command
+int newdata # read new columns from the input file
+int newxy # load new columns into the x and y arrays
+int newhist # load new column into the histogram array
+int newcoords # load new data into the coords array
+int newplot # replot the current plot
+int plottype # the plot type
+int undelete # delete or undelete points
+
+bool bval
+int type, ncmd, nrcols, ncols, ival, marktype
+pointer sp, cmd, str, rcols, cols
+real rval
+bool clgetb()
+int strdic(), nscan(), clgeti()
+real clgetr()
+
+errchk clgstr(), clgetb(), clgeti(), clgetr()
+errchk clpstr(), clputb(), clputi(), clputr()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (rcols, PX_SZCOLNAME * (PX_MAXNCOLS + 1), TY_CHAR)
+ call salloc (cols, PX_SZCOLNAME * (PX_MAXNCOLS + 1), TY_CHAR)
+
+ # Get the command.
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Define the pset type.
+ call salloc (str, SZ_LINE, TY_CHAR)
+ switch (plottype) {
+ case PX_XYPLOT:
+ call strcpy ("xyplot.", Memc[str], SZ_LINE)
+ case PX_HISTPLOT:
+ call strcpy ("histplot.", Memc[str], SZ_LINE)
+ case PX_RADPLOT:
+ call strcpy ("radplot.", Memc[str], SZ_LINE)
+ case PX_SURFPLOT:
+ call strcpy ("surfplot.", Memc[str], SZ_LINE)
+ case PX_CNTRPLOT:
+ call strcpy ("cntrplot.", Memc[str], SZ_LINE)
+ }
+
+ # Process the command.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, PX_PCMDS)
+ switch (ncmd) {
+
+ case PX_PCMD_PHOTCOLUMNS:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call pt_gphotcols (px, Memc[rcols], nrcols, Memc[cols],
+ ncols)
+ if (gd != NULL)
+ call gdeactivate (gd, AW_CLEAR)
+ call pt_lcols ("PHOTOMETRY COLUMNS", Memc[rcols], nrcols,
+ Memc[cols], ncols)
+ if (gd != NULL)
+ call greactivate (gd, AW_PAUSE)
+ } else {
+ call pt_gusercols (px, Memc[rcols], nrcols, Memc[cols], ncols)
+ call pt_setnames (px, Memc[cmd], Memc[rcols])
+ newdata = YES
+ newxy = YES
+ newhist = YES
+ newcoords = YES
+ newplot = YES
+ }
+
+ case PX_PCMD_USERCOLUMNS:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call pt_gusercols (px, Memc[rcols], nrcols, Memc[cols], ncols)
+ if (gd != NULL)
+ call gdeactivate (gd, AW_CLEAR)
+ call pt_lcols ("USER COLUMNS", Memc[rcols], nrcols, Memc[cols],
+ ncols)
+ if (gd != NULL)
+ call greactivate (gd, AW_PAUSE)
+ } else {
+ call pt_gphotcols (px, Memc[rcols], nrcols, Memc[cols], ncols)
+ call pt_setnames (px, Memc[rcols], Memc[cmd])
+ newdata = YES
+ newxy = YES
+ newhist = YES
+ newcoords = YES
+ newplot = YES
+ }
+
+ case PX_PCMD_XCOLUMN:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call printf ("X column requested: %s stored: %s\n")
+ call pargstr (PX_RXCOLNAME(px))
+ call pargstr (PX_XCOLNAME(px))
+ } else {
+ call strupr (Memc[cmd])
+ call strcpy (Memc[cmd], PX_RXCOLNAME(px), PX_SZCOLNAME)
+ if (strdic (Memc[cmd], Memc[cmd], PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)]) > 0) {
+ call strcpy (Memc[cmd], PX_XCOLNAME(px), PX_SZCOLNAME)
+ newxy = YES
+ newplot = YES
+ call clputr ("xyplot.x1", INDEFR)
+ call clputr ("xyplot.x2", INDEFR)
+ } else {
+ call printf ("Column %s not found\n")
+ call pargstr (PX_RXCOLNAME(px))
+ }
+ }
+
+ case PX_PCMD_YCOLUMN:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call printf ("Y column requested: %s stored: %s\n")
+ call pargstr (PX_RYCOLNAME(px))
+ call pargstr (PX_YCOLNAME(px))
+ } else {
+ call strupr (Memc[cmd])
+ call strcpy (Memc[cmd], PX_RYCOLNAME(px), PX_SZCOLNAME)
+ if (strdic (Memc[cmd], Memc[cmd], PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)]) > 0) {
+ call strcpy (Memc[cmd], PX_YCOLNAME(px), PX_SZCOLNAME)
+ newxy = YES
+ newplot = YES
+ call clputr ("xyplot.y1", INDEFR)
+ call clputr ("xyplot.y2", INDEFR)
+ } else {
+ call printf ("Column %s not found\n")
+ call pargstr (PX_RYCOLNAME(px))
+ }
+ }
+
+ case PX_PCMD_HCOLUMN:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call printf ("Histogram column requested: %s stored: %s\n")
+ call pargstr (PX_RHCOLNAME(px))
+ call pargstr (PX_HCOLNAME(px))
+ } else {
+ call strupr (Memc[cmd])
+ call strcpy (Memc[cmd], PX_RHCOLNAME(px), PX_SZCOLNAME)
+ if (strdic (Memc[cmd], Memc[cmd], PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)]) > 0) {
+ call strcpy (Memc[cmd], PX_HCOLNAME(px), PX_SZCOLNAME)
+ newhist = YES
+ newplot = YES
+ call clputr ("histplot.z1", INDEFR)
+ call clputr ("histplot.z2", INDEFR)
+ call clputr ("histplot.x1", INDEFR)
+ call clputr ("histplot.x2", INDEFR)
+ call clputr ("histplot.y1", INDEFR)
+ call clputr ("histplot.y2", INDEFR)
+ } else {
+ call printf ("Column %s not found\n")
+ call pargstr (PX_RHCOLNAME(px))
+ }
+ }
+
+ case PX_PCMD_XPOSCOLUMN:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call printf ("X coord column requested: %s stored: %s\n")
+ call pargstr (PX_RXPOSNAME(px))
+ call pargstr (PX_XPOSNAME(px))
+ } else {
+ call strupr (Memc[cmd])
+ call strcpy (Memc[cmd], PX_RXPOSNAME(px), PX_SZCOLNAME)
+ if (strdic (Memc[cmd], Memc[cmd], PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)]) > 0) {
+ call strcpy (Memc[cmd], PX_XPOSNAME(px), PX_SZCOLNAME)
+ newcoords = YES
+ } else {
+ call printf ("Column %s not found\n")
+ call pargstr (PX_RXPOSNAME(px))
+ }
+ }
+
+ case PX_PCMD_YPOSCOLUMN:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call printf ("X coord column requested: %s stored: %s\n")
+ call pargstr (PX_RYPOSNAME(px))
+ call pargstr (PX_YPOSNAME(px))
+ } else {
+ call strupr (Memc[cmd])
+ call strcpy (Memc[cmd], PX_RYPOSNAME(px), PX_SZCOLNAME)
+ if (strdic (Memc[cmd], Memc[cmd], PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)]) > 0) {
+ call strcpy (Memc[cmd], PX_YPOSNAME(px), PX_SZCOLNAME)
+ newcoords = YES
+ } else {
+ call printf ("Column %s not found\n")
+ call pargstr (PX_RXPOSNAME(px))
+ }
+ }
+
+ case PX_PCMD_EDIT:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS)
+ call printf ("The parameter set is undefined\n")
+ else {
+ type = strdic (Memc[cmd], Memc[cmd], SZ_LINE, PX_PLOTTYPES)
+ if (gd != NULL)
+ call gdeactivate (gd, 0)
+ switch (type) {
+ case PX_XYPLOT:
+ call clcmdw ("eparam xyplot")
+ case PX_HISTPLOT:
+ call clcmdw ("eparam histplot")
+ case PX_RADPLOT:
+ call clcmdw ("eparam radplot")
+ case PX_SURFPLOT:
+ call clcmdw ("eparam surfplot")
+ case PX_CNTRPLOT:
+ call clcmdw ("eparam cntrplot")
+ default:
+ call printf (
+ "The parameter set %s undefined\n")
+ call pargstr (Memc[cmd])
+ }
+ newplot = YES
+ if (gd != NULL)
+ call greactivate (gd, 0)
+ }
+
+ case PX_PCMD_UNLEARN:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS)
+ call printf ("The parameter set is undefined\n")
+ else {
+ type = strdic (Memc[cmd], Memc[cmd], SZ_LINE, PX_PLOTTYPES)
+ switch (type) {
+ case PX_XYPLOT:
+ call clcmdw ("unlearn xyplot")
+ case PX_HISTPLOT:
+ call clcmdw ("unlearn histplot")
+ case PX_RADPLOT:
+ call clcmdw ("unlearn radplot")
+ case PX_SURFPLOT:
+ call clcmdw ("unlearn surfplot")
+ case PX_CNTRPLOT:
+ call clcmdw ("unlearn cntrplot")
+ default:
+ call printf ("The parameter set %s is undefined\n")
+ call pargstr (Memc[cmd])
+ }
+ newplot = YES
+ }
+
+ case PX_PCMD_NBINS:
+ call strcpy ("histplot.nbins", Memc[str], SZ_LINE)
+ call gargi (ival)
+ if (nscan() == 1) {
+ ival = clgeti (Memc[str])
+ call printf ("nbins = %d\n")
+ call pargi (ival)
+ } else
+ call clputi (Memc[str], ival)
+
+ case PX_PCMD_Z1:
+ call strcpy ("histplot.z1", Memc[str], SZ_LINE)
+ call gargr (rval)
+ if (nscan() == 1) {
+ rval = clgetr (Memc[str])
+ call printf ("z1 = %g\n")
+ call pargr (rval)
+ } else
+ call clputr (Memc[str], rval)
+
+ case PX_PCMD_Z2:
+ call strcpy ("histplot.z2", Memc[str], SZ_LINE)
+ call gargr (rval)
+ if (nscan() == 1) {
+ rval = clgetr (Memc[str])
+ call printf ("z2 = %g\n")
+ call pargr (rval)
+ } else
+ call clputr (Memc[str], rval)
+
+ case PX_PCMD_TOP_CLOSED:
+ call strcpy ("histplot.top_closed", Memc[str], SZ_LINE)
+ call gargb (bval)
+ if (nscan() == 1) {
+ bval = clgetb (Memc[str])
+ call printf ("top_closed = %b\n")
+ call pargb (bval)
+ } else
+ call clputb (Memc[str], bval)
+
+ case PX_PCMD_X1:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargr (rval)
+ if (nscan() == 1) {
+ rval = clgetr (Memc[str])
+ call printf ("%s = %g\n")
+ call pargstr (Memc[cmd])
+ call pargr (rval)
+ } else
+ call clputr (Memc[str], rval)
+
+ case PX_PCMD_X2:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargr (rval)
+ if (nscan() == 1) {
+ rval = clgetr (Memc[str])
+ call printf ("%s = %g\n")
+ call pargstr (Memc[cmd])
+ call pargr (rval)
+ } else
+ call clputr (Memc[str], rval)
+
+ case PX_PCMD_Y1:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargr (rval)
+ if (nscan() == 1) {
+ rval = clgetr (Memc[str])
+ call printf ("%s = %g\n")
+ call pargstr (Memc[cmd])
+ call pargr (rval)
+ } else
+ call clputr (Memc[str], rval)
+
+ case PX_PCMD_Y2:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargr (rval)
+ if (nscan() == 1) {
+ rval = clgetr (Memc[str])
+ call printf ("%s = %g\n")
+ call pargstr (Memc[cmd])
+ call pargr (rval)
+ } else
+ call clputr (Memc[str], rval)
+
+ case PX_PCMD_MARKER:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call clgstr (Memc[str], Memc[cmd], SZ_LINE)
+ call printf ("marker = %s\n")
+ call pargstr (Memc[cmd])
+ } else {
+ call pt_marker (Memc[cmd], SZ_LINE, marktype)
+ call clpstr (Memc[str], Memc[cmd])
+ }
+
+ case PX_PCMD_SZMARKER:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargr (rval)
+ if (nscan() == 1) {
+ call printf ("%s = %g\n")
+ call pargstr (Memc[cmd])
+ call pargr (clgetr (Memc[str]))
+ } else
+ call clputr (Memc[str], rval)
+
+ case PX_PCMD_GRID:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargb (bval)
+ if (nscan() == 1) {
+ bval = clgetb (Memc[str])
+ call printf ("%s = %b\n")
+ call pargb (bval)
+ call pargstr (Memc[cmd])
+ } else
+ call clputb (Memc[str], bval)
+
+ case PX_PCMD_LOGX:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargb (bval)
+ if (nscan() == 1) {
+ bval = clgetb (Memc[str])
+ call printf ("%s = %b\n")
+ call pargstr (Memc[cmd])
+ call pargb (bval)
+ } else
+ call clputb (Memc[str], bval)
+
+ case PX_PCMD_LOGY:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargb (bval)
+ if (nscan() == 1) {
+ bval = clgetb (Memc[str])
+ call printf ("%s = %b\n")
+ call pargstr (Memc[cmd])
+ call pargb (bval)
+ } else
+ call clputb (Memc[str], bval)
+
+ case PX_PCMD_BOX:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargb (bval)
+ if (nscan() == 1) {
+ bval = clgetb (Memc[str])
+ call printf ("%s = %b\n")
+ call pargstr (Memc[cmd])
+ call pargb (bval)
+ } else
+ call clputb (Memc[str], bval)
+
+ case PX_PCMD_TICKLABELS:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargb (bval)
+ if (nscan() == 1) {
+ bval = clgetb (Memc[str])
+ call printf ("%s = %b\n")
+ call pargstr (Memc[cmd])
+ call pargb (bval)
+ } else
+ call clputb (Memc[str], bval)
+
+ case PX_PCMD_FILL:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargb (bval)
+ if (nscan() == 1) {
+ bval = clgetb (Memc[str])
+ call printf ("%s = %b\n")
+ call pargstr (Memc[cmd])
+ call pargb (bval)
+ } else
+ call clputb (Memc[str], bval)
+
+ case PX_PCMD_ROUND:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargb (bval)
+ if (nscan() == 1) {
+ bval = clgetb (Memc[str])
+ call printf ("%s = %b\n")
+ call pargstr (Memc[cmd])
+ call pargb (bval)
+ } else
+ call clputb (Memc[str], bval)
+
+ case PX_PCMD_MAJRX:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargi (ival)
+ if (nscan() == 1) {
+ ival = clgeti (Memc[str])
+ call printf ("%s = %d\n")
+ call pargstr (Memc[cmd])
+ call pargi (ival)
+ } else
+ call clputi (Memc[str], ival)
+
+ case PX_PCMD_MINRX:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargi (ival)
+ if (nscan() == 1) {
+ ival = clgeti (Memc[str])
+ call printf ("%s = %d\n")
+ call pargstr (Memc[cmd])
+ call pargi (ival)
+ } else
+ call clputi (Memc[str], ival)
+
+ case PX_PCMD_MAJRY:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargi (ival)
+ if (nscan() == 1) {
+ ival = clgeti (Memc[str])
+ call printf ("%s = %d\n")
+ call pargstr (Memc[cmd])
+ call pargi (ival)
+ } else
+ call clputi (Memc[str], ival)
+
+ case PX_PCMD_MINRY:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargi (ival)
+ if (nscan() == 1) {
+ ival = clgeti (Memc[str])
+ call printf ("%s = %d\n")
+ call pargstr (Memc[cmd])
+ call pargi (ival)
+ } else
+ call clputi (Memc[str], ival)
+
+ case PX_PCMD_DELETE:
+ call gargb (bval)
+ if (nscan() == 1) {
+ call printf ("delete = %b\n")
+ if (undelete == YES)
+ call pargb (false)
+ else
+ call pargb (true)
+ } else {
+ if (bval)
+ undelete = NO
+ else
+ undelete = YES
+ }
+
+ case PX_PCMD_RIN:
+ call strcpy ("radplot.rinner", Memc[str], SZ_LINE)
+ call gargr (rval)
+ if (nscan() == 1) {
+ rval = clgetr (Memc[str])
+ call printf ("rinner = %g\n")
+ call pargr (rval)
+ } else
+ call clputr (Memc[str], rval)
+
+ case PX_PCMD_ROUT:
+ call strcpy ("radplot.router", Memc[str], SZ_LINE)
+ call gargr (rval)
+ if (nscan() == 1) {
+ rval = clgetr (Memc[str])
+ call printf ("router = %g\n")
+ call pargr (rval)
+ } else
+ call clputr (Memc[str], rval)
+
+ case PX_PCMD_NCOLUMNS:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargi (ival)
+ if (nscan() == 1) {
+ ival = clgeti (Memc[str])
+ call printf ("%s = %d\n")
+ call pargstr (Memc[cmd])
+ call pargi (ival)
+ } else
+ call clputi (Memc[str], ival)
+
+ case PX_PCMD_NLINES:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargi (ival)
+ if (nscan() == 1) {
+ ival = clgeti (Memc[str])
+ call printf ("%s = %d\n")
+ call pargstr (Memc[cmd])
+ call pargi (ival)
+ } else
+ call clputi (Memc[str], ival)
+
+ case PX_PCMD_AXES:
+ call strcpy ("surfplot.axes", Memc[str], SZ_LINE)
+ call gargb (bval)
+ if (nscan() == 1) {
+ bval = clgetb (Memc[str])
+ call printf ("axes = %b\n")
+ call pargb (bval)
+ } else
+ call clputb (Memc[str], bval)
+
+ case PX_PCMD_ANGH:
+ call strcpy ("surfplot.angh", Memc[str], SZ_LINE)
+ call gargr (rval)
+ if (nscan() == 1) {
+ rval = clgetr (Memc[str])
+ call printf ("angh = %g\n")
+ call pargr (rval)
+ } else
+ call clputr (Memc[str], rval)
+
+ case PX_PCMD_ANGV:
+ call strcpy ("surfplot.angv", Memc[str], SZ_LINE)
+ call gargr (rval)
+ if (nscan() == 1) {
+ rval = clgetr (Memc[str])
+ call printf ("angv = %g\n")
+ call pargr (rval)
+ } else
+ call clputr (Memc[str], rval)
+
+ case PX_PCMD_FLOOR:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargr (rval)
+ if (nscan() == 1) {
+ rval = clgetr (Memc[str])
+ call printf ("%s = %g\n")
+ call pargstr (Memc[cmd])
+ call pargr (rval)
+ } else
+ call clputr (Memc[str], rval)
+
+ case PX_PCMD_CEILING:
+ call strcat (Memc[cmd], Memc[str], SZ_LINE)
+ call gargr (rval)
+ if (nscan() == 1) {
+ rval = clgetr (Memc[str])
+ call printf ("%s = %g\n")
+ call pargstr (Memc[cmd])
+ call pargr (rval)
+ } else
+ call clputr (Memc[str], rval)
+
+ case PX_PCMD_ZERO:
+ call strcpy ("cntrplot.zero", Memc[str], SZ_LINE)
+ call gargr (rval)
+ if (nscan() == 1) {
+ rval = clgetr (Memc[str])
+ call printf ("zero = %g\n")
+ call pargr (rval)
+ } else
+ call clputr (Memc[str], rval)
+
+ case PX_PCMD_NCONTOURS:
+ call strcpy ("cntrplot.ncontours", Memc[str], SZ_LINE)
+ call gargi (ival)
+ if (nscan() == 1) {
+ ival = clgeti (Memc[str])
+ call printf ("ncontours = %d\n")
+ call pargi (ival)
+ } else
+ call clputi (Memc[str], ival)
+
+ case PX_PCMD_INTERVAL:
+ call strcpy ("cntrplot.interval", Memc[str], SZ_LINE)
+ call gargr (rval)
+ if (nscan() == 1) {
+ rval = clgetr (Memc[str])
+ call printf ("interval = %g\n")
+ call pargr (rval)
+ } else
+ call clputr (Memc[str], rval)
+
+ case PX_PCMD_NHI:
+ call strcpy ("cntrplot.nhi", Memc[str], SZ_LINE)
+ call gargi (ival)
+ if (nscan() == 1) {
+ ival = clgeti (Memc[str])
+ call printf ("nhi = %d\n")
+ call pargi (ival)
+ } else
+ call clputi (Memc[str], ival)
+
+ case PX_PCMD_DASHPAT:
+ call strcpy ("cntrplot.dashpat", Memc[str], SZ_LINE)
+ call gargi (ival)
+ if (nscan() == 1) {
+ ival = clgeti (Memc[str])
+ call printf ("dashpat = %d\n")
+ call pargi (ival)
+ } else
+ call clputi (Memc[str], ival)
+
+ case PX_PCMD_LABEL:
+ call strcpy ("cntrplot.label", Memc[str], SZ_LINE)
+ call gargb (bval)
+ if (nscan() == 1) {
+ bval = clgetb (Memc[str])
+ call printf ("label = %b\n")
+ call pargb (bval)
+ } else
+ call clputb (Memc[str], bval)
+
+ default:
+ call printf ("Unknown or ambiguous colon command\7\n")
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/ptools/pexamine/ptdelete.x b/noao/digiphot/ptools/pexamine/ptdelete.x
new file mode 100644
index 00000000..f8a6581e
--- /dev/null
+++ b/noao/digiphot/ptools/pexamine/ptdelete.x
@@ -0,0 +1,335 @@
+include <gset.h>
+include <mach.h>
+include "pexamine.h"
+
+define MSIZE 2.0
+
+# PT_DELPT -- Mark/unmark the point nearest the cursor.
+
+procedure pt_delpt (gd, wx, wy, xpos, ypos, x, y, deleted, npix, undelete,
+ matchrad)
+
+pointer gd # pointer to the graphics stream
+real wx # X cursor position
+real wy # Y cursor position
+real xpos[ARB] # X coordinate array
+real ypos[ARB] # Y coordinate array
+real x[ARB] # X array of plotted data
+real y[ARB] # Y array of plotted data
+int deleted[ARB] # array of delete indicators
+int npix # number of pixels
+int undelete # undelete flag
+real matchrad # matching radius
+
+int i, row
+real r2min, r2, mr2, wx0, wy0, xpos0, ypos0
+
+begin
+ # Initialize.
+ row = 0
+ r2min = MAX_REAL
+
+ # Set matching radius for the image display or graph.
+ if (IS_INDEFR(matchrad)) {
+ mr2 = MAX_REAL
+ if (gd != NULL)
+ call gctran (gd, wx, wy, wx0, wy0, 1, 0)
+ else {
+ wx0 = wx
+ wy0 = wy
+ }
+ } else {
+ mr2 = matchrad ** 2
+ wx0 = wx
+ wy0 = wy
+ }
+
+ # Search for the point nearest the cursor.
+ do i = 1 , npix {
+
+ if (deleted[i] == PX_DELETE)
+ next
+
+ if ((deleted[i] == PX_MARK && undelete == NO) ||
+ (deleted[i] == PX_GOOD && undelete == YES))
+ next
+
+ if (! IS_INDEFR(xpos[i]) && ! IS_INDEFR(ypos[i])) {
+ if (IS_INDEFR(matchrad)) {
+ if (gd != NULL)
+ call gctran (gd, xpos[i], ypos[i], xpos0, ypos0, 1, 0)
+ else {
+ xpos0 = xpos[i]
+ ypos0 = ypos[i]
+ }
+ } else {
+ xpos0 = xpos[i]
+ ypos0 = ypos[i]
+ }
+ r2 = (wx0 - xpos0) ** 2 + (wy0 - ypos0) ** 2
+ } else
+ r2 = MAX_REAL
+ if (r2 >= r2min)
+ next
+
+ r2min = r2
+ row = i
+ }
+
+ # Return if point not found.
+ if ((row == 0) || (r2min > mr2))
+ return
+
+ # Delete the point.
+ if (undelete == NO) {
+ deleted[row] = PX_MARK
+ if (gd == NULL)
+ return
+ call gseti (gd, G_PMLTYPE, GL_SOLID)
+ call gmark (gd, x[row], y[row], GM_CROSS, MSIZE, MSIZE)
+ } else {
+ deleted[row] = PX_GOOD
+ if (gd == NULL)
+ return
+ call gseti (gd, G_PMLTYPE, GL_CLEAR)
+ call gmark (gd, x[row], y[row], GM_CROSS, MSIZE, MSIZE)
+ }
+end
+
+
+# PT_DYGTG -- Delete all points with Y > Y (cursor).
+
+procedure pt_dygtg (gd, wy, ypos, x, y, deleted, npix, undelete)
+
+pointer gd # pointer to graphics stream
+real wy # Y cursor position
+real ypos[ARB] # Y array of coordinate data
+real x[ARB] # X array of plotted data
+real y[ARB] # Y array of plotted data
+int deleted[ARB] # array of delete indicators
+int npix # number of pixels
+int undelete # the delete or undelete flag
+
+int i
+
+begin
+ do i = 1 , npix {
+ if (ypos[i] <= wy)
+ next
+ if ((deleted[i] == PX_GOOD) && (undelete == NO)) {
+ deleted[i] = PX_MARK
+ if (gd == NULL)
+ next
+ call gseti (gd, G_PMLTYPE, GL_SOLID)
+ call gmark (gd, x[i], y[i], GM_CROSS, MSIZE, MSIZE)
+ } else if ((deleted[i] == PX_MARK) && (undelete == YES)) {
+ deleted[i] = PX_GOOD
+ if (gd == NULL)
+ next
+ call gseti (gd, G_PMLTYPE, GL_CLEAR)
+ call gmark (gd, x[i], y[i], GM_CROSS, MSIZE, MSIZE)
+ }
+ }
+end
+
+
+# PT_DYLTG -- Delete all points with Y < Y (cursor).
+
+procedure pt_dyltg (gd, wy, ypos, x, y, deleted, npix, undelete)
+
+pointer gd # pointer to graphics stream
+real wy # Y cursor position
+real ypos[ARB] # Y array of coordinate data
+real x[ARB] # X array of plotted data
+real y[ARB] # Y array of plotted data
+int deleted[ARB] # array of delete indicators
+int npix # number of pixels
+int undelete # the delete or undelete flag
+
+int i
+
+begin
+ do i = 1 , npix {
+ if (ypos[i] >= wy)
+ next
+ if ((deleted[i] == PX_GOOD) && (undelete == NO)) {
+ deleted[i] = PX_MARK
+ if (gd == NULL)
+ next
+ call gseti (gd, G_PMLTYPE, GL_SOLID)
+ call gmark (gd, x[i], y[i], GM_CROSS, MSIZE, MSIZE)
+ } else if ((deleted[i] == PX_MARK) && (undelete == YES)) {
+ deleted[i] = PX_GOOD
+ if (gd == NULL)
+ next
+ call gseti (gd, G_PMLTYPE, GL_CLEAR)
+ call gmark (gd, x[i], y[i], GM_CROSS, MSIZE, MSIZE)
+ }
+ }
+end
+
+
+# PT_DXGTG -- Mark delete for all points with X > X (cursor)
+
+procedure pt_dxgtg (gd, wx, xpos, x, y, deleted, npix, undelete)
+
+pointer gd # pointer to graphics stream
+real wx # X cursor position
+real xpos[ARB] # X coordinate array
+real x[ARB] # X array of plotted data
+real y[ARB] # Y array of plotted data
+int deleted[ARB] # array of delete indicators
+int npix # number of pixels
+int undelete # the delete or undelete flag
+
+int i
+
+begin
+ do i = 1 , npix {
+ if (xpos[i] <= wx)
+ next
+ if ((deleted[i] == PX_GOOD) && (undelete == NO)) {
+ deleted[i] = PX_MARK
+ if (gd == NULL)
+ next
+ call gseti (gd, G_PMLTYPE, GL_SOLID)
+ call gmark (gd, x[i], y[i], GM_CROSS, MSIZE, MSIZE)
+ } else if ((deleted[i] == PX_MARK) && (undelete == YES)) {
+ deleted[i] = PX_GOOD
+ if (gd == NULL)
+ next
+ call gseti (gd, G_PMLTYPE, GL_CLEAR)
+ call gmark (gd, x[i], y[i], GM_CROSS, MSIZE, MSIZE)
+ }
+ }
+end
+
+
+# PT_DXLTG -- Mark delete for all points with X < X (cursor).
+
+procedure pt_dxltg (gd, wx, xpos, x, y, deleted, npix, undelete)
+
+pointer gd # pointer to graphics stream
+real wx # X cursor position
+real xpos[ARB] # X coordinate array
+real x[ARB] # X array of plotted data
+real y[ARB] # Y array of plotted data
+int deleted[ARB] # array of delete indicators
+int npix # number of pixels
+int undelete # the delete or undelete flag
+
+int i
+
+begin
+ do i = 1 , npix {
+ if (xpos[i] >= wx)
+ next
+ if ((deleted[i] == PX_GOOD) && (undelete == NO)) {
+ deleted[i] = PX_MARK
+ if (gd == NULL)
+ next
+ call gseti (gd, G_PMLTYPE, GL_SOLID)
+ call gmark (gd, x[i], y[i], GM_CROSS, MSIZE, MSIZE)
+ } else if ((deleted[i] == PX_MARK) && (undelete == YES)) {
+ deleted[i] = PX_GOOD
+ if (gd == NULL)
+ next
+ call gseti (gd, G_PMLTYPE, GL_CLEAR)
+ call gmark (gd, x[i], y[i], GM_CROSS, MSIZE, MSIZE)
+ }
+ }
+end
+
+
+# PT_DBOXG -- Delete all points inside a box
+
+procedure pt_dboxg (gd, xpos, ypos, x, y, deleted, npix, x1, y1, x2, y2,
+ undelete)
+
+pointer gd # pointer to the graphics stream
+real xpos[ARB] # x coordinate array
+real ypos[ARB] # y coordinate array
+real x[ARB] # x array of plotted data
+real y[ARB] # y array of plotted data
+int deleted[ARB] # array of deletion indicators
+int npix # number of pixels
+real x1, y1, x2, y2 # corners of the box
+int undelete # delete or undelete points
+
+int i
+real temp
+
+begin
+ # Make sure the points are in the correct order.
+ if (x2 < x1) {
+ temp = x1
+ x1 = x2
+ x2 = temp
+ }
+ if (y2 < y1) {
+ temp = y1
+ y1 = y2
+ y2 = temp
+ }
+
+ # Search for points within the box and delete.
+ do i = 1 , npix {
+ if (xpos[i] < x1 || xpos[i] > x2 || ypos[i] < y1 || ypos[i] > y2)
+ next
+ if ((deleted[i] == PX_GOOD) && (undelete == NO)) {
+ deleted[i] = PX_MARK
+ if (gd == NULL)
+ next
+ call gseti (gd, G_PMLTYPE, GL_SOLID)
+ call gmark (gd, x[i], y[i], GM_CROSS, MSIZE, MSIZE)
+ } else if ((deleted[i] == PX_MARK) && (undelete == YES)) {
+ deleted[i] = PX_GOOD
+ if (gd == NULL)
+ next
+ call gseti (gd, G_PMLTYPE, GL_CLEAR)
+ call gmark (gd, x[i], y[i], GM_CROSS, MSIZE, MSIZE)
+ }
+ }
+end
+
+
+# PT_MDELETE -- Overplot crosses on those points which have been marked for
+# deletion.
+
+procedure pt_mdelete (gd, x, y, deleted, npix)
+
+pointer gd # pointer to the graphics stream
+real x[ARB] # the array plotted along the x axis
+real y[ARB] # the array plotted along the y axis
+int deleted[ARB] # the array of deletion indices
+int npix # the number of pixels
+
+int i
+
+begin
+ do i = 1, npix {
+ if (deleted[i] != PX_MARK)
+ next
+ call gseti (gd, G_PMLTYPE, GL_SOLID)
+ call gmark (gd, x[i], y[i], GM_CROSS, MSIZE, MSIZE)
+ }
+end
+
+
+# PT_UPDATE -- Actually delete points currently marked for deletion.
+
+procedure pt_update (deleted, npix)
+
+int deleted[ARB] # array of deletions indices
+int npix # the number of pixels
+
+int i
+
+begin
+ # Add the marked points to the deletions array.
+ do i = 1, npix {
+ if (deleted[i] != PX_MARK)
+ next
+ deleted[i] = PX_DELETE
+ }
+end
diff --git a/noao/digiphot/ptools/pexamine/ptgetphot.x b/noao/digiphot/ptools/pexamine/ptgetphot.x
new file mode 100644
index 00000000..df3b27f0
--- /dev/null
+++ b/noao/digiphot/ptools/pexamine/ptgetphot.x
@@ -0,0 +1,432 @@
+include <tbset.h>
+include "../../lib/ptkeysdef.h"
+include "pexamine.h"
+
+define NAPRESULT 10
+
+# PT_GETPHOT -- Read the specified columns out of the photometry catalog.
+# PT_GETPHOT works with either the "old" APPHOT files or the new ST Tables.
+
+int procedure pt_getphot (px, apd, key, max_nstars, first_star)
+
+pointer px # pointer to the pexamine structure
+int apd # input photometry file descriptor
+pointer key # pointer to key structure for text files
+int max_nstars # the maximum number of stars
+int first_star # first star to load
+
+int i, nstars
+int pt_goldap(), pt_gtabphot(), strdic()
+errchk pt_goldap(), pt_gtabphot()
+
+begin
+ # Allocate the required memory for the photometry, user and
+ # dummy columns and fill with INDEFR.
+ do i = 1, PX_MAXNCOLS {
+ call realloc (Memi[PX_COLPTRS(px)+i-1], max_nstars, TY_REAL)
+ call amovkr (INDEFR, Memr[Memi[PX_COLPTRS(px)+i-1]], max_nstars)
+ }
+
+ # Get the results.
+ if (key == NULL)
+ nstars = pt_gtabphot (apd, px, max_nstars, first_star)
+ else
+ nstars = pt_goldap (apd, px, key, max_nstars, first_star)
+
+ # Reallocate space if necessary.
+ if (nstars < max_nstars) {
+ do i = 1, PX_MAXNCOLS {
+ if (Memi[PX_COLPTRS(px)+i-1] == NULL)
+ next
+ if (i > PX_NCOLS(px)) {
+ call mfree (Memi[PX_COLPTRS(px)+i-1], TY_REAL)
+ Memi[PX_COLPTRS(px)+i-1] = NULL
+ } else
+ call realloc (Memi[PX_COLPTRS(px)+i-1], nstars, TY_REAL)
+ }
+ }
+
+ # Get the x and y columns.
+ if (strdic (PX_RXCOLNAME(px), PX_XCOLNAME(px), PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)]) <= 0)
+ PX_XCOLNAME(px) = EOS
+ if (strdic (PX_RYCOLNAME(px), PX_YCOLNAME(px), PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)]) <= 0)
+ PX_YCOLNAME(px) = EOS
+
+ # Get the x and y coordinate columns.
+ if (strdic (PX_RXPOSNAME(px), PX_XPOSNAME(px), PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)]) <= 0)
+ PX_XPOSNAME(px) = EOS
+ if (strdic (PX_RYPOSNAME(px), PX_YPOSNAME(px), PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)]) <= 0)
+ PX_YPOSNAME(px) = EOS
+
+ # Get the histogram column names.
+ if (strdic (PX_RHCOLNAME(px), PX_HCOLNAME(px), PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)]) <= 0)
+ PX_HCOLNAME(px) = EOS
+
+ return (nstars)
+end
+
+
+# PT_GOLDAP -- Read in the photometry from an old style APPHOT file.
+
+int procedure pt_goldap (apd, px, apkey, max_nstars, first_star)
+
+int apd # pointer to the input file descriptor
+pointer px # pointer to the pexamine structure
+pointer apkey # pointer to the key structure
+int max_nstars # maximum number of stars
+int first_star # first star to load
+
+char lbracket
+int i, ip, index, nselect, nphot, nptr, nstars
+pointer sp, data, rcolname, colname
+int pt_photsel(), pt_getnames(), strdic(), stridx()
+data lbracket /'['/
+
+begin
+ call smark (sp)
+ call salloc (data, PX_MAXNCOLS, TY_REAL)
+ call salloc (rcolname, PX_SZCOLNAME, TY_CHAR)
+ call salloc (colname, PX_SZCOLNAME, TY_CHAR)
+
+ # Rewind the text file.
+ call seek (apd, BOF)
+
+ # Now read in the results.
+ nptr = 0
+ nstars = 0
+ while (pt_photsel (apkey, apd, Memc[PX_RCOLNAMES(px)], first_star +
+ max_nstars - 1, Memc[PX_COLNAMES(px)], Memr[data]) != EOF) {
+ nselect = KY_NSELECT(apkey)
+ if (nselect <= 0)
+ break
+ nstars = nstars + 1
+ if (nstars < first_star)
+ next
+ do i = 1, nselect
+ Memr[Memi[PX_COLPTRS(px)+i-1]+nptr] = Memr[data+i-1]
+ nptr = nptr + 1
+ }
+
+ # Count the fields.
+ ip = 1
+ nselect = 0
+ while (pt_getnames (Memc[PX_COLNAMES(px)], ip, Memc[rcolname],
+ PX_SZCOLNAME) != EOF)
+ nselect = nselect + 1
+ PX_NCOLS(px) = nselect
+
+ # Count the photometry fields.
+ ip = 1
+ nselect = 0
+ nphot = 0
+ while (pt_getnames (Memc[PX_RCOLNAMES(px)], ip, Memc[rcolname],
+ PX_SZCOLNAME) != EOF) {
+ nselect = nselect + 1
+ if (nselect > PX_RNPHOT(px))
+ break
+ if (strdic (Memc[rcolname], Memc[colname], PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)]) <= 0) {
+ index = stridx (lbracket, Memc[rcolname])
+ if (index <= 1)
+ next
+ call strcpy (Memc[rcolname], Memc[colname], index - 1)
+ if (strdic (Memc[colname], Memc[colname], PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)]) <= 0)
+ next
+ }
+ nphot = nphot + 1
+ }
+ PX_NPHOT(px) = nphot
+
+ # Count the user fields.
+ PX_NUSER(px) = PX_NCOLS(px) - PX_NPHOT(px)
+
+ call sfree (sp)
+
+ return (nptr)
+end
+
+
+# PT_GTABPHOT -- Read in the photometry from an ST table. It may be possible
+# to do this more efficiently depending on how the table ir organized.
+
+int procedure pt_gtabphot (tp, px, max_nstars, first_star)
+
+pointer tp # table descriptor
+pointer px # pointer to the pexamine structure
+int max_nstars # maximum number of stars
+int first_star # first star to load
+
+bool nullflag
+int ntot, ncount, record, ip, col, nrow, ival
+pointer sp, colname, colptrs, cptr, dptr
+int pt_getnames(), tbpsta(), tbcigi()
+
+begin
+ # Allocate working memory.
+ call smark (sp)
+ call salloc (colname, PX_SZCOLNAME, TY_CHAR)
+ call salloc (colptrs, PX_MAXNCOLS + 2, TY_POINTER)
+
+ # Define the column pointers for the preset columns.
+ ip = 1
+ ncount = 0
+ Memc[PX_COLNAMES(px)] = EOS
+ ntot = 0
+ while (pt_getnames (Memc[PX_RCOLNAMES(px)], ip, Memc[colname],
+ PX_SZCOLNAME) != EOF) {
+
+ ncount = ncount + 1
+ call tbcfnd (tp, Memc[colname], Memi[colptrs+ntot], 1)
+ if (Memi[colptrs+ntot] == NULL)
+ call strcat ("[1]", Memc[colname], PX_SZCOLNAME)
+ call tbcfnd (tp, Memc[colname], Memi[colptrs+ntot], 1)
+ if (Memi[colptrs+ntot] == NULL)
+ next
+
+ call strcat (",", Memc[PX_COLNAMES(px)], (PX_MAXNCOLS + 1) *
+ PX_SZCOLNAME)
+ call strcat (Memc[colname], Memc[PX_COLNAMES(px)],
+ (PX_MAXNCOLS + 1) * PX_SZCOLNAME)
+
+ ntot = ntot + 1
+ if (ncount <= PX_RNPHOT(px))
+ PX_NPHOT(px) = ntot
+ }
+ PX_NCOLS(px) = ntot
+ PX_NUSER(px) = PX_NCOLS(px) - PX_NPHOT(px)
+
+ # Get the results filling in any record that can not be interpreted
+ # as a real number with INDEFR.
+
+ nrow = tbpsta (tp, TBL_NROWS)
+ if (first_star > nrow) {
+ call sfree (sp)
+ return (0)
+ }
+
+ nrow = min (nrow - first_star + 1, max_nstars)
+
+ do col = 1, PX_NCOLS(px) {
+
+ cptr = Memi[colptrs+col-1]
+ if (cptr == NULL)
+ next
+ dptr = Memi[PX_COLPTRS(px)+col-1]
+ if (dptr == NULL)
+ next
+
+ if (tbcigi (cptr, TBL_COL_DATATYPE) == TY_REAL) {
+ do record = first_star, nrow + first_star - 1
+ call tbrgtr (tp, cptr, Memr[dptr+record-first_star],
+ nullflag, 1, record)
+ } else if (tbcigi (cptr, TBL_COL_DATATYPE) == TY_INT) {
+ do record = first_star, nrow + first_star - 1 {
+ call tbrgti (tp, cptr, ival, nullflag, 1, record)
+ Memr[dptr+record-first_star] = ival
+ }
+ }
+ }
+
+ call sfree (sp)
+
+ if (PX_NCOLS(px) <= 0)
+ return (0)
+ else
+ return (nrow)
+end
+
+
+# PT_PHOTSEL -- Procedure to select real records from a text file.
+
+int procedure pt_photsel (key, fd, infields, max_nrecords, outfields, data)
+
+pointer key # pointer to key structure
+int fd # text file descriptor
+char infields[ARB] # requested output fields
+int max_nrecords # maximum number of records to be read
+char outfields[ARB] # selected output field
+real data[ARB] # array of real values read from the file
+
+int nchars, nunique, uunique, funique, ncontinue, recptr
+int first_rec, record
+pointer line
+int getline(), strncmp(), pt_choose()
+
+data first_rec /YES/
+
+begin
+ # Initialize the file read.
+ if (first_rec == YES) {
+ record = 0
+ nunique = 0
+ uunique = 0
+ funique = 0
+ call malloc (line, SZ_LINE, TY_CHAR)
+ }
+
+ ncontinue = 0
+ recptr = 1
+
+ # Loop over the text file records.
+ repeat {
+
+ # Check for the maximum number of records and EOF.
+ if (record >= max_nrecords)
+ nchars = EOF
+ else
+ nchars = getline (fd, Memc[line])
+ if (nchars == EOF)
+ break
+
+ # Determine the type of record.
+ if (Memc[line] == KY_CHAR_POUND) {
+
+ if (strncmp (Memc[line], KY_CHAR_KEYWORD, KY_LEN_STR) == 0) {
+ call pt_kyadd (key, Memc[line], nchars)
+ } else if (strncmp (Memc[line], KY_CHAR_NAME,
+ KY_LEN_STR) == 0) {
+ nunique = nunique + 1
+ call pt_kname (key, Memc[line], nchars, nunique)
+ } else if (strncmp (Memc[line], KY_CHAR_UNITS,
+ KY_LEN_STR) == 0) {
+ uunique = uunique + 1
+ call pt_knunits (key, Memc[line], nchars, uunique)
+ } else if (strncmp (Memc[line], KY_CHAR_FORMAT,
+ KY_LEN_STR) == 0) {
+ funique = funique + 1
+ call pt_knformats (key, Memc[line], nchars, funique)
+ }
+
+ } else if (Memc[line] == KY_CHAR_NEWLINE) {
+ # skip blank lines
+
+ } else {
+
+ # Construct the table record.
+ call pt_mkrec (key, Memc[line], nchars, first_rec, recptr,
+ ncontinue)
+
+ # Construct output record when there is no continuation char.
+ if (Memc[line+nchars-2] != KY_CHAR_CONT) {
+
+ # Select the appropriate records.
+ if (first_rec == YES) {
+ call pt_fields (key, infields, outfields)
+ if (pt_choose (key, outfields) <= 0) {
+ nchars = EOF
+ break
+ }
+ }
+
+ # Construct the output record by moving selected fields
+ # into the data structures.
+
+ call pt_grecord (key, data)
+ first_rec = NO
+ record = record + 1
+
+ # Record is complete so exit the loop.
+ break
+ }
+ }
+
+ }
+
+ if (nchars == EOF) {
+ first_rec = YES
+ record = 0
+ nunique = 0
+ uunique = 0
+ funique = 0
+ call mfree (line, TY_CHAR)
+ return (EOF)
+ } else
+ return (record)
+end
+
+
+# PT_FIELDS -- Check the user definitions for multiply defined entries.
+
+procedure pt_fields (key, infields, outfields)
+
+pointer key # pointer to keys strucuture
+char infields[ARB] # the list of input fields
+char outfields[ARB] # the list of input fields
+
+int ijunk, num
+pointer sp, name, aranges, ranges, rangeset, list
+int pt_gnfn(), pt_ranges(), decode_ranges(), get_next_number(), strlen()
+int pt_kstati()
+pointer pt_ofnl()
+
+begin
+ call smark (sp)
+ call salloc (name, PX_SZCOLNAME, TY_CHAR)
+ call salloc (aranges, SZ_LINE, TY_CHAR)
+ call salloc (ranges, SZ_LINE, TY_CHAR)
+ call salloc (rangeset, 3 * KY_MAXNRANGES + 1, TY_INT)
+
+ list = pt_ofnl (key, infields)
+ outfields[1] = EOS
+ while (pt_gnfn (list, Memc[name], Memc[aranges], KY_SZPAR) != EOF) {
+ if (Memc[name] == EOS)
+ next
+ num = 0
+ if (Memc[aranges] == EOS) {
+ if (pt_kstati (key, Memc[name], KY_NUMELEMS) > 1)
+ call strcat ("[1]", Memc[name], PX_SZCOLNAME)
+ } else if (pt_ranges (Memc[aranges], Memc[ranges], ijunk,
+ SZ_LINE) == ERR) {
+ call strcat ("[1]", Memc[name], PX_SZCOLNAME)
+ } else if (decode_ranges (Memc[ranges], Memi[rangeset],
+ KY_MAXNRANGES, ijunk) == ERR) {
+ call strcat ("[1]", Memc[name], PX_SZCOLNAME)
+ } else if (get_next_number (Memi[rangeset], num) > 0) {
+ call sprintf (Memc[name+strlen(Memc[name])], PX_SZCOLNAME,
+ "[%d]")
+ call pargi (num)
+ } else {
+ call strcat ("[1]", Memc[name], PX_SZCOLNAME)
+ }
+ call strcat (",", outfields, PX_SZCOLNAME * (PX_MAXNCOLS + 1))
+ call strcat (Memc[name], outfields, PX_SZCOLNAME *
+ (PX_MAXNCOLS + 1))
+ }
+
+ call pt_cfnl (list)
+ call sfree (sp)
+end
+
+
+# PT_GRECORD -- Move selected photometry results into a real arrays.
+
+procedure pt_grecord (key, data)
+
+pointer key # pointer to keys strucuture
+real data[ARB] # output array of real selected data
+
+int i, index, elem, maxch, kip, ip
+int ctor()
+
+begin
+ do i = 1, KY_NSELECT(key) {
+
+ index = Memi[KY_SELECT(key)+i-1]
+ elem = Memi[KY_ELEM_SELECT(key)+i-1]
+ maxch = Memi[KY_LEN_SELECT(key)+i-1]
+ kip = Memi[KY_PTRS(key)+index-1] + (elem - 1) * maxch
+
+ ip = 1
+ if (kip == NULL)
+ data[i] = INDEFR
+ else if (ctor (Memc[kip], ip, data[i]) <= 0)
+ data[i] = INDEFR
+ }
+
+end
diff --git a/noao/digiphot/ptools/pexamine/ptimplot.x b/noao/digiphot/ptools/pexamine/ptimplot.x
new file mode 100644
index 00000000..8e586b97
--- /dev/null
+++ b/noao/digiphot/ptools/pexamine/ptimplot.x
@@ -0,0 +1,940 @@
+include <imhdr.h>
+include <gset.h>
+include <math.h>
+include <mach.h>
+
+
+# PT_RPLOT -- Plot the radial profile.
+
+procedure pt_rplot (gd, im, wx, wy)
+
+pointer gd # pointer to the graphics stream
+pointer im # pointer to the input image
+real wx, wy # radial profile coordinates
+
+int marker_type, lenbuf, npix
+pointer sp, radius, intensity, marker, longtitle
+real szmarker, rin, rout, x1, x2, y1, y2, dmin, dmax
+bool clgetb()
+int clgeti(), strlen(), pt_radpix()
+real clgetr()
+
+begin
+ # Check for undefined graphics stream.
+ if (gd == NULL) {
+ call printf ("The graphics device is undefined\n")
+ return
+ }
+
+ # Check for undefined input image.
+ if (im == NULL) {
+ call printf ("The graphics device is undefined\n")
+ return
+ }
+
+ # Check for an undefined center.
+ if (IS_INDEFR(wx) || IS_INDEFR(wy)) {
+ call printf ("The radial profile plot center is undefined.\n")
+ return
+ }
+
+ # Get the inner and outer radii.
+ rin = clgetr ("radplot.rinner")
+ rout = clgetr ("radplot.router")
+ if (rout <= rin) {
+ call printf (
+ "The outer radius %g is <= the inner radius %g\n")
+ call pargr (rin)
+ call pargr (rout)
+ return
+ }
+
+ # Allocate working space.
+ call smark (sp)
+
+ # Get the data.
+ lenbuf = PI * (rin + rout + 1.0) * (rout - rin + 0.5)
+ call salloc (radius, lenbuf, TY_REAL)
+ call salloc (intensity, lenbuf, TY_REAL)
+ npix = pt_radpix (im, wx, wy, rin, rout, Memr[radius], Memr[intensity])
+ if (npix <= 0) {
+ call printf ("The object at %g %g is off the image\n")
+ call pargr (wx)
+ call pargr (wy)
+ call sfree (sp)
+ return
+ }
+
+ # Clear the plotting strucuture.
+ call gclear (gd)
+
+ # Fetch the window and viewport parameters.
+ x1 = clgetr ("radplot.x1")
+ x2 = clgetr ("radplot.x2")
+ y1 = clgetr ("radplot.y1")
+ y2 = clgetr ("radplot.y2")
+ if (IS_INDEFR(x1) || IS_INDEFR(x2)) {
+ call pt_alimr (Memr[radius], npix, dmin, dmax)
+ if (IS_INDEFR(x1))
+ x1 = dmin
+ if (IS_INDEFR(x2))
+ x2 = dmax
+ }
+ if (IS_INDEFR(y1) || IS_INDEFR(y2)) {
+ call pt_alimr (Memr[intensity], npix, dmin, dmax)
+ if (IS_INDEFR(y1))
+ y1 = dmin
+ if (IS_INDEFR(y2))
+ y2 = dmax
+ }
+
+ # Set the scale of the axes.
+ call gswind (gd, x1, x2, y1, y2)
+ if (clgetb ("radplot.logx"))
+ call gseti (gd, G_XTRAN, GW_LOG)
+ else
+ call gseti (gd, G_XTRAN, GW_LINEAR)
+ if (clgetb ("radplot.logy"))
+ call gseti (gd, G_YTRAN, GW_LOG)
+ else
+ call gseti (gd, G_YTRAN, GW_LINEAR)
+
+ # Get the x and y axes parameters.
+ if (! clgetb ("radplot.fill"))
+ call gseti (gd, G_ASPECT, 1)
+ if (clgetb ("radplot.round"))
+ call gseti (gd, G_ROUND, YES)
+
+ # Get the axis drawing parameters.
+ if (clgetb ("radplot.box")) {
+
+ # Get number of major and minor tick marks.
+ call gseti (gd, G_XNMAJOR, clgeti ("radplot.majrx"))
+ call gseti (gd, G_XNMINOR, clgeti ("radplot.minrx"))
+ call gseti (gd, G_YNMAJOR, clgeti ("radplot.majry"))
+ call gseti (gd, G_YNMINOR, clgeti ("radplot.minry"))
+
+ # Label tick marks on axes.
+ if (clgetb ("radplot.ticklabels"))
+ call gseti (gd, G_LABELTICKS, YES)
+ else
+ call gseti (gd, G_LABELTICKS, NO)
+
+ # Draw grid.
+ if (clgetb ("radplot.grid"))
+ call gseti (gd, G_DRAWGRID, YES)
+ else
+ call gseti (gd, G_DRAWGRID, NO)
+
+ # Optionally draw a box around the plot.
+ call salloc (longtitle, 2 * SZ_LINE, TY_CHAR)
+ if (clgetb ("radplot.banner")) {
+ call sysid (Memc[longtitle], 2 * SZ_LINE)
+ call sprintf (Memc[longtitle+strlen(Memc[longtitle])],
+ 2 * SZ_LINE, "\n%s: xc=%g yc=%g rinner=%g router=%g\n%s")
+ call pargstr (IM_HDRFILE(im))
+ call pargr (wx)
+ call pargr (wy)
+ call pargr (rin)
+ call pargr (rout)
+ call pargstr ("Radial Profile Plot")
+ } else {
+ call sprintf (Memc[longtitle], 2 * SZ_LINE,
+ "%s: xc=%g yc=%g rinner=%g router=%g\n%s")
+ call pargstr (IM_HDRFILE(im))
+ call pargr (wx)
+ call pargr (wy)
+ call pargr (rin)
+ call pargr (rout)
+ call pargstr ("Radial Profile Plot")
+ }
+ call glabax (gd, Memc[longtitle], "Radial distance (pixels)",
+ "Intensity (counts)")
+ }
+
+ # Get the marker type, the size of the marker and the linewidth.
+ call salloc (marker, SZ_FNAME, TY_CHAR)
+ call clgstr ("radplot.marker", Memc[marker], SZ_FNAME)
+ call pt_marker (Memc[marker], SZ_FNAME, marker_type)
+ if (marker_type != GM_POINT)
+ szmarker = clgetr ("radplot.szmarker")
+ else
+ szmarker = 0.0
+ call gsetr (gd, G_PLWIDTH, 2.0)
+
+ # Draw the points in using the deletions array.
+ call gpmark (gd, Memr[radius], Memr[intensity], npix, marker_type,
+ szmarker, szmarker)
+ call gflush (gd)
+
+ call sfree (sp)
+end
+
+
+define CSIZE 24
+
+# PT_SPLOT -- Draw a perspective view of a surface. The altitude
+# and azimuth of the viewing angle are variable.
+
+procedure pt_splot (gd, im, x, y)
+
+pointer gd # pointer to the graphics stream
+pointer im # pointer to the image descriptor
+real x, y # the object center
+
+int nx, ny, x1, x2, y1, y2, npts, wkid
+pointer data, sp, sdata, work, longtitle
+real floor, ceiling, angv, angh
+bool clgetb()
+int clgeti(), strlen()
+pointer pt_gdata()
+real clgetr()
+
+int first
+real vpx1, vpx2, vpy1, vpy2
+common /frstfg/ first
+common /noaovp/ vpx1, vpx2, vpy1, vpy2
+
+begin
+ # Check for undefined graphics stream.
+ if (gd == NULL) {
+ call printf ("The graphics device is undefined\n")
+ return
+ }
+
+ # Check for undefined input image.
+ if (im == NULL) {
+ call printf ("The graphics device is undefined\n")
+ return
+ }
+
+ # Check for an undefined center.
+ if (IS_INDEFR(x) || IS_INDEFR(y)) {
+ call printf ("The surface plot center is undefined\n")
+ return
+ }
+
+ # Get the data.
+ ny = clgeti ("surfplot.nlines")
+ nx = clgeti ("surfplot.ncolumns")
+ x1 = x - (nx - 1) / 2 + 0.5
+ x2 = x + nx / 2 + 0.5
+ y1 = y - (ny - 1) / 2 + 0.5
+ y2 = y + ny / 2 + 0.5
+ data = pt_gdata (im, x1, x2, y1, y2)
+ if (data == NULL) {
+ call printf ("The requested image section if off the image\n")
+ return
+ }
+
+ call smark (sp)
+
+ # Set the title.
+ call salloc (longtitle, 2 * SZ_LINE, TY_CHAR)
+ if (clgetb ("surfplot.banner")) {
+ Memc[longtitle] = '\n'
+ call sysid (Memc[longtitle+1], 2 * SZ_LINE)
+ call sprintf (Memc[longtitle+strlen(Memc[longtitle])], 2 * SZ_LINE,
+ "\nObject at x: %g y: %g\nSurface plot of %s[%d:%d,%d:%d]")
+ call pargr (x)
+ call pargr (y)
+ call pargstr (IM_HDRFILE(im))
+ call pargi (x1)
+ call pargi (x2)
+ call pargi (y1)
+ call pargi (y2)
+ } else {
+ call sprintf (Memc[longtitle], 2 * SZ_LINE,
+ "\nObject at x: %g y: %g\nSurface plot of %s[%d:%d,%d:%d]")
+ call pargr (x)
+ call pargr (y)
+ call pargstr (IM_HDRFILE(im))
+ call pargi (x1)
+ call pargi (x2)
+ call pargi (y1)
+ call pargi (y2)
+ }
+
+ # Initialize the plot.
+ call gclear (gd)
+
+ # Set the viewport, turn off axes drawing.
+ call gsview (gd, 0.1, 0.9, 0.1, 0.9)
+ call gseti (gd, G_DRAWAXES, NO)
+ call glabax (gd, Memc[longtitle], "", "")
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ npts = nx * ny
+
+ # Take floor and ceiling if enabled (nonzero).
+ floor = clgetr ("surfplot.floor")
+ ceiling = clgetr ("surfplot.ceiling")
+ if (IS_INDEFR (floor) && IS_INDEFR (ceiling))
+ sdata = data
+ else {
+ call salloc (sdata, npts, TY_REAL)
+ call amovr (Memr[data], Memr[sdata], npts)
+ if (! IS_INDEFR (floor) && ! IS_INDEFR (ceiling)) {
+ floor = min (floor, ceiling)
+ ceiling = max (floor, ceiling)
+ }
+ if (! IS_INDEFR (floor))
+ call amaxkr (Memr[sdata], floor, Memr[sdata], npts)
+ if (! IS_INDEFR (ceiling))
+ call aminkr (Memr[sdata], ceiling, Memr[sdata], npts)
+ }
+
+ # Open graphics device and make plot.
+ call gopks (STDERR)
+ wkid = 1
+ call gopwk (wkid, 6, gd)
+ call gacwk (wkid)
+
+ first = 1
+ call srfabd()
+ call ggview (gd, vpx1, vpx2, vpy1, vpy2)
+ call set (vpx1, vpx2, vpy1, vpy2, 1.0, 1024., 1.0, 1024., 1)
+
+ angh = clgetr ("surfplot.angh")
+ angv = clgetr ("surfplot.angv")
+ call salloc (work, 2 * (2*nx*ny+nx+ny), TY_REAL)
+ call ezsrfc (Memr[sdata], nx, ny, angh, angv, Memr[work])
+
+ if (clgetb ("surfplot.axes")) {
+ call gswind (gd, real (x1), real (x2), real (y1), real (y2))
+ call gseti (gd, G_CLIP, NO)
+ call pt_perimeter (gd, Memr[sdata], nx, ny, angh, angv)
+ }
+
+ call gdawk (wkid)
+ call gclks ()
+ call sfree (sp)
+end
+
+
+# PT_CPLOT -- Contour map
+# This is an interface to the NCAR CONREC routine.
+
+procedure pt_cplot (gd, im, x, y)
+
+pointer gd # pointer to the graphics stream
+pointer im # pointer to the input image
+real x, y # center of the contour plot
+
+int nx, ny, x1, x2, y1, y2, nhi, dashpat, npts, ncontours, wkid, nset
+pointer data, sp, longtitle, data1
+real xs, xe, ys, ye, vx1, vx2, vy1, vy2
+real zero, floor, ceiling, zmin, zmax, interval, finc
+bool clgetb(), fp_equalr()
+int clgeti(), btoi(), strlen()
+pointer pt_gdata()
+real clgetr()
+
+int isizel, isizem, isizep, nrep, ncrt, ilab, nulbll, ioffd
+int ioffm, isolid, nla, nlm, first
+real xlt, ybt, side, ext, hold[5]
+common /conflg/ first
+common /conre4/ isizel, isizem , isizep, nrep, ncrt, ilab, nulbll,
+ ioffd, ext, ioffm, isolid, nla, nlm, xlt, ybt, side
+common /noaolb/ hold
+
+begin
+ # Check for undefined graphics stream.
+ if (gd == NULL) {
+ call printf ("The graphics device is undefined\n")
+ return
+ }
+
+ # Check for undefined input image.
+ if (im == NULL) {
+ call printf ("The graphics device is undefined\n")
+ return
+ }
+
+ # Check fo an undefined center.
+ if (IS_INDEFR(x) || IS_INDEFR(y)) {
+ call printf ("The center of the contour plot is undefined\n")
+ return
+ }
+
+ # Get the data.
+ ny = clgeti ("cntrplot.nlines")
+ nx = clgeti ("cntrplot.ncolumns")
+ x1 = x - (nx - 1) / 2 + 0.5
+ x2 = x + nx / 2 + 0.5
+ y1 = y - (ny - 1) / 2 + 0.5
+ y2 = y + ny / 2 + 0.5
+ data = pt_gdata (im, x1, x2, y1, y2)
+ if (data == NULL) {
+ call printf ("The image section to be contoured is off the image\n")
+ return
+ }
+
+ call smark (sp)
+
+ # Intialize the plot
+ call gclear (gd)
+
+ # Set the WCS.
+ xs = x1
+ xe = x2
+ ys = y1
+ ye = y2
+ call gswind (gd, xs, xe, ys, ye)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (! clgetb ("cntrplot.fill"))
+ call gsetr (gd, G_ASPECT, real (ny-1) / real (nx-1))
+ call gseti (gd, G_ROUND, btoi (clgetb ("cntrplot.round")))
+
+ if (clgetb ("cntrplot.box")) {
+
+ # Get number of major and minor tick marks.
+ call gseti (gd, G_XNMAJOR, clgeti ("cntrplot.majrx"))
+ call gseti (gd, G_XNMINOR, clgeti ("cntrplot.minrx"))
+ call gseti (gd, G_YNMAJOR, clgeti ("cntrplot.majry"))
+ call gseti (gd, G_YNMINOR, clgeti ("cntrplot.minry"))
+
+ # Label tick marks on axes ?
+ call gseti (gd, G_LABELTICKS, btoi (clgetb ("cntrplot.ticklabels")))
+
+ # Construct the title.
+ call salloc (longtitle, 2 * SZ_LINE, TY_CHAR)
+ if (clgetb ("cntrplot.banner")) {
+ call sysid (Memc[longtitle], 2 * SZ_LINE)
+ call sprintf (Memc[longtitle+strlen(Memc[longtitle])],
+ 2 * SZ_LINE,
+ "\nObject at x: %g y: %g\n\nContour plot of %s[%d:%d,%d:%d]\n")
+ call pargr (x)
+ call pargr (y)
+ call pargstr (IM_HDRFILE(im))
+ call pargi (x1)
+ call pargi (x2)
+ call pargi (y1)
+ call pargi (y2)
+ } else {
+ call sprintf (Memc[longtitle], 2 * SZ_LINE,
+ "\nObject at x: %g y: %g\n\nContour plot of %s[%d:%d,%d:%d]\n")
+ call pargr (x)
+ call pargr (y)
+ call pargstr (IM_HDRFILE(im))
+ call pargi (x1)
+ call pargi (x2)
+ call pargi (y1)
+ call pargi (y2)
+ }
+
+ call glabax (gd, Memc[longtitle], "", "")
+ }
+
+ # First of all, intialize conrec's block data before altering any
+ # parameters in common.
+ first = 1
+ call conbd
+
+ # Set the contouring parameters.
+ zero = clgetr ("cntrplot.zero")
+ floor = clgetr ("cntrplot.floor")
+ ceiling = clgetr ("cntrplot.ceiling")
+ nhi = clgeti ("cntrplot.nhi")
+ dashpat = clgeti ("cntrplot.dashpat")
+
+ # Resolve INDEF limits.
+ npts = nx * ny
+ if (IS_INDEFR (floor) || IS_INDEFR (ceiling)) {
+ call alimr (Memr[data], npts, zmin, zmax)
+ if (IS_INDEFR (floor))
+ floor = zmin
+ if (IS_INDEFR (ceiling))
+ ceiling = zmax
+ }
+
+ # Apply the zero point shift.
+ if (abs (zero) > EPSILON) {
+ call salloc (data1, npts, TY_REAL)
+ call asubkr (Memr[data], zero, Memr[data1], npts)
+ floor = floor - zero
+ ceiling = ceiling - zero
+ } else
+ data1 = data
+
+ # Avoid conrec's automatic scaling.
+ if (fp_equalr (floor, 0.0))
+ floor = EPSILON
+ if (fp_equalr (ceiling, 0.0))
+ ceiling = EPSILON
+
+ # The user can suppress the contour labelling by setting the common
+ # parameter "ilab" to zero.
+ if (btoi (clgetb ("cntrplot.label")) == NO)
+ ilab = 0
+ else
+ ilab = 1
+
+ # User can specify either the number of contours or the contour
+ # interval, or let conrec pick a nice number. Get params and
+ # encode the FINC param expected by conrec.
+
+ ncontours = clgeti ("cntrplot.ncontours")
+ if (ncontours <= 0) {
+ interval = clgetr ("cntrplot.interval")
+ if (interval <= 0.0)
+ finc = 0
+ else
+ finc = interval
+ } else
+ finc = - abs (ncontours)
+
+ # Open device and make contour plot.
+ call gopks (STDERR)
+ wkid = 1
+ call gopwk (wkid, 6, gd)
+ call gacwk (wkid)
+
+ # Make the contour plot.
+ nset = 1 # No conrec viewport
+ ioffm = 1 # No conrec box
+ call gswind (gd, 1., real (nx), 1., real (ny))
+ call ggview (gd, vx1, vx2, vy1, vy2)
+ call set (vx1, vx2, vy1, vy2, 1.0, real (nx), 1.0, real (ny), 1)
+ call conrec (Memr[data1], nx, nx, ny, floor, ceiling, finc, nset,
+ nhi, -dashpat)
+
+ call gdawk (wkid)
+ call gclks ()
+
+ call gswind (gd, xs, xe, ys, ye)
+ if (fp_equalr (hold[5], 1.0)) {
+ call sprintf (Memc[longtitle], 2 * SZ_LINE,
+ "\n\nContoured from %g to %g, interval = %g\n\n")
+ call pargr (hold[1])
+ call pargr (hold[2])
+ call pargr (hold[3])
+ } else {
+ call sprintf (Memc[longtitle], 2 * SZ_LINE,
+ "\n\nContoured from %g to %g, interval = %g, labels scaled by %g\n\n")
+ call pargr (hold[1])
+ call pargr (hold[2])
+ call pargr (hold[3])
+ call pargr (hold[5])
+ }
+
+ call gseti (gd, G_DRAWAXES, NO)
+ call glabax (gd, Memc[longtitle], "", "")
+
+ call sfree (sp)
+end
+
+
+# PT_PERIMETER -- Draw and label axes around the surface plot.
+
+procedure pt_perimeter (gd, z, ncols, nlines, angh, angv)
+
+pointer gd # graphics pointer
+int ncols # number of image columns
+int nlines # number of image lines
+real z[ncols, nlines] # array of intensity values
+real angh # angle of horizontal inclination
+real angv # angle of vertical inclination
+
+char tlabel[10]
+int i, j
+pointer sp, x_val, y_val, kvec
+real xmin, ymin, delta, fact1, flo, hi, xcen, ycen
+real x1_perim, x2_perim, y1_perim, y2_perim, z1, z2
+real wc1, wc2, wl1, wl2, del
+int itoc()
+
+data fact1 /2.0/
+real vpx1, vpx2, vpy1, vpy2
+common /noaovp/ vpx1, vpx2, vpy1, vpy2
+
+begin
+ call smark (sp)
+ call salloc (x_val, ncols + 2, TY_REAL)
+ call salloc (y_val, nlines + 2, TY_REAL)
+ call salloc (kvec, max (ncols, nlines) + 2, TY_REAL)
+
+ # Get window coordinates set up calling procedure.
+ call ggwind (gd, wc1, wc2, wl1, wl2)
+
+ # Set up window, viewport for output. The coordinates returned
+ # from trn32s are in the range [1-1024].
+ call set (vpx1, vpx2, vpy1, vpy2, 1.0, 1024., 1.0, 1024., 1)
+
+ # Find range of z for determining perspective.
+ flo = MAX_REAL
+ hi = -flo
+ do j = 1, nlines {
+ call alimr (z[1,j], ncols, z1, z2)
+ flo = min (flo, z1)
+ hi = max (hi, z2)
+ }
+
+ # Set up linear endpoints and spacing as used in surface.
+ delta = (hi-flo) / (max (ncols, nlines) -1.) * fact1
+ xmin = -(real (ncols/2) * delta + real (mod (ncols+1, 2)) * delta)
+ ymin = -(real (nlines/2) * delta + real (mod (nlines+1, 2)) * delta)
+ del = 2.0 * delta
+
+ # The perimeter is separated from the surface plot by the
+ # width of delta.
+ x1_perim = xmin - delta
+ y1_perim = ymin - delta
+ x2_perim = xmin + (real (ncols) * delta)
+ y2_perim = ymin + (real (nlines) * delta)
+
+ # Set up linear arrays over full perimeter range.
+ do i = 1, ncols + 2
+ Memr[x_val+i-1] = x1_perim + (i-1) * delta
+ do i = 1, nlines + 2
+ Memr[y_val+i-1] = y1_perim + (i-1) * delta
+
+ # Draw and label axes and tick marks.
+ # It is important that frame has not been called after calling srface.
+ # First to draw the perimeter. Which axes get drawn depends on the
+ # values of angh and angv. Get angles in the range [-180, 180].
+
+ if (angh > 180.)
+ angh = angh - 360.
+ else if (angh < -180.)
+ angh = angh + 360.
+ if (angv > 180.)
+ angv = angv - 360.
+ else if (angv < -180.)
+ angv = angv + 360.
+
+ # Calculate positions for the axis labels.
+ xcen = 0.5 * (x1_perim + x2_perim)
+ ycen = 0.5 * (y1_perim + y2_perim)
+
+ if (angh >= 0.0) {
+
+ # Case 1: xy rotation positive, looking down from above mid z.
+ if (angv >= 0.0) {
+
+ # First draw x axis.
+ call amovkr (y2_perim, Memr[kvec], ncols + 2)
+ call pt_draw_axis (Memr[x_val+1], Memr[kvec], flo, ncols + 1)
+ call pt_label_axis (xcen, y2_perim+del, flo, "X-AXIS", -1, -2)
+ call pt_draw_ticksx (Memr[x_val+1], y2_perim, y2_perim+delta,
+ flo, ncols)
+ if (itoc (int (wc1), tlabel, 10) <= 0)
+ tlabel[1] = EOS
+ call pt_label_axis (xmin, y2_perim+del, flo, tlabel, -1, -2)
+ if (itoc (int (wc2), tlabel, 10) <= 0)
+ tlabel[1] = EOS
+ call pt_label_axis (Memr[x_val+ncols], y2_perim+del, flo,
+ tlabel, -1, -2)
+
+ # Now draw y axis.
+ call amovkr (x2_perim, Memr[kvec], nlines + 2)
+ call pt_draw_axis (Memr[kvec], Memr[y_val+1], flo, nlines + 1)
+ call pt_label_axis (x2_perim+del, ycen, flo, "Y-AXIS", 2, -1)
+ call pt_draw_ticksy (x2_perim, x2_perim+delta, Memr[y_val+1],
+ flo, nlines)
+ if (itoc (int (wl1), tlabel, 10) <= 0)
+ tlabel[1] = EOS
+ call pt_label_axis (x2_perim+del, ymin, flo, tlabel, 2, -1)
+ if (itoc (int (wl2), tlabel, 10) <= 0)
+ tlabel[1] = EOS
+ call pt_label_axis (x2_perim+del, Memr[y_val+nlines], flo,
+ tlabel, 2, -1)
+
+ # Case 2: xy rotation positive, looking up from below mid z.
+ } else {
+
+ # First draw x axis.
+ call amovkr (y1_perim, Memr[kvec], ncols + 2)
+ call pt_draw_axis (Memr[x_val], Memr[kvec], flo, ncols + 1)
+ call pt_label_axis (xcen, y1_perim-del, flo, "X-AXIS", -1, 2)
+ call pt_draw_ticksx (Memr[x_val+1], y1_perim, y1_perim-delta,
+ flo, ncols)
+ if (itoc (int (wc1), tlabel, 10) <= 0)
+ tlabel[1] = EOS
+ call pt_label_axis (xmin, y1_perim-del, flo, tlabel, -1, 2)
+ if (itoc (int (wc2), tlabel, 10) <= 0)
+ tlabel[1] = EOS
+ call pt_label_axis (Memr[x_val+ncols], y1_perim-del, flo,
+ tlabel, -1, 2)
+
+ # Now draw y axis.
+ call amovkr (x1_perim, Memr[kvec], nlines + 2)
+ call pt_draw_axis (Memr[kvec], Memr[y_val], flo, nlines + 1)
+ call pt_label_axis (x1_perim-del, ycen, flo, "Y-AXIS", 2, 1)
+ call pt_draw_ticksy (x1_perim, x1_perim-delta, Memr[y_val+1],
+ flo, nlines)
+ if (itoc (int (wl1), tlabel, 10) <= 0)
+ tlabel[1] = EOS
+ call pt_label_axis (x1_perim-del, ymin, flo, tlabel, 2, 1)
+ if (itoc (int (wl2), tlabel, 10) <= 0)
+ tlabel[1] = EOS
+ call pt_label_axis (x1_perim-del, Memr[y_val+nlines], flo,
+ tlabel, 2, 1)
+ }
+ }
+
+ if (angh < 0.0) {
+
+ # Case 3: xy rotation negative, looking down from above mid z
+ # (default).
+ if (angv > 0.0) {
+
+ # First draw x axis.
+ call amovkr (y1_perim, Memr[kvec], ncols + 2)
+ call pt_draw_axis (Memr[x_val+1], Memr[kvec], flo, ncols + 1)
+ call pt_label_axis (xcen, y1_perim-del, flo, "X-AXIS", 1, 2)
+ call pt_draw_ticksx (Memr[x_val+1], y1_perim, y1_perim-delta,
+ flo, ncols)
+ if (itoc (int (wc1), tlabel, 10) <= 0)
+ tlabel[1] = EOS
+ call pt_label_axis (xmin, y1_perim-del, flo, tlabel, 1, 2)
+ if (itoc (int (wc2), tlabel, 10) <= 0)
+ tlabel[1] = EOS
+ call pt_label_axis (Memr[x_val+ncols], y1_perim-del, flo,
+ tlabel, 1, 2)
+
+ # Now draw y axis.
+ call amovkr (x2_perim, Memr[kvec], nlines + 2)
+ call pt_draw_axis (Memr[kvec], Memr[y_val], flo, nlines + 1)
+ call pt_label_axis (x2_perim+del, ycen, flo, "Y-AXIS", 2, -1)
+ call pt_draw_ticksy (x2_perim, x2_perim+delta, Memr[y_val+1],
+ flo, nlines)
+ if (itoc (int (wl1), tlabel, 10) <= 0)
+ tlabel[1] = EOS
+ call pt_label_axis (x2_perim+del, ymin, flo, tlabel, 2, -1)
+ if (itoc (int (wl2), tlabel, 10) <= 0)
+ tlabel[1] = EOS
+ call pt_label_axis (x2_perim+del, Memr[y_val+nlines], flo,
+ tlabel, 2, -1)
+
+ # Case 4: xy rotation negative, looking up from below mid Z.
+ } else {
+
+ # First draw x axis.
+ call amovkr (y2_perim, Memr[kvec], ncols + 2)
+ call pt_draw_axis (Memr[x_val], Memr[kvec], flo, ncols + 1)
+ call pt_label_axis (xcen, y2_perim+del, flo, "X-AXIS", 1, -2)
+ call pt_draw_ticksx (Memr[x_val+1], y2_perim, y2_perim+delta,
+ flo, ncols)
+ if (itoc (int (wc1), tlabel, 10) <= 0)
+ tlabel[1] = EOS
+ call pt_label_axis (xmin, y2_perim+del, flo, tlabel, 1, -2)
+ if (itoc (int (wc2), tlabel, 10) <= 0)
+ tlabel[1] = EOS
+ call pt_label_axis (Memr[x_val+ncols], y2_perim+del, flo,
+ tlabel, 1, -2)
+
+ # Now draw y axis.
+ call amovkr (x1_perim, Memr[kvec], nlines + 2)
+ call pt_draw_axis (Memr[kvec], Memr[y_val+1], flo, nlines + 1)
+ call pt_label_axis (x1_perim-del, ycen, flo, "Y-AXIS", 2, 1)
+ call pt_draw_ticksy (x1_perim, x1_perim-delta, Memr[y_val+1],
+ flo, nlines)
+ if (itoc (int (wl1), tlabel, 10) <= 0)
+ tlabel[1] = EOS
+ call pt_label_axis (x1_perim-del, ymin, flo, tlabel, 2, 1)
+ if (itoc (int (wl2), tlabel, 10) <= 0)
+ tlabel[1] = EOS
+ call pt_label_axis (x1_perim-del, Memr[y_val+nlines], flo,
+ tlabel, 2, 1)
+ }
+ }
+
+ # Flush plotit buffer before returning.
+ call plotit (0, 0, 2)
+ call sfree (sp)
+end
+
+
+# PT_DRAW_AXIS -- Draw the axes around the plot.
+
+procedure pt_draw_axis (xvals, yvals, zval, nvals)
+
+real xvals[nvals]
+real yvals[nvals]
+real zval
+int nvals
+
+int i
+pointer sp, xt, yt
+real dum
+
+begin
+ call smark (sp)
+ call salloc (xt, nvals, TY_REAL)
+ call salloc (yt, nvals, TY_REAL)
+
+ do i = 1, nvals
+ call trn32s (xvals[i], yvals[i], zval, Memr[xt+i-1], Memr[yt+i-1],
+ dum, 1)
+
+ call gpl (nvals, Memr[xt], Memr[yt])
+ call sfree (sp)
+end
+
+
+# PT_LABEL_AXIS -- Label the axes.
+
+procedure pt_label_axis (xval, yval, zval, sppstr, path, up)
+
+real xval
+real yval
+real zval
+char sppstr[SZ_LINE]
+int path
+int up
+
+int nchars
+int strlen()
+% character*64 fstr
+
+begin
+ nchars = strlen (sppstr)
+% call f77pak (sppstr, fstr, 64)
+ call pwrzs (xval, yval, zval, fstr, nchars, CSIZE, path, up, 0)
+end
+
+
+# PT_DRAW_TICKSX -- Draw the x tick marks.
+
+procedure pt_draw_ticksx (x, y1, y2, zval, nvals)
+
+real x[nvals]
+real y1, y2
+real zval
+int nvals
+
+int i
+real tkx[2], tky[2], dum
+
+begin
+ do i = 1, nvals {
+ call trn32s (x[i], y1, zval, tkx[1], tky[1], dum, 1)
+ call trn32s (x[i], y2, zval, tkx[2], tky[2], dum, 1)
+ call gpl (2, tkx[1], tky[1])
+ }
+end
+
+
+# PT_DRAW_TICKSY -- Draw the y tick marks.
+
+procedure pt_draw_ticksy (x1, x2, y, zval, nvals)
+
+real x1, x2
+real y[nvals]
+real zval
+int nvals
+
+int i
+real tkx[2], tky[2], dum
+
+begin
+ do i = 1, nvals {
+ call trn32s (x1, y[i], zval, tkx[1], tky[1], dum, 1)
+ call trn32s (x2, y[i], zval, tkx[2], tky[2], dum, 1)
+ call gpl (2, tkx[1], tky[1])
+ }
+end
+
+
+# PT_GDATA -- Get image data with boundary checking.
+
+pointer procedure pt_gdata (im, x1, x2, y1, y2)
+
+pointer im # pointer to the input image
+int x1, x2, y1, y2 # subraster limits both input and output
+
+int i, nc, nl
+pointer imgs2r()
+errchk imgs2r
+
+begin
+ nc = IM_LEN(im,1)
+ nl = IM_LEN(im,2)
+ if (IS_INDEFI (x1))
+ x1 = 1
+ if (IS_INDEFI (x2))
+ x2 = nc
+ if (IS_INDEFI (y1))
+ y1 = 1
+ if (IS_INDEFI (y2))
+ y2 = nl
+
+ i = max (x1, x2)
+ x1 = min (x1, x2)
+ x2 = i
+ i = max (y1, y2)
+ y1 = min (y1, y2)
+ y2 = i
+
+ if (x2 < 1 || x1 > nc || y2 < 1 || y1 > nl)
+ return (NULL)
+
+ x1 = max (1, x1)
+ x2 = min (nc, x2)
+ y1 = max (1, y1)
+ y2 = min (nl, y2)
+
+ return (imgs2r (im, x1, x2, y1, y2))
+end
+
+
+# PT_RADPIX -- Procedure to fetch the image pixels in an annulus around
+# a given center.
+
+int procedure pt_radpix (im, wx, wy, rin, rout, rcoords, pix)
+
+pointer im # pointer to IRAF image
+real wx, wy # center of sky annulus
+real rin, rout # inner and outer radius of sky annulus
+real rcoords[ARB] # radial coordinate array
+real pix[ARB] # pixel array
+
+int i, j, ncols, nlines, c1, c2, l1, l2, npix
+pointer buf
+real xc1, xc2, xl1, xl2, rin2, rout2, rj2, r2
+pointer imgs2r()
+
+begin
+ if (rout <= rin)
+ return (0)
+
+ # Test for out of bounds sky regions.
+ ncols = IM_LEN(im,1)
+ nlines = IM_LEN(im,2)
+ xc1 = wx - rout
+ xc2 = wx + rout
+ xl1 = wy - rout
+ xl2 = wy + rout
+ if (xc2 < 1.0 || xc1 > real (ncols) || xl2 < 1.0 || xl1 > real (nlines))
+ return (0)
+
+ # Compute the column and line limits.
+ c1 = max (1.0, min (real (ncols), wx - rout)) + 0.5
+ c2 = min (real (ncols), max (1.0, wx + rout)) + 0.5
+ l1 = max (1.0, min (real (nlines), wy - rout)) + 0.5
+ l2 = min (real (nlines), max (1.0, wy + rout)) + 0.5
+
+ # Fetch the sky pixels.
+ rin2 = rin ** 2
+ rout2 = rout ** 2
+ npix = 0
+
+ do j = l1, l2 {
+ buf = imgs2r (im, c1, c2, j, j)
+ rj2 = (wy - j) ** 2
+ do i = c1, c2 {
+ r2 = (wx - i) ** 2 + rj2
+ if (r2 > rin2 && r2 <= rout2) {
+ rcoords[npix+1] = sqrt (r2)
+ pix[npix+1] = Memr[buf+i-c1]
+ npix = npix + 1
+ }
+ }
+ }
+
+ return (npix)
+end
diff --git a/noao/digiphot/ptools/pexamine/ptplot.x b/noao/digiphot/ptools/pexamine/ptplot.x
new file mode 100644
index 00000000..beeb9fec
--- /dev/null
+++ b/noao/digiphot/ptools/pexamine/ptplot.x
@@ -0,0 +1,1462 @@
+include <error.h>
+include <mach.h>
+include <ctype.h>
+include <gset.h>
+include <fset.h>
+include <tbset.h>
+include "../../lib/ptkeysdef.h"
+include "pexamine.h"
+
+define GHELPFILE "ptools$pexamine/pexamine.key"
+define FRACTION 0.05
+
+int procedure pt_plot (gd, px, apd, apkey, im, deleted, npix, max_npix,
+ first_star, match_radius, use_display)
+
+pointer gd # pointer to the graphics stream
+pointer px # pointer to the pexamine structure
+pointer apd # the input catalog descriptor
+pointer apkey # pointer to the text file structure
+pointer im # pointer to the input image
+int deleted[ARB] # array of deleted values
+int npix # number of points
+int max_npix # maximum number of points
+int first_star # first object read in
+real match_radius # tolerance in pixels for cursor positioning
+int use_display # use the image display
+
+int newdata, newxy, xyinvalid, newhist, hinvalid, plottype, newplot
+int firstplot, newcoo, cooinvalid, undelete, status, key, starno, curtype
+pointer sp, title, xlabel, ylabel, cmd, x, y, h, xpos, ypos
+real wx, wy, twx, twy
+
+bool fp_equalr()
+int pt_rxydata(), pt_rhdata(), pt_rcoodata(), pt_getphot(), pt_fstarg()
+int pt_gcur(), pt_gldata()
+
+define replot_ 91
+
+begin
+ # Allocate working stack space.
+ call smark (sp)
+ call salloc (title, SZ_LINE, TY_CHAR)
+ call salloc (xlabel, SZ_LINE, TY_CHAR)
+ call salloc (ylabel, SZ_LINE, TY_CHAR)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Initialize some parameters.
+ twx = INDEFR
+ twy = INDEFR
+ newdata = NO
+ newxy = YES
+ newhist = YES
+ newcoo = YES
+ newplot = YES
+ firstplot = YES
+ curtype = 'g'
+ plottype = PX_XYPLOT
+ call amovki (PX_GOOD, deleted, npix)
+
+ undelete = NO
+
+replot_
+ if (newdata == YES) {
+ if (apkey != NULL) {
+ call pt_kyfree (apkey)
+ call pt_kyinit (apkey)
+ }
+ npix = pt_getphot (px, apd, apkey, npix, first_star)
+ }
+
+ if (newxy == YES)
+ xyinvalid = pt_rxydata (px, x, y)
+ if (newhist == YES)
+ hinvalid = pt_rhdata (px, h)
+ if (newcoo == YES)
+ cooinvalid = pt_rcoodata (px, xpos, ypos)
+
+ switch (plottype) {
+ case PX_XYPLOT:
+ call pt_xyinfo (px, apd, apkey, Memc[title], SZ_LINE,
+ Memc[xlabel], Memc[ylabel], SZ_LINE)
+ if (xyinvalid == NO) {
+ if (newplot == YES) {
+ call pt_xyplot (gd, Memr[x], Memr[y], deleted, npix,
+ Memc[title], Memc[xlabel], Memc[ylabel])
+ }
+ } else {
+ call printf ("Cannot plot X: %s versus Y: %s\n")
+ call pargstr (Memc[xlabel])
+ call pargstr (Memc[ylabel])
+ }
+
+ case PX_HISTPLOT:
+ call pt_hinfo (px, apd, apkey, Memc[title], SZ_LINE,
+ Memc[xlabel], Memc[ylabel], SZ_LINE)
+ if (hinvalid == NO) {
+ if (newplot == YES) {
+ call pt_hplot (gd, Memr[h], deleted, npix, Memc[title],
+ Memc[xlabel], Memc[ylabel])
+ }
+ } else {
+ call printf ("Cannot plot histogram of %s\n")
+ call pargstr (Memc[xlabel])
+ }
+
+ case PX_RADPLOT:
+ if (im != NULL) {
+ if (newplot == YES)
+ call pt_rplot (gd, im, twx, twy)
+ } else
+ call printf ("The input image is undefined\n")
+
+ case PX_SURFPLOT:
+ if (im != NULL) {
+ if (newplot == YES)
+ call pt_splot (gd, im, twx, twy)
+ } else
+ call printf ("The input image is undefined\n")
+
+ case PX_CNTRPLOT:
+ if (im != NULL) {
+ if (newplot == YES)
+ call pt_cplot (gd, im, twx, twy)
+ } else
+ call printf ("The input image is undefined\n")
+
+ default:
+ call printf ("Invalid plot type\n")
+ }
+
+ if ((firstplot == YES || newdata == YES) && (xyinvalid == NO)) {
+ call printf ("nstars read: %d first_star: %d max_nstars: %d\n")
+ call pargi (npix)
+ call pargi (first_star)
+ call pargi (max_npix)
+ }
+
+ newdata = NO
+ newxy = NO
+ newcoo = NO
+ newhist = NO
+ newplot = NO
+ firstplot = NO
+
+ while (pt_gcur (curtype, wx, wy, key, Memc[cmd], SZ_LINE) != EOF) {
+
+ switch (key) {
+
+ # Quit and do not make changes.
+ case 'q':
+ call printf ("Type 'q' to confirm quit without saving edits\n")
+ if (pt_gcur (curtype, wx, wy, key, Memc[cmd], SZ_LINE) == EOF)
+ next
+ if (key != 'q')
+ next
+ status = PX_QUIT
+ break
+
+ # Exit and do the changes.
+ case 'e':
+ status = PX_EXIT
+ break
+
+ # Print the help page.
+ case '?':
+ call gpagefile (gd, GHELPFILE, "")
+
+ # Activate the graphics cursor.
+ case 'g':
+ curtype = 'g'
+
+ # Activate the image cursor.
+ case 'i':
+ if (use_display == YES)
+ curtype = 'i'
+ else
+ call printf ("The image display is not available\n")
+
+ # Plot the current y column versus the current x column.
+ case 'x':
+ if (plottype != PX_XYPLOT) {
+ newplot = YES
+ plottype = PX_XYPLOT
+ }
+ if (newplot == YES)
+ goto replot_
+
+ # Plot the current histogram.
+ case 'h':
+ if (plottype != PX_HISTPLOT) {
+ newplot = YES
+ plottype = PX_HISTPLOT
+ }
+ if (newplot == YES)
+ goto replot_
+
+ # Print a matrix of points around the cursor.
+ case 'm':
+ if (im == NULL) {
+ call printf ("The input image is undefined\n")
+ next
+ } else if (cooinvalid == YES) {
+ call printf ("The x or y coordinate data is undefined\n")
+ next
+ } else if (curtype == 'i') {
+ starno = pt_fstarg (gd, wx, wy, Memr[xpos], Memr[ypos],
+ npix, match_radius)
+ } else if (xyinvalid == YES) {
+ call printf ("The x or y column data is undefined\n")
+ next
+ } else if (plottype != PX_XYPLOT) {
+ call printf ("Points must be marked on an X-Y plot\n")
+ next
+ } else {
+ starno = pt_fstarg (gd, wx, wy, Memr[x], Memr[y], npix,
+ INDEFR)
+ }
+
+ if (starno > 0)
+ call pt_print (gd, im, Memr[xpos+starno-1],
+ Memr[ypos+starno-1])
+
+ # Plot the the radial profile of the point nearest the graphics
+ # cursor.
+ case 'r', 's', 'c':
+
+ if (im == NULL) {
+ call printf ("The input image is undefined\n")
+ next
+ }
+ if (cooinvalid == YES) {
+ call printf ("The x or y coordinate data is undefined\n")
+ next
+ }
+
+ if (curtype == 'i') {
+ starno = pt_fstarg (gd, wx, wy, Memr[xpos], Memr[ypos],
+ npix, match_radius)
+ } else if (xyinvalid == YES) {
+ call printf ("The x or y column data is undefined\n")
+ next
+ } else if (plottype != PX_XYPLOT) {
+ call printf ("Points must be marked on the X-Y plot\n")
+ next
+ } else {
+ starno = pt_fstarg (gd, wx, wy, Memr[x], Memr[y], npix,
+ INDEFR)
+ }
+
+ if (starno > 0) {
+ switch (key) {
+ case 'r':
+ if (plottype != PX_RADPLOT)
+ newplot = YES
+ plottype = PX_RADPLOT
+ case 'c':
+ if (plottype != PX_CNTRPLOT)
+ newplot = YES
+ plottype = PX_CNTRPLOT
+ case 's':
+ if (plottype != PX_SURFPLOT)
+ newplot = YES
+ plottype = PX_SURFPLOT
+ }
+ wx = Memr[xpos+starno-1]
+ wy = Memr[ypos+starno-1]
+ if (! fp_equalr (wx, twx) && ! fp_equalr (wy, twy)) {
+ newplot = YES
+ twx = wx
+ twy = wy
+ }
+ } else
+ call printf ("Cannot find selected star in the catalog\n")
+
+ if (newplot == YES)
+ goto replot_
+
+ # Replot the current plot.
+ case 'p':
+ newplot = YES
+ goto replot_
+
+ # Print out the names, types and units of all defined columns.
+ case 'l':
+ call pt_colinfo (gd, apd, apkey)
+
+ # Print out the names, values and units of the stored columns
+ # for the object nearest the cursor.
+ case 'o':
+ if (curtype == 'g') {
+ if (xyinvalid == YES)
+ call printf ("The x or y column data is undefined\n")
+ else if (plottype != PX_XYPLOT)
+ call printf ("Points must be marked on an x-y plot\n")
+ else {
+ starno = pt_gldata (gd, px, apd, apkey, wx, wy,
+ Memr[x], Memr[y], npix, INDEFR)
+ if (starno > 0)
+ call printf ("Star found\n")
+ else
+ call printf ("Star not found\n")
+ }
+ } else if (curtype == 'i') {
+ if (cooinvalid == NO) {
+ starno = pt_gldata (gd, px, apd, apkey, wx, wy,
+ Memr[xpos], Memr[ypos], npix, match_radius)
+ if ((gd != NULL) && (starno > 0) && (xyinvalid == NO) &&
+ (plottype == PX_XYPLOT)) {
+ call gscur (gd, Memr[x+starno-1], Memr[y+starno-1])
+ call printf ("Star found\n")
+ curtype = 'g'
+ } else
+ call printf ("Star not found\n")
+ } else
+ call printf (
+ "The x or y coordinate data is undefined\n")
+ }
+
+ # Undelete everything.
+ case 'z':
+ call amovki (PX_GOOD, deleted, npix)
+ newplot = YES
+ goto replot_
+
+ # Delete points and replot.
+ case 'f':
+ call pt_update (deleted, npix)
+ newplot = YES
+ goto replot_
+
+ # Mark a point for deletion.
+ case 'd':
+ if (curtype == 'g') {
+ if ((xyinvalid == YES) || (plottype != PX_XYPLOT))
+ call printf (
+ "Invalid plot type for deleting points\n")
+ else
+ call pt_delpt (gd, wx, wy, Memr[x], Memr[y], Memr[x],
+ Memr[y], deleted, npix, NO, INDEFR)
+ } else if (curtype == 'i') {
+ if (cooinvalid == NO) {
+ if ((xyinvalid == NO) && (plottype == PX_XYPLOT))
+ call pt_delpt (gd, wx, wy, Memr[xpos], Memr[ypos],
+ Memr[x], Memr[y], deleted, npix, NO,
+ match_radius)
+ else
+ call pt_delpt (NULL, wx, wy, Memr[xpos], Memr[ypos],
+ Memr[x], Memr[y], deleted, npix, NO,
+ match_radius)
+ } else
+ call printf (
+ "The x or y coordinate data is undefined\n")
+ }
+
+ # Undelete a point marked for deletion.
+ case 'u':
+ if (curtype == 'g') {
+ if ((xyinvalid == YES) || (plottype != PX_XYPLOT))
+ call printf (
+ "Invalid plot type for undeleting points\n")
+ else
+ call pt_delpt (gd, wx, wy, Memr[x], Memr[y], Memr[x],
+ Memr[y], deleted, npix, YES, INDEFR)
+ } else if (curtype == 'i') {
+ if (cooinvalid == NO) {
+ if (xyinvalid == NO && plottype == PX_XYPLOT)
+ call pt_delpt (gd, wx, wy, Memr[xpos], Memr[ypos],
+ Memr[x], Memr[y], deleted, npix, YES,
+ match_radius)
+ else
+ call pt_delpt (NULL, wx, wy, Memr[xpos], Memr[ypos],
+ Memr[x], Memr[y], deleted, npix, YES,
+ match_radius)
+ } else
+ call printf (
+ "The x and y coordinate data is undefined\n")
+ }
+
+ # Toggle the delete/undelete function
+ case 't':
+ if (undelete == NO) {
+ call printf ("Now undeleting points\n")
+ undelete = YES
+ } else if (undelete == YES) {
+ call printf ("Now deleting points\n")
+ undelete = NO
+ }
+
+ # Mark for deletion points with X < X (cursor).
+ case '(':
+ if (curtype == 'g') {
+ if ((xyinvalid == NO) && (plottype == PX_XYPLOT)) {
+ call pt_dxltg (gd, wx, Memr[x], Memr[x], Memr[y],
+ deleted, npix, undelete)
+ } else if ((hinvalid == NO) && plottype == PX_HISTPLOT) {
+ call pt_dxltg (NULL, wx, Memr[h], Memr[h], Memr[h],
+ deleted, npix, undelete)
+ newplot = YES
+ } else
+ call printf (
+ "Invalid plot type for (un)deleting points\n")
+ } else if (curtype == 'i') {
+ if (cooinvalid == YES) {
+ call printf (
+ "The x or y coordinate data is undefined\n")
+ } else if ((xyinvalid == NO) && (plottype == PX_XYPLOT)) {
+ call pt_dxltg (gd, wx, Memr[xpos], Memr[x], Memr[y],
+ deleted, npix, undelete)
+ } else {
+ call pt_dxltg (NULL, wx, Memr[xpos], Memr[x], Memr[y],
+ deleted, npix, undelete)
+ if (plottype == PX_XYPLOT || plottype == PX_HISTPLOT)
+ newplot = YES
+ else
+ call printf (
+ "Replot x-y or histogram to show (un)deletions\n")
+ }
+ }
+ if (newplot == YES)
+ goto replot_
+
+ # Mark for deletion points with X > X (cursor).
+ case ')':
+ if (curtype == 'g') {
+ if ((xyinvalid == NO) && (plottype == PX_XYPLOT)) {
+ call pt_dxgtg (gd, wx, Memr[x], Memr[x], Memr[y],
+ deleted, npix, undelete)
+ } else if ((hinvalid == NO) && (plottype == PX_HISTPLOT)) {
+ call pt_dxgtg (NULL, wx, Memr[h], Memr[h], Memr[h],
+ deleted, npix, undelete)
+ newplot = YES
+ } else
+ call printf (
+ "Invalid plot type for (un)deleting points\n")
+ } else if (curtype == 'i') {
+ if (cooinvalid == YES) {
+ call printf (
+ "The x and y coordinate data is undefined\n")
+ } else if ((xyinvalid == NO) && (plottype == PX_XYPLOT)) {
+ call pt_dxgtg (gd, wx, Memr[xpos], Memr[x], Memr[y],
+ deleted, npix, undelete)
+ } else {
+ call pt_dxgtg (NULL, wx, Memr[xpos], Memr[x], Memr[y],
+ deleted, npix, undelete)
+ if (plottype == PX_XYPLOT || plottype == PX_HISTPLOT)
+ newplot = YES
+ else
+ call printf (
+ "Replot x-y or histogram to show (un)deletions\n")
+ }
+ }
+ if (newplot == YES)
+ goto replot_
+
+ # Mark for deletion points with Y > Y (cursor).
+ case '^':
+ if (curtype == 'g') {
+ if ((xyinvalid == NO) && (plottype == PX_XYPLOT))
+ call pt_dygtg (gd, wy, Memr[y], Memr[x], Memr[y],
+ deleted, npix, undelete)
+ else
+ call printf (
+ "Invalid plot type for (un)deleting points\n")
+ } else if (curtype == 'i') {
+ if (cooinvalid == YES)
+ call printf (
+ "The x and y coordinate data is undefined\n")
+ else if ((xyinvalid == NO) && (plottype == PX_XYPLOT))
+ call pt_dygtg (gd, wy, Memr[ypos], Memr[x], Memr[y],
+ deleted, npix, undelete)
+ else {
+ call pt_dygtg (NULL, wy, Memr[ypos], Memr[x], Memr[y],
+ deleted, npix, undelete)
+ if (plottype == PX_XYPLOT || plottype == PX_HISTPLOT)
+ newplot = YES
+ else
+ call printf (
+ "Replot x-y or histogram to show (un)deletions\n")
+ }
+ }
+ if (newplot == YES)
+ goto replot_
+
+ # Mark for deletion points with Y < Y (cursor).
+ case 'v':
+ if (curtype == 'g') {
+ if ((xyinvalid == NO) && (plottype == PX_XYPLOT))
+ call pt_dyltg (gd, wy, Memr[y], Memr[x], Memr[y],
+ deleted, npix, undelete)
+ else
+ call printf (
+ "Invalid plot type for (un)deleting points\n")
+ } else if (curtype == 'i') {
+ if (cooinvalid == YES)
+ call printf (
+ "The x and y coordinate data is undefined\n")
+ else if ((xyinvalid == NO) && (plottype == PX_XYPLOT))
+ call pt_dyltg (gd, wy, Memr[ypos], Memr[x], Memr[y],
+ deleted, npix, undelete)
+ else {
+ call pt_dyltg (NULL, wy, Memr[ypos], Memr[x], Memr[y],
+ deleted, npix, undelete)
+ if (plottype == PX_XYPLOT || plottype == PX_HISTPLOT)
+ newplot = YES
+ else
+ call printf (
+ "Replot x-y or histogram to show (un)deletions\n")
+ }
+ }
+ if (newplot == YES)
+ goto replot_
+
+ # Mark points for deletion inside a box.
+ case 'b':
+ if (curtype == 'g') {
+ if ((xyinvalid == NO) && (plottype == PX_XYPLOT)) {
+ twx = wx; twy = wy
+ call printf ("again:\n")
+ if (pt_gcur (curtype, wx, wy, key, Memc[cmd],
+ SZ_LINE) == EOF)
+ next
+ call pt_dboxg (gd, Memr[x], Memr[y], Memr[x], Memr[y],
+ deleted, npix, twx, twy, wx, wy, undelete)
+ } else
+ call printf (
+ "Invalid plot type for (un)deleting points\n")
+ } else if (curtype == 'i') {
+ if (cooinvalid == YES)
+ call printf (
+ "The x or y coordinate data is undefined\n")
+ else {
+ twx = wx; twy = wy
+ call printf ("again:\n")
+ if (pt_gcur (curtype, wx, wy, key, Memc[cmd],
+ SZ_LINE) == EOF)
+ next
+ if ((xyinvalid == NO) && (plottype == PX_XYPLOT))
+ call pt_dboxg (gd, Memr[xpos], Memr[ypos], Memr[x],
+ Memr[y], deleted, npix, twx, twy, wx, wy,
+ undelete)
+ else {
+ call pt_dboxg (NULL, Memr[xpos], Memr[ypos],
+ Memr[x], Memr[y], deleted, npix, twx, twy,
+ wx, wy, undelete)
+ if ((plottype == PX_XYPLOT) ||
+ (plottype == PX_HISTPLOT))
+ newplot = YES
+ else
+ call printf (
+ "Replot x-y or histogram to show (un)deletions\n")
+ }
+ }
+ }
+
+ # Colon commands:
+ case ':':
+ iferr (call pt_colon (px, gd, Memc[cmd], newdata, newxy,
+ newhist, newcoo, newplot, plottype, undelete))
+ call erract (EA_WARN)
+ if (newplot == YES)
+ goto replot_
+
+ default:
+ call printf ("Unknown or ambiguous keystroke command\007\n")
+ }
+ }
+
+ call sfree (sp)
+
+ return (status)
+end
+
+
+# PT_PRINT -- Print a 10 by 10 box of pixel values around the star.
+
+procedure pt_print (gd, im, x, y)
+
+pointer gd # pointer to the graphics stream
+pointer im # pointer to the input image
+real x, y # center of box
+
+int i, j, x1, x2, y1, y2, nx
+pointer data
+pointer pt_gdata()
+
+begin
+ if (gd != NULL)
+ call gdeactivate (gd, 0)
+
+ # Check that the image is defined.
+ if (im == NULL) {
+ call printf ("The input image is undefined\n")
+ return
+ }
+
+ # Check that the center is defined.
+ if (IS_INDEFR(x) || IS_INDEFR(y)) {
+ call printf ("The box center is undefined\n")
+ return
+ }
+
+ x1 = x - 5 + 0.5
+ x2 = x + 5 + 0.5
+ y1 = y - 5 + 0.5
+ y2 = y + 5 + 0.5
+ data = pt_gdata (im, x1, x2, y1, y2)
+ if (data == NULL) {
+ call printf ("The requested image section is off the image\n")
+ return
+ }
+ nx = x2 - x1 + 1
+
+ call printf ("\n%4w")
+ do i = x1, x2 {
+ call printf (" %4d ")
+ call pargi (i)
+ }
+ call printf ("\n")
+
+ do j = y2, y1, -1 {
+ call printf ("%4d")
+ call pargi (j)
+ do i = x1, x2 {
+ call printf (" %5g")
+ call pargr (Memr[data+(j-y1)*nx+(i-x1)])
+ }
+ call printf ("\n")
+ }
+ call printf ("\n")
+
+ if (gd != NULL)
+ call greactivate (gd, 0)
+end
+
+
+define LEN_TYPESTR 9
+
+# PT_COLINFO -- Print the name, type and units of all the columns in the
+# input catalog.
+
+procedure pt_colinfo (gd, apd, key)
+
+pointer gd # pointer to the graphics stream
+pointer apd # the file descriptor for the input catalog
+int key # the key structure for text catalogs
+
+int len_colname, i, datatype, numelems
+pointer tty, sp, name, units, type, junk, colptr
+int tbpsta(), tbcigi(), pt_gnfn(), pt_kstati()
+pointer ttyodes(), tbcnum(), pt_ofnl()
+
+begin
+ if (gd != NULL)
+ call gdeactivate (gd, AW_CLEAR)
+ else {
+ tty = ttyodes ("terminal")
+ call ttyclear (STDOUT, tty)
+ }
+
+ len_colname = max (SZ_COLNAME, KY_SZPAR)
+ call printf ("\n%*.*s %*.*s %s\n\n")
+ call pargi (-len_colname)
+ call pargi (len_colname)
+ call pargstr ("COLUMN")
+ call pargi (-LEN_TYPESTR)
+ call pargi (LEN_TYPESTR)
+ call pargstr ("TYPE")
+ call pargstr ("UNITS")
+
+ call smark (sp)
+ call salloc (name, len_colname, TY_CHAR)
+ call salloc (units, max (SZ_COLUNITS, KY_SZPAR), TY_CHAR)
+ call salloc (type, LEN_TYPESTR, TY_CHAR)
+
+ if (key == NULL) {
+
+ do i = 1, tbpsta (apd, TBL_NCOLS) {
+
+ colptr = tbcnum (apd, i)
+ call tbcigt (colptr, TBL_COL_NAME, Memc[name], SZ_COLNAME)
+ call tbcigt (colptr, TBL_COL_UNITS, Memc[units], SZ_COLUNITS)
+ datatype = tbcigi (colptr, TBL_COL_DATATYPE)
+ switch (datatype) {
+ case TY_BOOL:
+ call strcpy ("boolean", Memc[type], LEN_TYPESTR)
+ case TY_SHORT, TY_INT, TY_LONG:
+ call strcpy ("integer", Memc[type], LEN_TYPESTR)
+ case TY_REAL:
+ call strcpy ("real", Memc[type], LEN_TYPESTR)
+ case TY_DOUBLE:
+ call strcpy ("double", Memc[type], LEN_TYPESTR)
+ default:
+ if (datatype < 0)
+ call strcpy ("character", Memc[type], LEN_TYPESTR)
+ else
+ call strcpy ("undefined", Memc[type], LEN_TYPESTR)
+ }
+
+ call printf ("%*.*s %*.*s %s\n")
+ call pargi (-len_colname)
+ call pargi (len_colname)
+ call pargstr (Memc[name])
+ call pargi (-LEN_TYPESTR)
+ call pargi (LEN_TYPESTR)
+ call pargstr (Memc[type])
+ call pargstr (Memc[units])
+ }
+
+ } else {
+
+ call salloc (junk, SZ_LINE, TY_CHAR)
+ colptr = pt_ofnl (key, "*")
+ while (pt_gnfn (colptr, Memc[name], Memc[junk], KY_SZPAR) != EOF) {
+ #if (pt_kstati (key, Memc[name], KY_INDEX) <= KY_NOKEYS(key))
+ if (pt_kstati (key, Memc[name], KY_INDEX) <= KY_NPKEYS(key))
+ next
+ numelems = pt_kstati (key, Memc[name], KY_NUMELEMS)
+ call pt_kstats (key, Memc[name], KY_UNITSTR, Memc[units],
+ KY_SZPAR)
+ datatype = pt_kstati (key, Memc[name], KY_DATATYPE)
+ switch (datatype) {
+ case TY_BOOL:
+ call strcpy ("boolean", Memc[type], LEN_TYPESTR)
+ case TY_CHAR:
+ call strcpy ("character", Memc[type], LEN_TYPESTR)
+ case TY_INT:
+ call strcpy ("integer", Memc[type], LEN_TYPESTR)
+ case TY_REAL:
+ call strcpy ("real", Memc[type], LEN_TYPESTR)
+ default:
+ call strcpy ("undefined", Memc[type], LEN_TYPESTR)
+ }
+
+ do i = 1, numelems {
+ if (numelems == 1)
+ call strcpy (Memc[name], Memc[junk], KY_SZPAR)
+ else {
+ call sprintf (Memc[junk], KY_SZPAR, "%s[%d]")
+ call pargstr (Memc[name])
+ call pargi (numelems)
+ }
+ call printf ("%*.*s %*.*s %s\n")
+ call pargi (-len_colname)
+ call pargi (len_colname)
+ call pargstr (Memc[junk])
+ call pargi (-LEN_TYPESTR)
+ call pargi (LEN_TYPESTR)
+ call pargstr (Memc[type])
+ call pargstr (Memc[units])
+ }
+
+ }
+ call pt_cfnl (colptr)
+
+ }
+ call printf ("\n")
+
+ call sfree (sp)
+
+ if (gd != NULL)
+ call greactivate (gd, AW_PAUSE)
+ else
+ call ttycdes (tty)
+end
+
+
+# PT_GLDATA -- List the values of the loaded columns for this point.
+
+int procedure pt_gldata (gd, px, apd, key, wx, wy, x, y, npix, matchrad)
+
+pointer gd # pointer to the graphics stream
+pointer px # pointer to the pexamine structure
+int apd # file descriptor for catalog
+pointer key # pointer to the key structure for text files
+real wx # the graphics cursor x coordinate
+real wy # the graphics cursor y coordinate
+real x[ARB] # the array of x plotted data
+real y[ARB] # the array of y plotted data
+int npix # the number of points
+real matchrad # matching radius
+
+int row, ip, ncol
+pointer sp, name, units, colptr
+int pt_getnames(), pt_fstarg()
+
+begin
+ if (gd != NULL)
+ call gdeactivate (gd, 0)
+
+ # Find the star.
+ row = pt_fstarg (gd, wx, wy, x, y, npix, matchrad)
+
+ # List the values of the loaded columns.
+ if (row != 0) {
+
+ call smark (sp)
+ call salloc (name, PX_SZCOLNAME, TY_CHAR)
+ call salloc (units, max (KY_SZPAR, SZ_COLUNITS), TY_CHAR)
+
+ call printf ("\n%*.*s %s (%s)\n\n")
+ call pargi (-PX_SZCOLNAME)
+ call pargi (PX_SZCOLNAME)
+ call pargstr ("COLUMN")
+ call pargstr ("VALUE")
+ call pargstr ("UNITS")
+
+ ip = 1
+ ncol = 0
+ while (pt_getnames (Memc[PX_COLNAMES(px)], ip, Memc[name],
+ PX_SZCOLNAME) != EOF) {
+ if (PX_COLPTRS(px) == NULL)
+ next
+ if (key == NULL) {
+ call tbcfnd (apd, Memc[name], colptr, 1)
+ call tbcigt (colptr, TBL_COL_UNITS, Memc[units],
+ SZ_COLUNITS)
+ } else
+ call pt_kstats (key, Memc[name], KY_UNITSTR, Memc[units],
+ KY_SZPAR)
+ call printf ("%*.*s %g (%s)\n")
+ call pargi (-PX_SZCOLNAME)
+ call pargi (PX_SZCOLNAME)
+ call pargstr (Memc[name])
+ call pargr (Memr[Memi[PX_COLPTRS(px)+ncol]+row-1])
+ call pargstr (Memc[units])
+ ncol = ncol + 1
+ }
+ call printf ("\n")
+
+ call sfree (sp)
+ }
+
+ if (gd != NULL)
+ call greactivate (gd, 0)
+
+ return (row)
+end
+
+
+# PT_XYPLOT -- Plot the x and y points.
+
+procedure pt_xyplot (gd, x, y, deleted, npix, title, xlabel, ylabel)
+
+pointer gd # pointer to the graphics stream
+real x[ARB] # array of x coordinates
+real y[ARB] # array of y coordinates
+int deleted[ARB] # deletions array
+int npix # number of points
+char title[ARB] # title of the plot
+char xlabel[ARB] # x axis label
+char ylabel[ARB] # y axis label
+
+int i, marker_type
+pointer sp, marker, longtitle
+real szmarker, x1, x2, y1, y2, dmin, dmax
+bool clgetb()
+int clgeti(), strlen()
+real clgetr()
+
+begin
+ # Check for undefined graphis stream.
+ if (gd == NULL) {
+ call printf ("The graphics device is undefined\n")
+ return
+ }
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (marker, SZ_FNAME, TY_CHAR)
+ call salloc (longtitle, 2 * SZ_LINE, TY_CHAR)
+
+ # Clear the plotting strucuture.
+ call gclear (gd)
+
+ # Fetch the window and viewport parameters.
+ x1 = clgetr ("xyplot.x1")
+ x2 = clgetr ("xyplot.x2")
+ y1 = clgetr ("xyplot.y1")
+ y2 = clgetr ("xyplot.y2")
+ if (IS_INDEFR(x1) || IS_INDEFR(x2)) {
+ call pt_alimr (x, npix, dmin, dmax)
+ if (IS_INDEFR(x1))
+ x1 = dmin - FRACTION * (dmax - dmin)
+ if (IS_INDEFR(x2))
+ x2 = dmax + FRACTION * (dmax - dmin)
+ }
+ if (IS_INDEFR(y1) || IS_INDEFR(y2)) {
+ call pt_alimr (y, npix, dmin, dmax)
+ if (IS_INDEFR(y1))
+ y1 = dmin - FRACTION * (dmax - dmin)
+ if (IS_INDEFR(y2))
+ y2 = dmax + FRACTION * (dmax - dmin)
+ }
+
+ # Set the scale of the axes.
+ call gswind (gd, x1, x2, y1, y2)
+ if (clgetb ("xyplot.logx"))
+ call gseti (gd, G_XTRAN, GW_LOG)
+ else
+ call gseti (gd, G_XTRAN, GW_LINEAR)
+ if (clgetb ("xyplot.logy"))
+ call gseti (gd, G_YTRAN, GW_LOG)
+ else
+ call gseti (gd, G_YTRAN, GW_LINEAR)
+
+ # Get the x and y axes parameters.
+ if (! clgetb ("xyplot.fill"))
+ call gseti (gd, G_ASPECT, 1)
+ if (clgetb ("xyplot.round"))
+ call gseti (gd, G_ROUND, YES)
+
+ # Get the axis drawing parameters.
+ if (clgetb ("xyplot.box")) {
+
+ # Get number of major and minor tick marks.
+ call gseti (gd, G_XNMAJOR, clgeti ("xyplot.majrx"))
+ call gseti (gd, G_XNMINOR, clgeti ("xyplot.minrx"))
+ call gseti (gd, G_YNMAJOR, clgeti ("xyplot.majry"))
+ call gseti (gd, G_YNMINOR, clgeti ("xyplot.minry"))
+
+ # Label tick marks on axes.
+ if (clgetb ("xyplot.ticklabels"))
+ call gseti (gd, G_LABELTICKS, YES)
+ else
+ call gseti (gd, G_LABELTICKS, NO)
+
+ # Draw grid.
+ if (clgetb ("xyplot.grid"))
+ call gseti (gd, G_DRAWGRID, YES)
+ else
+ call gseti (gd, G_DRAWGRID, NO)
+
+ # Optionally draw a box around the plot.
+ if (clgetb ("xyplot.banner")) {
+ call sysid (Memc[longtitle], 2 * SZ_LINE)
+ call sprintf (Memc[longtitle+strlen(Memc[longtitle])],
+ 2 * SZ_LINE, "\n%s")
+ call pargstr (title)
+ } else
+ call strcpy (title, Memc[longtitle], 2 * SZ_LINE)
+ call glabax (gd, Memc[longtitle], xlabel, ylabel)
+
+ }
+
+ # Get the marker type, the size of the marker and the linewidth.
+ call clgstr ("xyplot.marker", Memc[marker], SZ_FNAME)
+ call pt_marker (Memc[marker], SZ_FNAME, marker_type)
+ if (marker_type != GM_POINT)
+ szmarker = clgetr ("xyplot.szmarker")
+ else
+ szmarker = 0.0
+ call gsetr (gd, G_PLWIDTH, 2.0)
+
+ # Draw the points in using the deletions array.
+ do i = 1, npix {
+ if (deleted[i] == PX_DELETE)
+ next
+ call gmark (gd, x[i], y[i], marker_type, szmarker, szmarker)
+ }
+
+ # Overplot crosses for those new points marked for deletion.
+ call pt_mdelete (gd, x, y, deleted, npix)
+
+ call gflush (gd)
+ call sfree (sp)
+end
+
+
+# PT_HPLOT -- Compute and plot histogram.
+
+procedure pt_hplot (gd, x, deleted, npix, title, xlabel, ylabel)
+
+pointer gd # pointer to the graphics stream
+real x[ARB] # array of points to be made into a histogram
+int deleted[ARB] # deletions array
+int npix # number of pixels
+char title[ARB] # the title of the plot
+char xlabel[ARB] # the x axis label
+char ylabel[ARB] # the y axis label
+
+int i, j, nbins, nbins1
+pointer sp, hgm, xp, yp, longtitle
+real z1, z2, dz, x1, x2, y1, y2, dmin, dmax
+bool clgetb(), fp_equalr()
+int clgeti(), strlen()
+real clgetr()
+
+begin
+ # Check for undefined graphis stream.
+ if (gd == NULL) {
+ call printf ("The graphics device is undefined\n")
+ return
+ }
+
+ # Get default histogram resolution and range.
+ nbins = clgeti ("histplot.nbins")
+ z1 = clgetr ("histplot.z1")
+ z2 = clgetr ("histplot.z2")
+
+ # Use data limits for INDEF limits.
+ if (IS_INDEFR(z1) || IS_INDEFR(z2)) {
+ call pt_alimr (x, npix, dmin, dmax)
+ if (IS_INDEFR(z1))
+ z1 = dmin
+ if (IS_INDEFR(z2))
+ z2 = dmax
+ }
+ if (z1 > z2) {
+ dz = z1
+ z1 = z2
+ z2 = dz
+ }
+
+ # Test for constant valued image, which causes zero divide in ahgm.
+ if (fp_equalr (z1, z2)) {
+ call printf ("Warning: Histogram has no data range.\n")
+ return
+ }
+
+ # The extra bin counts the pixels that equal z2 and shifts the
+ # remaining bins to evenly cover the interval [z1,z2].
+ # Note that real numbers could be handled better - perhaps
+ # adjust z2 upward by ~ EPSILONR (in ahgm itself).
+
+ nbins1 = nbins + 1
+
+ # Initialize the histogram buffer and image line vector.
+ call smark (sp)
+ call salloc (hgm, nbins1, TY_INT)
+ call aclri (Memi[hgm], nbins1)
+
+ # Accumulate the histogram. Add the ability to use the deletions
+ # array in future.
+ call pt_ahgmr (x, deleted, npix, Memi[hgm], nbins1, z1, z2)
+
+ # "Correct" the topmost bin for pixels that equal z2. Each
+ # histogram bin really wants to be half open.
+
+ if (clgetb ("histplot.top_closed"))
+ Memi[hgm+nbins-1] = Memi[hgm+nbins-1] + Memi[hgm+nbins1-1]
+
+ # List or plot the histogram. In list format, the bin value is the
+ # z value of the left side (start) of the bin.
+
+ dz = (z2 - z1) / real (nbins)
+
+ # Plot the histogram in box mode.
+ nbins1 = 2 * nbins + 2
+ call salloc (xp, nbins1, TY_REAL)
+ call salloc (yp, nbins1, TY_REAL)
+ Memr[xp] = z1
+ Memr[yp] = 0.0
+ j = 1
+ do i = 0, nbins - 1 {
+ Memr[xp+j] = Memr[xp+j-1]
+ Memr[yp+j] = Memi[hgm+i]
+ j = j + 1
+ Memr[xp+j] = Memr[xp+j-1] + dz
+ Memr[yp+j] = Memr[yp+j-1]
+ j = j + 1
+ }
+ Memr[xp+j] = Memr[xp+j-1]
+ Memr[yp+j] = 0.0
+
+ # Construct the title.
+ call salloc (longtitle, 2 * SZ_LINE, TY_CHAR)
+ if (clgetb ("histplot.banner")) {
+ call sysid (Memc[longtitle], 2 * SZ_LINE)
+ call sprintf (Memc[longtitle+strlen(Memc[longtitle])], 2 * SZ_LINE,
+ "\nHistogram from z1=%g to z2=%g, nbins=%d\n%s")
+ call pargr (z1)
+ call pargr (z2)
+ call pargi (nbins)
+ call pargstr (title)
+ } else {
+ call sprintf (Memc[longtitle], 2 * SZ_LINE,
+ "Histogram from z1=%g to z2=%g, nbins=%d\n%s")
+ call pargr (z1)
+ call pargr (z2)
+ call pargi (nbins)
+ call pargstr (title)
+ }
+
+ # Clear the screen.
+ call gclear (gd)
+
+ # Compute the data window to be plotted.
+ x1 = clgetr ("histplot.x1")
+ x2 = clgetr ("histplot.x2")
+ if (IS_INDEFR(x1) || IS_INDEFR(x2)) {
+ call alimr (Memr[xp], nbins1, dmin, dmax)
+ if (IS_INDEFR(x1))
+ x1 = dmin
+ if (IS_INDEFR(x2))
+ x2 = dmax
+ }
+ y1 = clgetr ("histplot.y1")
+ y2 = clgetr ("histplot.y2")
+ if (IS_INDEFR(y1) || IS_INDEFR(y2)) {
+ call alimr (Memr[yp], nbins1, dmin, dmax)
+ if (IS_INDEFR(y1))
+ y1 = dmin
+ if (IS_INDEFR(y2))
+ y2 = dmax
+ }
+
+ # Set the scale of the axes.
+ call gswind (gd, x1, x2, y1, y2)
+ call gseti (gd, G_XTRAN, GW_LINEAR)
+ if (clgetb ("histplot.logy"))
+ call gseti (gd, G_YTRAN, GW_LOG)
+ else
+ call gseti (gd, G_YTRAN, GW_LINEAR)
+
+ if (! clgetb ("xyplot.fill"))
+ call gseti (gd, G_ASPECT, 1)
+ if (clgetb ("xyplot.round"))
+ call gseti (gd, G_ROUND, YES)
+ call gsetr (gd, G_PLWIDTH, 2.0)
+
+ # Draw a box around the axes.
+ if (clgetb ("histplot.box")) {
+
+ # Label tick marks on axes.
+ if (clgetb ("histplot.ticklabels"))
+ call gseti (gd, G_LABELTICKS, YES)
+ else
+ call gseti (gd, G_LABELTICKS, NO)
+
+ # Get number of major and minor tick marks.
+ call gseti (gd, G_XNMAJOR, clgeti ("histplot.majrx"))
+ call gseti (gd, G_XNMINOR, clgeti ("histplot.minrx"))
+ call gseti (gd, G_YNMAJOR, clgeti ("histplot.majry"))
+ call gseti (gd, G_YNMINOR, clgeti ("histplot.minry"))
+
+ # Draw the axes.
+ call glabax (gd, Memc[longtitle], xlabel, ylabel)
+
+ }
+
+ # Draw the historgram.
+ call gseti (gd, G_PLTYPE, GL_SOLID)
+ call gpline (gd, Memr[xp], Memr[yp], nbins1)
+ call gflush (gd)
+
+ call sfree (sp)
+end
+
+
+# PT_XYINFO -- Get the title and axes labels for the X-Y plot.
+
+procedure pt_xyinfo (px, tp, key, title, max_sztitle, xlabel, ylabel,
+ max_szlabel)
+
+pointer px # pointer to the pexamine strcuture
+pointer tp # input catalog file descriptor
+pointer key # pointer to key structure for text files
+char title[ARB] # title for the plot
+int max_sztitle # maximum length of the title
+char xlabel[ARB] # X axis label
+char ylabel[ARB] # Y axis label
+int max_szlabel # maximum size of the label
+
+pointer sp, label, units, cd
+
+begin
+ call smark (sp)
+ call salloc (label, max_szlabel, TY_CHAR)
+ call salloc (units, max_szlabel, TY_CHAR)
+
+ # Get the title.
+
+ # Get the x and y labels for the columns.
+ if (key == NULL) {
+
+ call tbtnam (tp, title, max_sztitle)
+
+ call tbcfnd (tp, PX_XCOLNAME(px), cd, 1)
+ if (cd != NULL) {
+ call strcpy (PX_XCOLNAME(px), Memc[label], max_szlabel)
+ call tbcigt (cd, TBL_COL_UNITS, Memc[units], SZ_COLUNITS)
+ } else {
+ call strcpy ("UNDEFINED", Memc[label], max_szlabel)
+ Memc[units] = EOS
+ }
+ call sprintf (xlabel, max_szlabel, "%s in %s")
+ call pargstr (Memc[label])
+ call pargstr (Memc[units])
+
+ call tbcfnd (tp, PX_YCOLNAME(px), cd, 1)
+ if (cd != NULL) {
+ call strcpy (PX_YCOLNAME(px), Memc[label], max_szlabel)
+ call tbcigt (cd, TBL_COL_UNITS, Memc[units], SZ_COLUNITS)
+ } else {
+ call strcpy ("UNDEFINED", Memc[label], max_szlabel)
+ Memc[units] = EOS
+ }
+ call sprintf (ylabel, max_szlabel, "%s in %s")
+ call pargstr (Memc[label])
+ call pargstr (Memc[units])
+
+ } else {
+
+ call fstats (tp, F_FILENAME, title, max_sztitle)
+
+ if (PX_XCOLNAME(px) == EOS) {
+ call strcpy ("UNDEFINED", Memc[label], max_szlabel)
+ Memc[units] = EOS
+ } else {
+ call strcpy (PX_XCOLNAME(px), Memc[label], max_szlabel)
+ call pt_kstats (key, PX_XCOLNAME(px), KY_UNITSTR, Memc[units],
+ max_szlabel)
+ }
+ call sprintf (xlabel, max_szlabel, "%s %s")
+ call pargstr (Memc[label])
+ call pargstr (Memc[units])
+
+ if (PX_YCOLNAME(px) == EOS) {
+ call strcpy ("UNDEFINED", Memc[label], max_szlabel)
+ Memc[units] = EOS
+ } else {
+ call strcpy (PX_YCOLNAME(px), Memc[label], max_szlabel)
+ call pt_kstats (key, PX_YCOLNAME(px), KY_UNITSTR, Memc[units],
+ max_szlabel)
+ }
+ call sprintf (ylabel, max_szlabel, "%s %s")
+ call pargstr (Memc[label])
+ call pargstr (Memc[units])
+
+ }
+
+ call sfree (sp)
+end
+
+
+# PT_HINFO -- Get the title and axes labels for the histogram plot.
+
+procedure pt_hinfo (px, tp, key, title, max_sztitle, xlabel, ylabel,
+ max_szlabel)
+
+pointer px # pointer to the pexamine strcuture
+pointer tp # input catalog file descriptor
+pointer key # pointer to key structure for text files
+char title[ARB] # title for the plot
+int max_sztitle # maximum length of the title
+char xlabel[ARB] # X axis label
+char ylabel[ARB] # Y axis label
+int max_szlabel # maximum size of the label
+
+pointer sp, label, units, cd
+
+begin
+ call smark (sp)
+ call salloc (label, max_szlabel, TY_CHAR)
+ call salloc (units, max_szlabel, TY_CHAR)
+
+ # Get the title.
+
+ # Get the x and y labels for the columns.
+ if (key == NULL) {
+
+ call tbtnam (tp, title, max_sztitle)
+
+ call tbcfnd (tp, PX_HCOLNAME(px), cd, 1)
+ if (cd != NULL) {
+ call strcpy (PX_HCOLNAME(px), Memc[label], max_szlabel)
+ call tbcigt (cd, TBL_COL_UNITS, Memc[units], SZ_COLUNITS)
+ } else {
+ call strcpy ("UNDEFINED", Memc[label], max_szlabel)
+ Memc[units] = EOS
+ }
+ call sprintf (xlabel, max_szlabel, "%s in %s")
+ call pargstr (Memc[label])
+ call pargstr (Memc[units])
+
+ call sprintf (ylabel, max_szlabel, "N(%s)")
+ call pargstr (Memc[label])
+
+ } else {
+
+ call fstats (tp, F_FILENAME, title, max_sztitle)
+
+ if (PX_HCOLNAME(px) == EOS) {
+ call strcpy ("UNDEFINED", Memc[label], max_szlabel)
+ Memc[units] = EOS
+ } else {
+ call strcpy (PX_HCOLNAME(px), Memc[label], max_szlabel)
+ call pt_kstats (key, PX_HCOLNAME(px), KY_UNITSTR, Memc[units],
+ max_szlabel)
+ }
+ call sprintf (xlabel, max_szlabel, "%s %s")
+ call pargstr (Memc[label])
+ call pargstr (Memc[units])
+
+ call sprintf (ylabel, max_szlabel, "N(%s)")
+ call pargstr (Memc[label])
+
+ }
+
+ call sfree (sp)
+end
+
+
+# PT_GCUR -- Get PEXAMINE cursor value.
+# This is an interface between the standard cursor input and PEXAMINE.
+# It reads the appropriate cursor, makes the appropriate default
+# coordinate conversions when using graphics cursor input, and gets any
+# further cursor reads needed. Missing coordinates default to the last
+# coordinates.
+
+int procedure pt_gcur (curtype, x, y, key, strval, maxch)
+
+int curtype # cursor type
+real x, y # cursor position
+int key # keystroke value of cursor event
+char strval[ARB] # string value, if any
+int maxch # max chars out
+
+char ch
+int nitems, wcs, ip
+int clgcur(), ctor(), cctoc()
+errchk clgcur
+
+begin
+ # Initialize.
+ strval[1] = EOS
+
+ # Get a cursor values from the desired cursor parameter.
+ switch (curtype) {
+ case 'i':
+ nitems = clgcur ("icommands", x, y, wcs, key, strval, maxch)
+ case 'g':
+ nitems = clgcur ("gcommands", x, y, wcs, key, strval, maxch)
+ }
+
+ call flush (STDOUT)
+
+ # Map numeric colon sequences (: x [y] key strval) to make them appear
+ # as ordinary "x y key" type cursor reads. This makes it possible for
+ # the user to access any command using typed in rather than positional
+ # cursor coordinates. Special treatment is also given to the syntax
+ # ":lN" and ":cN", provided for compatibility with IMPLOT for simple
+ # line and column plots.
+
+ if (key == ':') {
+ for (ip=1; IS_WHITE(strval[ip]); ip=ip+1)
+ ;
+ if (IS_DIGIT(strval[ip])) {
+ if (ctor (strval, ip, x) <= 0)
+ ;
+ if (ctor (strval, ip, y) <= 0)
+ y = x
+ for (; IS_WHITE(strval[ip]); ip=ip+1)
+ ;
+ if (cctoc (strval, ip, ch) > 0)
+ key = ch
+ call strcpy (strval[ip], strval, maxch)
+
+ }
+ }
+
+ return (nitems)
+end
+
+
+# PT_FSTARG -- Find the the point data point nearest the input position.
+
+int procedure pt_fstarg (gd, wx, wy, x, y, npix, matchrad)
+
+pointer gd # pointer to the graphics descriptor
+real wx # X cursor position
+real wy # Y cursor position
+real x[ARB] # X array of plotted data
+real y[ARB] # Y array of plotted data
+int npix # number of pixels
+real matchrad # the matching radius
+
+int i, row
+real r2min, r2, mr2, wx0, wy0, x0, y0
+
+begin
+ row = 0
+ r2min = MAX_REAL
+ if (IS_INDEFR(matchrad)) {
+ mr2 = MAX_REAL
+ if (gd != NULL)
+ call gctran (gd, wx, wy, wx0, wy0, 1, 0)
+ else {
+ wx0 = wx
+ wy0 = wy
+ }
+ } else {
+ mr2 = matchrad ** 2
+ wx0 = wx
+ wy0 = wy
+ }
+
+ # Search for the nearest point.
+ do i = 1 , npix {
+ if (! IS_INDEFR(x[i]) && ! IS_INDEFR(y[i])) {
+ if (IS_INDEFR(matchrad)) {
+ if (gd != NULL)
+ call gctran (gd, x[i], y[i], x0, y0, 1, 0)
+ else {
+ x0 = x[i]
+ y0 = y[i]
+ }
+ } else {
+ x0 = x[i]
+ y0 = y[i]
+ }
+ r2 = (wx0 - x0) ** 2 + (wy0 - y0) ** 2
+ } else
+ r2 = MAX_REAL
+ if (r2 >= r2min)
+ next
+ r2min = r2
+ row = i
+ }
+
+ if ((row != 0) && (r2min <= mr2))
+ return (row)
+ else
+ return (0)
+end
+
+
+# PT_MARKER -- Return an integer code for the marker type string.
+
+procedure pt_marker (marker, maxch, imark)
+
+char marker[ARB] # string defining the marker type
+int maxch # maximum length of the marker name
+int imark # the integer code for the marker
+
+int i
+int strdic()
+
+begin
+ i = strdic (marker, marker, maxch, PX_MARKERS)
+ switch (i) {
+ case 1:
+ imark = GM_POINT
+ case 2:
+ imark = GM_BOX
+ case 3:
+ imark = GM_PLUS
+ case 4:
+ imark = GM_CROSS
+ case 5:
+ imark = GM_CIRCLE
+ case 6:
+ imark = GM_HLINE
+ case 7:
+ imark = GM_VLINE
+ case 8:
+ imark = GM_DIAMOND
+ default:
+ imark = GM_BOX
+ call strcpy ("box", marker, maxch)
+ }
+end
diff --git a/noao/digiphot/ptools/pexamine/ptrddata.x b/noao/digiphot/ptools/pexamine/ptrddata.x
new file mode 100644
index 00000000..ff0864b9
--- /dev/null
+++ b/noao/digiphot/ptools/pexamine/ptrddata.x
@@ -0,0 +1,125 @@
+include "../../lib/ptkeysdef.h"
+include "pexamine.h"
+
+# PT_RXYDATA -- Load the data for the input columns from the structure.
+
+int procedure pt_rxydata (px, xptr, yptr)
+
+pointer px # pointer to the pexamine structure
+pointer xptr # pointer to the X coordinate array
+pointer yptr # pointer to the Y coordinate array
+
+int data_invalid, field
+pointer sp, str
+int strdic()
+
+begin
+ data_invalid = NO
+
+ # Allocate some temporary memory
+ call smark (sp)
+ call salloc (str, PX_SZCOLNAME, TY_CHAR)
+
+ # Load the x column.
+ field = strdic (PX_XCOLNAME(px), Memc[str], PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)])
+ if (field > 0)
+ xptr = Memi[PX_COLPTRS(px)+field-1]
+ else {
+ xptr = NULL
+ data_invalid = YES
+ }
+
+ # Load the y column.
+ field = strdic (PX_YCOLNAME(px), Memc[str], PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)])
+ if (field > 0)
+ yptr = Memi[PX_COLPTRS(px)+field-1]
+ else {
+ yptr = NULL
+ data_invalid = YES
+ }
+
+ call sfree (sp)
+
+ return (data_invalid)
+end
+
+
+# PT_RHDATA -- Load the data for the histogram column from the structure.
+
+int procedure pt_rhdata (px, xptr)
+
+pointer px # pointer to the pexamine structure
+pointer xptr # array containing the x points
+
+int data_invalid, field
+pointer sp, str
+int strdic()
+
+begin
+ data_invalid = NO
+
+ # Allocate some temporary memory
+ call smark (sp)
+ call salloc (str, PX_SZCOLNAME, TY_CHAR)
+
+ # Load the x column.
+ field = strdic (PX_HCOLNAME(px), Memc[str], PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)])
+ if (field > 0)
+ xptr = Memi[PX_COLPTRS(px)+field-1]
+ else {
+ xptr = NULL
+ data_invalid = YES
+ }
+
+ call sfree (sp)
+
+ return (data_invalid)
+end
+
+
+# PT_RCOODATA -- Load the coordinate data from the structure.
+
+int procedure pt_rcoodata (px, xptr, yptr)
+
+pointer px # pointer to the pexamine structure
+pointer xptr # pointer to x coordinates array
+pointer yptr # pointer to y coordinates array
+
+int data_invalid, field
+pointer sp, str
+int strdic()
+
+begin
+ data_invalid = NO
+
+ # Allocate some temporary memory
+ call smark (sp)
+ call salloc (str, PX_SZCOLNAME, TY_CHAR)
+
+ # Load the x coordinate.
+ field = strdic (PX_XPOSNAME(px), Memc[str], PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)])
+ if (field > 0)
+ xptr = Memi[PX_COLPTRS(px)+field-1]
+ else {
+ data_invalid = YES
+ xptr = NULL
+ }
+
+ # Load the y coordinate.
+ field = strdic (PX_YPOSNAME(px), Memc[str], PX_SZCOLNAME,
+ Memc[PX_COLNAMES(px)])
+ if (field > 0)
+ yptr = Memi[PX_COLPTRS(px)+field-1]
+ else {
+ data_invalid = YES
+ yptr = NULL
+ }
+
+ call sfree (sp)
+
+ return (data_invalid)
+end
diff --git a/noao/digiphot/ptools/pexamine/ptsetup.x b/noao/digiphot/ptools/pexamine/ptsetup.x
new file mode 100644
index 00000000..5a8bc832
--- /dev/null
+++ b/noao/digiphot/ptools/pexamine/ptsetup.x
@@ -0,0 +1,360 @@
+include <error.h>
+include <ctotok.h>
+include "pexamine.h"
+
+# PT_INIT - Initialize the pexamine structure.
+
+pointer procedure pt_init (photcols, usercols, xcol, ycol, xpos, ypos, hcol)
+
+char photcols[ARB] # the list of photometry columns
+char usercols[ARB] # the list of user columns
+char xcol[ARB] # the name of the x column
+char ycol[ARB] # the name of the y column
+char xpos[ARB] # the name of the x coord column
+char ypos[ARB] # the name of the y coord column
+char hcol[ARB] # the name of the histogram column
+
+pointer px
+bool streq()
+int strdic()
+
+begin
+ # Preload the daophot and apphot photometry fields.
+ if (streq ("DAOPHOT", photcols) || streq ("daophot", photcols))
+ call strcpy (PX_DAOCOLS, photcols, PX_SZCOLNAME * (PX_MAXNCOLS + 1))
+ else if (streq ("APPHOT", photcols) || streq ("apphot", photcols))
+ call strcpy (PX_APCOLS, photcols, PX_SZCOLNAME * (PX_MAXNCOLS + 1))
+
+ # Allocate space for the pexamine structure and the column lists.
+ call malloc (px, LEN_PXSTRUCT, TY_STRUCT)
+
+ # Initialize the requested column information.
+ PX_RNPHOT(px) = 0; PX_RNUSER(px) = 0; PX_RNCOLS(px) = 0
+ call malloc (PX_RCOLNAMES(px), PX_SZCOLNAME * (PX_MAXNCOLS + 1),
+ TY_CHAR)
+ Memc[PX_RCOLNAMES(px)] = EOS
+
+ # Initialize the stored column information.
+ PX_NPHOT(px) = 0; PX_NUSER(px) = 0; PX_NCOLS(px) = 0
+ call malloc (PX_COLNAMES(px), PX_SZCOLNAME * (PX_MAXNCOLS + 1),
+ TY_CHAR)
+ Memc[PX_COLNAMES(px)] = EOS
+
+ # Decode the column strings. Check that the number of columns
+ # does not exceed the maximum number permitted, by extracting
+ # the column names one by one from the photometry and user column
+ # strings.
+
+ call pt_setnames (px, photcols, usercols)
+
+ # Convert all the input column name specifications to upper case.
+ call strupr (xcol)
+ call strupr (ycol)
+ call strupr (xpos)
+ call strupr (ypos)
+ call strupr (hcol)
+
+ # Decode the x and y columns.
+ if (strdic (xcol, PX_RXCOLNAME(px), PX_SZCOLNAME,
+ Memc[PX_RCOLNAMES(px)]) <= 0)
+ call strcpy (xcol, PX_RXCOLNAME(px), PX_SZCOLNAME)
+ if (strdic (ycol, PX_RYCOLNAME(px), PX_SZCOLNAME,
+ Memc[PX_RCOLNAMES(px)]) <= 0)
+ call strcpy (ycol, PX_RYCOLNAME(px), PX_SZCOLNAME)
+
+ # Decode the y and y coordinate column names.
+ if (strdic (xpos, PX_RXPOSNAME(px), PX_SZCOLNAME,
+ Memc[PX_RCOLNAMES(px)]) <= 0)
+ call strcpy (xpos, PX_RXPOSNAME(px), PX_SZCOLNAME)
+ if (strdic (ypos, PX_RYPOSNAME(px), PX_SZCOLNAME,
+ Memc[PX_RCOLNAMES(px)]) <= 0)
+ call strcpy (ypos, PX_RYPOSNAME(px), PX_SZCOLNAME)
+
+ # Decode the histogram column name.
+ if (strdic (hcol, PX_RHCOLNAME(px), PX_SZCOLNAME,
+ Memc[PX_RCOLNAMES(px)]) <= 0)
+ call strcpy (hcol, PX_RHCOLNAME(px), PX_SZCOLNAME)
+
+ # Allocate space for the pointers and initialize them to NULL.
+ call malloc (PX_COLPTRS(px), PX_MAXNCOLS, TY_POINTER)
+ call amovki (NULL, Memi[PX_COLPTRS(px)], PX_MAXNCOLS)
+
+ return (px)
+end
+
+
+# PT_FREE -- Free memory used by the pexamine task.
+
+procedure pt_free (px)
+
+pointer px
+
+int i
+
+begin
+ # Free the column lists.
+ if (PX_RCOLNAMES(px) != NULL)
+ call mfree (PX_RCOLNAMES(px), TY_CHAR)
+ if (PX_COLNAMES(px) != NULL)
+ call mfree (PX_COLNAMES(px), TY_CHAR)
+
+ # Free the column pointers.
+ do i = 1, PX_MAXNCOLS {
+ if (Memi[PX_COLPTRS(px)+i-1] != NULL)
+ call mfree (Memi[PX_COLPTRS(px)+i-1], TY_REAL)
+ }
+ if (PX_COLPTRS(px) != NULL)
+ call mfree (PX_COLPTRS(px), TY_POINTER)
+
+ # Free the pexamine structure.
+ call mfree (px, TY_STRUCT)
+end
+
+
+# PT_SETNAMES -- Decode the photometry and user columns.
+
+procedure pt_setnames (px, photcols, usercols)
+
+pointer px # pointer to the pexamine strucuture
+char photcols[ARB] # list of photometry columns
+char usercols[ARB] # list of user columns
+
+int ip, nphot
+pointer sp, name
+int pt_getnames()
+
+begin
+ call smark (sp)
+ call salloc (name, PX_SZCOLNAME, TY_CHAR)
+
+ call strupr (photcols)
+ call strupr (usercols)
+ Memc[PX_RCOLNAMES(px)] = EOS
+
+ ip = 1
+ nphot = 0
+ while (pt_getnames (photcols, ip, Memc[name], PX_SZCOLNAME) != EOF) {
+ if (nphot >= PX_MAXNCOLS)
+ break
+ #if (Memc[name] == EOS)
+ #next
+ call strcat (",", Memc[PX_RCOLNAMES(px)], PX_SZCOLNAME *
+ (PX_MAXNCOLS + 1))
+ call strcat (Memc[name], Memc[PX_RCOLNAMES(px)], PX_SZCOLNAME *
+ (PX_MAXNCOLS + 1))
+ nphot = nphot + 1
+ }
+ PX_RNPHOT(px) = nphot
+
+ # Decode the user columns.
+ ip = 1
+ while (pt_getnames (usercols, ip, Memc[name], PX_SZCOLNAME) != EOF) {
+ if (nphot >= PX_MAXNCOLS)
+ break
+ #if (Memc[name] == EOS)
+ #next
+ call strcat (",", Memc[PX_RCOLNAMES(px)], PX_SZCOLNAME *
+ (PX_MAXNCOLS + 1))
+ call strcat (Memc[name], Memc[PX_RCOLNAMES(px)], PX_SZCOLNAME *
+ (PX_MAXNCOLS + 1))
+ nphot = nphot + 1
+ }
+ PX_RNUSER(px) = nphot - PX_RNPHOT(px)
+
+ PX_RNCOLS(px) = nphot
+
+ call sfree (sp)
+end
+
+
+# PT_GPHOTCOLS -- Extract the requested and stored photometric columns
+# from the pexamine structure.
+
+procedure pt_gphotcols (px, rphotcols, rnphot, photcols, nphot)
+
+pointer px # pointer to the pexamine structure
+char rphotcols[ARB] # list of requested photometric columns
+int rnphot # number of requested photometric columns
+char photcols[ARB] # list of photometric columns
+int nphot # number of photometric columns
+
+int ip, ncols
+pointer sp, name
+int pt_getnames()
+
+begin
+ call smark (sp)
+ call salloc (name, PX_SZCOLNAME, TY_CHAR)
+
+ ip = 1
+ ncols = 0
+ rphotcols[1] = EOS
+ while (pt_getnames (Memc[PX_RCOLNAMES(px)], ip, Memc[name],
+ PX_SZCOLNAME) != EOF) {
+ #if (Memc[name] == EOS)
+ #next
+ ncols = ncols + 1
+ if (ncols > PX_RNPHOT(px))
+ break
+ call strcat (",", rphotcols, PX_SZCOLNAME * (PX_MAXNCOLS + 1))
+ call strcat (Memc[name], rphotcols, PX_SZCOLNAME *
+ (PX_MAXNCOLS + 1))
+ }
+ rnphot = PX_RNPHOT(px)
+
+ ip = 1
+ ncols = 0
+ photcols[1] = EOS
+ while (pt_getnames (Memc[PX_COLNAMES(px)], ip, Memc[name],
+ PX_SZCOLNAME) != EOF) {
+ #if (Memc[name] == EOS)
+ #next
+ ncols = ncols + 1
+ if (ncols > PX_NPHOT(px))
+ break
+ call strcat (",", photcols, PX_SZCOLNAME * (PX_MAXNCOLS + 1))
+ call strcat (Memc[name], photcols, PX_SZCOLNAME *
+ (PX_MAXNCOLS + 1))
+ }
+ nphot = PX_NPHOT(px)
+
+ call sfree (sp)
+end
+
+
+# PT_GUSERCOLS -- Extract the requested and stored user columns
+# from the pexamine structure.
+
+procedure pt_gusercols (px, rusercols, rnuser, usercols, nuser)
+
+pointer px # pointer to the pexamine structure
+char rusercols[ARB] # list of requested user columns
+int rnuser # number of requested user columns
+char usercols[ARB] # list of user columns
+int nuser # number of user columns
+
+int ip, ncols
+pointer sp, name
+int pt_getnames()
+
+begin
+ call smark (sp)
+ call salloc (name, PX_SZCOLNAME, TY_CHAR)
+
+ ip = 1
+ ncols = 0
+ rusercols[1] = EOS
+ while (pt_getnames (Memc[PX_RCOLNAMES(px)], ip, Memc[name],
+ PX_SZCOLNAME) != EOF) {
+ #if (Memc[name] == EOS)
+ #next
+ ncols = ncols + 1
+ if (ncols <= PX_RNPHOT(px))
+ next
+ call strcat (",", rusercols, PX_SZCOLNAME * (PX_MAXNCOLS + 1))
+ call strcat (Memc[name], rusercols, PX_SZCOLNAME *
+ (PX_MAXNCOLS + 1))
+ }
+ rnuser = PX_RNUSER(px)
+
+ ip = 1
+ ncols = 0
+ usercols[1] = EOS
+ while (pt_getnames (Memc[PX_COLNAMES(px)], ip, Memc[name],
+ PX_SZCOLNAME) != EOF) {
+ #if (Memc[name] == EOS)
+ #next
+ ncols = ncols + 1
+ if (ncols <= PX_NPHOT(px))
+ next
+ call strcat (",", usercols, PX_SZCOLNAME * (PX_MAXNCOLS + 1))
+ call strcat (Memc[name], usercols, PX_SZCOLNAME *
+ (PX_MAXNCOLS + 1))
+ }
+ nuser = PX_NUSER(px)
+
+ call sfree (sp)
+end
+
+
+# PT_LCOLS -- List the requested and stored columns with an optional
+# title string.
+
+procedure pt_lcols (title, rcols, rncols, cols, ncols)
+
+char title[ARB] # title string for column listing
+char rcols[ARB] # list of requested columns
+int rncols # the number of requested columns
+char cols[ARB] # list of stored columns
+int ncols # the number of stored columns
+
+int ip1, ip2, i
+pointer sp, name1, name2
+int pt_getnames()
+
+begin
+ call smark (sp)
+ call salloc (name1, PX_SZCOLNAME, TY_CHAR)
+ call salloc (name2, PX_SZCOLNAME, TY_CHAR)
+
+ call printf ("\n%s\n\n")
+ call pargstr (title)
+
+ ip1 = 1
+ ip2 = 1
+ do i = 1, max (rncols, ncols) {
+ if (pt_getnames (rcols, ip1, Memc[name1], PX_SZCOLNAME) == EOF)
+ Memc[name1] = EOS
+ if (pt_getnames (cols, ip2, Memc[name2], PX_SZCOLNAME) == EOF)
+ Memc[name2] = EOS
+ call printf (" requested: %*.*s stored: %*.*s\n")
+ call pargi (-PX_SZCOLNAME)
+ call pargi (PX_SZCOLNAME)
+ call pargstr (Memc[name1])
+ call pargi (-PX_SZCOLNAME)
+ call pargi (PX_SZCOLNAME)
+ call pargstr (Memc[name2])
+ }
+
+ call sfree (sp)
+end
+
+
+# PT_GETNAMES -- Decode the list of column names into list of column names.
+
+int procedure pt_getnames (colnames, ip, name, maxch)
+
+char colnames[ARB] # list of column names
+int ip # pointer in to the list of names
+char name[ARB] # the output column name
+int maxch # maximum length of a column name
+
+int op, token
+int ctotok(), strlen()
+
+begin
+ # Decode the column labels.
+ op = 1
+ while (colnames[ip] != EOS) {
+
+ token = ctotok (colnames, ip, name[op], maxch)
+ if (name[op] == EOS)
+ next
+ if ((token == TOK_UNKNOWN) || (token == TOK_CHARCON))
+ break
+ if ((token == TOK_PUNCTUATION) && (name[op] == ',')) {
+ if (op == 1)
+ next
+ else
+ break
+ }
+
+ op = op + strlen (name[op])
+ }
+
+ name[op] = EOS
+ if ((colnames[ip] == EOS) && (op == 1))
+ return (EOF)
+ else
+ return (op - 1)
+end
diff --git a/noao/digiphot/ptools/pexamine/ptwtfile.x b/noao/digiphot/ptools/pexamine/ptwtfile.x
new file mode 100644
index 00000000..02f5f282
--- /dev/null
+++ b/noao/digiphot/ptools/pexamine/ptwtfile.x
@@ -0,0 +1,143 @@
+include "../../lib/ptkeysdef.h"
+include "pexamine.h"
+
+# PT_WTFILE -- Write out the catalogs of selected and rejected objects.
+
+procedure pt_wtfile (apd, key, apout, aprej, deleted, nstars)
+
+int apd # input catalog file descriptor
+pointer key # key structure for textfiles
+int apout # output catalog file descriptor
+int aprej # rejections catalog file descriptor
+int deleted[ARB] # deletions array
+int nstars # number of stars in the catalog
+
+int i, nselect, ndelete
+int pt_selrej()
+
+begin
+ # ST tables format.
+ if (key == NULL) {
+
+ # Write out the good data.
+ if (apout != NULL) {
+ call tbtcre (apout)
+ call tbhcal (apd, apout)
+ nselect = 0
+ do i = 1, nstars {
+ if (deleted[i] == PX_DELETE)
+ next
+ nselect = nselect + 1
+ call tbrcpy (apd, apout, i, nselect)
+ }
+ }
+
+ # Write out the deletions.
+ if (aprej != NULL) {
+ call tbtcre (aprej)
+ call tbhcal (apd, aprej)
+ ndelete = 0
+ do i = 1, nstars {
+ if (deleted[i] != PX_DELETE)
+ next
+ ndelete = ndelete + 1
+ call tbrcpy (apd, aprej, i, ndelete)
+ }
+ }
+
+ # Write out a text file.
+ } else {
+ if (pt_selrej (apd, apout, aprej, deleted, nstars) < nstars)
+ ;
+ }
+end
+
+
+define LEN_LONGLINE 10
+
+# PT_SELREJ -- Select and/or reject records based on evaluating a logical
+# expression.
+
+int procedure pt_selrej (tp_in, tp_out, tp_rej, deleted, nstars)
+
+int tp_in # the input catalog file descriptor
+int tp_out # the output catalog file descriptor
+int tp_rej # the rejections catalog file descriptor
+int deleted[ARB] # the deletions array
+int nstars # maximum number of stars
+
+int record, nchars, buflen, lenrecord
+pointer line, lline
+int getline()
+
+begin
+ # Check that output has been requested.
+ if (tp_out == NULL && tp_rej == NULL)
+ return (0)
+
+ # Rewind the input file.
+ call seek (tp_in, BOF)
+
+ # Initialize the file read.
+ record = 0
+ lenrecord = 0
+ buflen = LEN_LONGLINE * SZ_LINE
+ call malloc (line, SZ_LINE, TY_CHAR)
+ call malloc (lline, buflen, TY_CHAR)
+
+ # Loop over the text file records.
+ repeat {
+
+ # Read in a line of the text file.
+ nchars = getline (tp_in, Memc[line])
+ if (nchars == EOF)
+ break
+
+ # Determine the type of record.
+ if (Memc[line] == KY_CHAR_POUND || Memc[line] == KY_CHAR_NEWLINE) {
+
+ if (tp_out != NULL)
+ call putline (tp_out, Memc[line])
+ if (tp_rej != NULL)
+ call putline (tp_rej, Memc[line])
+
+ } else {
+
+ # Reallocate the temporary record space.
+ if (lenrecord > buflen) {
+ buflen = buflen + SZ_LINE
+ call realloc (lline, buflen, TY_CHAR)
+ }
+
+ # Store the record.
+ call amovc (Memc[line], Memc[lline+lenrecord], nchars)
+ lenrecord = lenrecord + nchars
+ Memc[lline+lenrecord] = EOS
+
+ # Do the record bookkeeping.
+ if (Memc[line+nchars-2] != KY_CHAR_CONT) {
+
+ # Increment the record counter.
+ record = record + 1
+
+ # Write out the expression.
+ if ((tp_out != NULL) && (deleted[record] != PX_DELETE))
+ call putline (tp_out, Memc[lline])
+ if ((tp_rej != NULL) && (deleted[record] == PX_DELETE))
+ call putline (tp_rej, Memc[lline])
+ if (record >= nstars)
+ break
+
+ # Reinitialize the record read.
+ lenrecord = 0
+ }
+ }
+
+ }
+
+ # Cleanup.
+ call mfree (line, TY_CHAR)
+ call mfree (lline, TY_CHAR)
+
+ return (record)
+end
diff --git a/noao/digiphot/ptools/pexamine/t_pexamine.x b/noao/digiphot/ptools/pexamine/t_pexamine.x
new file mode 100644
index 00000000..10db0747
--- /dev/null
+++ b/noao/digiphot/ptools/pexamine/t_pexamine.x
@@ -0,0 +1,188 @@
+include <fset.h>
+include <error.h>
+include "pexamine.h"
+
+# T_PEXAMINE -- Interactively examine and edit APPHOT and DAOPHOT output.
+
+procedure t_pexamine()
+
+pointer input # pointer to the name of the catalog
+pointer output # pointer to the name of the edited catalog
+pointer xcolumn # pointer to the name of the X column
+pointer ycolumn # pointer to the name of the Y column
+pointer xposcolumn # pointer to the name of the X coord column
+pointer yposcolumn # pointer to the name of the Y coord column
+pointer hcolumn # pointer to the name of the histogram column
+pointer photcolumns # pointer to the photometry columns
+pointer usercolumns # pointer to the user columns
+pointer graphics # pointer to the name of the graphics device
+pointer image # pointer to the name of the input image
+pointer reject # pointer to the name of the deletions catalog
+real match_radius # the matching radius
+
+int numrows, max_nstars, first_star, status
+int apd, apout, aprej, use_display
+pointer sp, key, px, gd, im, deleted
+
+bool clgetb()
+int fstati(), access(), clgeti(), pt_getphot(), pt_plot(), open(), btoi()
+pointer gopen(), tbtopn(), pt_init(), immap()
+real clgetr()
+
+begin
+ # Flush on a newline if the standard output is not redirected.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get some working memory.
+ call smark (sp)
+ call salloc (input, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (reject, SZ_FNAME, TY_CHAR)
+ call salloc (photcolumns, PX_SZCOLNAME * (PX_MAXNCOLS + 1), TY_CHAR)
+ call salloc (xcolumn, PX_SZCOLNAME, TY_CHAR)
+ call salloc (ycolumn, PX_SZCOLNAME, TY_CHAR)
+ call salloc (hcolumn, PX_SZCOLNAME, TY_CHAR)
+ call salloc (xposcolumn, PX_SZCOLNAME, TY_CHAR)
+ call salloc (yposcolumn, PX_SZCOLNAME, TY_CHAR)
+ call salloc (usercolumns, PX_SZCOLNAME * (PX_MAXNCOLS + 1), TY_CHAR)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+
+ # Fetch the input and output file parameters and the column
+ # definition parameters.
+ call clgstr ("input", Memc[input], SZ_FNAME)
+ call clgstr ("output", Memc[output], SZ_FNAME)
+ call clgstr ("image", Memc[image], SZ_FNAME)
+ call clgstr ("deletions", Memc[reject], SZ_FNAME)
+ call clgstr ("photcolumns", Memc[photcolumns], PX_SZCOLNAME *
+ (PX_MAXNCOLS + 1))
+ call clgstr ("xcolumn", Memc[xcolumn], PX_SZCOLNAME)
+ call clgstr ("ycolumn", Memc[ycolumn], PX_SZCOLNAME)
+ call clgstr ("hcolumn", Memc[hcolumn], PX_SZCOLNAME)
+ call clgstr ("xposcolumn", Memc[xposcolumn], PX_SZCOLNAME)
+ call clgstr ("yposcolumn", Memc[yposcolumn], PX_SZCOLNAME)
+ call clgstr ("usercolumns", Memc[usercolumns], PX_SZCOLNAME *
+ (PX_MAXNCOLS + 1))
+
+ match_radius = clgetr ("match_radius")
+ max_nstars = clgeti ("max_nstars")
+ first_star = clgeti ("first_star")
+
+ # Get the graphics and display parameters.
+ call clgstr ("icommands.p_filename", Memc[graphics], SZ_FNAME)
+ if (Memc[graphics] != EOS)
+ use_display = YES
+ else
+ use_display = btoi (clgetb ("use_display"))
+ call clgstr ("graphics", Memc[graphics], SZ_FNAME)
+
+ # Initialize the pexamine struture.
+ px = pt_init (Memc[photcolumns], Memc[usercolumns], Memc[xcolumn],
+ Memc[ycolumn], Memc[xposcolumn], Memc[yposcolumn], Memc[hcolumn])
+
+ # Open the input catalog.
+ if (access (Memc[input], 0, TEXT_FILE) == YES) {
+ apd = open (Memc[input], READ_ONLY, TEXT_FILE)
+ call pt_kyinit (key)
+ } else {
+ apd = tbtopn (Memc[input], READ_ONLY, 0)
+ key = NULL
+ }
+
+ # Open the input image.
+ if (Memc[image] == EOS)
+ im = NULL
+ else
+ im = immap (Memc[image], READ_ONLY, 0)
+
+ # Allocate buffer space.
+ iferr {
+ numrows = min (max_nstars, pt_getphot (px, apd, key, max_nstars,
+ first_star))
+ call malloc (deleted, numrows, TY_INT)
+ } then
+ call erract (EA_FATAL)
+
+ # Plot the data and enter the interactive cursor loop.
+ gd = gopen (Memc[graphics], NEW_FILE, STDGRAPH)
+ status = pt_plot (gd, px, apd, key, im, Memi[deleted], numrows,
+ max_nstars, first_star, match_radius, use_display)
+ call gclose (gd)
+
+ if (status == PX_EXIT) {
+
+ # Open the output file.
+ if (Memc[output] != EOS) {
+ if (access (Memc[output], 0, 0) == YES) {
+ call printf ("The catalog %s already exists\n")
+ call pargstr (Memc[output])
+ call mktemp ("out", Memc[output], SZ_FNAME)
+ call printf ("The new output catalog is %s\n")
+ call pargstr (Memc[output])
+ }
+ if (key == NULL)
+ apout = tbtopn (Memc[output], NEW_COPY, apd)
+ else
+ apout = open (Memc[output], NEW_FILE, TEXT_FILE)
+ } else
+ apout = NULL
+
+ # Open a reject points catalog if required.
+ if (Memc[reject] != EOS) {
+ if (access (Memc[reject], 0, 0) == YES) {
+ call printf ("The catalog %s already exists.\n")
+ call pargstr (Memc[reject])
+ call mktemp ("rej", Memc[reject], SZ_FNAME)
+ call printf ("The new rejections catalog is %s\n")
+ call pargstr (Memc[reject])
+ }
+ if (key == NULL)
+ aprej = tbtopn (Memc[reject], NEW_COPY, apd)
+ else
+ aprej = open (Memc[reject], NEW_FILE, TEXT_FILE)
+ } else
+ aprej = NULL
+
+ # Write the output catalog file.
+ call pt_wtfile (apd, key, apout, aprej, Memi[deleted], numrows)
+
+ # Close the output file.
+ if (apout != NULL) {
+ if (key == NULL)
+ call tbtclo (apout)
+ else
+ call close (apout)
+ }
+
+ # Close the rejected points file.
+ if (aprej != NULL) {
+ if (key == NULL)
+ call tbtclo (aprej)
+ else
+ call close (aprej)
+ }
+
+ } else if (status == ERR)
+ call fseti (STDOUT, F_CANCEL, OK)
+
+ # Close the input file.
+ if (key != NULL) {
+ call pt_kyfree (key)
+ call close (apd)
+ } else if (apd != NULL)
+ call tbtclo (apd)
+
+ # Close the image.
+ if (im != NULL)
+ call imunmap(im)
+
+ # Return the buffer space.
+ call mfree (deleted, TY_INT)
+
+ # Free the program structures.
+ call pt_free (px)
+ call sfree (sp)
+ if (status == ERR)
+ call erract (EA_ERROR)
+end
diff --git a/noao/digiphot/ptools/prenumber.cl b/noao/digiphot/ptools/prenumber.cl
new file mode 100644
index 00000000..2a174275
--- /dev/null
+++ b/noao/digiphot/ptools/prenumber.cl
@@ -0,0 +1,50 @@
+# PRENUMBER - Renumber the ID column of an APPHOT/DAOPHOT database from 1 to
+# N where N is the number of objects in the database. The renumbering is
+# done in place.
+
+procedure prenumber (infile)
+
+string infile {prompt="Input apphot/daophot databases(s) to be renumbered"}
+int idoffset {0, min=0, prompt="Id number offset"}
+string id {"ID", prompt="Id name keyword"}
+
+struct *inlist
+
+begin
+ # Local variable declarations.
+ file tmpin
+ string in, inname, expr
+
+ # Cache the istable parameters.
+ cache ("istable")
+
+ # Get the positional parameters.
+ in = infile
+ expr = "rownum + " // idoffset
+
+ # Expand the file list names.
+ tmpin = mktemp ("tmp$")
+ files (in, sort=no, > tmpin)
+
+ # Loop over each file in the input and output lists selecting records.
+ inlist = tmpin
+ while (fscan (inlist, inname) != EOF) {
+ istable (inname)
+ if (istable.table) {
+ if (defpar ("tcalc.verbose") || defpar ("tcalc.harmless")) {
+ tcalc (inname, id, expr, datatype="real", colunits="",
+ colfmt="", verbose=no, harmless=0.1)
+ } else {
+ tcalc (inname, id, expr, datatype="real", colunits="",
+ colfmt="")
+ }
+ } else if (istable.text) {
+ txrenumber (inname, idoffset=idoffset, id=id)
+ } else {
+ print ("Cannot run PRENUMBER on file: " // inname)
+ }
+ }
+ inlist = ""
+
+ delete (tmpin, ver-, >& "dev$null")
+end
diff --git a/noao/digiphot/ptools/pselect.cl b/noao/digiphot/ptools/pselect.cl
new file mode 100644
index 00000000..86ebb9bf
--- /dev/null
+++ b/noao/digiphot/ptools/pselect.cl
@@ -0,0 +1,77 @@
+# PSELECT - Select records from an ST table of an APPHOT/DAOPHOT text file
+# based on the value of a boolean expression.
+
+procedure pselect (infiles, outfiles, expr)
+
+string infiles {prompt="Input apphot/daophot database(s)"}
+string outfiles {prompt="Output apphot/daophot database(s)"}
+string expr {prompt="Boolean expression for record selection"}
+
+struct *inlist, *outlist
+
+begin
+ # Local variable declarations.
+ file tmpin, tmpout
+ int nin, nout
+ string in, out, ex, inname, outname
+
+ # Cache the istable parameters.
+ cache ("istable")
+
+ # Get the positional parameters.
+ in = infiles
+ out = outfiles
+ ex = expr
+
+ # Make temporary names.
+ tmpin = mktemp ("tmp$")
+ tmpout = mktemp ("tmp$")
+
+ # Expand the file list names.
+ files (in, sort=no, > tmpin)
+ files (out, sort=no, > tmpout)
+
+ # Compute the lengths of the input and output lists.
+ inlist = tmpin
+ for (nin = 0; fscan (inlist, inname) != EOF; nin = nin + 1)
+ ;
+ inlist = ""
+ outlist = tmpout
+ for (nout = 0; fscan (outlist, outname) != EOF; nout = nout + 1)
+ ;
+ outlist = ""
+
+ # Delete the temporary files.
+ delete (tmpin, ver-, >& "dev$null")
+ delete (tmpout, ver-, >& "dev$null")
+
+ # Quit if the number of input and output files is different.
+ if (nin != nout) {
+ print ("ERROR: Input and output file lists are different lengths")
+ return
+ }
+
+ # Expand the file list names.
+ files (in, sort=no, > tmpin)
+ files (out, sort=no, > tmpout)
+
+ # Loop over each file in the input and output lists selecting records.
+ inlist = tmpin
+ outlist = tmpout
+ while (fscan (inlist, inname) != EOF && fscan (outlist, outname) !=
+ EOF) {
+ istable (inname)
+ if (istable.table) {
+ tselect (inname, outname, ex)
+ } else if (istable.text) {
+ txselect (inname, outname, ex)
+ } else {
+ print ("ERROR: Cannot run PSELECT on file: " // inname)
+ }
+ }
+
+ delete (tmpin, ver-, >& "dev$null")
+ delete (tmpout, ver-, >& "dev$null")
+ inlist = ""
+ outlist = ""
+end
diff --git a/noao/digiphot/ptools/psort.cl b/noao/digiphot/ptools/psort.cl
new file mode 100644
index 00000000..d99d55c6
--- /dev/null
+++ b/noao/digiphot/ptools/psort.cl
@@ -0,0 +1,42 @@
+# PSORT - Sort an ST or APPHOT/DAOPHOT file based on a single column.
+
+procedure psort (infiles, field)
+
+string infiles {prompt="Input Apphot/daophot database(s) to be sorted"}
+string field {prompt="Field to be sorted on"}
+bool ascend {yes, prompt="Sort in increasing value order?"}
+
+struct *inlist
+
+begin
+ # Local variable declarations.
+ file tmpin
+ string in, col, inname
+
+ # Cache the istable parameters.
+ cache ("istable")
+
+ # Get the positional parameters.
+ in = infiles
+ col = field
+
+ # Expand the file list names.
+ tmpin = mktemp ("tmp$")
+ files (in, sort=no, > tmpin)
+
+ # Loop over each file in the input and output lists selecting records.
+ inlist = tmpin
+ while (fscan (inlist, inname) != EOF) {
+ istable (inname)
+ if (istable.table) {
+ tsort (inname, col, ascend=ascend, casesens=yes)
+ } else if (istable.text) {
+ txsort (inname, col, ascend=ascend)
+ } else {
+ print ("Cannot run PSORT on file: " // inname)
+ }
+ }
+ inlist = ""
+
+ delete (tmpin, ver-, >& "dev$null")
+end
diff --git a/noao/digiphot/ptools/ptools.cl b/noao/digiphot/ptools/ptools.cl
new file mode 100644
index 00000000..72cacab5
--- /dev/null
+++ b/noao/digiphot/ptools/ptools.cl
@@ -0,0 +1,50 @@
+# Package script task for the PTOOLSX package.
+#{ PTOOLSX -- Photometry tools package.
+
+
+package ptools
+
+# Define the ptools executable tasks.
+
+task pconvert,
+ istable,
+ pexamine,
+ tbcrename,
+ tbkeycol,
+ txconcat,
+ txcalc,
+ txdump,
+ txrenumber,
+ txselect,
+ txsort = "ptools$x_ptools.e"
+
+# Define the tasks which are CL scripts.
+
+task tbconcat = "ptools$tbconcat.cl"
+task tbdump = "ptools$tbdump.cl"
+task tbcalc = "ptools$tbcalc.cl"
+task tbrenumber = "ptools$tbrenumber.cl"
+task tbselect = "ptools$tbselect.cl"
+task tbsort = "ptools$tbsort.cl"
+
+task pconcat = "ptools$pconcat.cl"
+task pcalc = "ptools$pcalc.cl"
+task pdump = "ptools$pdump.cl"
+task prenumber = "ptools$prenumber.cl"
+task pselect = "ptools$pselect.cl"
+task psort = "ptools$psort.cl"
+
+task pttest = "ptools$pttest.cl"
+
+# Pset tasks.
+
+task xyplot = "ptools$xyplot.par"
+task histplot = "ptools$histplot.par"
+task radplot = "ptools$radplot.par"
+task surfplot = "ptools$surfplot.par"
+task cntrplot = "ptools$cntrplot.par"
+
+hidetask tbkeycol, tbcrename
+hidetask xyplot, histplot, radplot, surfplot, cntrplot
+
+clbye()
diff --git a/noao/digiphot/ptools/ptools.hd b/noao/digiphot/ptools/ptools.hd
new file mode 100644
index 00000000..344197a7
--- /dev/null
+++ b/noao/digiphot/ptools/ptools.hd
@@ -0,0 +1,34 @@
+# Help directory for the PTOOLS package
+
+$doc = "./doc/"
+
+$pconvert = "ptools$pconvert/"
+$ptutils = "ptools$ptutils/"
+$pexamine = "ptools$pexamine/"
+$txtools = "ptools$txtools/"
+
+pcalc hlp=doc$pcalc.hlp, src=ptools$pcalc.cl
+pconcat hlp=doc$pconcat.hlp, src=ptools$pconcat.cl
+pconvert hlp=doc$pconvert.hlp, src=pconvert$t_pconvert.x
+pdump hlp=doc$pdump.hlp, src=ptools$pdump.cl
+istable hlp=doc$istable.hlp, src=ptutils$t_istable.x
+prenumber hlp=doc$prenumber.hlp, src=ptools$prenumber.cl
+pexamine hlp=doc$pexamine.hlp, src=pexamine$t_pexamine.x
+pttest hlp=doc$pttest.hlp, src=ptools$pttest.cl
+pselect hlp=doc$pselect.hlp, src=ptools$pselect.cl
+psort hlp=doc$psort.hlp, src=ptools$psort.cl
+tbcalc hlp=doc$tbcalc.hlp, src=ptools$tbcalc.cl
+tbconcat hlp=doc$tbconcat.hlp, src=ptools$tbconcat.cl
+tbcrename hlp=doc$tbcrename.hlp, src=ptutils$t_tbcrename.x
+tbdump hlp=doc$tbdump.hlp, src=ptools$t_tbdump.cl
+tbkeycol hlp=doc$tbkeycol.hlp, src=ptutils$t_tbkeycol.x
+tbrenumber hlp=doc$tbrenumber.hlp, src=ptools$tbrenumber.cl
+tbselect hlp=doc$tbselect.hlp, src=ptools$tbselect.cl
+tbsort hlp=doc$tbsort.hlp, src=ptools$tbsort.cl
+txconcat hlp=doc$txconcat.hlp, src=txtools$t_txconcat.x
+txcalc hlp=doc$txcalc.hlp, src=txtools$t_txcalc.x
+txdump hlp=doc$txdump.hlp, src=txtools$t_txdump.x
+txrenumber hlp=doc$txrenumber.hlp, src=txtools$t_txrenumber.x
+txselect hlp=doc$txselect.hlp, src=txtools$t_txselect.x
+txsort hlp=doc$txsort.hlp, src=txtools$t_txsort.x
+revisions sys=ptoolsx$Revisions
diff --git a/noao/digiphot/ptools/ptools.men b/noao/digiphot/ptools/ptools.men
new file mode 100644
index 00000000..2e13df00
--- /dev/null
+++ b/noao/digiphot/ptools/ptools.men
@@ -0,0 +1,24 @@
+ istable - Is a file a table or text database file ?
+ pconcat - Concatenate a list of apphot/daophot databases
+ pconvert - Convert from an apphot/daophot text to tables database
+ pcalc - Do arithmetic on a list of apphot/daophot tables databases
+ pdump - Print selected columns of a list of daophot/apphot databases
+ prenumber - Renumber a list of apphot/daophot databases
+ pexamine - Interactively examine and edit an apphot/daophot database
+ pselect - Select records from a list of apphot/daophot databases
+ psort - Sort a list of apphot/daophot databases
+ pttest - Run basic tests on the ptoolsx package tasks
+
+ tbconcat - Concatenate a list of apphot/daophot tables databases
+ tbcalc - Do arithmetic on a list of apphot/daophot tables databases
+ tbdump - Print selected columns of a list of tables databases
+ tbrenumber - Renumber a list of apphot/daophot tables databases
+ tbselect - Select records from a list of apphot/daophot tables databases
+ tbsort - Sort a list of apphot/daophot tables databases
+
+ txconcat - Concatenate a list of apphot/daophot text databases
+ txcalc - Do arithmetic on a list of apphot/daophot text databases
+ txdump - Print selected columns of a list of apphot/daophot text databases
+ txrenumber - Renumber a list of apphot/daophot text databases
+ txselect - Select records from a list of apphot/daophot text databases
+ txsort - Sort a list of apphot/daophot text databases
diff --git a/noao/digiphot/ptools/ptools.par b/noao/digiphot/ptools/ptools.par
new file mode 100644
index 00000000..cf641f88
--- /dev/null
+++ b/noao/digiphot/ptools/ptools.par
@@ -0,0 +1,3 @@
+# PTOOLSX package parameter file
+
+version,s,h,"Aug91"
diff --git a/noao/digiphot/ptools/pttest.cl b/noao/digiphot/ptools/pttest.cl
new file mode 100644
index 00000000..a601a17e
--- /dev/null
+++ b/noao/digiphot/ptools/pttest.cl
@@ -0,0 +1,550 @@
+# PTTEST - Self testing procedure for the PTOOLS package.
+
+procedure pttest (rootname)
+
+string rootname {prompt="Root name of the output test files"}
+string ptlogfile {"", prompt="Name of the output log file"}
+string ptplotfile {"", prompt="Name of the output plot file"}
+
+begin
+ # Declare local variables.
+ string root, txtfile1, txtfile2, tblfile1, ptlog, ptplot
+
+ # Check that the user truly wants to proceed.
+ s1 = ""
+ print ("")
+ print ("PTTEST INITIALIZES THE PTOOLS TASK PARAMETERS")
+ print ("TYPE 'q' or 'Q' TO QUIT, ANY OTHER KEY TO PROCEED")
+ if (scan (s1) != EOF) {
+ if (s1 == "q" || s1 == "Q") {
+ print ("TERMINATING THE PTTEST TASK")
+ bye
+ }
+ }
+ print ("")
+
+ # Define the image name and the log and plot file names.
+ root = rootname
+ ptlog = ptlogfile
+ if (ptlog == "") {
+ ptlog = root // ".log"
+ }
+ ptplot = ptplotfile
+ if (ptplot == "") {
+ ptplot = root // ".plot"
+ }
+
+ # Read in the FITS file and check for the existance of the log and
+ # plot files.
+
+ txtfile1 = root // ".txt.1"
+ if (! access (txtfile1)) {
+ copy ("ptools$test/test1.dat", txtfile1, verbose-)
+ } else {
+ error (0, "Error: The first test text file already exists on disk")
+ }
+ txtfile2 = root // ".txt.2"
+ if (! access (txtfile2)) {
+ copy ("ptools$test/test2.dat", txtfile2, verbose-)
+ } else {
+ error (0, "Error: The second test text file already exists on disk")
+ }
+ tblfile1 = root // ".tbl.1"
+ if (! access (tblfile1)) {
+ ;
+ } else {
+ error (0, "Error: The test tables file already exists on disk")
+ }
+ if (access (ptlog)) {
+ error (0, "Error: The log file already exists on disk")
+ }
+ if (access (ptplot)) {
+ error (0, "Error: The plot file already exists on disk")
+ }
+
+ # Initialize the PTOOLS package.
+
+ print ("INITIALIZE THE PTOOLS PACKAGE", >> ptlog)
+ print ("", >> ptlog)
+ print ("")
+ print ("INITIALIZE THE PTOOLS PACKAGE")
+ print ("")
+
+ unlearn ("txconcat")
+ unlearn ("txdump")
+ unlearn ("txrenumber")
+ unlearn ("txselect")
+ unlearn ("txsort")
+ unlearn ("pconvert")
+
+ unlearn ("tbconcat")
+ unlearn ("tbdump")
+ unlearn ("tbrenumber")
+ unlearn ("tbselect")
+ unlearn ("tbsort")
+ unlearn ("tbkeycol")
+ unlearn ("tbcrename")
+
+ unlearn ("pconcat")
+ unlearn ("pdump")
+ unlearn ("prenumber")
+ unlearn ("pselect")
+ unlearn ("psort")
+ unlearn ("pexamine")
+ unlearn ("xyplot")
+ unlearn ("histplot")
+ unlearn ("radplot")
+ unlearn ("surfplot")
+ unlearn ("cntrplot")
+ unlearn ("istable")
+
+ # Copy the first test file to the log file.
+
+ print ("COPY THE FIRST TEST FILE TO THE LOG FILE", >> ptlog)
+ print ("COPY THE FIRST TEST FILE TO THE LOG FILE")
+ print ("", >> ptlog)
+
+ concatenate (txtfile1, ptlog, append=yes)
+
+ # Testing the TXCONCAT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE TXCONCAT TASK (FIRST TEXT FILE)", >> ptlog)
+ print (" APPENDING THE FIRST TEXT FILE TO ITSELF", >> ptlog)
+ print ("TESTING THE TXCONCAT TASK (FIRST TEXT FILE)")
+ print ("", >> ptlog)
+
+ txconcat (txtfile1 // "," // txtfile1, root // ".app.1", task="TASK")
+ concatenate (root // ".app.1", ptlog, append=yes)
+ delete (root // ".app.1", ver-, >& "dev$null")
+
+ # Testing the PCONCAT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE PCONCAT TASK (FIRST TEXT FILE)", >> ptlog)
+ print (" APPENDING THE FIRST TEXT FILE TO ITSELF", >> ptlog)
+ print ("TESTING THE PCONCAT TASK (FIRST TEXT FILE)")
+ print ("", >> ptlog)
+
+ pconcat (txtfile1 // "," // txtfile1, root // ".app.1", task="TASK")
+ concatenate (root // ".app.1", ptlog, append=yes)
+ delete (root // ".app.1", ver-, >& "dev$null")
+
+ # Testing the TXDUMP task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE TXDUMP TASK (FIRST TEXT FILE)", >> ptlog)
+ print ("DUMPING FIELDS ID, XCENTER, YCENTER, MSKY AND MAG[1]",
+ >> ptlog)
+ print ("TESTING THE TXDUMP TASK (FIRST TEXT FILE)")
+ print ("", >> ptlog)
+
+ txdump (txtfile1, "id,xcenter,ycenter,msky,mag[1]", "yes", headers-,
+ parameters+, >> ptlog)
+
+ # Testing the PDUMP task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE PDUMP TASK (FIRST TEXT FILE)", >> ptlog)
+ print ("DUMPING FIELDS ID, XCENTER, YCENTER, MSKY AND MAG[1]",
+ >> ptlog)
+ print ("TESTING THE PDUMP TASK (FIRST TEXT FILE)")
+ print ("", >> ptlog)
+
+ pdump (txtfile1, "id,xcenter,ycenter,msky,mag[1]", yes, headers-,
+ parameters+, >> ptlog)
+
+ # Testing the TXSELECT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE TXSELECT TASK (FIRST TEXT FILE)", >> ptlog)
+ print ("SELECTING RECORDS WITH MAG[1] <= 18.0", >> ptlog)
+ print ("TESTING THE TXSELECT TASK (FIRST TEXT FILE)")
+ print ("", >> ptlog)
+
+ txselect (txtfile1, root // ".sel.1", "mag[1] <= 18.0")
+ concatenate (root // ".sel.1", ptlog, append=yes)
+ delete (root // ".sel.1", ver-, >& "dev$null")
+
+ # Testing the PSELECT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE PSELECT TASK (FIRST TEXT FILE)", >> ptlog)
+ print ("SELECTING RECORDS WITH MAG[1] <= 18.0", >> ptlog)
+ print ("TESTING THE PSELECT TASK (FIRST TEXT FILE)")
+ print ("", >> ptlog)
+
+ pselect (txtfile1, root // ".sel.1", "mag[1] <= 18.0")
+ concatenate (root // ".sel.1", ptlog, append=yes)
+ delete (root // ".sel.1", ver-, >& "dev$null")
+
+ # Testing the TXSORT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE TXSORT TASK (FIRST TEXT FILE)", >> ptlog)
+ print ("SORTING ON COLUMN MAG[1]", >> ptlog)
+ print ("TESTING THE TXSORT TASK (FIRST TEXT FILE)")
+ print ("", >> ptlog)
+
+ copy (txtfile1, root // ".srt.1", verbose-)
+ txsort (root // ".srt.1", "MAG[1]", ascend+)
+ concatenate (root // ".srt.1", ptlog, append=yes)
+
+ # Testing the PSORT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE PSORT TASK (FIRST TEXT FILE)", >> ptlog)
+ print ("SORTING ON COLUMN MAG[1]", >> ptlog)
+ print ("TESTING THE PSORT TASK (FIRST TEXT FILE)")
+ print ("", >> ptlog)
+
+ copy (txtfile1, root // ".srt.2", verbose-)
+ psort (root // ".srt.2", "MAG[1]", ascend+)
+ concatenate (root // ".srt.1", ptlog, append=yes)
+
+ # Testing the TXRENUMBER task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE TXRENUMBER TASK (FIRST TEXT FILE)", >> ptlog)
+ print ("RENUMBERING ON COLUMN ID", >> ptlog)
+ print ("TESTING THE TXRENUMBER TASK (FIRST TEXT FILE)")
+ print ("", >> ptlog)
+
+ txrenumber (root // ".srt.1", idoffset=0, id="ID")
+ concatenate (root // ".srt.1", ptlog, append=yes)
+
+ # Testing the PRENUMBER task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE PRENUMBER TASK (FIRST TEXT FILE)", >> ptlog)
+ print ("RENUMBERING ON COLUMN ID", >> ptlog)
+ print ("TESTING THE PRENUMBER TASK (FIRST TEXT FILE)")
+ print ("", >> ptlog)
+
+ prenumber (root // ".srt.2", idoffset=0, id="ID")
+ concatenate (root // ".srt.2", ptlog, append=yes)
+
+ delete (root // ".srt.1", ver-, >& "dev$null")
+ delete (root // ".srt.2", ver-, >& "dev$null")
+
+ # Copy the second test file to the log file.
+
+ print ("")
+ print ("", >> ptlog)
+ print ("COPY THE SECOND TEST FILE TO THE LOG FILE", >> ptlog)
+ print ("COPY THE SECOND TEST FILE TO THE LOG FILE")
+ print ("", >> ptlog)
+
+ concatenate (txtfile2, ptlog, append=yes)
+
+ # Testing the TXDUMP task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE TXDUMP TASK (SECOND TEXT FILE)", >> ptlog)
+ print ("DUMPING FIELDS ID, XCENTER, YCENTER, MSKY AND MAG[1]",
+ >> ptlog)
+ print ("TESTING THE TXDUMP TASK (SECOND TEXT FILE)")
+ print ("", >> ptlog)
+
+ txdump (txtfile2, "id,xcenter,ycenter,msky,mag[1]", "yes", headers-,
+ parameters+, >> ptlog)
+
+ # Testing the PDUMP task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE PDUMP TASK (SECOND TEXT FILE)", >> ptlog)
+ print ("DUMPING FIELDS ID, XCENTER, YCENTER, MSKY AND MAG[1]",
+ >> ptlog)
+ print ("TESTING THE PDUMP TASK (SECOND TEXT FILE)")
+ print ("", >> ptlog)
+
+ pdump (txtfile2, "id,xcenter,ycenter,msky,mag[1]", yes, headers-,
+ parameters+, >> ptlog)
+
+ # Testing the TXSELECT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE TXSELECT TASK (SECOND TEXT FILE)", >> ptlog)
+ print ("SELECTING RECORDS WITH MAG[1] >= 11.5", >> ptlog)
+ print ("TESTING THE TXSELECT TASK (SECOND TEXT FILE)")
+ print ("", >> ptlog)
+
+ txselect (txtfile2, root // ".sel.1", "mag[1] >= 11.5")
+ concatenate (root // ".sel.1", ptlog, append=yes)
+ delete (root // ".sel.1", ver-, >& "dev$null")
+
+ # Testing the PSELECT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE PSELECT TASK (SECOND TEXT FILE)", >> ptlog)
+ print ("SELECTING RECORDS WITH MAG[1] >= 11.5", >> ptlog)
+ print ("TESTING THE PSELECT TASK (SECOND TEXT FILE)")
+ print ("", >> ptlog)
+
+ pselect (txtfile2, root // ".sel.1", "mag[1] >= 11.5")
+ concatenate (root // ".sel.1", ptlog, append=yes)
+ delete (root // ".sel.1", ver-, >& "dev$null")
+
+ # Testing the TXSORT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE TXSORT TASK (SECOND TEXT FILE)", >> ptlog)
+ print ("SORTING ON COLUMN MAG[1]", >> ptlog)
+ print ("TESTING THE TXSORT TASK (SECOND TEXT FILE)")
+ print ("", >> ptlog)
+
+ copy (txtfile2, root // ".srt.1", verbose-)
+ txsort (root // ".srt.1", "MAG[1]", ascend+)
+ concatenate (root // ".srt.1", ptlog, append=yes)
+
+ # Testing the PSORT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE PSORT TASK (SECOND TEXT FILE)", >> ptlog)
+ print ("SORTING ON COLUMN MAG[1]", >> ptlog)
+ print ("TESTING THE PSORT TASK (SECOND TEXT FILE)")
+ print ("", >> ptlog)
+
+ copy (txtfile2, root // ".srt.2", verbose-)
+ psort (root // ".srt.2", "MAG[1]", ascend+)
+ concatenate (root // ".srt.1", ptlog, append=yes)
+
+ # Testing the TXRENUMBER task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE TXRENUMBER TASK (SECOND TEXT FILE)", >> ptlog)
+ print ("RENUMBERING ON COLUMN ID", >> ptlog)
+ print ("TESTING THE TXRENUMBER TASK (SECOND TEXT FILE)")
+ print ("", >> ptlog)
+
+ txrenumber (root // ".srt.1", id="ID")
+ concatenate (root // ".srt.1", ptlog, append=yes)
+
+ # Testing the PRENUMBER task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE PRENUMBER TASK (SECOND TEXT FILE)", >> ptlog)
+ print ("RENUMBERING ON COLUMN ID", >> ptlog)
+ print ("TESTING THE PRENUMBER TASK (SECOND TEXT FILE)")
+ print ("", >> ptlog)
+
+ prenumber (root // ".srt.2", id="ID")
+ concatenate (root // ".srt.2", ptlog, append=yes)
+
+ delete (root // ".srt.1", ver-, >& "dev$null")
+ delete (root // ".srt.2", ver-, >& "dev$null")
+
+ # Testing the PCONVERT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE PCONVERT TASK (FIRST TEXT FILE)", >> ptlog)
+ print ("CREATING TABLE FILE BY CONVERTING ALL COLUMNS", >> ptlog)
+ print ("")
+ print ("TESTING THE PCONVERT TASK (FIRST TEXT FILE)")
+ print ("", >> ptlog)
+
+ pconvert (txtfile1, tblfile1, "*", expr+, append-)
+
+ # Check to see if the tables package is loaded.
+
+ if (! defpac ("nttools")) {
+
+ print ("THE NTTOOLS PACKAGE IS NOT LOADED: TERMINATING PTTEST")
+
+ } else {
+
+ # Testing the TBCONCAT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE TBCONCAT/TBDUMP TASKS", >> ptlog)
+ print ("APPENDING TABLE FILE TO ITSELF", >> ptlog)
+ print ("DUMPING COLUMNS ID, XCENTER, YCENTER, MKSKY, and MAG[1]",
+ >> ptlog)
+ print ("TESTING THE TBCONCAT/TBDUMP TASKS")
+ print ("", >> ptlog)
+
+ tbconcat (tblfile1 // "," // tblfile1, root // ".app.1",
+ task="TASK")
+ tbdump (root // ".app.1", "ID,XCENTER,YCENTER,MSKY,MAG\[1]",
+ "yes", datafile="STDOUT", cdfile="", pfile="", rows="-",
+ pagwidth=158, >> ptlog)
+ delete (root // ".app.1", ver-, >& "dev$null")
+
+ # Testing the PCONCAT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE PCONCAT/PDUMP TASKS", >> ptlog)
+ print ("APPENDING TABLE FILE TO ITSELF", >> ptlog)
+ print ("DUMPING COLUMNS ID, XCENTER, YCENTER, MKSKY, and MAG[1]",
+ >> ptlog)
+ print ("TESTING THE PCONCAT/PDUMP TASKS")
+ print ("", >> ptlog)
+
+ pconcat (tblfile1 // "," // tblfile1, root // ".app.1",
+ task="TASK")
+ pdump (root // ".app.1", "ID,XCENTER,YCENTER,MSKY,MAG\[1]",
+ yes, headers-, parameters+, >> ptlog)
+ delete (root // ".app.1", ver-, >& "dev$null")
+
+ # Testing the TBSELECT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE TBSELECT/TBDUMP TASKS", >> ptlog)
+ print ("SELECTING RECORDS WITH MAG[1] <= 18.0", >> ptlog)
+ print ("DUMPING COLUMNS ID, XCENTER, YCENTER, MKSKY, and MAG[1]",
+ >> ptlog)
+ print ("TESTING THE TBSELECT/TBDUMP TASKS")
+ print ("", >> ptlog)
+
+ tbselect (tblfile1, root // ".sel.1", "mag[1] <= 18.0")
+ tbdump (root // ".sel.1", "ID,XCENTER,YCENTER,MSKY,MAG\[1]",
+ "yes", datafile="STDOUT", cdfile="", pfile="", rows="-",
+ pagwidth=158, >> ptlog)
+ delete (root // ".sel.1", ver-, >& "dev$null")
+
+ # Testing the PSELECT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE PSELECT/PDUMP TASKS", >> ptlog)
+ print ("SELECTING RECORDS WITH MAG[1] <= 18.0", >> ptlog)
+ print ("DUMPING COLUMNS ID, XCENTER, YCENTER, MKSKY, and MAG[1]",
+ >> ptlog)
+ print ("TESTING THE PSELECT/PDUMP TASKS")
+ print ("", >> ptlog)
+
+ pselect (tblfile1, root // ".sel.1", "mag[1] <= 18.0")
+ pdump (root // ".sel.1", "ID,XCENTER,YCENTER,MSKY,MAG\[1]",
+ yes, headers-, parameters+, >> ptlog)
+ delete (root // ".sel.1", ver-, >& "dev$null")
+
+ # Testing the TBSORT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE TBSORT/TBDUMP TASKS", >> ptlog)
+ print ("SORTING ON COLUMN MAG[1]", >> ptlog)
+ print ("DUMPING COLUMNS ID, XCENTER, YCENTER, MKSKY, and MAG[1]",
+ >> ptlog)
+ print ("TESTING THE TBSORT/TBDUMP TASKS")
+ print ("", >> ptlog)
+
+ copy (tblfile1, root // ".srt.1", verbose-)
+ tbsort (root // ".srt.1", "MAG\[1]", ascend+, casesens+)
+ tbdump (root // ".srt.1", "ID,XCENTER,YCENTER,MSKY,MAG\[1]",
+ "yes", datafile="STDOUT", cdfile="", pfile="", rows="-",
+ pagwidth=158, >> ptlog)
+
+ # Testing the PSORT task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE PSORT/PDUMP TASKS", >> ptlog)
+ print ("SORTING ON COLUMN MAG[1]", >> ptlog)
+ print ("DUMPING COLUMNS ID, XCENTER, YCENTER, MKSKY, and MAG[1]",
+ >> ptlog)
+ print ("TESTING THE PSORT/PDUMP TASK")
+ print ("", >> ptlog)
+
+ copy (tblfile1, root // ".srt.2", verbose-)
+ psort (root // ".srt.2", "MAG\[1]", ascend+)
+ pdump (root // ".srt.2", "ID,XCENTER,YCENTER,MSKY,MAG\[1]",
+ yes, headers-, parameters+, >> ptlog)
+
+ # Testing the TBRENUMBER task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE TBRENUMBER/TBDUMP TASKS", >> ptlog)
+ print ("RENUMBERING ON COLUMN ID", >> ptlog)
+ print ("DUMPING COLUMNS ID, XCENTER, YCENTER, MKSKY, and MAG[1]",
+ >> ptlog)
+ print ("TESTING THE TBRENUMBER/PDUMP TASKS")
+ print ("", >> ptlog)
+
+ tbrenumber (root // ".srt.1", idoffset=0, id="ID")
+ tbdump (root // ".srt.1", "ID,XCENTER,YCENTER,MSKY,MAG\[1]",
+ "yes", datafile="STDOUT", cdfile="", pfile="", rows="-",
+ pagwidth=158, >> ptlog)
+
+ # Testing the PRENUMBER task.
+
+ print ("", >> ptlog)
+ print ("TESTING THE PRENUMBER/PDUMP TASKS", >> ptlog)
+ print ("RENUMBERING ON COLUMN ID", >> ptlog)
+ print ("DUMPING COLUMNS ID, XCENTER, YCENTER, MKSKY, and MAG[1]",
+ >> ptlog)
+ print ("TESTING THE PRENUMBER/PDUMP TASKS")
+ print ("", >> ptlog)
+
+ prenumber (root // ".srt.2", id="ID")
+ pdump (root // ".srt.2", "ID,XCENTER,YCENTER,MSKY,MAG\[1]",
+ yes, headers-, parameters+, >> ptlog)
+
+ delete (root // ".srt.1", ver-, >& "dev$null")
+ delete (root // ".srt.2", ver-, >& "dev$null")
+ }
+
+ # Testing the PEXAMINE task.
+
+ xyplot.x1=16.0
+ xyplot.x2=20.0
+ xyplot.y1=0.0
+ xyplot.y2=0.5
+
+ histplot.z1=16.0
+ histplot.z2=20.0
+ histplot.nbins=8
+
+ print ("")
+ print ("", >> ptlog)
+ print ("TESTING THE PEXAMINE TASK (FIRST TEXT FILE)", >> ptlog)
+ print ("DUMPING THE RESULTS TO THE PLOT FILE", >> ptlog)
+ print ("TESTING THE PEXAMINE TASK (FIRST TEXT FILE)")
+ print ("", >> ptlog)
+
+ pexamine (txtfile1, "", "", gcommands="ptools$test/gcommands.dat",
+ icommands="ptools$test/icommands.dat", >>G ptplot, >& "dev$null")
+
+ print ("", >> ptlog)
+ print ("TESTING THE PEXAMINE TASK (TABLE FILE)", >> ptlog)
+ print ("DUMPING THE RESULTS TO THE PLOT FILE", >> ptlog)
+ print ("TESTING THE PEXAMINE TASK (TABLE FILE)")
+ print ("", >> ptlog)
+
+ pexamine (tblfile1, "", "", gcommands="ptools$test/gcommands.dat",
+ icommands="ptools$test/icommands.dat", >>G ptplot, >& "dev$null")
+
+ # Clean up.
+ delete (txtfile1, ver-, >& "dev$null")
+ delete (txtfile2, ver-, >& "dev$null")
+ delete (tblfile1, ver-, >& "dev$null")
+
+ unlearn ("txconcat")
+ unlearn ("txdump")
+ unlearn ("txrenumber")
+ unlearn ("txselect")
+ unlearn ("txsort")
+ unlearn ("pconvert")
+
+ unlearn ("tbconcat")
+ unlearn ("tbdump")
+ unlearn ("tbrenumber")
+ unlearn ("tbselect")
+ unlearn ("tbsort")
+ unlearn ("tbkeycol")
+ unlearn ("tbcrename")
+
+ unlearn ("pconcat")
+ unlearn ("pdump")
+ unlearn ("prenumber")
+ unlearn ("pselect")
+ unlearn ("psort")
+ unlearn ("pexamine")
+
+ unlearn ("xyplot")
+ unlearn ("histplot")
+ unlearn ("radplot")
+ unlearn ("surfplot")
+ unlearn ("cntrplot")
+
+ unlearn ("istable")
+
+ bye
+end
diff --git a/noao/digiphot/ptools/ptutils/mkpkg b/noao/digiphot/ptools/ptutils/mkpkg
new file mode 100644
index 00000000..3c3dc1bb
--- /dev/null
+++ b/noao/digiphot/ptools/ptutils/mkpkg
@@ -0,0 +1,12 @@
+# miscellaneous useful tasks
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ t_istable.x ../../lib/ptkeysdef.h
+ t_tbkeycol.x <tbset.h>
+ t_tbcrename.x <tbset.h>
+ ;
diff --git a/noao/digiphot/ptools/ptutils/t_istable.x b/noao/digiphot/ptools/ptutils/t_istable.x
new file mode 100644
index 00000000..b8cbf5db
--- /dev/null
+++ b/noao/digiphot/ptools/ptutils/t_istable.x
@@ -0,0 +1,71 @@
+include "../../lib/ptkeysdef.h"
+
+# T_ISTABLE -- Decide whether an input file is an ST Table, an APPHOT style
+# text file or neither.
+
+procedure t_istable ()
+
+pointer infile # name of the input file
+
+bool table, text, other
+int fd, type
+pointer sp, line
+int access(), tbtopn(), open(), getline(), strmatch()
+errchk tbtopn(), open()
+
+begin
+ # Get some working space.
+ call smark (sp)
+ call salloc (infile, SZ_FNAME, TY_CHAR)
+ call salloc (line, SZ_LINE, TY_CHAR)
+
+ # Fetch the name of the input file
+ call clgstr ("infile", Memc[infile], SZ_FNAME)
+ if (access (Memc[infile], READ_ONLY, TEXT_FILE) == YES)
+ type = TEXT_FILE
+ else
+ type = BINARY_FILE
+
+ if (type == BINARY_FILE) {
+ iferr {
+ fd = tbtopn (Memc[infile], READ_ONLY, 0)
+ } then {
+ table = false
+ text = false
+ other = true
+ } else {
+ table = true
+ text = false
+ other = false
+ call tbtclo (fd)
+ }
+ } else {
+ table = false
+ iferr {
+ fd = open (Memc[infile], READ_ONLY, TEXT_FILE)
+ } then {
+ text = false
+ other = true
+ } else {
+ Memc[line] = EOS
+ if (getline (fd, Memc[line]) != EOF) {
+ if (strmatch (Memc[line], KY_CHAR_IRAF) != 0) {
+ text = true
+ other = false
+ } else {
+ text = false
+ other = true
+ }
+ }
+ call close (fd)
+ }
+ }
+
+ # Store the results in the istable parameter file.
+ call clputb ("table", table)
+ call clputb ("text", text)
+ call clputb ("other", other)
+
+ # Free memory.
+ call sfree (sp)
+end
diff --git a/noao/digiphot/ptools/ptutils/t_tbcrename.x b/noao/digiphot/ptools/ptutils/t_tbcrename.x
new file mode 100644
index 00000000..8f54e9d5
--- /dev/null
+++ b/noao/digiphot/ptools/ptutils/t_tbcrename.x
@@ -0,0 +1,73 @@
+include <tbset.h>
+
+# T_TBCRENAME -- Rename a list of columns in an ST table.
+
+procedure t_tbcrename ()
+
+int tlist # the tables list descriptor
+int columns # the input columns list descriptor
+int names # the output column names list descriptor
+
+pointer sp, table, incname, outcname, tp, colptr
+int clpopnu(), clplen(), clgfil(), access(), tbpsta()
+pointer tbtopn()
+
+begin
+ # Open the lists of tables and keywords.
+ tlist = clpopnu ("table")
+ if (clplen (tlist) <= 0)
+ return
+ columns = clpopnu ("columns")
+ names = clpopnu ("names")
+ if (clplen (columns) != clplen (names))
+ call error (0,
+ "The number of new names does not equal the number of columns")
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (table, SZ_FNAME, TY_CHAR)
+ call salloc (incname, SZ_COLNAME, TY_CHAR)
+ call salloc (outcname, SZ_COLNAME, TY_CHAR)
+
+ # Loop over the list of ST tables.
+ while (clgfil (tlist, Memc[table], SZ_FNAME) != EOF) {
+
+ # If the file is not an ST table go to the next file in the list.
+ if (access (Memc[table], 0, TEXT_FILE) == YES)
+ next
+ iferr (tp = tbtopn (Memc[table], READ_WRITE, 0))
+ next
+ if (tbpsta (tp, TBL_WHTYPE) == TBL_TYPE_TEXT)
+ next
+
+ # Loop over the input column list.
+ while (clgfil (columns, Memc[incname], SZ_COLNAME) != EOF &&
+ clgfil (names, Memc[outcname], SZ_COLNAME) != EOF) {
+
+ # If the output column already exists in the table skip
+ # to the next input column.
+ call tbcfnd (tp, Memc[outcname], colptr, 1)
+ if (colptr != NULL)
+ next
+
+ # If the input column does not exist in the table skip to the
+ # next column.
+
+ call tbcfnd (tp, Memc[incname], colptr, 1)
+ if (colptr == NULL)
+ next
+
+ # Rename the column.
+ call tbcnam (tp, colptr, Memc[outcname])
+ }
+
+ call tbtclo (tp)
+ call clprew (columns)
+ call clprew (names)
+ }
+
+ call clpcls (columns)
+ call clpcls (names)
+ call clpcls (tlist)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/ptools/ptutils/t_tbkeycol.x b/noao/digiphot/ptools/ptutils/t_tbkeycol.x
new file mode 100644
index 00000000..47923ca6
--- /dev/null
+++ b/noao/digiphot/ptools/ptutils/t_tbkeycol.x
@@ -0,0 +1,140 @@
+include <tbset.h>
+
+# T_TBKEYCOL -- For all the rows of a list of ST tables, copy the values of
+# selected table keywords into new columns of the same name. If the columns
+# already exist no action is taken.
+
+procedure t_tbkeycol ()
+
+int tlist # the tables list descriptor
+int klist # the keywords list descriptor
+
+bool bval
+double dval
+int i, keytype, keyptr, nrows, keylength, ival
+pointer sp, table, keyword, keyvalue, format, tp, colptr
+real rval
+
+bool itob()
+int clpopnu(), clgfil(), clplen(), tbpsta(), strlen(), access()
+int ctoi(), ctor(), ctod()
+pointer tbtopn()
+errchk tbtopn()
+
+begin
+ # Open the lists of tables and keywords.
+ tlist = clpopnu ("tables")
+ if (clplen (tlist) <= 0)
+ return
+ klist = clpopnu ("keywords")
+ if (clplen (klist) <= 0)
+ return
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (table, SZ_FNAME, TY_CHAR)
+ call salloc (keyword, SZ_KEYWORD, TY_CHAR)
+ call salloc (keyvalue, SZ_PARREC, TY_CHAR)
+ call salloc (format, SZ_COLFMT, TY_CHAR)
+
+ # Loop over the list of ST tables.
+ while (clgfil (tlist, Memc[table], SZ_FNAME) != EOF) {
+
+ # If the file is not an ST table go to the next file in the list.
+ if (access(Memc[table], 0, TEXT_FILE) == YES)
+ next
+ iferr (tp = tbtopn (Memc[table], READ_WRITE, 0))
+ next
+ if (tbpsta (tp, TBL_WHTYPE) == TBL_TYPE_TEXT)
+ next
+
+
+ # Loop over the keywords.
+ while (clgfil (klist, Memc[keyword], SZ_FNAME) != EOF) {
+
+ # If a column named keyword already exists in the table
+ # skip to the next keyword.
+ call tbcfnd (tp, Memc[keyword], colptr, 1)
+ if (colptr != NULL)
+ next
+
+ # If keyword does not exist in the table skip to the
+ # next keyword.
+ call tbhfkr (tp, Memc[keyword], keytype, Memc[keyvalue],
+ keyptr)
+ if (keyptr == 0)
+ next
+
+ nrows = tbpsta (tp, TBL_NROWS)
+
+ # Decode the header value and copy it into all the rows
+ # of the table.
+ i = 1
+ switch (keytype) {
+ case TY_BOOL:
+ call tbcdef (tp, colptr, Memc[keyword], "undefined",
+ "%-3.3b", keytype, 1, 1)
+ if (ctoi (Memc[keyvalue], i, ival) <= 0)
+ ival = NO
+ bval = itob (ival)
+ do i = 1, nrows
+ call tbrptb (tp, colptr, bval, 1, i)
+ case TY_CHAR:
+ keylength = strlen (Memc[keyvalue])
+ call sprintf (Memc[format], SZ_COLFMT, "%*.*s")
+ call pargi (-keylength)
+ call pargi (keylength)
+ call tbcdef (tp, colptr, Memc[keyword], "undefined",
+ Memc[format], -keylength, 1, 1)
+ do i = 1, nrows
+ call tbrptt (tp, colptr, Memc[keyvalue], keylength,
+ 1, i)
+ case TY_INT:
+ keylength = ctoi (Memc[keyvalue], i, ival)
+ if (keylength <= 0) {
+ ival = INDEFI
+ keylength = 6
+ }
+ call sprintf (Memc[format], SZ_COLFMT, "%%%d.%dd")
+ call pargi (-keylength)
+ call pargi (keylength)
+ call tbcdef (tp, colptr, Memc[keyword], "undefined",
+ Memc[format], keytype, 1, 1)
+ do i = 1, nrows
+ call tbrpti (tp, colptr, ival, 1, i)
+ case TY_REAL:
+ keylength = ctor (Memc[keyvalue], i, rval)
+ if (keylength <= 0) {
+ rval = INDEFR
+ keylength = 6
+ }
+ call sprintf (Memc[format], SZ_COLFMT, "%%%dg")
+ call pargi (-keylength)
+ call tbcdef (tp, colptr, Memc[keyword], "undefined",
+ Memc[format], keytype, 1, 1)
+ do i = 1, nrows
+ call tbrptr (tp, colptr, rval, 1, i)
+ case TY_DOUBLE:
+ keylength = ctod (Memc[keyvalue], i, dval)
+ if (keylength <= 0) {
+ dval = INDEFD
+ keylength = 6
+ }
+ call sprintf (Memc[format], SZ_COLFMT, "%%%dg")
+ call pargi (-keylength)
+ call tbcdef (tp, colptr, Memc[keyword], "undefined",
+ Memc[format], keytype, 1, 1)
+ do i = 1, nrows
+ call tbrptd (tp, colptr, dval, 1, i)
+ }
+
+ }
+
+ call tbtclo (tp)
+ call clprew (klist)
+ }
+
+ call clpcls (klist)
+ call clpcls (tlist)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/ptools/radplot.par b/noao/digiphot/ptools/radplot.par
new file mode 100644
index 00000000..0d579463
--- /dev/null
+++ b/noao/digiphot/ptools/radplot.par
@@ -0,0 +1,22 @@
+# The PEXAMINE task radial profile plotting parameters
+
+rinner,r,h,0.0,,,Inner radius of the region to be plotted in pixels
+router,r,h,8.0,,,Outer radius of the region to be plotted in pixels
+x1,r,h,INDEF,,,Left world x-coord if not autoscaling
+x2,r,h,INDEF,,,Right world x-coord if not autoscaling
+y1,r,h,INDEF,,,Lower world y-coord if not autoscaling
+y2,r,h,INDEF,,,Upper world y-coord if not autoscaling
+marker,s,h,"box","point|box|plus|cross|circle|diamond|hline|vline",,Marker type
+szmarker,r,h,1.0,0.0,,Marker size
+logx,b,h,no,,,Log scale the x axis?
+logy,b,h,no,,,Log scale the y axis?
+box,b,h,yes,,,Draw box around periphery of window?
+ticklabels,b,h,yes,,,Label tick marks?
+majrx,i,h,5,,,Number of major divisions along x axis
+minrx,i,h,5,,,Number of minor divisions along x axis
+majry,i,h,5,,,Number of major divisions along y axis
+minry,i,h,5,,,Number of minor divisions along y axis
+round,b,h,no,,,Round axes to nice values?
+fill,b,h,yes,,,Fill viewport vs enforce unity aspect ratio?
+grid,b,h,no,,,Draw grid lines at major tick marks?
+banner,b,h,yes,,,Standard banner?
diff --git a/noao/digiphot/ptools/surfplot.par b/noao/digiphot/ptools/surfplot.par
new file mode 100644
index 00000000..1d94e5cc
--- /dev/null
+++ b/noao/digiphot/ptools/surfplot.par
@@ -0,0 +1,10 @@
+# The PEXAMINE task surface plotting parameters
+
+ncolumns,i,h,21,2,,"Number of columns"
+nlines,i,h,21,2,,"Number of lines"
+axes,b,h,yes,,,Draw axes?
+angh,r,h, -33.,,,Horizontal viewing angle (degrees)
+angv,r,h,25.,,,Vertical viewing angle (degrees)
+floor,r,h,INDEF,,,Minimum value to be plotted
+ceiling,r,h,INDEF,,,Maximum value to be plotted
+banner,b,h,yes,,,Standard banner?
diff --git a/noao/digiphot/ptools/tbcalc.cl b/noao/digiphot/ptools/tbcalc.cl
new file mode 100644
index 00000000..25f1ee60
--- /dev/null
+++ b/noao/digiphot/ptools/tbcalc.cl
@@ -0,0 +1,37 @@
+# TBCALC -- Perform arithmetic operations on a column column of an
+# APPHOT/DAOPHOT STSDAS table database.
+
+procedure tbcalc (tables, column, value)
+
+file tables {prompt="Input apphot/daophot tables databases to be renumbered"}
+string column {prompt="Column to be edited"}
+string value {prompt="New value or expression for column"}
+
+struct *inlist
+
+begin
+ # Declare local variables.
+ file ttables, tcolumn, tvalue
+ string tmpin, inname
+
+ # Get the positional parameters.
+ ttables = tables
+ tcolumn = column
+ tvalue = value
+
+ tmpin = mktemp ("tmp$")
+ files (ttables, sort=no, > tmpin)
+
+ inlist = tmpin
+ while (fscan (inlist, inname) != EOF) {
+ if (defpar ("tcalc.verbose") || defpar ("tcalc.harmless")) {
+ tcalc (inname, tcolumn, tvalue, datatype="real", colunits="",
+ colfmt="", verbose=no, harmless=0.1)
+ } else {
+ tcalc (inname, tcolumn, tvalue, datatype="real", colunits="",
+ colfmt="")
+ }
+ }
+ delete (tmpin, ver-, >& "dev$null")
+ inlist = ""
+end
diff --git a/noao/digiphot/ptools/tbconcat.cl b/noao/digiphot/ptools/tbconcat.cl
new file mode 100644
index 00000000..d9e5c429
--- /dev/null
+++ b/noao/digiphot/ptools/tbconcat.cl
@@ -0,0 +1,113 @@
+# TBCONCAT -- Concatenate a list of apphot/daophot STSDAS table databases
+# into a single output database. All the input files must of been written
+# by the same task.
+
+procedure tbconcat (tables, outtable)
+
+file tables {prompt="Input apphot/daophot tables databases to be concatenated"}
+file outtable {prompt="Output apphot/daophot STSDAS table database"}
+string task {"TASK", prompt="Task name keyword"}
+
+struct *inlist
+
+begin
+ # Declare local variables.
+ bool stat, first_tab
+ file in, out
+ int npars, first_npars, ncols, first_ncols
+ string tmpin, inname, first_inname, tkname, first_tkname
+
+ # Cache the parameters.
+ cache ("istable", "keypar", "tinfo")
+
+ # Get the positional parameters.
+ in = tables
+ out = outtable
+
+ # Make a file lists.
+ tmpin = mktemp ("tmp$")
+ files (in, sort=no, > tmpin)
+
+ # Loop through the list checking that all the files are
+ # tables that they were created with the same task and
+ # that they have the same number of parameters and columns
+
+ stat = yes
+ first_tab = yes
+
+ inlist = tmpin
+ while (fscan (inlist, inname) != EOF) {
+
+ # Check that the input file is an STSDAS table.
+ istable (inname)
+ if (! istable.table) {
+ print ("ERROR: File " // inname // " is not an ST table")
+ stat = no
+ break
+ }
+
+
+ # Check that all the input files were written by the same task.
+ if (defpar ("keypar.silent")) {
+ keypar (inname, task, silent=no)
+ } else {
+ keypar (inname, task)
+ }
+ if (first_tab) {
+ first_inname = inname
+ first_tkname = keypar.value
+ } else {
+ tkname = keypar.value
+ if (tkname != first_tkname) {
+ print ("ERROR:")
+ print (" File" // first_inname // " written by task " //
+ first_tkname)
+ print (" File" // inname // " written by task " //
+ tkname)
+ stat = no
+ break
+ }
+ }
+
+ # Check that the number of parameters and columns is the same.
+ tinfo (inname, ttout=no)
+ if (first_tab) {
+ first_npars = tinfo.npar
+ first_ncols = tinfo.ncols
+ } else {
+ npars = tinfo.npar
+ ncols = tinfo.ncols
+ if (npars != first_npars) {
+ print ("ERROR:")
+ print (" File " // first_inname // " has " //
+ first_npars // "parameters")
+ print (" File " // inname // " has " // npars //
+ "parameters")
+ stat = no
+ break
+ }
+ if (ncols != first_ncols) {
+ print ("ERROR:")
+ print (" File " // first_inname // " has " //
+ first_ncols // "columns")
+ print (" File " // inname // " has " // ncols //
+ "columns")
+ stat = no
+ break
+ }
+ }
+
+ first_tab = no
+ }
+
+ delete (tmpin, ver-, >& "dev$null")
+ inlist = ""
+
+ # Return if status is not ok.
+ if (! stat)
+ return
+
+ # Do the actual append.
+ tmerge (in, out, option="append", allcols=no, tbltype="row",
+ allrows=100, extracol=0)
+end
diff --git a/noao/digiphot/ptools/tbcrename.par b/noao/digiphot/ptools/tbcrename.par
new file mode 100644
index 00000000..c466c337
--- /dev/null
+++ b/noao/digiphot/ptools/tbcrename.par
@@ -0,0 +1,6 @@
+# TBCRENAME Parameters
+
+tables,s,a,,,,Input apphot/daophot tables databases
+columns,s,a,"",,,List of column names to be changed
+names,s,a,"",,,List of new column names
+mode,s,h,"ql",,,Mode of task
diff --git a/noao/digiphot/ptools/tbdump.cl b/noao/digiphot/ptools/tbdump.cl
new file mode 100644
index 00000000..f3482a5f
--- /dev/null
+++ b/noao/digiphot/ptools/tbdump.cl
@@ -0,0 +1,44 @@
+# TBDUMP -- Dump selected columns of an APPHOT/DAOPHOT STSDAS table database.
+
+procedure tbdump (tables, fields, expr)
+
+file tables {prompt = "Input apphot/daophot tables database(s)"}
+string fields {"", prompt = "Fields to be extracted"}
+string expr {"yes", prompt = "Boolean expression for record selection"}
+file datafile {"STDOUT", prompt = "Output file for table data"}
+file cdfile {"", prompt = "Output file for table column definitions"}
+file pfile {"", prompt = "Output file for table header parameters"}
+string rows {"-", prompt = "Range of rows to dump"}
+int pagwidth {158, prompt = "Output page width"}
+
+struct *inlist
+
+begin
+ # Declare local variables
+ file ttables
+ string tfields, texpr, tmpin, tmpout, inname
+
+ # Get the positional parameters.
+ ttables = tables
+ tfields = fields
+ texpr = expr
+
+ tmpin = mktemp ("tmp$")
+ files (ttables, sort=no, > tmpin)
+
+ inlist = tmpin
+ while (fscan (inlist, inname) != EOF) {
+ if (texpr != "yes") {
+ tmpout = mktemp ("tmp$")
+ tselect (inname, tmpout, texpr)
+ tdump (tmpout, cdfile=cdfile, pfile=pfile, datafile=datafile,
+ columns=tfields, rows=rows, pwidth=pagwidth)
+ tdelete (tmpout, ver-, >& "dev$null")
+ } else {
+ tdump (inname, cdfile=cdfile, pfile=pfile, datafile=datafile,
+ columns=tfields, rows=rows, pwidth=pagwidth)
+ }
+ }
+ delete (tmpin, ver-, >& "dev$null")
+ inlist = ""
+end
diff --git a/noao/digiphot/ptools/tbkeycol.par b/noao/digiphot/ptools/tbkeycol.par
new file mode 100644
index 00000000..bc6bc159
--- /dev/null
+++ b/noao/digiphot/ptools/tbkeycol.par
@@ -0,0 +1,5 @@
+# TKEYCOL Parameters
+
+tables,s,a,,,,Input apphot/daophot tables databases
+keywords,s,a,"",,,Table keywords to be copied to table columns
+mode,s,h,"ql",,,Mode of task
diff --git a/noao/digiphot/ptools/tbrenumber.cl b/noao/digiphot/ptools/tbrenumber.cl
new file mode 100644
index 00000000..75778ac6
--- /dev/null
+++ b/noao/digiphot/ptools/tbrenumber.cl
@@ -0,0 +1,36 @@
+# TBRENUMBER -- Renumber the ID column of an APPHOT/DAOPHOT STSDAS table
+# database.
+
+procedure tbrenumber (tables)
+
+file tables {prompt="Input apphot/daophot tables databases to be renumbered"}
+int idoffset {0, min=0, prompt="Id number offset"}
+string id {"ID", prompt="Id name keyword"}
+
+struct *inlist
+
+begin
+ # Declare local variables.
+ file ttables
+ string tmpin, inname, expr
+
+ # Get the positional parameters.
+ ttables = tables
+ expr = "rownum + " // idoffset
+
+ tmpin = mktemp ("tmp$")
+ files (ttables, sort=no, > tmpin)
+
+ inlist = tmpin
+ while (fscan (inlist, inname) != EOF) {
+ if (defpar ("tcalc.verbose") || defpar ("tcalc.harmless")) {
+ tcalc (inname, id, expr, datatype="real", colunits="",
+ colfmt="", verbose=no, harmless=0.1)
+ } else {
+ tcalc (inname, id, expr, datatype="real", colunits="",
+ colfmt="")
+ }
+ }
+ delete (tmpin, ver-, >& "dev$null")
+ inlist = ""
+end
diff --git a/noao/digiphot/ptools/tbselect.cl b/noao/digiphot/ptools/tbselect.cl
new file mode 100644
index 00000000..2ba294f8
--- /dev/null
+++ b/noao/digiphot/ptools/tbselect.cl
@@ -0,0 +1,20 @@
+# TBSELECT -- Select records from an APPHOT/DAOPHOT STSDAS table based
+# on the value of an expression.
+
+procedure tbselect (intable, outtable, expr)
+
+file intable {"", prompt = "Input apphot/daophot tables database(s)"}
+file outtable {"", prompt = "Output apphot/daophot tables database(s)"}
+string expr {"", prompt = "Boolean expression for record selection"}
+
+begin
+ # Declare the local variables.
+ string tintable, touttable, texpr
+
+ # Get the positional parameters.
+ tintable = intable
+ touttable = outtable
+ texpr = expr
+
+ tselect (tintable, touttable, texpr)
+end
diff --git a/noao/digiphot/ptools/tbsort.cl b/noao/digiphot/ptools/tbsort.cl
new file mode 100644
index 00000000..c5d10f24
--- /dev/null
+++ b/noao/digiphot/ptools/tbsort.cl
@@ -0,0 +1,21 @@
+# TBSORT -- Sort an APPHOT/DAOPHOT STSDAS table using the values in the
+# selected columns.
+
+procedure tbsort (table, fields)
+
+file table {"", prompt="Input apphot/daophot tables database(s)to be sorted"}
+string fields {"", prompt = "Fields to be sorted on"}
+bool ascend {yes, prompt = "Sort in ascending value order ?"}
+bool casesens {yes, prompt = "Case sensitive sort ?"}
+
+begin
+ # Decalre the local variables.
+ string ttable, tfields
+
+ # Get the positional parameters.
+ ttable = table
+ tfields = fields
+
+ # Sort the table.
+ tsort (ttable, tfields, ascend=ascend, casesens=casesens)
+end
diff --git a/noao/digiphot/ptools/test/gcommands.dat b/noao/digiphot/ptools/test/gcommands.dat
new file mode 100644
index 00000000..1ec5ac13
--- /dev/null
+++ b/noao/digiphot/ptools/test/gcommands.dat
@@ -0,0 +1,3 @@
+h
+i
+e
diff --git a/noao/digiphot/ptools/test/icommands.dat b/noao/digiphot/ptools/test/icommands.dat
new file mode 100644
index 00000000..01058d84
--- /dev/null
+++ b/noao/digiphot/ptools/test/icommands.dat
@@ -0,0 +1 @@
+g
diff --git a/noao/digiphot/ptools/test/test1.dat b/noao/digiphot/ptools/test/test1.dat
new file mode 100644
index 00000000..7f2e9dc5
--- /dev/null
+++ b/noao/digiphot/ptools/test/test1.dat
@@ -0,0 +1,133 @@
+#K IRAF = NOAO/IRAFV2.10BETA version %-23s
+#K USER = davis name %-23s
+#K HOST = tucana computer %-23s
+#K DATE = 10-04-91 mm-dd-yr %-23s
+#K TIME = 07:57:32 hh:mm:ss %-23s
+#K PACKAGE = apphot name %-23s
+#K TASK = phot name %-23s
+#
+#K SCALE = 1. units %-23.7g
+#K FWHMPSF = 2. scaleunit %-23.7g
+#K EMISSION = yes switch %-23b
+#K DATAMIN = INDEF counts %-23.7g
+#K DATAMAX = INDEF counts %-23.7g
+#K EXPOSURE = "" keyword %-23s
+#K AIRMASS = "" keyword %-23s
+#K FILTER = "" keyword %-23s
+#K OBSTIME = "" keyword %-23s
+#
+#K NOISE = poisson model %-23s
+#K THRESHOLD = 30. counts %-23.7g
+#K CTHRESHOLD = 0. counts %-23.7g
+#K SIGMA = 10. counts %-23.7g
+#K GAIN = "" keyword %-23s
+#K EPADU = 1. e-/adu %-23.7g
+#K CCDREAD = "" keyword %-23s
+#K READNOISE = 0. e- %-23.7g
+#
+#K CALGORITHM = none algorithm %-23s
+#K CBOXWIDTH = 5. scaleunit %-23.7g
+#K MAXSHIFT = 1. scaleunit %-23.7g
+#K CMAXITER = 10 number %-23d
+#K MINSNRATIO = 1. number %-23.7g
+#K CLEAN = no switch %-23b
+#K RCLEAN = 1. scaleunit %-23.7g
+#K RCLIP = 2. scaleunit %-23.7g
+#K KCLEAN = 3. sigma %-23.7g
+#
+#K SALGORITHM = mode algorithm %-23s
+#K ANNULUS = 6. scaleunit %-23.7g
+#K DANNULUS = 12. scaleunit %-23.7g
+#K SMAXITER = 10 number %-23d
+#K SKREJECT = 3. sigma %-23.7g
+#K SNREJECT = 50 number %-23d
+#K KHIST = 3. sigma %-23.7g
+#K BINSIZE = 0.1 sigma %-23.7g
+#K SMOOTH = no switch %-23b
+#K RGROW = 0. scaleunit %-23.7g
+#K SKYVALUE = 0. counts %-23.7g
+#
+#K WEIGHTING = constant model %-23s
+#K APERTURES = 3.0,5.0 scaleunit %-23s
+#K ZMAG = 25. zeropoint %-23.7g
+#
+#N IMAGE XINIT YINIT ID COORDS LID \
+#U imagename pixels pixels ## filename ## \
+#F %-23s %-10.2f %-10.2f %-5d %-23s %-5d
+#
+#N XCENTER YCENTER XSHIFT YSHIFT XERR YERR CIER CERROR \
+#U pixels pixels pixels pixels pixels pixels ## cerrors \
+#F %-12.2f %-11.2f %-8.2f %-8.2f %-8.2f %-8.2f %-5d %-13s
+#
+#N MSKY STDEV SSKEW NSKY NSREJ SIER SERROR \
+#U counts counts counts npix npix ## serrors \
+#F %-18.7g %-15.7g %-15.7g %-7d %-6d %-5d %-13s
+#
+#N ITIME XAIRMASS IFILTER OTIME \
+#U timeunit number name timeunit \
+#F %-18.7g %-15.7g %-23s %-23s
+#
+#N RAPERT SUM AREA MAG MERR PIER PERROR \
+#U scale counts pixels mag mag ## perrors \
+#F %-12.2f %-15.7f %-15.7f %-7.3f %-6.3f %-5d %-13s
+#
+testim 41.05 4.01 1 testim.coo.1 1 \
+ 41.05 4.01 0.00 0.00 INDEF INDEF 0 No_error \
+ 101.2498 10.10408 3.265505 422 10 0 No_error \
+ 1. INDEF INDEF INDEF \
+ 3.00 4177.432 28.38464 17.212 0.055 0 No_error *\
+ 5.00 0. 0. INDEF INDEF 302 Out_of_bounds *
+testim 23.05 7.01 2 testim.coo.1 2 \
+ 23.05 7.01 0.00 0.00 INDEF INDEF 0 No_error \
+ 100.046 10.3039 5.156589 599 26 0 No_error \
+ 1. INDEF INDEF INDEF \
+ 3.00 3729.583 28.38464 17.627 0.078 0 No_error *\
+ 5.00 9275.692 79.08551 17.163 0.083 0 No_error *
+testim 18.01 7.98 3 testim.coo.1 3 \
+ 18.01 7.98 0.00 0.00 INDEF INDEF 0 No_error \
+ 99.18147 9.960084 4.406289 624 27 0 No_error \
+ 1. INDEF INDEF INDEF \
+ 3.00 3848.674 28.38741 17.465 0.066 0 No_error *\
+ 5.00 9254.844 79.12583 17.129 0.078 0 No_error *
+testim 25.99 22.00 4 testim.coo.1 4 \
+ 25.99 22.00 0.00 0.00 INDEF INDEF 0 No_error \
+ 100.8048 10.62133 5.339536 839 57 0 No_error \
+ 1. INDEF INDEF INDEF \
+ 3.00 4807.073 28.38794 16.777 0.040 0 No_error *\
+ 5.00 10242.03 79.1264 16.612 0.053 0 No_error *
+testim 35.99 22.00 5 testim.coo.1 5 \
+ 35.99 22.00 0.00 0.00 INDEF INDEF 0 No_error \
+ 101.8237 10.81446 5.27525 836 32 0 No_error \
+ 1. INDEF INDEF INDEF \
+ 3.00 5733.314 28.38794 16.366 0.030 0 No_error *\
+ 5.00 11055.33 79.12638 16.308 0.041 0 No_error *
+testim 8.00 22.96 6 testim.coo.1 6 \
+ 8.00 22.96 0.00 0.00 INDEF INDEF 0 No_error \
+ 98.55382 9.745545 -1.86605 642 15 0 No_error \
+ 1. INDEF INDEF INDEF \
+ 3.00 5121.953 28.38596 16.584 0.033 0 No_error *\
+ 5.00 10346.71 79.10844 16.484 0.045 0 No_error *
+testim 30.96 25.04 7 testim.coo.1 7 \
+ 30.96 25.04 0.00 0.00 INDEF INDEF 0 No_error \
+ 101.0168 10.24696 1.970369 865 39 0 No_error \
+ 1. INDEF INDEF INDEF \
+ 3.00 4406.198 28.38385 17.032 0.048 0 No_error *\
+ 5.00 10425.96 79.07048 16.532 0.048 0 No_error *
+testim 21.06 26.07 8 testim.coo.1 8 \
+ 21.06 26.07 0.00 0.00 INDEF INDEF 0 No_error \
+ 100.5127 10.64676 6.194943 841 65 0 No_error \
+ 1. INDEF INDEF INDEF \
+ 3.00 3008.981 28.37686 19.512 0.409 0 No_error *\
+ 5.00 8254.723 78.98734 18.753 0.346 0 No_error *
+testim 28.96 33.93 9 testim.coo.1 9 \
+ 28.96 33.93 0.00 0.00 INDEF INDEF 0 No_error \
+ 101.6732 10.37004 5.42453 845 61 0 No_error \
+ 1. INDEF INDEF INDEF \
+ 3.00 3637.463 28.37949 17.809 0.090 0 No_error *\
+ 5.00 8691.696 79.00822 17.953 0.164 0 No_error *
+testim 35.99 41.97 10 testim.coo.1 10 \
+ 35.99 41.97 0.00 0.00 INDEF INDEF 0 No_error \
+ 101.5544 10.21878 4.627132 673 19 0 No_error \
+ 1. INDEF INDEF INDEF \
+ 3.00 5199.237 28.38675 16.588 0.034 0 No_error *\
+ 5.00 10383.58 79.12172 16.573 0.050 0 No_error *
diff --git a/noao/digiphot/ptools/test/test2.dat b/noao/digiphot/ptools/test/test2.dat
new file mode 100644
index 00000000..20ecab5c
--- /dev/null
+++ b/noao/digiphot/ptools/test/test2.dat
@@ -0,0 +1,315 @@
+#K IRAF = NOAO/IRAF V2.9.version %-15s
+#K USER = cmartin name %-15s
+#K HOST = kepler computer %-15s
+#K DATE = 05-24-91 mm-dd-yr %-15s
+#K TIME = 15:13:50 hh:mm:ss %-15s
+#K PACKAGE = apphot name %-15s
+#K TASK = polyphot name %-15s
+#
+#K SCALE = 1. units %-15.7g
+#K FWHMPSF = 1. scaleunit %-15.7g
+#K EMISSION = yes switch %-15b
+#K DATAMIN = INDEF counts %-15.7g
+#K DATAMAX = INDEF counts %-15.7g
+#K EXPOSURE = "" keyword %-15s
+#K AIRMASS = "" keyword %-15s
+#K FILTER = "" keyword %-15s
+#
+#K NOISE = poisson model %-15s
+#K THRESHOLD = 0. counts %-15.7g
+#K CTHRESHOLD = 0. counts %-15.7g
+#K SIGMA = INDEF counts %-15.7g
+#K GAIN = "" keyword %-15s
+#K EPADU = 1. e-/adu %-15.7g
+#K CCDREAD = "" keyword %-15s
+#K READNOISE = 0. e- %-15.7g
+#
+#K CALGORITHM = centroid algorithm %-15s
+#K CBOXWIDTH = 5. scaleunit %-15.7g
+#K MAXSHIFT = 1. scaleunit %-15.7g
+#K CMAXITER = 10 number %-15d
+#K MINSNRATIO = 1. number %-15.7g
+#K CLEAN = no switch %-15b
+#K RCLEAN = 1. scaleunit %-15.7g
+#K RCLIP = 2. scaleunit %-15.7g
+#K KCLEAN = 3. sigma %-15.7g
+#
+#K SALGORITHM = mode algorithm %-15s
+#K ANNULUS = 10. scaleunit %-15.7g
+#K DANNULUS = 10. scaleunit %-15.7g
+#K SMAXITER = 10 number %-15d
+#K SKREJECT = 3. sigma %-15.7g
+#K SNREJECT = 50 number %-15d
+#K KHIST = 3. sigma %-15.7g
+#K BINSIZE = 0.1 sigma %-15.7g
+#K SMOOTH = no switch %-15b
+#K RGROW = 0. scaleunit %-15.7g
+#K SKYVALUE = 0. counts %-15.7g
+#
+#K WEIGHTING = constant model %-15s
+#K ZMAG = 26. zeropoint %-15.7g
+#
+#N IMAGE XINIT YINIT ID COORDS LID \
+#U imagename pixels pixels ## filename ## \
+#F %-23s %-10.2f %-10.2f %-5d %-20s %-5d
+#
+#N XCENTER YCENTER XSHIFT YSHIFT XERR YERR CIER CERROR \
+#U pixels pixels pixels pixels pixels pixels ## cerrors \
+#F %-12.2f %-9.2f %-7.2f %-7.2f %-7.2f %-7.2f %-5d %-13s
+#
+#N MSKY STDEV SSKEW NSKY NSREJ SIER SERROR \
+#U counts counts counts npix npix ## serrors \
+#F %-18.7g %-15.7g %-15.7g %-7d %-6d %-5d %-13s
+#
+#N ITIME XAIRMASS IFILTER \
+#U timeunit number name \
+#F %-18.7g %-15.7g %-23s
+#
+#N SUM AREA MAG MERR PIER PERROR \
+#U counts pixels mag mag ## perrors \
+#F %-18.7g %-15.7g %-9.3f %-8.3f %-7d %-13s
+#
+#N POLYGONS PID OLDXMEAN OLDYMEAN XMEAN YMEAN MINRAD NVER \
+#U filename ## pixels pixels pixels pixels pixels ## \
+#F %-23s %-5d %-9.2f %-9.2f %-9.2f %-9.2f %-9.2f %-5d
+#
+#N XVERTEX YVERTEX \
+#U pixels pixels \
+#F %-12.2f %-9.2f
+#
+rot.N2903 186.64 195.51 1 nullfile 1 \
+ 187.70 198.05 1.06 2.54 0.00 0.01 27 Shift_too_big \
+ 11.29906 43.04229 33.70715 702 243 0 No_error \
+ 1. INDEF INDEF \
+ 412419.6 404.0344 11.974 0.003 0 No_error \
+ ell.N2903 1 186.64 195.51 187.70 198.05 17.77 14 \
+ 171.03 198.06 *\
+ 176.03 203.81 *\
+ 181.03 205.44 *\
+ 186.03 206.08 *\
+ 191.03 205.96 *\
+ 196.03 205.04 *\
+ 201.03 202.89 *\
+ 204.37 198.05 *\
+ 199.37 192.30 *\
+ 194.37 190.66 *\
+ 189.37 190.03 *\
+ 184.37 190.15 *\
+ 179.37 191.07 *\
+ 174.37 193.22 *
+rot.N2903 186.64 195.51 2 nullfile 2 \
+ 187.70 198.05 1.06 2.54 0.00 0.01 27 Shift_too_big \
+ 11.29906 43.04229 33.70715 702 243 0 No_error \
+ 1. INDEF INDEF \
+ 491112.9 1657.524 11.814 0.008 0 No_error \
+ ell.N2903 2 186.64 195.51 187.70 198.05 34.43 28 \
+ 154.37 198.06 *\
+ 159.37 206.55 *\
+ 164.37 209.57 *\
+ 169.37 211.52 *\
+ 174.37 212.83 *\
+ 179.37 213.67 *\
+ 184.37 214.10 *\
+ 189.37 214.16 *\
+ 194.37 213.86 *\
+ 199.37 213.16 *\
+ 204.37 212.02 *\
+ 209.37 210.31 *\
+ 214.37 207.73 *\
+ 219.37 203.09 *\
+ 221.03 198.05 *\
+ 216.03 189.56 *\
+ 211.03 186.54 *\
+ 206.03 184.59 *\
+ 201.03 183.27 *\
+ 196.03 182.44 *\
+ 191.03 182.01 *\
+ 186.03 181.95 *\
+ 181.03 182.25 *\
+ 176.03 182.95 *\
+ 171.03 184.09 *\
+ 166.03 185.80 *\
+ 161.03 188.38 *\
+ 156.03 193.02 *
+rot.N2903 186.64 195.51 3 nullfile 3 \
+ 187.70 198.05 1.06 2.54 0.00 0.01 27 Shift_too_big \
+ 11.29906 43.04229 33.70715 702 243 0 No_error \
+ 1. INDEF INDEF \
+ 692970.2 3752.306 11.467 0.011 0 No_error \
+ ell.N2903 3 186.64 195.51 187.70 198.05 51.10 42 \
+ 137.70 198.05 *\
+ 142.70 208.60 *\
+ 147.70 212.57 *\
+ 152.70 215.33 *\
+ 157.70 217.41 *\
+ 162.70 219.00 *\
+ 167.70 220.23 *\
+ 172.70 221.13 *\
+ 177.70 221.76 *\
+ 182.70 222.12 *\
+ 187.70 222.24 *\
+ 192.70 222.12 *\
+ 197.70 221.76 *\
+ 202.70 221.13 *\
+ 207.70 220.23 *\
+ 212.70 219.00 *\
+ 217.70 217.41 *\
+ 222.70 215.33 *\
+ 227.70 212.57 *\
+ 232.70 208.60 *\
+ 237.70 198.05 *\
+ 237.70 198.05 *\
+ 232.70 187.51 *\
+ 227.70 183.54 *\
+ 222.70 180.78 *\
+ 217.70 178.70 *\
+ 212.70 177.11 *\
+ 207.70 175.88 *\
+ 202.70 174.98 *\
+ 197.70 174.35 *\
+ 192.70 173.99 *\
+ 187.70 173.87 *\
+ 182.70 173.99 *\
+ 177.70 174.35 *\
+ 172.70 174.98 *\
+ 167.70 175.88 *\
+ 162.70 177.11 *\
+ 157.70 178.70 *\
+ 152.70 180.78 *\
+ 147.70 183.54 *\
+ 142.70 187.51 *\
+ 137.70 198.05 *
+rot.N2903 186.64 195.51 4 nullfile 4 \
+ 187.70 198.05 1.06 2.55 0.00 0.01 27 Shift_too_big \
+ 11.29906 43.04229 33.70715 702 243 0 No_error \
+ 1. INDEF INDEF \
+ 1187322. 6709.435 10.885 0.011 0 No_error \
+ ell.N2903 4 186.64 195.51 187.70 198.05 67.77 54 \
+ 121.03 198.06 *\
+ 126.03 210.31 *\
+ 131.03 215.05 *\
+ 136.03 218.44 *\
+ 141.03 221.09 *\
+ 146.03 223.23 *\
+ 151.03 224.99 *\
+ 156.03 226.44 *\
+ 161.03 227.62 *\
+ 166.03 228.56 *\
+ 171.03 229.28 *\
+ 176.03 229.81 *\
+ 181.03 230.15 *\
+ 186.03 230.30 *\
+ 191.03 230.27 *\
+ 196.03 230.05 *\
+ 201.03 229.66 *\
+ 206.03 229.06 *\
+ 211.03 228.27 *\
+ 216.03 227.25 *\
+ 221.03 225.99 *\
+ 226.03 224.44 *\
+ 231.03 222.57 *\
+ 236.03 220.27 *\
+ 241.03 217.41 *\
+ 246.03 213.67 *\
+ 251.03 208.13 *\
+ 254.37 198.04 *\
+ 249.37 185.80 *\
+ 244.37 181.06 *\
+ 239.37 177.67 *\
+ 234.37 175.02 *\
+ 229.37 172.88 *\
+ 224.37 171.12 *\
+ 219.37 169.67 *\
+ 214.37 168.50 *\
+ 209.37 167.55 *\
+ 204.37 166.83 *\
+ 199.37 166.30 *\
+ 194.37 165.96 *\
+ 189.37 165.81 *\
+ 184.37 165.84 *\
+ 179.37 166.06 *\
+ 174.37 166.45 *\
+ 169.37 167.05 *\
+ 164.37 167.84 *\
+ 159.37 168.86 *\
+ 154.37 170.12 *\
+ 149.37 171.67 *\
+ 144.37 173.55 *\
+ 139.37 175.84 *\
+ 134.37 178.70 *\
+ 129.37 182.44 *\
+ 124.37 187.98 *
+rot.N2903 186.64 195.51 5 nullfile 5 \
+ 187.70 198.05 1.06 2.54 0.00 0.01 27 Shift_too_big \
+ 11.29906 43.04229 33.70715 702 243 0 No_error \
+ 1. INDEF INDEF \
+ 1607853. 10511.2 10.568 0.013 0 No_error \
+ ell.N2903 5 186.64 195.51 187.70 198.05 84.43 68 \
+ 104.37 198.05 *\
+ 109.37 211.81 *\
+ 114.37 217.20 *\
+ 119.37 221.13 *\
+ 124.37 224.26 *\
+ 129.37 226.85 *\
+ 134.37 229.03 *\
+ 139.37 230.90 *\
+ 144.37 232.49 *\
+ 149.37 233.85 *\
+ 154.37 235.00 *\
+ 159.37 235.97 *\
+ 164.37 236.76 *\
+ 169.37 237.38 *\
+ 174.37 237.85 *\
+ 179.37 238.17 *\
+ 184.37 238.34 *\
+ 189.37 238.36 *\
+ 194.37 238.24 *\
+ 199.37 237.97 *\
+ 204.37 237.56 *\
+ 209.37 236.98 *\
+ 214.37 236.25 *\
+ 219.37 235.35 *\
+ 224.37 234.26 *\
+ 229.37 232.97 *\
+ 234.37 231.46 *\
+ 239.37 229.69 *\
+ 244.37 227.61 *\
+ 249.37 225.17 *\
+ 254.37 222.24 *\
+ 259.37 218.63 *\
+ 264.37 213.86 *\
+ 269.37 206.08 *\
+ 271.03 198.05 *\
+ 266.03 184.30 *\
+ 261.03 178.91 *\
+ 256.03 174.98 *\
+ 251.03 171.85 *\
+ 246.03 169.26 *\
+ 241.03 167.08 *\
+ 236.03 165.21 *\
+ 231.03 163.62 *\
+ 226.03 162.26 *\
+ 221.03 161.10 *\
+ 216.03 160.14 *\
+ 211.03 159.35 *\
+ 206.03 158.73 *\
+ 201.03 158.26 *\
+ 196.03 157.94 *\
+ 191.03 157.77 *\
+ 186.03 157.75 *\
+ 181.03 157.87 *\
+ 176.03 158.14 *\
+ 171.03 158.55 *\
+ 166.03 159.13 *\
+ 161.03 159.86 *\
+ 156.03 160.76 *\
+ 151.03 161.85 *\
+ 146.03 163.14 *\
+ 141.03 164.65 *\
+ 136.03 166.42 *\
+ 131.03 168.49 *\
+ 126.03 170.94 *\
+ 121.03 173.87 *\
+ 116.03 177.48 *\
+ 111.03 182.25 *\
+ 106.03 190.03 *
diff --git a/noao/digiphot/ptools/txcalc.par b/noao/digiphot/ptools/txcalc.par
new file mode 100644
index 00000000..d557d988
--- /dev/null
+++ b/noao/digiphot/ptools/txcalc.par
@@ -0,0 +1,6 @@
+# TXCALC Parameters
+
+textfiles,s,a,,,,Input apphot/daophot text database(s)
+field,s,a,,,,Field to be edited
+value,s,a,,,,New value or expression for field
+mode,s,h,"ql",,,Mode of task
diff --git a/noao/digiphot/ptools/txconcat.par b/noao/digiphot/ptools/txconcat.par
new file mode 100644
index 00000000..57249639
--- /dev/null
+++ b/noao/digiphot/ptools/txconcat.par
@@ -0,0 +1,6 @@
+# TXCONCAT Parameters
+
+textfiles,s,a,,,,Input apphot/daophot text databases to be concatenated
+outfile,s,a,,,,Output apphot/daophot text database
+task,s,h,"TASK",,,Task name keyword
+mode,s,h,"ql",,,Mode of task
diff --git a/noao/digiphot/ptools/txdump.par b/noao/digiphot/ptools/txdump.par
new file mode 100644
index 00000000..ce400817
--- /dev/null
+++ b/noao/digiphot/ptools/txdump.par
@@ -0,0 +1,8 @@
+# TXDUMP Parameters
+
+textfiles,s,a,,,,Input apphot/daophot text database(s)
+fields,s,a,,,,Fields to be extracted
+expr,s,a,yes,,,Boolean expression for record selection
+headers,b,h,no,,,Print the field headers ?
+parameters,b,h,yes,,,Print the parameters if headers is yes ?
+mode,s,h,"ql",,,Mode of task
diff --git a/noao/digiphot/ptools/txrenumber.par b/noao/digiphot/ptools/txrenumber.par
new file mode 100644
index 00000000..a9140216
--- /dev/null
+++ b/noao/digiphot/ptools/txrenumber.par
@@ -0,0 +1,6 @@
+# TXRENUMBER Parameters
+
+textfiles,s,a,,,,Input apphot/daophot text database(s) to be renumbered
+idoffset,i,h,0,,,Id number offset
+id,s,h,ID,,,Id name keyword
+mode,s,h,"ql",,,Mode of task
diff --git a/noao/digiphot/ptools/txselect.par b/noao/digiphot/ptools/txselect.par
new file mode 100644
index 00000000..080bc6d7
--- /dev/null
+++ b/noao/digiphot/ptools/txselect.par
@@ -0,0 +1,6 @@
+# TXSELECT Parameters
+
+textfiles,s,a,,,,Input apphot/daophot text database(s)
+outfiles,s,a,,,,Output apphot/daophot text databases(s)
+expr,s,a,"yes",,,Boolean expression for record selection
+mode,s,h,"ql",,,Mode of task
diff --git a/noao/digiphot/ptools/txsort.par b/noao/digiphot/ptools/txsort.par
new file mode 100644
index 00000000..95cc14e4
--- /dev/null
+++ b/noao/digiphot/ptools/txsort.par
@@ -0,0 +1,6 @@
+# TXSORT Parameters
+
+textfiles,s,a,,,,Input apphot/daophot text database(s) to be sorted
+field,s,a,MAG,,,Field to be sorted on
+ascend,b,h,yes,,,Sort in increasing value order?
+mode,s,h,"ql",,,Mode of task
diff --git a/noao/digiphot/ptools/txtools/mkpkg b/noao/digiphot/ptools/txtools/mkpkg
new file mode 100644
index 00000000..55485e70
--- /dev/null
+++ b/noao/digiphot/ptools/txtools/mkpkg
@@ -0,0 +1,23 @@
+# TXTOOLS tasks
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ t_txconcat.x ../../lib/ptkeysdef.h <fset.h> <error.h>
+ t_txdump.x
+ ptxdump.x <fset.h> <error.h> <evexpr.h> ../../lib/ptkeysdef.h
+ t_txcalc.x <fset.h>
+ ptxcalc.x ../../lib/ptkeysdef.h <error.h> \
+ <ctype.h> <evexpr.h>
+ t_txrenumber.x <fset.h>
+ ptrenumb.x ../../lib/ptkeysdef.h
+ t_txsort.x <fset.h>
+ ptsortnum.x <ctype.h> ../../lib/ptkeysdef.h
+ ptqsort.x
+ t_txselect.x <fset.h>
+ ptxselect.x ../../lib/ptkeysdef.h <error.h> \
+ <ctype.h> <evexpr.h>
+ ;
diff --git a/noao/digiphot/ptools/txtools/ptqsort.x b/noao/digiphot/ptools/txtools/ptqsort.x
new file mode 100644
index 00000000..3883424f
--- /dev/null
+++ b/noao/digiphot/ptools/txtools/ptqsort.x
@@ -0,0 +1,215 @@
+define LOGPTR 20 # log2(maxpts) (1e6)
+
+# PT_QSORT -- Vector Quicksort. In this version the index array is
+# sorted.
+
+procedure pt_qsortr (data, a, b, npix)
+
+real data[ARB] # data array
+int a[ARB], b[ARB] # index array
+int npix # number of pixels
+
+int i, j, lv[LOGPTR], p, uv[LOGPTR], temp
+real pivot
+
+begin
+ # Initialize the indices for an inplace sort.
+ do i = 1, npix
+ a[i] = i
+ call amovi (a, b, npix)
+
+ 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[b[j]]
+
+ while (i < j) {
+ for (i=i+1; data[b[i]] < pivot; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (data[b[j]] <= pivot)
+ break
+ if (i < j) { # out of order pair
+ temp = b[j] # interchange elements
+ b[j] = b[i]
+ b[i] = temp
+ }
+ }
+
+ j = uv[p] # move pivot to position i
+ temp = b[j] # interchange elements
+ b[j] = b[i]
+ b[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
+ }
+ }
+end
+
+
+# PT_QSORT -- Vector Quicksort. In this version the index array is
+# sorted.
+
+procedure pt_qsorti (data, a, b, npix)
+
+int data[ARB] # data array
+int a[ARB], b[ARB] # index array
+int npix # number of pixels
+
+int i, j, lv[LOGPTR], p, uv[LOGPTR], temp
+int pivot
+
+begin
+ # Initialize the indices for an inplace sort.
+ do i = 1, npix
+ a[i] = i
+ call amovi (a, b, npix)
+
+ 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[b[j]]
+
+ while (i < j) {
+ for (i=i+1; data[b[i]] < pivot; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (data[b[j]] <= pivot)
+ break
+ if (i < j) { # out of order pair
+ temp = b[j] # interchange elements
+ b[j] = b[i]
+ b[i] = temp
+ }
+ }
+
+ j = uv[p] # move pivot to position i
+ temp = b[j] # interchange elements
+ b[j] = b[i]
+ b[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
+ }
+ }
+end
+
+
+# PT_QSORT -- Vector Quicksort. In this version the index array is
+# sorted.
+
+procedure pt_qsortb (data, a, b, npix)
+
+bool data[ARB] # data array
+int a[ARB], b[ARB] # index array
+int npix # number of pixels
+
+int i, j, lv[LOGPTR], p, uv[LOGPTR], temp
+bool pivot
+int pt_compareb()
+
+begin
+ # Initialize the indices for an inplace sort.
+ do i = 1, npix
+ a[i] = i
+ call amovi (a, b, npix)
+
+ 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[b[j]]
+
+ while (i < j) {
+ #for (i=i+1; data[b[i]] != pivot; i=i+1)
+ for (i=i+1; pt_compareb (data[b[i]], pivot) < 0; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ #if (data[b[j]] != pivot)
+ if (pt_compareb (data[b[j]], pivot) <= 0)
+ break
+ if (i < j) { # out of order pair
+ temp = b[j] # interchange elements
+ b[j] = b[i]
+ b[i] = temp
+ }
+ }
+
+ j = uv[p] # move pivot to position i
+ temp = b[j] # interchange elements
+ b[j] = b[i]
+ b[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
+ }
+ }
+end
+
+
+# PT_COMPAREB -- Compare to booleans for the sort routine.
+
+int procedure pt_compareb (a, b)
+
+bool a # first boolean
+bool b # second boolean
+
+begin
+ if (! a && b)
+ return (-1)
+ else if (a && ! b)
+ return (1)
+ else
+ return (0)
+end
diff --git a/noao/digiphot/ptools/txtools/ptrenumb.x b/noao/digiphot/ptools/txtools/ptrenumb.x
new file mode 100644
index 00000000..85fee34a
--- /dev/null
+++ b/noao/digiphot/ptools/txtools/ptrenumb.x
@@ -0,0 +1,221 @@
+include "../../lib/ptkeysdef.h"
+
+# PT_RENUMBER -- Renumber the input file.
+
+int procedure pt_renumber (tp_in, tp_out, idoffset, id)
+
+int tp_in # the input text file descriptor
+int tp_out # the output text file descriptor
+int idoffset # the id number offset
+char id[ARB] # the name of the id column
+
+int first_rec, nunique, uunique, funique, record
+int ncontinue, recptr, nchars, field
+pointer key, line
+int getline(), strncmp(), pt_kstati()
+
+begin
+ # Initialize keyword structure.
+ call pt_kyinit (key)
+
+ # Initialize the file read.
+ first_rec = YES
+ nunique = 0
+ uunique = 0
+ funique = 0
+ record = 0
+ call malloc (line, SZ_LINE, TY_CHAR)
+
+ # Initilize the record read.
+ ncontinue = 0
+ recptr = 1
+
+ # Loop over the text file records.
+ repeat {
+
+ # Read in a line of the text file.
+ nchars = getline (tp_in, Memc[line])
+ if (nchars == EOF)
+ break
+
+ # Determine the type of record.
+ if (Memc[line] == KY_CHAR_POUND) {
+
+ if (strncmp (Memc[line], KY_CHAR_KEYWORD, KY_LEN_STR) == 0) {
+ call pt_kyadd (key, Memc[line], nchars)
+ call putline (tp_out, Memc[line])
+ } else if (strncmp (Memc[line], KY_CHAR_NAME,
+ KY_LEN_STR) == 0) {
+ nunique = nunique + 1
+ call pt_kname (key, Memc[line], nchars, nunique)
+ call putline (tp_out, Memc[line])
+ } else if (strncmp (Memc[line], KY_CHAR_UNITS,
+ KY_LEN_STR) == 0) {
+ uunique = uunique + 1
+ call pt_knunits (key, Memc[line], nchars, uunique)
+ call putline (tp_out, Memc[line])
+ } else if (strncmp (Memc[line], KY_CHAR_FORMAT,
+ KY_LEN_STR) == 0) {
+ funique = funique + 1
+ call pt_knformats (key, Memc[line], nchars, funique)
+ call putline (tp_out, Memc[line])
+ } else {
+ # skip lines beginning with # sign
+ call putline (tp_out, Memc[line])
+ }
+
+ } else if (Memc[line] == KY_CHAR_NEWLINE) {
+
+ # skip blank lines
+ call putline (tp_out, Memc[line])
+
+ } else {
+
+ # Check that the ID column exists and its datatype is
+ # integer.
+
+ if (first_rec == YES) {
+ field = pt_kstati (key, id, KY_INDEX)
+ if (field <= 0)
+ break
+ if (pt_kstati (key, id, KY_DATATYPE) != TY_INT)
+ break
+ }
+
+ # Replace the ID string.
+ call pt_idreplace (key, field, 1, Memc[line], nchars,
+ record + idoffset + 1, first_rec, recptr, ncontinue)
+
+ # Write the output record.
+ call putline (tp_out, Memc[line])
+
+ # Do the record book-keeping.
+ if (Memc[line+nchars-2] != KY_CHAR_CONT) {
+
+ # Increment the record counter.
+ record = record + 1
+ first_rec = NO
+
+ # Reinitialize the record read.
+ ncontinue = 0
+ recptr = 1
+ }
+ }
+
+ }
+
+ # Cleanup.
+ call mfree (line, TY_CHAR)
+ call pt_kyfree (key)
+
+ return (record)
+end
+
+
+# PT_IDREPLACE -- Replace the id with the current record number.
+
+procedure pt_idreplace (key, field, element, line, nchars, record, first_rec,
+ recptr, ncontinue)
+
+pointer key # pointer to record structure
+int field # field to be fetched
+int element # field array element
+char line[ARB] # input line
+int nchars # length of line array
+int record # current record number
+int first_rec # first record
+int recptr # line per record index
+int ncontinue # number of unique lines per record
+
+int len, i, cip, nper_line, nokeys, nckeys, nkeys
+pointer sp, str
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # The number of header columns defined by #K at the beginning of
+ # the file is nokeys.
+ if (recptr == 1)
+ nokeys = KY_NPKEYS(key)
+
+ # Increment the continuation statement counter or reset to 0.
+ if (line[nchars-2] == '*')
+ ncontinue = ncontinue + 1
+ else
+ ncontinue = 0
+
+ # Replace the current id with the record number.
+ cip = 1
+ if (ncontinue < 1) {
+
+ nper_line = Memi[KY_NPLINE(key)+recptr-1]
+ nkeys = nokeys + nper_line
+ call amovki (int(1), Memi[KY_NELEMS(key)+nokeys], nper_line)
+
+ do i = nokeys + 1, nkeys {
+ len = Memi[KY_KINDICES(key)+i-1]
+ if (i == field) {
+ call sprintf (Memc[str], SZ_FNAME, "%*s")
+ call pargi (-len)
+ call pargi (record)
+ call amovc (Memc[str], line[cip], len)
+ }
+ cip = cip + len
+ }
+
+ recptr = recptr + 1
+ nokeys = nkeys
+
+ } else if (ncontinue == 1) {
+
+ nckeys = nokeys + 1
+ nkeys = nokeys + Memi[KY_NPLINE(key)+recptr-1]
+
+ if (first_rec == YES) {
+ Memi[KY_NCONTINUE(key)+recptr-1] = KY_NLINES
+ do i = nckeys, nkeys
+ call malloc (Memi[KY_PTRS(key)+i-1], KY_NLINES *
+ Memi[KY_KINDICES(key)+i-1], TY_CHAR)
+ }
+
+ do i = nckeys, nkeys {
+ len = Memi[KY_KINDICES(key)+i-1]
+ if ((i == field) && (element == 1)) {
+ call sprintf (Memc[str], SZ_FNAME, "%*s")
+ call pargi (-len)
+ call pargi (record)
+ call amovc (Memc[str], line[cip], len)
+ }
+ cip = cip + len
+ }
+
+ nokeys = nkeys
+ recptr = recptr + 1
+
+ } else {
+
+ if (ncontinue > Memi[KY_NCONTINUE(key)+recptr-2]) {
+ Memi[KY_NCONTINUE(key)+recptr-2] =
+ Memi[KY_NCONTINUE(key)+recptr-2] + KY_NLINES
+ do i = nckeys, nkeys
+ call realloc (Memi[KY_PTRS(key)+i-1],
+ Memi[KY_NCONTINUE(key)+recptr-2] *
+ Memi[KY_KINDICES(key)+i-1], TY_CHAR)
+ }
+
+ do i = nckeys, nkeys {
+ len = Memi[KY_KINDICES(key)+i-1]
+ if ((i == field) && (element == ncontinue)) {
+ call sprintf (Memc[str], SZ_FNAME, "%*s")
+ call pargi (-len)
+ call pargi (record)
+ call amovc (Memc[str], line[cip], len)
+ }
+ Memi[KY_NELEMS(key)+i-1] = ncontinue
+ cip = cip + len
+ }
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/ptools/txtools/ptsortnum.x b/noao/digiphot/ptools/txtools/ptsortnum.x
new file mode 100644
index 00000000..463b2f38
--- /dev/null
+++ b/noao/digiphot/ptools/txtools/ptsortnum.x
@@ -0,0 +1,446 @@
+include <ctype.h>
+include "../../lib/ptkeysdef.h"
+
+# PT_SORTNUM -- Decode the column used for the sort, compute the file
+# record structure map, sort on the extracted column, reorder the
+# input file and write the output file.
+
+int procedure pt_sortnum (tp_in, tp_out, column, ascend)
+
+pointer tp_in # input Table descriptor
+pointer tp_out # output Table descriptor
+char column[ARB] # column name for sort
+int ascend # forward sort
+
+int coltype, colwidth, nrecs
+pointer key, colptr, colindex, recmap
+int pt_colmap()
+
+begin
+ # Initialize.
+ call pt_kyinit (key)
+ colptr = NULL
+ colindex = NULL
+ recmap = NULL
+
+ # Decode the sort column and map the record structure.
+ nrecs = pt_colmap (key, tp_in, tp_out, column, colptr, colindex,
+ coltype, colwidth, recmap)
+
+ # Sort the column and write the output file.
+ if (nrecs > 0) {
+ call pt_colsort (colptr, Memi[colindex], nrecs, coltype)
+ if (ascend == NO)
+ call pt_flipi (Memi[colindex], nrecs)
+ call pt_reorder (tp_in, tp_out, Memi[recmap], Memi[colindex], nrecs)
+ }
+
+ # Free space.
+ if (colptr != NULL)
+ call mfree (colptr, coltype)
+ if (colindex != NULL)
+ call mfree (colindex, TY_INT)
+ if (recmap != NULL)
+ call mfree (recmap, TY_INT)
+ call pt_kyfree (key)
+
+ return (nrecs)
+end
+
+
+define BUFSIZE 1000
+
+# PT_COLMAP -- Decode the column to be sorted and compute the record
+# structure of the file.
+
+int procedure pt_colmap (key, tp_in, tp_out, column, colptr, colindex, coltype,
+ bufwidth, recmap)
+
+pointer key # pointer to the database structure
+int tp_in # the input text file descriptor
+int tp_out # the output text file descriptor
+char column[ARB] # column to be sorted
+pointer colptr # pointer to extracted column array
+pointer colindex # pointer to index array for extracted column
+int coltype # data type of the column to be sorted
+int bufwidth # column width if chars
+pointer recmap # pointer to the record structure map
+
+int first_rec, nunique, uunique, funique, record
+int ncontinue, recptr, nchars, szbuf, colwidth, field, element
+long loffset, roffset
+pointer sp, line, name, value
+int getline(), strncmp(), pt_kstati()
+long note()
+
+begin
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+ call salloc (name, SZ_FNAME, TY_CHAR)
+ call salloc (value, SZ_FNAME, TY_CHAR)
+
+ # Initialize the file read.
+ first_rec = YES
+ nunique = 0
+ uunique = 0
+ funique = 0
+ record = 0
+ szbuf = 0
+
+ # Initilize the record read.
+ ncontinue = 0
+ recptr = 1
+
+ # Loop over the text file records.
+ repeat {
+
+ # Read in a line of the text file.
+ loffset = note (tp_in)
+ nchars = getline (tp_in, Memc[line])
+ if (nchars == EOF)
+ break
+
+ # Determine the type of record.
+ if (Memc[line] == KY_CHAR_POUND) {
+
+ if (strncmp (Memc[line], KY_CHAR_KEYWORD, KY_LEN_STR) == 0) {
+ call pt_kyadd (key, Memc[line], nchars)
+ if (first_rec == YES)
+ call putline (tp_out, Memc[line])
+ } else if (strncmp (Memc[line], KY_CHAR_NAME,
+ KY_LEN_STR) == 0) {
+ nunique = nunique + 1
+ call pt_kname (key, Memc[line], nchars, nunique)
+ call putline (tp_out, Memc[line])
+ } else if (strncmp (Memc[line], KY_CHAR_UNITS,
+ KY_LEN_STR) == 0) {
+ uunique = uunique + 1
+ call pt_knunits (key, Memc[line], nchars, uunique)
+ call putline (tp_out, Memc[line])
+ } else if (strncmp (Memc[line], KY_CHAR_FORMAT,
+ KY_LEN_STR) == 0) {
+ funique = funique + 1
+ call pt_knformats (key, Memc[line], nchars, funique)
+ call putline (tp_out, Memc[line])
+ } else {
+ # skip lines beginning with # sign
+ call putline (tp_out, Memc[line])
+ }
+
+ } else if (Memc[line] == KY_CHAR_NEWLINE) {
+ # skip blank lines
+ call putline (tp_out, Memc[line])
+
+ } else {
+
+ # Get the variable index.
+ if (first_rec == YES) {
+ call pt_kid (column, Memc[name], element)
+ field = pt_kstati (key, Memc[name], KY_INDEX)
+ if (field <= 0)
+ break
+ }
+
+ # Save the offset of the beginning of the current record.
+ if (recptr == 1)
+ roffset = loffset
+
+ # Construct the data record.
+ call pt_kgfield (key, field, element, Memc[line], nchars,
+ Memc[value], first_rec, recptr, ncontinue)
+
+ # Decode the selected fields.
+ if (Memc[line+nchars-2] != KY_CHAR_CONT) {
+
+ # Select the appropriate column, get its datatype and
+ # allocate the appropriate space.
+
+ if (first_rec == YES) {
+ element = pt_kstati (key, column, KY_ELEMENT)
+ if (IS_INDEFI(element))
+ break
+ coltype = pt_kstati (key, column, KY_DATATYPE)
+ if (IS_INDEFI(coltype))
+ break
+ colwidth = pt_kstati (key, column, KY_LENGTH)
+ if (coltype == TY_CHAR)
+ bufwidth = colwidth + 1
+ else
+ bufwidth = 1
+ }
+
+ # Reallocate buffer space if necessary.
+ if (record >= szbuf) {
+ szbuf = szbuf + BUFSIZE
+ if (coltype == TY_CHAR)
+ call realloc (colptr, szbuf * bufwidth, TY_CHAR)
+ else
+ call realloc (colptr, szbuf, coltype)
+ call realloc (colindex, szbuf, TY_INT)
+ call realloc (recmap, szbuf, TY_INT)
+ }
+
+ # Decode the selected column.
+ record = record + 1
+ Memi[colindex+record-1] = 1 + (record - 1) * bufwidth
+ Memi[recmap+record-1] = roffset
+ call pt_gsrt (Memc[value], colptr, coltype, bufwidth,
+ record)
+ first_rec = NO
+
+ # Reinitialize the record read.
+ ncontinue = 0
+ recptr = 1
+ }
+ }
+
+ }
+
+ # Cleanup.
+ call sfree (sp)
+ return (record)
+end
+
+
+# PT_KGFIELD -- Fetch a single fields from the input file.
+
+procedure pt_kgfield (key, field, element, line, nchars, value, first_rec,
+ recptr, ncontinue)
+
+pointer key # pointer to record structure
+int field # field to be fetched
+int element # field array element
+char line[ARB] # input line
+int nchars # length of line array
+char value[ARB] # the field value
+int first_rec # first record
+int recptr # line per record index
+int ncontinue # number of unique lines per record
+
+int len, i, cip, nper_line, nokeys, nckeys, nkeys
+
+begin
+ # Fetch the value if it is a #K parameter as this will already
+ # be sorted in the key structure.
+
+ if ((recptr == 1) && (field <= KY_NPKEYS(key))) {
+ len = Memi[KY_KINDICES(key)+field-1]
+ call amovc (Memc[Memi[KY_PTRS(key)+field-1]], value, len)
+ value[len+1] = EOS
+ }
+
+ # The number of header columns defined by #K at the beginning of
+ # the file is nokeys.
+ if (recptr == 1)
+ nokeys = KY_NPKEYS(key)
+
+ # Increment the continuation statement counter or reset to 0.
+ if (line[nchars-2] == '*')
+ ncontinue = ncontinue + 1
+ else
+ ncontinue = 0
+
+ # Fill in the record.
+ cip = 1
+ if (ncontinue < 1) {
+
+ nper_line = Memi[KY_NPLINE(key)+recptr-1]
+ nkeys = nokeys + nper_line
+ call amovki (int(1), Memi[KY_NELEMS(key)+nokeys], nper_line)
+
+ do i = nokeys + 1, nkeys {
+ len = Memi[KY_KINDICES(key)+i-1]
+ if (i == field) {
+ call amovc (line[cip], value, len)
+ value[len+1] = EOS
+ }
+ cip = cip + len
+ }
+
+ recptr = recptr + 1
+ nokeys = nkeys
+
+ } else if (ncontinue == 1) {
+
+ nckeys = nokeys + 1
+ nkeys = nokeys + Memi[KY_NPLINE(key)+recptr-1]
+
+ if (first_rec == YES) {
+ Memi[KY_NCONTINUE(key)+recptr-1] = KY_NLINES
+ do i = nckeys, nkeys
+ call malloc (Memi[KY_PTRS(key)+i-1], KY_NLINES *
+ Memi[KY_KINDICES(key)+i-1], TY_CHAR)
+ }
+
+ do i = nckeys, nkeys {
+ len = Memi[KY_KINDICES(key)+i-1]
+ if ((i == field) && (element == 1)) {
+ call amovc (line[cip], value, len)
+ value[len+1] = EOS
+ }
+ cip = cip + len
+ }
+
+ nokeys = nkeys
+ recptr = recptr + 1
+
+ } else {
+
+ if (ncontinue > Memi[KY_NCONTINUE(key)+recptr-2]) {
+ Memi[KY_NCONTINUE(key)+recptr-2] =
+ Memi[KY_NCONTINUE(key)+recptr-2] + KY_NLINES
+ do i = nckeys, nokeys
+ call realloc (Memi[KY_PTRS(key)+i-1],
+ Memi[KY_NCONTINUE(key)+recptr-2] *
+ Memi[KY_KINDICES(key)+i-1], TY_CHAR)
+ }
+
+ do i = nckeys, nkeys {
+ len = Memi[KY_KINDICES(key)+i-1]
+ if ((i == field) && (element == ncontinue)) {
+ call amovc (line[cip], value, len)
+ value[len+1] = EOS
+ }
+ Memi[KY_NELEMS(key)+i-1] = ncontinue
+ cip = cip + len
+ }
+ }
+end
+
+
+# PT_COLSORT -- Sort the column.
+
+procedure pt_colsort (colptr, colindex, nrecs, coltype)
+
+pointer colptr # array of column pointers
+int colindex[ARB] # column indices
+int nrecs # number of records
+int coltype # column type
+
+begin
+ # Sort the column.
+ switch (coltype) {
+ case TY_INT:
+ call pt_qsorti (Memi[colptr], colindex, colindex, nrecs)
+ case TY_REAL:
+ call pt_qsortr (Memr[colptr], colindex, colindex, nrecs)
+ case TY_CHAR:
+ call strsrt (colindex, Memc[colptr], nrecs)
+ case TY_BOOL:
+ call pt_qsortb (Memb[colptr], colindex, colindex, nrecs)
+ }
+end
+
+
+# PT_REORDER -- Reorder the input file and write it to the output file.
+
+procedure pt_reorder (tp_in, tp_out, recmap, colindex, nrecs)
+
+int tp_in # input table file descriptor
+int tp_out # output file descriptor
+int recmap[ARB] # record strucuture map
+int colindex[ARB] # column index
+int nrecs # number of records
+
+int i
+long lptr
+pointer sp, line
+
+begin
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+
+ do i = 1, nrecs {
+ lptr = recmap[colindex[i]]
+ call seek (tp_in, lptr)
+ call pt_rwrecord (tp_in, tp_out, Memc[line])
+ }
+
+ call sfree (sp)
+end
+
+
+# PT_GSRT -- Decode the column to be sorted.
+
+procedure pt_gsrt (value, colptr, coltype, colwidth, record)
+
+char value[ARB] # value to be decoded
+pointer colptr # pointer to the decode column
+int coltype # the data type of the sort column
+int colwidth # width of the column
+int record # the current record number
+
+int ip
+int ctoi(), ctor(), ctowrd()
+
+begin
+ # Decode the output value.
+ ip = 1
+ switch (coltype) {
+ case TY_INT:
+ if (ctoi (value, ip, Memi[colptr+record-1]) <= 0)
+ Memi[colptr+record-1] = INDEFI
+ case TY_REAL:
+ if (ctor (value, ip, Memr[colptr+record-1]) <= 0)
+ Memr[colptr+record-1] = INDEFR
+ case TY_BOOL:
+ while (IS_WHITE(value[ip]))
+ ip = ip + 1
+ switch (value[ip]) {
+ case 'Y', 'y':
+ Memb[colptr+record-1] = true
+ case 'N', 'n':
+ Memb[colptr+record-1] = false
+ default:
+ Memb[colptr+record-1] = false
+ }
+ case TY_CHAR:
+ if (ctowrd (value, ip, Memc[colptr+(record-1)*colwidth],
+ colwidth) <= 0)
+ Memc[colptr+(record-1)*colwidth] = EOS
+ default:
+ ;
+ }
+end
+
+
+# PT_FLIPI -- Filp an integer array in place.
+
+procedure pt_flipi (a, npix)
+
+int a[ARB] # array to be flipped
+int npix # number of pixels
+
+int i, nhalf, ntotal, itemp
+
+begin
+ nhalf = npix / 2
+ ntotal = npix + 1
+ do i = 1, nhalf {
+ itemp = a[i]
+ a[i] = a[ntotal-i]
+ a[ntotal-i] = itemp
+ }
+end
+
+
+# PT_RWRECORD -- Read a text record and write it out to the output file.
+
+procedure pt_rwrecord (tp_in, tp_out, line)
+
+int tp_in # input file descriptor
+int tp_out # output file descriptor
+char line[ARB] # line buffer
+
+int nchars
+int getline()
+
+begin
+ nchars = getline (tp_in, line)
+ while (nchars != EOF) {
+ call putline (tp_out, line)
+ if (line[nchars-1] != KY_CHAR_CONT)
+ break
+ nchars = getline (tp_in, line)
+ }
+end
diff --git a/noao/digiphot/ptools/txtools/ptxcalc.x b/noao/digiphot/ptools/txtools/ptxcalc.x
new file mode 100644
index 00000000..5e3d07ac
--- /dev/null
+++ b/noao/digiphot/ptools/txtools/ptxcalc.x
@@ -0,0 +1,255 @@
+include <ctype.h>
+include <error.h>
+include <evexpr.h>
+include "../../lib/ptkeysdef.h"
+
+define LEN_LONGLINE 10
+
+# PT_XCALC -- Edit a field in a record using a value expression and a
+# a selection expression.
+
+int procedure pt_xcalc (tp_in, tp_out, field, value, expr)
+
+int tp_in # the input text file descriptor
+int tp_out # the output text file descriptor
+char field[ARB] # field to be edited
+char value[ARB] # the new value expression
+char expr[ARB] # the expression to be evaluated
+
+bool oexpr
+int first_rec, nunique, uunique, funique, fieldno, fieldtype, fieldlen
+int elem, record, editall, ncontinue, recptr, nchars, buflen, lenrecord
+int offset, fieldptr
+pointer key, lline, o, v, sp, line, name, newvalue, fmtstr
+
+bool streq()
+extern pt_getop()
+int getline(), strncmp(), pt_kstati(), pt_fmkrec()
+pointer evexpr(), locpr()
+errchk evexpr(), locpr(), pt_getop()
+
+begin
+ # Get some working space.
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+ call salloc (name, SZ_FNAME, TY_CHAR)
+ call salloc (newvalue, SZ_FNAME, TY_CHAR)
+ call salloc (fmtstr, SZ_FNAME, TY_CHAR)
+
+ # Initialize keyword structure.
+ call pt_kyinit (key)
+
+ # Initialize the file read.
+ first_rec = YES
+ nunique = 0
+ uunique = 0
+ funique = 0
+ record = 0
+
+ # Initialize the buffers.
+ buflen = LEN_LONGLINE * SZ_LINE
+ call malloc (lline, buflen, TY_CHAR)
+
+ # Initilize the record read.
+ ncontinue = 0
+ recptr = 1
+ fieldptr = 0
+
+ # Initialize the expression decoding.
+ o = NULL
+ if (streq (expr, "yes") || streq (expr, "YES"))
+ editall = YES
+ else
+ editall = NO
+ v = NULL
+
+ # Loop over the text file records.
+ repeat {
+
+ # Read in a line of the text file.
+ nchars = getline (tp_in, Memc[line])
+ if (nchars == EOF)
+ break
+
+ # Determine the type of record.
+ if (Memc[line] == KY_CHAR_POUND) {
+
+ if (strncmp (Memc[line], KY_CHAR_KEYWORD, KY_LEN_STR) == 0) {
+ call pt_kyadd (key, Memc[line], nchars)
+ call putline (tp_out, Memc[line])
+ } else if (strncmp (Memc[line], KY_CHAR_NAME,
+ KY_LEN_STR) == 0) {
+ nunique = nunique + 1
+ call pt_kname (key, Memc[line], nchars, nunique)
+ call putline (tp_out, Memc[line])
+ } else if (strncmp (Memc[line], KY_CHAR_UNITS,
+ KY_LEN_STR) == 0) {
+ uunique = uunique + 1
+ call pt_knunits (key, Memc[line], nchars, uunique)
+ call putline (tp_out, Memc[line])
+ } else if (strncmp (Memc[line], KY_CHAR_FORMAT,
+ KY_LEN_STR) == 0) {
+ funique = funique + 1
+ call pt_knformats (key, Memc[line], nchars, funique)
+ call putline (tp_out, Memc[line])
+ } else {
+ # skip lines beginning with # sign
+ call putline (tp_out, Memc[line])
+ }
+
+ } else if (Memc[line] == KY_CHAR_NEWLINE) {
+ # skip blank lines
+ call putline (tp_out, Memc[line])
+
+ } else {
+
+ # Set the record size and set the column to be altered.
+ if (recptr == 1) {
+ lenrecord = nchars
+ if (first_rec == YES) {
+ call pt_kid (field, Memc[name], elem)
+ fieldno = pt_kstati (key, Memc[name], KY_INDEX)
+ if (fieldno <= 0) {
+ call eprintf (
+ "Cannot find field %s in input file\n")
+ call pargstr (Memc[name])
+ break
+ }
+ fieldtype = pt_kstati (key, Memc[name], KY_DATATYPE)
+ if (fieldtype != TY_INT && fieldtype != TY_REAL) {
+ call eprintf ("Field %s is not numeric\n")
+ call pargstr (Memc[name])
+ break
+ }
+ fieldlen = pt_kstati (key, Memc[name], KY_LENGTH)
+ call pt_kstats (key, Memc[name], KY_FMTSTR,
+ Memc[fmtstr], SZ_FNAME)
+ }
+ } else
+ lenrecord = lenrecord + nchars
+
+ # Build the record.
+ offset = pt_fmkrec (key, fieldno, elem, Memc[line],
+ nchars, first_rec, recptr, ncontinue)
+ if (offset > 0)
+ fieldptr = lenrecord - nchars + offset
+
+ # Reallocate the temporary record space if necessary.
+ if (lenrecord > buflen) {
+ buflen = buflen + SZ_LINE
+ call realloc (lline, buflen, TY_CHAR)
+ }
+
+ # Store the record.
+ call amovc (Memc[line], Memc[lline+lenrecord-nchars], nchars)
+ Memc[lline+lenrecord] = EOS
+
+ # Do the record bookkeeping.
+ if (Memc[line+nchars-2] != KY_CHAR_CONT) {
+
+ # Evaluate the value and selection expression.
+ iferr {
+
+ if (editall == NO) {
+ call pt_apset (key)
+ o = evexpr (expr, locpr (pt_getop), 0)
+ if (O_TYPE(o) != TY_BOOL)
+ call error (0,
+ "Selection expression must be a boolean")
+ oexpr = O_VALB(o)
+ } else
+ oexpr = true
+
+ if (oexpr) {
+ call pt_apset (key)
+ v = evexpr (value, locpr (pt_getop), 0)
+ switch (fieldtype) {
+ case TY_BOOL:
+ if (O_TYPE(v) != TY_BOOL) {
+ call error (0,
+ "Value must be a boolean expression")
+ } else if (fieldptr > 0) {
+ call sprintf (Memc[newvalue], fieldlen,
+ Memc[fmtstr])
+ call pargb (O_VALB(v))
+ call amovc (Memc[newvalue],
+ Memc[lline+fieldptr-1], fieldlen)
+ }
+ case TY_INT:
+ if (O_TYPE(v) != TY_INT) {
+ call error (0,
+ "Value must be an integer expression")
+ } else if (fieldptr > 0) {
+ call sprintf (Memc[newvalue], fieldlen,
+ Memc[fmtstr])
+ call pargi (O_VALI(v))
+ call amovc (Memc[newvalue],
+ Memc[lline+fieldptr-1], fieldlen)
+ }
+ case TY_REAL:
+ if (O_TYPE(v) != TY_REAL) {
+ call error (0,
+ "Value must be a real expression")
+ } else if (fieldptr > 0) {
+ call sprintf (Memc[newvalue], fieldlen,
+ Memc[fmtstr])
+ call pargr (O_VALR(v))
+ call amovc (Memc[newvalue],
+ Memc[lline+fieldptr-1], fieldlen)
+ }
+ case TY_CHAR:
+ if (O_TYPE(v) != TY_CHAR) {
+ call error (0,
+ "Value must be a string expression")
+ } else if (fieldptr > 0) {
+ call sprintf (Memc[newvalue], fieldlen,
+ Memc[fmtstr])
+ call pargstr (O_VALC(v))
+ call amovc (Memc[newvalue],
+ Memc[lline+fieldptr-1], fieldlen)
+ }
+ default:
+ call error (0,
+ "Value expression is undefined")
+ }
+ }
+
+ } then {
+ call erract (EA_WARN)
+ call error (0,
+ "Error evaluating the value expression")
+ }
+
+ # Write out the record.
+ call putline (tp_out, Memc[lline])
+
+ # Increment the record counter.
+ record = record + 1
+ first_rec = NO
+
+ # Reinitialize the record read.
+ ncontinue = 0
+ recptr = 1
+ fieldptr = 0
+ if (o != NULL) {
+ call xev_freeop (o)
+ call mfree (o, TY_STRUCT)
+ }
+ o = NULL
+ if (v != NULL) {
+ call xev_freeop (v)
+ call mfree (v, TY_STRUCT)
+ }
+ v = NULL
+ }
+ }
+
+ }
+
+ # Cleanup.
+ call mfree (lline, TY_CHAR)
+ call sfree (sp)
+ call pt_kyfree (key)
+
+ return (record)
+end
diff --git a/noao/digiphot/ptools/txtools/ptxdump.x b/noao/digiphot/ptools/txtools/ptxdump.x
new file mode 100644
index 00000000..5d98f1e3
--- /dev/null
+++ b/noao/digiphot/ptools/txtools/ptxdump.x
@@ -0,0 +1,421 @@
+include <fset.h>
+include <error.h>
+include <evexpr.h>
+include "../../lib/ptkeysdef.h"
+
+# PT_XDUMP -- Procedure to select records from a text file in apphot/daophot
+# format. This procedure reads through an apphot/daophot output file line by
+# line. The lines preceded by #K define the task parameters. These are
+# fields which do not often change during the execution of an apphot/daophot
+# task. The lines beginning with #N describe the fields in the output
+# record which change for each star. The lines beginning with #U describe
+# the units of each field, while those beginning with #F describe the format
+# of each field. Blank lines and lines beginning with # are ignored.
+
+procedure pt_xdump (fd, fields, expr, headers, parameters)
+
+int fd # text file descriptor
+char fields[ARB] # fields to be output
+char expr[ARB] # boolean expression to be evaluated
+int headers # format the output file ?
+int parameters # dump the parameters ?
+
+bool oexpr
+int nchars, nunique, uunique, funique, ncontinue, first_rec, recptr
+int nselect, szbuf, nmove, printall
+pointer sp, line, key, outline, o
+
+bool streq()
+extern pt_getop()
+int fstati(), getline(), strncmp(), pt_kszselbuf, pt_fmt(), pt_ffmt()
+pointer pt_choose(), evexpr(), locpr()
+errchk evexpr (), pt_getop()
+
+begin
+ # If the output has been redirected do not flush on a newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Allocate temporary space and space for the keyword structure.
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+ call pt_kyinit (key)
+
+ # Initialize counters.
+ nunique = 0
+ uunique = 0
+ funique = 0
+
+ # Setup the record counters. First_rec is set to NO after the first
+ # record is read. A record usually consists of several lines of text.
+ # A '\' in column 80 indicats that the current line is a part of
+ # the previous record. If there is a blank in column 80 the current
+ # line terminates the current record. In some cases the fields of a
+ # record may have more than one value, for example the magnitude field.
+ # These lines are marked by a '*\' in columns 79 and 80 respectively.
+
+ # The variable first_rec is set to NO after the first record is read.
+ # The variable recptr maintains a counter of the number of unique
+ # lines there are in a given record while ncontinue maintains a count
+ # of the number of times a given portion of the record is repeated.
+
+ # Initialize the record reading.
+ outline = NULL
+ first_rec = YES
+ recptr = 1
+ ncontinue = 0
+
+ # Initialize the expression decoding.
+ o = NULL
+ if (streq (expr, "yes")) {
+ oexpr = true
+ printall = YES
+ } else {
+ oexpr = false
+ printall = NO
+ }
+
+ # Loop over the text file records.
+ nchars = getline (fd, Memc[line])
+ while (nchars != EOF) {
+
+ # Determine the type of record. Add keywords to the database.
+ if (Memc[line] == KY_CHAR_POUND) {
+
+ if (strncmp (Memc[line], KY_CHAR_KEYWORD, KY_LEN_STR) == 0) {
+ call pt_kyadd (key, Memc[line], nchars)
+ if (headers == YES && parameters == YES)
+ call putline (STDOUT, Memc[line])
+ } else if (strncmp (Memc[line], KY_CHAR_NAME,
+ KY_LEN_STR) == 0) {
+ nunique = nunique + 1
+ call pt_kname (key, Memc[line], nchars, nunique)
+ } else if (strncmp (Memc[line], KY_CHAR_UNITS,
+ KY_LEN_STR) == 0) {
+ uunique = uunique + 1
+ call pt_knunits (key, Memc[line], nchars, uunique)
+ } else if (strncmp (Memc[line], KY_CHAR_FORMAT,
+ KY_LEN_STR) == 0) {
+ funique = funique + 1
+ call pt_knformats (key, Memc[line], nchars, funique)
+ } else if (headers == YES && parameters == YES) {
+ if (nunique == 0 || nunique != uunique || nunique !=
+ funique)
+ call putline (STDOUT, Memc[line])
+ }
+
+ } else if (Memc[line] == KY_CHAR_NEWLINE) {
+ # Skip lines beginning with a newline
+
+ } else {
+
+ # Construct the record. This routine is called repeatedly
+ # until a record without the continuation character is
+ # encountered.
+
+ call pt_mkrec (key, Memc[line], nchars, first_rec, recptr,
+ ncontinue)
+
+ # Construct the output record when there is no terminating
+ # continuation char.
+ if (Memc[line+nchars-2] != KY_CHAR_CONT) {
+
+ # Select the appropriate records and compute the size of
+ # the output buffer. This routine only needs to be called
+ # once.
+
+ if (outline == NULL) {
+ nselect = pt_choose (key, fields)
+ if (nselect <= 0)
+ break
+ szbuf = pt_kszselbuf (key)
+ call malloc (outline, szbuf, TY_CHAR)
+ } else
+ Memc[outline] = EOS
+
+ # Evaluate the expression.
+ iferr {
+ if (printall == NO) {
+ call pt_apset (key)
+ o = evexpr (expr, locpr (pt_getop), 0)
+ if (O_TYPE(o) != TY_BOOL)
+ call error (0, "Expression must be a boolean")
+ oexpr = O_VALB(o)
+ }
+ } then {
+ call erract (EA_WARN)
+ call error (0, "Error evaluating selection expression")
+ }
+
+ if (first_rec == YES && headers == YES) {
+ call pt_fnstr (key, Memc[outline], szbuf)
+ call putline (STDOUT, Memc[outline])
+ call pt_fustr (key, Memc[outline], szbuf)
+ call putline (STDOUT, Memc[outline])
+ call pt_ffstr (key, Memc[outline], szbuf)
+ call putline (STDOUT, Memc[outline])
+ call putline (STDOUT, "#\n")
+ }
+
+ # Construct the output record.
+ if (oexpr) {
+ if (headers == YES)
+ nmove = pt_fmt (key, Memc[outline], szbuf)
+ else
+ nmove = pt_ffmt (key, Memc[outline], szbuf)
+ if (nmove > 0)
+ call putline (STDOUT, Memc[outline])
+ }
+
+ # Get ready for next record.
+ first_rec = NO
+ recptr = 1
+ ncontinue = 0
+ if (o != NULL) {
+ call xev_freeop (o)
+ call mfree (o, TY_STRUCT)
+ }
+ }
+ }
+
+ # Read the next line.
+ nchars = getline (fd, Memc[line])
+ }
+
+ # Free space.
+ call pt_kyfree (key)
+ if (outline != NULL)
+ call mfree (outline, TY_CHAR)
+ call sfree (sp)
+end
+
+
+# PT_FMT -- Procedure to format an apphot/daophot output record.
+
+int procedure pt_fmt (key, line, szbuf)
+
+pointer key # pointer to keys strucuture
+char line[ARB] # output line
+int szbuf # maximum buffer size
+
+char blank
+int i, op, kip, nk, index, elem, maxch
+data blank /' '/
+
+begin
+ # Add leading three blanks.
+ call strcpy (" ", line[1], 3)
+
+ # Move records.
+ op = 4
+ do i = 1, KY_NSELECT(key) {
+
+ # Find the key.
+ index = Memi[KY_SELECT(key)+i-1]
+ elem = Memi[KY_ELEM_SELECT(key)+i-1]
+ maxch = Memi[KY_LEN_SELECT(key)+i-1]
+ kip = Memi[KY_PTRS(key)+index-1] + (elem - 1) * maxch
+
+ # Trim leading whitespace.
+ for (nk = 0; Memc[kip] == ' ' && nk < maxch; nk = nk + 1)
+ kip = kip + 1
+
+ # Check the buffer size.
+ if ((op + maxch) >= szbuf)
+ break
+
+ # Copy value to output buffer.
+ call amovc (Memc[kip], line[op], maxch - nk)
+ op = op + maxch - nk
+ call amovkc (blank, line[op], nk)
+ op = op + nk
+ }
+
+ line[op] = '\n'
+ line[op+1] = EOS
+ return (op)
+end
+
+
+# PT_FFMT -- Procedure to free format an apphot output record.
+
+int procedure pt_ffmt (key, line, szbuf)
+
+pointer key # pointer to keys strucuture
+char line[ARB] # output line
+int szbuf # size of the output buffer
+
+int i, op, kip, nk, index, elem, maxch
+
+begin
+ op = 1
+ do i = 1, KY_NSELECT(key) {
+
+ # Find the key.
+ index = Memi[KY_SELECT(key)+i-1]
+ elem = Memi[KY_ELEM_SELECT(key)+i-1]
+ maxch = Memi[KY_LEN_SELECT(key)+i-1]
+ kip = Memi[KY_PTRS(key)+index-1] + (elem - 1) * maxch
+
+ # Trim leading whitespace.
+ for (nk = 0; Memc[kip] == ' ' && nk < maxch; nk = nk + 1)
+ kip = kip + 1
+
+ # Trim trailing whitesapce.
+ for (nk = 0; Memc[kip+nk] != ' ' && nk < maxch; nk = nk + 1)
+ ;
+
+ # Check buffer space.
+ if ((op + nk + 2) >= szbuf)
+ break
+
+ # Copy value to output buffer.
+ call amovc (Memc[kip], line[op], nk)
+ op = op + nk
+ line[op] = ' '
+ op = op + 1
+ line[op] = ' '
+ op = op + 1
+ }
+
+ if (op > 1) {
+ line[op-2] = '\n'
+ line[op-1] = EOS
+ return (op - 2)
+ } else {
+ line[1] = EOS
+ return (0)
+ }
+end
+
+
+# PT_FNSTR -- Format an apphot/daophot selected name string.
+
+procedure pt_fnstr (key, line, maxline)
+
+pointer key # pointer to keys strucuture
+char line[ARB] # output line
+int maxline # add new line every max lines
+
+int op, nchars
+int gstrcpy()
+
+begin
+ # Add leading three characters.
+ call strcpy (KY_CHAR_NAME, line[1], KY_LEN_STR)
+
+ # Copy the selected name string.
+ op = KY_LEN_STR + 1
+ nchars = gstrcpy (Memc[KY_NAME_SELECT(key)], line[op], maxline -
+ KY_LEN_STR)
+
+ # Add the newline and EOS character.
+ op = op + nchars
+ line[op] = '\n'
+ line[op+1] = EOS
+end
+
+
+# PT_FUSTR -- Format an apphot/daophot selected units string.
+
+procedure pt_fustr (key, line, maxline)
+
+pointer key # pointer to keys strucuture
+char line[ARB] # output line
+int maxline # add new line every max lines
+
+int op, nchars
+int gstrcpy()
+
+begin
+ # Add leading three blanks.
+ op = 1
+ call strcpy (KY_CHAR_UNITS, line[op], KY_LEN_STR)
+
+ # Copy the selected name string.
+ op = KY_LEN_STR + 1
+ nchars = gstrcpy (Memc[KY_UNIT_SELECT(key)], line[op], maxline -
+ KY_LEN_STR)
+
+ # Add the newline and EOS character.
+ op = op + nchars
+ line[op] = '\n'
+ line[op+1] = EOS
+end
+
+
+# PT_FFSTR -- Format an apphot selected format string.
+
+procedure pt_ffstr (key, line, maxline)
+
+pointer key # pointer to keys strucuture
+char line[ARB] # output line
+int maxline # add new line every max lines
+
+char ctype
+int fwidth, prec, type, op, nchars
+pointer sp, format
+int pt_kyfstr(), gstrcpy()
+
+begin
+ fwidth = Memi[KY_LEN_SELECT(key)]
+ call smark (sp)
+ call salloc (format, fwidth, TY_CHAR)
+
+ # Adjust the format of the first field to correct for the three
+ # blanks.
+ call strcpy (Memc[KY_FMT_SELECT(key)], Memc[format], fwidth)
+ if (pt_kyfstr (Memc[format], fwidth, prec, type, ctype) != ERR) {
+ if (type == TY_REAL) {
+ Memc[format] = '%'
+ call sprintf (Memc[format+1], fwidth - 1, "%d.%d%c%*t")
+ call pargi (-(fwidth+KY_LEN_STR))
+ call pargi (prec)
+ call pargc (ctype)
+ call pargi (fwidth)
+ } else {
+ Memc[format] = '%'
+ call sprintf (Memc[format+1], fwidth - 1, "%d%c%*t")
+ call pargi (-(fwidth+KY_LEN_STR))
+ call pargc (ctype)
+ call pargi (fwidth)
+ }
+ call amovc (Memc[format], Memc[KY_FMT_SELECT(key)], fwidth)
+ }
+
+ # Add leading three blanks.
+ op = 1
+ call strcpy (KY_CHAR_FORMAT, line[op], KY_LEN_STR)
+
+ # Copy the selected name string.
+ op = KY_LEN_STR + 1
+ nchars = gstrcpy (Memc[KY_FMT_SELECT(key)], line[op], maxline -
+ KY_LEN_STR)
+
+ # Add the newline and EOS character.
+ op = op + nchars
+ line[op] = '\n'
+ line[op+1] = EOS
+
+ call sfree (sp)
+end
+
+
+# PT_KSZSELBUF -- Compute the buffer size required to hold the output selected
+# line.
+
+int procedure pt_kszselbuf (key)
+
+pointer key # pointer to the keyword structure
+
+int i, szbuf
+
+begin
+ szbuf = 0
+
+ do i = 1, KY_NSELECT(key)
+ szbuf = szbuf + Memi[KY_LEN_SELECT(key)+i-1] + 2
+ szbuf = szbuf + 4
+
+ return (szbuf)
+end
diff --git a/noao/digiphot/ptools/txtools/ptxselect.x b/noao/digiphot/ptools/txtools/ptxselect.x
new file mode 100644
index 00000000..77990909
--- /dev/null
+++ b/noao/digiphot/ptools/txtools/ptxselect.x
@@ -0,0 +1,160 @@
+include <ctype.h>
+include <error.h>
+include <evexpr.h>
+include "../../lib/ptkeysdef.h"
+
+define LEN_LONGLINE 10
+
+# PT_XSELECT -- Select records based on evaluating a logical expression.
+
+int procedure pt_xselect (tp_in, tp_out, expr)
+
+int tp_in # the input text file descriptor
+int tp_out # the output text file descriptor
+char expr[ARB] # the expression to be evaluated
+
+bool oexpr
+int first_rec, nunique, uunique, funique, record, printall
+int ncontinue, recptr, nchars, buflen, lenrecord
+pointer key, line, lline, o
+
+bool streq()
+extern pt_getop()
+int getline(), strncmp()
+pointer evexpr(), locpr()
+errchk evexpr(), pt_getop()
+
+begin
+ # Initialize keyword structure.
+ call pt_kyinit (key)
+
+ # Initialize the file read.
+ first_rec = YES
+ nunique = 0
+ uunique = 0
+ funique = 0
+ record = 0
+
+ # Initialize the buffers.
+ buflen = LEN_LONGLINE * SZ_LINE
+ call malloc (line, SZ_LINE, TY_CHAR)
+ call malloc (lline, buflen, TY_CHAR)
+
+ # Initilize the record read.
+ ncontinue = 0
+ recptr = 1
+
+ # Initialize the expression decoding.
+ o = NULL
+ if (streq (expr, "yes")) {
+ oexpr = true
+ printall = YES
+ } else {
+ oexpr = false
+ printall = NO
+ }
+
+ # Loop over the text file records.
+ repeat {
+
+ # Read in a line of the text file.
+ nchars = getline (tp_in, Memc[line])
+ if (nchars == EOF)
+ break
+
+ # Determine the type of record.
+ if (Memc[line] == KY_CHAR_POUND) {
+
+ if (strncmp (Memc[line], KY_CHAR_KEYWORD, KY_LEN_STR) == 0) {
+ call pt_kyadd (key, Memc[line], nchars)
+ call putline (tp_out, Memc[line])
+ } else if (strncmp (Memc[line], KY_CHAR_NAME,
+ KY_LEN_STR) == 0) {
+ nunique = nunique + 1
+ call pt_kname (key, Memc[line], nchars, nunique)
+ call putline (tp_out, Memc[line])
+ } else if (strncmp (Memc[line], KY_CHAR_UNITS,
+ KY_LEN_STR) == 0) {
+ uunique = uunique + 1
+ call pt_knunits (key, Memc[line], nchars, uunique)
+ call putline (tp_out, Memc[line])
+ } else if (strncmp (Memc[line], KY_CHAR_FORMAT,
+ KY_LEN_STR) == 0) {
+ funique = funique + 1
+ call pt_knformats (key, Memc[line], nchars, funique)
+ call putline (tp_out, Memc[line])
+ } else {
+ # skip lines beginning with # sign
+ call putline (tp_out, Memc[line])
+ }
+
+ } else if (Memc[line] == KY_CHAR_NEWLINE) {
+ # skip blank lines
+ call putline (tp_out, Memc[line])
+
+ } else {
+
+ # Reset the record size.
+ if (recptr == 1)
+ lenrecord = nchars
+ else
+ lenrecord = lenrecord + nchars
+
+ # Build the record.
+ call pt_mkrec (key, Memc[line], nchars, first_rec, recptr,
+ ncontinue)
+
+ # Reallocate the temporary record space.
+ if (lenrecord > buflen) {
+ buflen = buflen + SZ_LINE
+ call realloc (lline, buflen, TY_CHAR)
+ }
+
+ # Store the record.
+ call amovc (Memc[line], Memc[lline+lenrecord-nchars], nchars)
+ Memc[lline+lenrecord] = EOS
+
+ # Do the record bookkeeping.
+ if (Memc[line+nchars-2] != KY_CHAR_CONT) {
+
+ # Evaluate the expression.
+ iferr {
+ if (printall == NO) {
+ call pt_apset (key)
+ o = evexpr (expr, locpr (pt_getop), 0)
+ if (O_TYPE(o) != TY_BOOL)
+ call error (0, "Expression must be a boolean")
+ oexpr = O_VALB(o)
+ }
+ } then {
+ call erract (EA_WARN)
+ call error (0, "Error evaluating selection expression")
+ }
+
+ # Write out the expression.
+ if (oexpr)
+ call putline (tp_out, Memc[lline])
+
+ # Increment the record counter.
+ record = record + 1
+ first_rec = NO
+
+ # Reinitialize the record read.
+ ncontinue = 0
+ recptr = 1
+ if (o != NULL) {
+ call xev_freeop (o)
+ call mfree (o, TY_STRUCT)
+ }
+ }
+ }
+
+ }
+
+ # Cleanup.
+ call mfree (line, TY_CHAR)
+ call mfree (lline, TY_CHAR)
+ call pt_kyfree (key)
+
+ return (record)
+end
diff --git a/noao/digiphot/ptools/txtools/t_txcalc.x b/noao/digiphot/ptools/txtools/t_txcalc.x
new file mode 100644
index 00000000..2c7c39db
--- /dev/null
+++ b/noao/digiphot/ptools/txtools/t_txcalc.x
@@ -0,0 +1,65 @@
+include <fset.h>
+
+# T_TXCALC -- Edit a field in an APPHOT/DAOPHOT text data base using a
+# value expression.
+
+procedure t_txcalc ()
+
+pointer infile # the input file list
+pointer outfile # the output file list
+pointer field # pointer to the field to be edited
+pointer value # pointer to the value expression string
+
+int inlist, tp_in, tp_out, nrecs
+pointer sp
+int clpopnu(), access(), open(), fstati(), clgfil(), pt_xcalc()
+
+begin
+ # Set the standard output to flush on newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get some memory.
+ call smark (sp)
+ call salloc (infile, SZ_FNAME, TY_CHAR)
+ call salloc (outfile, SZ_FNAME, TY_CHAR)
+ call salloc (field, SZ_FNAME, TY_CHAR)
+ call salloc (value, SZ_LINE, TY_CHAR)
+
+ # Get the various task parameters.
+ inlist = clpopnu ("textfiles")
+ #outlist = clpopnu ("outfiles")
+ call clgstr ("field", Memc[field], SZ_FNAME)
+ call strupr (Memc[field])
+ call clgstr ("value", Memc[value], SZ_LINE)
+
+ while (clgfil (inlist, Memc[infile], SZ_FNAME) != EOF) {
+
+ # Open the input file.
+ if (access (Memc[infile], 0, TEXT_FILE) == YES)
+ tp_in = open (Memc[infile], READ_ONLY, TEXT_FILE)
+ else
+ call error (0, "The input file is a binary file.")
+
+ # Open an output text file.
+ call mktemp ("temp", Memc[outfile], SZ_FNAME)
+ tp_out = open (Memc[outfile], NEW_FILE, TEXT_FILE)
+
+ # Select the stars.
+ nrecs = pt_xcalc (tp_in, tp_out, Memc[field], Memc[value], "yes")
+
+ # Close up the input and output files.
+ call close (tp_in)
+ call close (tp_out)
+
+ if (nrecs <= 0) {
+ call delete (Memc[outfile])
+ } else {
+ call delete (Memc[infile])
+ call rename (Memc[outfile], Memc[infile])
+ }
+ }
+
+ call clpcls (inlist)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/ptools/txtools/t_txconcat.x b/noao/digiphot/ptools/txtools/t_txconcat.x
new file mode 100644
index 00000000..cae8354b
--- /dev/null
+++ b/noao/digiphot/ptools/txtools/t_txconcat.x
@@ -0,0 +1,128 @@
+include <fset.h>
+include <error.h>
+include "../../lib/ptkeysdef.h"
+
+# T_TXCONCAT -- Procedure to concatenate standard APPHOT and DAOPHOT text
+# output files into a single file. The task checks to see that the list
+# of input files was produced by the same task.
+
+procedure t_txconcat()
+
+int list # input file list descriptor
+int tp_in # input file descriptor
+int tp_out # output file descriptor
+
+int len_list, first_file, stat
+pointer sp, infile, outfile, task, task1, task2
+int fstati(), clpopnu(), clplen(), open(), clgfil(), strncmp()
+
+begin
+ # Set the standard output to flush on newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get some memory.
+ call smark (sp)
+ call salloc (infile, SZ_FNAME, TY_CHAR)
+ call salloc (outfile, SZ_FNAME, TY_CHAR)
+ call salloc (task, SZ_FNAME, TY_CHAR)
+ call salloc (task1, SZ_FNAME, TY_CHAR)
+ call salloc (task2, SZ_FNAME, TY_CHAR)
+
+ # Get the task parameters.
+ list = clpopnu ("textfiles")
+ len_list = clplen (list)
+ if (len_list <= 0)
+ call error (0, "Empty input file list.\n")
+ else if (len_list == 1)
+ call error (0, "Input file list has only one file.\n")
+ call clgstr ("outfile", Memc[outfile], SZ_FNAME)
+ call clgstr ("task", Memc[task], SZ_FNAME)
+
+ # Loop over the input files to check the task keyword.
+ first_file = YES
+ stat = OK
+ while (clgfil (list, Memc[infile], SZ_FNAME) != EOF) {
+ tp_in = open (Memc[infile], READ_ONLY, TEXT_FILE)
+ if (first_file == YES) {
+ call pt_gtaskname (tp_in, Memc[task], Memc[task1], SZ_FNAME)
+ if (Memc[task1] == EOS) {
+ call eprintf (
+ "File: %s is not an APPHOT/DAOPHOT text database file")
+ call pargstr (Memc[infile])
+ stat = ERR
+ }
+ first_file = NO
+ } else {
+ call pt_gtaskname (tp_in, Memc[task], Memc[task2], SZ_FNAME)
+ if (Memc[task2] == EOS) {
+ call eprintf (
+ "File: %s is not an APPHOT/DAOPHOT text database file\n")
+ call pargstr (Memc[infile])
+ stat = ERR
+ }
+ if (strncmp (Memc[task1], Memc[task2], SZ_FNAME) != 0) {
+ call eprintf (
+ "TASK keyword is not the same for all input files\n")
+ stat = ERR
+ }
+ }
+ call close (tp_in)
+ if (stat == ERR)
+ break
+ }
+ call clprew (list)
+
+ # Loop over the input text files and copy each file to the output
+ # file.
+ if (stat == OK) {
+ tp_out = open (Memc[outfile], NEW_FILE, TEXT_FILE)
+ while (clgfil (list, Memc[infile], SZ_FNAME) != EOF) {
+ tp_in = open (Memc[infile], READ_ONLY, TEXT_FILE)
+ call fcopyo (tp_in, tp_out)
+ call close (tp_in)
+ }
+ call close (tp_out)
+ }
+
+ call clpcls (list)
+ call sfree (sp)
+end
+
+
+# PT_GTASKNAME -- Fetch a task name from an APPHOT/DAOPHOT text file.
+
+procedure pt_gtaskname (tp_in, name, outname, maxch)
+
+int tp_in # input file descriptor
+char name[ARB] # task keyword
+char outname[ARB] # output task name
+int maxch # maximum number of characters
+
+int findex, lindex
+pointer sp, line
+int getline(), strncmp(), gstrmatch(), ctowrd()
+
+begin
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+
+ outname[1] = EOS
+ while (getline (tp_in, Memc[line]) != EOF) {
+ if (Memc[line] != KY_CHAR_POUND)
+ break
+ if (strncmp (Memc[line], KY_CHAR_KEYWORD, KY_LEN_STR) != 0)
+ next
+ if (gstrmatch (Memc[line], name, findex, lindex) == 0)
+ next
+ lindex = lindex + 1
+ if (ctowrd (Memc[line], lindex, outname, maxch) <= 0)
+ break
+ lindex = lindex + 1
+ if (ctowrd (Memc[line], lindex, outname, maxch) <= 0)
+ outname[1] = EOS
+ break
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/ptools/txtools/t_txdump.x b/noao/digiphot/ptools/txtools/t_txdump.x
new file mode 100644
index 00000000..8d2b332e
--- /dev/null
+++ b/noao/digiphot/ptools/txtools/t_txdump.x
@@ -0,0 +1,45 @@
+# T_TXDUMP -- Procedure to perform a relational select operation upon a set of
+# records within a text file. Our function is to select all records from the
+# input file matching some criterion, printing the listed fields on the
+# standard output. Dumping the keywords and reheadersting is optional.
+
+procedure t_txdump ()
+
+pointer textfile # list of input text files
+pointer fields # list of fields to be dumped
+pointer expr # boolean expression to be evaluated
+int headers # format the output
+int parameters # print the headers
+
+int list, fd
+pointer sp
+bool clgetb()
+int clpopnu(), clgfil(), open(), btoi()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (textfile, SZ_FNAME, TY_CHAR)
+ call salloc (fields, SZ_LINE, TY_CHAR)
+ call salloc (expr, SZ_LINE, TY_CHAR)
+
+ # Get the parameters.
+ list = clpopnu ("textfiles")
+ call clgstr ("fields", Memc[fields], SZ_LINE)
+ call strupr (Memc[fields])
+ call clgstr ("expr", Memc[expr], SZ_LINE)
+ headers = btoi (clgetb ("headers"))
+ parameters = btoi (clgetb ("parameters"))
+
+ # Select records.
+ while (clgfil (list, Memc[textfile], SZ_FNAME) != EOF) {
+ fd = open (Memc[textfile], READ_ONLY, TEXT_FILE)
+ if (Memc[fields] != EOS)
+ call pt_xdump (fd, Memc[fields], Memc[expr], headers,
+ parameters)
+ call close (fd)
+ }
+
+ call clpcls (list)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/ptools/txtools/t_txrenumber.x b/noao/digiphot/ptools/txtools/t_txrenumber.x
new file mode 100644
index 00000000..2b41d541
--- /dev/null
+++ b/noao/digiphot/ptools/txtools/t_txrenumber.x
@@ -0,0 +1,65 @@
+include <fset.h>
+
+# T_TXRENUMBER -- Procedure to renumber standard APPHOT and DAOPHOT text
+# output files. The ST TTOOLS task can be used for binary format.
+# The program assumes that there is a column labelled ID.
+
+procedure t_txrenumber ()
+
+pointer tp_in # pointer to the input table
+pointer tp_out # pointer to the output table
+pointer id # name of the id column
+
+int inlist, nrecs, idoffset
+pointer sp, infile, outfile
+int clpopnu(), clgeti(), clgfil(), access(), open(), fstati(), pt_renumber()
+
+begin
+ # Set the standard output to flush on newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get some memory.
+ call smark (sp)
+ call salloc (infile, SZ_FNAME, TY_CHAR)
+ call salloc (outfile, SZ_FNAME, TY_CHAR)
+ call salloc (id, SZ_FNAME, TY_CHAR)
+
+ # Get the various task parameters.
+ inlist = clpopnu ("textfiles")
+ idoffset = clgeti ("idoffset")
+ call clgstr ("id", Memc[id], SZ_FNAME)
+ call strlwr (Memc[id])
+
+ # Loop over the input files.
+ while (clgfil (inlist, Memc[infile], SZ_FNAME) != EOF) {
+
+ # Open the input file.
+ if (access (Memc[infile], 0, TEXT_FILE) == YES)
+ tp_in = open (Memc[infile], READ_ONLY, TEXT_FILE)
+ else
+ next
+
+ # Open an output text file.
+ call mktemp ("temp", Memc[outfile], SZ_FNAME)
+ tp_out = open (Memc[outfile], NEW_FILE, TEXT_FILE)
+
+ # Renumber the stars.
+ nrecs = pt_renumber (tp_in, tp_out, idoffset, Memc[id])
+
+ # Close up the input and output files.
+ call close (tp_in)
+ call close (tp_out)
+
+ # Rename the files.
+ if (nrecs <= 0)
+ call delete (Memc[outfile])
+ else {
+ call delete (Memc[infile])
+ call rename (Memc[outfile], Memc[infile])
+ }
+ }
+
+ call clpcls (inlist)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/ptools/txtools/t_txselect.x b/noao/digiphot/ptools/txtools/t_txselect.x
new file mode 100644
index 00000000..3dee8a51
--- /dev/null
+++ b/noao/digiphot/ptools/txtools/t_txselect.x
@@ -0,0 +1,64 @@
+include <fset.h>
+
+# T_TXSELECT -- Select records from an APPHOT file based on the value of
+# a logical expression.
+
+procedure t_txselect ()
+
+int tp_in # input file descriptor
+int tp_out # output file descriptor
+pointer expr # pointer to the expression string
+
+int inlist, outlist
+pointer sp, infile, outfile
+int clpopnu(), clplen(), access(), open(), fstati(), clgfil(), pt_xselect()
+
+begin
+ # Set the standard output to flush on newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get some memory.
+ call smark (sp)
+ call salloc (infile, SZ_FNAME, TY_CHAR)
+ call salloc (outfile, SZ_FNAME, TY_CHAR)
+ call salloc (expr, SZ_LINE, TY_CHAR)
+
+ # Get the various task parameters.
+ inlist = clpopnu ("textfiles")
+ outlist = clpopnu ("outfiles")
+ call clgstr ("expr", Memc[expr], SZ_LINE)
+
+ # Check that the input and output file lists have the
+ # same length.
+ if (clplen (inlist) != clplen (outlist))
+ call error (0,
+ "Input and output file lists are not the same length")
+
+ while ((clgfil (inlist, Memc[infile], SZ_FNAME) != EOF) &&
+ (clgfil (outlist, Memc[outfile], SZ_FNAME) != EOF)) {
+
+ # Open the input file.
+ if (access (Memc[infile], 0, TEXT_FILE) == YES)
+ tp_in = open (Memc[infile], READ_ONLY, TEXT_FILE)
+ else
+ call error (0, "The input file is a binary file.")
+
+ # Open an output text file.
+ tp_out = open (Memc[outfile], NEW_FILE, TEXT_FILE)
+
+ # Select the stars.
+ if (pt_xselect (tp_in, tp_out, Memc[expr]) <= 0) {
+ call eprintf ("File: %s is empty\n")
+ call pargstr (Memc[infile])
+ }
+
+ # Close up the input and output files.
+ call close (tp_in)
+ call close (tp_out)
+ }
+
+ call clpcls (inlist)
+ call clpcls (outlist)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/ptools/txtools/t_txsort.x b/noao/digiphot/ptools/txtools/t_txsort.x
new file mode 100644
index 00000000..4635a881
--- /dev/null
+++ b/noao/digiphot/ptools/txtools/t_txsort.x
@@ -0,0 +1,65 @@
+include <fset.h>
+
+# T_TXSORT -- Procedure to sort standard APPHOT and DAOPHOT text
+# output files. The ST TTOOLS task can be used for binary format.
+
+procedure t_txsort ()
+
+int tp_in # input file descriptor
+int tp_out # input file descriptor
+
+int inlist, ascend, nrecs
+pointer sp, infile, outfile, column
+bool clgetb()
+int clpopnu(), clgfil(), access(), btoi(), open(), fstati(), pt_sortnum()
+
+begin
+ # Set the standard output to flush on newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get some memory.
+ call smark (sp)
+ call salloc (infile, SZ_FNAME, TY_CHAR)
+ call salloc (outfile, SZ_FNAME, TY_CHAR)
+ call salloc (column, SZ_FNAME, TY_CHAR)
+
+ # Get the various task parameters.
+ inlist = clpopnu ("textfiles")
+ call clgstr ("field", Memc[column], SZ_FNAME)
+ ascend = btoi (clgetb ("ascend"))
+
+ # Check the column on which to sort.
+ call strlwr (Memc[column])
+ if (Memc[column] == EOS)
+ call error (0, "The sort column is undefined.")
+
+ while (clgfil (inlist, Memc[infile], SZ_FNAME) != EOF) {
+
+ # Open the input file.
+ if (access (Memc[infile], 0, TEXT_FILE) == YES)
+ tp_in = open (Memc[infile], READ_ONLY, TEXT_FILE)
+ else
+ call error (0, "The input file is not a text file.")
+
+ # Open an output text file.
+ call mktemp ("temp", Memc[outfile], SZ_FNAME)
+ tp_out = open (Memc[outfile], NEW_FILE, TEXT_FILE)
+
+ # Sort the stars.
+ nrecs = pt_sortnum (tp_in, tp_out, Memc[column], ascend)
+
+ # Close up the input and output files.
+ call close (tp_in)
+ call close (tp_out)
+ if (nrecs <= 0)
+ call delete (Memc[outfile])
+ else {
+ call delete (Memc[infile])
+ call rename (Memc[outfile], Memc[infile])
+ }
+ }
+
+ call clpcls (inlist)
+ call sfree (sp)
+end
diff --git a/noao/digiphot/ptools/x_ptools.x b/noao/digiphot/ptools/x_ptools.x
new file mode 100644
index 00000000..25ecc59d
--- /dev/null
+++ b/noao/digiphot/ptools/x_ptools.x
@@ -0,0 +1,11 @@
+task pconvert = t_pconvert,
+ istable = t_istable,
+ pexamine = t_pexamine,
+ tbcrename = t_tbcrename,
+ tbkeycol = t_tbkeycol,
+ txconcat = t_txconcat,
+ txcalc = t_txcalc,
+ txdump = t_txdump,
+ txrenumber = t_txrenumber,
+ txselect = t_txselect,
+ txsort = t_txsort
diff --git a/noao/digiphot/ptools/xyplot.par b/noao/digiphot/ptools/xyplot.par
new file mode 100644
index 00000000..3ae725b0
--- /dev/null
+++ b/noao/digiphot/ptools/xyplot.par
@@ -0,0 +1,20 @@
+# The PEXAMINE task x-y plot parameters
+
+x1,r,h,INDEF,,,Left world x-coord if not autoscaling
+x2,r,h,INDEF,,,Right world x-coord if not autoscaling
+y1,r,h,INDEF,,,Lower world y-coord if not autoscaling
+y2,r,h,INDEF,,,Upper world y-coord if not autoscaling
+marker,s,h,"box","point|box|plus|cross|circle|diamond|hline|vline",,Marker type
+szmarker,r,h,1.0,0.0,,Marker size
+logx,b,h,no,,,Log scale the x axis?
+logy,b,h,no,,,Log scale the y axis?
+box,b,h,yes,,,Draw box around periphery of window?
+ticklabels,b,h,yes,,,Label tick marks?
+majrx,i,h,5,,,Number of major divisions along x axis
+minrx,i,h,5,,,Number of minor divisions along x axis
+majry,i,h,5,,,Number of major divisions along y axis
+minry,i,h,5,,,Number of minor divisions along y axis
+round,b,h,no,,,Round axes to nice values?
+fill,b,h,yes,,,Fill viewport vs enforce unity aspect ratio?
+grid,b,h,no,,,Draw grid lines at major tick marks?
+banner,b,h,yes,,,Standard banner?