	PRO CDROM_AVG_TEMPS, DRIVE=DRIVE, DESTINATION=DESTINATION,	$
		DATE=DATE_SEL, ERRMSG=ERRMSG
;+
; Project     :	SOHO - CDS
;
; Name        :	CDROM_AVG_TEMPS
;
; Purpose     :	Calculate 5 minute average temperatures from CDROM
;
; Category    :	Calibration, Class4
;
; Explanation :	This routine reads in the telemetry from a CDROM containing CDS
;		telemetry, and calculates the 5 minute averaged temperatures.
;		These temperatures are then written to FITS binary table files
;		in the directory $CDS_VDS_CAL_WAV_W, with one file for every
;		month.
;
; Syntax      :	CDROM_AVG_TEMPS
;
; Examples    :	IDL> $ cd-mount
;		IDL> cdrom_avg_temps
;		IDL> $ cd-umount
;
; Inputs      :	None.
;
; Opt. Inputs :	None.
;
; Outputs     :	The 5-minute averaged temperatures are written to FITS binary
;		tables in the directory $CDS_VDS_CAL_WAV_W
;
; Opt. Outputs:	None.
;
; Keywords    :	DRIVE	    = A character string giving the same of the mount
;			      point for the CDROM.  The default is "/cdrom" on
;			      Unix systems, and "CDROM:[000000]" on VMS
;			      systems.
;
;		DESTINATION = The directory to write the output files.  The
;			      default is given by the environment variable
;			      CDS_VDS_CAL_WAV_W.
;
;		DATE	    = A specific date to extract from the CDROM.  Can
;			      be in any standard CDS time format.  If not set,
;			      then the entire CDROM is processed.
;
;		ERRMSG = If defined and passed, then any error messages will be
;			 returned to the user in this parameter rather than
;			 depending on the MESSAGE routine in IDL.  If no errors
;			 are encountered, then a null string is returned.  In
;			 order to use this feature, ERRMSG must be defined
;			 first, e.g.
;
;				ERRMSG = ''
;				CDROM_AVG_TEMPS, ERRMSG=ERRMSG, ...
;				IF ERRMSG NE '' THEN ...
;
; Calls       :	FINDFILE, CONCAT_DIR, BREAK_FILE, STR2UTC, ANYTIM2UTC,
;		OPEN_TM_FILE, TAI2UTC, CHECK_SUM, IEEE_TO_HOST, TM_CALIB, UNIQ,
;		DATE2MJD, FILE_EXIST, FXBOPEN, FXBREAD, FXBCLOSE, DELVARX,
;		FXHMAKE, FXADDPAR, FXWRITE, FXBHMAKE, FXBADDCOL, FXBCREATE,
;		FXBWRITE, FXBFINISH
;
; Common      :	The common block from fitsgen.cmn is used.
;
; Restrictions:	A valid CDROM containing CDS telemetry must be mounted.
;
; Side effects:	None.
;
; Prev. Hist. :	None.
;
; History     :	Version 1, 21-Dec-1999, William Thompson, GSFC
;		Version 2, 21-Jul-2000, William Thompson, GSFC
;			Handle times outside range
;		Version 3, 25-Jul-2000, William Thompson, GSFC
;			Detect if no data on CDROM
;
; Contact     :	WTHOMPSON
;-
;
@fitsgen.cmn
	ON_ERROR, 2
	TM_DEFINE_STRUC
	MON_NAME = ['January', 'February', 'March', 'April', 'May', 'June', $
		'July', 'August', 'September', 'October', 'November',	$
		'December']
;
;  Determine the value of the DRIVE parameter.
;
	IF N_ELEMENTS(DRIVE) EQ 0 THEN BEGIN
	    CASE OS_FAMILY() OF
		'unix':	DRIVE = '/cdrom'
		'vms':	DRIVE = 'CDROM:[000000]'
		ELSE:	BEGIN
		    MESSAGE = 'Only supported in VMS or Unix'
		    GOTO, HANDLE_ERROR
		    END
	    ENDCASE
	ENDIF
