	FUNCTION MAKECDSHEADER, FILENAME, RASTER, PLAN, RASTER_DEF
;+
; Project     :	SOHO - CDS
;
; Name        :	MAKECDSHEADER()
;
; Purpose     :	Creates primary header from telemetry for CDS FITS file
;
; Explanation :	Uses the header information from the telemetry to create a
;		primary FITS header.
;
; Use         :	HEADER = MAKECDSHEADER(FILENAME,RASTER,PLAN,RASTER_DEF)
;
; Inputs      :	FILENAME   = Name of the file to receive the data.
;		RASTER	   = Structure variable from READ_RASTER, containing
;			     all the metadata extracted from the science
;			     telemetry stream pertaining to the raster.
;		PLAN	   = Science plan entry corresponding to the raster,
;			     from FIND_IN_PLAN.
;		RASTER_DEF = Raster definition from GET_RASTER
;
; Opt. Inputs :	None.
;
; Outputs     :	The result of the function is the primary header.
;
; Opt. Outputs:	None.
;
; Keywords    :	None.
;
; Calls       :	FXHMAKE, FXADDPAR, DEC2BIN, FXBHMAKE, TRIM, FXBADDCOL, UNSIGN
;
; Common      :	FITSGEN contains the arrays WAVELENGTHS, POINTINGS, TIMES.
;
; Restrictions:	None.
;
; Side effects:	None.
;
; Category    :	Data_handling, Telemetry, I/O, FITS, CDS.
;
; Prev. Hist. :	None.
;
; Written     :	William Thompson, GSFC, 18 October 1994
;
; Modified    :	Version 1, William Thompson, GSFC, 27 June 1995
;		Version 2, William Thompson, GSFC, 3 August 1995
;			Added PROG_IND and SEQ_NUM to header.
;		Version 3, William Thompson, GSFC, 22 August 1995
;			Corrected bug with interaction with online catalog,
;			r.e. SEQVALID.
;		Version 4, William Thompson, GSFC, 25 August 1995
;			Added GIS parameters from Engineering B packet
;			Only write VDS parameters if NIS detector
;		Version 5, William Thompson, GSFC, 26 September 1995
;			Changed GET_STATE to CP_GET_STATE
;		Version 6, William Thompson, GSFC, 13 October 1995
;			Removed obsolete call to ENGB_DECODE
;		Version 7, William Thompson, GSFC, 16 October 1995
;			Filename written to header without a path.
;		Version 8, William Thompson, GSFC, 4 December 1995
;			Add parameters SC_ROLL, SC_X0, SC_Y0
;		Version 9, William Thompson, GSFC, 30 January 1996
;			Add GSET_ID
;		Version 10, William Thompson, GSFC, 21 February 1996
;			Changed to extract certain parameters from the catalog
;			if available.
;		Version 11, William Thompson, GSFC, 22 February 1996
;			Call GET_VDS_STATE instead of CP_GET_STATE.
;		Version 12, William Thompson, GSFC, 28 February 1996
;			Correct the end times based on the exposure times.
;		Version 13, William Thompson, GSFC, 6 March 1996
;			Put pointing zone ID in the header, if possible.
;			Use TOP_LEVEL keyword with TAG_EXIST
;		Version 14, William Thompson, GSFC, 12 March 1996
;			Add OBS_SEQ and OBS_MODE
;		Version 15, William Thompson, GSFC, 1 April 1996
;			Add COMMENTS
;		Version 16, William Thompson, GSFC, 3 April 1996
;			Fix bug where OBS_MODE was not written to FITS headers
;		Version 17, William Thompson, GSFC, 16 April 1996
;			Improved OBS_SEQ, OBS_MODE
;		Version 18, William Thompson, GSFC, 4 June 1996
;			Fixed bug associated with adding COMMENTS
;		Version 19, William Thompson, GSFC, 12 September 1996
;			Treat STUDYCOUNTER as an unsigned integer.
;		Version 20, William Thompson, GSFC, 22 October 1996
;			Use actual SFDU ADID.
;		Version 21, William Thompson, GSFC, 6 March 1998
;			Improve comments in FITS header.
;		Version 22, 05-Jan-2000, William Thompson, GSFC
;			Added /NOZ in call to TAI2UTC.
;
; Version     : Version 21, 6 March 1998
;-
;
	ON_ERROR, 2
	LOGICAL = ['F','T']
