	PRO GET_DETAIL, DATE, OBS, ERRMSG=ERRMSG, KEEP_OPEN=KEEP_OPEN
;+
; Project     :	SOHO - CDS
;
; Name        :	GET_DETAIL
;
; Purpose     :	Extracts a CDS detailed science plan observation
;
; Explanation :	This routine extracts parameters which describe the CDS
;		detailed science plan at a particular point in time.
;
; Use         :	GET_DETAIL, DATE, OBS
;
; Inputs      :	DATE	= The date/time value that the user wishes the detailed
;			  science plan record for.  This can be in any of the
;			  standard CDS time formats.
;
; Opt. Inputs :	None.
;
; Outputs     :	OBS	= Structure containing the detailed science plan
;			  record.  It contains the following tags:
;
;			STRUCT_TYPE= The character string 'CDS-DETAIL'
;			PROG_ID	   = Program ID, linking one or more studies
;				     together
;			STUDY_ID   = Number defining the study
;			STUDYVAR   = Number giving the study variation ID
;			SCI_OBJ    = Science objective from the daily science
;				     meeting
;			SCI_SPEC   = Specific science objective from meeting
;			CMP_NO	   = Campaign number
;			OBJECT	   = Code for object planned to be observed
;			OBJ_ID	   = Object identification
;			DATE_OBS   = Date/time of beginning of observation,
;				     in TAI format
;			DATE_END   = Date/time of end of observation, in TAI
;				     format
;			ORIG_DUR   = Original duration of the observation, in
;				     seconds, before being truncated by
;				     following time-tagged observations.
;			N_RASTERS1 = Variable number of rasters parameter
;			TIME_TAGGED= True (1) if the start of the study is to
;				     be a time-tagged event.  Otherwise, the
;				     study will begin immediately after the
;				     previous study.
;			TRACKING   = True (1) if feature tracking to be used,
;				     or false (0) otherwise
;			N_POINTINGS= Number of pointings to apply to the study.
;			N_REPEAT_S = Number of times to repeat study.
;			FLAG_MASTER= Nonzero if flag master
;			GSET_ID	   = GSET ID number
;			GET_RAW	   = True if raw data should be collected.
;			PROG_NUM   = Study counter number (negative is
;				     predicted)
;			POINTINGS  = An array of pointings to use with the
;				     study.
;
;		If no entry is found, then a simpler structure is returned with
;		STUDY_ID set to -1.  POINTINGS is itself a structure of type
;		PLAN_PNT_STRUC with the following tags:
;
;			INS_X	   = Pointing in X relative to sun center
;			INS_Y	   = Pointing in Y relative to sun center
;			ZONE_ID	   = Pointing zone ID
;
; 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_DETAIL, ERRMSG=ERRMSG, ... 
;                       IF ERRMSG NE '' THEN ...
;
;       KEEP_OPEN = set to inhibit calling DBCLOSE
;                   (useful when calling GET_DETAIL in a loop, but
;                    caller must remember to NOT set this keyword on
;                    the last call in the loop)
;
;
; Calls       :	DATATYPE, DBOPEN, DBFIND, DBEXT, DBCLOSE, TRIM
;
; 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, 17 November 1994
;			Fixed so that if time is on boundary, then the plan
;			which starts then is picked.
;		Version 4, William Thompson, GSFC, 21 November 1994
;			Added item N_REPEAT_S
;		Version 5, William Thompson, GSFC, 26 January 1995
;			Added tag STRUCT_TYPE
;		Version 6, William Thompson, GSFC, 13 February 1995
;			Changed way pointing is handled.
;		Version 7, William Thompson, GSFC, 28 March 1995
;			Added ZONE_ID to pointing structure.
;		Version 8, William Thompson, GSFC, 28 April 1995
;			Returns an error string when no entry is found.
;		Version 9, William Thompson, GSFC, 8 May 1995
;			Modified to pay attention to DELETED field in database
;		Version 10, William Thompson, GSFC, 22 May 1995
;			Changed way DBFIND is called, to speed up.
;		Version 11, William Thompson, GSFC, 20 June 1995
;			Added tag FLAG_MASTER
;		Version 12, William Thompson, GSFC, 28 September 1995
;			Added tags ORIG_DUR, GSET_ID, GET_RAW
;		Version 13, William Thompson, GSFC, 4 June 1997
;			Added tag PROG_NUM
;		Version 14, Dominic Zarro, GSFC, 15 July 1997
;			Added keyword KEEP_OPEN
;		Version 15, William Thompson, GSFC, 26 May 1998
;			Look for entries in "_year" files
;
; Version     :	Version 15, 26 May 1998
;-
;
	IF !DEBUG EQ 0 THEN ON_ERROR, 2 ELSE ON_ERROR, 0
;
;  Initialize the output structure, in case any errors occur.
;
	OBS = {STUDY_ID: -1}
;
;  Check the number of parameters.
;
        IF N_PARAMS() NE 2 THEN BEGIN
           MESSAGE = 'Syntax:  GET_DETAIL, DATE, OBS'
	   GOTO, HANDLE_ERROR
        ENDIF
