	PRO GET_PLAN, INSTRUMENT, DATE, OBS, ERRMSG=ERRMSG
;+
; Project     :	SOHO - CDS
;
; Name        :	GET_PLAN
;
; Purpose     :	Extracts a SoHO science plan observation
;
; Explanation :	This routine extracts parameters which describe the SoHO
;		science plan at a particular point in time.
;
; Use         :	GET_PLAN, DATE, OBS
;
; Inputs      :	INSTRUMENT = The name or code value for the instrument to
;			     retrieve the plan entry for.
;		DATE	   = The date/time value that the user wishes the
;			     science plan record for.  This can be in any of
;			     the standard CDS time formats.
;
; Opt. Inputs :	None.
;
; Outputs     :	OBS	= Structure containing the science plan record.  It
;			  contains the following tags:
;
;			STRUCT_TYPE  = The character string 'SOHO-PLAN'.
;			INSTRUME     = Single letter code specifying the
;				       instrument.
;			SCI_OBJ      = Science objective from the daily science
;				       meeting
;			SCI_SPEC     = Specific science objective from meeting
;			NOTES	     = Further notes about the observation
;			START_TIME   = Date/time of beginning of observation,
;				       in TAI format
;			END_TIME     = Date/time of end of observation, in TAI
;				       format
;			OBJECT	     = Code for object planned to be observed
;			OBJ_ID	     = Object identification
;			PROG_ID	     = Program ID, linking one or more studies
;				       together
;			CMP_NO	     = Campaign number
;			XCEN	     = Center(s) of instrument FOV along X
;				       axis, given as a character string.
;			YCEN	     = Center(s) of instrument FOV along Y
;				       axis, given as a character string.
;			DISTURBANCES = Description of any disturbances
;
;		If no entry is found, then a simpler structure is returned with
;		INSTRUME set to the null string.
;
; Opt. Outputs:	None.
;
; Keywords    :
;       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 = ''
;                       GET_PLAN, ERRMSG=ERRMSG, ... 
;                       IF ERRMSG NE '' THEN ...
;
;
; Calls       :	DATATYPE, DBOPEN, DBFIND, DBEXT, DBCLOSE, TRIM, GET_INSTRUMENT
;
; Common      :	None.
;
; Restrictions:	None.
;
; Side effects:	None.
;
; Category    :	Planning, Databases.
;
; Prev. Hist. :	None.
;
; Written     :	William Thompson, GSFC, 26 July 1994
;
; Modified    :	Version 1, William Thompson, GSFC, 3 August 1994
;               Version 2, Liyun Wang, GSFC/ARC, September 22, 1994
;                  Added the keyword ERRMSG.
;		Version 3, William Thompson, GSFC, 24 October 1994
;			Fixed bug with INSTRUME vs. INSTRUMENT.
;		Version 4, William Thompson, GSFC, 17 November 1994
;			Fixed so that if time is on boundary, then the plan
;			which starts then is picked.
;		Version 5, William Thompson, GSFC, 26 January 1995
;			Added tag STRUCT_TYPE
;		Version 6, William Thompson, GSFC, 28 April 1995
;			Returns an error string when no entry is found.
;		Version 7, William Thompson, GSFC, 8 May 1995
;			Modified to pay attention to DELETED field in database
;		Version 8, William Thompson, GSFC, 18 August 1995
;			Added tags XCEN, YCEN
;		Version 9, William Thompson, GSFC, 26 May 1998
;			Look for entries in "_year" files
;
; Version     :	Version 9, 26 May 1998
;-
;
	ON_ERROR, 2
;
;  Initialize the output structure, in case any errors occur.
;
	OBS = {INSTRUME: ''}
;
;  Check the number of parameters.
;
        IF N_PARAMS() NE 3 THEN BEGIN
           MESSAGE = 'Syntax:  GET_PLAN, INSTRUMENT, DATE, OBS'
	   GOTO, HANDLE_ERROR
        ENDIF