@fitsgen.cmn
;
;  Check the number of parameters.
;
	IF N_PARAMS() NE 4 THEN MESSAGE, 'Syntax:  Result = MAKECDSHEADER' + $
		'( FILENAME, RASTER, PLAN, RASTER_DEF, )'
;
;  Make a basic FITS primary header, with no primary array, and signaling that
;  there will be an extension to the file.  Add the creation date to the FITS
;  header.
;
	FXHMAKE, HEADER, /EXTEND, /DATE
;
;  Add the SFDU ADID information.
;
	FXADDPAR, HEADER, 'SFDUADID', 'NSSD0229', 'SFDU ADID'
;
;  Break the filename into it's constituent pieces.
;
	BREAK_FILE, FILENAME, DISK, DIR, NAME, EXT
	NAME = NAME + EXT
	FXADDPAR, HEADER, 'FILENAME', NAME
;
;  Store information from the raster header structure in the FITS header.
;
	SCIHEAD = RASTER.HEADER.SCI
	DETECTOR = RASTER.INSTRUMENT
;
	FXADDPAR, HEADER, 'ORIGIN',   'SOHO-EOF',	$
		'Institute where file was written'
	FXADDPAR, HEADER, 'TELESCOP', 'SOHO',	$
		'Solar Heliospheric Observatory'
	FXADDPAR, HEADER, 'INSTRUME', 'CDS', 'Coronal Diagnostic Spectrometer'
	FXADDPAR, HEADER, 'DETECTOR', DETECTOR,	$
		'Normal or Grazing Incidence Spectrometer'
	FXADDPAR, HEADER, 'PROG_NUM', UNSIGN(SCIHEAD.STUDYCOUNTER),	$
		'Study counter'
	FXADDPAR, HEADER, 'PROG_IND', PLAN.PROG_IND, 'Repeated study index'
	FXADDPAR, HEADER, 'SEQ_IND',  SCIHEAD.RASTERCOUNTER,	$
		'Raster index within the study'
	FXADDPAR, HEADER, 'SEQ_NUM',  PLAN.SEQ_NUM,	$
		'Unique number for this dataset'
;
;  Add the raster ID number and variation index.
;
	FXADDPAR, HEADER, 'RAS_ID', RASTER_DEF.RAS_ID, 'Raster ID'
	IF TAG_EXIST(RASTER_DEF, 'RAS_VAR', /TOP_LEVEL) THEN	$
		RAS_VAR = RASTER_DEF.RAS_VAR ELSE RAS_VAR = -1
	FXADDPAR, HEADER, 'RAS_VAR', RAS_VAR, 'Raster variation index'
;
;  Take the exposure time from the raster definition.  If no raster definition
;  was found, then assume that the exposure time in the telemetry is in units
;  of 0.1 seconds.
;
	IF RASTER_DEF.RAS_ID NE -1 THEN EXPTIME = RASTER_DEF.EXPTIME ELSE $
		EXPTIME = SCIHEAD.EXPOSURETIME/10.
;
;  If the exposure time differs from what you would get if you made the
;  default assumption, then correct the end times accordingly.
;
	DIFF = EXPTIME - SCIHEAD.EXPOSURETIME/10.
	IF DIFF NE 0 THEN BEGIN
		TIMES.OBT_END = TIMES.OBT_END + DIFF
		TIMES.DATE_END = TAI2UTC(UTC2TAI(TIMES.DATE_END)+DIFF,	$
			/CCSDS, /NOZ)
	ENDIF
;
;  Store the times.
;
	FXADDPAR, HEADER, 'DATE_OBS', TIMES.DATE_OBS,	$
		'Start date/time of observation'
	FXADDPAR, HEADER, 'DATE_END', TIMES.DATE_END,	$
		'End date/time of observation'
	FXADDPAR, HEADER, 'OBT_TIME', TIMES.OBT_TIME, FORMAT='(F15.3)',	$
		'Onboard start time (TAI seconds since 1-Jan-1958)'
	FXADDPAR, HEADER, 'OBT_END', TIMES.OBT_END, FORMAT='(F15.3)',	$
		'Onboard end time (TAI seconds since 1-Jan-1958)'
