	FUNCTION FORM_RASTER, PACKET, RASTER, DATAWIN, MSG
;+
; Project     : SOHO - CDS
;
; Name        : FORM_RASTER()
;
; Purpose     : Sets up the structure of a raster.
;
; Explanation : Sets up a structure variable to receive the data making up a
;		complete NIS or GIS raster.
;
; Use         : Result = FORM_RASTER( PACKET, RASTER, DATAWIN, MSG )
;
; Inputs      : PACKET	= The packet containing the raster header.
;
; Opt. Inputs : None.
;
; Outputs     : RASTER	= Structure variable for containing the metadata, in
;			  the form:
;
;			INSTRUMENT	= Either 'GIS' or 'NIS'.
;			HEADER		= Raster header structure, defined by
;					  either VDSRASTERDFN or GISRASTERDFN
;					  (see TM_DEFINE_STRUC).
;			SP_STATUS	= The science process status, from
;					  SPS_DECODE.
;			STARTTIME	= Exposure start times.
;			OPSLPOSITION	= Offset pointing system X coordinates.
;			OPSRPOSITION	= Offset pointing system Y coordinates.
;			MIRRORPOSITION	= Mirror positions.
;			SLITPOSITION	= Slit positions.
;			SUNSENSORPITCH	= Sun sensor pitch values.
;			SUNSENSORYAW	= Sun sensor yaw values.
;			SOLAR_X		= Solar X position.
;			SOLAR_Y		= Solar Y position.
;			EV_STATUS	= Event status, from EVS_DECODE.
;			EV_LEVEL	= Event level.
;			HEADERFOUND	= Whether exposure header was found or
;					  not.
;			WIDTH1		= Array containing the width of each
;					  data window in the first dimension,
;					  after all orientation and compression
;					  information has been taken into
;					  consideration.
;			WIDTH2		= Array containing the width of each
;					  data window in the second dimension,
;					  after all orientation and compression
;					  information has been taken into
;					  consideration.  For GIS this is 1.
;			BIN1		= Array containing the bin size in
;					  pixels for each data window in the
;					  first dimension.
;			BIN2		= Array containing the bin size in the
;					  second dimension.  For GIS this is 1.
;			MIRRORSTEP	= Mirror step size in arcsec
;			SLITSTEP	= Slit step size in arcsec
;			N_DATA		= Number of data values in each
;					  exposure.
;
;		DATAWIN	= Array containing the data windows.  This will have
;			  the dimensions
;
;				(N1, N2, N_WINDOWS, N_EXPOSURES)	;VDS
;				(N1, N_WINDOWS, N_EXPOSURES)		;GIS
;
;			  where N1 and N2 are large enough to be consistent
;			  with each of the data windows.
;
;		MSG	= String containing a message describing any error
;			  detected by the routine.
;
;		The result of the function is either True (1) for success or
;		False (0) for failure.  If unsuccessful, then MSG will contain
;		the reason for the failure.
;
; Opt. Outputs: None.
;
; Keywords    : None.
;
; Calls       : SPS_DECODE, EVS_DECODE, GET_CDHS_DEXWIN
;
; Common      : None.
;
; Restrictions: None.
;
; Side effects: The mirror and slit step sizes, which are not directly
;		downloaded in the telemetry, are initially set to zero by this
;		routine.  Their calculation is deferred until later.
;
; Category    : Data Handling, Telemetry.
;
; Prev. Hist. : Taken from earlier routines called READ_VDS/GIS_RASTER and
;		PARSE_VDS/GIS_RASTER, written by William Thompson, GSFC,
;		February 1993.
;
; Written     : William Thompson, GSFC, 22 March 1993.
;
; Modified    : Version 1, William Thompson, GSFC, 6 April 1993.
;			Modified for version 2.4 of the packet format document.
;		Version 2, William Thompson, GSFC, 16 November 1993.
;			Modified for version 3.0 of the packet format document.
;			Removed check of binning factors.
;			Split off DATAWIN from RASTER structure for greater
;			speed.
;		Version 3, William Thompson, GSFC, 13 June 1994.
;			Split RASTERLENGTH into NUMMIRRORPOS and NUMSLITPOS.
;		Version 4, William Thompson, GSFC, 22 August 1994
;			Added SP_STATUS, WIDTH1, WIDTH2 to output structure.
;			Implemented VDS orientation, compression modes SUMLINE
;				and SUMWIN.
;			Initialize DATAWIN to -1.
;			Redefined DATA_WIN to be structures.
;		Version 5, William Thompson, GSFC, 18 October 1994
;			Added MIRRORSTEP and SLITSTEP to output structure.
;		Version 6, William Thompson, GSFC, 22 December 1994
;			Added SOLAR_X, SOLAR_Y, EV_STATUS, and EV_LEVEL to
;			output structure.
;		Version 7, William Thompson, GSFC, 27 June 1995
;			Added STUDY_ID and STUDYVAR to structure.
;		Version 8, William Thompson, GSFC, 2 August 1995
;			Added BIN1 and BIN2 to structure.
;		Version 9, William Thompson, GSFC, 26 February 1996
;			Correct datawindow ID in raster structure.
;		Version 10, William Thompson, GSFC, 20 October 1997
;			Accommodate compression mode 8.
;
; Version     : Version 10, 20 October 1997
;-
;
	ON_ERROR, 2
