; $Id: dcs_calculate_revenge.pro,v 1.4 2005/02/14 17:50:33 azuah Exp $
; Written by J.R.D. Copley.
;************************************************************************************************
;###############################################################################
;
; LICENSE:
;  The software in this file is written by an employee of 
;  National Institute of Standards and Technology 
;  as part of the DAVE software project.
;
;  The DAVE software package is not subject to copyright protection
;  and is in the public domain. It should be considered as an
;  experimental neutron scattering data reduction, visualization, and
;  analysis system. As such, the authors assume no responsibility
;  whatsoever for its use, and make no guarantees, expressed or
;  implied, about its quality, reliability, or any other
;  characteristic. The use of certain trade names or commercial
;  products does not imply any endorsement of a particular product,
;  nor does it imply that the named product is necessarily the best
;  product for the stated purpose. We would appreciate acknowledgment
;  if the DAVE software is used or if the code in this file is
;  included in another product.
;
;###############################################################################
pro dcs_calculate_revenge,speeds,phases,distances,angles,$
	wavelength,mspeed,resmode,num,denom,slowchopper,calcphases,error
;************************************************************************************************
;
compile_opt strictarr
;
dcs_chopper_info,distances,angles
;
error=""
nsame=0
slowchopper=0
num=1
denom=1
;
for i=0,6 do begin
	if (speeds[i] eq speeds[0]) then nsame=nsame+1 else begin
		slowchopper=i+1
		ratio=speeds[i]/speeds[0]
		denom=1.0/ratio
		if (abs(denom-round(denom)) lt 0.02) then begin
			slowmode=1
			num=1
			denom=round(denom)
		endif else begin
			for denom=2,27 do begin
				if (abs(ratio*denom-(denom-1)) lt 0.02) then begin
					slowmode=2
					denom=round(denom)
					num=denom-1
					goto,continuation
				endif
			endfor
		endelse
	endelse
	continuation:; chopper=chopper-1
endfor
;
if (nsame lt 6) then begin
	error=" FATAL: Fewer than 6 choppers at same speed."
	return
endif
mspeed=speeds[0]
freq=round((mspeed/60.0)*1000.0)/1000.0
period=round((60000000.0/mspeed)*1000.0)/1000.0
if (nsame eq 6) then begin
	if (slowchopper ge 3 and slowchopper le 5) then begin
	endif else begin
		error="FATAL: Slow chopper number is <3 or >5."
		return
	endelse
endif
;
nwl=0
for k=0,2 do begin
	angdif=angles[1,k]-angles[0,k]
	pdif=phases[1]-phases[0]
	tdif=period*(pdif-angdif)/360.0
;	disdif=moddistances[1]-moddistances[0]
	disdif=distances[1]-distances[0]
	wl=!dcs_hom*tdif/disdif
	if (wl gt 0.1 and wl lt 25.0) then begin
		nwl=nwl+1
		kmod=k
		waveapprox=wl
	endif
endfor
;
if (nwl eq 0 or nwl gt 1) then begin
	error="FATAL: Wavelength cannot be determined."
	return
endif
;
theta=angles[*,kmod]
angdif=theta[0]-theta[6]
disdif=distances[0]-distances[6]
pdif=phases[0]-phases[6]
for mult=0,10 do begin
	pdif=pdif+360.0
	tdif=period*(pdif+angdif)/360.0
	wavelength=!dcs_hom*tdif/disdif
	if (abs(wavelength-waveapprox) lt 0.1) then goto,continuation2
endfor
;
continuation2:
resmode=kmod+1
;
factor=1.0e4
wavelength=round(wavelength*factor)/factor
;
calcphases=fltarr(7)
diff=fltarr(7)
addedfrac=0.0
for i=0,6 do begin
	time=distances[i]*wavelength/!dcs_hom+addedfrac*period
	if (slowchopper eq (i+1)) then $
		perio=period*denom/num $
		else perio=period
	phase=(360.0/perio)*time-(30.0-theta[i])
	while (phase ge 360.0) do phase=phase-360.0
	while (phase lt 0.0) do phase=phase+360.0
	calcphases[i]=round(phase*100.0)/100.0
	diff[i]=calcphases[i]-phases[i]
	diff[i]=round(diff[i]*100.0)/100.0
endfor
;
addedfrac=-diff[0]/360.0
addedtime=addedfrac*period
for i=0,6 do begin
	if (slowchopper eq (i+1)) then $
		perio=period*denom/num $
		else perio=period
	phase=calcphases[i]+addedtime/perio*360.0
	while (phase ge 360.0) do phase=phase-360.0
	while (phase lt 0.0) do phase=phase+360.0
	calcphases[i]=phase
endfor
;
end