;
;  Store the information from the science plan.  Start with the parameters
;  derived from the study ID.  If the study ID is not found, then use default
;  values.
;
	IF TAG_EXIST(PLAN,'STUDY_ID', /TOP_LEVEL) THEN BEGIN
		STUDY_ID = PLAN.STUDY_ID
		STUDYVAR = PLAN.STUDYVAR
	END ELSE BEGIN
		STUDY_ID = RASTER.STUDY_ID
		STUDYVAR = RASTER.STUDYVAR
	ENDELSE
	GET_STUDY, STUDY_ID, STUDYVAR, STUDY
	IF STUDY.STUDY_ID LT 0 THEN STUDY = {STUDY_ID: SCIHEAD.STUDYID,	$
		TITLE_ID: -1,	$
		OBS_PROG: '',	$
		TITLE: '',	$
		CATEGORY: ''}
	FXADDPAR, HEADER, 'OBS_PROG', STUDY.OBS_PROG, 'Observing program name'
	FXADDPAR, HEADER, 'TITLE', STRTRIM(STUDY.TITLE),	$
		'Observing program title'
	FXADDPAR, HEADER, 'STUDY_ID', STUDY_ID, 'Study ID'
	FXADDPAR, HEADER, 'TITLE_ID', STUDY.TITLE_ID, 'Study title ID'
	FXADDPAR, HEADER, 'STUDYVAR', STUDYVAR, 'Study variation index'
	CASE STUDY.CATEGORY OF
		'T':	CATEGORY = 'Test'
		'S':	CATEGORY = 'Science'
		'C':	CATEGORY = 'Calibration'
		ELSE:	CATEGORY = STUDY.CATEGORY
	ENDCASE
	FXADDPAR, HEADER, 'CATEGORY', CATEGORY,	'Study category'
;
;  Do the rest of the parameters from the science plan.
;
	FXADDPAR, HEADER, 'SCI_OBJ',  STRTRIM(PLAN.SCI_OBJ,2),	$
		'Scientific objective'
	FXADDPAR, HEADER, 'SCI_SPEC', STRTRIM(PLAN.SCI_SPEC,2),	$
		'More specific scientific objective'
	FXADDPAR, HEADER, 'OBJECT',   PLAN.OBJECT,	$
		'Type of object or event observed'
	FXADDPAR, HEADER, 'OBJ_ID',   PLAN.OBJ_ID,   'Object ID'
	FXADDPAR, HEADER, 'TRACKING', LOGICAL(PLAN.TRACKING),	$
		'Solar feature tracking (true/false)'
;
;  Add the information about the program.  If the program ID is not found, then
;  use default values.
;
	GET_PROGRAM, PLAN.PROG_ID, PROGRAM
	IF PROGRAM.PROG_ID LE 0 THEN PROGRAM = {PROG_ID: PLAN.PROG_ID,	$
		PROGNAME: ''}
	FXADDPAR, HEADER, 'PROG_ID',  PROGRAM.PROG_ID,	$
		'Multi-study program ID'
	FXADDPAR, HEADER, 'PROGNAME', PROGRAM.PROGNAME,	$
		'Multi-study program name'
;
;  Add the information about the campaign.  If not found, then use default
;  values.
;
	GET_CAMPAIGN, PLAN.CMP_NO, CAMPAIGN
	IF CAMPAIGN.CMP_NO LE 0 THEN CAMPAIGN = {CMP_NO: PLAN.CMP_NO,	$
		CMP_NAME: ''}
	FXADDPAR, HEADER, 'CMP_NO', PLAN.CMP_NO, 'SOHO campaign ID number'
	FXADDPAR, HEADER, 'CMP_NAME', CAMPAIGN.CMP_NAME, 'Campaign name'