;
;  Check the number of parameters.
;
	IF N_PARAMS() NE 4 THEN MESSAGE,	$
		'Syntax:  Result = FORM_RASTER( PACKET, RASTER, DATAWIN, MSG )'
;
;  Decide whether the instrument is GIS or NIS.
;
	IF PACKET.HDR.ID EQ '01'X THEN INSTRUMENT = 'GIS' ELSE	$
		INSTRUMENT = 'NIS'
;
;  Check some of the parameters depending on which instrument is being used.
;
	N_WINDOWS = PACKET.PKT.NWINDOWS
	WINDOWS   = PACKET.PKT.DATA_WIN
;
;  Decode the science process status word.
;
	SPS_DECODE, PACKET.PKT.SCI.SCI_STATUS, SP_STATUS
;
;  Check the GIS window list.
;
	IF INSTRUMENT EQ 'GIS' THEN BEGIN
		N_WINDOWS = PACKET.PKT.NWINDOWS
		IF (N_WINDOWS LT 1) OR (N_WINDOWS GT 61) THEN BEGIN
			MSG = 'Number of data windows ' +	$
				STRTRIM(FIX(N_WINDOWS),2) + ' out of range'
			RETURN, 0
		ENDIF
;
		START1 = REFORM((WINDOWS.START)(0:N_WINDOWS-1))
		WIDTH1 = REFORM((WINDOWS.LENGTH)(0:N_WINDOWS-1))
		WIDTH2 = REPLICATE(1,N_WINDOWS)
		BIN1   = REPLICATE(1,N_WINDOWS)
		BIN2   = REPLICATE(1,N_WINDOWS)
;
		FOR IWINDOW = 0, N_WINDOWS-1 DO BEGIN
			ISTART1 = START1(IWINDOW)
			IWIDTH1 = WIDTH1(IWINDOW)
			SWINDOW = STRTRIM(IWINDOW,2)
			SSTART  = STRTRIM(ISTART1, 2)
			SWIDTH  = STRTRIM(IWIDTH1, 2)
;
			IF (ISTART1 LT 0) OR (ISTART1 GT 8191) THEN BEGIN
				MSG = 'Window ' + SWINDOW + ' start pixel ' + $
					SSTART + ' out of range'
				RETURN, 0
			ENDIF
;
			IF (IWIDTH1 LT 1) OR (IWIDTH1 GT 8192) THEN BEGIN
				MSG = 'Window ' + SWINDOW + ' width ' +	$
					SWIDTH + ' out of range'
				RETURN, 0
			ENDIF
;
			IF (ISTART1 + IWIDTH1) GT 8192 THEN BEGIN
				MSG = 'Window ' + SWINDOW + ' start pixel ' + $
					SSTART + ' and width ' + SWIDTH + $
					' are incompatible'
				RETURN, 0
			ENDIF
		ENDFOR
