Viewing contents of file '../idllib/contrib/groupk/init_scan.pro'
;+
; NAME:
; GET_SCAN
;
; PURPOSE:
;
; This function reads in major frame(s) of the HEAO A-1 data from a
; data file into buffers. Each buffer contains a set of sequential
; major frames and may be referred to as a "scan". The number of
; sequential major frames may vary according to the number of
; sequential major frames found in the data file.
;
; CATEGORY:
; I/O
;
; CALLING SEQUENCE:
;
; Result = GET_SCAN( Move [, PICKMJF=Pickmjf, DATA=Data, NOWARN=Nowarn, LOG=Log] )
;
; INPUTS:
; Move: Buffer command to tell which buffer to retreive:
; 1 -> Get the next buffer.
; 0 -> Get the current buffer.
; -1 -> Get the previous buffer.
; If the buffer pointer is at the top of the buffer stack and
; Move = 1, then the next major frame buffer is read from the data file.
;
; INPUT KEYWORD PARAMETERS:
;
; PICKMJF: Get the major frame buffer with the major frame number
; specified by PICKMJF by searching forward. NOTE: Move must
; be set to 1 if the PICKMJF keyword is set, [long].
;
; NOWARN: Suppress printing of warning messages to screen.
;
; LOG: Output warning messages to log file.
;
; OUTPUTS:
; This function serves to both read major frames from file into buffers
; and return buffer elements to the USER through output keywords. When
; BOTH the end of file has been reached and the buffer for that file
; is empty, then this function returns 1, otherwise it returns 0.
; In other words, it returns the EOFB (end of file and buffer) status.
;
; OUTPUT KEYWORD PARAMETERS:
;
; DATA: Array of MJF data structures with dimension equal to the
; number of sequential major frames in the scan. (See DEF_MJF
; for the definition of the MJF data structure.)
;
; RESTRICTIONS:
; Data file must be in the proper IDL format as defined by the
; FMT_SRCDATA program.
;
; EXAMPLE:
; Assume we have a data file named crab.idl:
;
; unit = INIT_SCAN( 'crab.idl' )
;
; eofb = GET_SCAN( 1, DATA=Data )
;
; nmjf = n_elements( data )
; nbin = nmjf*data.nbin(0)
; cts = reform( data.cts, nbin )
; trns = reform( data.trns, data.nsrc(0), nbin )
;
; for i=0,nbin-1 do $
; print, cts(i), trns(*,i)
;
; MODIFICATION HISTORY:
; Written by: H.C. Wen, May, 1994.
; 15-MAY-1994 Added an end-of-file flag for each file buffer, eofb.
; Changed logical unit to file pointer.
; Properly empty the contents of the buffers to the
; USER after the end of file has been reached.
; 18-MAY-1994 Before, data in buffers were physically moved using
; SHIFT, (e.g. buf.mjf = SHIFT( buf.mjf,1 ) ), extremely
; inefficient! Now, only the POINTERS to the buffer elements
; get shifted, buf.ptr = SHIFT( buf.ptr,1 ).
; 09-JUN-1994 Added the NOWARN and LOG keywords.
; 26-JUN-1994 Formerly, READ_BUF; changed the variable keywords
; to structure keywords and the multiple commons with
; variables to one common with one structure variable.
; Eliminated multiple file option change file pointer
; back to logical unit.
; 01-AUG-1994 Formerly called GET_BUF; moved the specific definition
; of data structure to DEF_MJF. Had to add another element
; to SCAN_COM, bufdata, because IDL doesn't allow structures
; to have anonymous structure members.
; 09-AUG-1994 Bugfixes: set pickmjf_=0 after 1st time call to READ_MJF.
; Check if PICKMJF buffer is already in look ahead buffer.
;-
function GET_SCAN, Move, PICKMJF=Pickmjf, DATA=Data, NOWARN=Nowarn, LOG=Log
common SCAN_COM, buf, bufdata
ON_ERROR,2 ; Return to caller if an error occurs
NP = N_PARAMS()
if NP ne 1 then $
message,'Must be called with 1 parameter, Move.'
if N_ELEMENTS( buf ) eq 0 then $
message,'Buffer not initialized. Call INIT_SCAN first.'
in = buf.lunit
Pickmjf_ = 0
if keyword_set( PICKMJF ) then Pickmjf_ = pickmjf
;___________________________________________________________________________________
;
;
; This will be our definitions for our pointers:
;
; bufdata :Buffer array of structures which hold the data.
; ptr :Array of pointers whose elements point to array buffer
; elements.
; seq_ptr :Array of pointers whose elements point to the beginning
; of sequential ptr elements.
; ptr_ptr :A pointer to a seq_ptr element. (pointer to a pointer)
;
;-----------------------------------------------------------------------------------
;
; And this will be our conventions how data is held in these buffers:
;
; Each element of seq_ptr points to the beginning of a group of sequential
; major frames, where the number of major frames in a group can range from
; 1 to the maximum number of buffers, nbuffers. As for the buffers, the
; first buf.ptr element, (e.g. buf.mjf(buf.ptr(0))) is always reserved as
; a look ahead buffer to check for sequential major frames. Namely, only
; buf.ptr elements (1) - (nbuffers-1) may be returned to the USER.
; The first element can be accessed in the "next" call when it is
; shifted up to higher indices.
;
; ptr_ptr Points to the seq_ptr element pointing to the
; "current" group of sequential major frame(s). This
; group of major frame(s) is returned to the USER.
;
; ptr_ptr - 1 Points to the seq_ptr element pointing to the
; "next" group of sequential major frame(s).
;
; ptr_ptr + 1 Points to the seq_ptr element pointing to the
; "previous" group of sequential major frame(s).
;___________________________________________________________________________________
;
if move eq 1 then begin
if buf.ptr_ptr eq 0 then begin
; Check if PICKMJF buffer is already in the "look ahead" buffer
if (bufdata(buf.ptr(0)).mjf eq pickmjf_) $
then pickmjf_ = 0
GET_NEW: iss = READ_MJF( in, PICKMJF=pickmjf_, FORMAT=buf.format, $
DATA=data_mjf )
if (iss) eq 0 then buf.eofb = 1
;
; Shift previous major frames into higher indices
buf.ptr = SHIFT( buf.ptr,1 )
; Put current data into "look ahead" buffer
bufdata(buf.ptr(0)) = data_mjf(0)
buf.nbuffill = (buf.nbuffill+1) < buf.nbuffers
; Take care of pointers
if buf.nbuffill eq 1 then begin
pickmjf_ = 0
buf.nptr = 0
buf.ptr_ptr = 0
buf.seq_ptr(0) = 0
goto, GET_NEW ;need to push "look ahead" into current buffer
endif
; Check if the "current" and "previous" major frames are sequential
;
; If they are then the major frame just moved out of the "look ahead" buffer
; is part of the "previous" major frame group. Link this major frame to the
; "previous" major frame by making the appropriate pointer assignments.
;
; If they are not, then shift older pointer assignments up and position
; "current" pointer on this new major frame.
adj_prev = bufdata( buf.ptr(1) ).mjf $
- bufdata( buf.ptr(2) ).mjf
if adj_prev eq 1 then begin
buf.seq_ptr = buf.seq_ptr + 1
if buf.seq_ptr( buf.nptr-1 ) gt (buf.nbuffers-1) then $
buf.nptr = buf.nptr-1
endif else begin
buf.seq_ptr(buf.nbuffers-1) = 0
buf.seq_ptr = SHIFT( buf.seq_ptr + 1,1 )
buf.nptr = (buf.nptr+1) < (buf.nbuffers-1)
endelse
; Check if the "next" and "current" major frames are sequential
;
; If they are, then we need to move the sequential major frame out of the
; "look ahead" buffer.
adj_now = bufdata( buf.ptr(0) ).mjf $
- bufdata( buf.ptr(1) ).mjf
if adj_now eq 1 then goto, GET_NEW
; Return if end of file and buffer is empty
if buf.eofb and (bufdata( buf.ptr(1) ).mjf eq 0) then begin
return, 1
endif
endif else buf.ptr_ptr = buf.ptr_ptr - 1
endif
if move eq -1 then begin
if buf.seq_ptr(buf.ptr_ptr) ge buf.seq_ptr(buf.nptr-1) then begin
printdev,'Reached end of buffer.',NODISPLAY=nowarn,LOG=log
printdev,'Returning last major frame(s) stored in buffer.',$
NODISPLAY=nowarn, LOG=log
endif else buf.ptr_ptr = buf.ptr_ptr + 1
endif
if pickmjf_ ne 0 then begin
pickmjf_ = 0
goto, GET_NEW ;push "look ahead" buffer into current buffer
endif
; Return header information and data
i_1st = buf.seq_ptr( buf.ptr_ptr )
if buf.seq_ptr( buf.ptr_ptr ) gt 1 then begin
if buf.ptr_ptr eq 0 then i_last = 1 $
else i_last = buf.seq_ptr( buf.ptr_ptr - 1 ) + 1
nmjf = i_1st - i_last + 1 ; # MJFs in buffer
imjf = indgen(nmjf) + i_last
imjf = buf.ptr(reverse( imjf ))
endif else begin ; beginning of buffer
nmjf = 1
imjf = buf.ptr(i_1st)
endelse
Data = bufdata( imjf )
return,0
end
;+
; NAME:
; CLEAR_SCAN
;
; PURPOSE:
;
; Resets all the common block structure to 0.
;
; CATEGORY:
; I/O
;
; CALLING SEQUENCE:
;
; CLEAR_SCAN
;
; RESTRICTIONS:
; Remember, when you exit an IDL routine or program, any common
; block variables are still defined!
;
; MODIFICATION HISTORY:
; Written by: H.C. Wen, May, 1994.
; 15-MAY-1994 Added an end-of-file flag for each file buffer, eofb.
; 26-JUN-1994 Reduced the multi-common, multi-variables to ONE common
; and ONE structure, buf.
; 01-AUG-1994 Formerly called CLEAR_BUF
;-
pro CLEAR_SCAN
common SCAN_COM, buf, bufdata
if N_ELEMENTS( buf ) ne 0 then buf = 0 ;deallocate structure
end
;+
; NAME:
; END_SCAN
;
; PURPOSE:
;
; Closes the data file used by GET_SCAN to extract
; HEAO A-1 data.
;
; CATEGORY:
; I/O
;
; CALLING SEQUENCE:
;
; END_SCAN
;
; INPUT KEYWORD PARAMETERS:
;
; NOWARN: Suppress printing of warning messages to screen.
;
; LOG: Output warning messages to log file.
;
; OUTPUTS:
; Closes the current data file associated with the buffer.
;
; MODIFICATION HISTORY:
; Written by: H.C. Wen, May, 1994.
; 15-MAY-1994 Changed logical unit to file pointer.
; 26-JUN-1994 Eliminated multiple file option. Change file pointer
; back to logical unit.
; 01-AUG-1994 Formerly named CLOSE_BUF
; 09-AUG-1994 Added the close statement
;-
pro END_SCAN, NOWARN=Nowarn, LOG=Log
common SCAN_COM, buf, bufdata
ON_ERROR,2 ; Return to caller if an error occurs
ON_IOERROR, NOFILE
printdev,'Closing data file.',NODISPLAY=nowarn,LOG=log
close, buf.lunit
free_lun, buf.lunit
return
NOFILE: message, !ERR_STRING
end
;+
; NAME:
; INIT_SCAN
;
; PURPOSE:
;
; Initializes all the common block variables to their
; appropriate values before you run the GET_SCAN routine.
;
; CATEGORY:
; I/O
;
; CALLING SEQUENCE:
;
; Result = INIT_SCAN( Newfile, [, NBUFFERS=NBuffers, FORMAT=Format] )
;
; INPUT KEYWORD PARAMETERS:
;
; NBUFFERS: The number of major frames you want retained in the
; buffer arrays, [integer].(See RESTRICTIONS below)
;
; FORMAT: String describing format of the data file. (See READ_MJF)
;
; OUTPUT:
; This function returns the value of the file pointer associated
; with Newfile.
;
; RESTRICTIONS:
; You MUST call this routine BEFORE calling GET_SCAN!
; One of the buffer elements is reserved for "looking ahead"
; for sequential major frames. (i.e. the USER actually has
; nbuffers - 1 buffers available.
;
; MODIFICATION HISTORY:
; Written by: H.C. Wen, May, 1994.
; 15-MAY-1994 Added an end-of-file flag for each file buffer, eofb.
; 26-JUN-1994 Replace multiple commons with multi-variables/arrays
; with one common and one structure.
; Merged OPEN_BUF, eliminated multiple files.
; 01-AUG-1994 Formerly called INIT_BUF; Added FORMAT keyword, shifted
; definition of data structure to a separate routine,
; DEF_MJF so that all xxx_SCAN routines will be independent
; of any modifications to the data structure.
;-
function INIT_SCAN, Newfile, NBUFFERS=Nbuffers, FORMAT=Format
common SCAN_COM, buf, bufdata
ON_ERROR,2 ; Return to caller if an error occurs
ON_IOERROR, NOFILE
NP = N_PARAMS()
if NP ne 1 then message,'Must be called with 1 parameter, Newfile.'
CLEAR_SCAN ; Make sure buffer hasn't initialized by previous calls.
; Define number of buffers
if not keyword_set( NBUFFERS ) then Nbuffers = 10
; Open data file
openr,in,newfile,/GET_LUN
; Define the MJF data structure associated with this file
if NOT keyword_set( FORMAT ) then Format = !HEAO_FMT
MJFstruc = DEF_MJF( in, FORMAT=Format )
; Initialize buffer structure scalars and define buffer structure arrays
bufdata = replicate( MJFstruc, nbuffers ) ;Array of structures
;pointers
ptr = indgen( nbuffers ) ;pointer to buffers
ptr_ptr = 0 ;pointer to ptr
nptr = 0 ;number of ptr's
seq_ptr = intarr( nbuffers ) ;pointer to sequential mjf buffers
;I/O
lunit = in ;logical unit
eofb = 0 ;end of buffer status
nbuffill = 0 ;number of filled buffers
; Define buf structure
buf = { nbuffers : nbuffers, $ ;general dimensions
ptr : ptr , $ ;pointers
ptr_ptr : ptr_ptr , $
nptr : nptr , $
seq_ptr : seq_ptr , $
lunit : lunit , $ ;I/O
format : format , $
eofb : eofb , $
nbuffill : nbuffill }
return, buf.lunit
NOFILE: message, !ERR_STRING
end