;
;  Add the information about the line list.
;
	IF RASTER_DEF.RAS_ID NE -1 THEN BEGIN
		LL_ID = RASTER_DEF.LL_ID 
	END ELSE BEGIN
		GET_DATAWIN,RASTER.HEADER.SCI.DATAWINDOWID,DW
		IF DW.DW_ID NE -1 THEN LL_ID = DW.LL_ID ELSE LL_ID = -1
	ENDELSE
	FXADDPAR, HEADER, 'LL_ID', LL_ID, 'Line list ID number'
;
;  Store the pointing information.
;
	FXADDPAR, HEADER, 'INS_X0', POINTINGS.INS_X0, FORMAT='(F7.1)',	$
		'Prelim. ins. pointing in X from OPS (arcsec)'
	FXADDPAR, HEADER, 'INS_Y0', POINTINGS.INS_Y0, FORMAT='(F7.1)',	$
		'Prelim. ins. pointing in Y from OPS (arcsec)'
	FXADDPAR, HEADER, 'INS_ROLL', POINTINGS.INS_ROLL, FORMAT='(F7.2)', $
		'Preliminary ins. roll angle (degrees CCW)'
	FXADDPAR, HEADER, 'XCEN', POINTINGS.XCEN, FORMAT='(F7.1)',	$
		'Prelim. center in X of field-of-view (arcsec)'
	FXADDPAR, HEADER, 'YCEN', POINTINGS.YCEN, FORMAT='(F7.1)',	$
		'Prelim. center in Y of field-of-view (arcsec)'
	FXADDPAR, HEADER, 'ANGLE', POINTINGS.ANGLE, FORMAT='(F7.2)',	$
		'Prelim. orientation of field-of-view (arcsec)'
	FXADDPAR, HEADER, 'IXWIDTH', POINTINGS.IXWIDTH, FORMAT='(F7.1)', $
		'Prelim. width in X of field-of-view (arcsec)'
	FXADDPAR, HEADER, 'IYWIDTH', POINTINGS.IYWIDTH, FORMAT='(F7.1)', $
		'Prelim. width in Y of field-of-view (arcsec)'
;
;  Store the spacecraft attitude information.
;
	FXADDPAR, HEADER, 'SC_X0', POINTINGS.SC_X0, FORMAT='(F7.1)',	$
		'Preliminary S/C pointing in X (arcsec)'
	FXADDPAR, HEADER, 'SC_Y0', POINTINGS.SC_Y0, FORMAT='(F7.1)',	$
		'Preliminary S/C pointing in Y (arcsec)'
	FXADDPAR, HEADER, 'SC_ROLL', POINTINGS.SC_ROLL, FORMAT='(F7.2)', $
		'Preliminary S/C roll angle (degrees CCW)'
;
;  Store the minimum and maximum wavelengths.
;
	FXADDPAR, HEADER, 'WAVEMIN', WAVELENGTHS.WAVEMIN,	$
		'Minimum wavelength in observation (Angstroms)'
	FXADDPAR, HEADER, 'WAVEMAX', WAVELENGTHS.WAVEMAX,	$
		'Maximum wavelength in observation (Angstroms)'
;
;  Store some additional parameters from the raster header.
;
	FXADDPAR, HEADER, 'COMP_ID', FIX(SCIHEAD.COMPRESSION),	$
		'Telemetry data compression scheme'
	FXADDPAR, HEADER, 'COMP_OPT', UNSIGN(SCIHEAD.COMP_OPTION), $
		'Telemetry data compression option'
	FXADDPAR, HEADER, 'DW_ID',  SCIHEAD.DATAWINDOWID,	$
		'Data extraction window list ID'
	FXADDPAR, HEADER, 'SER_ID',   SCIHEAD.SEQUENCEID,	$
		'On-board series load ID'
	FXADDPAR, HEADER, 'EXPCOUNT', (SCIHEAD.NUMMIRRORPOS > 1) * $
                                      (SCIHEAD.NUMSLITPOS   > 1), $
		'Number of exposures in the raster'
;
;  The exposure time was calculated earlier.
;
	FXADDPAR, HEADER, 'EXPTIME', EXPTIME, FORMAT='(F10.3)',	$
		'Exposure time in seconds'
