STScI Logo

t_ridsmtn



include	<error.h>
include	<fset.h>
include	<mach.h>
include	<imhdr.h>
include	"idsmtn.h"

# T_RIDSMTN -- Code for the IDS mountain format tape reader.  IDS
# records in raw or mountain reduced format can be read into a series of
# one dimensional IRAF images.  The first record on each mtn tape is a
# dummy record and is ignored.  Each IDS header is read and compared
# against the "record_numbers" list.  Depending on the user's request,
# the header can be printed in long or short form, an IRAF image can created.
#
# Modified 6May85 to key off the IIDS header parameters NP1 and NP2
# to copy to the output image only the pixels indicated.

procedure t_ridsmtn ()

pointer sp, cp, ids, vnb
char	ids_file[SZ_PATHNAME], rec_numbers[SZ_LINE]
int	file_number, records[3, MAX_RANGES], nrecs, nrecs_read, fd
int	unp1, unp2, i, sz_buffer

bool	clgetb(), is_in_range()
char	clgetc()
int	clgeti(), mtopen(), decode_ranges(), read()
int	get_data_type(), btoi(), mtfile(), mtneedfileno()

include	"lut.com"
include	"powersof2.com"

begin
	# Allocate space for the control parameter descriptor structure
	# and the program data structure

	call smark (sp)
	call salloc (cp, LEN_CP, TY_STRUCT)
	call salloc (ids, LEN_IDS, TY_STRUCT)

	# Initialize look up tables used to decode bytes of varian data.
	do i = 0, 255 {
	    neg_lut6[i] = and (not (i),  77B)
	    neg_lut7[i] = and (not (i), 177B)
	    neg_lut8[i] = and (not (i), 377B) 
	}

	# Initialize powers of 2 table used to assemble floating point numbers.
	do i = 1, 255
	    tbl[i] = 2.0D0 ** double (i - 129)

	# Get parameters from the cl and generate the input file name.  If
	# the input file is a general tape device, append the file_number suffix

	call clgstr ("ids_file", ids_file, SZ_FNAME)
	if (mtfile(ids_file) == YES) {
	    if (mtneedfileno (ids_file) == YES) {
	        file_number = clgeti ("file_number")
		call mtfname (ids_file, file_number, ids_file, SZ_FNAME)
	    }
	}

	IS_REDUCED(cp) = btoi (clgetb ("reduced_data"))
	LONG_HEADER(cp) = btoi (clgetb ("long_header"))
	PRINT_PIXELS(cp) = btoi (clgetb ("print_pixels"))
	call clgstr ("record_numbers", rec_numbers, SZ_LINE)
	if (decode_ranges (rec_numbers, records, MAX_RANGES, nrecs) == ERR)
	    call error (1, "Error in record_numbers specifications")

	# If an output image is to be written, get output data type and
	# root output data type.

	MAKE_IMAGE(cp) = btoi (clgetb ("make_image"))
	if (MAKE_IMAGE(cp) == YES) {
	    call clgstr ("iraf_file", IRAF_FILE(cp), SZ_FNAME)
	    OFFSET(cp) = clgeti ("offset")
	    DATA_TYPE(cp) = get_data_type (clgetc ("data_type"))
	    if (DATA_TYPE(cp) == ERR)
		DATA_TYPE(cp) = TY_REAL

	    unp1 = clgeti ("np1")
	    unp2 = clgeti ("np2")
	}

	fd = mtopen (ids_file, READ_ONLY, 0)
	sz_buffer = SZB_IDS_RECORD / SZB_CHAR
	if (mtfile (ids_file) == YES)
	    sz_buffer = sz_buffer + 64

	# Allocate input buffer in units of integers
	call salloc (vnb, sz_buffer * SZ_INT, TY_INT)
	
	nrecs_read = 0
	while (nrecs_read < nrecs) {

	    # Read IDS record into buffer.  Unpack bytes into integer array.
	    if (read (fd, Memi[vnb], sz_buffer) == EOF) {
		call printf ("IDS tape at End of File\n")
	        break
	    } else {
		call achtbi (Memi[vnb], Memi[vnb], SZB_IDS_RECORD)
		call vn_int_to_int (Memi[vnb], 1, NREC(ids))

		iferr {
	            if (is_in_range (records, NREC(ids))) {
		        nrecs_read = nrecs_read + 1
		        call idsm_read_record (Memi[vnb], cp, ids, unp1,unp2)
			call flush (STDOUT)
		    }
	        } then {
		    call erract (EA_WARN)
		    next
		}
	    }
	}

	call sfree (sp)
	call close (fd)