;
;  Check the input parameters.
;
	IF DATATYPE(INSTRUMENT,1) NE 'String' THEN BEGIN
           MESSAGE = 'INSTRUMENT must be a character string'
           GOTO, HANDLE_ERROR
	END ELSE IF N_ELEMENTS(INSTRUMENT) GT 1 THEN BEGIN
           MESSAGE = 'INSTRUMENT must be a scalar'
           GOTO, HANDLE_ERROR
	ENDIF
;
	IF N_ELEMENTS(DATE) NE 1 THEN BEGIN
           MESSAGE = 'DATE must be a scalar'
           GOTO, HANDLE_ERROR
	ENDIF
;
;  Make sure the instrument parameter is meaningful.
;
	GET_INSTRUMENT, INSTRUMENT, INS_DESC
	IF INS_DESC.CODE EQ '' THEN BEGIN
           MESSAGE = 'Instrument ' + INSTRUMENT + ' not recognized'
           GOTO, HANDLE_ERROR
	ENDIF
;
;  Convert the date to TAI format.
;
	IF DATATYPE(DATE,1) EQ 'Double' THEN TAI = DATE ELSE	$
		TAI = UTC2TAI(DATE)
;
;  Open the database.
;
	TRAILER = ''
;
OPEN_DATABASE:
	DBOPEN, 'sci_plan' + TRAILER
;
;  Search for entries with dates spanning that given by the user.
;
	ENTRIES = DBFIND('END_TIME>' + TRIM(TAI,'(F15.3)') + ',START_TIME<' + $
		TRIM(TAI,'(F15.3)') + ',INSTRUME=' + INS_DESC.CODE +	$
		',DELETED=N', /SILENT)
;
;  If no entries were found, then try opening the database with the year.
;  Otherwise, return immediately.
;
	IF !ERR EQ 0 THEN BEGIN
	    IF TRAILER EQ '' THEN BEGIN
		TEMP = ANYTIM2UTC(DATE,/EXT)
		TRAILER = "_" + TRIM(TEMP.YEAR)
		FILE = FIND_WITH_DEF('sci_plan'+TRAILER+'.dbf', '$ZDBASE')
		IF FILE NE '' THEN GOTO, OPEN_DATABASE
	    ENDIF
	    MESSAGE = 'Plan entry not found'
	    GOTO, HANDLE_ERROR
	ENDIF
;
;  Extract the entries.
;
	DBEXT, ENTRIES, 'instrume,sci_obj,sci_spec,notes,start_time,end_time',$
		INSTRUME, SCI_OBJ, SCI_SPEC, NOTES, START_TIME, END_TIME
	DBEXT, ENTRIES, 'object,obj_id,prog_id,cmp_no,xcen,ycen,disturbances',$
		OBJECT, OBJ_ID, PROG_ID, CMP_NO, XCEN, YCEN, DISTURBANCES
;
;  If more than one entry has been found, then use the one with the closest
;  start time to the requested time.  This avoids problems with times which are
;  right on the boundaries between entries.
;
	DIFF = ABS(START_TIME - TAI)
	I = (WHERE(DIFF EQ MIN(DIFF)))(0)
;
;  Define the output structure.
;
	OBS = { STRUCT_TYPE: 'SOHO-PLAN',	$
		INSTRUME: INSTRUME(I),		$
		SCI_OBJ: SCI_OBJ(I),		$
		SCI_SPEC: SCI_SPEC(I),		$
		NOTES: NOTES(I),		$
		START_TIME: START_TIME(I),	$
		END_TIME: END_TIME(I),		$
		OBJECT: OBJECT(I),		$
		OBJ_ID: OBJ_ID(I),		$
		PROG_ID: PROG_ID(I),		$
		CMP_NO: CMP_NO(I),		$
		XCEN: XCEN(I),			$
		YCEN: YCEN(I),			$
		DISTURBANCES: DISTURBANCES(I)}
	GOTO, FINISH
;
;  Error handling point.
;
HANDLE_ERROR:
	IF N_ELEMENTS(ERRMSG) NE 0 THEN ERRMSG = 'GET_PLAN: ' + MESSAGE $
		ELSE MESSAGE, MESSAGE, /CONTINUE
;
;  Close the database, and return.
;
FINISH:
	DBCLOSE
;
	RETURN
	END