;
;  Check the NIS window list.
;
	END ELSE BEGIN
		IF (N_WINDOWS LT 1) OR (N_WINDOWS GT 32) THEN BEGIN
			MSG = 'Number of data windows ' +	$
				STRTRIM(FIX(N_WINDOWS),2) + ' out of range'
			RETURN, 0
		ENDIF
;
		START1 = REFORM((WINDOWS.STARTX)(0:N_WINDOWS-1))
		START2 = REFORM((WINDOWS.STARTY)(0:N_WINDOWS-1))
		WIDTH1 = REFORM((WINDOWS.LENGTHX)(0:N_WINDOWS-1))
		WIDTH2 = REFORM((WINDOWS.LENGTHY)(0:N_WINDOWS-1))
		BIN1   = REPLICATE(1,N_WINDOWS)
		BIN2   = REPLICATE(1,N_WINDOWS)
;
		FOR IWINDOW = 0, N_WINDOWS-1 DO BEGIN
			ISTART1 = START1(IWINDOW)
			ISTART2 = START2(IWINDOW)
			IWIDTH1 = WIDTH1(IWINDOW)
			IWIDTH2 = WIDTH2(IWINDOW)
			SWINDOW = STRTRIM(IWINDOW,2)
			SSTART1 = STRTRIM(ISTART1, 2)
			SSTART2 = STRTRIM(ISTART2, 2)
			SWIDTH1 = STRTRIM(IWIDTH1, 2)
			SWIDTH2 = STRTRIM(IWIDTH2, 2)
;
			IF (ISTART1 LT 0) OR (ISTART1 GT 1023) THEN BEGIN
				MSG = 'Window ' + SWINDOW + ' X start pixel '+$
					SSTART1 + ' out of range'
				RETURN, 0
			ENDIF
;
			IF (IWIDTH1 LT 1) OR (IWIDTH1 GT 1024) THEN BEGIN
				MSG = 'Window ' + SWINDOW + ' X width '	 + $
					SWIDTH1 + ' out of range'
				RETURN, 0
			ENDIF
;
			IF (ISTART1 + IWIDTH1) GT 1024 THEN BEGIN
				MSG = 'Window ' + SWINDOW + ' X start pixel '+$
					SSTART1 + ' and width '	 + SWIDTH1 + $
					' are incompatible'
				RETURN, 0
			ENDIF
;
			IF (ISTART2 LT 0) OR (ISTART2 GT 1023) THEN BEGIN
				MSG = 'Window ' + SWINDOW + ' Y start pixel '+$
					SSTART2 + ' out of range'
				RETURN, 0
			ENDIF
;
			IF (IWIDTH2 LT 1) OR (IWIDTH2 GT 1024) THEN BEGIN
				MSG = 'Window ' + SWINDOW + ' Y width '	 + $
					SWIDTH2 + ' out of range'
				RETURN, 0
			ENDIF
;
			IF (ISTART2 + IWIDTH2) GT 1024 THEN BEGIN
				MSG = 'Window ' + SWINDOW + ' Y start pixel '+$
					SSTART2 + ' and width '	 + SWIDTH2 + $
					' are incompatible'
				RETURN, 0
			ENDIF
		ENDFOR
;
;  If the VDS orientation is set to columns, then swap WIDTH1 and WIDTH2.
;
		IF (INSTRUMENT EQ 'NIS') AND (SP_STATUS.VDS_ORIENT) THEN BEGIN
			TEMP = WIDTH1
			WIDTH1 = WIDTH2
			WIDTH2 = TEMP
		ENDIF
	ENDELSE
;
;  If the compression scheme is SUMLINE (6), then WIDTH1 is set to 1.  Retain
;  the old width as BIN1.
;
	IF PACKET.PKT.SCI.COMPRESSION EQ 6 THEN BEGIN
		BIN1 = WIDTH1
		WIDTH1(*) = 1
	ENDIF
;
;  If the compression scheme is SUMWIN (7), then both WIDTH1 and WIDTH2 are set
;  to 1.  Retain the old widths as BIN1 and BIN2.
;
	IF PACKET.PKT.SCI.COMPRESSION EQ 7 THEN BEGIN
		BIN1 = WIDTH1
		BIN2 = WIDTH2
		WIDTH1(*) = 1
		WIDTH2(*) = 1
	ENDIF