end


# IDSM_READ_RECORD -- is called once for each IDS record that appears in
# the "record_numbers" range.   The header is printed and the IDS pixels
# converted or skipped, depending on user request.

procedure idsm_read_record (vnb, cp, ids, unp1, unp2)

int	vnb[ARB]		# Buffer of unpacked IDS record - one byte/int
pointer	cp			# Pointer to control parameter data structure
pointer	ids			# Pointer to program data structure
int	unp1, unp2		# End points of the spectrum

pointer	sp, pixels
char	out_fname[SZ_FNAME]
int	stat
int	strlen(), idsm_read_header()
errchk	idsm_read_header, idsm_write_image, bswap4, vn_rraw
errchk	vn_rred, salloc, malloc

begin
	# Allocate space on stack for pixel buffers
	call smark (sp)
	call salloc (pixels, NPIX_IDS_REC, TY_REAL)
	call malloc (COEFF(ids), MAX_NCOEFF, TY_REAL)

	iferr (stat = idsm_read_header (vnb, ids)) {
	    call mfree (COEFF(ids), TY_REAL)
	    call sfree (sp)
	    call erract (EA_WARN)
	    return 
	}

	if (stat == DUMMY) {
	    call printf ("Dummy IDS record encountered\n")
	    call mfree (COEFF(ids), TY_REAL)
	    call sfree (sp)
	    return
	} else 
	    call idsm_print_header (ids, LONG_HEADER(cp))

	if (MAKE_IMAGE(cp) == YES || PRINT_PIXELS(cp) == YES) {

	    if (IS_REDUCED(cp) == YES)
	        call vn_rred (vnb, DATA_BYTE, Memr[pixels], NPIX_IDS_REC)
	    else
	        call vn_rraw (vnb, DATA_BYTE, Memr[pixels], NPIX_IDS_REC)
	    
	    if (MAKE_IMAGE(cp) == YES) {
	        call strcpy (IRAF_FILE(cp), out_fname, SZ_FNAME)
	        call sprintf (out_fname[strlen(out_fname)+1], SZ_FNAME, ".%04d")
	            call pargi (NREC(ids) + OFFSET(cp))
	        iferr {
		    call idsm_write_image (Memr[pixels], DATA_TYPE(cp), 
			IS_REDUCED(cp), out_fname, ids, unp1, unp2)
		} then {
	            call mfree (COEFF(ids), TY_REAL)
	            call sfree (sp)
		    call erract (EA_WARN)
		    return
		}
	    }
    
	    if (PRINT_PIXELS(cp) == YES)
	        call idsm_print_pixels (Memr[pixels], NP2(ids))

	}
	call mfree (COEFF(ids), TY_REAL)
	call sfree (sp)
end


# IDSM_READ_HEADER -- Read an IDS header and fill the program data
# structure with header values.  Returns EOF or OK.

int procedure idsm_read_header (varian, ids)

int	varian[ARB]		# Buffer of unpack varian record - one byte/int
pointer	ids			# Pointer to program data structure

errchk	vn_int_to_int, vn_long_to_int, vn_gdouble, reduction_flags
errchk	unpk_vn_id