;
;  Determine the destination directory.
;
	IF N_ELEMENTS(DESTINATION) EQ 0 THEN BEGIN
	    DESTINATION = GETENV('CDS_VDS_CAL_WAV_W')
	    IF DESTINATION EQ '' THEN BEGIN
		MESSAGE = 'Environment variable CDS_VDS_CAL_WAV_W not defined'
		GOTO, HANDLE_ERROR
	    ENDIF
	ENDIF
;
;  Decide whether or not upper- or lowercase filenames are being used.
;
	VOLDESC = FINDFILE(CONCAT_DIR(DRIVE,'voldesc.sfd*'), COUNT=COUNT)
	LOWER = COUNT NE 0
	IF NOT LOWER THEN BEGIN
	    VOLDESC = FINDFILE(CONCAT_DIR(DRIVE,'VOLDESC.SFD*'), COUNT=COUNT)
	    UPPER = COUNT NE 0
	    IF NOT UPPER THEN BEGIN
		MESSAGE = 'Incorrect CDROM mounted'
		GOTO, HANDLE_ERROR
	    ENDIF
	ENDIF
;
;  Set up the name of the base directory for CDS telemetry data.
;
	DIRS = ['data', 'so']
	IF NOT LOWER THEN DIRS = STRUPCASE(DIRS)
	BASE = CONCAT_DIR(DRIVE, /DIR, DIRS(0))
	BASE = CONCAT_DIR(BASE,  /DIR, DIRS(1))
;
;  Step through the three CDS telemetry rates, and collect all the filenames.
;
	RATES = ['g026', 'g027', 'g028']
	LZ = 'lz'
	DAT_FILES = '*.d*'
	SFD_FILES = '*.s*'
	IF NOT LOWER THEN BEGIN
	    RATES = STRUPCASE(RATES)
	    LZ = STRUPCASE(LZ)
	    DAT_FILES = STRUPCASE(DAT_FILES)
	    SFD_FILES = STRUPCASE(SFD_FILES)
	ENDIF
	FILES = ''
	SFDUS = ''
	FOR I_RATE = 0, 2 DO BEGIN
;
;  Set up the name of the directory containing the telemetry data.
;
	    PATH = CONCAT_DIR(BASE, /DIR, RATES(I_RATE))
	    PATH = CONCAT_DIR(PATH, /DIR, LZ)
;
;  Find all the SFDU and data files in this directory.  Make sure that only the
;  highest version number is used.
;
	    TEMP = FINDFILE(CONCAT_DIR(PATH, SFD_FILES), COUNT=COUNT)
	    IF COUNT GT 0 THEN BEGIN
		BREAK_FILE, TEMP, DISK, DIR, NAME
		S = REVERSE(SORT([NAME]))
		TEMP = TEMP(S)
		NAME = NAME(S)
		LAST = ''
		FOR I = 0, COUNT-1 DO BEGIN
		    TEST = STRMID(NAME(I),0,4)
		    IF TEST NE LAST THEN SFDUS = [SFDUS, TEMP(I)]
		    LAST = TEST
		ENDFOR
	    ENDIF
;
	    TEMP = FINDFILE(CONCAT_DIR(PATH, DAT_FILES), COUNT=COUNT)
	    IF COUNT GT 0 THEN BEGIN
		BREAK_FILE, TEMP, DISK, DIR, NAME
		S = REVERSE(SORT([NAME]))
		TEMP = TEMP(S)
		NAME = NAME(S)
		LAST = ''
		FOR I = 0, COUNT-1 DO BEGIN
		    TEST = STRMID(NAME(I),0,4)
		    IF TEST NE LAST THEN FILES = [FILES, TEMP(I)]
		    LAST = TEST
		ENDFOR
	    ENDIF
	ENDFOR
;
;  Remove the dummy first filename.
;
	N_FILES = N_ELEMENTS(FILES) - 1
	IF N_FILES EQ 0 THEN BEGIN
		MESSAGE = 'No data files found on the CDROM'
		GOTO, HANDLE_ERROR
	ENDIF
	FILES = FILES(1:*)
	SFDUS = SFDUS(1:*)
