PRO HSI_ADVANCE_ROLL_SOLUTION, obs_time_interval, start_time, stop_time,$ ; $ pred_period, pred_pa_target,  $
		TEST_TIME=test_time,  LATENCY=latency, SC_SUN_OFFSET=sc_sun_offset, PA_CORR=pa_corr,$
                spin_rate,theta0z
;
; Analyses PMTRAS data for obs_time_interval and returns predicted clock angle at future_time
;
;
; If TEST_TIME is defined, start_time and stop_time inputs are not required and the interpolated "actual"
;	PA at test_time is printed.
;
; sc_sun_offset = 2 element vector representing the s/c pointing offset (+W,+N) in degrees relative to sun center.
; pa_corr		= an empirial position angle offset (degrees) that is added to THETAz0 to reflect recent biasses.
;
; 30-MAY-02 		First version (ghurford@ssl.berkeley.edu)
; 31-May-02			Remove the !PI adjustment to PMTRAS_ANALYSIS output
;					Express roll rate in radians/s, not rpm.
;  8-Jun-02 gh		Use quadratic model of pa vs time to extrapolate to stop time, then linear fit back to target time.
;					Add TEST_TIME keyword
; 10-JUn-02 gh		Add PLOT keyword
; 11-Jun-02 gh		Add optional inputs for comparing actual-predicted position angles.
; 12-jun-02 gh		Use last instead of observed roll value as the msmt point.
;					Correct trivial error in sign of actual-predicted position angles.
;					Include the !PI adjustment to PMTRAS_ANALYSIS output.
;					Destroy object after use.
; 16-Jun-02 gh/jm	Zero the clock drift file so that all times are in terms of s/c clock, not UTC.
;			gh		Once again, remove the !PI adjustment to PMTRAS_ANALYSIS output.
;					Add LATENCY keyword.
; 17-Jun-02 gh		Include latency offset in displayed target time.
;					Minor output format change.
; 18-Jun-02 gh		Add SC_SUN_OFFSET keyword
; 			gh		Change calculation of theta0Z by 180 degrees to match results of June 17 and 18.
; 19-Jun-02 gh		Add display of sc_sun_offset input value.
; 22-Jun-02 gh		Add TIMEBIN keyword.
; 24-Apr-03 gh		Remove blipmin=150 argument in call to pmtras_analysis
; 18-May-03 gh		Implement new default algorithm to base predictions on a quadratic fit to pa at
;						specific times separated by integral orbital periods.
;					Define OLD_METHOD keyword to retain ability to use previous algorithm.
; 16-Apr-04 gh		Completely recoded to exploit fits to roll database.
; 17-Apr-04 gh		Recode TEST_TIME keyword handling to work with roll database.
;  9-Jun-04 gh		Eliminate printing of sc_sun_offset which has not been used since 16-april-04 version.
; 					Suppress printing of (irrelevant) latency when in TEST_TIME mode.
;					Correct printing bug in TEST_TIME mode when exiting due to extrapolation.
;					Add PA_CORR keyword.
;
; latency = time delay (s) between the nominal time of the ATS load and the first execution of the offpointing software
;
; Zero clock drift file to force target time and solution to be in s/c units.
; Unless reversed, THIS APPLIES TO THE REMAINDER OF THE IDL SESSION !!!!
hsi_clock_drift, /zero_init_drift
;
IF N_ELEMENTS(latency) EQ 0 THEN latency = 0				; default is no latency
IF N_ELEMENTS(pa_corr) EQ 0 THEN pa_corr = 0.				; default is no empirical correction
IF N_ELEMENTS(sc_sun_offset) EQ 0 THEN sc_sun_offset = FLTARR(2)		; default is [0,0]

IF KEYWORD_SET (test_time) THEN BEGIN
	opmt 		= hsi_roll_db_full()
	dbsolution 	=  opmt->getdata(obs_time_interval=obs_time_interval)
	IF N_ELEMENTS(dbsolution) EQ -1 THEN MESSAGE, 'HSI_ADVANCE_ROLL_SOLUTION could not find the roll database.'
	obj_destroy, opmt
;
	ok 				= WHERE(dbsolution.roll_quality GE 192, nok)
	solnok 			= hsi_pmtras_dbase_expand(dbsolution[ok])	; convert to structure with monatonically increasing radians
	phaseok			= solnok.posn_angle 							; DOUBLE in radians
	t0 				= dbsolution[0].sctime							; LONG in seconds
	trelok 			= dbsolution[ok].sctime - t0					; LONG array
	test_time_st 	= hsi_any2sctime(test_time)
	test_time_rel	= test_time_st.seconds - t0
	pa_test_solar	= INTERPOL(phaseok, trelok, test_time_rel, /QUAD)
	p_angle 		= pb0r(t0_target_s)							; p,b0,r in deg, deg, arcmin
	pa_test			= pa_test_solar - p_angle[0]*!DTOR			; make position angles wrt celestial rather than solar N.
	PRINT, 'OBS_TIME: from:      ', ANYTIM(obs_time_interval[0], /ECS)
	PRINT, '            to:      ', ANYTIM(obs_time_interval[1], /ECS)