begin
	# The following header words are written as Varian single word
	# integers.

	call vn_int_to_int (varian, NREC_OFFSET, NREC(ids))

	if (NREC(ids) == 0) 
	    # DUMMY IDS record encountered
	    return (DUMMY)
	 
	call vn_int_to_int (varian,   NP1_OFFSET,   NP1(ids))
	call vn_int_to_int (varian,   NP2_OFFSET,   NP2(ids))
	call vn_int_to_int (varian, OFLAG_OFFSET, OFLAG(ids))
	call vn_int_to_int (varian, SMODE_OFFSET, SMODE(ids))
	call vn_int_to_int (varian,  BEAM_OFFSET,  BEAM(ids))
	call vn_int_to_int (varian,   DRA_OFFSET,   DRA(ids))
	call vn_int_to_int (varian,  DDEC_OFFSET,  DDEC(ids))

	# Now unpack Varian double word integers into integers.
	call vn_long_to_int (varian, ITM_OFFSET, ITM(ids))
	call vn_long_to_int (varian,  UT_OFFSET,  UT(ids))
	call vn_long_to_int (varian,  ST_OFFSET,  ST(ids))

	# Now unpack those header words written in Varian 3 word floating point.
	call vn_gdouble (varian,  W0_OFFSET,  W0(ids))
	call vn_gdouble (varian, WPC_OFFSET, WPC(ids))
	call vn_gdouble (varian,  HA_OFFSET,  HA(ids))
	call vn_gdouble (varian,  RA_OFFSET,  RA(ids))
	call vn_gdouble (varian, DEC_OFFSET, DEC(ids))

	# Extract and interpret the 9 reduction flags
	call reduction_flags (varian, ids)

	# Unpack the IDS label
	call unpk_vn_id (varian, LABEL_OFFSET, LABEL(ids))

	return (OK)
end


# VN_INT_TO_INT -- Unpack a single integer value from a char buffer containing
# packed varian short (16-bit) integers.  The number of the word containing
# the value of interest is passed as an argument.

procedure vn_int_to_int (inbuf, offset, int_value)

int	inbuf[ARB]		# Unpacked IDS record
int	offset			# WORD offset as read from tape
int	int_value		# Integer value returned

int	bytes[2]

include	"lut.com"

begin
	call amovi (inbuf[offset], bytes, 2)
	if (bytes[1] < 127)
	    int_value = (bytes[1] * (2 ** 8)) + bytes[2]
	else {
	    bytes[1] = neg_lut8[bytes[1]] * (2 ** 8)
	    bytes[2] = neg_lut8[bytes[2]] 
	    int_value = -1 * (bytes[1] + bytes[2] + 1)
	}
end


# VN_LONG_TO_INT -- Unpack a SPP integer from a buffer containing packed
# varian long (32-bit) intgers.

procedure vn_long_to_int (inbuf, offset, int_value)

int	inbuf[ARB]	# Buffer containing unpacked varian longs one byte/int
int	offset		# Byte offset to field to be unpacked
int	int_value	# Integer value returned

int	bytes[4]

include	"lut.com"

begin
	call amovi (inbuf[offset], bytes, 4)

	if (bytes[1] < 127)
	    int_value = bytes[4] + (bytes[3] * (2 ** 8)) + (bytes[2] * 
	        (2 ** 15)) + (bytes[1] * (2 ** 23))
	 else {
	    bytes[1] = neg_lut8[bytes[1]] + (2 ** 23)
	    bytes[2] = neg_lut8[bytes[2]] + (2 ** 15)
	    bytes[3] = neg_lut7[bytes[3]] + (2 ** 8)
	    bytes[4] = neg_lut8[bytes[4]]
	    int_value = -1 * (bytes[1] + bytes[2] + bytes[3] + bytes[4] + 1)
	}
end


# VN_GDOUBLE -- Unpack a SPP double from a buffer containing packed
# varian 3-word (48-bit) floating point numbers.

procedure vn_gdouble (inbuf, offset, dbl_value)

int	inbuf[ARB]	# Buffer of unpacked varian 3wrd reals 1 byte/int
int	offset		# Word offset to value to be unpacked
double	dbl_value	# Double value returned