;
;  Open up all the SFDU files, and get the start and stop times.
;
	GET_LUN, UNIT
	LINE = ''
	FOR I_FILE = 0, N_FILES-1 DO BEGIN
	    OPENR, UNIT, SFDUS(I_FILE)
	    WHILE NOT EOF(UNIT) DO BEGIN
		READF, UNIT, LINE
		IF STRMID(LINE,0,11) EQ 'START_DATE=' THEN	$
			START_DATE = STRMID(LINE,11,STRPOS(LINE,';')-11)
		IF STRMID(LINE,0,10) EQ 'STOP_DATE=' THEN	$
			STOP_DATE = STRMID(LINE,10,STRPOS(LINE,';')-10)
	    ENDWHILE
	    CLOSE, UNIT
;
	    START_DATE = STR2UTC(START_DATE)
	    STOP_DATE  = STR2UTC(STOP_DATE)
	    IF I_FILE EQ 0 THEN BEGIN
		STARTS = START_DATE
		STOPS  = STOP_DATE
	    END ELSE BEGIN
		STARTS = [STARTS, START_DATE]
		STOPS  = [STOPS,  STOP_DATE ]
	    ENDELSE
	ENDFOR
	DATES  = STARTS.MJD
	FREE_LUN, UNIT
;
;  If the DATE keyword was set, then filter out all but the files pertaining to
;  the selected date.
;
	IF N_ELEMENTS(DATE_SEL) EQ 1 THEN BEGIN
	    TEMP = ANYTIM2UTC(DATE_SEL)
	    W = WHERE(STARTS.MJD EQ TEMP.MJD, N_FILES)
	    IF N_FILES EQ 0 THEN BEGIN
		MESSAGE = 'Selected date not found on CDROM'
		GOTO, HANDLE_ERROR
	    ENDIF
	    STARTS = STARTS(W)
	    STOPS  = STOPS(W)
	    FILES  = FILES(W)
	ENDIF
;
;  Define the output arrays.
;
	MJD0 = MIN(STARTS.MJD) - 1
	MJD1 = MAX( STOPS.MJD) + 1
	NDAYS = MJD1 - MJD0
	TIME = REPLICATE(STARTS(0), 289, NDAYS)
	TIME.MJD = MJD0 + REBIN( LINDGEN(1,NDAYS),   289, NDAYS)
	TIME.TIME = 300000L * REBIN( LINDGEN(289,1), 289, NDAYS)
	N_TIME = 289L*NDAYS
	TIME = REFORM(TIME, N_TIME, /OVERWRITE)
	BTM  = FLTARR(32, N_TIME)
	NBTM = INTARR(32, N_TIME)
;
;  Step through the data files.
;
	GET_LUN, UNIT
	FOR I_FILE = 0, N_FILES-1 DO BEGIN
	    FILE = FILES(I_FILE)
	    PRINT, 'Reading packets from file ' + FILE
	    IF NOT OPEN_TM_FILE(UNIT, FILE, MODE) THEN BEGIN
		MESSAGE = 'Unable to open file ' + FILE
		GOTO, HANDLE_ERROR
	    ENDIF
	    IF MODE NE 4 THEN BEGIN
		MESSAGE = 'File ' + FILE + ' not opened with correct mode'
		GOTO, HANDLE_ERROR
	    ENDIF
;
;  Step through the packets in groups of 10000.
;
	    I_PACK = 0L
	    UTC = TAI2UTC(0.0D0)		;Define the UTC structure
	    WHILE I_PACK LT NUM_PACK DO BEGIN
		N_PACK = 10000 < (NUM_PACK - I_PACK)
		PP = BYTARR(300,N_PACK)
		READU, UNIT, PP
;
;  Find all the engineering B packets, and process those who pass the checksum
;  test.
;
		WB = WHERE(PP(12,*) EQ '0B'X, NB)
		UTC = REPLICATE(UTC(0), NB>1)
		BTM0 = INTARR(32,NB>1)
		GOOD = BYTARR(NB>1)
		FOR J = 0,NB-1 DO BEGIN
		    P = PP(*,WB(J))
		    CHKSUM = (FIX(P([299,298]),0,1))(0)
		    IF CHECK_SUM(P,3,148) EQ CHKSUM THEN BEGIN
			BTM0(*,J) = FIX(P(50:113),0,32)
			UTC(J) = TAI2UTC(OBT2TAI(P(6:11)))
			GOOD(J) = 1
		    ENDIF
		ENDFOR
