#!/usr/bin/python # Reference only: the beamline scientist's laser-delay script, attached to request 2. # Kept verbatim (Python 2 era, CaChannel/epicsPV) as the behavioural spec for the BEC # LaserDelay device. Do not import or run it from BEC code. from CaChannel import ca, CaChannel from epicsPV import epicsPV from math import * from numpy import * import time #Possible values of Laser: Duetto, KML, XITON, PI Laser="Duetto" Beamline="SuperXAS" #LaserTriggerMode: "internal" or "external" External means from Event receiver. LaserTriggerMode="external" # Units of time are nanoseconds #If internal triggering is used, set LaserPeriod (time between two laser pulses) as it is set at the laser LaserPeriod=0 if (LaserTriggerMode=="internal"): LaserPeriod=2000.2 #Timing mode "DelayAndPhase" - use both Delay card and phase shifter, "Delay" - use only delay card, "Phase" - use only phase shifter if (Laser=="Duetto"): TimingMode="DelayAndPhase" #Index Of delay channel (as in EPICS name) used for laser DelayChIndex=1 EVRChIndex=2 #For SuperXAS 1 corresponds to the old (KML) phase shifter #For SuperXAS 2 corresponds to ES4 phase shifter PhaseShifterIndex=2 #change only for another synchrotron RFPeriod=2.0 DelayCh=CaChannel() DelayChFine=CaChannel() EVRCh=CaChannel() PhaseV1=CaChannel() PhaseV2=CaChannel() def ConnectEpics(): global CavityPeriod, Laser, Beamline global DelayCh, DelayChFine, EVRCh, PhaseV1, PhaseV2 if (Laser=="Duetto"): CavityPeriod=12.01 if (Beamline=="SuperXAS"): DN="X10DA-ES2-TIM:SET"+str(DelayChIndex) EVRChName="X10DA-ES2-TIM:EVR-FPS"+str(EVRChIndex) if (PhaseShifterIndex==1): PhaseV1Name="X10DA-LAS-PHSH:V1" PhaseV2Name="X10DA-LAS-PHSH:V2" if (PhaseShifterIndex==2): PhaseV1Name="X10DA-ES4:AO-02" PhaseV2Name="X10DA-ES4:AO-01" if (Beamline=="Phoenix"): DN="X07MB-ES-TIM:SET"+str(DelayChIndex) EVRChName="X07MB-ES-TIM:EVR-FPS"+str(EVRChIndex) PhaseV1Name="X07MB-ES1-PP2:VO2" PhaseV2Name="X07MB-ES1-PP2:VO1" DelayChName=DN+"-DELAY" DelayChFineName=DN+"-FINE" if ((TimingMode=="Delay") or (TimingMode=="DelayAndPhase")): DelayCh.searchw(DelayChName) DelayChFine.searchw(DelayChFineName) if ((TimingMode=="Phase") or (TimingMode=="DelayAndPhase")): PhaseV1.searchw(PhaseV1Name) PhaseV2.searchw(PhaseV2Name) if (LaserTriggerMode=="external"): EVRCh.searchw(EVRChName) #Maybe will be useful to automatically set pulse width for different lasers #def SetPulseWidth(): def CurrentSituation(FromScopeXrayMinusLaser): global LaserPeriod, OffsetT if (TimingMode=="Delay"): PhaseT=0 if (TimingMode=="Phase"): DelayCardT=0 if (LaserTriggerMode=="external"): LaserPeriod=1000*EVRCh.getw() print ("LaserPeriod=", LaserPeriod) if ((TimingMode=="Delay") or (TimingMode=="DelayAndPhase")): dt1=DelayCh.getw() dt2=DelayChFine.getw() DelayCardT=2.0*dt1+0.01*dt2 if ((TimingMode=="Phase") or (TimingMode=="DelayAndPhase")): PhaseT=GetPhaseT() Ph=FromScopeXrayMinusLaser%CavityPeriod OffsetPhaseT=-PhaseT-Ph OffsetT=-DelayCardT-FromScopeXrayMinusLaser print ("LaserPeriod=", LaserPeriod) print ("OffsetT=", OffsetT) print ("Current PhaseT", PhaseT) print ("Offset Phse shifter T", OffsetPhaseT) qwe=(LaserPeriod, OffsetT, OffsetPhaseT, PhaseT) # print ("qwe=",qwe) savetxt("Timing.offset", qwe) def GetPhaseT(): v1=PhaseV1.getw() v2=PhaseV2.getw() phi=atan2(v2,v1) T=RFPeriod*phi/(2*pi) return T def SetVoltages(phi): #Vmax may be different for different lasers or phase shifters #if (PhaseShifterIndex==1): Vmax=1.0 V1=Vmax*cos(phi) V2=Vmax*sin(phi) PhaseV1.putw(V1) PhaseV2.putw(V2) #set values via epics print (V1, V2) time.sleep(0.1) def MovePhaseShifter(RelativeDelay): NumStepsPerPeriod=36 DelayStep=sign(RelativeDelay)*RFPeriod/NumStepsPerPeriod #read current values of CurT=GetPhaseT() for t1 in arange(0,RelativeDelay, DelayStep): phi1=2*pi*(CurT+t1)/RFPeriod SetVoltages(phi1) phi1=2*pi*(CurT+RelativeDelay)/RFPeriod SetVoltages(phi1) def MoveDelayCard(NewDelayTime): print ("ndt,lp", NewDelayTime, LaserPeriod) t1=NewDelayTime%LaserPeriod t2=int(t1/2.0) t3=int((t1%2.0)/0.009999) print ("t1 t2 t3 ",t1,t2,t3) DelayCh.putw(t2) DelayChFine.putw(t3) def SetDelay(t=0): global LaserPeriod, OffsetT a=loadtxt("Timing.offset") LaserPeriod=a[0] OffsetT=a[1] print ("a1=",a[1]) OffsetPhaseT=a[2] print ("OffsetPhaseT from File", OffsetPhaseT) CurrentPhaseT=a[3] print ("Current value of PhaseT", CurrentPhaseT) TotalT=-OffsetT-t ForPhaseShifter=-t%CavityPeriod-OffsetPhaseT print ("-t/Cavity", -t%CavityPeriod, "-OffsetPhaseT", OffsetPhaseT, "-CurrentPhaseT", CurrentPhaseT) MoveDelayCard(TotalT) print ("Relative Phase shifter delay", ForPhaseShifter-CurrentPhaseT) MovePhaseShifter(ForPhaseShifter-CurrentPhaseT) print ("OffsetT before save=", OffsetT) savetxt("Timing.offset",(LaserPeriod,OffsetT,OffsetPhaseT,ForPhaseShifter)) def main(): ConnectEpics() # CurSit=-20.015+15.46 # #CurSit=-14.58+15.46 # CurSit=546.04-546.92 #CurSit=0.1 #CurrentSituation(FromScopeXrayMinusLaser=CurSit) print ("------------------") SetDelay(-4.9) # SetDelay(0.5) # time.sleep(5) # SetDelay(.5) if __name__=="__main__": main() #MovePhaseShifter(2.0) #MoveDelayCard(25.) #time.sleep(10)