;
	FXADDPAR, HEADER, 'NX', (SCIHEAD.NUMMIRRORPOS > 1),	$
		'Number of positions in X direction'
	FXADDPAR, HEADER, 'NY', (SCIHEAD.NUMSLITPOS> 1),	$
		'Number of positions in Y direction'
	FXADDPAR, HEADER, 'XSTEP', RASTER.MIRRORSTEP, FORMAT='(F10.3)',	$
		'Step size in arcsec in X direction'
	FXADDPAR, HEADER, 'YSTEP', RASTER.SLITSTEP, FORMAT='(F10.3)',	$
		'Step size in arcsec in Y direction'
;
;  The following parameters are in MCU telemetry format and have to be decoded
;  before putting into the FITS header.
;
	OPS_DECODE, SCIHEAD.OPSLPOSITION, OPSLBITS, OPSLPOSITION
	FXADDPAR, HEADER, 'OPSLBITS', OPSLBITS,		$
		'OPS L status bits at start of raster'
	FXADDPAR, HEADER, 'OPS_L',    OPSLPOSITION,		$
		'OPS L position at start of raster'
;
	OPS_DECODE, SCIHEAD.OPSRPOSITION, OPSRBITS, OPSRPOSITION
	FXADDPAR, HEADER, 'OPSRBITS', OPSRBITS,		$
		'OPS R status bits at start of raster'
	FXADDPAR, HEADER, 'OPS_R',    OPSRPOSITION,		$
		'OPS R position at start of raster'
;
;  The status bits in the raster header should be zero, so there's no point in
;  writing them to the FITS file.
;
	SLITPOS_DECODE, SCIHEAD.SLITPOSITION, SLITBITS, SLITPOSITION
;	FXADDPAR, HEADER, 'SLITBITS', SLITBITS,		$
;		'Slit position status bits at start of raster'
	FXADDPAR, HEADER, 'SLIT_POS', SLITPOSITION,		$
		'Slit position at start of raster'
;
	IF TAG_EXIST(PLAN,'SLIT_NUM', /TOP_LEVEL) THEN	$
		SLIT_NUM = PLAN.SLIT_NUM ELSE		$
		SLIT_NUM = FIX(SCIHEAD.SLITNUMBER)
	FXADDPAR, HEADER, 'SLIT_NUM', SLIT_NUM, 'Slit number'
;
	FXADDPAR, HEADER, 'MIR_POS',  FIX(SCIHEAD.MIRRORPOSITION), $
		'Mirror position at start of raster'
	FXADDPAR, HEADER, 'NWINDOWS', FIX(RASTER.HEADER.NWINDOWS), $
		'Number of data windows'
;
;  Add those keywords derived from the science process status parameter.
;
	FXADDPAR, HEADER, 'EV_ENAB',  LOGICAL(RASTER.SP_STATUS.EVENT_REC), $
		'Event recognition enabled'
	FXADDPAR, HEADER, 'COMP_ERR', LOGICAL(RASTER.SP_STATUS.COMP_ERR), $
		'Data compression scheme error'
	IF DETECTOR EQ 'NIS' THEN BEGIN
		FXADDPAR, HEADER, 'VDS_ORI',	$
			LOGICAL(RASTER.SP_STATUS.VDS_ORIENT),	$
			'VDS telemetry data oriented by columns'
		FXADDPAR, HEADER, 'VDS_ACC',	$
			LOGICAL(RASTER.SP_STATUS.VDS_ACCUM),	$
			'VDS accumulate mode'
	ENDIF
;
;  Add in the parameters which are derived from other parameters.
;
	IF RASTER_DEF.RAS_ID GT 0 THEN BEGIN
		OBS_SEQ = 'R' + TRIM(RASTER_DEF.RAS_ID) + 'V' + TRIM(RAS_VAR)
	END ELSE OBS_SEQ = 'ENG'
	FXADDPAR, HEADER, 'OBS_SEQ', OBS_SEQ, 'Observing sequence'
	OBS_MODE = DETECTOR + '-S' + TRIM(SLIT_NUM) + '-R' +	$
		TRIM(RASTER_DEF.RAS_ID>0) + '-E' + TRIM(EXPTIME)
	FXADDPAR, HEADER, 'OBS_MODE', OBS_MODE, 'Observing mode'