;
;  Filter out the packets that didn't pass the checksum test.  Calibrate the
;  rest.
;
		W = WHERE(GOOD EQ 1, COUNT)
		IF COUNT GT 0 THEN BEGIN
		    IEEE_TO_HOST, BTM0
		    BTM0 = BTM0 AND 'FFF'X
		    BTM1 = FLTARR(32,COUNT)
		    FOR K=0,31 DO BTM1(K,*) =		$
			    TM_CALIB('BTM'+NTRIM(K), BTM0(K,W), /QUIET)
		    UTC = UTC(W)
;
;  Step through the good engineering B packets, and determine where it falls in
;  the output array.
;
		    FOR J = 0,COUNT-1 DO BEGIN
			TIME1 = UTC(J).TIME - 300000L
			TIME2 = UTC(J).TIME
			WJ = (WHERE((UTC(J).MJD EQ TIME.MJD) AND	$
				(TIME1 LT TIME.TIME) AND		$
				(TIME2 GE TIME.TIME), COUNT))(0)
;
;  Don't process any packets where the calibration failed for any of the
;  temperatures (recognized as a temperature of -30).  Also, don't process any
;  packets outside the expected time range.
;
			IF COUNT EQ 1 THEN BEGIN
			    WI = WHERE(BTM1(*,J) NE -30, COUNT)
			    IF COUNT GT 0 THEN BEGIN
				BTM(WI,WJ)  = BTM(WI,WJ) + BTM1(WI,J)
				NBTM(WI,WJ) = NBTM(WI,WJ) + 1
			    ENDIF
			ENDIF
		    ENDFOR
		ENDIF
;
;  Step to the next group of packets.
;
		I_PACK = I_PACK + N_PACK
	    ENDWHILE
;
;  Step to the next file.
;
	    CLOSE, UNIT
	ENDFOR
	FREE_LUN, UNIT
;
;  Filter out points which don't have at least 5 measurements in them.
;
	W = WHERE(AVERAGE(NBTM,1) GE 5, COUNT)
	IF COUNT EQ 0 THEN BEGIN
	    MESSAGE = 'CDROM contains no valid data'
	    GOTO, HANDLE_ERROR
	ENDIF
	TIME = TIME(W)
	BTM = BTM(*,W) / (NBTM(*,W) > 1)
	TIME.TIME = TIME.TIME + 150000L
;
;  Determine all the days that were measured.
;
	MJD = TIME.MJD
	MJD = MJD(UNIQ(MJD))
;
;  Determine all the months.
;
	MJD2DATE, MJD, YEAR, MONTH, DAY
	S_MONTH = STRTRIM(YEAR,2) + '_' + STRING(MONTH,FORMAT='(I2.2)')
	INDEX = UNIQ(S_MONTH)
	YEARS    = YEAR(INDEX)
	MONTHS   = MONTH(INDEX)
	S_MONTHS = S_MONTH(INDEX)
;
;  Step through each month.  Determine all the days in the month.  Create the
;  data arrays to be stored in the file.
;
	FOR I_MONTH = 0,N_ELEMENTS(S_MONTHS)-1 DO BEGIN
	    MJD1 = DATE2MJD(YEARS(I_MONTH), MONTHS(I_MONTH), 1)
	    NDAYS = DATE2MJD(YEARS(I_MONTH), MONTHS(I_MONTH)+1, 1) - MJD1
	    MJDS = MJD1 + REBIN( LINDGEN(1, NDAYS), 288, NDAYS)
	    TIMES = 150000L + 300000L * REBIN( LINDGEN(288,1), 288, NDAYS)
	    MJDS  = REFORM(MJDS,  288*NDAYS)
	    TIMES = REFORM(TIMES, 288*NDAYS)
	    BTMS = REPLICATE(-30., 32, 288*NDAYS)
	    MEAS = FLTARR(288*NDAYS)
