aboutsummaryrefslogtreecommitdiff
path: root/sys/qpoe/zzdebug.x
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
commitfa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch)
treebdda434976bc09c864f2e4fa6f16ba1952b1e555 /sys/qpoe/zzdebug.x
downloadiraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz
Initial commit
Diffstat (limited to 'sys/qpoe/zzdebug.x')
-rw-r--r--sys/qpoe/zzdebug.x1696
1 files changed, 1696 insertions, 0 deletions
diff --git a/sys/qpoe/zzdebug.x b/sys/qpoe/zzdebug.x
new file mode 100644
index 00000000..5ca2de42
--- /dev/null
+++ b/sys/qpoe/zzdebug.x
@@ -0,0 +1,1696 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <ctype.h>
+include <imhdr.h>
+include <qpexset.h>
+include <qpioset.h>
+include <qpset.h>
+include <gset.h>
+include "qpoe.h"
+include "qpex.h"
+include "qpio.h"
+
+# ZZDEBUG -- Debug routines for the QPOE package.
+
+task parsei = t_parsei, # parse integer range list
+ parser = t_parser, # parse floating range list
+ qpparse = t_qpparse, # test qp_parse
+ tokens = t_tokens, # test get token, macro replacement
+ comp = t_comp, # test QPEX compile
+ expand = t_expand, # perform macro expansion on text
+ recio = t_recio, # test general record i/o
+ newcopy = t_newcopy, # test inheritance
+ syms = t_syms, # dump symbol table
+ hlist = t_hlist, # list file header
+ dumpevl = t_dumpevl, # dump event list descriptor
+ mkpoe = t_mkpoe, # convert CFA poefile to QPOE poefile
+ testpoe = t_testpoe, # make a test QPOE file
+ countpoe = t_countpoe, # count photons in regions
+ tfilter = t_tfilter, # verify time filtering
+ plotpoe = t_plotpoe, # read and plot photons
+ sum = t_sum, # sum counts in an image section
+ setwcs = t_setwcs, # store a wcs in a qpoe file
+ setmask = t_setmask, # set the default mask
+ mergei = t_mergei, # test merging of range lists
+ clear = t_clear # clear the screen
+
+define SZ_EXPR 256
+define SZ_OBUF 128000
+define SZ_TBUF 8
+define MAX_EVENTS 8192
+define SZ_RLBUF 512
+
+
+# PARSEI -- Test integer range list decoding and expression optimization.
+
+procedure t_parsei()
+
+pointer xs, xe
+char lbuf[SZ_LINE], left[SZ_TBUF], right[SZ_TBUF]
+int nranges, xlen, i1, i2, i
+
+int getline(), qpex_parsei()
+bool streq()
+
+begin
+ xlen = 0
+
+ repeat {
+ # Get next expression.
+ call printf ("parse> ")
+ call flush (STDOUT)
+ if (getline (STDIN, lbuf) == EOF)
+ break
+ else if (streq (lbuf, "bye\n"))
+ break
+
+ # Parse the expression.
+ nranges = qpex_parsei (lbuf, xs, xe, xlen)
+
+ # List the ranges.
+ do i = 1, nranges {
+ i1 = Memi[xs+i-1]
+ i2 = Memi[xe+i-1]
+
+ if (IS_LEFTI(i1))
+ call strcpy ("LEFT", left, SZ_TBUF)
+ else {
+ call sprintf (left, SZ_TBUF, "%d")
+ call pargi (i1)
+ }
+
+ if (IS_RIGHTI(i2))
+ call strcpy ("RIGHT", right, SZ_TBUF)
+ else {
+ call sprintf (right, SZ_TBUF, "%d")
+ call pargi (i2)
+ }
+
+ call printf ("%2d: %8s %8s\n")
+ call pargi (i)
+ call pargstr (left)
+ call pargstr (right)
+ }
+
+ call flush (STDOUT)
+ }
+
+ call mfree (xs, TY_INT)
+ call mfree (xe, TY_INT)
+end
+
+
+# PARSER -- Test real range list decoding and expression optimization.
+
+procedure t_parser()
+
+pointer xs, xe
+char lbuf[SZ_LINE]
+int nranges, xlen, i
+
+int getline(), qpex_parser()
+bool streq()
+
+begin
+ xlen = 0
+
+ repeat {
+ # Get next expression.
+ call printf ("parse> ")
+ call flush (STDOUT)
+ if (getline (STDIN, lbuf) == EOF)
+ break
+ else if (streq (lbuf, "bye\n"))
+ break
+
+ # Parse the expression.
+ nranges = qpex_parser (lbuf, xs, xe, xlen)
+ do i = 1, nranges {
+ call printf ("%2d: %7g %7g\n")
+ call pargi (i)
+ call pargr (Memr[xs+i-1])
+ call pargr (Memr[xe+i-1])
+ }
+ call flush (STDOUT)
+ }
+
+ call mfree (xs, TY_REAL)
+ call mfree (xe, TY_REAL)
+end
+
+
+# QPPARSE -- Test qp_parse.
+
+procedure t_qpparse()
+
+char expr[SZ_LINE]
+char root[SZ_FNAME]
+char filter[SZ_FNAME]
+
+begin
+ call clgstr ("expr", expr, SZ_LINE)
+ call qp_parse (expr, root, SZ_FNAME, filter, SZ_FNAME)
+
+ call printf ("root=`%s', filter=`%s'\n")
+ call pargstr (root)
+ call pargstr (filter)
+end
+
+
+# TOKENS -- Translate an input character stream into a stream of QPOE tokens.
+# Macro replacement is performed on the input text.
+
+procedure t_tokens()
+
+char input[SZ_FNAME], refpoe[SZ_FNAME]
+char tokbuf[SZ_FNAME], num[SZ_FNAME]
+
+pointer qp, in
+int token, junk
+int qp_gettok(), gltoc()
+pointer qp_open, qp_opentext()
+
+begin
+ input[1] = '@'
+ call clgstr ("input", input[2], SZ_FNAME-1)
+ call clgstr ("refpoe", refpoe, SZ_FNAME)
+
+ if (refpoe[1] != EOS)
+ qp = qp_open (refpoe, READ_ONLY, NULL)
+ else
+ qp = NULL
+ in = qp_opentext (qp, input)
+
+ repeat {
+ token = qp_gettok (in, tokbuf, SZ_FNAME)
+ if (token != EOF) {
+ call printf ("%10s: %s\n")
+ switch (token) {
+ case TOK_IDENTIFIER:
+ call pargstr ("IDENT")
+ case TOK_NUMBER:
+ call pargstr ("NUMBER")
+ case TOK_STRING:
+ call pargstr ("STRING")
+ case TOK_COMMAND:
+ call pargstr ("COMMAND")
+ case TOK_PLUSEQUALS:
+ call pargstr ("PLUSEQ")
+ case TOK_COLONEQUALS:
+ call pargstr ("COLONEQ")
+ default:
+ junk = gltoc (token, num, SZ_FNAME, 8)
+ call pargstr (num)
+ }
+ if (IS_PRINT(tokbuf[1]))
+ call pargstr (tokbuf)
+ else
+ call pargstr ("")
+ }
+ } until (token == EOF)
+
+ call printf ("EOF\n")
+ call flush (STDOUT)
+
+ call qp_closetext (in)
+ if (qp != NULL)
+ call qp_close (qp)
+end
+
+
+# COMP -- Compile an expression with QPEX and print out the contents of
+# the resultant descriptor, including the assembler translation of the
+# expression.
+
+procedure t_comp()
+
+int out
+pointer qp, ex
+char text[SZ_LINE]
+char output[SZ_FNAME]
+
+int open()
+bool streq()
+pointer qp_open(), qpex_open()
+
+begin
+ call clgstr ("poefile", text, SZ_LINE)
+ qp = qp_open (text, READ_ONLY, 0)
+
+ call clgstr ("output", output, SZ_FNAME)
+ if (output[1] != EOS)
+ out = open (output, APPEND, TEXT_FILE)
+ else
+ out = NULL
+
+ repeat {
+ call clgstr ("expr", text, SZ_LINE)
+ if (streq (text, "bye"))
+ break
+ else if (text[1] != EOS) {
+ ex = qpex_open (qp, text)
+ call qpex_debug (ex, STDOUT, QPEXD_SHOWALL)
+ if (out != NULL) {
+ call fprintf (out, "\f")
+ call qpex_debug (ex, out, QPEXD_SHOWALL)
+ }
+ call qpex_close (ex)
+ call flush (STDOUT)
+ }
+ }
+
+ call close (out)
+ call qp_close (qp)
+end
+
+
+# EXPAND -- Perform macro expansion on text input by the user.
+
+procedure t_expand()
+
+pointer qp, sp, ip, text, obuf
+int getline(), qp_expandtext(), strncmp(), clgeti()
+pointer qp_open()
+
+begin
+ call smark (sp)
+ call salloc (text, SZ_LINE, TY_CHAR)
+ call salloc (obuf, SZ_OBUF, TY_CHAR)
+
+ call clgstr ("poefile", Memc[text], SZ_LINE)
+ qp = qp_open (Memc[text], READ_ONLY, 0)
+ call qp_seti (qp, QPOE_DEBUGLEVEL, clgeti("debug"))
+
+ call printf ("Q> ")
+ call flush (STDOUT)
+
+ while (getline (STDIN, Memc[text]) != EOF) {
+ for (ip=text; IS_WHITE(Memc[ip]); ip=ip+1)
+ ;
+ if (strncmp (Memc[ip], "bye", 3) == 0)
+ break
+ else if (Memc[ip] != '\n') {
+ call write (STDOUT, Memc[obuf],
+ qp_expandtext (qp, Memc[text], Memc[obuf], SZ_OBUF))
+ call printf ("\n")
+ }
+
+ call printf ("Q> ")
+ call flush (STDOUT)
+ }
+
+ call qp_close (qp)
+ call sfree (sp)
+end
+
+
+# RECIO -- Test general record i/o.
+
+procedure t_recio()
+
+int i, n, nrec
+pointer sp, qp, rp, poefile, data
+int qp_read(), qp_accessf(), clgeti()
+pointer qp_open()
+
+begin
+ call smark (sp)
+ call salloc (poefile, SZ_FNAME, TY_CHAR)
+ call salloc (data, 4096 * 3, TY_STRUCT)
+
+ call clgstr ("poefile", Memc[poefile], SZ_FNAME)
+ qp = qp_open (Memc[poefile], READ_WRITE, 0)
+ call qp_seti (qp, QPOE_DEBUGLEVEL, clgeti("debug"))
+ nrec = clgeti ("nrec")
+
+ # Initialize the data array.
+ do i = 1, nrec {
+ rp = data + (i-1) * 3
+ Memr[rp] = i
+ Memi[rp+1] = i
+ Mems[P2S(rp)+4] = i*10+1
+ Mems[P2S(rp)+5] = i*10+2
+ }
+
+ if (qp_accessf (qp, "urec") == NO)
+ call qp_addf (qp, "urec", "{r,i,s,s}", 0, "User record type", 0)
+ if (qp_accessf (qp, "data") == NO)
+ call qp_addf (qp, "data", "urec", nrec, "User records", 0)
+
+ # Initialize the parameter.
+ call qp_write (qp, "data", Memi[data], nrec, 1, "urec")
+
+ call eprintf ("---------------- Full array read test:")
+ call aclri (Memi[data], nrec * 3)
+ n = qp_read (qp, "data", Memi[data], nrec, 1, "urec")
+ call eprintf (" n=%d\n"); call pargi(n)
+ do i = 1, nrec {
+ rp = data + (i-1) * 3
+ call eprintf ("%8.1f %4d %4d %4d\n")
+ call pargr (Memr[rp])
+ call pargi (Memi[rp+1])
+ call pargs (Mems[P2S(rp)+4])
+ call pargs (Mems[P2S(rp)+5])
+ }
+
+ call eprintf ("---------------- Array element read test:\n")
+ call aclri (Memi[data], nrec * 3)
+ do i = 1, nrec {
+ rp = data + (i-1) * 3
+ n = qp_read (qp, "data", Memi[rp], 1, i, "urec")
+ call eprintf ("%4d %8.1f %4d %4d %4d\n")
+ call pargi (i)
+ call pargr (Memr[rp])
+ call pargi (Memi[rp+1])
+ call pargs (Mems[P2S(rp)+4])
+ call pargs (Mems[P2S(rp)+5])
+ }
+
+ call eprintf ("---------------- Array element read test (reversed):\n")
+ call aclri (Memi[data], nrec * 3)
+ do i = nrec, 1, -1 {
+ rp = data + (i-1) * 3
+ n = qp_read (qp, "data", Memi[rp], 1, i, "urec")
+ call eprintf ("%4d %8.1f %4d %4d %4d\n")
+ call pargi (i)
+ call pargr (Memr[rp])
+ call pargi (Memi[rp+1])
+ call pargs (Mems[P2S(rp)+4])
+ call pargs (Mems[P2S(rp)+5])
+ }
+
+ call qp_close (qp)
+ call sfree (sp)
+end
+
+
+# NEWCOPY -- Test inheritance occurring during a new-copy open.
+
+procedure t_newcopy()
+
+char iname[SZ_FNAME] # input name
+char oname[SZ_FNAME] # output name
+
+pointer iqp, oqp
+pointer qp_open()
+
+begin
+ call clgstr ("input", iname, SZ_FNAME)
+ call clgstr ("output", oname, SZ_FNAME)
+
+ iqp = qp_open (iname, READ_ONLY, NULL)
+ oqp = qp_open (oname, NEW_COPY, iqp)
+
+ call printf ("iqp=%x; oqp=%x\n")
+ call pargi (iqp)
+ call pargi (oqp)
+
+ call qp_close (oqp)
+ call qp_close (iqp)
+end
+
+
+# SYMS -- Dump the symbol table of a QPOE datafile.
+
+procedure t_syms()
+
+char fname[SZ_FNAME]
+pointer qp, qp_open()
+
+begin
+ call clgstr ("fname", fname, SZ_FNAME)
+ qp = qp_open (fname, READ_ONLY, 0)
+ call qp_dsym (qp, STDOUT)
+ call qp_close (qp)
+end
+
+
+# HLIST -- List selected header parameters.
+
+procedure t_hlist()
+
+pointer qp, list, sym
+int nelem, maxelem, flags
+char datatype[SZ_DATATYPE], comment[SZ_COMMENT]
+char fname[SZ_FNAME], param[SZ_FNAME], pattern[SZ_FNAME]
+pointer qp_open(), qp_ofnlu(), qp_ofnls(), qp_gpsym()
+int qp_queryf(), qp_gnfn()
+bool clgetb()
+
+begin
+ call clgstr ("fname", fname, SZ_FNAME)
+ call clgstr ("pattern", pattern, SZ_FNAME)
+
+ qp = qp_open (fname, READ_ONLY, 0)
+ if (clgetb ("sort"))
+ list = qp_ofnls (qp, pattern)
+ else
+ list = qp_ofnlu (qp, pattern)
+
+ call printf (" PARAM DTYPE NELEM MAXEL LF OFF FLG COMMENT\n")
+ while (qp_gnfn (list, param, SZ_FNAME) != EOF) {
+ nelem = qp_queryf (qp, param, datatype, maxelem, comment, flags)
+ sym = qp_gpsym (qp, param)
+
+ call printf ("%15s %6s %5d %5d %2d%4d %3o %s\n")
+ call pargstr (param)
+ call pargstr (datatype)
+ call pargi (nelem)
+ call pargi (maxelem)
+ if (sym != NULL) {
+ call pargi (S_LFILE(sym))
+ call pargi (S_OFFSET(sym))
+ call pargi (and (flags, 777B))
+ call pargstr (comment)
+ } else {
+ call pargi (0)
+ call pargi (0)
+ call pargi (0)
+ call pargstr ("[could not find symbol (macro?)]")
+ }
+ }
+
+ call qp_cfnl (list)
+ call qp_close (qp)
+end
+
+
+# DUMPEVL -- Dump an event list descriptor.
+
+procedure t_dumpevl()
+
+pointer qp, io, dd, ev
+char poefile[SZ_FNAME], param[SZ_FNAME]
+char datatype[SZ_DATATYPE], comment[SZ_COMMENT]
+int offset, dtype, size, nelem, maxelem, flags, i, j
+pointer qp_open(), qpio_open(), qpio_stati(), coerce()
+int qp_queryf(), sizeof()
+
+begin
+ call clgstr ("poefile", poefile, SZ_FNAME)
+ qp = qp_open (poefile, READ_ONLY, NULL)
+
+ call clgstr ("eventlist", param, SZ_FNAME)
+ if (param[1] == EOS)
+ call strcpy ("events", param, SZ_FNAME)
+ io = qpio_open (qp, param, READ_ONLY)
+
+ call printf ("%s.%s:\n")
+ call pargstr (poefile)
+ call pargstr (param)
+
+ nelem = qp_queryf (qp, param, datatype, maxelem, comment, flags)
+ call printf ("dtype=%s nelem=%d maxel=%d flg=%o comment=%s\n")
+ call pargstr (datatype)
+ call pargi (nelem)
+ call pargi (maxelem)
+ call pargi (and (flags, 777B))
+ call pargstr (comment)
+
+ call printf ("%s=%dx%d ")
+ call pargstr ("blockfactor")
+ call pargi (qpio_stati(io, QPIO_XBLOCKFACTOR))
+ call pargi (qpio_stati(io, QPIO_YBLOCKFACTOR))
+ call printf ("%s=%d ")
+ call pargstr ("bucketlen")
+ call pargi (qpio_stati(io, QPIO_BUCKETLEN))
+ call printf ("%s=%d ")
+ call pargstr ("debug")
+ call pargi (qpio_stati(io, QPIO_DEBUG))
+ call printf ("%s=%d ")
+ call pargstr ("evxoff")
+ call pargi (qpio_stati(io, QPIO_EVXOFF))
+ call printf ("%s=%d ")
+ call pargstr ("evxtype")
+ call pargi (qpio_stati(io, QPIO_EVXTYPE))
+ call printf ("%s=%d ")
+ call pargstr ("evyoff")
+ call pargi (qpio_stati(io, QPIO_EVYOFF))
+ call printf ("%s=%d ")
+ call pargstr ("evytype")
+ call pargi (qpio_stati(io, QPIO_EVYTYPE))
+ call printf ("\n")
+
+ call printf ("%s=%xX ")
+ call pargstr ("ex")
+ call pargi (qpio_stati(io, QPIO_EX))
+ call printf ("%s=%d ")
+ call pargstr ("noindex")
+ call pargi (qpio_stati(io, QPIO_NOINDEX))
+ call printf ("%s=%d ")
+ call pargstr ("optbufsize")
+ call pargi (qpio_stati(io, QPIO_OPTBUFSIZE))
+ call printf ("%s=%xX ")
+ call pargstr ("pl")
+ call pargi (qpio_stati(io, QPIO_PL))
+ call printf ("%s=%d ")
+ call pargstr ("eventlen")
+ call pargi (qpio_stati(io, QPIO_EVENTLEN))
+ call printf ("%s=%d ")
+ call pargstr ("fd")
+ call pargi (qpio_stati(io, QPIO_FD))
+ call printf ("\n")
+
+ call printf ("%s=%d ")
+ call pargstr ("indexlen")
+ call pargi (qpio_stati(io, QPIO_INDEXLEN))
+ call printf ("%s=%d ")
+ call pargstr ("ixxoff")
+ call pargi (qpio_stati(io, QPIO_IXXOFF))
+ call printf ("%s=%d ")
+ call pargstr ("ixxtype")
+ call pargi (qpio_stati(io, QPIO_IXXTYPE))
+ call printf ("%s=%d ")
+ call pargstr ("ixyoff")
+ call pargi (qpio_stati(io, QPIO_IXYOFF))
+ call printf ("%s=%d ")
+ call pargstr ("ixytype")
+ call pargi (qpio_stati(io, QPIO_IXYTYPE))
+ call printf ("%s=%d ")
+ call pargstr ("lf")
+ call pargi (qpio_stati(io, QPIO_LF))
+ call printf ("%s=%xX ")
+ call pargstr ("maskp")
+ call pargi (qpio_stati(io, QPIO_MASKP))
+ call printf ("\n")
+
+ call printf ("%s=%xX ")
+ call pargstr ("maxevp")
+ call pargi (qpio_stati(io, QPIO_MAXEVP))
+ call printf ("%s=%xX ")
+ call pargstr ("minevp")
+ call pargi (qpio_stati(io, QPIO_MINEVP))
+ call printf ("%s=%d ")
+ call pargstr ("ncols")
+ call pargi (qpio_stati(io, QPIO_NCOLS))
+ call printf ("%s=%d ")
+ call pargstr ("nlines")
+ call pargi (qpio_stati(io, QPIO_NLINES))
+ call printf ("%s=%xX ")
+ call pargstr ("paramp")
+ call pargi (qpio_stati(io, QPIO_PARAMP))
+ call printf ("%s=%xX ")
+ call pargstr ("qp")
+ call pargi (qpio_stati(io, QPIO_QP))
+ call printf ("\n")
+
+ # Print domain attributes.
+ dd = IO_DD(io)
+ call printf ("Domain `%s': len=%d nfields=%d xfield=%d yfield=%d\n")
+ call pargstr (datatype)
+ call pargi (DD_STRUCTLEN(dd))
+ call pargi (DD_NFIELDS(dd))
+ call pargi (DD_XFIELD(dd))
+ call pargi (DD_YFIELD(dd))
+
+ # Print min/max evl records.
+ do j = 1, 2 {
+ if (j == 1) {
+ call printf ("minevl: ")
+ ev = qpio_stati (io, QPIO_MINEVP)
+ } else {
+ call printf ("maxevl: ")
+ ev = qpio_stati (io, QPIO_MAXEVP)
+ }
+
+ do i = 1, DD_NFIELDS(dd) {
+ offset = DD_FOFFSET(dd,i)
+ dtype = DD_FTYPE(dd,i)
+ size = sizeof(dtype)
+
+ switch (dtype) {
+ case TY_SHORT:
+ call printf (" s%d=%d")
+ call pargi (offset * size * SZB_CHAR)
+ call pargs (Mems[coerce(ev,TY_SHORT,dtype) + offset])
+ case TY_INT:
+ call printf (" i%d=%d")
+ call pargi (offset * size * SZB_CHAR)
+ call pargi (Memi[coerce(ev,TY_SHORT,dtype) + offset])
+ case TY_LONG:
+ call printf (" l%d=%d")
+ call pargi (offset * size * SZB_CHAR)
+ call pargl (Meml[coerce(ev,TY_SHORT,dtype) + offset])
+ case TY_REAL:
+ call printf (" r%d=%0.5g")
+ call pargi (offset * size * SZB_CHAR)
+ call pargr (Memr[coerce(ev,TY_SHORT,dtype) + offset])
+ case TY_DOUBLE:
+ call printf (" d%d=%0.8g")
+ call pargi (offset * size * SZB_CHAR)
+ call pargd (Memd[coerce(ev,TY_SHORT,dtype) + offset])
+ default:
+ call printf (" type=%d")
+ call pargi (dtype)
+ }
+ }
+
+ call printf ("\n")
+ }
+end
+
+
+# MKPOE -- Convert CFA poefile to QPOE poefile.
+# -------------------------
+
+# Size limiting defintions.
+define LEN_EVBUF 512 # size of output event buffer
+define LEN_CVBUF 1000 # max number of mask regions
+define SZ_KEY 20
+
+# CFA Poefile definitions.
+define SZ_EVENT SZ_OEVENT
+define SZ_IEVENT 10 # size of input event struct, chars
+define SZ_OEVENT 12 # size of output event struct, chars
+define SZ_FILEHEADER 256 # size of file header, chars
+
+# File header fields of interest.
+define O_MISSION 1 # byte offset of "mission" field
+define T_MISSION TY_SHORT # datatype of mission field
+define O_INSTRUMENT 1 # byte offset of "instrument" field
+define T_INSTRUMENT TY_SHORT # datatype of instrument field
+define O_XDIM 129 # byte offset of Xdim field
+define T_XDIM TY_SHORT # datatype of Xdim field
+define O_YDIM 131 # byte offset of Ydim field
+define T_YDIM TY_SHORT # datatype of Ydim field
+define O_PSTART 505 # byte offset of PhotonStart field
+define T_PSTART TY_LONG # datatype of PhotonStart field
+define O_PSTOP 509 # byte offset of PhotonStop field
+define T_PSTOP TY_LONG # datatype of PhotonStop field
+
+# Input event struct fields of interest.
+define O_X 1 # sky coordinates
+define T_X TY_SHORT
+define O_Y 3
+define T_Y TY_SHORT
+define O_TIME 5 # arrival time
+define T_TIME TY_DOUBLE
+define O_PHA 13 # pulse height
+define T_PHA TY_SHORT
+define O_PI 15 # energy
+define T_PI TY_SHORT
+define O_DX 17 # detector coordinates
+define T_DX TY_SHORT
+define O_DY 19
+define T_DY TY_SHORT
+
+# The event struct to be stored in the QPOE file.
+define EVTYPE "event"
+define FIELDLIST "{s:x,s:y,s,s,d,s,s}"
+
+define EV_X Mems[$1]
+define EV_Y Mems[$1+1]
+define EV_PHA Mems[$1+2]
+define EV_PI Mems[$1+3]
+define EV_TIME Memd[($1+4-1)/SZ_DOUBLE+1]
+define EV_DX Mems[$1+8]
+define EV_DY Mems[$1+9]
+
+# Define an event structure with short coordinates
+define S_FIELDLIST "{s:x,s:y,s,s,d,s,s}"
+define S_SZ_EVENT 10
+define S_EV_X Mems[$1]
+define S_EV_Y Mems[$1+1]
+define S_EV_PHA Mems[$1+2]
+define S_EV_PI Mems[$1+3]
+define S_EV_TIME Memd[($1+4-1)/SZ_DOUBLE+1]
+define S_EV_DX Mems[$1+8]
+define S_EV_DY Mems[$1+9]
+
+# Define an event structure with integer coordinates
+define I_FIELDLIST "{d,i:x,i:y,i,i,s,s}"
+define I_SZ_EVENT 14
+define I_EV_TIME Memd[($1-1)/SZ_DOUBLE+1]
+define I_EV_X Memi[($1+4-1)/SZ_INT+1]
+define I_EV_Y Memi[($1+6-1)/SZ_INT+1]
+define I_EV_DX Memi[($1+8-1)/SZ_INT+1]
+define I_EV_DY Memi[($1+10-1)/SZ_INT+1]
+define I_EV_PHA Mems[$1+12]
+define I_EV_PI Mems[$1+13]
+
+# Define an event structure with real coordinates
+define R_FIELDLIST "{d,r:x,r:y,r,r,s,s}"
+define R_SZ_EVENT 14
+define R_EV_TIME Memd[($1-1)/SZ_DOUBLE+1]
+define R_EV_X Memr[($1+4-1)/SZ_REAL+1]
+define R_EV_Y Memr[($1+6-1)/SZ_REAL+1]
+define R_EV_DX Memr[($1+8-1)/SZ_REAL+1]
+define R_EV_DY Memr[($1+10-1)/SZ_REAL+1]
+define R_EV_PHA Mems[$1+12]
+define R_EV_PI Mems[$1+13]
+
+# Define an event structure with double coordinates
+define D_FIELDLIST "{d,d:x,d:y,d,d,s,s}"
+define D_SZ_EVENT 22
+define D_EV_TIME Memd[($1-1)/SZ_DOUBLE+1]
+define D_EV_X Memd[($1+4-1)/SZ_DOUBLE+1]
+define D_EV_Y Memd[($1+8-1)/SZ_DOUBLE+1]
+define D_EV_DX Memd[($1+12-1)/SZ_DOUBLE+1]
+define D_EV_DY Memd[($1+16-1)/SZ_DOUBLE+1]
+define D_EV_PHA Mems[$1+20]
+define D_EV_PI Mems[$1+21]
+
+
+# MKPOE -- Write out a new POEFILE, taking a CFA POE file as input.
+# The input file uses big-endian format for integers, and IEEE for floats.
+# The input file must be sorted in order for the output file to be indexed.
+
+procedure t_mkpoe()
+
+char infile[SZ_FNAME] # input CFA-format poefile
+char outfile[SZ_FNAME] # output QPOE-format poefile
+
+char key[SZ_KEY]
+pointer sp, hdr, obuf, optr, ph, ev, qp, io
+int datastart, dataend, mission, instrument, now
+int debug, nphotons, naxes, axlen[2], dmin[8], dmax[8], in, op, i
+
+bool clgetb()
+double mp_getd()
+pointer qp_open(), qpio_open()
+int open(), read(), mp_geti(), clgeti(), clktime()
+
+begin
+ call smark (sp)
+ call salloc (hdr, SZ_FILEHEADER, TY_CHAR)
+ call salloc (obuf, LEN_EVBUF * SZ_OEVENT / SZ_SHORT, TY_SHORT)
+ call salloc (optr, LEN_EVBUF, TY_POINTER)
+ call salloc (ph, SZ_IEVENT, TY_CHAR)
+
+ call clgstr ("infile", infile, SZ_FNAME)
+ call clgstr ("outfile", outfile, SZ_FNAME)
+
+ # Open the input and output files. Clobber the output file if
+ # it already exists.
+
+ in = open (infile, READ_ONLY, BINARY_FILE)
+ iferr (call qp_delete (outfile))
+ ;
+ qp = qp_open (outfile, NEW_FILE, NULL)
+
+ # Set the datafile page size.
+ call qp_seti (qp, QPOE_PAGESIZE, clgeti("pagesize"))
+
+ # Set the bucket length in units of number of events.
+ call qp_seti (qp, QPOE_BUCKETLEN, clgeti("bucketlen"))
+
+ # Set the debug level.
+ debug = clgeti ("debug")
+ call qp_seti (qp, QPOE_DEBUGLEVEL, debug)
+
+ # Read and decode the input file header.
+ if (read (in, Memc[hdr], SZ_FILEHEADER) < SZ_FILEHEADER)
+ call error (1, "cannot read input file header")
+
+ naxes = 2
+ axlen[1] = mp_geti (Memc[hdr], O_XDIM, T_XDIM)
+ axlen[2] = mp_geti (Memc[hdr], O_YDIM, T_YDIM)
+ datastart = mp_geti (Memc[hdr], O_PSTART, T_PSTART)
+ dataend = mp_geti (Memc[hdr], O_PSTOP, T_PSTOP)
+ nphotons = (dataend - datastart + 1) / (SZ_IEVENT * SZB_CHAR)
+
+ mission = mp_geti (Memc[hdr], O_MISSION, T_MISSION)
+ instrument = mp_geti (Memc[hdr], O_INSTRUMENT, T_INSTRUMENT)
+
+ call eprintf ("xdim=%d, ydim=%d, datastart=%d, nphotons=%d\n")
+ call pargi (axlen[1])
+ call pargi (axlen[2])
+ call pargi (datastart)
+ call pargi (nphotons)
+
+ # Setup the QPOE file header.
+ call qp_addf (qp, "naxes", "i", 1, "number of image axes", 0)
+ call qp_puti (qp, "naxes", naxes)
+ call qp_addf (qp, "axlen", "i", 2, "length of each axis", 0)
+ call qp_write (qp, "axlen", axlen, 2, 1, "i")
+
+ now = clktime(0)
+ call qp_addf (qp, "cretime", "i", 1, "image creation time", 0)
+ call qp_puti (qp, "cretime", now)
+ call qp_addf (qp, "modtime", "i", 1, "image modify time", 0)
+ call qp_puti (qp, "modtime", now)
+ call qp_addf (qp, "limtime", "i", 1, "data min/max update time", 0)
+ call qp_puti (qp, "limtime", now)
+
+ # Invent some data min/max values for now.
+ do i = 1, 8 {
+ dmin[i] = 0
+ dmax[i] = 64
+ }
+ call qp_addf (qp, "datamin", "i", 8, "minimum pixel value", 0)
+ call qp_write (qp, "datamin", dmin, 8, 1, "i")
+ call qp_addf (qp, "datamax", "i", 8, "maximum pixel value", 0)
+ call qp_write (qp, "datamax", dmax, 8, 1, "i")
+
+ # Throw in a few miscellaneous params for testing purposes.
+ call qp_addf (qp, "mission", "s", 1, "mission type code", 0)
+ call qp_puti (qp, "mission", mission)
+ call qp_addf (qp, "instrument", "s", 1, "instrument type code", 0)
+ call qp_puti (qp, "instrument", instrument)
+
+ # Define the event structure for the QPOE output file.
+ call qp_addf (qp, EVTYPE, FIELDLIST, 1, "event record type", 0)
+
+ # Copy the event (photon) list.
+ call qp_addf (qp, "events", "event", 0, "main event list", 0)
+ io = qpio_open (qp, "events", NEW_FILE)
+ call seek (in, datastart / SZB_CHAR + 1)
+ op = 0
+
+ do i = 1, nphotons {
+ # Read next event.
+ if (read (in, Memc[ph], SZ_IEVENT) < SZ_IEVENT)
+ call error (2, "photon event list truncated")
+
+ # Copy/transform event struct (not very efficient, but this
+ # is only debug code).
+
+ ev = obuf + (op * SZ_OEVENT / SZ_SHORT)
+ Memi[optr+op] = ev
+
+ EV_TIME(ev) = mp_getd (Memc[ph], O_TIME, T_TIME)
+ EV_X(ev) = mp_geti (Memc[ph], O_X, T_X)
+ EV_Y(ev) = mp_geti (Memc[ph], O_Y, T_Y)
+ EV_PHA(ev) = mp_geti (Memc[ph], O_PHA, T_PHA)
+ EV_PI(ev) = mp_geti (Memc[ph], O_PI, T_PI)
+ EV_DX(ev) = mp_geti (Memc[ph], O_DX, T_DX)
+ EV_DY(ev) = mp_geti (Memc[ph], O_DY, T_DY)
+
+ if (debug > 4) {
+ call eprintf ("%4d %4d %4d %4d %7d %7d %g\n")
+ call pargs (EV_X(ev))
+ call pargs (EV_Y(ev))
+ call pargs (EV_DX(ev))
+ call pargs (EV_DY(ev))
+ call pargs (EV_PHA(ev))
+ call pargs (EV_PI(ev))
+ call pargd (EV_TIME(ev))
+ }
+
+ # Bump output pointer and flush output buffer when it fills.
+ op = op + 1
+ if (op >= LEN_EVBUF) {
+ call qpio_putevents (io, Memi[optr], op)
+ op = 0
+ }
+ }
+
+ # Flush any remaining buffered data.
+ if (op > 0)
+ call qpio_putevents (io, Memi[optr], op)
+
+ # Construct index.
+ if (clgetb ("mkindex")) {
+ call clgstr ("key", key, SZ_KEY)
+ call qpio_mkindex (io, key)
+ }
+
+ # Clean up.
+ call qpio_close (io)
+ call qp_close (qp)
+ call close (in)
+
+ call sfree (sp)
+end
+
+
+# MP_GETI -- Get an integer field from the raw input data.
+
+int procedure mp_geti (buf, boffset, dtype)
+
+char buf[ARB] # byte-stream data buffer
+int boffset # byte offset of desired field
+int dtype # datatype of stored field
+
+short sval
+int nbytes, ival
+int sizeof()
+
+begin
+ nbytes = sizeof(dtype) * SZB_CHAR
+
+ switch (dtype) {
+ case TY_SHORT:
+ if (BYTE_SWAP2 == YES)
+ call bswap2 (buf, boffset, sval, 1, nbytes)
+ else
+ call bytmov (buf, boffset, sval, 1, nbytes)
+ return (sval)
+ case TY_INT, TY_LONG:
+ if (BYTE_SWAP4 == YES)
+ call bswap4 (buf, boffset, ival, 1, nbytes)
+ else
+ call bytmov (buf, boffset, ival, 1, nbytes)
+ return (ival)
+ default:
+ call error (3, "bad dtype switch in mp_geti")
+ }
+end
+
+
+# MP_GETD -- Get a double field from the raw input data. We assume that both
+# the input and output are IEEE floating, hence all we are really doing here
+# is providing for arbitrarily aligned fields, and providing type conversion.
+
+double procedure mp_getd (buf, boffset, dtype)
+
+char buf[ARB] # byte-stream data buffer
+int boffset # byte offset of desired field
+int dtype # datatype of stored field
+
+double dval
+real rval
+int nbytes, half
+int sizeof()
+
+begin
+ nbytes = sizeof(dtype) * SZB_CHAR
+ half = nbytes / 2
+
+ switch (dtype) {
+ case TY_REAL:
+ if (BYTE_SWAP4 == YES)
+ call bswap4 (buf, boffset, rval, 1, nbytes)
+ else
+ call bytmov (buf, boffset, rval, 1, nbytes)
+ return (rval)
+ case TY_DOUBLE:
+ if (BYTE_SWAP4 == YES) {
+ call bswap4 (buf, boffset, dval, 1+half, half)
+ call bswap4 (buf, boffset+half, dval, 1, half)
+ } else
+ call bytmov (buf, boffset, dval, 1, nbytes)
+ return (dval)
+ default:
+ call error (3, "bad dtype switch in mp_getd")
+ }
+end
+
+
+# TESTPOE -- Make a test QPOE file, generating an artificial sequence of
+# events (for testing special cases). The event list is not sorted or
+# indexed.
+
+procedure t_testpoe()
+
+char outfile[SZ_FNAME] # output QPOE-format poefile
+
+pointer sp, ev, qp, io, evl[1]
+int nevents, naxes, axlen[2], i, datatype
+pointer qp_open(), qpio_open()
+int clgeti()
+char clgetc()
+
+begin
+ # Open the output file.
+ call clgstr ("outfile", outfile, SZ_FNAME)
+ iferr (call qp_delete (outfile))
+ ;
+ qp = qp_open (outfile, NEW_FILE, NULL)
+
+ naxes = 2
+ axlen[1] = clgeti ("ncols")
+ axlen[2] = clgeti ("nlines")
+ datatype = clgetc ("datatype")
+
+ # Setup the QPOE file header.
+ call qp_addf (qp, "naxes", "i", 1, "number of image axes", 0)
+ call qp_puti (qp, "naxes", naxes)
+ call qp_addf (qp, "axlen", "i", 2, "length of each axis", 0)
+ call qp_write (qp, "axlen", axlen, 2, 1, "i")
+
+ # Define the event structure for the QPOE output file.
+ call smark (sp)
+ switch (datatype) {
+ case 's':
+ call salloc (ev, S_SZ_EVENT / SZ_SHORT, TY_SHORT)
+ call qp_addf (qp, EVTYPE, S_FIELDLIST, 1, "event record type", 0)
+ case 'i':
+ call salloc (ev, I_SZ_EVENT / SZ_SHORT, TY_SHORT)
+ call qp_addf (qp, EVTYPE, I_FIELDLIST, 1, "event record type", 0)
+ case 'r':
+ call salloc (ev, R_SZ_EVENT / SZ_SHORT, TY_SHORT)
+ call qp_addf (qp, EVTYPE, R_FIELDLIST, 1, "event record type", 0)
+ case 'd':
+ call salloc (ev, D_SZ_EVENT / SZ_SHORT, TY_SHORT)
+ call qp_addf (qp, EVTYPE, D_FIELDLIST, 1, "event record type", 0)
+ }
+
+
+ # Copy the event (photon) list.
+ call qp_addf (qp, "events", "event", 0, "main event list", 0)
+ io = qpio_open (qp, "events", NEW_FILE)
+
+ # Generate some dummy events.
+ nevents = clgeti ("nevents")
+ evl[1] = ev
+
+ # Hack this to generate different types of test files.
+ do i = 1, nevents {
+ switch (datatype) {
+
+ case 's':
+ S_EV_TIME(ev) = 1.0D0 + double(i) / 10.0D0
+ if (mod(i,2) == 0) {
+ S_EV_X(ev) = (i - 1) * 10 + 1
+ S_EV_Y(ev) = (i - 1) * 10 + 1
+ } else {
+ S_EV_X(ev) = axlen[1] - ((i - 1) * 10 + 1)
+ S_EV_Y(ev) = axlen[2] - ((i - 1) * 10 + 1)
+ }
+ S_EV_PHA(ev) = mod (nint(i * 11.1111), 20)
+ S_EV_PI(ev) = i / 2
+ S_EV_DX(ev) = nevents - i + 1
+ S_EV_DY(ev) = nevents - i + 1
+
+ case 'i':
+ I_EV_TIME(ev) = 1.0D0 + double(i) / 10.0D0
+ if (mod(i,2) == 0) {
+ I_EV_X(ev) = (i - 1) * 10 + 1
+ I_EV_Y(ev) = (i - 1) * 10 + 1
+ } else {
+ I_EV_X(ev) = axlen[1] - ((i - 1) * 10 + 1)
+ I_EV_Y(ev) = axlen[2] - ((i - 1) * 10 + 1)
+ }
+ I_EV_PHA(ev) = mod (nint(i * 11.1111), 20)
+ I_EV_PI(ev) = i / 2
+ I_EV_DX(ev) = nevents - i + 1
+ I_EV_DY(ev) = nevents - i + 1
+
+ case 'r':
+ R_EV_TIME(ev) = 1.0D0 + double(i) / 10.0D0
+ if (mod(i,2) == 0) {
+ R_EV_X(ev) = (i - 1) * 10 + 1
+ R_EV_Y(ev) = (i - 1) * 10 + 1
+ } else {
+ R_EV_X(ev) = axlen[1] - ((i - 1) * 10 + 1)
+ R_EV_Y(ev) = axlen[2] - ((i - 1) * 10 + 1)
+ }
+ R_EV_PHA(ev) = mod (nint(i * 11.1111), 20)
+ R_EV_PI(ev) = i / 2
+ R_EV_DX(ev) = nevents - i + 1
+ R_EV_DY(ev) = nevents - i + 1
+
+ case 'd':
+ D_EV_TIME(ev) = 1.0D0 + double(i) / 10.0D0
+ if (mod(i,2) == 0) {
+ D_EV_X(ev) = (i - 1) * 10 + 1
+ D_EV_Y(ev) = (i - 1) * 10 + 1
+ } else {
+ D_EV_X(ev) = axlen[1] - ((i - 1) * 10 + 1)
+ D_EV_Y(ev) = axlen[2] - ((i - 1) * 10 + 1)
+ }
+ D_EV_PHA(ev) = mod (nint(i * 11.1111), 20)
+ D_EV_PI(ev) = i / 2
+ D_EV_DX(ev) = nevents - i + 1
+ D_EV_DY(ev) = nevents - i + 1
+
+ }
+
+ call qpio_putevents (io, evl, 1)
+ }
+
+ # Clean up.
+ call qpio_close (io)
+ call qp_close (qp)
+ call sfree (sp)
+end
+
+
+# COUNTPOE -- Count photons in regions. Whether or not there are any regions
+# depends upon whether the user specifies a region mask, or upon whether the
+# image has a default mask. If there is no mask the entire image is counted.
+# If the user specifies a filter then event attribute filtering will be
+# performed as well. Mask region values should be restricted to the range
+# 0-999.
+
+procedure t_countpoe()
+
+bool list_events
+int debug, nev, mval, m, i
+pointer sp, qp, poefile, evlist, evl, cv, ev, io
+
+bool clgetb()
+pointer qp_open(), qpio_open()
+int qpio_getevents(), clgeti()
+
+begin
+ call smark (sp)
+ call salloc (poefile, SZ_FNAME, TY_CHAR)
+ call salloc (evlist, SZ_EXPR, TY_CHAR)
+ call salloc (evl, LEN_EVBUF, TY_POINTER)
+ call salloc (cv, LEN_CVBUF, TY_INT)
+
+ call clgstr ("poefile", Memc[poefile], SZ_FNAME)
+ qp = qp_open (Memc[poefile], READ_ONLY, NULL)
+
+ debug = clgeti ("debug")
+ call qp_seti (qp, QPOE_DEBUGLEVEL, debug)
+
+ call clgstr ("eventlist", Memc[evlist], SZ_EXPR)
+ io = qpio_open (qp, Memc[evlist], READ_ONLY)
+
+ list_events = clgetb ("list_events")
+ if (list_events)
+ call printf (" EV X Y DX DY PHA PI TIME\n")
+
+ call aclri (Memi[cv], LEN_CVBUF)
+
+ # Scan the event list.
+ while (qpio_getevents (io, Memi[evl], mval, LEN_EVBUF, nev) != EOF) {
+ if (list_events) {
+ do i = 1, nev {
+ ev = Memi[evl+i-1]
+ call printf ("%4d %4d %4d %4d %4d %7d %7d %g\n")
+ call pargi (i)
+ call pargs (EV_X(ev))
+ call pargs (EV_Y(ev))
+ call pargs (EV_DX(ev))
+ call pargs (EV_DY(ev))
+ call pargs (EV_PHA(ev))
+ call pargs (EV_PI(ev))
+ call pargd (EV_TIME(ev))
+ }
+ }
+
+ m = min (LEN_CVBUF, mval)
+ Memi[cv+m] = Memi[cv+m] + nev
+ }
+
+ call qpio_close (io)
+
+ # Print the count of the number of photons in each region.
+ if (list_events)
+ call printf ("\n")
+
+ call printf ("REGION: ")
+ do i = 0, LEN_CVBUF-1
+ if (Memi[cv+i] > 0) {
+ call printf (" %6oB")
+ call pargi (i)
+ }
+ call printf ("\n")
+
+ call printf ("COUNTS: ")
+ do i = 0, LEN_CVBUF-1
+ if (Memi[cv+i] > 0) {
+ call printf (" %7d")
+ call pargi (Memi[cv+i])
+ }
+ call printf ("\n")
+
+ call qp_close (qp)
+ call sfree (sp)
+end
+
+
+# TFILTER -- Perform a brute force time filtering operation upon an event
+# list, and compare against the results of a standard QPEX time filter.
+# This is used to verify the operation of the optimized QPEX time filter.
+
+procedure t_tfilter()
+
+bool open_left, open_right, pass
+int nev1, nev2, totev, mval, nev, xlen, nranges, fd1, fd2, i, j
+pointer sp, poefile, filter, output, fname, evl, x1, y1, t1, x2, y2, t2
+pointer qp, io, ex, ev, xs, xe
+double t
+
+bool clgetb()
+int qpio_getevents(), qpex_attrld(), open()
+pointer qp_open(), qpio_open(), qpex_open()
+
+begin
+ call smark (sp)
+ call salloc (poefile, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (filter, SZ_EXPR, TY_CHAR)
+ call salloc (evl, LEN_EVBUF, TY_POINTER)
+
+ call salloc (x1, MAX_EVENTS, TY_SHORT)
+ call salloc (y1, MAX_EVENTS, TY_SHORT)
+ call salloc (t1, MAX_EVENTS, TY_DOUBLE)
+ call salloc (x2, MAX_EVENTS, TY_SHORT)
+ call salloc (y2, MAX_EVENTS, TY_SHORT)
+ call salloc (t2, MAX_EVENTS, TY_DOUBLE)
+
+ nev1 = 0
+ nev2 = 0
+ totev = 0
+
+ call clgstr ("poefile", Memc[poefile], SZ_FNAME)
+ qp = qp_open (Memc[poefile], READ_ONLY, NULL)
+ io = qpio_open (qp, "", READ_ONLY)
+
+ call clgstr ("filter", Memc[filter], SZ_EXPR)
+ ex = qpex_open (qp, Memc[filter])
+
+ call clgstr ("output", Memc[output], SZ_FNAME)
+
+ if (clgetb ("showfilter")) {
+ call qpex_debug (ex, STDOUT, QPEXD_SHOWALL)
+ call flush (STDOUT)
+ }
+
+ # Scan the event list using the given filter.
+ call printf ("scan event list using optimized filter: ")
+ call flush (STDOUT)
+
+ call qpio_seti (io, QPIO_EX, ex)
+ while (qpio_getevents (io, Memi[evl], mval, LEN_EVBUF, nev) != EOF) {
+ do i = 1, nev {
+ ev = Memi[evl+i-1]
+ Mems[x1+nev1] = EV_X(ev)
+ Mems[y1+nev1] = EV_Y(ev)
+ Memd[t1+nev1] = EV_TIME(ev)
+ nev1 = min (MAX_EVENTS, nev1 + 1)
+ }
+ }
+
+ call printf ("%d events\n")
+ call pargi (nev1)
+ xlen = 128
+ call malloc (xs, TY_DOUBLE, xlen)
+ call malloc (xe, TY_DOUBLE, xlen)
+
+ # Get the time filter as a list of ranges.
+ xs = NULL; xe = NULL; xlen = 0
+ nranges = qpex_attrld (ex, "time", xs, xe, xlen)
+ if (nranges > 0) {
+ open_left = IS_INDEF(Memd[xs])
+ open_right = IS_INDEF(Memd[xe+nranges-1])
+ } else {
+ open_left = false
+ open_right = false
+ }
+
+ # Scan the event list, applying a brute force time filter.
+ call qpio_seti (io, QPIO_EX, NULL)
+ call printf ("scan event list using brute force filter: ")
+ call flush (STDOUT)
+
+ while (qpio_getevents (io, Memi[evl], mval, LEN_EVBUF, nev) != EOF) {
+ do i = 1, nev {
+ ev = Memi[evl+i-1]
+ t = EV_TIME(ev)
+
+ # Apply the time filter.
+ if (open_left && open_right && nranges == 1)
+ pass = true
+ else {
+ pass = false
+ do j = 1, nranges {
+ if (j == 1 && open_left) {
+ if (t <= Memd[xe]) {
+ pass = true
+ break
+ }
+ } else if (j == nranges && open_right) {
+ if (t >= Memd[xs+nranges-1]) {
+ pass = true
+ break
+ }
+ } else if (t >= Memd[xs+j-1] && t <= Memd[xe+j-1]) {
+ pass = true
+ break
+ }
+ }
+ }
+
+ if (pass) {
+ Mems[x2+nev2] = EV_X(ev)
+ Mems[y2+nev2] = EV_Y(ev)
+ Memd[t2+nev2] = EV_TIME(ev)
+ nev2 = min (MAX_EVENTS, nev2 + 1)
+ }
+ }
+
+ totev = totev + nev
+ }
+
+ call printf ("%d events\n")
+ call pargi (nev2)
+ call printf ("out of a total of %d events\n")
+ call pargi (totev)
+ call flush (STDOUT)
+
+ # Dump the two event lists if an output root filename was given.
+ if (Memc[output] != EOS) {
+ call sprintf (Memc[fname], SZ_FNAME, "%s.1")
+ call pargstr (Memc[output])
+ iferr (call delete (Memc[fname]))
+ ;
+ fd1 = open (Memc[fname], NEW_FILE, TEXT_FILE)
+
+ call sprintf (Memc[fname], SZ_FNAME, "%s.2")
+ call pargstr (Memc[output])
+ iferr (call delete (Memc[fname]))
+ ;
+ fd2 = open (Memc[fname], NEW_FILE, TEXT_FILE)
+
+ do i = 1, max (nev1, nev2) {
+ if (i <= nev1) {
+ call fprintf (fd1, "%d %d %g\n")
+ call pargs (Mems[x1+i-1])
+ call pargs (Mems[y1+i-1])
+ call pargd (Memd[t1+i-1])
+ }
+ if (i <= nev2) {
+ call fprintf (fd2, "%d %d %g\n")
+ call pargs (Mems[x2+i-1])
+ call pargs (Mems[y2+i-1])
+ call pargd (Memd[t2+i-1])
+ }
+ }
+
+ call close (fd1)
+ call close (fd2)
+ }
+
+ # Compare the results of the two filters for equality.
+ pass = true
+ do i = 1, min (nev1, nev2) {
+ if (Mems[x1+i-1] != Mems[x2+i-1] || Mems[y1+i-1] != Mems[y2+i-1]) {
+ call printf ("bad compare at event %d: ")
+ call pargi (i)
+ call printf ("[%d,%d,%0.4f] != [%d,%d,%0.4f]\n")
+ call pargs (Mems[x1+i-1])
+ call pargs (Mems[y1+i-1])
+ call pargd (Memd[t1+i-1])
+ call pargs (Mems[x2+i-1])
+ call pargs (Mems[y2+i-1])
+ call pargd (Memd[t2+i-1])
+ pass = false
+ break
+ }
+ }
+
+ if (pass) {
+ call printf ("first %d events are identical\n")
+ call pargi (min (nev1, nev2))
+ }
+
+ call mfree (xs, TY_DOUBLE)
+ call mfree (xe, TY_DOUBLE)
+ call qpex_close (ex)
+ call qpio_close (io)
+ call qp_close (qp)
+
+ call sfree (sp)
+end
+
+
+# PLOTPOE -- Read and plot photons, showing the position of each photon
+# in the image matrix, according to the current coordinate system.
+
+procedure t_plotpoe()
+
+int ncols, nlines, xblock, yblock, mval, nev, i
+pointer sp, poefile, evlist, evl, xv, yv, qp, io, ev, gp
+pointer qp_open(), gopen(), qpio_open
+int clgeti(), qp_stati(), qp_geti(), qpio_getevents()
+
+begin
+ call smark (sp)
+ call salloc (poefile, SZ_FNAME, TY_CHAR)
+ call salloc (evlist, SZ_EXPR, TY_CHAR)
+ call salloc (evl, LEN_EVBUF, TY_POINTER)
+ call salloc (xv, LEN_EVBUF, TY_REAL)
+ call salloc (yv, LEN_EVBUF, TY_REAL)
+
+ call clgstr ("poefile", Memc[poefile], SZ_FNAME)
+ qp = qp_open (Memc[poefile], READ_ONLY, NULL)
+
+ call qp_seti (qp, QPOE_DEBUGLEVEL, clgeti ("debug"))
+ call qp_seti (qp, QPOE_XBLOCKFACTOR, clgeti ("xblock"))
+ call qp_seti (qp, QPOE_YBLOCKFACTOR, clgeti ("yblock"))
+
+ xblock = qp_stati (qp, QPOE_XBLOCKFACTOR)
+ yblock = qp_stati (qp, QPOE_YBLOCKFACTOR)
+ ncols = qp_geti (qp, "axlen[1]") / xblock
+ nlines = qp_geti (qp, "axlen[2]") / yblock
+
+ gp = gopen ("stdgraph", NEW_FILE, STDGRAPH)
+ call gswind (gp, 1., real(ncols), 1., real(nlines))
+ call gsetr (gp, G_ASPECT, 1.0)
+
+ call clgstr ("eventlist", Memc[evlist], SZ_EXPR)
+ io = qpio_open (qp, Memc[evlist], READ_ONLY)
+
+ if (Memc[evlist] == EOS)
+ call glabax (gp, "events", "X", "Y")
+ else
+ call glabax (gp, Memc[evlist], "X", "Y")
+
+ # Scan the event list.
+ while (qpio_getevents (io, Memi[evl], mval, LEN_EVBUF, nev) != EOF) {
+ do i = 1, nev {
+ ev = Memi[evl+i-1]
+ Memr[xv+i-1] = EV_X(ev) / xblock + 1.0
+ Memr[yv+i-1] = EV_Y(ev) / yblock + 1.0
+ }
+ call gpmark (gp, Memr[xv], Memr[yv], nev, GM_POINT, 0.0, 0.0)
+ call gflush (gp)
+ }
+
+ call qpio_close (io)
+ call gclose (gp)
+
+ call qp_close (qp)
+ call sfree (sp)
+end
+
+
+# SUM -- Sum the counts in an image section.
+
+procedure t_sum()
+
+double sum
+char image[SZ_LINE]
+int ncols, nlines, i
+pointer im, immap(), imgl2i()
+real asumi()
+
+begin
+ call clgstr ("image", image, SZ_LINE)
+ im = immap (image, READ_ONLY, 0)
+
+ ncols = IM_LEN(im,1)
+ nlines = IM_LEN(im,2)
+
+ call printf ("ncols=%d, nlines=%d, pixtype=%d\n")
+ call pargi (ncols)
+ call pargi (nlines)
+ call pargi (IM_PIXTYPE(im))
+ call flush (STDOUT)
+
+ sum = 0
+ do i = 1, nlines
+ sum = sum + asumi (Memi[imgl2i(im,i)], ncols)
+
+ call printf ("total pixels = %d, counts = %14.0f\n")
+ call pargi (ncols * nlines)
+ call pargd (sum)
+
+ call imunmap (im)
+end
+
+
+# SETWCS -- Store a wcs in a QPOE file.
+
+procedure t_setwcs()
+
+pointer qp, mw
+char text[SZ_LINE]
+pointer qp_open, mw_open
+
+begin
+ call clgstr ("poefile", text, SZ_LINE)
+ qp = qp_open (text, READ_WRITE, 0)
+
+ mw = mw_open (NULL, 2)
+ call qp_savewcs (qp, mw)
+
+ call mw_close (mw)
+ call qp_close (qp)
+end
+
+
+# SETFILT -- Set the default filter in a QPOE file.
+
+procedure t_setfilt()
+
+pointer qp
+char poefile[SZ_FNAME]
+char filter[SZ_LINE]
+pointer qp_open()
+
+begin
+ call clgstr ("poefile", poefile, SZ_FNAME)
+ qp = qp_open (poefile, READ_WRITE, 0)
+
+ call clgstr ("deffilt", filter, SZ_LINE)
+ call qp_astr (qp, "deffilt", filter, "default filter")
+
+ call qp_close (qp)
+end
+
+
+# SETMASK -- Set the default mask in a QPOE file.
+
+procedure t_setmask()
+
+pointer qp
+char poefile[SZ_FNAME]
+char mask[SZ_LINE]
+pointer qp_open()
+
+begin
+ call clgstr ("poefile", poefile, SZ_FNAME)
+ qp = qp_open (poefile, READ_WRITE, 0)
+
+ call clgstr ("defmask", mask, SZ_LINE)
+ call qp_astr (qp, "defmask", mask, "default mask")
+
+ call qp_close (qp)
+end
+
+
+# MERGEI -- Test the merge range list routine (integer version).
+# The lists may be specified either as strings, or as @file-name.
+
+procedure t_mergei()
+
+int p1, p2
+char list1[SZ_LINE], list2[SZ_LINE]
+pointer sp, rl1, rl2, op, xs, xe, ys, ye, os, oe
+int fd, ch, xlen, ylen, olen, nx, ny, nout, i
+int open(), getci(), qpex_parsei(), qp_rlmergei()
+
+begin
+ call smark (sp)
+ call salloc (rl1, SZ_RLBUF, TY_CHAR)
+ call salloc (rl2, SZ_RLBUF, TY_CHAR)
+
+ # Get the first range list.
+ call clgstr ("list1", list1, SZ_LINE)
+ if (list1[1] == '@') {
+ fd = open (list1[2], READ_ONLY, TEXT_FILE)
+ op = rl1
+ while (getci (fd, ch) != EOF) {
+ if (ch == '\n')
+ ch = ' '
+ Memc[op] = ch
+ op = op + 1
+ }
+ Memc[op] = EOS
+ } else
+ call strcpy (list1, Memc[rl1], SZ_RLBUF)
+
+ # Get the second range list.
+ call clgstr ("list2", list2, SZ_LINE)
+ if (list2[1] == '@') {
+ fd = open (list2[2], READ_ONLY, TEXT_FILE)
+ op = rl2
+ while (getci (fd, ch) != EOF) {
+ if (ch == '\n')
+ ch = ' '
+ Memc[op] = ch
+ op = op + 1
+ }
+ Memc[op] = EOS
+ } else
+ call strcpy (list2, Memc[rl2], SZ_RLBUF)
+
+ # Parse the lists.
+ xlen = 100
+ call malloc (xs, xlen, TY_INT)
+ call malloc (xe, xlen, TY_INT)
+ nx = qpex_parsei (Memc[rl1], xs, xe, xlen)
+
+ ylen = 100
+ call malloc (ys, ylen, TY_INT)
+ call malloc (ye, ylen, TY_INT)
+ ny = qpex_parsei (Memc[rl2], ys, ye, ylen)
+
+ # Merge the lists.
+ olen = 100
+ call malloc (os, olen, TY_INT)
+ call malloc (oe, olen, TY_INT)
+ nout = qp_rlmergei (os,oe,olen,
+ Memi[xs],Memi[xe],nx, Memi[ys],Memi[ye],ny)
+
+ # Print results:
+ call printf ("---- list 1 -----\n")
+ do i = 1, nx {
+ p1 = Memi[xs+i-1]
+ p2 = Memi[xe+i-1]
+ call printf ("%8d %8s : %8s\n")
+ call pargi (i)
+ if (IS_LEFTI(p1))
+ call pargstr ("left")
+ else
+ call pargi (p1)
+ if (IS_RIGHTI(p2))
+ call pargstr ("right")
+ else
+ call pargi (p2)
+ }
+
+ call printf ("---- list 2 -----\n")
+ do i = 1, ny {
+ p1 = Memi[ys+i-1]
+ p2 = Memi[ye+i-1]
+ call printf ("%8d %8s : %8s\n")
+ call pargi (i)
+ if (IS_LEFTI(p1))
+ call pargstr ("left")
+ else
+ call pargi (p1)
+ if (IS_RIGHTI(p2))
+ call pargstr ("right")
+ else
+ call pargi (p2)
+ }
+
+ call printf ("---- merged -----\n")
+ do i = 1, nout {
+ p1 = Memi[os+i-1]
+ p2 = Memi[oe+i-1]
+ call printf ("%8d %8s : %8s\n")
+ call pargi (i)
+ if (IS_LEFTI(p1))
+ call pargstr ("left")
+ else
+ call pargi (p1)
+ if (IS_RIGHTI(p2))
+ call pargstr ("right")
+ else
+ call pargi (p2)
+ }
+
+ # Free list storage.
+ call mfree (xs, TY_INT); call mfree (xe, TY_INT)
+ call mfree (ys, TY_INT); call mfree (ye, TY_INT)
+ call mfree (os, TY_INT); call mfree (oe, TY_INT)
+
+ call sfree (sp)
+end
+
+
+# CLEAR -- Clear the terminal screen.
+
+procedure t_clear()
+
+pointer tty
+pointer ttyodes()
+errchk ttyodes
+
+begin
+ # Clear the screen.
+ tty = ttyodes ("terminal")
+ call ttyclear (STDOUT, tty)
+ call ttycdes (tty)
+end