;
;  Add in the parameters from the current state.
;
	ERRMSG=''
	GET_VDS_STATE, TIMES.OBT_TIME, STATE, ERRMSG=ERRMSG
	IF ERRMSG EQ '' THEN IF STATE.DATE NE 0 THEN BEGIN
	    IF DETECTOR EQ 'NIS' THEN BEGIN
		IF TAG_EXIST(PLAN,'VDS_MODE', /TOP_LEVEL) THEN	$
			VDS_MODE = PLAN.VDS_MODE ELSE VDS_MODE = STATE.VDS_READ
		FXADDPAR, HEADER, 'VDS_MODE', VDS_MODE, 'VDS readout mode'
		IF TAG_EXIST(PLAN,'VDS_PMCP', /TOP_LEVEL) THEN	$
			VDS_PMCP = PLAN.VDS_PMCP ELSE VDS_PMCP = STATE.VDS_PMCP
		FXADDPAR, HEADER, 'VDS_PMCP', VDS_PMCP,	$
			'VDS MCP programmable voltage setting'
	    ENDIF
	ENDIF
;
;  For the GIS detector, add in the GSET_ID.
;
	IF DETECTOR EQ 'GIS' THEN BEGIN
	    IF TAG_EXIST(PLAN, 'GSET_ID', /TOP_LEVEL) THEN	$
		    GSET_ID = PLAN.GSET_ID ELSE GSET_ID = -1
	    FXADDPAR, HEADER, 'GSET_ID', GSET_ID, 'GIS setup ID'
;
;  Also add in the parameters from the Engineering B packet.
;
	    ENGB_STORE, ENGB, /EXTRACT
	    IF ENGB.BUGHV(0) NE -1 THEN BEGIN
		ENGB = ENGB_CALIB( ENGB )
;
		FXADDPAR, HEADER, 'BUGHV1', ENGB.BUGHV(0),	$
			'High voltage, detector 1'
		FXADDPAR, HEADER, 'BUGHV2', ENGB.BUGHV(1),	$
			'High voltage, detector 2'
		FXADDPAR, HEADER, 'BUGHV3', ENGB.BUGHV(2),	$
			'High voltage, detector 3'
		FXADDPAR, HEADER, 'BUGHV4', ENGB.BUGHV(3),	$
			'High voltage, detector 4'
;
		FXADDPAR, HEADER, 'BKGCHK1', ENGB.BKGCHK(0),	$
			'Lookup table checksum, detector 1'
		FXADDPAR, HEADER, 'BKGCHK2', ENGB.BKGCHK(1),	$
			'Lookup table checksum, detector 2'
		FXADDPAR, HEADER, 'BKGCHK3', ENGB.BKGCHK(2),	$
			'Lookup table checksum, detector 3'
		FXADDPAR, HEADER, 'BKGCHK4', ENGB.BKGCHK(3),	$
			'Lookup table checksum, detector 4'
;
		FXADDPAR, HEADER, 'BIGMCP1', ENGB.BIGMCP(0),	$
			'High voltage current, detector 1'
		FXADDPAR, HEADER, 'BIGMCP2', ENGB.BIGMCP(1),	$
			'High voltage current, detector 2'
		FXADDPAR, HEADER, 'BIGMCP3', ENGB.BIGMCP(2),	$
			'High voltage current, detector 3'
		FXADDPAR, HEADER, 'BIGMCP4', ENGB.BIGMCP(3),	$
			'High voltage current, detector 4'
;
		FXADDPAR, HEADER, 'BUGMCPB1', ENGB.BUGMCPB(0),	$
			'MCP F/face, detector 1'
		FXADDPAR, HEADER, 'BUGMCPB2', ENGB.BUGMCPB(1),	$
			'MCP F/face, detector 2'
		FXADDPAR, HEADER, 'BUGMCPB3', ENGB.BUGMCPB(2),	$
			'MCP F/face, detector 3'
		FXADDPAR, HEADER, 'BUGMCPB4', ENGB.BUGMCPB(3),	$
			'MCP F/face, detector 4'