;
;  If a temperature file for the month already exists, then read it in, and
;  store the data in the appropriate places in the output array.
;
	    FILENAME = 'temps_' + S_MONTHS(I_MONTH) + '.fits'
	    FILE = CONCAT_DIR('$CDS_VDS_CAL_WAV', FILENAME)
	    IF FILE_EXIST(FILE) THEN BEGIN
		FXBOPEN, LUN0, FILE, 1
		FXBREAD, LUN0, MJD0, 'MJD'
		FXBREAD, LUN0, TIME0, 'TIME'
		FXBREAD, LUN0, BTM0, 'BTM', NANVALUE=-30
		FXBCLOSE, LUN0
		DELVARX, LUN0
		FOR J=0,N_ELEMENTS(MJD0)-1 DO BEGIN
		    WJ = WHERE((MJD0(J) EQ MJDS) AND (TIME0(J) EQ TIMES))
		    BTMS(*,WJ) = BTM0(*,J)
		    MEAS(WJ) = 1
		ENDFOR
	    ENDIF
;
;  Step through the days in the target month that were read in from the CDROM.
;  Store the data in the appropriate places in the output array.
;
	    WI = WHERE((YEARS(I_MONTH) EQ YEAR) AND	$
		    (MONTHS(I_MONTH) EQ MONTH), ICOUNT)
	    FOR J = 0,ICOUNT-1 DO BEGIN
		WJ = WHERE(MJD(WI(J)) EQ TIME.MJD, JCOUNT)
		FOR K = 0,JCOUNT-1 DO BEGIN
		   WK = WHERE((TIME(WJ(K)).MJD EQ MJDS) AND	$
			    (TIME(WJ(K)).TIME EQ TIMES))
		   BTMS(*,WK) = BTM(*,WJ(K))
		   MEAS(WK) = 1
		ENDFOR
	    ENDFOR
;
;  Filter out times that weren't measured.
;
	    W = WHERE(MEAS EQ 1, NTIMES)
	    MJDS  = MJDS(W)
	    TIMES = TIMES(W)
	    BTMS  = BTMS(*,W)
;
;  Save the data in a FITS file.
;
	    FILE = CONCAT_DIR(DESTINATION, 'temporary.fits')
	    FXHMAKE, HEADER, /INIT, /EXTEND, /DATE
	    FXADDPAR, HEADER, 'FILENAME', FILENAME
	    FXADDPAR, HEADER, 'COMMENT',	$
		    'This file contains 5-minute averaged CDS temperatures'
	    FXADDPAR, HEADER, 'COMMENT', '        for ' +		$
		    MON_NAME(MONTHS(I_MONTH)-1) + ', ' +	$
		    NTRIM(YEARS(I_MONTH))
	    FXWRITE, FILE, HEADER
	    FXBHMAKE, HEADER, NTIMES, 'TEMPS', 'CDS temperatures'
	    FXBADDCOL, IMJD, HEADER, 0L, 'MJD', 'Modified Julian Day'
	    FXBADDCOL, ITIME, HEADER, 0L, 'TIME', 'Time of day (milliseconds)'
	    FXBADDCOL, IBTM, HEADER, FLTARR(32), 'BTM', 'Temperatures (C)'
	    FXBCREATE, LUN, FILE, HEADER
	    FOR JTIME = 0,NTIMES-1 DO BEGIN
		FXBWRITE, LUN, MJDS(JTIME), IMJD, JTIME+1
		FXBWRITE, LUN, TIMES(JTIME), ITIME, JTIME+1
		FXBWRITE, LUN, BTMS(*,JTIME), IBTM, JTIME+1, NANVALUE=-30
	    ENDFOR
	    FXBFINISH, LUN
	    DELVARX, LUN
	    SPAWN, 'mv ' + FILE + ' ' + CONCAT_DIR(DESTINATION, FILENAME)
	ENDFOR
;
	PRINT, 'Finished processing CDROM'
	RETURN
;
;  Error handling point.
;
HANDLE_ERROR:
	IF N_ELEMENTS(UNIT) EQ 1 THEN FREE_LUN, UNIT
	IF N_ELEMENTS(LUN0) EQ 1 THEN FXBCLOSE, LUN0
	IF N_ELEMENTS(LUN)  EQ 1 THEN FXBFINISH, LUN
	IF N_ELEMENTS(ERRMSG) EQ 0 THEN MESSAGE, MESSAGE ELSE	$
		ERRMSG = 'CDROM_AVG_TEMPS: ' + MESSAGE
;
	END