;
;  If the compression scheme is USER, then assume that the compression mode is
;  binning along the slit, with the binning factor stored in COMP_OPTION.
;
	IF (INSTRUMENT EQ 'NIS') AND (PACKET.PKT.SCI.COMPRESSION EQ 8)	$
			THEN BEGIN
		BINNING = PACKET.PKT.SCI.COMP_OPTION
		IF SP_STATUS.VDS_ORIENT THEN BEGIN
			BIN1 = BIN1 * BINNING
			WIDTH1 = FIX((WIDTH1 + BINNING - 1) / BINNING)
		END ELSE BEGIN
			BIN2 = BIN2 * BINNING
			WIDTH2 = FIX((WIDTH2 + BINNING - 1) / BINNING)
		ENDELSE
	ENDIF
;
;  Calculate the number of exposures, and the amount of data per exposure.
;
	N_EXPOSURES = (PACKET.PKT.SCI.NUMMIRRORPOS > 1) *	$
		(PACKET.PKT.SCI.NUMSLITPOS > 1)
	N_DATA = TOTAL(WIDTH1*LONG(WIDTH2))
;
;  Generate a dummy event status array.
;
	EVSBYTE = BYTARR(N_EXPOSURES)
	EVS_DECODE, BYTARR(N_EXPOSURES), EV_STATUS
;
;  Define the raster structure.
;
	RASTER = {INSTRUMENT:	INSTRUMENT,		$
		HEADER:		PACKET.PKT,		$
		SP_STATUS:	SP_STATUS,		$
		STARTTIME:	BYTARR(6,N_EXPOSURES),	$
		OPSLPOSITION:	INTARR(N_EXPOSURES),	$
		OPSRPOSITION:	INTARR(N_EXPOSURES),	$
		MIRRORPOSITION:	BYTARR(N_EXPOSURES),	$
		SLITPOSITION:	INTARR(N_EXPOSURES),	$
		SUNSENSORPITCH:	INTARR(N_EXPOSURES),	$
		SUNSENSORYAW:	INTARR(N_EXPOSURES),	$
		SOLAR_X:	INTARR(N_EXPOSURES),	$
		SOLAR_Y:	INTARR(N_EXPOSURES),	$
		EV_STATUS:	EV_STATUS,		$
		EV_LEVEL:	INTARR(N_EXPOSURES),	$
		HEADERFOUND:	BYTARR(N_EXPOSURES),	$
		WIDTH1:		WIDTH1,			$
		WIDTH2:		WIDTH2,			$
		BIN1:		BIN1,			$
		BIN2:		BIN2,			$
		MIRRORSTEP:	0.0,			$
		SLITSTEP:	0.0,			$
		N_DATA:		N_DATA,			$
		STUDY_ID:	-1,			$
		STUDYVAR:	-1}
;
;  Correct the data window ID number in the header.
;
	DW = GET_CDHS_DEXWIN(RASTER.HEADER.SCI.DATAWINDOWID)
	IF TAG_EXIST(DW,'CDHS_ID') THEN RASTER.HEADER.SCI.DATAWINDOWID = DW.ID
;
;  Define the array to store the data windows, depending on whether the data is
;  from the NIS or GIS instruments.  Initialize the array to -1 in case not all
;  the data is read in.
;
	IF INSTRUMENT EQ 'GIS' THEN BEGIN
		N1 = MAX(WIDTH1)
		DATAWIN = REPLICATE(-1L, N1, N_WINDOWS, N_EXPOSURES)
	END ELSE BEGIN
		N1 = MAX(WIDTH1)
		N2 = MAX(WIDTH2)
		DATAWIN = REPLICATE(-1L, N1, N2, N_WINDOWS, N_EXPOSURES)
	ENDELSE
;
;  If window summation compression method is used, then the data will be double
;  precision (IDL does not have a 64 bit integer type).
;
	IF PACKET.PKT.SCI.COMPRESSION EQ 7 THEN DATAWIN = DOUBLE(DATAWIN)
;
	MSG = 'Successful completion'
	RETURN, 1
	END