int	bytes[6], exp, mantissa

include	"lut.com"
include	"powersof2.com"

begin
	call amovi (inbuf[offset], bytes, 6)

	if (bytes[3] > 127) {
	    bytes[6] = neg_lut8[bytes[6]]
	    bytes[5] = neg_lut7[bytes[5]] * (2 ** 8)
	    bytes[4] = neg_lut8[bytes[4]] * (2 ** 15)
	    bytes[3] = neg_lut6[bytes[3]] * (2 ** 23)
	    mantissa = -1 * (bytes[6] + bytes[5] + bytes[4] + bytes[3] + 1)
	} else
	    mantissa = bytes[6] + (bytes[5] * (2 ** 8)) + (bytes[4] * 
	        (2 ** 15)) + (bytes[3] * (2 ** 23))

	if (bytes[1] > 127) {
	    bytes[1] = neg_lut8[bytes[1]] * (2 ** 8)
	    bytes[2] = neg_lut8[bytes[2]]
	    exp = -1 * (bytes[1] + bytes[2] + 1)
	} else
	    exp = bytes[2] + (bytes[1] * (2 ** 8))

	# Reconstruct the floating point number as a SPP real.  Powers of
	# two are stored in the tbl[] array where 2 ** n = tbl[n+129].
	# The mantissa is divided by 2 ** 29 to move the binary point
	# above bit 29.

	exp = exp + 129 - 29

	if (exp <= 0)
	    dbl_value = 0.0D0
	else if (exp > 255)
	    dbl_value = double (MAX_REAL)
	else if (exp > 0 && exp <= 255)
	    dbl_value = double (mantissa) * tbl[exp]
end


# IDSM_WRITE_IMAGE -- Write a one dimensional IRAF image of an IDS record.

procedure idsm_write_image (pixels, data_type, is_reduced, out_fname, 
	ids, unp1, unp2)

real	pixels[ARB]		# Array of unpacked IDS pixels
int	data_type		# Data type of output pixels
int	is_reduced		# Is data in reduced format?
char	out_fname[SZ_FNAME]	# Filename of output IRAF image
pointer	ids			# Pointer to program data structure
int	unp1, unp2		# Pixel endpoints of spectrum

int	pix1, pix2, npts, temp
pointer	im
pointer	immap(), impl1r()
errchk	immap, amovr, idsm_store_keywords, impl1r, imunmap

begin
	# Map new IRAF image and set up image header
	im = immap (out_fname, NEW_IMAGE, LEN_USER_AREA)
	IM_NDIM(im) = 1

	# Select the pixels to be written out.
	# When the data is in reduced format, write out the
	# entire vector.
	#
	# If the user parameter is zero, use the header elements.
	# On some IRS tapes, these parameters are backwards.

	if (NP1(ids) > NP2(ids)) {
	    temp = NP1(ids)
	    NP1(ids) = NP2(ids)
	    NP2(ids) = temp
	}

	if (is_reduced == YES) {
	    pix1 = 1
	    pix2 = NPIX_IDS_REC

	} else {

	    if (unp1 == 0)
	        pix1 = NP1(ids) + 1
	    else
	        pix1 = unp1

	    if (unp2 == 0)
	        pix2 = NP2(ids)
	    else
	        pix2 = unp2
	}

	npts = pix2 - pix1 + 1

	NP1(ids) = 0
	NP2(ids) = npts

	IM_LEN(im, 1) = npts
	call strcpy (LABEL(ids), IM_TITLE(im), SZ_IMTITLE)
	IM_PIXTYPE(im) = data_type

	# Move pixel_buffer into image row vector
	call amovr (pixels[pix1], Memr[impl1r(im)], npts)

	# Write IDS specific header words to IRAF image header
	# Update W0 for possible new starting pixel

	W0(ids) = W0(ids) + double (pix1 - 1) * WPC(ids)

	call idsm_store_keywords (ids, im)

	call imunmap (im)