;
;  Check the input parameter.
;
	IF N_ELEMENTS(DATE) NE 1 THEN BEGIN
           MESSAGE = 'DATE must be a scalar'
           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_details' + TRAILER
;
;  Search for entries with dates spanning that given by the user.
;
	ENTRIES = DBFIND('DATE_END>' + TRIM(TAI,'(F15.3)') + ',DATE_OBS<' + $
		TRIM(TAI,'(F15.3)') + ',DELETED=N', /SILENT)
;
;  If no entries were found, then try opening the database with the year
;  appended.  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_details'+TRAILER+'.dbf', '$ZDBASE')
		IF FILE NE '' THEN GOTO, OPEN_DATABASE
	    ENDIF
	    MESSAGE = 'No detailed science plan entry found meeting search criteria'
	    GOTO, HANDLE_ERROR
	ENDIF
;
;  Extract the entries.
;
	DBEXT, ENTRIES, 'prog_id,study_id,studyvar,sci_obj,sci_spec,cmp_no', $
		PROG_ID, STUDY_ID, STUDYVAR, SCI_OBJ, SCI_SPEC, CMP_NO
	DBEXT, ENTRIES, 'object,obj_id,date_obs,date_end,n_rasters1', $
		OBJECT, OBJ_ID, DATE_OBS, DATE_END, N_RASTERS1
	DBEXT, ENTRIES, 'time_tagged,tracking,n_pointings,n_repeat_s', $
		TIME_TAGGED, TRACKING, N_POINTINGS, N_REPEAT_S
	DBEXT, ENTRIES, 'flag_master,orig_dur,gset_id,get_raw,prog_num', $
		FLAG_MASTER, ORIG_DUR, GSET_ID, GET_RAW, PROG_NUM
;
;  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(DATE_OBS - TAI)
	I = (WHERE(DIFF EQ MIN(DIFF)))(0)
;
;  Define the structure to be used with the pointings.
;
	POINTINGS = {PLAN_PNT_STRUC, INS_X: 0.0, INS_Y: 0.0, ZONE_ID: 0}
;
;  Extract the pointings associated with this entry.
;
	N_POINTINGS = N_POINTINGS(I)
	IF N_POINTINGS GT 0 THEN BEGIN
		DBOPEN, 'point_details' + TRAILER
		ENTRIES = DBFIND('DATE_OBS=' + TRIM(DATE_OBS(I),'(F15.3)') + $
			',DELETED=N', /SILENT)
		DBEXT, ENTRIES, 'pt_ind,ins_x,ins_y,zone_id',	$
			PT_IND, INS_X, INS_Y, ZONE_ID
;
;  Put the data into the structure.
;
		IF N_POINTINGS EQ 1 THEN BEGIN
			POINTINGS.INS_X   = INS_X(0)
			POINTINGS.INS_Y   = INS_Y(0)
			POINTINGS.ZONE_ID = ZONE_ID(0)
		END ELSE BEGIN
			POINTINGS = REPLICATE(POINTINGS, N_POINTINGS)
			S = SORT(PT_IND)
			POINTINGS.INS_X   = INS_X(S)
			POINTINGS.INS_Y   = INS_Y(S)
			POINTINGS.ZONE_ID = ZONE_ID(S)
		ENDELSE
	ENDIF
;
;  Define the output structure as a whole.
;
	OBS = { STRUCT_TYPE: 'CDS-DETAIL',	$
		PROG_ID: PROG_ID(I),		$
		STUDY_ID: STUDY_ID(I),		$
		STUDYVAR: STUDYVAR(I),		$
		SCI_OBJ: SCI_OBJ(I),		$
		SCI_SPEC: SCI_SPEC(I),		$
		CMP_NO: CMP_NO(I),		$
		OBJECT: OBJECT(I),		$
		OBJ_ID: OBJ_ID(I),		$
		DATE_OBS: DATE_OBS(I),		$
		DATE_END: DATE_END(I),		$
		ORIG_DUR: ORIG_DUR(I),		$
		N_RASTERS1: N_RASTERS1(I),	$
		TIME_TAGGED: TIME_TAGGED(I),	$
		TRACKING: TRACKING(I),		$
		N_POINTINGS: N_POINTINGS,	$
		N_REPEAT_S: N_REPEAT_S(I),	$
		FLAG_MASTER: FLAG_MASTER(I),	$
		GSET_ID: GSET_ID(I),		$
		GET_RAW: GET_RAW(I),		$
		PROG_NUM: PROG_NUM(I),		$
		POINTINGS: POINTINGS}
	GOTO, FINISH
;
;  Error handling point.
;
HANDLE_ERROR:
	IF N_ELEMENTS(ERRMSG) NE 0 THEN ERRMSG = 'GET_DETAIL: ' + MESSAGE $
		ELSE MESSAGE, MESSAGE, /CONTINUE
;
;  Close the database, and return.
;
FINISH:
   IF NOT KEYWORD_SET(KEEP_OPEN) THEN BEGIN
    DBCLOSE 
    DPRINT,'Closing DB'
   ENDIF
;
	RETURN
	END