;
		FXADDPAR, HEADER, 'BKGRCD1', ENGB.BKGRCD(0),	$
			'Raw event count, detector 1'
		FXADDPAR, HEADER, 'BKGRCD2', ENGB.BKGRCD(1),	$
			'Raw event count, detector 2'
		FXADDPAR, HEADER, 'BKGRCD3', ENGB.BKGRCD(2),	$
			'Raw event count, detector 3'
		FXADDPAR, HEADER, 'BKGRCD4', ENGB.BKGRCD(3),	$
			'Raw event count, detector 4'
;
		FXADDPAR, HEADER, 'BKGULCD1', ENGB.BKGULCD(0),	$
			'Upper level discriminator count, detector 1'
		FXADDPAR, HEADER, 'BKGULCD2', ENGB.BKGULCD(1),	$
			'Upper level discriminator count, detector 2'
		FXADDPAR, HEADER, 'BKGULCD3', ENGB.BKGULCD(2),	$
			'Upper level discriminator count, detector 3'
		FXADDPAR, HEADER, 'BKGULCD4', ENGB.BKGULCD(3),	$
			'Upper level discriminator count, detector 4'
;
		FXADDPAR, HEADER, 'BKGHV1L', ENGB.BKGHV_L(0),	$
			'High voltage last set value, detector 1'
		FXADDPAR, HEADER, 'BKGHV2L', ENGB.BKGHV_L(1),	$
			'High voltage last set value, detector 2'
		FXADDPAR, HEADER, 'BKGHV3L', ENGB.BKGHV_L(2),	$
			'High voltage last set value, detector 3'
		FXADDPAR, HEADER, 'BKGHV4L', ENGB.BKGHV_L(3),	$
			'High voltage last set value, detector 4'
;
		FXADDPAR, HEADER, 'BKGLDLD1', ENGB.BKGLDLD(0),	$
			'Last setting low level discriminator, detector 1'
		FXADDPAR, HEADER, 'BKGLDLD2', ENGB.BKGLDLD(1),	$
			'Last setting low level discriminator, detector 2'
		FXADDPAR, HEADER, 'BKGLDLD3', ENGB.BKGLDLD(2),	$
			'Last setting low level discriminator, detector 3'
		FXADDPAR, HEADER, 'BKGLDLD4', ENGB.BKGLDLD(3),	$
			'Last setting low level discriminator, detector 4'
	    ENDIF
	ENDIF
;
;  If the plan structure contains a ZONE_ID flag, then put it in the FITS
;  header.
;
	IF TAG_EXIST(PLAN,'ZONE_ID', /TOP_LEVEL) THEN	$
		FXADDPAR, HEADER, 'ZONE_ID', PLAN.ZONE_ID, 'Pointing zone ID'
;
;  Assume that the sequence is valid, unless known otherwise.
;
	IF TAG_EXIST(PLAN,'SEQVALID', /TOP_LEVEL) THEN	$
		SEQVALID = PLAN.SEQVALID ELSE SEQVALID = 1B
	SEQVALID = LOGICAL(SEQVALID)
	FXADDPAR, HEADER, 'SEQVALID', SEQVALID, 'Valid data (true/false)'
;
;  Add a keyword signalling whether or not the data is processed from the
;  realtime/quicklook files, or from the final CDROM.
;
	IF KEYWORD_SET(FINALDIST) THEN DATASRC = 'Final Distribution (CDROM)' $
		ELSE DATASRC = 'Quicklook and realtime telemetry'
	FXADDPAR, HEADER, 'DATASRC', DATASRC, 'Data source'
;
;  Add any comments.
;
	LIST_EXP_COMM, PLAN.SEQ_NUM, COMM, N_FOUND
	IF N_FOUND GT 0 THEN FOR I_COMM = 0, N_FOUND-1 DO	$
		FXADDPAR, HEADER, 'COMMENT', COMM(I_COMM).COMMENT
;
	RETURN, HEADER
	END