;	PRINT, 'SC_SUN_OFFSET (deg) ', sc_sun_offset
;	PRINT, 'LATENCY (s)      =  ', latency
	PRINT, 'TEST_TIME =          ', ANYTIM(test_time, /ECS)
	IF test_time_rel GT trelok[nok-1] THEN BEGIN
		PRINT, 'LAST DATA TIME =     ', ANYTIM(trelok[nok-1]+t0,/ECS)
		PRINT, 'Did not attempt extrapolation.'
	ENDIF ELSE 	PRINT, 'PA at test_time[rad]=', (pa_test + 2000*!DPI) MOD (2.*!DPI)
	RETURN
ENDIF
;
;
; Calculate target time in sc clock units at integer seconds.
target_sc_time 			= hsi_any2sctime(start_time)					; convert nominal future_time to sc clock
target_sc_time.bmicro 	= 0												; Truncate sc clock to integral seconds
t0_target_s 			= hsi_sctime2any(target_sc_time) + latency		; Add ATS-to-execution latency
t0_target_label 		= anytim(t0_target_s, /ECS)

stop_sc_time			= hsi_any2sctime(stop_time)
stop_sct				= DOUBLE(stop_sc_time.seconds)
target_sct				= DOUBLE(target_sc_time.seconds) + latency		; target time in sctime seconds

PMTRAS_DBASE_MANAGER, TIME_RANGE=obs_time_interval, PRED_TIMES=[stop_sct, target_sct], PRED_ROLL=pred_roll
p_angle_target 	= pb0r(t0_target_s)					; p,b0,r in deg, deg, arcmin
p_angle_stop	= pb0r(stop_time)
pa_stop			= pred_roll[0] - (p_angle_stop[0]	*!DTOR)		; make position angles wrt celestial rather than solar N.
pa_target		= pred_roll[1] - (p_angle_target[0]	*!DTOR)

;
; Determine average spin period and roll rate between target and stop times.
;spin_rate			= (pa_stop - pa_target) / (t_stop_rel - t_target_rel)		; radians/s
spin_rate			= (pa_stop - pa_target) / (stop_sct - target_sct)		; radians/s
avperiod			= 2 * !PI / spin_rate										; seconds
;
; Determine target clock angle
; theta0z			= (pa_target - !PI/2.) MOD (2.*!PI)						; convention used until June 18,2002
theta0z				= (pa_target + pa_corr*!DTOR + !PI/2.) MOD (2.*!PI)		; convention used from  June 19
; Print results
PRINT
PRINT, 		'OBS_TIME: from:     ', ANYTIM(obs_time_interval[0], /ECS)
PRINT, 		'            to:     ', ANYTIM(obs_time_interval[1], /ECS)
; PRINT, 		'SC_SUN_OFFSET (deg) ', sc_sun_offset
PRINT, 		'LATENCY (s)      =  ', latency
PRINT,		'PA_corr (deg)    =  ', pa_corr
IF KEYWORD_SET(timebin) THEN PRINT, 'TIMEBIN (s)      =  ', timebin
IF KEYWORD_SET(old_method) NE 0 THEN	$
	PRINT,  'MEASUREMENT TIME =  ', t_roll_msmt_label
PRINT, 		'TARGET TIME      =  ', t0_target_label
PRINT, 		'STOP TIME        =  ', ANYTIM(stop_time, /ECS)
IF KEYWORD_SET(old_method) NE 0 THEN	$
	PRINT, 	'PAmsmt   [rad]   =  ', posn_angle_msmt MOD (2.*!PI)
PRINT, 		'PAtarget [rad]   =  ', pa_target   MOD (2.*!PI)
PRINT, 		'PAstop   [rad]   =  ', pa_stop     MOD (2.*!PI)
PRINT, 		'<PERIOD> [sec]   =  ', avperiod
PRINT
PRINT, 		'TARGET SC TIME   =',   target_sc_time.seconds, '.000000 '
PRINT, 		'SPIN RATE[rad/s] =  ', spin_rate, '       <=============='
PRINT, theta0z, FORMAT = "('THETAz0 [rad]    =', F14.3, 10X, '<=============')"
RETURN
END