end


# IDSM_PRINT_HEADER -- print the ids header in either long or short mode.  This
# procedure has been slightly modified from the version used in ridsfile or
# RIDSOUT.

procedure idsm_print_header (ids, long_header)

pointer	ids		# Pointer to program data structure
int	long_header	# Print header in long format (YES/NO)?
int	i

begin
	if (long_header == YES) {
	    call printf ("\nRECORD = %d, label = \"%s\",\n")
	        call pargi (NREC(ids))
	        call pargstr (LABEL(ids))

	    if (OFLAG(ids) == 1) {
		call printf ("oflag = OBJECT, beam_number = %d,")
		    call pargi (BEAM(ids))
	    } else {
		call printf ("oflag = SKY,    beam_number = %d,")
		    call pargi (BEAM(ids))
	    }

	    call printf ("   W0 = %0.3f,")
	        call pargd (W0(ids))
	    call printf ("    WPC = %0.3f,  ITM = %d,\n")
	        call pargd (WPC(ids))
		call pargi (ITM(ids))
	    call printf ("NP1 = %d, NP2 = %d,")
		call pargi (NP1(ids))
		call pargi (NP2(ids))
	    call printf ("    UT = %h,   ST = %h,")
		call pargr (UT(ids) / 3600.)
		call pargr (ST(ids) / 3600.)
	    call printf ("   HA = %h,\n")
		call pargd (HA(ids))
	    call printf ("RA = %h,   DEC = %h,")
		call pargd (RA(ids))
		call pargd (DEC(ids))
	    if (DRA(ids) != 0 || DDEC(ids) != 0) {
		call printf ("   DRA = %g,   DDEC = %g,\n")
		    call pargr (DRA(ids) / 100.)
		    call pargr (DDEC(ids) / 100.)
	    } else
		call printf ("\n")
	    call printf ("df = %d, sm = %d, qf = %d, dc = %d, qd = %d, ") 
		call pargi (DF_FLAG(ids))
		call pargi (SM_FLAG(ids))
		call pargi (QF_FLAG(ids))
		call pargi (DC_FLAG(ids))
		call pargi (QD_FLAG(ids))
	    call printf ("ex = %d, bs = %d, ca = %d, co = %d")
		call pargi (EX_FLAG(ids))
		call pargi (BS_FLAG(ids))
		call pargi (CA_FLAG(ids))
		call pargi (CO_FLAG(ids))

	     # The df coeffecients are printed out in the case where the df
	     # flag has been set.

	    if (DF_FLAG(ids) != -1) {
		call printf (",\n")
		do i = 1, DF_FLAG(ids) {
		    call printf ("df[%d] = %10.8g")
			call pargi(i)
			call pargr(Memr[COEFF(ids)+i-1])
		    if (i != DF_FLAG(ids))
		        call printf (", ")
		    if (mod (i, 4) == 0)
		        call printf ("\n")
		}
	    } else
		call printf ("\n")
	    call printf ("\n")
	} else {
	    call printf ("RECORD = %d, label = \"%.45s\", ITM = %d\n")
	        call pargi (NREC(ids))
	        call pargstr (LABEL(ids))
		call pargi (ITM(ids))
	}
end


# IDSM_PRINT_PIXELS -- Print the ids pixel values.  

procedure idsm_print_pixels (pixel_buf, nvalues)

real	pixel_buf[ARB]		# Buffer containing pixels to be listed
int	nvalues			# Number of pixel values to print
int	n_pix

begin
	for (n_pix = 1; n_pix < nvalues; n_pix = n_pix + 4) {
	    call printf ("%10.4e %10.4e %10.4e %10.4e\n")
	        call pargr (pixel_buf[n_pix])
	        call pargr (pixel_buf[n_pix + 1])
	        call pargr (pixel_buf[n_pix + 2])
	        call pargr (pixel_buf[n_pix + 3])
	}
	call printf ("\n")
end

Source Code · Search Form · STSDAS