class DisplayEpicsPVClass(ScannableBase): """Create PD to display single EPICS PV""" def __init__(self, name, pvstring, unitstring, formatstring): self.setName(name) self.setInputNames([]) self.setExtraNames([name]) self.Units = [unitstring] self.setOutputFormat([formatstring]) self.setLevel(3) self.cli = CAClient(pvstring) def atStart(self): if not self.cli.isConfigured(): self.cli.configure() def getPosition(self): if self.cli.isConfigured(): return float(self.cli.caget()) else: self.cli.configure() return float(self.cli.caget()) self.cli.clearup() def isBusy(self): return 0 def atEnd(self): if self.cli.isConfigured(): self.cli.clearup()
class HexapodAxis(PseudoDevice): '''scannable or pseudo device for an individual, single Hexapod axis, it takes 8 inputs in the following order: 1. the name string of this object 2. the PV string for input target value 3. the PV string for read-back value 4. the PV string that control or start the motion 5. the positional tolerance within which the motor is treated as in-position 6. the unit string used for the measurement, keyworded as 'unitstring' 7. the format string for the return data, keyworded as 'formatstring' 8. the hexapod controller instance for example, hpx=HexapodAxis('hpx', 'ME02P-MO-BASE-01:UCS_X','ME02P-MO-BASE-01:UCSXR', 'ME02P-MO-BASE-01:START.PROC', 0.01, 'mm', '%9.4f', hexapodController) ''' def __init__(self, name, pvinstring, pvoutstring, pvctrlstring, tolerance=0.01, unitstring='mm', formatstring='%9.4f', controller=None): self.setName(name); self.setInputNames([name]) self.Units=[unitstring] self.setOutputFormat([formatstring]) self.setLevel(3) self.incli=CAClient(pvinstring) self.outcli=CAClient(pvoutstring) self.movecli=CAClient(pvctrlstring) self.lastpos=0.0 self.currentpos=0.0 self.targetpos=0.0 self._tolerance=tolerance self.controller=controller def atScanStart(self): if not self.incli.isConfigured(): self.incli.configure() if not self.outcli.isConfigured(): self.outcli.configure() if not self.movecli.isConfigured(): self.movecli.configure() def atScanEnd(self): if self.incli.isConfigured(): self.incli.clearup() if self.outcli.isConfigured(): self.outcli.clearup() if self.movecli.isConfigured(): self.movecli.clearup() def rawGetPosition(self): try: if self.outcli.isConfigured(): self.currentpos=float(self.outcli.caget()) else: self.outcli.configure() self.currentpos=float(self.outcli.caget()) self.outcli.clearup() return self.currentpos except Exception, err: print "Error returning current position" + err return 0
class SingleEpicsPositionerClass(ScannableMotionBase): '''Create PD for single EPICS positioner''' def __init__(self, name, pvinstring, pvoutstring, pvstatestring, pvstopstring, unitstring, formatstring): self.setName(name); self.setInputNames([name]) self.Units=[unitstring] self.setOutputFormat([formatstring]) self.setLevel(3) self.incli=CAClient(pvinstring) self.outcli=CAClient(pvoutstring) self.statecli=CAClient(pvstatestring) self.stopcli=CAClient(pvstopstring) def rawGetPosition(self): output=0.0 try: if not self.outcli.isConfigured(): self.outcli.configure() output=float(self.outcli.caget()) #self.outcli.clearup() return float(output) except: print "Error returning position" return 0 def rawAsynchronousMoveTo(self,new_position): try: if self.incli.isConfigured(): self.incli.caput(new_position) else: self.incli.configure() self.incli.caput(new_position) #self.incli.clearup() except: print "error moving to position" def rawIsBusy(self): try: if self.statecli.isConfigured(): self.status = self.statecli.caget() else: self.statecli.configure() self.status=self.statecli.caget() #self.statecli.clearup() return not int(self.status) except: print "problem with isMoving string: "+self.status+": Returning busy status" return 1 def stop(self): print "calling stop" if self.stopcli.isConfigured(): self.stopcli.caput(1) else: self.stopcli.configure() self.stopcli.caput(1)
def caget(pvstring): 'caget from Jython' cli=CAClient(pvstring) cli.configure() out=cli.caget() cli.clearup() return out
class EpicsReadWritePVClass(ScannableMotionBase): '''Create PD to display single EPICS PV''' def __init__(self, name, pvstring, unitstring, formatstring): self.setName(name); self.setInputNames([name]) self.Units=[unitstring] self.setOutputFormat([formatstring]) self.setLevel(8) self.outcli=CAClient(pvstring) def rawGetPosition(self): output=0.0 try: if not self.outcli.isConfigured(): self.outcli.configure() output=float(self.outcli.caget()) output = self.getOutputFormat()[0] % output return float(output) except: print "Error returning position" return 0 def rawAsynchronousMoveTo(self,position): self.new_position=position # need this attribute for some other classes try: if self.outcli.isConfigured(): self.outcli.caput(position) else: self.outcli.configure() self.outcli.caput(position) except: print "error moving to position %f" % float(position) def rawIsBusy(self): return 0
class DisplayEpicsPVClass(ScannableMotionBase): '''Create PD to display single EPICS PV''' def __init__(self, name, pvstring, unitstring, formatstring): self.setName(name); self.setInputNames([name]) self.Units=[unitstring] self.setOutputFormat([formatstring]) self.setLevel(8) self.outcli=CAClient(pvstring) def rawGetPosition(self): output=0.0 try: if not self.outcli.isConfigured(): self.outcli.configure() output=float(self.outcli.caget()) #print output #sleep(10) #self.outcli.clearup() output = self.getOutputFormat()[0] % output return float(output) except: print "Error returning position" return 0 def rawAsynchronousMoveTo(self,position): return def rawIsBusy(self): return 0
class GasRigClass(ScannableMotionBase): '''Create a scannable for a gas injection rig''' def __init__(self, name, rootPV): self.setName(name); self.setInputNames([name]) self.setLevel(3) self.setsequencecli=CAClient(rootPV+SEQUENCE_CONTROL) self.statecli=CAClient(rootPV+SEQUENCE_STATUS) self.atpressurecli=CAClient(rootPV+AT_PRESSURE_PROC) def getState(self): try: if not self.statecli.isConfigured(): self.statecli.configure() output=int(self.statecli.caget()) self.statecli.clearup() else: output=int(self.statecli.caget()) return sequence[output] except: print "Error returning current state" return 0 def setSequence(self,new_position): try: if not self.setsequencecli.isConfigured(): self.setsequencecli.configure() self.setsequencecli.caput(new_position) self.setsequencecli.clearup() else: self.setsequencecli.caput(new_position) except: print "error setting sequence" def atPressure(self): try: if not self.atpressurecli.isConfigured(): self.atpressurecli.configure() self.atpressurecli.caput(1) self.atpressurecli.clearup() else: self.atpressurecli.caput(1) except: print "error setting at_pressure"
class SingleEpicsPositionerClass(ScannableBase): """Create PD for single EPICS positioner""" def __init__(self, name, pvinstring, pvoutstring, pvstatestring, pvstopstring, unitstring, formatstring): self.setName(name) self.setInputNames([name]) self.setExtraNames([name]) self.Units = [unitstring] self.setOutputFormat([formatstring]) self.setLevel(3) self.incli = CAClient(pvinstring) self.outcli = CAClient(pvoutstring) self.statecli = CAClient(pvstatestring) self.stopcli = CAClient(pvstopstring) def atStart(self): if not self.incli.isConfigured(): self.incli.configure() if not self.outcli.isConfigured(): self.outcli.configure() if not self.statecli.isConfigured(): self.statecli.configure() if not self.stopcli.isConfigured(): self.stopcli.configure() def getPosition(self): output = 99 try: if self.outcli.isConfigured(): # if not isinstance(self.outcli.caget(),type(None)): # print self.outcli.caget() return float(self.outcli.caget()) else: self.outcli.configure() output = self.outcli.caget() if output == None: raise Exception, "null pointer exception in getPosition" self.outcli.clearup() return float(output) except Exception, e: print "error in getPosition", e.getMessage(), e, output raise e
class HexapodAxisStatus(object): '''Hexapod axis status class implementing position-compare algorithm with tolerance input. isBusy() method should be used to query the motion status of this axis.''' def __init__(self, name, pvinstring, pvoutstring, tolerance=0.01): self.name=name self.incli=CAClient(pvinstring) self.outcli=CAClient(pvoutstring) self.currentpos=0.0 self.targetpos=0.0 self._tolerance=tolerance def getCurrentPosition(self): try: if self.outcli.isConfigured(): self.currentpos=float(self.outcli.caget()) else: self.outcli.configure() self.currentpos=float(self.outcli.caget()) self.outcli.clearup() return self.currentpos except Exception, err: print "Error returning current position of " + self.name + err return 0
class PVWithSeparateReadbackAndToleranceScannable(ScannableBase): def __init__(self, name, pv_set, pv_read, timeout, tolerance = 0.0005): #BL16B-EA-PSU-01 self.name = name self.inputNames = [name] self.outputFormat = ['%6.4f'] self.timeout = timeout self.tol = tolerance self._time_triggered = None self._last_target = None self._pv_set = CAClient(pv_set) self._pv_read = CAClient(pv_read) self._pv_set.configure() self._pv_read.configure() def asynchronousMoveTo(self, value): self._pv_set.caput(value) self._time_triggered = time.time() self._last_target = value def isBusy(self): if self._last_target == None: return False i = (float(self._pv_read.caget())) if abs(i - self._last_target) <= self.tol: return False if (time.time() - self._time_triggered) > self.timeout: raise Exception('Timed out after %fs setting current to %f. The current has hung at %f, and the voltage is %f\n*Is the voltage set too low?*' % ((self.timeout, self.last_target) + self.getPosition())) return True def getPosition(self): return float(self._pv_read.caget())
class NimaLangmuirBlodgettTroughDeviceClass(object): NLBT_CONTROL_MODE = { "SPEED": 0, "PRESSURE": 1, "AREA": 2 } def __init__(self, name, rootPV): self.name = name self.setupEpics(rootPV) self.mode = 2 self.speed = 30.0 self.pressure = None self.area = None self.temperature = None self.time = None self.pressureB = None self.areaB = None self.spot = None self.minArea = 0 self.maxArea = 900 self.minSpeed = 5 self.maxSpeed = 100 self.running = False def __del__(self): self.cleanChannel(self.chStart) self.cleanChannel(self.chStop) self.cleanChannel(self.chMode) self.cleanChannel(self.chAreaTarget) self.cleanChannel(self.chPiTarget) self.cleanChannel(self.chSpeedTarget) self.cleanChannel(self.chTemp) self.cleanChannel(self.chTime) self.cleanChannel(self.chPiA) self.cleanChannel(self.chPiB) self.cleanChannel(self.chArea) self.cleanChannel(self.chAreaB) self.cleanChannel(self.chSpot) def setupEpics(self, rootPV): # Epics PVs for control the Trough: self.chStart = CAClient(rootPV + ":Start") self.configChannel(self.chStart) self.chStop = CAClient(rootPV + ":Stop") self.configChannel(self.chStop) self.chMode = CAClient(rootPV + ":Mode") self.configChannel(self.chMode) self.chAreaTarget = CAClient(rootPV + ":AreaTarget") self.configChannel(self.chAreaTarget) self.chPiTarget = CAClient(rootPV + ":PiTarget") self.configChannel(self.chPiTarget) self.chSpeedTarget = CAClient(rootPV + ":SpeedTarget") self.configChannel(self.chSpeedTarget) # Epics PVs for read back the Trough: self.chTemp = CAClient(rootPV + ":Temp") self.configChannel(self.chTemp) self.chTime = CAClient(rootPV + ":Time") self.configChannel(self.chTime) self.chPiA = CAClient(rootPV + ":PiA") self.configChannel(self.chPiA) self.chPiB = CAClient(rootPV + ":PiB") self.configChannel(self.chPiB) self.chArea = CAClient(rootPV + ":Area") self.configChannel(self.chArea) self.chAreaB = CAClient(rootPV + ":AreaB") self.configChannel(self.chAreaB) self.chSpot = CAClient(rootPV + ":Spot") self.configChannel(self.chSpot) def configChannel(self, channel): if not channel.isConfigured(): channel.configure() def cleanChannel(self, channel): if channel.isConfigured(): channel.clearup() def isRunning(self): return self.running def setAreaLimits(self, low, high): self.minArea, self.maxArea = low, high def getAreaLimits(self): return [self.minArea, self.maxArea] def setSpeedLimits(self, low, high): self.minSpeed, self.maxSpeed = low, high def getSpeedLimits(self): return [self.minSpeed, self.maxSpeed] def getMode(self): self.mode = int(float(self.chMode.caget())) print "Trough Mode: " + self.NLBT_CONTROL_MODE.keys()[ self.NLBT_CONTROL_MODE.values().index(self.mode)] return self.mode def setMode(self, newMode): if newMode in self.NLBT_CONTROL_MODE.values(): self.mode = newMode elif newMode.upper() in self.NLBT_CONTROL_MODE.keys(): self.mode = self.NLBT_CONTROL_MODE[newMode.upper()] else: print "Please use the right mode: 'speed/pressure/area' or 0/1/2. " return self.chMode.caput(self.mode) sleep(1) def setArea(self, newValue): self.chAreaTarget.caput(newValue) sleep(1) def getArea(self): self.area = float(self.chArea.caget()) return self.area def setPressure(self, newValue): self.chPiTarget.caput(newValue) sleep(1) def getPressure(self): self.pressure = float(self.chPiA.caget()) return self.pressure def setSpeed(self, newValue): self.speed = newValue self.chSpeedTarget.caput(self.speed) sleep(1) def getSpeed(self): self.speed = float(self.chSpeedTarget.caget()) return self.speed def getTemperature(self): self.temperature = float(self.chTemp.caget()) return self.temperature def update(self): self.area = float(self.chArea.caget()) self.temperature = float(self.chTemp.caget()) self.pressure = float(self.chPiA.caget()) # self.pressureB =float( self.chPiB.caget() ); self.time = float(self.chTime.caget()) self.areaB = float(self.chAreaB.caget()) # self.spot =float( self.chSpot.caget() ); return [ self.area, self.pressure, self.speed, self.areaB, self.temperature, self.time ] def readValues(self): return self.update() def start(self): if self.running: return self.chStart.caput(1) sleep(0.2) self.chStart.caput(0) sleep(0.1) self.running = True def stop(self): self.chStop.caput(1) sleep(0.2) self.chStop.caput(0) sleep(0.1) self.running = False def asynchronousAreaMoveTo(self, newArea): self.setMode( NimaLangmuirBlodgettTroughDeviceClass.NLBT_CONTROL_MODE['AREA']) self.setArea(newArea) if not self.isRunning(): self.start() def synchronousAreaMoveTo(self, newArea): self.asynchronousAreaMoveTo(newArea) while self.getStatus() is not True: sleep(5)
class EpicsCamserverConnector(ScannableMotionBase): """ This class implements the communication between EPICS and Camserver. It will pass a command string for interpretation by camserver, and listen to the response from camserver. Example usage: >>>ecc = EpicsCamserverConnector("ecc") >>>pos ecc "command" ? PVs for Camserver communications: BL07I-EA-PILAT-01:GEN - write the string you want to send here BL07I-EA-PILAT-01:GEN:SEND - write 1 to send it to the camserver BL07I-EA-PILAT-01:GENIN - the reply message gets set in here """ camserverCommandPV = "BL07I-EA-PILAT-01:GEN" camserverWriterPV = "BL07I-EA-PILAT-01:GEN:SEND" camserverReaderPV = "BL07I-EA-PILAT-01:GENIN" def __init__(self, name): self.name = name self.epicsClient = CAClient("camserver") #self.epicsClient.configure() print "epicsClient: " + str(self.epicsClient) self.camserverCommandClient = CAClient(self.camserverWriterPV) print "camserverCommandClient: " + str(self.camserverCommandClient) self.camserverWriterClient = CAClient(self.camserverWriterPV) print "camserverWriterClient: " + str(self.camserverWriterClient) self.camserverReaderClient = CAClient(self.camserverReaderPV) print "camserverReaderClient: " + str(self.camserverReaderClient) def sendCommand(self, command): print "EpicsCamserverConnector.sendCommand(), command: " + command self.epicsClient.caput(self.camserverCommandPV, String2ByteArray(command)) self.epicsClient.caput(self.camserverWriterPV, 1) self.result = self.epicsClient.caget(self.camserverReaderPV) print "result: " + self.result def sendCommand2(self, command): pass # put in all available camserver commands def callMenu(self): pass def callExptime(self, exptime): pass def menu(self): arr = [] for each in "menu": arr.append(ord(each)) self.epicsClient.caput(self.camserverCommandPV, arr) def exposure(self, time): arr = [] for each in "exposure ": arr.append(ord(each)) arr.append(ord(str(time))) self.epicsClient.caput(self.camserverCommandPV, arr)
class DetectorControlClass(ScannableMotionBase): """Create PD for single EPICS ETL detector""" def __init__(self, name, pvinstring, pvoutstring, unitstring, formatstring): self.setName(name) self.setInputNames([name]) self.Units = [unitstring] self.setOutputFormat([formatstring]) self.setLevel(3) self.incli = CAClient(pvinstring) self.outcli = CAClient(pvoutstring) def atStart(self): if not self.incli.isConfigured(): self.incli.configure() if not self.outcli.isConfigured(): self.outcli.configure() def getPosition(self): try: if not self.outcli.isConfigured(): self.outcli.configure() output = float(self.outcli.caget()) self.outcli.clearup() else: output = float(self.outcli.caget()) return output except: print "Error returning current position" return 0 def getTargetPosition(self): try: if not self.incli.isConfigured(): self.incli.configure() target = float(self.incli.caget()) self.incli.clearup() else: target = float(self.incli.caget()) return target except: print "Error returning target position" return 0 def asynchronousMoveTo(self, new_position): try: if not self.incli.isConfigured(): self.incli.configure() self.incli.caput(new_position) self.incli.clearup() else: self.incli.caput(new_position) except: print "error moving to position" def isBusy(self): return self.getPosition() != self.getTargetPosition() def atEnd(self): if self.incli.isConfigured(): self.incli.clearup() if self.outcli.isConfigured(): self.outcli.clearup() def toString(self): return self.name + " : " + str(self.getPosition())
class EPICSODQBPMClass(ScannableBase): '''PD for OD QBPM device Inputs: None Outputs: Range, C1, C2, C3, C4, X, Y self.set_range(value) - set gain 0 = highest calibration sequence: self.dark_current() save dark current at current gain (beam off) self.set_zero() calibrate zero x,y (beam on) self.setxy(xval, yval) calibrate gains to give position in mm (go to xval, yval; beam on) - NOT TESTED Additional methods: config() loads qbpm parameters''' # a=A1*(current4-A2) etc # X=GX*(a-b)/(a+b) etc # a,b,c,d=chan 4,2,1,3 def __init__(self, name, pvrootstring,help=None): self.setName(name); if help is not None: self.__doc__+='\nHelp specific to '+self.name+':\n'+help #[self.A1,self.A2,self.B1,self.B2,self.C1,self.C2,self.D1,self.D2,self.GX, self.GY]=xyparamvec self.pvrootstring=pvrootstring self.setInputNames([]) self.setExtraNames(['Range','C1','C2','C3','C4','X','Y']); #self.setReportingUnits([' ','uA','uA','uA','uA','mm','mm']) self.setOutputFormat(['%.0f','%.9f','%.9f','%.9f','%.9f','%.3f','%.3f']) self.setLevel(9) self.rangecli=CAClient(pvrootstring+':RANGE_MENU');self.rangecli.configure() self.c1cli=CAClient(pvrootstring+':PHD1:I');self.c1cli.configure() self.c2cli=CAClient(pvrootstring+':PHD2:I');self.c2cli.configure() self.c3cli=CAClient(pvrootstring+':PHD3:I');self.c3cli.configure() self.c4cli=CAClient(pvrootstring+':PHD4:I');self.c4cli.configure() self.xcli=CAClient(pvrootstring+':XPOS');self.xcli.configure() self.ycli=CAClient(pvrootstring+':YPOS');self.ycli.configure() self.IR1cli=CAClient(pvrootstring+':PHD1:I_R');self.IR1cli.configure() self.IR2cli=CAClient(pvrootstring+':PHD2:I_R');self.IR2cli.configure() self.IR3cli=CAClient(pvrootstring+':PHD3:I_R');self.IR3cli.configure() self.IR4cli=CAClient(pvrootstring+':PHD4:I_R');self.IR4cli.configure() def getPosition(self): self.rangestring=self.rangecli.caget() self.c1string=self.c1cli.caget() self.c2string=self.c2cli.caget() self.c3string=self.c3cli.caget() self.c4string=self.c4cli.caget() self.xstring=self.xcli.caget() self.ystring=self.ycli.caget() return [float(self.rangestring),float(self.c1string), float(self.c2string),float(self.c3string),float(self.c4string),float(self.xstring),float(self.ystring)] # def asynchronousMoveTo(self,new_position): # self.rangecli.caput(new_position) def isBusy(self): return 0 def set_params(self,params): [A1,A2,B1,B2,C1,C2,D1,D2,GX,GY]=params self.configcli=CAClient(self.pvrootstring+':A1_SP');self.configcli.configure(); self.configcli.caput(A1); self.configcli.clearup(); self.configcli=CAClient(self.pvrootstring+':A2_SP');self.configcli.configure(); self.configcli.caput(A2); self.configcli.clearup(); self.configcli=CAClient(self.pvrootstring+':B1_SP');self.configcli.configure(); self.configcli.caput(B1); self.configcli.clearup(); self.configcli=CAClient(self.pvrootstring+':B2_SP');self.configcli.configure(); self.configcli.caput(B2); self.configcli.clearup(); self.configcli=CAClient(self.pvrootstring+':C1_SP');self.configcli.configure(); self.configcli.caput(C1); self.configcli.clearup(); self.configcli=CAClient(self.pvrootstring+':C2_SP');self.configcli.configure(); self.configcli.caput(C2); self.configcli.clearup(); self.configcli=CAClient(self.pvrootstring+':D1_SP');self.configcli.configure(); self.configcli.caput(D1); self.configcli.clearup(); self.configcli=CAClient(self.pvrootstring+':D2_SP');self.configcli.configure(); self.configcli.caput(D2); self.configcli.clearup(); self.configcli=CAClient(self.pvrootstring+':GX_SP');self.configcli.configure(); self.configcli.caput(GX); self.configcli.clearup(); self.configcli=CAClient(self.pvrootstring+':GY_SP');self.configcli.configure(); self.configcli.caput(GY); self.configcli.clearup(); def get_params(self): self.configcli=CAClient(self.pvrootstring+':A1_SP');self.configcli.configure(); A1=float(self.configcli.caget());self.configcli.clearup() self.configcli=CAClient(self.pvrootstring+':A2_SP');self.configcli.configure(); A2=float(self.configcli.caget()); self.configcli.clearup() self.configcli=CAClient(self.pvrootstring+':B1_SP');self.configcli.configure(); B1=float(self.configcli.caget()); self.configcli.clearup() self.configcli=CAClient(self.pvrootstring+':B2_SP');self.configcli.configure(); B2=float(self.configcli.caget()); self.configcli.clearup() self.configcli=CAClient(self.pvrootstring+':C1_SP');self.configcli.configure(); C1=float(self.configcli.caget()); self.configcli.clearup() self.configcli=CAClient(self.pvrootstring+':C2_SP');self.configcli.configure(); C2=float(self.configcli.caget()); self.configcli.clearup() self.configcli=CAClient(self.pvrootstring+':D1_SP');self.configcli.configure(); D1=float(self.configcli.caget()); self.configcli.clearup() self.configcli=CAClient(self.pvrootstring+':D2_SP');self.configcli.configure(); D2=float(self.configcli.caget()); self.configcli.clearup() self.configcli=CAClient(self.pvrootstring+':GX_SP');self.configcli.configure(); GX=float(self.configcli.caget()); self.configcli.clearup() self.configcli=CAClient(self.pvrootstring+':GY_SP');self.configcli.configure(); GY=float(self.configcli.caget()); self.configcli.clearup() return [A1,A2,B1,B2,C1,C2,D1,D2,GX,GY] def get_rawcounts(self): self.IR1=float(self.IR1cli.caget()) self.IR2=float(self.IR2cli.caget()) self.IR3=float(self.IR3cli.caget()) self.IR4=float(self.IR4cli.caget()) return [self.IR1, self.IR2, self.IR3, self.IR4] def set_range(self, newrange): self.rangecli.caput(newrange) def factory_reset(self): params=[A1,A2,B1,B2,C1,C2,D1,D2,GX,GY]=[1,0,1,0,1,0,1,0,1,1] self.set_params(params) def dark_current(self): #offsets not persistent - do dark current with beam off [A1,A2,B1,B2,C1,C2,D1,D2,GX,GY]=self.get_params() self.configcli=CAClient(self.pvrootstring+':PHD4:I_R');self.configcli.configure(); A2=float(self.configcli.caget()); self.configcli.clearup() self.configcli=CAClient(self.pvrootstring+':PHD2:I_R');self.configcli.configure(); B2=float(self.configcli.caget()); self.configcli.clearup() self.configcli=CAClient(self.pvrootstring+':PHD1:I_R');self.configcli.configure(); C2=float(self.configcli.caget()); self.configcli.clearup() self.configcli=CAClient(self.pvrootstring+':PHD3:I_R');self.configcli.configure(); D2=float(self.configcli.caget()); self.configcli.clearup() self.set_params([A1,A2,B1,B2,C1,C2,D1,D2,GX,GY]) print 'new dark currents (i4,i2,i1,i3):', [A2, B2, C2, D2] def set_zero(self): #do with beam on [ic,ib,id,ia]=self.get_rawcounts() [A1,A2,B1,B2,C1,C2,D1,D2,GX,GY]=self.get_params() A1B1=A1*B1; C1D1=C1*D1; #get products A1_B1=(ib-B2)/(ia-A2); #calculate ratio X=0 C1_D1=(id-D2)/(ic-C2); #calculate ratio Y=0 #re-calc A1, B1 etc for zero X,Y but keep ratio at current value [A1, B1, C1, D1]=[sqrt(A1B1*A1_B1), sqrt(A1B1/A1_B1), sqrt(C1D1*C1_D1), sqrt(C1D1/C1_D1)] self.set_params([A1,A2,B1,B2,C1,C2,D1,D2,GX,GY]) def set_xy(self,x,y): #do with beam on [ic,ib,id,ia]=self.get_rawcounts() [A1,A2,B1,B2,C1,C2,D1,D2,GX,GY]=self.get_params() [a,b,c,d]=[A1*(ia-A2), B1*(ib-B2),C1*(ic-C2), D1*(id-D2)] [GX, GY]=[x*(a+b)/(a-b),y*(c+d)/(c-d)] #print [A1,A2,B1,B2,C1,C2,D1,D2,GX,GY] self.set_params([A1,A2,B1,B2,C1,C2,D1,D2,GX,GY])
class Scaler8512ChannelEpicsDeviceClass(ScannableMotionBase): def __init__(self, name, strChTP, strChCNT, strChSn): self.setName(name) self.setInputNames([name]) self.setExtraNames([]) # self.Units=[strUnit]; self.setLevel(7) self.setOutputFormat(["%20.8f"]) self.chTP = CAClient(strChTP) self.chCNT = CAClient(strChCNT) self.chSn = CAClient(strChSn) self.tp = -1 # self.setTimePreset(time) def atScanStart(self): if not self.chTP.isConfigured(): self.chTP.configure() if not self.chCNT.isConfigured(): self.chCNT.configure() if not self.chSn.isConfigured(): self.chSn.configure() #Scannable Implementations def getPosition(self): return self.getCount() def asynchronousMoveTo(self, newPos): self.setCollectionTime(newPos) self.collectData() def isBusy(self): return self.getStatus() def atScanEnd(self): if self.chTP.isConfigured(): self.chTP.clearup() if self.chCNT.isConfigured(): self.chCNT.clearup() if self.chSn.isConfigured(): self.chSn.clearup() #Scaler 8512 implementations def getTimePreset(self): if self.chTP.isConfigured(): newtp = self.chTP.caget() else: self.chTP.configure() newtp = float(self.chTP.caget()) self.chTP.clearup() self.tp = newtp return self.tp #Set the Time Preset and start counting automatically def setTimePreset(self, newTime): self.tp = newTime newtp = newTime if self.chTP.isConfigured(): tp = self.chTP.caput(newtp) else: self.chTP.configure() tp = self.chTP.caput(newtp) self.chTP.clearup() # Thread.sleep(1000) def getCount(self): if self.chSn.isConfigured(): output = self.chSn.caget() else: self.chSn.configure() output = self.chSn.caget() self.chSn.clearup() return float(output) #Detector implementations #Tells the detector to begin to collect a set of data, then returns immediately. #public void collectData() throws DeviceException; #Set the Time Preset and start counting automatically def collectData(self): #self.setTimePreset(self.tp) if self.chCNT.isConfigured(): tp = self.chCNT.caput(1) else: self.chCNT.configure() tp = self.chCNT.caput(1) self.chCNT.clearup() # Thread.sleep(1000) #Tells the detector how long to collect for during a call of the collectData() method. #public void setCollectionTime(double time) throws DeviceException; def setCollectionTime(self, newTime): self.setTimePreset(newTime) #Returns the latest data collected. #public Object readout() throws DeviceException; def getCollectionTime(self): nc = self.getTimePreset() return nc #Returns the current collecting state of the device. # return ACTIVE (1) if the detector has not finished the requested operation(s), # IDLE(0) if in an completely idle state and # STANDBY(2) if temporarily suspended. #public int getStatus() throws DeviceException; def getStatus(self): if self.chCNT.isConfigured(): self.stauts = self.chCNT.caget() else: self.chCNT.configure() self.stauts = self.chCNT.caget() self.chCNT.clearup() if self.stauts == '0': #still counting, Busy return 0 else: return 1
class EpicsCameraClass(DetectorBase): DETECTOR_STATUS_IDLE, DETECTOR_STATUS_BUSY, DETECTOR_STATUS_PAUSED, DETECTOR_STATUS_STANDBY, DETECTOR_STATUS_FAULT, DETECTOR_STATUS_MONITORING = range( 6) #CA Put Callback listener that handles the callback event class CaputCallbackListenerClass(PutListener): def __init__(self, camera): self.camera = camera def putCompleted(self, event): if event.getStatus() != CAStatus.NORMAL: print 'Camera trigger failed!' print 'Failed source: ' + event.getSource().getName() print 'Failed stuatus: ' + event.getStatus() else: #print 'The camera is called back'; self.camera.cameraStatus = EpicsCameraClass.DETECTOR_STATUS_IDLE return def getStatus(self): return self.camera.cameraStatus def __init__(self, name, pvRootCamera, panelName="Fleacam"): self.setName(name) self.setInputNames([]) self.setLevel(7) self.pvRoot = pvRootCamera self.setupEpics(pvRootCamera) self.panel = panelName self.fileName = None self.filePath = None self.filePrefix = None # self.data = ScanFileHolder(); self.dataHolder = None self.rawData = None self.dataset = None self.width = 1024 self.height = 768 # self.rawDataArray = [[0. for x in range(self.width)] for y in range(self.height)]; # self.rawDataArray = [[x+y*self.width for x in range(self.width)] for y in range(self.height)]; self.exposureTime = 1 self.cameraStatus = EpicsCameraClass.DETECTOR_STATUS_IDLE self.putListener = EpicsCameraClass.CaputCallbackListenerClass(self) # self.putListener = EpicsCameraClass.CaputCallbackListenerClass(); self.alive = True self.save = False self.logScale = False def __del__(self): self.cleanChannel(self.frameData) self.cleanChannel(self.frameWidth) self.cleanChannel(self.frameHeight) self.cleanChannel(self.capture) self.cleanChannel(self.enableStream) self.cleanChannel(self.enableCapture) def setupEpics(self, pvRootCamera): self.frameData = CAClient(pvRootCamera + ':DATA') self.configChannel(self.frameData) self.frameWidth = CAClient(pvRootCamera + ':WIDTH') self.configChannel(self.frameWidth) self.frameHeight = CAClient(pvRootCamera + ':HEIGHT') self.configChannel(self.frameHeight) self.capture = CAClient(pvRootCamera + ':SNAPSHOT') self.configChannel(self.capture) self.enableStream = CAClient(pvRootCamera + ':ENABLE') self.configChannel(self.enableStream) self.enableCapture = CAClient(pvRootCamera + ':DISAIMG1') self.configChannel(self.enableCapture) def configChannel(self, channel): if not channel.isConfigured(): channel.configure() def cleanChannel(self, channel): if channel.isConfigured(): channel.clearup() #TODO: Don need this command once the EPICS bugs fixed def turnOn(self): cmd = "caput " + self.pvRoot + ":GETSNAP1.VAL 1" print cmd os.system(cmd) cmd = "caput " + self.pvRoot + ":GETSNAP1.OUTB '" + self.pvRoot + ":CHKACQ.PROC CA'" print cmd os.system(cmd) def setAlive(self, alive=True): self.alive = alive def setSave(self, save=True): self.save = save def setFile(self, subDir, newFilePrefix): """Set file path and name""" # imagePath = InterfaceProvider.getPathConstructor().createFromProperty("gda.data.scan.datawriter.datadir"); imagePath = InterfaceProvider.getPathConstructor( ).createFromDefaultProperty() + File.separator newFilePath = os.path.join(imagePath, subDir) if not os.path.exists(newFilePath): print "Path does not exist. Create new one." os.makedirs(newFilePath) if not os.path.isdir(newFilePath): print "Invalid path" return self.filePath = newFilePath self.filePrefix = newFilePrefix print "Image file path set to " + self.filePath def getFilePath(self): return self.filePath def getFilePrefix(self): return self.filePrefix def getWidth(self): self.width = int(float(self.frameWidth.caget())) return self.width def getHeight(self): self.height = int(float(self.frameHeight.caget())) return self.height def getCameraData(self): # self.rawData = self.frameData.getController().cagetByteArray(self.frameData.getChannel()); self.width = int(float(self.frameWidth.caget())) self.height = int(float(self.frameHeight.caget())) self.rawData = self.frameData.cagetArrayByte() #cast the byte array to double array for dataset tempDoubleList = [float(x) for x in self.rawData] # self.dataset=DataSet.array(self.frameData.cagetArrayDouble()); self.dataset = dnp.array(tempDoubleList) self.dataset.shape = [self.height, self.width] # self.data = ScanFileHolder(); # self.data.addDataSet(self.getName(), self.dataset); return self.dataset def saveImageFile(self, fileName, width=None, height=None, rawData=None): if width == None: width = self.width if height == None: height = self.height if rawData == None: rawData = self.rawData # Rend an image # Create a buffered image in which to draw # bufferedImage = BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); # bufferedImage.setRGB(0, 0, width, height, rawData, 0, width); bufferedImage = BufferedImage(width, height, BufferedImage.TYPE_BYTE_INDEXED) # bufferedImage = BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); bufferedImage.getRaster().setDataElements(0, 0, width, height, rawData) # Create a graphics contents on the buffered image, draw something and then dispose it # g2d = bufferedImage.createGraphics(); # g2d.setColor(Color.white); # g2d.fillRect(0, 0, width, height); # g2d.setColor(Color.black); # g2d.fillOval(0, 0, width, height); # g2d.dispose(); # Save as PNG file = File(fileName) ImageIO.write(bufferedImage, "png", file) return def loadImageFile(self, fileName): if fileName != None: #Get data from file directly # self.data.load(PNGLoader(fileName)); self.dataHolder = dnp.io.load(fileName) # self.dataset = self.data.getAxis(0); self.dataset = self.dataHolder[0] if self.alive: self.display() return self.dataset def trigger(self, newExpos): #TODO: Maybe not needed once EPICS bugs fixed: #Disable the stream (Stream OFF) self.enableStream.caput(0) #To 'arm' the feature: self.enableCapture.caput(0) sleep(0.1) # Trigger the camera without caput callback # self.capture.caput(1); # self.cameraStatus = EpicsCameraClass.DETECTOR_STATUS_IDLE; # Trigger the camera with caput callback self.capture.getController().caput(self.capture.getChannel(), 1, self.putListener) self.cameraStatus = EpicsCameraClass.DETECTOR_STATUS_BUSY #TODO: remove the fake callback once its implemented by controls: # self.fakeCallback(); def fakeCallback(self, occurs=1): fakeStatus = CAStatus.NORMAL fakeEvent = PutEvent(self.capture.getChannel(), DBRType.ENUM, occurs, fakeStatus) self.putListener.putCompleted(fakeEvent) def postCapture(self): if not self.save: return runs = NumTracker(self.name) nextNum = NumTracker(self.name).getCurrentFileNumber() + 1 self.fileName = os.path.join(self.filePath, self.filePrefix + str(nextNum) + ".png") # print "New File name is: ----------->" + self.fileName; #My Own PNG file writer # self.saveImageFile(self.fileName); #PNG file writer from GDA Analysis package # self.data.setDataSet(self.getName(), self.dataset); # self.data.save(PNGSaver(self.fileName)); dnp.io.save(self.fileName, self.dataset) runs.incrementNumber() #DetectorBase Implementation def getPosition(self): return self.readout() def asynchronousMoveTo(self, newExpos): self.setCollectionTime(newExpos) self.collectData() # def moveTo(self, newPos): # self.asynchronousMoveTo(newPos); # while self.isBusy(): # sleep(5); # def waitWhileBusy(self): # while self.isBusy(): # sleep(5); # return; def getCollectionTime(self): return self.exposureTime def setCollectionTime(self, newExpos): self.exposureTime = newExpos def collectData(self): self.trigger(self.exposureTime) while self.getStatus() != EpicsCameraClass.DETECTOR_STATUS_IDLE: sleep(0.1) self.getCameraData() self.postCapture() return def readout(self): if self.alive: self.display() if self.save: return self.fileName else: return self.dataset def getStatus(self): return self.cameraStatus def createsOwnFiles(self): return self.save def toString(self): # self.getPosition(); if self.fileName == None: result = "No image file saved." else: result = "Latest image file saved as: " + self.fileName return result def singleShot(self, newExpos): self.setCollectionTime(newExpos) self.collectData() self.readout() def display(self, dataset=None): if dataset is None: if self.dataset is None: print "No dataset to display" return else: dataset = self.dataset if self.panel: RCPPlotter.imagePlot(self.panel, dataset) else: print "No panel set to display" raise Exception( "No panel_name set in %s. Set this or set %s.setAlive(False)" % (self.name, self.name))
class EpicsMCAWaveformDataDeviceClass(ScannableMotionBase): def __init__(self, name, rootPV, numberOfMCA): self.numberOfDetectors = numberOfMCA self.setupEpics(rootPV) self.setName(name) self.setInputNames([]) self.setLevel(7) en = [] of = [] for i in range(self.numberOfDetectors): en.append("Channel_" + str(i + 1)) of.append("%20.12f") self.setExtraNames(en) self.setOutputFormat(of) self.timeout = 30 self.defaultSize = 100 self.reset() def __del__(self): self.cleanChannel(self.chHead) for chd in self.chData: self.cleanChannel(chd) def reset(self): self.data = [[None]] * self.numberOfDetectors self.dataset = None self.readPointer = -1 def getDataLength(self): if self.dataset is None: return 0 dim = self.dataset.getDimensions() return dim[1] """ rootPV: BL07I-EA-DET-01:MCA-01 Waveform: BL07I-EA-DET-01:MCA-01:mca1 Head: BL07I-EA-DET-01:MCA-01:mca1.NORD """ def setupEpics(self, rootPV): #Epics PV for the Number of elements available (Head of waveform) # Epics PVs for the channels: self.chData = [] for i in range(self.numberOfDetectors): self.chData.append(CAClient(rootPV + ":mca" + str(i + 1))) self.configChannel(self.chData[i]) self.chHead = CAClient(rootPV + ":mca1.NORD") self.configChannel(self.chHead) def configChannel(self, channel): if not channel.isConfigured(): channel.configure() def cleanChannel(self, channel): if channel.isConfigured(): channel.clearup() # Epics level operation: def getHead(self): head = int(float(self.chHead.caget())) - 1 return head def getNewEpicsData(self, offset, size): #To check the head head = self.getHead() if offset > head: print " No new data available. Offset exceeds Head(" + str( head) + ")." return False print "New data available, Offset does not exceed Head(" + str( head) + ")." la = [] #To get the waveform data from EPICS print "---> Debug: get waveform: start at: " + ctime() for i in range(self.numberOfDetectors): # self.data[i]=self.chData[i].cagetArrayDouble(); #TODO: make sure that the self.data[i] is a list # self.data[i]=self.chData[i].cagetArrayDouble(); self.data[i] = self.chData[i].getController().cagetDoubleArray( self.chData[i].getChannel(), head + 1) # print "The type of subarray data from caget is: ", type(self.data[i]); # print "The subarray data from caget is: ", self.data[i]; la.append(self.data[i]) print "---> Debug: get waveform: end at: " + ctime() ds = DatasetFactory.createFromObject( la) #ds is a new DataSet with dimension [numberOfDetectors, size]; self.dataset = ds return True # DetectorBase Implementation def getPosition(self): resultList = list(self.readout()) resultJavaArray = jarray.array(resultList, 'd') return resultJavaArray def asynchronousMoveTo(self, newPosition): self.readPointer = int(newPosition) def isDataAvailableNew(self): self.getNewEpicsData(self.getDataLength(), self.defaultSize) len = self.getDataLength() if len == 0 or self.readPointer > len - 1: #either buffer is empty or no new data print "Checking Data Queue: no new data, buffer length: " + str( len) return False #Epics data exhausted. else: #self.readPointer <= len-1, which means there are new data in the buffer to offer print "Checking Data Queue: Data available." return True def isDataAvailable(self): # print "---> Debug: Checking data availability" len = self.getDataLength() if len == 0 or self.readPointer > len - 1: #either buffer is empty or no new data # if len == 0: # print "---> Debug: Empty buffer. No new data" # else: # print "---> Debug: No newly Buffered data. Try to fetch new data from EPICS" while self.getNewEpicsData(len, self.defaultSize): len = self.getDataLength() if self.readPointer <= len - 1: #After updating buffer, new data available return True # print "---> Debug: No more data from EPICS" return False #Epics data exhausted. else: #self.readPointer <= len-1, which means there are new data in the buffer to offer # print "---> Debug: New Buffered data available." return True def isBusy(self): return False def readout(self): if self.isDataAvailable(): temp = self.dataset.getSlice( [0, self.readPointer], [self.numberOfDetectors, self.readPointer + 1], [1, 1]) #TODO: For the new version of dataset, the above line should be changed to: # temp = self.dataset[:, self.readPointer] result = temp.getBuffer() else: #No new data to read print "Wrong readPointer: %d " % self.readPointer, " or wrong dataLength: %d" % ( self.getDataLength()) raise Exception('Array Out of Boundary Error!') return result def toString(self): return self.getName() + ": Count=" + str(self.getPosition()) def readoutChannel(self, channelIndex): result = self.readout() return result[channelIndex - 1]
class EpicsRS232PVClass(ScannableBase): def __init__(self, name, pvSend, pvReceive, pvMode, pvProc, pvTimeOut): self.setName(name) self.setInputNames([]) self.setExtraNames([name]) # self.Units=[strUnit]; self.setLevel(7) # self.setOutputFormat(["%20.12f"]); self.chSend = CAClient(pvSend) self.chSend.configure() self.chReceive = CAClient(pvReceive) self.chReceive.configure() self.chMode = CAClient(pvMode) self.chMode.configure() self.chProc = CAClient(pvProc) self.chProc.configure() self.chTimeOut = CAClient(pvTimeOut) self.chTimeOut.configure() self.lastingTime = 60 self.cs = Finder.find("command_server") self.resultSentout = False def atScanStart(self): print 'Flush the port' self.flush() #Scannable Implementations def getPosition(self): return self.lastingTime def asynchronousMoveTo(self, newPos): self.lastingTime = newPos self.flush() self.str0 = self.chReceive.caget() self.resultSentout = False print 'Ready to take command' i = 0 message = "Ready." while True: i = i + 1 self.chMode.caput("Write/Read") sleep(0.2) self.chSend.caput(message) sleep(2) self.str1 = self.chReceive.caget() print str(i) + ': str0= ' + self.str0 + ' str1=' + self.str1 if self.str0 != self.str1: self.str0 = self.str1 print 'new command coming' if self.str1 == 'ok' and self.resultSentout == True: message = 'Ready.' self.resultSentout = False continue elif self.str1 == 'ok' and self.resultSentout == False: continue result = self.interpret(self.str1) message = 'Result:' + str(result) #self.chSend.caput(message); self.resultSentout = True print 'End of monitoring.' def isBusy(self): return False def atScanEnd(self): print 'At Scan End' def toString(self): ss = self.getName() + " will monitor the port for " + str( self.getPosition()) + ' seconds.' return ss def interpret(self, strGdaCommand): print 'Execution of GDA command: ' + strGdaCommand result = self.cs.evaluateCommand(strGdaCommand) return result def flush(self): #reset self.chMode.caput("Flush") self.chProc.caput(1) #press the proc button to receive sleep(5) def setTimeOut(self, timeout): #reset self.chTimeOut.caput(timeout) sleep(0.5)
class KBMirrorPiezoDeviceClass(object): def __init__(self, rootPV='BL06I-OP-KBM-01:VFM:FPITCH', freqPV='BL06I-OP-KBM-01:VFM:FPITCH:FREQ', freqDivPV='BL06I-OP-KBM-01:HFM:FPITCH:FREQDIVISOR'): self.freq = None self.freqdiv = None self.amp = None self.offset = None self.chFreq = CAClient(freqPV) self.chFreq.configure() self.chFreqDiv = CAClient(freqDivPV) self.chFreqDiv.configure() self.chAmp = CAClient(rootPV + ':AMPL') self.chAmp.configure() self.chOffset = CAClient(rootPV + ':OFF') self.chOffset.configure() self.fovFactor = 100.0 def setFovFactor(self, newFovFactor): self.fovFactor = newFovFactor * 1.0 def __del__(self): self.cleanChannel(self.chFreq) self.cleanChannel(self.chFreqDiv) self.cleanChannel(self.chAmp) self.cleanChannel(self.chOffset) def configChannel(self, channel): if not channel.isConfigured(): channel.configure() def cleanChannel(self, channel): if channel.isConfigured(): channel.clearup() def setFreq(self, freq): self.chFreq.caput(freq) def getFreq(self): self.freq = float(str(self.chFreq.caget())) return self.freq def setFreqDiv(self, div): self.chFreqDiv.caput(div) def getFreqDiv(self): self.freqdiv = float(str(self.chFreqDiv.caget())) return self.freqdiv def setAmplitude(self, ampl): self.chAmp.caput(ampl) def getAmplitude(self): self.amp = float(str(self.chAmp.caget())) return self.amp def setOffset(self, offset): self.chOffset.caput(offset) def getOffset(self): self.offset = float(str(self.chOffset.caget())) return self.offset def update(self): self.getFreq() self.getFreqDiv() self.getAmplitude() self.getOffset() print "Frequency = %f \nFrequencyDivisor = %f \nAmplitude = %f \nOffset = %f" % ( self.freq, self.freqdiv, self.amp, self.offset)
class EpicsPVWithMonitorListener(PseudoDevice, MonitorListener, Runnable): '''create a scannable that monitors the EPICS PV value changes and update its value passively. This value is used by a running thread to control the scan processing this object participates in. ''' def __init__(self, name, pvstring, unitstring, formatstring): self.setName(name) self.setInputNames([name]) self.Units=[unitstring] self.setOutputFormat([formatstring]) self.setLevel(5) self.outcli=CAClient(pvstring) self.currenttemp=float(self.rawGetPosition()) self.monitor=None self.thread=None self.runThread=False def atScanStart(self): '''prepare to start scan: creating channel, monitor, and start control thread''' if not self.outcli.isConfigured(): self.outcli.configure() self.monitor=self.outcli.camonitor(self) self.thread=Thread(self,"Thread: "+self.getName()) self.runThread=True self.thread.start() def atScanEnd(self): '''clean up after scan finished successfully: remove monitor, destroy channel, and stop control thread''' if self.outcli.isConfigured(): self.outcli.removeMonitor(self.monitor) self.monitor=None self.outcli.clearup() self.runThread=False self.thread=None def rawGetPosition(self): ''' return current position.''' output=0.0 if not self.outcli.isConfigured(): self.outcli.configure() output=float(self.outcli.caget()) self.outcli.clearup() else: output=float(self.outcli.caget()) return float(output) def rawAsynchronousMoveTo(self,position): '''Not implemented, this is only a monitoring object''' print "object " + self.getName()+" cannot be moved." return def rawIsBusy(self): '''monitoring object never busy''' return 0 def monitorChanged(self, mevent): self.currenttemp = float(mevent.getDBR().getDoubleValue()[0]) def run(self): # print "Thread: " + self.getName() + " started" while (self.runThread): if (JythonServerFacade.getInstance().getScanStatus() == JythonStatus.RUNNING and self.currenttemp >= float(MAXTEMP)): JythonServerFacade.getInstance().pauseCurrentScan() print "Scan paused as temperature " + self.getName() +" returns: "+str(self.currenttemp) elif (JythonServerFacade.getInstance().getScanStatus() == JythonStatus.PAUSED and self.currenttemp <= float(MINTEMP)): print "Scan resumed as temperature " + self.getName() +" returns: "+str(self.currenttemp) JythonServerFacade.getInstance().resumeCurrentScan() sleep(10) def stop(self): '''clean up after scan finished successfully: remove monitor, destroy channel, and stop control thread on emergence stop or unexpected crash. If required, can be used to manually clean up the object.''' if not self.monitor == None: self.outcli.removeMonitor(self.monitor) self.monitor=None if self.outcli.isConfigured(): self.outcli.clearup() if not self.thread == None: self.runThread=False self.thread=None
class hvunit_K2410(ScannableMotionBase): '''Device to set/read voltage and current on the Keithley 2410 unit, the inizialization sets the unit to operate as V generator, and current reader. It also sets the current limit to 2 mA, if the currents limit is turned above this value or the auto key is switched the software will give a warning each time the getPosition or an asinchronousmoveto are operated To instantiate: hv=hvunit_K2410('hv','BL16I-EA-K2400-01:','Volt','%6.3f') format string: hv.setOutputFormat(['%6.3f']*2+['%6.3e']*3) ''' def __init__(self, name, pvkeithley, unitstring, formatstring, help=None): self.setName(name) self.setInputNames(['Vdem']) self.setExtraNames(['Vmes', 'Cmes', 'Rmes', 'Pmes']) self.setOutputFormat([formatstring] * 5) self.unitstring = unitstring self.setLevel(9) self.readcur = CAClient(pvkeithley + 'I') self.readcur.configure() self.readres = CAClient(pvkeithley + 'R') self.readres.configure() self.readvol = CAClient(pvkeithley + 'V') self.readvol.configure() self.sourcelev = CAClient(pvkeithley + 'SOUR_LEV') self.sourcelev.configure() self.sourcemode = CAClient(pvkeithley + 'SOUR_MODE') self.sourcemode.configure() self.sourcefunc = CAClient(pvkeithley + 'SOUR_FUNC') self.sourcefunc.configure() ############### Added By Me ########################### self.sourcerange = CAClient(pvkeithley + 'SOUR_RANG') self.sourcerange.configure() self.command = CAClient(pvkeithley + 'COMMAND') self.command.configure() self.response = CAClient(pvkeithley + 'RESPONSE') self.response.configure() ########################################################### self.sourVorC = CAClient(pvkeithley + 'SOTX') self.sourVorC.configure() self.sensVorC = CAClient(pvkeithley + 'SETX') self.sensVorC.configure() self.sensfunc = CAClient(pvkeithley + 'SENS_FUNC') self.sensfunc.configure() self.sensprot = CAClient(pvkeithley + 'SENS_PROT') self.sensprot.configure() self.sensmeasrange = CAClient(pvkeithley + 'SENS_RANG') self.sensmeasrange.configure() self.sensrangeauto = CAClient(pvkeithley + 'SENS_RANG_AUTO') self.sensrangeauto.configure() self.souroutp = CAClient(pvkeithley + 'OUTP') self.souroutp.configure() self.reset() self.__doc__ += 'Units for current: ' + self.unitstring if help is not None: self.__doc__ += '\nHelp specific to ' + self.name + ':\n' + help def reset(self): self.setSourceMode(0) # 0 set source to V mode, 1 set to curr self.setSourceFunc(0) # 0 set source to V mode, 1 set to curr self.setSourVorC(0) # 0 set source to V mode, 1 set to curr self.setSensVorC(0) # 0 set source to V mode, 1 set to curr self.setSensFunc(1) # 0 set sense to V mode, 1 set to curr #self.setSensProt(5E-6) # protection to 1mA self.setSensMeasRange(1100.0) self.setSourceRange(1100) #######delete if problem (testing) self.setSensAutoRange(0) def getPosition(self): Vdem = float(self.sourcelev.caget()) Vmes = float(self.readvol.caget()) Imes = float(self.readcur.caget()) return [Vdem, Vmes, Imes, Vmes / Imes, Vmes * Imes] def asynchronousMoveTo(self, new_position): if self.status() == '1': self.sourcelev.caput(new_position) else: print 'First turn the output on using: ' + self.name + ".ON()" def isBusy(self): if abs(float(self.sourcelev.caget()) - float(self.readvol.caget())) < 1e-3: return 0 else: return 1 def setSourceFunc(self, sour_func): # 0 set source to V mode, 1 set to curr mode self.sourcefunc.caput(sour_func) def getSourceFunc(self): return self.sourcefunc.caget() def setSourceMode(self, sour_mode): # 0 set source to V mode, 1 set to curr mode self.sourcemode.caput(sour_mode) ############### Added By Gareth ########################### def setSourceRange(self, sour_range): # Up to 1100 V set source to V mode self.sourcerange.caput(sour_range) ########################################################### def getSourceMode(self): return self.sourcemode.caget() def setSourVorC(self, VorC): # 0 set input to V mode, 1 set to curr mode self.sourVorC.caput(VorC) def getSourVorC(self): return self.sourVorC.caget() def ON(self): self.souroutp.caput(1) def OFF(self): self.souroutp.caput(0) def status(self): return self.souroutp.caget() # sensor functions def setSensVorC(self, VorC): # 0 set input to V mode, 1 set to curr mode self.sensVorC.caput(VorC) def getSensVorC(self): return self.sensVorC.caget() def setSensFunc(self, sensfunc): # 0 set input to V mode, 1 set to curr mode self.sensfunc.caput(sensfunc) def setSensProt(self, sensprot): # 0 set input to V mode, 1 set to curr mode self.sensprot.caput(sensprot) def getSensFunc(self): return float(self.sensprot.caget()) def setSensMeasRange(self, sensrange): # 0 set input to V mode, 1 set to curr mode self.sensmeasrange.caput(sensrange) def getSensMeasRange(self): return float(self.sensmeasrange.caget()) def setSensAutoRange(self, autorange): # 0 set input to man, 1 set to auto self.sensrangeauto.caput(autorange) def getSensAutoRange(self): # 0 set input to man, 1 set to auto return self.sensrangeauto.caget() def setCurrProt(self, value): self.command.caput(':SENS:CURR:PROT:LEV' + ' ' + str(value)) sleep(1) self.command.caput(':SENS:CURR:PROT:LEV' + '?') def getCurrProt(self): self.command.caput(':SENS:CURR:PROT:LEV' + '?') sleep(1) return self.response.caget()
class rs232: def __init__(self, port, panel): self.port = port panelDict = {'U1': 'I', 'U2': 'J'} if panel.upper() not in ['U1', 'U2', 'I', 'J']: print "-> patch panel choice is invalid: allowed values are U1 or U2" print "-> U1 panel selected as default." self.panel = 'U1' else: self.panel = panel panelStr = panelDict[panel.upper()] rootComStr = "BL06" + panelStr + "-EA-USER-01:ASYN" self.addrStr = rootComStr + "%1u." % self.port pvIn = rootComStr + "%1u.TINP" % self.port pvOut = rootComStr + "%1u.AOUT" % self.port self.chIn = CAClient(pvIn) self.chIn.configure() self.chOut = CAClient(pvOut) self.chOut.configure() self.baudList = [ "Unknown", "300", "600", "1200", "2400", "4800", "9600" ] self.baudList += ["19200", "38400", "57600", "115200", "230400"] self.bitList = ["Unknown", "5", "6", "7", "8"] self.stopList = ["Unknown", "1", "2"] self.parityList = ["Unknown", "None", "Even", "Odd"] self.flowList = ["Unknown", "None", "Hardware"] self.getParameters() self.report() def initialize(self): strOut = "-> setting Serial port %u " % self.port + "of panel %s" % self.panel print strOut self.chOut.caput(self.addrStr + "BAUD", str(self.baud)) sleep(0.5) self.chOut.caput(self.addrStr + "DBIT", str(self.bit)) sleep(0.5) self.chOut.caput(self.addrStr + "SBIT", str(self.stop)) sleep(0.5) self.chOut.caput(self.addrStr + "PRTY", str(self.parity)) sleep(0.5) self.chOut.caput(self.addrStr + "FCTL", self.flow) sleep(0.5) self.chOut.caput(self.addrStr + "OEOS", self.outTerm) sleep(0.5) self.chOut.caput(self.addrStr + "IEOS", self.inTerm) self.report() def setParameters(self, baud, bit, stop, parity, flow, outTermination, inTermination): #example: com.setParameters(4800,8, 1, "None", "None", "\r","\r\n") if str(baud) in self.baudList: self.baud = str(baud) else: self.baud = "Unknown" if str(bit) in self.bitList: self.bit = str(bit) else: self.bit = "Unknown" if str(stop) in self.stopList: self.stop = str(stop) else: self.stop = "Unknown" if parity in self.parityList: self.parity = str(parity) else: self.parity = "Unknown" if flow in self.flowList: self.flow = str(flow) else: self.flow = "Unknown" self.outTerm = outTermination self.inTerm = inTermination self.initialize() def setBaud(self, baud): if str(baud) in self.baudList: self.baud = str(baud) else: self.baud = "Unknown" self.initialize() def setDataBits(self, bit): if str(bit) in self.bitList: self.bit = str(bit) else: self.bit = "Unknown" self.initialize() def setStop(self, stop): if str(stop) in self.stopList: self.stop = str(stop) else: self.stop = "Unknown" self.initialize() def setInTerminator(self, inTerm): self.stop = str(inTerm) self.initialize() def getParameters(self): self.baud = self.baudList[int(self.chIn.caget(self.addrStr + "BAUD"))] self.bit = self.bitList[int(self.chIn.caget(self.addrStr + "DBIT"))] self.stop = self.stopList[int(self.chIn.caget(self.addrStr + "SBIT"))] self.parity = self.parityList[int( self.chIn.caget(self.addrStr + "PRTY"))] self.flow = self.flowList[int(self.chIn.caget(self.addrStr + "FCTL"))] self.outTerm = str(self.chIn.caget(self.addrStr + "OEOS")) self.inTerm = str(self.chIn.caget(self.addrStr + "IEOS")) def report(self): self.getParameters() outStr = "Rs232 port %d " % self.port + "of patch panel %s current configuration:" % self.panel print outStr strOut = " Baud: %s, " % self.baud + "Bit: %s," % self.bit + " Stop bit: %s," % self.stop strOut += " Parity: %s," % self.parity + " Flow: %s" % self.flow print strOut print " Output terminator: %s," % self.outTerm + " Input terminator: %s" % self.inTerm def send(self, strCom): self.chOut.caput(strCom) sleep(0.05) return def read(self): strCom = self.chIn.caget(self.addrStr + "TINP") return strCom
class EpicsPVWithMonitorListener(ScannableMotionBase, MonitorListener, Runnable): '''create a scannable that monitors the EPICS PV value changes and update its value passively. This value is used by a running thread to control the scan processing this object participates in. ''' def __init__(self, name, pvstring, unitstring, formatstring): self.setName(name) self.setInputNames([name]) self.Units = [unitstring] self.setOutputFormat([formatstring]) self.setLevel(5) self.outcli = CAClient(pvstring) self.currenttemp = float(self.rawGetPosition()) self.monitor = None self.thread = None self.runThread = False def atScanStart(self): '''prepare to start scan: creating channel, monitor, and start control thread''' if not self.outcli.isConfigured(): self.outcli.configure() self.monitor = self.outcli.camonitor(self) self.thread = Thread(self, "Thread: " + self.getName()) self.runThread = True self.thread.start() def atScanEnd(self): '''clean up after scan finished successfully: remove monitor, destroy channel, and stop control thread''' if self.outcli.isConfigured(): self.outcli.removeMonitor(self.monitor) self.monitor = None self.outcli.clearup() self.runThread = False self.thread = None def rawGetPosition(self): ''' return current position.''' output = 0.0 if not self.outcli.isConfigured(): self.outcli.configure() output = float(self.outcli.caget()) self.outcli.clearup() else: output = float(self.outcli.caget()) return float(output) def rawAsynchronousMoveTo(self, position): '''Not implemented, this is only a monitoring object''' print "object " + self.getName() + " cannot be moved." return def isBusy(self): '''monitoring object never busy''' return 0 def monitorChanged(self, mevent): self.currenttemp = float(mevent.getDBR().getDoubleValue()[0]) def run(self): # print "Thread: " + self.getName() + " started" while (self.runThread): if (JythonServerFacade.getInstance().getScanStatus() == JythonStatus.RUNNING and self.currenttemp >= float(MAXTEMP)): JythonServerFacade.getInstance().pauseCurrentScan() print "Scan paused as temperature " + self.getName( ) + " returns: " + str(self.currenttemp) elif (JythonServerFacade.getInstance().getScanStatus() == JythonStatus.PAUSED and self.currenttemp <= float(MINTEMP)): print "Scan resumed as temperature " + self.getName( ) + " returns: " + str(self.currenttemp) JythonServerFacade.getInstance().resumeCurrentScan() sleep(10) def stop(self): '''clean up after scan finished successfully: remove monitor, destroy channel, and stop control thread on emergence stop or unexpected crash. If required, can be used to manually clean up the object.''' if not self.monitor == None: self.outcli.removeMonitor(self.monitor) self.monitor = None if self.outcli.isConfigured(): self.outcli.clearup() if not self.thread == None: self.runThread = False self.thread = None
class AlicatPressureController(ScannableMotionBase): ''' classdocs ''' def __init__(self,name, rootPV, formatstring): ''' Constructor ''' self.setName(name); self.setInputNames([name]) self.setOutputFormat([formatstring]) self.setLevel(3) self.readmodecli=CAClient(rootPV+READ_MODE) self.setmodecli=CAClient(rootPV+SET_MODE) self.readpressurecli=CAClient(rootPV+READ_PRESSURE) self.settargetcli=CAClient(rootPV+SET_TARGET) self.readtargetcli=CAClient(rootPV+READ_TARGET) self.setproportionalgaincli=CAClient(rootPV+SET_PROPORTIONAL_GAIN) self.readproportionalgaincli=CAClient(rootPV+READ_PROPORTIONAL_GAIN) self.setderivativegaincli=CAClient(rootPV+SET_DERIVATIVE_GAIN) self.readderivativegaincli=CAClient(rootPV+READ_DERIVATIVE_GAIN) def getMode(self): try: if not self.readmodecli.isConfigured(): self.readmodecli.configure() output=int(self.readmodecli.caget()) self.readmodecli.clearup() else: output=int(self.readmodecli.caget()) return modes[output] except: print "Error returning current mode" return 0 def setMode(self, mode): try: if not self.setmodecli.isConfigured(): self.setmodecli.configure() self.setmodecli.caput(mode) self.setmodecli.clearup() else: self.setmodecli.caput(mode) except: print "error set to mode" def setTarget(self, target): try: if not self.settargetcli.isConfigured(): self.settargetcli.configure() self.settargetcli.caput(target) self.settargetcli.clearup() else: self.settargetcli.caput(target) except: print "error set to target flow value" def getTarget(self): try: if not self.readtargetcli.isConfigured(): self.readtargetcli.configure() output=float(self.readtargetcli.caget()) self.readtargetcli.clearup() else: output=float(self.readtargetcli.caget()) return output except: print "Error returning flow target value" return 0 def getPressure(self): try: if not self.readpressurecli.isConfigured(): self.readpressurecli.configure() output=float(self.readpressurecli.caget()) self.readpressurecli.clearup() else: output=float(self.readpressurecli.caget()) return output except: print "Error returning pressure" return 0 def getProportionalGain(self): try: if not self.readproportionalgaincli.isConfigured(): self.readproportionalgaincli.configure() output=float(self.readproportionalgaincli.caget()) self.readproportionalgaincli.clearup() else: output=float(self.readproportionalgaincli.caget()) return output except: print "Error returning Proportional Gain" return 0 def setProportionalGain(self, gain): try: if not self.setproportionalgaincli.isConfigured(): self.setproportionalgaincli.configure() self.setproportionalgaincli.caput(gain) self.setproportionalgaincli.clearup() else: self.setproportionalgaincli.caput(gain) except: print "error set to proportional gain" def getDerivativeGain(self): try: if not self.readderivativegaincli.isConfigured(): self.readderivativegaincli.configure() output=float(self.readderivativegaincli.caget()) self.readderivativegaincli.clearup() else: output=float(self.readderivativegaincli.caget()) return output except: print "Error returning Derivative Gain" return 0 def setDerivativeGain(self, gain): try: if not self.setderivativegaincli.isConfigured(): self.setderivativegaincli.configure() self.setderivativegaincli.caput(gain) self.setderivativegaincli.clearup() else: self.setderivativegaincli.caput(gain) except: print "error set to derivative gain" #### methods for scannable def atScanStart(self): pass def atPointStart(self): pass def getPosition(self): pass def asynchronousMoveTo(self, posi): pass def isBusy(self): return False def stop(self): pass def atPointEnd(self): pass def atScanEnd(self): pass
class EpicsMotorClass(ScannableMotionBase): MOTOR_STATUS_UPPERLIMIT, MOTOR_STATUS_LOWERLIMIT, MOTOR_STATUS_FAULT, MOTOR_STATUS_READY, MOTOR_STATUS_BUSY, MOTOR_STATUS_UNKNOWN, MOTOR_STATUS_SOFTLIMITVIOLATION = range( 7) def __init__(self, name, pvRootMotor, strFormat): self.setName(name) self.setInputNames([name]) # self.setExtraNames([]); self.setOutputFormat([strFormat]) self.setLevel(7) self.chVAL = CAClient(pvRootMotor + '.VAL') self.chRBV = CAClient(pvRootMotor + '.RBV') self.chDMOV = CAClient(pvRootMotor + '.DMOV') self.chSTOP = CAClient(pvRootMotor + '.STOP') self.chHLM = CAClient(pvRootMotor + '.HLM') self.chLLM = CAClient(pvRootMotor + '.LLM') self.chUNIT = CAClient(pvRootMotor + '.EGU') self.chOFF = CAClient(pvRootMotor + '.OFF') self.chVAL.configure() self.chRBV.configure() self.chDMOV.configure() self.chSTOP.configure() self.chHLM.configure() self.chLLM.configure() self.chUNIT.configure() self.chOFF.configure() self.status = EpicsMotorClass.MOTOR_STATUS_READY self.dmov = None def __del__(self): self.cleanChannel(self.chVAL) self.cleanChannel(self.chDMOV) self.cleanChannel(self.chRBV) self.cleanChannel(self.chSTOP) self.cleanChannel(self.chHLM) self.cleanChannel(self.chLLM) self.cleanChannel(self.chUNIT) self.cleanChannel(self.chOFF) def configChannel(self, channel): if not channel.isConfigured(): channel.configure() def cleanChannel(self, channel): if channel.isConfigured(): channel.clearup() def atScanStart(self): self.configChannel(self.chVAL) self.configChannel(self.chDMOV) self.configChannel(self.chRBV) self.configChannel(self.chSTOP) self.configChannel(self.chHLM) self.configChannel(self.chLLM) self.configChannel(self.chUNIT) self.configChannel(self.chOFF) def getLimits(self): hlm = float(self.chHLM.caget()) llm = float(self.chLLM.caget()) return [hlm, llm] def getUnit(self): unit = self.chUNIT.caget() return unit def getOffset(self): return float(self.chOFF.caget()) def setOffset(self, new_offset): self.chOFF.caput(new_offset) def getPosition(self): return float(self.chRBV.caget()) def asynchronousMoveTo(self, new_position): self.chVAL.caput(new_position) def isBusy(self): self.dmov = int(float(self.chDMOV.caget())) if self.dmov == 1: self.status = EpicsMotorClass.MOTOR_STATUS_READY return False elif self.dmov == 0: self.status = EpicsMotorClass.MOTOR_STATUS_BUSY return True else: print 'Error: Unexpected DMOV: ' + self.dmov self.status = EpicsMotorClass.MOTOR_STATUS_UNKNOWN return True def stop(self): print self.getName() + ": Panic Stop Called" self.chSTOP.caput(1) def toString(self): ss = self.getName() + " : " + str( self.getPosition()) + " " + self.getUnit() + " (" + str( self.getLimits()[1]) + " : " + str(self.getLimits()[0]) + ")" return ss
class EpicsTriggerClass(ScannableMotionBase): def __init__(self, name, pvSet, pvGet, pulseLength): self.setName(name) self.setInputNames([name]) self.delay = None self.pulseLength = pulseLength self.setupEpics(pvSet, pvGet) def __del__(self): self.cleanChannel(self.chSet) self.cleanChannel(self.chGet) def setupEpics(self, pvSet, pvGet): # Epics PVs for checking fast scan readiness: self.chSet = CAClient(pvSet) self.configChannel(self.chSet) self.chGet = CAClient(pvGet) self.configChannel(self.chGet) def configChannel(self, channel): if not channel.isConfigured(): channel.configure() def cleanChannel(self, channel): if channel.isConfigured(): channel.clearup() def setPulseLength(self, newLength): self.pulseLength = newLength def setDelay(self, delay): self.delay = delay def caget(self): try: result = float(self.chGet.caget()) except: print "Error getting position" return result def caput(self, new_position): try: self.chSet.caput(new_position) except: print "Error setting position" def trigger(self, pulseLength): self.triggerOn() sleep(pulseLength) self.triggerOff() def triggerOn(self): self.caput(1) def triggerOff(self): self.caput(0) def getPosition(self): return self.caget() def asynchronousMoveTo(self, newLength): if self.delay is not None: sleep(self.delay) self.pulseLength = newLength self.trigger(self.pulseLength) def isBusy(self): return False
#Simple Demo about how to use EPICS caput() and caget() method to access PVs directly from GDA from gda.epics import CAClient #Create the Client epicsClient = CAClient() #Create the PV channels and use the caput and caget method directly print epicsClient.caget("BL06I-AL-SLITS-01:X:CENTER.RBV") epicsClient.caput("BL06I-AL-SLITS-01:X:CENTER", -0.55) #Clear up the channels epicsClient.clearup()
class EpicsAsynRS232DeviceClass(object): BAUDRATE = { 'UNKNOWN': 0, '300': 1, '600': 2, '1200': 3, '2400': 4, '4800': 5, '9600': 6, '19200': 7, '38400': 8, '57600': 9, '115200': 10, '230400': 11 } DATABITS = {'UNKNOWN': 0, '5': 1, '6': 2, '7': 3, '8': 4} PARITY = {'UNKNOWN': 0, 'None': 1, 'Even': 2, 'Odd': 3} FLOWCONTROL = {'UNKNOWN': 0, 'None': 1, 'Hardware': 2} TRANSFER_MODE = { 'WriteRead': 0, 'Write': 1, 'Read': 2, 'Flush': 3, 'NonIO': 4 } FORMAT = {'ASCII': 0, 'Hybrid': 1, 'Binary': 2, 'Flush': 3} SEVERITY = {'NO_ALARM': 0, 'MINOR': 1, 'MAJOR': 2, 'INVALID': 3} def __init__(self, rootPV): self.setupEpics(rootPV) portName = 'ty_50_1' baudRate = EpicsAsynRS232DeviceClass.BAUDRATE['9600'] dataBits = EpicsAsynRS232DeviceClass.DATABITS['8'] parity = EpicsAsynRS232DeviceClass.PARITY['None'] flowControl = EpicsAsynRS232DeviceClass.FLOWCONTROL['None'] # self.setPort('', baudRate, dataBits, parity, flowControl, 1); def __del__(self): self.cleanChannel(self.chPort) self.cleanChannel(self.chConnect) self.cleanChannel(self.chBaudRate) self.cleanChannel(self.chDataBits) self.cleanChannel(self.chParity) self.cleanChannel(self.chFlowControl) self.cleanChannel(self.chTimeout) self.cleanChannel(self.chTransfer) self.cleanChannel(self.chOutputFormat) self.cleanChannel(self.chOutputTerminator) self.cleanChannel(self.chOutputString) self.cleanChannel(self.chInputFormat) self.cleanChannel(self.chInputTerminator) self.cleanChannel(self.chInputString) self.cleanChannel(self.chErrorString) self.cleanChannel(self.chStatus) self.cleanChannel(self.chSeverity) self.cleanChannel(self.chScanMode) self.cleanChannel(self.chProcess) """ Asyn Driver for RS232: Port: BL07I-EA-USER-01:ASYN1.PORT Connection: BL07I-EA-USER-01:ASYN1.PCNCT Baud Rate: BL07I-EA-USER-01:ASYN1.BAUD Data Bits: BL07I-EA-USER-01:ASYN1.DBIT Parity: BL07I-EA-USER-01:ASYN1.PRTY Flow Control: BL07I-EA-USER-01:ASYN1.FCTL Timeout: BL07I-EA-USER-01:ASYN1.TMOT Transfer: BL07I-EA-USER-01:ASYN1.TMOD Output Format: BL07I-EA-USER-01:ASYN1.OFMT Output Terminator: BL07I-EA-USER-01:ASYN1.OEOS Output String: BL07I-EA-USER-01:ASYN1.AOUT Input Format: BL07I-EA-USER-01:ASYN1.IFMT Input Terminator: BL07I-EA-USER-01:ASYN1.IEOS Input String: BL07I-EA-USER-01:ASYN1.TINP Error String: BL07I-EA-USER-01:ASYN1.ERRS I/O Status: BL07I-EA-USER-01:ASYN1.STAT I/O Severity: BL07I-EA-USER-01:ASYN1.SEVR Scan Mode: BL07I-EA-USER-01:ASYN1.SCAN Process: BL07I-EA-USER-01:ASYN1.PROC """ def setupEpics(self, rootPV): self.chPort = CAClient(rootPV + ".PORT") self.configChannel(self.chPort) self.chConnect = CAClient(rootPV + ".PCNCT") self.configChannel(self.chConnect) self.chBaudRate = CAClient(rootPV + ".BAUD") self.configChannel(self.chBaudRate) self.chDataBits = CAClient(rootPV + ".DBIT") self.configChannel(self.chDataBits) self.chParity = CAClient(rootPV + ".PRTY") self.configChannel(self.chParity) self.chFlowControl = CAClient(rootPV + ".FCTL") self.configChannel(self.chFlowControl) self.chTimeout = CAClient(rootPV + ".TMOT") self.configChannel(self.chTimeout) self.chTransfer = CAClient(rootPV + ".TMOD") self.configChannel(self.chTransfer) self.chOutputFormat = CAClient(rootPV + ".OFMT") self.configChannel(self.chOutputFormat) self.chOutputTerminator = CAClient(rootPV + ".OEOS") self.configChannel(self.chOutputTerminator) self.chOutputString = CAClient(rootPV + ".AOUT") self.configChannel(self.chOutputString) self.chInputFormat = CAClient(rootPV + ".IFMT") self.configChannel(self.chInputFormat) self.chInputTerminator = CAClient(rootPV + ".IEOS") self.configChannel(self.chInputTerminator) self.chInputString = CAClient(rootPV + ".TINP") self.configChannel(self.chInputString) self.chErrorString = CAClient(rootPV + ".ERRS") self.configChannel(self.chErrorString) self.chStatus = CAClient(rootPV + ".STAT") self.configChannel(self.chStatus) self.chSeverity = CAClient(rootPV + ".SEVR") self.configChannel(self.chSeverity) self.chScanMode = CAClient(rootPV + ".SCAN") self.configChannel(self.chScanMode) self.chProcess = CAClient(rootPV + ".PROC") self.configChannel(self.chProcess) def configChannel(self, channel): if not channel.isConfigured(): channel.configure() def cleanChannel(self, channel): if channel.isConfigured(): channel.clearup() def setTimeout(self, timeout): self.chTimeout.caput(timeout) sleep(0.5) def toCheck(self): severity = int(self.chSeverity.caget()) if severity == self.SEVERITY["NO_ALARM"] or severity == self.SEVERITY[ "MINOR"]: return True else: print "Severity Error:" return False def setPort(self, portName, baudRate, dataBits, parity, flowControl, timeout): self.chPort.caput(portName) self.chBaudRate.caput(baudRate) self.chDataBits.caput(dataBits) self.chParity.caput(parity) self.chFlowControl.caput(flowControl) self.chTimeout.caput(timeout) self.chScanMode.caput(0) # Set to Passive self.flush() self.toCheck() def setOutputTerminator(self, terminator): self.chOutputTerminator.caput(terminator) def setInputTerminator(self, terminator): self.chInputTerminator.caput(terminator) def setScanMode(self, newScanMode): self.chScanMode.caput(newScanMode) def flush(self): self.chTransfer.caput(self.TRANSFER_MODE['Flush']) self.chProcess.caput(1) sleep(0.5) def write(self, sendString): self.chTransfer.caput(self.TRANSFER_MODE['Write']) self.chOutputString.caput(sendString) # self.chProcess.caput(1); sleep(0.5) self.toCheck() def read(self): self.chTransfer.caput(self.TRANSFER_MODE['Read']) # self.chProcess.caput(1); reply = self.chInputString.caget() self.toCheck() return reply def writeAndRead(self, sendString): self.chTransfer.caput(self.TRANSFER_MODE['WriteRead']) self.chOutputString.caput(sendString) # self.chProcess.caput(1); sleep(0.5) reply = self.chInputString.caget() self.toCheck() return reply
class EpicsWaveformDeviceClass(ScannableMotionBase): def __init__(self, name, rootPV, channelList, extraChannelList=[], elementCounter="iddFastScanElementCounter"): self.numberOfChannels=len(channelList); self.setupEpics(rootPV); self.setName(name); self.setInputNames(["pIndex"]); self.setLevel(7); en=[]; of=["%5.0f"]; for c in channelList + extraChannelList: en.append( str(c) ); of.append("%20.12f"); self.setExtraNames(en); self.setOutputFormat(of); self.timeout=30; self.defaultSize = 100; self.low = 0; self.high = 1000; self.keyChannel=None; # self.fastScanElementCounter = None; self.fastScanElementCounter = Finder.find(elementCounter); self.reset(); def __del__(self): self.cleanChannel(self.chHead); for chd in self.chData: self.cleanChannel(chd); def reset(self): self.data=[[None]]*self.numberOfChannels; self.dataset = None; self.readPointer = -1; #according to Pete leicester GDA should not reset Element Counter # self.resetHead(); def setFilter(self, low, high, keyChannel): self.low = low; self.high = high; self.keyChannel=keyChannel; def getDataLength(self): if self.dataset is None: return 0; dim=self.dataset.shape return dim[1]; """ waveform PVs rootPV = 'BL06I-MO-FSCAN-01' pvElementCounter= 'BL06I-MO-FSCAN-01:ELEMENTCOUNTER' pvDataChannel01 = 'BL06I-MO-FSCAN-01:CH1DATA' pvDataChannel02 = 'BL06I-MO-FSCAN-01:CH2DATA' pvDataChannel03 = 'BL06I-MO-FSCAN-01:CH3DATA' pvDataChannel04 = 'BL06I-MO-FSCAN-01:CH4DATA' ... """ def setupEpics(self, rootPV): #Epics PV for the Number of elements available self.chHead=CAClient(rootPV + ":ELEMENTCOUNTER"); self.configChannel(self.chHead); # Epics PVs for the channels: self.chData=[]; for i in range(self.numberOfChannels): self.chData.append( CAClient(rootPV + ":CH" + str(i+1) + "DATA")); self.configChannel(self.chData[i]); def configChannel(self, channel): if not channel.isConfigured(): channel.configure(); def cleanChannel(self, channel): if channel.isConfigured(): channel.clearup(); # Epics level operation: def getHead(self): if self.fastScanElementCounter != None: return int(float(self.fastScanElementCounter()))-1; else: head = int(float(self.chHead.caget()))-1; return head; def resetHead(self): self.chHead.caput(0); def getNewEpicsData(self, offset, size): #To check the head head=self.getHead(); if offset > head: # print " No new data available. Offset exceeds Head(" + str(head) + ")."; return False; # print "New data available, Offset does not exceed Head(" + str(head) + ")."; la=[]; #To get the waveform data from EPICS # print "---> Debug: get waveform: start at: " + ctime(); for i in range(self.numberOfChannels): # self.data[i]=self.chData[i].cagetArrayDouble(); #TODO: make sure that the self.data[i] is a list # self.data[i]=self.chData[i].cagetArrayDouble(); # self.data[i]=self.chData[i].getController().cagetDoubleArray(self.chData[i].getChannel(), head+1); # print "The type1 of subarray data from caget is: ", type1(self.data[i]); # print "The subarray data from caget is: ", self.data[i]; # print "---> Debug: get waveform: end at: " + ctime(); ok = False while( not ok): try: # logger.fullLog(None,"EpicsWaveformDeviceClass.getNewEpicsData: reading data for channel %d" %i) self.data[i]=self.chData[i].getController().cagetDoubleArray(self.chData[i].getChannel(), head+1); # logger.fullLog(None,"EpicsWaveformDeviceClass.getNewEpicsData: data read") ok=True except: type1, exception, traceback = sys.exc_info() logger.fullLog(None,"Error in EpicsWaveformDeviceClass.getNewEpicsData reading channel %d" %i, type1, exception , traceback, False) ScriptBase.checkForPauses(); la.append(self.data[i]); # ds=DataSet(la);#ds is a new DataSet with dimension [numberOfDetectors, size]; #TODO: For the new dataset, the above line should be changed to the following ds=dnp.array(la) #ds is a new DataSet with dimension [numberOfDetectors, size]; self.dataset = ds; return True; def getUnFilteredPosition(self): # resultList = list(self.readout()); resultList = [self.readPointer]; #The index resultList.extend(list(self.readout())); # the readout resultJavaArray = jarray.array(resultList, 'd'); return resultJavaArray; def applyFilter(self, inputList, low, high, index): if index is None: return inputList; outputList=[]; judge=inputList[index] for i in range(len(inputList)): if (judge>=low and judge<=high) or i==index: outputList.append(inputList[i]); else: outputList.append(0); return outputList; def getFilteredPosition(self): filteredReadout = self.applyFilter(list(self.readout()), self.low-1.0, self.high+1.0, self.keyChannel-1); # resultList = list(self.readout()); resultList = [self.readPointer]; #The index resultList.extend(filteredReadout); # the readout resultJavaArray = jarray.array(resultList, 'd'); return resultJavaArray; # DetectorBase Implementation def getPosition(self): # return self.getUnFilteredPosition(); return self.getFilteredPosition(); def asynchronousMoveTo(self,newPosition): self.readPointer = int(newPosition); def isDataAvailableNew(self): self.getNewEpicsData(self.getDataLength(), self.defaultSize); len1 = self.getDataLength(); if len1 == 0 or self.readPointer > len1-1:#either buffer is empty or no new data print "Checking Data Queue: no new data, buffer length: " + str(len1); return False;#Epics data exhausted. else: #self.readPointer <= len1-1, which means there are new data in the buffer to offer print "Checking Data Queue: Data available." return True; def isDataAvailable(self): # print "---> Debug: Checking data availability" len1 = self.getDataLength(); if len1 == 0 or self.readPointer > len1-1:#either buffer is empty or no new data while self.getNewEpicsData(len1, self.defaultSize): len1 = self.getDataLength(); if self.readPointer <= len1-1:#After updating buffer, new data available # logger.simpleLog("EpicsWaveformDeviceClass.isDataAvailable: True, len1=%d, readPointer= %d" % (len1, self.readPointer)); return True; # print "---> Debug: No more data from EPICS" # logger.simpleLog("EpicsWaveformDeviceClass.isDataAvailable: False"); return False;#Epics data exhausted. else: #self.readPointer <= len1-1, which means there are new data in the buffer to offer # print "---> Debug: New Buffered data available." # logger.simpleLog("EpicsWaveformDeviceClass.isDataAvailable: True"); return True; def isBusy(self): return False; def readout(self): if self.isDataAvailable(): result = self.dataset[:, self.readPointer] else:#No new data to read print "Wrong readPointer: %d " %self.readPointer, " or wrong dataLength: %d" %(self.getDataLength()); raise Exception('Array Out of Boundary Error!'); ev=self.getExtraChannelValues(result); result.resize(result.size+len(ev)) result[-len(ev):]=ev return result; def toString(self): return self.getName() + ": Count=" + str(self.getPosition()); #To artificially add extra channels of which value is a calculation of existing channels def getExtraChannelValues(self, d): Id, I0, If, Ifft, Iffb = d[0], d[1], d[2], d[3], d[6]; #Channel 2, channel 1 and channel 3 if I0 <= 0.001: I0 += 0.001; idi0 = float(Id)/I0; ifi0 = float(If)/I0; ifi0ft = float(Ifft)/I0; ifi0fb = float(Iffb)/I0; return [idi0, ifi0, ifi0ft, ifi0fb]; def readoutChannel(self, channelIndex): result = self.readout(); return result[channelIndex-1];
class FastEnergyScanClass: def __init__(self): self.startEnergy = CAClient(pvStartEnergy) self.endEnergy = CAClient(pvEndEnergy) self.scanTime = CAClient(pvScanTime) self.numberOfPoints = CAClient(pvNumberOfPoints) self.startButton = CAClient(pvStartButton) self.status = CAClient(pvReadyState) self.buildButton = CAClient(pvBuildButton) self.elementCounter = CAClient(pvElementCounter) self.channel01 = CAClient(pvDataChannel01) self.channel02 = CAClient(pvDataChannel02) self.channel03 = CAClient(pvDataChannel03) self.channel04 = CAClient(pvDataChannel04) self.energyPGM = CAClient(pvEnergyPGM) self.energyIDGAP = CAClient(pvEnergyIDGAP) self.scanReady01 = CAClient(pvScanReady01) self.scanReady02 = CAClient(pvScanReady02) self.scanReady03 = CAClient(pvScanReady03) self.scanReady04 = CAClient(pvScanReady04) self.scanStatus = 'Idle' self.arrayHead = 0 def atScanStart(self): self.scanStatus = 'Idle' self.arrayHead = 0 if not self.startEnergy.isConfigured(): self.startEnergy.configure() if not self.endEnergy.isConfigured(): self.endEnergy.configure() if not self.scanTime.isConfigured(): self.scanTime.configure() if not self.numberOfPoints.isConfigured(): self.numberOfPoints.configure() if not self.startButton.isConfigured(): self.startButton.configure() if not self.buildButton.isConfigured(): self.buildButton.configure() if not self.status.isConfigured(): self.status.configure() if not self.elementCounter.isConfigured(): self.elementCounter.configure() if not self.channel01.isConfigured(): self.channel01.configure() if not self.channel02.isConfigured(): self.channel02.configure() if not self.channel03.isConfigured(): self.channel03.configure() if not self.channel04.isConfigured(): self.channel04.configure() if not self.energyPGM.isConfigured(): self.energyPGM.configure() if not self.energyIDGAP.isConfigured(): self.energyIDGAP.configure() if not self.scanReady01.isConfigured(): self.scanReady01.configure() if not self.scanReady02.isConfigured(): self.scanReady02.configure() if not self.scanReady03.isConfigured(): self.scanReady03.configure() if not self.scanReady04.isConfigured(): self.scanReady04.configure() def atScanEnd(self): self.scanStatus = 'Idle' self.arrayHead = 0 if self.startEnergy.isConfigured(): self.startEnergy.clearup() if self.endEnergy.isConfigured(): self.endEnergy.clearup() if self.scanTime.isConfigured(): self.scanTime.clearup() if self.numberOfPoints.isConfigured(): self.numberOfPoints.clearup() if self.startButton.isConfigured(): self.startButton.clearup() if self.buildButton.isConfigured(): self.buildButton.clearup() if self.status.isConfigured(): self.status.clearup() if self.elementCounter.isConfigured(): self.elementCounter.clearup() if self.channel01.isConfigured(): self.channel01.clearup() if self.channel02.isConfigured(): self.channel02.clearup() if self.channel03.isConfigured(): self.channel03.clearup() if self.channel04.isConfigured(): self.channel04.clearup() if self.energyPGM.isConfigured(): self.energyPGM.clearup() if self.energyIDGAP.isConfigured(): self.energyIDGAP.clearup() if self.scanReady01.isConfigured(): self.scanReady01.clearup() if self.scanReady02.isConfigured(): self.scanReady02.clearup() if self.scanReady03.isConfigured(): self.scanReady03.clearup() if self.scanReady04.isConfigured(): self.scanReady04.clearup() #To check the PGM and ID motors are ready for the fast scan def checkMotorReady(self): c1 = int(float(self.scanReady01.caget())) c2 = int(float(self.scanReady02.caget())) c3 = int(float(self.scanReady03.caget())) c4 = int(float(self.scanReady04.caget())) return (c1 == 0 and c2 == 0 and c3 == 0 and c4 == 0) def setEnergyRange(self, startEnergy, endEnergy): self.startEnergy.caput(startEnergy) self.endEnergy.caput(endEnergy) def setTime(self, scanTime, pointTime): numberOfPoints = scanTime / pointTime self.scanTime.caput(scanTime) self.numberOfPoints.caput(numberOfPoints) #trigger the fast scan def start(self): self.startButton.caput(1) #trigger the fast scan def build(self): self.buildButton.caput('Busy') # click the build button def isBuilt(self): strStatus = self.getStatus() if strStatus == 'Scan ready': #Finished building return True else: return False #Total 6 status from Epics, plus internal Idle status ## "Scan complete" ## "Scan aborted" # "Moving PGM to midpoint" # "Calculating parameters" ## "Moving IDD and PGM to start position" ## "Scan ready" ## "Starting scan move" # "Scanning" ## "Scan complete" # "Idle" def getStatus(self): newScanStatus = self.status.caget() if newScanStatus != self.scanStatus: # scan status changed self.scanStatus = newScanStatus print self.scanStatus return self.scanStatus def isBusy(self): strStatus = self.getStatus() if strStatus == 'Scan complete': print 'fast energy scan finished.' return False else: return True def isScanning(self): strStatus = self.getStatus() if strStatus == 'Scanning' or strStatus == 'Starting scan move': return True else: return False #To get the number of valid data from the waveform def getDataNumbers(self): strLength = self.elementCounter.caget() return int(float(strLength)) def saveData(self): numberOfPoints = self.getDataNumbers() #self.printData(numberOfPoints); self.saveSRSData(numberOfPoints) def saveSRSData(self, numberOfPoints): srsHeader = [ " &SRS\n", " SRSRUN=null,SRSDAT=null,SRSTIM=null,\n", " SRSSTN='null',SRSPRJ='null ',SRSEXP='null ',\n", " SRSTLE=' ',\n", " SRSCN1=' ',SRSCN2=' ',SRSCN3=' ',\n", " &END\n" ] try: runs = NumTracker("tmp") nextNum = runs.getCurrentFileNumber() #nextNum = runs.incrementNumber() path = InterfaceProvider.getPathConstructor().createFromProperty( "gda.data.scan.datawriter.datadir") fileName = path + "/" + str(nextNum + 1) + ".dat" print fileName fh = open(fileName, 'w') #SRS Header for i in range(len(srsHeader)): fh.write(srsHeader[i]) titleLine = '%(v1)s \t %(v2)s \t %(v3)s \t %(v4)s \t %(v5)s \t %(v6)s \n' % { 'v1': 'PGM Energy', 'v2': 'ID GAP Energy', 'v3': 'Channel 1', 'v4': 'Channel 2', 'v5': 'Channel 3', 'v6': 'Channel 4' } fh.write(titleLine) arrayEnergyPGM = self.energyPGM.cagetArrayDouble() arrayEnergyIDGAP = self.energyIDGAP.cagetArrayDouble() arrayChannel01 = self.channel01.cagetArrayDouble() arrayChannel02 = self.channel02.cagetArrayDouble() arrayChannel03 = self.channel03.cagetArrayDouble() arrayChannel04 = self.channel04.cagetArrayDouble() for i in range(numberOfPoints): #print i, arrayEnergyPGM[i], arrayEnergyIDGAP[i], arrayChannel01[i], arrayChannel02[i], arrayChannel03[i], arrayChannel04[i]; newLine = '%(v1).8f \t %(v2).8f \t %(v3).8f \t %(v4).8f \t %(v5).8f \t %(v6).8f \n' % { 'v1': arrayEnergyPGM[i], 'v2': arrayEnergyIDGAP[i], 'v3': arrayChannel01[i], 'v4': arrayChannel02[i], 'v5': arrayChannel03[i], 'v6': arrayChannel04[i] } fh.write(newLine) fh.close() runs.incrementNumber() except: print "ERROR: Could not save data into file." def printData(self, numberOfPoints): arrayEnergyPGM = self.energyPGM.cagetArrayDouble() arrayEnergyIDGAP = self.energyIDGAP.cagetArrayDouble() arrayChannel01 = self.channel01.cagetArrayDouble() arrayChannel02 = self.channel02.cagetArrayDouble() arrayChannel03 = self.channel03.cagetArrayDouble() arrayChannel04 = self.channel04.cagetArrayDouble() for i in range(numberOfPoints): print i, arrayEnergyPGM[i], arrayEnergyIDGAP[i], arrayChannel01[ i], arrayChannel02[i], arrayChannel03[i], arrayChannel04[i] def plotWholeData(self, numberOfPoints): arrayEnergyPGM = self.energyPGM.cagetArrayDouble() arrayEnergyIDGAP = self.energyIDGAP.cagetArrayDouble() arrayChannel01 = self.channel01.cagetArrayDouble() arrayChannel02 = self.channel02.cagetArrayDouble() arrayChannel03 = self.channel03.cagetArrayDouble() arrayChannel04 = self.channel04.cagetArrayDouble() dataSetPGM = DatasetFactory.zeros(numberOfPoints) for i in range(numberOfPoints): dataSetPGM.set(arrayEnergyPGM[i], i) dvp = Plotter() dvp.plotOver("Data Vector", dataSetPGM.getIndexDataSet(), dataSetPGM) def plotData(self): newHead = self.getDataNumbers() if self.arrayHead >= newHead: print "No new data added for plotting" return self.arrayHead = newHead #to get new data arrayEnergyPGM = self.energyPGM.cagetArrayDouble() arrayEnergyIDGAP = self.energyIDGAP.cagetArrayDouble() arrayChannel01 = self.channel01.cagetArrayDouble() arrayChannel02 = self.channel02.cagetArrayDouble() arrayChannel03 = self.channel03.cagetArrayDouble() arrayChannel04 = self.channel04.cagetArrayDouble() dataSetEnergyPGM = DatasetFactory.zeros(newHead) dataSetEnergyPGM.setName("PGM Energy") dataSetEnergyIDGAP = DatasetFactory.zeros(newHead) dataSetEnergyIDGAP.setName("ID Gap Energy") dataSetChannel01 = DatasetFactory.zeros(newHead) dataSetChannel01.setName("Channel 1") dataSetChannel02 = DatasetFactory.zeros(newHead) dataSetChannel02.setName("Channel 2") dataSetChannel03 = DatasetFactory.zeros(newHead) dataSetChannel03.setName("Channel 3") dataSetChannel04 = DatasetFactory.zeros(newHead) dataSetChannel04.setName("Channel 4") for i in range(0, newHead): #print i, arrayEnergyPGM[i], arrayEnergyIDGAP[i], arrayChannel01[i], arrayChannel02[i], arrayChannel03[i], arrayChannel04[i]; dataSetEnergyPGM[i] = arrayEnergyPGM[i] dataSetEnergyIDGAP[i] = arrayEnergyIDGAP[i] dataSetChannel01[i] = arrayChannel01[i] dataSetChannel02[i] = arrayChannel02[i] dataSetChannel03[i] = arrayChannel03[i] dataSetChannel04[i] = arrayChannel04[i] #print i, arrayEnergyPGM[i], arrayEnergyIDGAP[i], arrayChannel01[i], arrayChannel02[i], arrayChannel03[i], arrayChannel04[i]; dvp = Plotter() indexDataSet = dataSetEnergyPGM.getIndexDataSet() #dvp.plot("Data Vector", indexDataSet, [dataSetChannel01, dataSetChannel02, dataSetChannel03, dataSetChannel04]); dvp.plot("Data Vector", dataSetEnergyPGM, [ dataSetChannel01, dataSetChannel02, dataSetChannel03, dataSetChannel04 ])
class FastEnergyScanControlClass(object): """ """ #CA Put Callback listener that handles the callback event class CaputCallbackListenerClass(PutListener): def __init__ (self, device): self.device = device; def putCompleted(self, event): if event.getStatus() != CAStatus.NORMAL: # @UndefinedVariable logger.simpleLog('Motor move failed!'); logger.simpleLog('Failed source: ' + event.getSource().getName()); else: if self.device.isScanAborted(): logger.simpleLog('Epics Scan aborted. The FastEnergyScanControlClass calls back successfully'); else: logger.logger.debug('FastEnergyScanControlClass.CaputCallbackListenerClass.putCompleted:Epics Scan finished. The FastEnergyScanControlClass calls back successfully. Delaying...'); sleep(1); self.device.fixDataHead(); logger.logger.debug('FastEnergyScanControlClass.CaputCallbackListenerClass.putCompleted:... Data Head fixed.'); self.device.isCalled = True; return; FASTSCAN_MODE = range(3); FASTSCAN_MODE_EPICS_STRING = ["Fixed", "Const velocity", "Slaved"]; FASTSCAN_MODE_GDA_STRING = ['fixid', 'cvid', 'slaveid']; FASTSCAN_STATUS = range(10); FASTSCAN_STATUS_STRING = ["Scan complete", "Scan aborted", "Moving PGM to midpoint", "Calculating parameters", "Moving IDD and PGM to start position", "Scan ready", "Starting scan move", "Scanning", "Scan complete", "Idle"]; #Total 6 status from Epics, plus internal Idle status # "Scan complete" # "Scan aborted" # "Moving PGM to midpoint" # "Calculating parameters" # "Moving IDD and PGM to start position" # "Scan ready" # "Starting scan move" # "Scanning" # "Scan complete" # "Idle" def __init__(self, name, rootPV): self.name = name; self.setupEpics(rootPV); self.startEnergy=600; self.endEnergy=700; self.scanStatus='Idle'; self.putListener = FastEnergyScanControlClass.CaputCallbackListenerClass(self); self.isCalled = True; self.areaDetector=None self.adbase=None self.pvName=None self.existingCameraParametersCaptured=False def __del__(self): self.cleanChannel(self.chScanReady01); self.cleanChannel(self.chScanReady02); self.cleanChannel(self.chScanReady03); self.cleanChannel(self.chScanReady04); self.cleanChannel(self.chScanReady); self.cleanChannel(self.chStartEnergy); self.cleanChannel(self.chEndEnergy); self.cleanChannel(self.chScanTime); self.cleanChannel(self.chNumberOfPoints); self.cleanChannel(self.chIdMove); self.cleanChannel(self.chAreaDetector); self.cleanChannel(self.chADCIntegration); self.cleanChannel(self.chBuild); self.cleanChannel(self.chBuildStatus); self.cleanChannel(self.chExecute); self.cleanChannel(self.chStop); self.cleanChannel(self.chStatus); self.cleanChannel(self.chHead); self.cleanChannel(self.chVelocityStatus); self.cleanChannel(self.chPGMStatus); def setupEpics(self, rootPV): # Epics PVs for checking fast scan readiness: self.chScanReady01=CAClient(rootPV + ":PGM:HOME.RVAL"); self.configChannel(self.chScanReady01); self.chScanReady02=CAClient(rootPV + ":PGM:MODE.RVAL"); self.configChannel(self.chScanReady02); self.chScanReady03=CAClient(rootPV + ":ID:ENABLE.RVAL"); self.configChannel(self.chScanReady03); self.chScanReady04=CAClient(rootPV + ":DATA:OK.RVAL"); self.configChannel(self.chScanReady04); # New Epics PV for checking fast scan readiness, this should be used to replace the above four pvs: self.chScanReady=CAClient(rootPV + ":STATUS"); self.configChannel(self.chScanReady); # Epics PVs for fast scan parameters setup: self.chStartEnergy=CAClient(rootPV + ":EV:START"); self.configChannel(self.chStartEnergy); self.chEndEnergy=CAClient(rootPV + ":EV:FINISH"); self.configChannel(self.chEndEnergy); self.chScanTime=CAClient(rootPV + ":TIME"); self.configChannel(self.chScanTime); self.chNumberOfPoints=CAClient(rootPV + ":NPULSES"); self.configChannel(self.chNumberOfPoints); self.chIdMode=CAClient(rootPV + ":IDMODE"); self.configChannel(self.chIdMode); self.chAreaDetector=CAClient(rootPV + ":AD:TRIGGER"); self.configChannel(self.chAreaDetector); self.chADCIntegration=CAClient(rootPV + ":ADCSC:TRIGGER"); self.configChannel(self.chADCIntegration); # Epics PVs for fast scan control and status: self.chBuild=CAClient(rootPV + ":BUILD"); self.configChannel(self.chBuild); self.chBuildStatus=CAClient(rootPV + ":BUILDSTATUS"); self.configChannel(self.chBuildStatus); self.chExecute=CAClient(rootPV + ":START"); self.configChannel(self.chExecute); self.chStop=CAClient(rootPV + ":STOP");self.configChannel(self.chStop); self.chStatus=CAClient(rootPV + ":RUN:STATE"); self.configChannel(self.chStatus); #Epics PV for the Number of elements available self.chHead=CAClient(rootPV + ":ELEMENTCOUNTER"); self.configChannel(self.chHead); self.chVelocityStatus=CAClient("BL06I-OP-IDD-01:SET:VEL.STAT"); self.configChannel(self.chVelocityStatus); #To check the PGM is not stucked self.chPGMStatus=CAClient("BL06I-OP-PGM-01:ENERGY.DMOV"); self.configChannel(self.chPGMStatus); def configChannel(self, channel): if not channel.isConfigured(): channel.configure(); def cleanChannel(self, channel): if channel.isConfigured(): channel.clearup(); # def fixPGM(self): # pgminit(); #To check the PGM is not used or stucked def checkPGM(self): dmov = int(float(self.chPGMStatus.caget())); if (dmov == 0): #stucked # self.fixPGM(); dmov = int(float(self.chPGMStatus.caget())); #return True if DMOV == 1 return (dmov == 1); #To check the PGM and ID motors are ready for the fast scan def checkMotorReady(self): # c1= int(float(self.chScanReady01.caget())); # c2= int(float(self.chScanReady02.caget())); # c3= int(float(self.chScanReady03.caget())); # c4= int(float(self.chScanReady04.caget())); # return (c1 == 0 and c2 == 0 and c3 == 0 and c4 == 0); c= int(float(self.chScanReady.caget())); return (c == 0); ##### add support for area detector def setAreaDetector(self, areadet): self.areaDetector=areadet def getAreaDetector(self): return self.areaDetector def prepareAreaDetectorForCollection(self, areadet, expotime, numImages): #get camera control object cs=areadet.getCollectionStrategy() adcmode=cs.getDecoratee() self.pcocontroller=adcmode.getPcoController() self.adbase=self.pcocontroller.getAreaDetector() if self.adbase is not None: #capture existing settings that will be changed for fast scan self.aquire_state=self.adbase.getAcquireState() self.exposure_period=self.adbase.getAcquirePeriod() self.exposure_time=self.adbase.getAcquireTime() self.image_mode=self.adbase.getImageMode() self.num_images=self.adbase.getNumImages() self.trigger_mode=self.adbase.getTriggerMode() self.adc_mode=self.pcocontroller.getADCMode() self.pixel_rate=self.pcocontroller.getPixRate() # self.arm_mode=self.pcocontroller.getArmMode() self.existingCameraParametersCaptured=True #stop camera before change settings self.adbase.stopAcquiring() #set camera parameters for fast scan self.adbase.setAcquireTime(expotime) self.adbase.setAcquirePeriod(expotime) self.adbase.setImageMode(1) # Multiple self.adbase.setNumImages(numImages) self.adbase.setTriggerMode(0) # Auto self.pcocontroller.setADCMode(0) # OneADC self.pcocontroller.setPixRate(0) # 10MHz # self.pcocontroller.setArmMode(1) # arm detector self.prepareKBMirrorRastering(expotime) else: raise RuntimeError("self.adbase is not defined!") def setKBRasteringControlPV(self, pvname): self.pvName=pvname def getKBRasteringControlPV(self): return self.pvName def prepareKBMirrorRastering(self, expotime): if self.pvName: self.ch=CAClient(self.pvName); self.configChannel(self.ch); self.cachedCh=float(self.ch.caget()) if "FREQ" in self.pvName: self.ch.caput(1.0/expotime) elif "PERIOD" in self.pvName: self.ch.caput(expotime) def restoreKBMirrorRastering(self): if self.pvName: self.ch.caput(self.cachedCh) def restoreAreaDetectorParametersAfterCollection(self): if not self.existingCameraParametersCaptured: return if self.adbase is not None: #stop camera before change settings self.adbase.stopAcquiring() #set camera parameters for fast scan self.adbase.setAcquireTime(self.exposure_time) self.adbase.setAcquirePeriod(self.exposure_period) self.adbase.setImageMode(self.image_mode) # Multiple self.adbase.setNumImages(self.num_images) self.adbase.setTriggerMode(self.trigger_mode) # Auto self.pcocontroller.setADCMode(self.adc_mode) # OneADC self.pcocontroller.setPixRate(self.pixel_rate) # 10MHz # self.pcocontroller.setArmMode(self.arm_mode) # arm detector if self.aquire_state == 1: self.adbase.startAcquiring() self.restoreKBMirrorRastering() else: raise RuntimeError("self.adbase is not defined!") def configureFileWriterPlugin(self, areadet,numImages): if not isinstance(areadet, NXDetector): raise Exception("'%s' detector is not a NXDetector! " % (areadet.getName())) additional_plugin_list = areadet.getAdditionalPluginList() datawriter=None scanNumber=nfn() for each in additional_plugin_list: if isinstance(each, MultipleImagesPerHDF5FileWriter): datawriter=each datawriter.getNdFile().getPluginBase().disableCallbacks() datawriter.getNdFile().getPluginBase().setBlockingCallbacks(0) filePathUsed = InterfaceProvider.getPathConstructor().createFromDefaultProperty() + "/" f=File(filePathUsed) if not f.exists(): if not f.mkdirs(): raise Exception("Folder does not exist and cannot be made: " + str(filePathUsed)) datawriter.getNdFile().setFilePath(filePathUsed) if not datawriter.getNdFile().filePathExists(): raise Exception("Path does not exist on IOC '" + filePathUsed + "'") datawriter.getNdFile().setFileName("pco") datawriter.getNdFile().setFileNumber(scanNumber) datawriter.getNdFile().setAutoIncrement(0) datawriter.getNdFile().setAutoSave(0) datawriter.getNdFile().setFileWriteMode(2); datawriter.getNdFileHDF5().setStoreAttr(0) datawriter.getNdFileHDF5().setStorePerform(0) datawriter.getNdFileHDF5().setLazyOpen(True); datawriter.getNdFileHDF5().setBoundaryAlign(0); datawriter.getNdFileHDF5().setNumCapture(numImages); datawriter.getNdFileHDF5().setNumRowChunks(0); datawriter.getNdFileHDF5().setNumColChunks(0); datawriter.getNdFileHDF5().setNumFramesChunks(0); datawriter.getNdFileHDF5().setNumFramesFlush(0); datawriter.getNdFileHDF5().startCapture(); datawriter.getNdFile().getPluginBase().enableCallbacks() elif isinstance(each, SingleImagePerFileWriter): datawriter=each datawriter.getNdFile().getPluginBase().disableCallbacks() filePathUsed = InterfaceProvider.getPathConstructor().createFromDefaultProperty() + "/" + str(scanNumber) + "_PCOImage/" f=File(filePathUsed) if not f.exists(): if not f.mkdirs(): raise Exception("Folder does not exist and cannot be made: " + str(filePathUsed)) datawriter.getNdFile().setFilePath(filePathUsed) if not datawriter.getNdFile().filePathExists(): raise Exception("Path does not exist on IOC '" + filePathUsed + "'") datawriter.getNdFile().setFileName("pco") datawriter.getNdFile().setFileNumber(1) datawriter.getNdFile().setAutoIncrement(1) datawriter.getNdFile().setAutoSave(1) datawriter.getNdFile().setFileWriteMode(0) datawriter.getNdFile().getPluginBase().enableCallbacks() if datawriter is None: raise Exception("Cannot find EPICS File Writer Plugin for detector %s" % (areadet.getName())) # datawriter.prepareForCollection(numImages, ScanInformation.EMPTY) def disableFileWritingPlugin(self, areadet): if not isinstance(areadet, NXDetector): raise Exception("'%s' detector is not a NXDetector! " % (areadet.getName())) additional_plugin_list = areadet.getAdditionalPluginList() datawriter=None for each in additional_plugin_list: if isinstance(each, MultipleImagesPerHDF5FileWriter): datawriter=each datawriter.getNdFile().getPluginBase().disableCallbacks() datawriter.getNdFileHDF5().stopCapture(); elif isinstance(each, SingleImagePerFileWriter): datawriter=each datawriter.getNdFile().getPluginBase().disableCallbacks() if datawriter is None: raise Exception("Cannot find EPICS File Writer Plugin for detector %s" % (areadet.getName())) def setupAreaDetectorROIs(self, rois, roi_provider_name='pco_roi'): '''update ROIs list in GDA but not yet set to EPICS This must be called when ROI is changed, and before self.prepareAreaDetectorForCollection(areadet) @param rois: list of rois i.e. [[x_start,y_start,x_size,y_size],[x_start,y_start,x_size,y_size],[x_start,y_start,x_size,y_size],[x_start,y_start,x_size,y_size]] ''' if not type(rois)== ListType: raise Exception("Input must be a list of ROIs, each provides a list specifies [x_start,y_start,x_size,y_size]") i=1 newRois=[] for roi in rois: newRoi=ImutableRectangularIntegerROI(roi[0],roi[1],roi[2],roi[3],'Region'+str(i)) i +=1 newRois.append(newRoi) roi_provider=Finder.find(roi_provider_name) roi_provider.updateRois(newRois) def clearAreaDetectorROIs(self, roi_provider_name='pco_roi'): roi_provider=Finder.find(roi_provider_name) roi_provider.updateRois([]) def getROIStatsPair4DetectorFromGDA(self, areadet): ''' retrieve GDA ROI and STAT pairs for a given detector ''' if not isinstance(areadet, NXDetector): raise Exception("'%s' detector is not a NXDetector! " % (areadet.getName())) additional_plugin_list = areadet.getAdditionalPluginList() roi_stat_pairs=[] for each in additional_plugin_list: if isinstance(each, ADRoiStatsPair): roi_stat_pairs.append(each) return roi_stat_pairs def prepareAreaDetectorROIsForCollection(self, areadet, numImages): '''configure ROIs and STATs plugins in EPICS for data collection with regions of interests @param areadet: must be a NXDetector ''' for each in self.getROIStatsPair4DetectorFromGDA(areadet): #ScanInformation is not used in zacscan so just create a dummy to make Java method works #update ROIs and enable EPICS rois and stats plugins each.prepareForCollection(numImages, ScanInformation.EMPTY) def stopROIStatsPair(self, areadet): '''stop or abort ROI and STAT plug-in processes. This must be called when users interrupt or abort beam stabilisation process! ''' for each in self.getROIStatsPair4DetectorFromGDA(areadet): each.stop() def completeCollectionFromROIStatsPair(self,areadet): '''must be called when beam stabilisation process completed! IMPORTANT: test prove this method leave ROI-STAT pair locked, should not be used until Java code fix this. ''' for each in self.getROIStatsPair4DetectorFromGDA(areadet): each.completeCollection() def enableAreaDetector(self): self.chAreaDetector.caput(1) # 0-Disabled, 1-Enabled def disableAreaDetector(self): self.chAreaDetector.caput(0) # 0-Disabled, 1-Enabled def setEnergyRange(self, startEnergy, endEnergy): self.startEnergy=startEnergy; self.endEnergy=endEnergy; self.chStartEnergy.caput(startEnergy); self.chEndEnergy.caput(endEnergy); def getEnergyRange(self): return [self.startEnergy, self.endEnergy]; def setTime(self, scanTime, pointTime): numberOfPoints = scanTime/pointTime; self.chScanTime.caput(scanTime) self.chNumberOfPoints.caput(numberOfPoints) def getNumberOfPoint(self): return int( float(self.chNumberOfPoints.caget()) ); def getVelocityStatus(self): return self.chVelocityStatus.caget(); def getDataHead(self): head = int(float(self.chHead.caget())); return head; def fixDataHead(self): head = self.getDataHead(); numberOfPoint = self.getNumberOfPoint(); if head >= numberOfPoint: logger.logger.debug("Enough points generated by the scan."); else: logger.simpleLog("Not enough points generated by the scan. Fix is needed to finished the scan."); self.chHead.caput(numberOfPoint); #trigger the scan def startScan(self): '''trigger the scan and setup callback listener for checking ''' self.isCalled = False; self.chExecute.getController().caput(self.chExecute.getChannel(), 1, self.putListener); #Abort the scan def abortScan(self): self.chStop.caput(1); # self.fixPGM(); #set the ID mode def setIDMode(self, mode): self.chIdMode.caput(mode) #select the ID Mode #get the ID mode def getIDMode(self): idmode=self.chIdMode.caget(); return int(float(idmode)); #trigger the scan def buildScan(self, timeout=None): if timeout is None: self.chBuild.caput('Busy') # click the build button and return else: self.chBuild.caput('Busy', timeout) # click the build button and wait for the call back def isBuilt(self): strStatus = self.getScanStatus(); # strBuildStatus=self.chBuildStatus.caget(); # if strBuildStatus == "Failure": # raise Exception("Fast energy scan CAN NOT be built. Please check the ID speed setting is not too slow!"); if strStatus == 'Build failed - ID velocity too slow': #Built error raise Exception("Fast energy scan CAN NOT be built. Please check the ID speed setting is not too slow!"); elif strStatus == 'Scan ready': #Finished building return True else: return False; def isScanReady(self): strStatus = self.getScanStatus(); if strStatus == "Scan ready": #Finished building return True else: return False; def isScanning(self): strStatus = self.getScanStatus(); if strStatus == "Scanning": #Finished building return True else: return False; def isScanComplete(self): strStatus = self.getScanStatus(); if strStatus in ['Scan complete', 'Scan aborted'] and self.isCalled: #The last scan is finished and is called back return True else: return False; def isScanAborted(self): strStatus = self.getScanStatus(); if strStatus == "Scan aborted": #The last scan is aborted. return True else: return False; def getScanStatus(self): newScanStatus = self.chStatus.caget(); if newScanStatus != self.scanStatus: # scan status changed self.scanStatus = newScanStatus; # print self.scanStatus; return self.scanStatus;
class GasRigValveClass(ScannableMotionBase): '''Create a scannable for a gas injection rig''' def __init__(self, name, rootPV): self.setName(name); self.setInputNames([name]) self.setLevel(5) self.controlcli=CAClient(rootPV+VALVE_CONTROL) self.statecli=CAClient(rootPV+VALVE_STATUS) self.modecli=CAClient(rootPV+VALVE_MODE) self.interlockscli=CAClient(rootPV+VALVE_INTERLOCKS) self.operationscli=CAClient(rootPV+VALVE_OPERATIONS) def getStatus(self): try: if not self.statecli.isConfigured(): self.statecli.configure() output=int(self.statecli.caget()) self.statecli.clearup() else: output=int(self.statecli.caget()) return STATUS_SEQUENCE[output] except: print "Error returning current state" return 0 def getMode(self): try: if not self.modecli.isConfigured(): self.modecli.configure() output=int(self.modecli.caget()) self.modecli.clearup() else: output=int(self.modecli.caget()) return MODE_SEQUENCE[output] except: print "Error returning current state" return 0 def getInterlocks(self): try: if not self.interlockscli.isConfigured(): self.interlockscli.configure() output=int(self.interlockscli.caget()) self.interlockscli.clearup() else: output=int(self.interlockscli.caget()) return INTERLOCKS_SEQUENCE[output] except: print "Error returning current state" return 0 def getOperations(self): try: if not self.operationscli.isConfigured(): self.operationscli.configure() output=int(self.operationscli.caget()) self.operationscli.clearup() else: output=int(self.operationscli.caget()) return output except: print "Error returning current state" return 0 def setControl(self,new_position): try: if not self.controlcli.isConfigured(): self.controlcli.configure() self.controlcli.caput(new_position) self.controlcli.clearup() else: self.controlcli.caput(new_position) except: print "error setting sequence" def on(self): self.setControl(0) def off(self): self.setControl(1) def reset(self): self.setControl(2) #### methods for scannable def getPosition(self): return self.getStatus() def asynchronousMoveTo(self, new_position): self.setControl(float(new_position)) def isBusy(self): return False def atScanStart(self): pass def atPointStart(self): pass def stop(self): pass def atPointEnd(self): pass def atScanEnd(self): pass
class EpicsScandataDeviceClass(ScannableMotionBase): def __init__(self, name, rootPV): self.numberOfDetectors=None; self.setupEpics(rootPV); self.setName(name); self.setInputNames(["index"]); self.setLevel(7); en=[]; of=["%5.0f"]; for i in range(self.numberOfDetectors): en.append("Channel_" + str(i+1)); of.append("%20.12f"); self.setExtraNames(en); self.setOutputFormat(of); self.timeout=30; self.defaultSize = 100; self.reset(); def __del__(self): self.cleanChannel(self.chHead); self.cleanChannel(self.chDetectorNumbers); self.cleanChannel(self.chOffset); self.cleanChannel(self.chSize); self.cleanChannel(self.chUpdate); for chd in self.chData: self.cleanChannel(chd); def reset(self): self.setDataOffset(0); self.resetHead(); self.setSize(self.defaultSize); self.data=[[None]]*self.numberOfDetectors; self.dataset = None; self.readPointer = -1; def getDataLength(self): if self.dataset is None: return 0; dim=self.dataset.shape return dim[1]; def setupEpics(self, rootPV): #Epics PV for the Number of elements available self.chHead=CAClient(rootPV + ":ELEMENTCOUNTER"); self.configChannel(self.chHead); #Epics PV for the Number of channels (detectors) self.chDetectorNumbers=CAClient(rootPV + ":NODETECTORS"); self.configChannel(self.chDetectorNumbers); #Epics PV for setting the starting point for reading self.chOffset=CAClient(rootPV + ":STARTINDEX"); self.configChannel(self.chOffset); #Epics PV for setting the number of points for reading self.chSize=CAClient(rootPV + ":NOELEMENTS"); self.configChannel(self.chSize); #Epics PV for getting the data specified in offset and size self.chUpdate=CAClient(rootPV + ":UPDATE"); self.configChannel(self.chUpdate); # Epics PVs for the channels: self.numberOfDetectors = int(float(self.chDetectorNumbers.caget())); self.chData=[]; for i in range(self.numberOfDetectors): self.chData.append( CAClient(rootPV + ":CH" + str(i+1) + "SUBARRAY")); self.configChannel(self.chData[i]); def configChannel(self, channel): if not channel.isConfigured(): channel.configure(); def cleanChannel(self, channel): if channel.isConfigured(): channel.clearup(); # Epics level operation: def getHead(self): head = int(float(self.chHead.caget()))-1; return head; def resetHead(self): self.chHead.caput(0); def setDataOffset(self, offset): self.chOffset.caput(self.timeout,offset); def getDataOffset(self): offset = int(float(self.chOffset.caget())); return offset; def setSize(self, size): self.chSize.caput(self.timeout,size); def getSize(self): size = int(float(self.chSize.caget())); return size; def updateData(self, offset, size): return self.getNewEpicsData(offset, size); def getNewEpicsData(self, offset, size): #To check the head head=self.getHead(); if offset > head: # print " No new data available. Offset exceeds Head(" + str(head) + ")."; return False; # print "New data available, Offset "+ str(offset) + " does not exceed Head(" + str(head) + ")."; size = min(size, head-offset+1); # print "New offset %d" %offset + ", new size %d" %size; self.setDataOffset(offset); self.setSize(size); # Ask EPICS to update the subarrays # print "---> Debug: updating subarrays: start at: " + ctime(); self.chUpdate.caput(self.timeout, 1); # self.chUpdate.caput(1); # sleep(1) # print "###> Debug: the current ElementCounter is : " + str(self.getHead()); # print "###> Debug: the subarray size is: " + str(size); # print "---> Debug: updating subarrays: end at: " + ctime(); la=[]; # To get the subarray data from EPICS # print "---> Debug: get subarrays: start at: " + ctime(); for i in range(self.numberOfDetectors): # self.data[i]=self.chData[i].cagetArrayDouble(); # TODO: make sure that the self.data[i] is a list # self.data[i]=self.chData[i].cagetArrayDouble(); # self.data[i]=self.chData[i].getController().cagetDoubleArray(self.chData[i].getChannel(), self.getSize()); ok = False while( not ok): try: # logger.fullLog(None,"EpicsWaveformDeviceClass.getNewEpicsData: reading data for channel %d" %i) self.data[i]=self.chData[i].getController().cagetDoubleArray(self.chData[i].getChannel(), size); # logger.fullLog(None,"EpicsWaveformDeviceClass.getNewEpicsData: data read") ok=True except: type1, exception, traceback = sys.exc_info() logger.fullLog(None,"Error in EpicsWaveformDeviceClass.getNewEpicsData reading channel %d" %i, type1, exception , traceback, False) ScriptBase.checkForPauses() # print "The type of subarray data from caget is: ", type(self.data[i]); # print "The subarray data from caget is: ", self.data[i]; la.append(self.data[i]); # print "---> Debug: get subarrays: end at: " + ctime(); # ds=DataSet(la);#ds is a new DataSet with dimension [numberOfDetectors, size]; # TODO: For the new dataset, the above line should be changed to the following ds=dnp.array(la) #ds is a new DataSet with dimension [numberOfDetectors, size]; if self.dataset is None: self.dataset = ds; else: self.dataset=self.dataset.append(ds, 1) # extend the dataset along the "size" axis # TODO: make sure that the self.dataset is a two dimensional dataset # print "###> Debug: the internal dataset is: ", self.dataset.getDimensions(); return True; # DetectorBase Implementation def getPosition(self): # resultList = list(self.readout()); resultList = [self.readPointer]; resultList.extend(list(self.readout())); resultJavaArray = jarray.array(resultList, 'd'); return resultJavaArray; def asynchronousMoveTo(self,newPosition): self.readPointer = int(newPosition); def isDataAvailableNew(self): self.getNewEpicsData(self.getDataLength(), self.defaultSize); len1 = self.getDataLength(); if len1 == 0 or self.readPointer > len1-1:#either buffer is empty or no new data print "Checking Data Queue: no new data, buffer length: " + str(len1); return False;#Epics data exhausted. else: #self.readPointer <= len1-1, which means there are new data in the buffer to offer print "Checking Data Queue: Data available." return True; def isDataAvailable(self): # print "---> Debug: Checking data availability" len1 = self.getDataLength(); if len1 == 0 or self.readPointer > len1-1:#either buffer is empty or no new data # if len1 == 0: # print "---> Debug: Empty buffer. No new data" # else: # print "---> Debug: No newly Buffered data. Try to fetch new data from EPICS" while self.getNewEpicsData(len1, self.defaultSize): len1 = self.getDataLength(); if self.readPointer <= len1-1:#After updating buffer, new data available return True; # print "---> Debug: No more data from EPICS" return False;#Epics data exhausted. else: #self.readPointer <= len1-1, which means there are new data in the buffer to offer # print "---> Debug: New Buffered data available." return True; def isBusy(self): return False; def readout(self): if self.isDataAvailable(): # temp = self.dataset.getSlice([0,self.readPointer], [self.numberOfDetectors, self.readPointer+1], [1,1]); #TODO: For the new version of dataset, the above line should be changed to: temp = self.dataset[:, self.readPointer] result = temp.getBuffer(); else:#No new data to read print "Wrong readPointer: %d " %self.readPointer, " or wrong dataLength: %d" %(self.getDataLength()); raise Exception('Array Out of Boundary Error!'); return result; def toString(self): return self.getName() + ": Count=" + str(self.getPosition()); def readoutChannel(self, channelIndex): result = self.readout(); return result[channelIndex-1];
class EpicsShutterClass(ScannableMotionBase): '''Create PD for single EPICS positioner The PVs to control the two EH2 photon shutters on I09 are: BL09I-PS-SHTR-02:CON BL09J-PS-SHTR-02:CON With states, 0 = Open 1 = Close 2 = Reset The status can be read back on. BL09I-PS-SHTR-02:STA BL09J-PS-SHTR-02:STA With states, 0 = Fault 1 = Open 2 = Opening 3 = Closed 4 = Closing ''' def __init__(self, name, pvcontrolstring, pvstatestring, unitstring, formatstring): self.setName(name) self.setInputNames([name]) self.Units = [unitstring] self.setOutputFormat([formatstring]) self.setLevel(3) self.incli = CAClient(pvcontrolstring) self.statecli = CAClient(pvstatestring) def rawGetPosition(self): output = 1 try: if not self.incli.isConfigured(): self.incli.configure() output = float(self.incli.caget()) #self.incli.clearup() return int(output) except: print "Error returning position" return 1 def rawAsynchronousMoveTo(self, new_position): try: if self.incli.isConfigured(): self.incli.caput(new_position) else: self.incli.configure() self.incli.caput(new_position) #self.incli.clearup() except: print "error moving to position" def isBusy(self): try: if self.statecli.isConfigured(): self.status = self.statecli.caget() else: self.statecli.configure() self.status = self.statecli.caget() #self.statecli.clearup() return int(self.status) == 2 or int(self.status) == 4 except: print "problem with isMoving string: " + self.status + ": Returning busy status" return 0
class pomsTemperatureScannable(ScannableBase): def __init__(self, name): self.setName(name) self.setInputNames(['temperature']) self.setExtraNames([]) self.setOutputFormat(["%3.3f"]) self.Units = ['Kelvin'] self.ca = CAClient() self.iambusy = False self.runningThread = False self.setPoint = 300 self.threshold = 0.5 # K self.timeWithinThreshold = 30 # s self.controlSensor = 2 self.rampRate = 5 #K / min def atScanStart(self): return def atScanEnd(self): return def asynchronousMoveTo(self, newPos): self.iambusy = True self.setPoint = float(newPos) #repeat as sometimes the message does not get through self.ca.caput("ME01D-EA-TCTRL-01:SETP_S", float(newPos)) # set set point time.sleep(4) self.ca.caput("ME01D-EA-TCTRL-01:SETP_S", float(newPos)) # set set point time.sleep(4) print "Changing temperature to %3.2f" % newPos if not self.runningThread: # if a temperature checking thread is not running from a previous pos command then start a new one mythread = Thread(checkTemperatureThread(self)) mythread.start() def getPosition(self): return float(self.ca.caget("ME01D-EA-TCTRL-01:KRDG1")) def isBusy(self): return self.iambusy def stop(self): print "stopping temperature scannable - the temperature will continue to change to the setpoint" self.runningThread = False self.iambusy = False def getSpeed(self): return (self.rampRate / 60.0) #return speed in K / s def setRampRate(self, rampRate): self.rampRate = rampRate if (self.rampRate == 0): while (self.ca.caget("ME01D-EA-TCTRL-01:RAMPST") != '0.0'): self.ca.caput("ME01D-EA-TCTRL-01:RAMPST_S", 1) time.sleep(2) self.ca.caput("ME01D-EA-TCTRL-01:RAMPST_S", 0) time.sleep(4) print "Temperature ramp disabled" else: while (self.ca.caget("ME01D-EA-TCTRL-01:RAMPST") != '1.0'): self.ca.caput("ME01D-EA-TCTRL-01:RAMPST_S", 0) time.sleep(2) self.ca.caput("ME01D-EA-TCTRL-01:RAMPST_S", 1) time.sleep(4) self.ca.caput("ME01D-EA-TCTRL-01:RAMP_S", self.rampRate) # set the ramp rate in K / min time.sleep(1) print "Temperature ramp rate set to %2.1f K / min" % self.rampRate
class EpicsFilter(ScannableBase): """Filter Class that implementing the GDA ScannableMotionBase interface""" IN_LIMIT_STATUS_NOTIN, IN_LIMIT_STATUS_IN = range(2) IN_LIMIT_STRING = ['Not in', 'In'] OUT_LIMIT_STATUS_NOTOUT, OUT_LIMIT_STATUS_OUT = range(2) OUT_LIMIT_STRING = ['Not out', 'Out'] FILTER_POSITION_OUT, FILTER_POSITION_IN, FILTER_POSITION_UNKNOWN = range(3) FILTER_POSITION_STRING = ['Out', 'In', 'Unknown'] FILTER_OUT, FILTER__IN = range(2) def __init__(self, name, rootPV): """ name: a pseudo device name for the filter rootPV: the EPICS base PV """ self.setName(name) self.setInputNames([name]) self.setExtraNames([]) # self.setLevel(7); self.filterRootPV = rootPV self.material = 'Al' self.thickness = 0 self.timeOutLimit = 30 self.inLimStatus = None self.outLimStatus = None self.filterPosition = None self.scaleOrder = None self.setup() def __del__(self): self.cleanChannel(self.chControl) self.cleanChannel(self.chInStatus) self.cleanChannel(self.chOutStatus) def setup(self): self.chControl = CAClient(self.filterRootPV + ':CTRL') self.configChannel(self.chControl) self.chInStatus = CAClient(self.filterRootPV + ':INLIM') self.configChannel(self.chInStatus) self.chOutStatus = CAClient(self.filterRootPV + ':OUTLIM') self.configChannel(self.chOutStatus) self.getFilterPosition() def configChannel(self, channel): if not channel.isConfigured(): channel.configure() def cleanChannel(self, channel): if channel.isConfigured(): channel.clearup() def setMaterial(self, m): self.material = m def getMaterial(self): return self.material def setThickness(self, t): self.thickness = t def getThickness(self): return self.thickness def setTimeOut(self, newTimeOut): self.timeOutLimit = newTimeOut def setOrder(self, newOrder): self.scaleOrder = newOrder def getOrder(self): return self.scaleOrder def setOrderValue(self, newOrderValue): if newOrderValue == None: self.scaleOrder = None return # self.scaleOrder = int(math.log(newOrderValue, 2)); #Does not work with Jython2.1 self.scaleOrder = int(math.log(newOrderValue) / math.log(2)) def setFilter(self, newPosition): # self.chControl.caput(self.timeOutLimit, newPosition); self.chControl.caput(newPosition) def setFilterIn(self): if self.getFilterPosition() != EpicsFilter.FILTER_POSITION_IN: self.setFilter(EpicsFilter.FILTER__IN) def setFilterOut(self): if self.getFilterPosition() != EpicsFilter.FILTER_POSITION_OUT: self.setFilter(EpicsFilter.FILTER_OUT) def getFilterPosition(self): # if self.filterPosition == EpicsFilter.FILTER_POSITION_UNKNOWN: #just changed from GDA # sleep(0.3); self.inLimStatus = int(float(self.chInStatus.caget())) self.outLimStatus = int(float(self.chOutStatus.caget())) # print 'InLimStatus: ' + str(self.inLimStatus); # print 'OutLimStatus: ' + str(self.outLimStatus); if self.inLimStatus == EpicsFilter.IN_LIMIT_STATUS_IN and self.outLimStatus == EpicsFilter.OUT_LIMIT_STATUS_NOTOUT: #In status self.filterPosition = EpicsFilter.FILTER_POSITION_IN elif self.inLimStatus == EpicsFilter.IN_LIMIT_STATUS_NOTIN and self.outLimStatus == EpicsFilter.OUT_LIMIT_STATUS_OUT: #Out status self.filterPosition = EpicsFilter.FILTER_POSITION_OUT else: #Something wrong self.filterPosition = EpicsFilter.FILTER_POSITION_UNKNOWN # self.positionString = EpicsFilter.FILTER_POSITION_STRING[self.filterPosition]; # print 'Filter Position: ' + str(self.filterPosition); return self.filterPosition """ScannableMotionBase Implementation""" def toString(self): self.getPosition() ss = self.getName() + ': ' + EpicsFilter.FILTER_POSITION_STRING[ self.filterPosition] return ss def getPosition(self): return self.getFilterPosition() def asynchronousMoveTo(self, newPosition): if type(newPosition).__name__ == 'str': if newPosition.lower() == 'in': value = 1 elif newPosition.lower() == 'out': value = 0 else: value = None elif type(newPosition).__name__ == 'int': if newPosition == 0 or newPosition == 1: value = newPosition else: value = None else: value = None if self.getFilterPosition() != value: self.filterPosition = EpicsFilter.FILTER_POSITION_UNKNOWN self.setFilter(value) sleep(0.6) return def isBusy(self): # print 'Filter Position from isBusy:' + str(self.filterPosition); if self.getFilterPosition() == EpicsFilter.FILTER_POSITION_UNKNOWN: return True else: return False
class SamplePressure(ScannableBase, MonitorListener): """ create a sannable to provide control of gas pressure in the sample. It will reports to users when the system pressure is less than the sample pressure requested. """ def __init__(self, name, systempressure): """ Constructor """ self.setName(name) self.setInputNames([name]) self.increment = 0.01 self.target = 0.0 self.lastTarget = 0.0 self.sampleP = 0.0 self.currentpressure = 0.0 self.pressureTolerance = 0.002 self.outcli = CAClient(CurrentPressure) self.incli = CAClient(TargetPressure) self.sysp = systempressure self.initialiseTarget() def atScanStart(self): """intialise parameters before scan""" # TODOS check requested sample pressure can be reached if not self.outcli.isConfigured(): self.outcli.configure() if not self.incli.isConfigured(): self.incli.configure() self.target = self.getPosition() def atScanEnd(self): """clean up resources""" if self.outcli.isConfigured(): self.outcli.clearup() if self.incli.isConfigured(): self.incli.clearup() def atPointStart(self): pass def atPointEnd(self): pass def getPosition(self): """ return the current gas pressure in sample """ try: if not self.outcli.isConfigured(): self.outcli.configure() output = float(self.outcli.caget()) self.outcli.clearup() else: output = float(self.outcli.caget()) return output except: print "Error returning current position" return 0 def asynchronousMoveTo(self, new_position): """ move the sample pressure to the specified value asynchronously. """ try: self.lastTarget = round(self.getLastTarget(), 3) self.sampleP = round(self.getPosition(), 3) self.target = round(float(new_position), 3) thread.start_new_thread(self.setSamplePressure, (self.sampleP, self.target, self.increment)) except: print "error moving sample pressure to (%s): %f" % (sys.exc_info()[0], float(new_position)) raise def isBusy(self): return abs(self.getPosition() - self.getTarget()) > self.getTolerance() def stop(self): """ stop or abort pressure move in the sample. """ self.asynchronousMoveTo(self.getPosition()) if self.outcli.isConfigured(): self.outcli.clearup() if self.incli.isConfigured(): self.incli.clearup() def setSamplePressure(self, SampleP, target, increment): # SET FINAL SAMPLE PRESSURE AND INCREMENTS if SampleP < target: SampleP = round(self.lastTarget + increment, 3) # increments in bar if SampleP > target: return try: if not self.incli.isConfigured(): self.incli.configure() while SampleP <= target: # final sample pressure in bar # interruptable() self.incli.caput(SampleP) # print "set sample pressure to "+str(SampleP)+", target is "+str(target) sleep(5) # wait time in seconds SampleP = round(SampleP + increment, 3) # check if smaple pressure required greater the system pressure then exit if self.sysp.getPosition() < target: # TODOs recharge the system pressure here??? print "System pressure %f is less than the demanding sample pressure %f. Please abort this scan or re-charge the system pressure." % ( self.sysp.getPosition(), target, ) # if self.incli.isConfigured(): # self.incli.clearup() except: print "error moving to position" elif SampleP > target: SampleP = round(self.lastTarget - increment, 3) # increments in bar if SampleP < target: return if SampleP < 0: SampleP = 0 if target < 0: raise Exception("Pressure cannot be negative.") try: if not self.incli.isConfigured(): self.incli.configure() while SampleP >= target: # final sample pressure in bar # interruptable() self.incli.caput(SampleP) # print "set sample pressure to "+str(SampleP)+", target is "+str(target) sleep(5) # wait time in seconds SampleP = round(SampleP - increment, 3) if SampleP < 0: self.incli.caput(0) break # if self.incli.isConfigured(): # self.incli.clearup() except: print "error moving to position" else: print "already at the sample pressure." return def setIncrement(self, value): self.increment = value def getIncrement(self): return self.increment def getTarget(self): return self.target def getLastTarget(self): try: if not self.incli.isConfigured(): self.incli.configure() output = float(self.incli.caget()) self.incli.clearup() else: output = float(self.incli.caget()) return output except: print "Error returning target value" return 0 def initialiseTarget(self): self.lastTarget = self.getLastTarget() def getTolerance(self): return self.pressureTolerance def setTolerance(self, value): self.pressureTolerance = value
class ROI_STAT_Pair_Class(): def __init__(self, pvRootName=PV_ROOT_NAME): self.pvRootName = pvRootName self.ca = CAClient() return def setRoi(self, roiNum, Xstart, Ystart, Xsize, Ysize): roiXStartPV = self.pvRootName + ":ROI" + str(roiNum) + ":MinX" roiYStartPV = self.pvRootName + ":ROI" + str(roiNum) + ":MinY" roiXSizePV = self.pvRootName + ":ROI" + str(roiNum) + ":SizeX" roiYSizePV = self.pvRootName + ":ROI" + str(roiNum) + ":SizeY" self.ca.caput(roiXStartPV, Xstart) self.ca.caput(roiYStartPV, Ystart) self.ca.caput(roiXSizePV, Xsize) self.ca.caput(roiYSizePV, Ysize) sleep(0.1) self.activateStat(roiNum) self.activateROIs(roiNum) return def activateStat(self, roiNum): statEnablePV = self.pvRootName + ":STAT" + str( roiNum) + ":EnableCallbacks" self.ca.caput(statEnablePV, "Enable") statStatOnPV = self.pvRootName + ":STAT" + str( roiNum) + ":ComputeStatistics" self.ca.caput(statStatOnPV, "Yes") def activateROIs(self, roiNum): roiEnablePV = self.pvRootName + ":ROI" + str( roiNum) + ":EnableCallbacks" self.ca.caput(roiEnablePV, "Enable") roiXEnablePV = self.pvRootName + ":ROI" + str(roiNum) + ":EnableX" self.ca.caput(roiXEnablePV, "Enable") roiYEnablePV = self.pvRootName + ":ROI" + str(roiNum) + ":EnableY" self.ca.caput(roiYEnablePV, "Enable") def deactivateStat(self, roiNum): statEnablePV = self.pvRootName + ":STAT" + str( roiNum) + ":EnableCallbacks" self.ca.caput(statEnablePV, "Disable") statStatOnPV = self.pvRootName + ":STAT" + str( roiNum) + ":ComputeStatistics" self.ca.caput(statStatOnPV, "No") def deactivateROIs(self, roiNum): roiEnablePV = self.pvRootName + ":ROI" + str( roiNum) + ":EnableCallbacks" self.ca.caput(roiEnablePV, "Disable") roiXEnablePV = self.pvRootName + ":ROI" + str(roiNum) + ":EnableX" self.ca.caput(roiXEnablePV, "Disable") roiYEnablePV = self.pvRootName + ":ROI" + str(roiNum) + ":EnableY" self.ca.caput(roiYEnablePV, "Disable") def getRoiAvg(self, roiNum): roiAvgPV = self.pvRootName + ":STAT" + str(roiNum) + ":MeanValue_RBV" return float(self.ca.caget(roiAvgPV))
class PGM_GratingClass(ScannableMotionUnitsBase): def __init__(self, name, strGetPV, strSetPV, strGratingMoveStatusPV, units="lines/mm"): self.setName(name) self.setInputNames([]) self.setExtraNames([name]) self.units = units self.setLevel(7) # self.setOutputFormat(["%20.12f"]); self.chSetGrating = CAClient(strSetPV) self.chGetGrating = CAClient(strGetPV) self.chStatusGrating = CAClient(strGratingMoveStatusPV) self.strGrating = '' self.grating = 0 def atScanStart(self): if not self.chGetGrating.isConfigured(): self.chGetGrating.configure() if not self.chSetGrating.isConfigured(): self.chSetGrating.configure() if not self.chStatusGrating.isConfigured(): self.chStatusGrating.configure() #Scannable Implementations def getPosition(self): return self.getGrating() def asynchronousMoveTo(self, newPos): self.setGrating(newPos) def isBusy(self): #sleep(60); return self.getStatus() == 1 def getUserUnits(self): return self.units def atScanEnd(self): if self.chGetGrating.isConfigured(): self.chGetGrating.clearup() if self.chSetGrating.isConfigured(): self.chSetGrating.clearup() if self.chStatusGrating.isConfigured(): self.chStatusGrating.clearup() def getStatus(self): if self.chStatusGrating.isConfigured(): g = self.chStatusGrating.caget() else: self.chStatusGrating.configure() g = self.chStatusGrating.caget() self.chStatusGrating.clearup() return int(float(g)) def getGrating(self): if self.chGetGrating.isConfigured(): g = self.chGetGrating.caget() else: self.chGetGrating.configure() g = self.chGetGrating.caget() self.chGetGrating.clearup() ng = int(float(g)) if ng == 0: self.grating = 150 elif ng == 1: self.grating = 400 elif ng == 2: self.grating = 1200 return self.grating def setGrating(self, x): if x == 150: #set to 150 self.strGrating = " 150 lines/mm" ng = 0 elif x == 400: #set to 400 self.strGrating = " 400 lines/mm" ng = 1 elif x == 1200: # set to 1200 self.strGrating = " 1200 lines/mm" ng = 2 else: print "Wrong grating number, must be 150, 400 or 1200 lines/mm" return if self.chSetGrating.isConfigured(): self.strSetGrating = self.chSetGrating.caput(ng) else: self.chSetGrating.configure() self.strGrating = self.chSetGrating.caput(ng) self.chSetGrating.clearup() def toString(self): ss = self.getName() + " : " + str(self.getPosition()) + " lines/mm" return ss
class EPICSODQBPMClass(ScannableBase): '''PD for OD QBPM device Inputs: None Outputs: Range, C1, C2, C3, C4, X, Y self.set_range(value) - set gain 0 = highest calibration sequence: self.dark_current() save dark current at current gain (beam off) self.set_zero() calibrate zero x,y (beam on) self.setxy(xval, yval) calibrate gains to give position in mm (go to xval, yval; beam on) - NOT TESTED Additional methods: config() loads qbpm parameters''' # a=A1*(current4-A2) etc # X=GX*(a-b)/(a+b) etc # a,b,c,d=chan 4,2,1,3 def __init__(self, name, pvrootstring, help=None): self.setName(name) if help is not None: self.__doc__ += '\nHelp specific to ' + self.name + ':\n' + help #[self.A1,self.A2,self.B1,self.B2,self.C1,self.C2,self.D1,self.D2,self.GX, self.GY]=xyparamvec self.pvrootstring = pvrootstring self.setInputNames([]) self.setExtraNames(['Range', 'C1', 'C2', 'C3', 'C4', 'X', 'Y']) #self.setReportingUnits([' ','uA','uA','uA','uA','mm','mm']) self.setOutputFormat( ['%.0f', '%.9f', '%.9f', '%.9f', '%.9f', '%.3f', '%.3f']) self.setLevel(9) self.rangecli = CAClient(pvrootstring + ':RANGE_MENU') self.rangecli.configure() self.c1cli = CAClient(pvrootstring + ':PHD1:I') self.c1cli.configure() self.c2cli = CAClient(pvrootstring + ':PHD2:I') self.c2cli.configure() self.c3cli = CAClient(pvrootstring + ':PHD3:I') self.c3cli.configure() self.c4cli = CAClient(pvrootstring + ':PHD4:I') self.c4cli.configure() self.xcli = CAClient(pvrootstring + ':XPOS') self.xcli.configure() self.ycli = CAClient(pvrootstring + ':YPOS') self.ycli.configure() self.IR1cli = CAClient(pvrootstring + ':PHD1:I_R') self.IR1cli.configure() self.IR2cli = CAClient(pvrootstring + ':PHD2:I_R') self.IR2cli.configure() self.IR3cli = CAClient(pvrootstring + ':PHD3:I_R') self.IR3cli.configure() self.IR4cli = CAClient(pvrootstring + ':PHD4:I_R') self.IR4cli.configure() def getPosition(self): self.rangestring = self.rangecli.caget() self.c1string = self.c1cli.caget() self.c2string = self.c2cli.caget() self.c3string = self.c3cli.caget() self.c4string = self.c4cli.caget() self.xstring = self.xcli.caget() self.ystring = self.ycli.caget() return [ float(self.rangestring), float(self.c1string), float(self.c2string), float(self.c3string), float(self.c4string), float(self.xstring), float(self.ystring) ] # def asynchronousMoveTo(self,new_position): # self.rangecli.caput(new_position) def isBusy(self): return 0 def set_params(self, params): [A1, A2, B1, B2, C1, C2, D1, D2, GX, GY] = params self.configcli = CAClient(self.pvrootstring + ':A1_SP') self.configcli.configure() self.configcli.caput(A1) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':A2_SP') self.configcli.configure() self.configcli.caput(A2) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':B1_SP') self.configcli.configure() self.configcli.caput(B1) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':B2_SP') self.configcli.configure() self.configcli.caput(B2) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':C1_SP') self.configcli.configure() self.configcli.caput(C1) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':C2_SP') self.configcli.configure() self.configcli.caput(C2) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':D1_SP') self.configcli.configure() self.configcli.caput(D1) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':D2_SP') self.configcli.configure() self.configcli.caput(D2) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':GX_SP') self.configcli.configure() self.configcli.caput(GX) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':GY_SP') self.configcli.configure() self.configcli.caput(GY) self.configcli.clearup() def get_params(self): self.configcli = CAClient(self.pvrootstring + ':A1_SP') self.configcli.configure() A1 = float(self.configcli.caget()) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':A2_SP') self.configcli.configure() A2 = float(self.configcli.caget()) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':B1_SP') self.configcli.configure() B1 = float(self.configcli.caget()) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':B2_SP') self.configcli.configure() B2 = float(self.configcli.caget()) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':C1_SP') self.configcli.configure() C1 = float(self.configcli.caget()) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':C2_SP') self.configcli.configure() C2 = float(self.configcli.caget()) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':D1_SP') self.configcli.configure() D1 = float(self.configcli.caget()) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':D2_SP') self.configcli.configure() D2 = float(self.configcli.caget()) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':GX_SP') self.configcli.configure() GX = float(self.configcli.caget()) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':GY_SP') self.configcli.configure() GY = float(self.configcli.caget()) self.configcli.clearup() return [A1, A2, B1, B2, C1, C2, D1, D2, GX, GY] def get_rawcounts(self): self.IR1 = float(self.IR1cli.caget()) self.IR2 = float(self.IR2cli.caget()) self.IR3 = float(self.IR3cli.caget()) self.IR4 = float(self.IR4cli.caget()) return [self.IR1, self.IR2, self.IR3, self.IR4] def set_range(self, newrange): self.rangecli.caput(newrange) def factory_reset(self): params = [A1, A2, B1, B2, C1, C2, D1, D2, GX, GY] = [1, 0, 1, 0, 1, 0, 1, 0, 1, 1] self.set_params(params) def dark_current(self): #offsets not persistent - do dark current with beam off [A1, A2, B1, B2, C1, C2, D1, D2, GX, GY] = self.get_params() self.configcli = CAClient(self.pvrootstring + ':PHD4:I_R') self.configcli.configure() A2 = float(self.configcli.caget()) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':PHD2:I_R') self.configcli.configure() B2 = float(self.configcli.caget()) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':PHD1:I_R') self.configcli.configure() C2 = float(self.configcli.caget()) self.configcli.clearup() self.configcli = CAClient(self.pvrootstring + ':PHD3:I_R') self.configcli.configure() D2 = float(self.configcli.caget()) self.configcli.clearup() self.set_params([A1, A2, B1, B2, C1, C2, D1, D2, GX, GY]) print 'new dark currents (i4,i2,i1,i3):', [A2, B2, C2, D2] def set_zero(self): #do with beam on [ic, ib, id, ia] = self.get_rawcounts() [A1, A2, B1, B2, C1, C2, D1, D2, GX, GY] = self.get_params() A1B1 = A1 * B1 C1D1 = C1 * D1 #get products A1_B1 = (ib - B2) / (ia - A2) #calculate ratio X=0 C1_D1 = (id - D2) / (ic - C2) #calculate ratio Y=0 #re-calc A1, B1 etc for zero X,Y but keep ratio at current value [A1, B1, C1, D1] = [ sqrt(A1B1 * A1_B1), sqrt(A1B1 / A1_B1), sqrt(C1D1 * C1_D1), sqrt(C1D1 / C1_D1) ] self.set_params([A1, A2, B1, B2, C1, C2, D1, D2, GX, GY]) def set_xy(self, x, y): #do with beam on [ic, ib, id, ia] = self.get_rawcounts() [A1, A2, B1, B2, C1, C2, D1, D2, GX, GY] = self.get_params() [a, b, c, d] = [A1 * (ia - A2), B1 * (ib - B2), C1 * (ic - C2), D1 * (id - D2)] [GX, GY] = [x * (a + b) / (a - b), y * (c + d) / (c - d)] #print [A1,A2,B1,B2,C1,C2,D1,D2,GX,GY] self.set_params([A1, A2, B1, B2, C1, C2, D1, D2, GX, GY])
class Keithley2612(): def __init__(self, channel, function, pvBase): self.channel = channel self.strFunctionSet = ['smua.source.func', 'smub.source.func'] self.strFunctionGet = [ 'print(smua.source.func)', 'print(smub.source.func)' ] self.strVoltageSet = ['smua.source.levelv', 'smub.source.levelv'] self.strVoltageGet = [ 'print(smua.source.levelv)', 'print(smub.source.levelv)' ] self.strCurrentSet = ['smua.source.leveli', 'smub.source.leveli'] self.strCurrentGet = [ 'print(smua.measure.i())', 'print(smub.measure.i())' ] self.strVoltageSet = ['smua.source.levelv', 'smub.source.levelv'] self.strResistanceGet = [ 'print(smua.measure.r())', 'print(smub.measure.r())' ] self.strSourceSet = ['smua.source.output', 'smub.source.output'] self.strVoltRangeSet = ['smua.source.rangev', 'smub.source.rangev'] self.chIn = CAClient(pvBase + "TINP") self.chIn.configure() self.chOut = CAClient(pvBase + "AOUT") self.chOut.configure() self.setFunction(function) print('-> setting Serial port: ' + pvBase + ' for the Keithley 2621A source meter:') print "Baud = 9600, bit = 8, bitstop = 1, parity = None, Flow Control = None" print "Output Terminator \\n, input terminator \\n" strcom = pvBase[0:23] self.chOut.caput(strcom + "BAUD", "9600") sleep(0.5) self.chOut.caput(strcom + "DBIT", "8") sleep(0.5) self.chOut.caput(strcom + "SBIT", "1") sleep(0.5) self.chOut.caput(strcom + "PRTY", "None") sleep(0.5) self.chOut.caput(strcom + "FCTL", "None") sleep(0.5) self.chOut.caput(strcom + "OEOS", "\n") sleep(0.5) self.chOut.caput(strcom + "IEOS", "\n") print "-> serial port configured" def send(self, strCom): self.chOut.caput(strCom) sleep(0.2) def turnOn(self): strOut = self.strSourceSet[self.channel] + '=1' self.chOut.caput(strOut) sleep(0.2) def turnOff(self): strOut = self.strSourceSet[self.channel] + '=0' self.chOut.caput(strOut) def getFunction(self): return int(self._getFloat(self.strFunctionGet[self.channel]), 'Function') def getVoltage(self): return self._getFloat(self.strVoltageGet[self.channel], 'Voltage') def getResistance(self): return self._getFloat(self.strResistanceGet[self.channel], 'Resistance') def getCurrent(self): return self._getFloat(self.strCurrentGet[self.channel], 'Current') def _getFloat(self, request, desc): self.chOut.caput(request) sleep(0.2) ret = self.chIn.caget() try: return float(ret) except: raise ValueError('Unable to parse %s float from "%s"' % (desc, ret)) def setVoltage(self, v): strOut = self.strVoltageSet[self.channel] + '=' + str(round(v, 5)) #print "Out String: " + strOut self.chOut.caput(strOut) sleep(0.2) return def setCurrent(self, i): strOut = self.strCurrentSet[self.channel] + '=' + str(round(i, 5)) #print "Out String: " + strOut; self.chOut.caput(strOut) return def setFunction(self, i): # i = 0, current source, i=1, voltage source strOut = self.strFunctionSet[self.channel] + '=' + str(i) self.chOut.caput(strOut) return
class ScalerChannelEpicsPVClass(ScannableBase): def __init__(self, name, strChTP, strChCNT, strChSn): self.setName(name); self.setInputNames([]); self.setExtraNames([name]); # self.Units=[strUnit]; #self.setLevel(5); self.setOutputFormat(["%20.12f"]); self.chTP=CAClient(strChTP); self.chCNT=CAClient(strChCNT); self.chSn=CAClient(strChSn); self.tp = -1; # self.setTimePreset(time) def atStart(self): if not self.chTP.isConfigured(): self.chTP.configure() if not self.chCNT.isConfigured(): self.chCNT.configure() if not self.chSn.isConfigured(): self.chSn.configure() #Scannable Implementations def getPosition(self): return self.getCount(); def asynchronousMoveTo(self,newPos): self.setCollectionTime(newPos); self.collectData(); def isBusy(self): return self.getStatus() def atEnd(self): if self.chTP.isConfigured(): self.chTP.clearup() if self.chCNT.isConfigured(): self.chCNT.clearup() if self.chSn.isConfigured(): self.chSn.clearup() #Scaler 8512 implementations def getTimePreset(self): if self.chTP.isConfigured(): newtp = self.chTP.caget() else: self.chTP.configure() newtp = float(self.chTP.caget()) self.chTP.clearup() self.tp = newtp return self.tp #Set the Time Preset and start counting automatically def setTimePreset(self, newTime): self.tp = newTime newtp = newTime; if self.chTP.isConfigured(): tp = self.chTP.caput(newtp) else: self.chTP.configure() tp = self.chTP.caput(newtp) self.chTP.clearup() # Thread.sleep(1000) def getCount(self): if self.chSn.isConfigured(): output = self.chSn.caget() else: self.chSn.configure() output = self.chSn.caget() self.chSn.clearup() return float(output) #Detector implementations #Tells the detector to begin to collect a set of data, then returns immediately. #public void collectData() throws DeviceException; #Set the Time Preset and start counting automatically def collectData(self): #self.setTimePreset(self.tp) if self.chCNT.isConfigured(): tp = self.chCNT.caput(1) else: self.chCNT.configure() tp = self.chCNT.caput(1) self.chCNT.clearup() # Thread.sleep(1000) #Tells the detector how long to collect for during a call of the collectData() method. #public void setCollectionTime(double time) throws DeviceException; def setCollectionTime(self, newTime): self.setTimePreset(newTime) #Returns the latest data collected. #public Object readout() throws DeviceException; def getCollectionTime(self): nc=self.getTimePreset() return nc #Returns the current collecting state of the device. # return ACTIVE (1) if the detector has not finished the requested operation(s), # IDLE(0) if in an completely idle state and # STANDBY(2) if temporarily suspended. #public int getStatus() throws DeviceException; def getStatus(self): if self.chCNT.isConfigured(): self.stauts = self.chCNT.caget() else: self.chCNT.configure() self.stauts = self.chCNT.caget() self.chCNT.clearup() if self.stauts == '0': #still counting, Busy return 0 else: return 1
class CameraCount(DetectorBase): ''' A scannable detector for diagnose camera providing Starndard EPICS area detector interface. By default it returns the total count of the camera when scanning. It also designed to record a time series of counts over specified period into a data file. Usage: to create an diagnose camera scannable object: >>>sd3cam=CameraCount("sd3cam","SD3","BL09J-MO-SD-03","counts", "%d") to collect time series for 30 seconds at exposure time of 0.1 second >>>sd3cam.collectFor(30, 0.1) to scan a motor with exposure time of 0.1 second >>>scan motor 1 100 1 sd3cam 0.1 ''' def __init__(self, name, epicsdevicename, pvroot, unitstring, formatstring): ''' Constructor ''' self.setName(name) self.setInputNames([name]) self.Units = [unitstring] self.setOutputFormat([formatstring]) self.epicsdevicename = epicsdevicename self.pvroot = pvroot self.exposure = CAClient(pvroot + ":CAM:AcquireTime") self.imagemode = CAClient(pvroot + ":CAM:ImageMode") self.acquire = CAClient(pvroot + ":CAM:Acquire") self.roiport = CAClient(pvroot + ":ROI:NDArrayPort") self.roienablecallback = CAClient(pvroot + ":ROI:EnableCallbacks") self.roienablex = CAClient(pvroot + ":ROI:EnableX") self.roienabley = CAClient(pvroot + ":ROI:EnableY") self.roiminx = CAClient(pvroot + ":ROI:MinX") self.roiminy = CAClient(pvroot + ":ROI:MinY") self.roisizex = CAClient(pvroot + ":ROI:SizeX") self.roisizey = CAClient(pvroot + ":ROI:SizeY") self.statenablecallback = CAClient(pvroot + ":STAT:EnableCallbacks") self.statport = CAClient(pvroot + ":STAT:NDArrayPort") self.statcompute = CAClient(pvroot + ":STAT:ComputeStatistics") self.stattimestamp = CAClient(pvroot + ":STAT:TimeStamp_RBV") self.stattotal = CAClient(pvroot + ":STAT:Total_RBV") self.timestamp = [] self.counts = [] #override scannable APIs def atScanStart(self): if not self.exposure.isConfigured(): self.exposure.configure() self.exposurevalue = float(self.exposure.caget()) if not self.acquire.isConfigured(): self.acquire.configure() self.acquirestate = int(self.acquire.caget()) if not self.stattotal.isConfigured(): self.stattotal.configure() self.acquire.caput(0) #set camera if not self.imagemode.isConfigured(): self.imagemode.configure() self.imagemodedata = int(self.imagemode.caget()) self.imagemode.caput(0) #Single mode def atScanEnd(self): self.exposure.caput(self.exposurevalue) self.imagemode.caput(self.imagemodedata) self.acquire.caput(self.acquirestate) if self.exposure.isConfigured(): self.exposure.clearup() if self.acquire.isConfigured(): self.acquire.clearup() if self.stattotal.isConfigured(): self.stattotal.clearup() if self.imagemode.isConfigured(): self.imagemode.clearup() def stop(self): if not self.acquire.isConfigured(): self.acquire.configure() self.acquire.caput(0) self.acquire.clearup() else: self.acquire.caput(0) #override Detector APIs def prepareForCollection(self): #set ROI if not self.roiport.isConfigured(): self.roiport.configure() self.roiport.caput(self.epicsdevicename + ".CAM") if not self.roienablecallback.isConfigured(): self.roienablecallback.configure() self.roienablecallback.caput(1) #set STAT if not self.statport.isConfigured(): self.statport.configure() self.statport.caput(self.epicsdevicename + ".ROI") if not self.statenablecallback.isConfigured(): self.statenablecallback.configure() self.statenablecallback.caput(1) if not self.statcompute.isConfigured(): self.statcompute.configure() self.statcomputedata = int(self.statcompute.caget()) self.statcompute.caput(1) def endCollection(self): #set ROI if self.roiport.isConfigured(): self.roiport.clearup() if self.roienablecallback.isConfigured(): self.roienablecallback.clearup() #set STAT if self.statport.isConfigured(): self.statport.clearup() if self.statenablecallback.isConfigured(): self.statenablecallback.clearup() self.statcompute.caput(self.statcomputedat) if self.statcompute.isConfigured(): self.statcompute.clearup() def setCollectionTime(self, t): if not self.exposure.isConfigured(): self.exposure.configure() self.exposure.caput(t) self.exposure.clearup() else: self.exposure.caput(t) def getCollectionTime(self): value = -1.0 if not self.exposure.isConfigured(): self.exposure.configure() value = float(self.exposure.caget()) self.exposure.clearup() else: value = float(self.exposure.caget()) return value def collectData(self): if not self.acquire.isConfigured(): self.acquire.configure() self.acquire.caput(1) self.acquire.clearup() else: self.acquire.caput(1) def readout(self): ''' return current total count''' output = 0.0 if not self.stattotal.isConfigured(): self.stattotal.configure() output = float(self.stattotal.caget()) self.stattotal.clearup() else: output = float(self.stattotal.caget()) return float(output) def getStatus(self): status = -1 if not self.acquire.isConfigured(): self.acquire.configure() status = int(self.acquire.caget()) self.acquire.clearup() else: status = self.acquire.caput(0) if status == 1: return Detector.BUSY return Detector.IDLE # Area Detector ROI interface def setROI(self, minx, miny, sizex, sizey): if not self.roiminx.isConfigured(): self.roiminx.configure() self.roiminx.caput(minx) self.roiminx.clearup() else: self.roiminx.caput(minx) if not self.roiminy.isConfigured(): self.roiminy.configure() self.roiminy.caput(miny) self.roiminy.clearup() else: self.roiminy.caput(miny) if not self.roisizex.isConfigured(): self.roisizex.configure() self.roisizex.caput(sizex) self.roisizex.clearup() else: self.roisizex.caput(sizex) if not self.roisizey.isConfigured(): self.roisizey.configure() self.roisizey.caput(sizey) self.roisizey.clearup() else: self.roisizey.caput(sizey) def enableROI(self): if not self.roienablex.isConfigured(): self.roienablex.configure() self.roienablex.caput(1) self.roienablex.clearup() else: self.roienablex.caput(1) if not self.roienabley.isConfigured(): self.roienabley.configure() self.roienabley.caput(1) self.roienabley.clearup() else: self.roienabley.caput(1) def disableROI(self): if not self.roienablex.isConfigured(): self.roienablex.configure() self.roienablex.caput(0) self.roienablex.clearup() else: self.roienablex.caput(0) if not self.roienabley.isConfigured(): self.roienabley.configure() self.roienabley.caput(0) self.roienabley.clearup() else: self.roienabley.caput(0) #time series def collectFor(self, t, exposure=1.0): #get camera ready self.stop() if not self.imagemode.isConfigured(): self.imagemode.configure() self.imagemode.caput(2) #Continuous mode self.imagemode.clearup() else: self.imagemode.caput(2) #Continuous mode self.prepareForCollection() self.setCollectionTime(exposure) self.timedata = EpicsMonitor('time') if not self.stattimestamp.isConfigured(): self.stattimestamp.configure() self.timemonitor = self.stattimestamp.camonitor(self.timedata) self.countdata = EpicsMonitor('count') if not self.stattotal.isConfigured(): self.stattotal.configure() self.countmonitor = self.stattotal.camonitor(self.countdata) timer = Timer(t, self.writeData) self.collectData() timer.start() def writeData(self): self.stop() self.stattimestamp.removeMonitor(self.timemonitor) self.stattotal.removeMonitor(self.countmonitor) filename = nextDataFile() print "saving data to %s, please wait..." % filename #length=min(self.timedata.getData().size, self.countdata.getData().size) timedataset = self.timedata.getData() countdataset = self.countdata.getData() dnp.plot.plot(timedataset, countdataset, "Plot") outfile = open(filename, "w") for time, count in zip(timedataset.getData().tolist(), countdataset.getData().tolist()): outfile.write("%f\t%d\n" % (time, count)) outfile.close() #dnp.io.save(filename, [timedataset, countdataset], format="text") # write 2 text fileseach with one dataset print "collection completed."
class AlicatPressureController(ScannableMotionBase): ''' construct a scannable for pressure control. It also provides access to other properties. ''' def __init__(self,name, rootPV, tolerance=0.01, formatstring="%.3f"): ''' Constructor ''' self.setName(name) self.setInputNames([name]) self.setOutputFormat([formatstring]) self.setLevel(3) self.readmodecli=CAClient(rootPV+READ_MODE) self.setmodecli=CAClient(rootPV+SET_MODE) self.readpressurecli=CAClient(rootPV+READ_PRESSURE) self.settargetcli=CAClient(rootPV+SET_TARGET) self.readtargetcli=CAClient(rootPV+READ_TARGET) self.setproportionalgaincli=CAClient(rootPV+SET_PROPORTIONAL_GAIN) self.readproportionalgaincli=CAClient(rootPV+READ_PROPORTIONAL_GAIN) self.setderivativegaincli=CAClient(rootPV+SET_DERIVATIVE_GAIN) self.readderivativegaincli=CAClient(rootPV+READ_DERIVATIVE_GAIN) self.mytolerance=tolerance self.isConfigured=False def configure(self): if not self.isConfigured: if not self.readmodecli.isConfigured(): self.readmodecli.configure() if not self.setmodecli.isConfigured(): self.setmodecli.configure() if not self.settargetcli.isConfigured(): self.settargetcli.configure() if not self.readtargetcli.isConfigured(): self.readtargetcli.configure() if not self.readpressurecli.isConfigured(): self.readpressurecli.configure() self.isConfigured=True def deconfigure(self): if self.isConfigured: if self.readmodecli.isConfigured(): self.readmodecli.clearup() if self.setmodecli.isConfigured(): self.setmodecli.clearup() if self.settargetcli.isConfigured(): self.settargetcli.clearup() if self.readtargetcli.isConfigured(): self.readtargetcli.clearup() if self.readpressurecli.isConfigured(): self.readpressurecli.clearup() self.isConfigured=False def getMode(self): try: if not self.readmodecli.isConfigured(): self.readmodecli.configure() output=int(self.readmodecli.caget()) self.readmodecli.clearup() else: output=int(self.readmodecli.caget()) return modes[output] except: print "Error returning current mode" return 0 def setMode(self, mode): try: if not self.setmodecli.isConfigured(): self.setmodecli.configure() self.setmodecli.caput(mode) self.setmodecli.clearup() else: self.setmodecli.caput(mode) except: print "error set to mode" def setTarget(self, target): try: if not self.settargetcli.isConfigured(): self.settargetcli.configure() self.settargetcli.caput(target) self.settargetcli.clearup() else: self.settargetcli.caput(target) except: print "error set to target flow value" def getTarget(self): try: if not self.settargetcli.isConfigured(): self.settargetcli.configure() output=float(self.settargetcli.caget()) self.settargetcli.clearup() else: output=float(self.settargetcli.caget()) return output except: print "Error returning target value" return 0 def getPressure(self): try: if not self.readpressurecli.isConfigured(): self.readpressurecli.configure() output=float(self.readpressurecli.caget()) self.readpressurecli.clearup() else: output=float(self.readpressurecli.caget()) return output except: print "Error returning pressure" return 0 def getProportionalGain(self): try: if not self.readproportionalgaincli.isConfigured(): self.readproportionalgaincli.configure() output=float(self.readproportionalgaincli.caget()) self.readproportionalgaincli.clearup() else: output=float(self.readproportionalgaincli.caget()) return output except: print "Error returning Proportional Gain" return 0 def setProportionalGain(self, gain): try: if not self.setproportionalgaincli.isConfigured(): self.setproportionalgaincli.configure() self.setproportionalgaincli.caput(gain) self.setproportionalgaincli.clearup() else: self.setproportionalgaincli.caput(gain) except: print "error set to proportional gain" def getDerivativeGain(self): try: if not self.readderivativegaincli.isConfigured(): self.readderivativegaincli.configure() output=float(self.readderivativegaincli.caget()) self.readderivativegaincli.clearup() else: output=float(self.readderivativegaincli.caget()) return output except: print "Error returning Derivative Gain" return 0 def setDerivativeGain(self, gain): try: if not self.setderivativegaincli.isConfigured(): self.setderivativegaincli.configure() self.setderivativegaincli.caput(gain) self.setderivativegaincli.clearup() else: self.setderivativegaincli.caput(gain) except: print "error set to derivative gain" def getTolerance(self): return self.mytolerance def setTolerance(self, value): self.mytolerance=value #### methods for scannable def getPosition(self): return self.getPressure() def asynchronousMoveTo(self, posi): self.setTarget(float(posi)) def moveTo(self, posi, sleepdelta=0.5): self.asynchronousMoveTo(posi) while self.isBusy(): sleep(sleepdelta) def isBusy(self): return (abs(float(self.getPosition())-float(self.getTarget()))>float(self.getTolerance())) def atScanStart(self): pass def atPointStart(self): pass def stop(self): pass def atPointEnd(self): pass def atScanEnd(self): pass
class KepkoMagnet(ScannableMotionBase): def __init__(self, name, pv): self.setName(name) self.setInputNames(['Oersted']) self.setOutputFormat(['%5.0f']) self.setLevel(6) self.ch = CAClient(pv) self.ch.configure() self.coeff = [0.0, 1.0] self.invCoeff = [0.0, 1.0] self.useInvCoeff = False self.fieldTolerance = 10 self.lastField = -999 def setConvCoeff(self, coeff): self.coeff = coeff def setInvConvCoeff(self, invCoeff): self.invCoeff = invCoeff def calcCurrent(self, oersted): ampere = float(0.0) k = 0.0 for i in self.invCoeff: ampere += i * pow(oersted, k) k += 1 return ampere def getCurrent(self): return float(self.ch.caget()) * 0.4 def calcField(self, ampere): oersted = float(0.0) k = 0.0 for i in self.coeff: oersted += i * pow(ampere, k) k += 1 if self.useInvCoeff: return oersted diff = abs(oersted - self.lastField) if diff > self.fieldTolerance: print "The last oersted value written (%r) differs from the oersted value (%r) calculated from the current (%r) by %r" % ( self.lastField, oersted, ampere, diff) print "This is more than the warning tolerance (%r)" % self.fieldTolerance return self.lastField #scannable implementation def atScanStart(self): return def atScanEnd(self): return def getPosition(self): return self.calcField(self.getCurrent()) def asynchronousMoveTo(self, newfield): self.lastField = newfield newcurrent = self.calcCurrent(newfield) self.ch.caput(newcurrent / 0.4) sleep(0.5) return None def isBusy(self): return False # Initialise the scannable #exec("magnet = None") #print"-> connect the Kepko to Analogue output 2 in patch panel U2 (branchline)" #print"-> magnet calibration for pole gap = 35.4 mm and bobbin turns = 784" #magnet = KepkoMagnet("magnet", "BL06J-EA-USER-01:AO2") # #magnet.setConvCoeff([0, 253.16, 7.22765, 9.37523, -1.81716, -3.49587, 0.155178, 0.267718, -0.00433883, -0.00662351]) #magnet.setInvConvCoeff([0, 0.00369277, -7.65554e-07, 6.49905e-09,5.76312e-12, -6.23302e-14, -1.77119e-17, 2.0429e-19,1.8207e-23, -1.70236e-25])
class PositionCompareMotorWithLimitsClass(ScannableMotionBase): '''Create a scannable for a single motor''' def __init__(self, name, pvinstring, pvoutstring, pvstopstring, tolerance, unitstring, formatstring, upperlimit, lowerlimit): self.setName(name); self.setInputNames([name]) self.Units=[unitstring] self.setOutputFormat([formatstring]) self.setLevel(5) self.incli=CAClient(pvinstring) self.outcli=CAClient(pvoutstring) self.stopcli=CAClient(pvstopstring) self._tolerance=tolerance self.setUpperGdaLimits(upperlimit) self.setLowerGdaLimits(lowerlimit) def setLowerGdaLimits(self, lowerlimit): ScannableMotionBase.setLowerGdaLimits(lowerlimit) def getLowerGdaLimits(self): return ScannableMotionBase.getLowerGdaLimits() def setUpperGdaLimits(self, upperlimit): ScannableMotionBase.setUpperGdaLimits(upperlimit) def getUpperGdaLimits(self): return ScannableMotionBase.getUpperGdaLimits() def setTolerance(self, tolerance): self._tolerance=tolerance def getTolerance(self): return self._tolerance def atScanStart(self): if not self.incli.isConfigured(): self.incli.configure() if not self.outcli.isConfigured(): self.outcli.configure() if not self.stopcli.isConfigured(): self.stopcli.configure() def rawGetPosition(self): try: if not self.outcli.isConfigured(): self.outcli.configure() output=float(self.outcli.caget()) self.outcli.clearup() else: output=float(self.outcli.caget()) return output except: print "Error returning current position" return 0 def getTargetPosition(self): try: if not self.incli.isConfigured(): self.incli.configure() target=float(self.incli.caget()) self.incli.clearup() else: target=float(self.incli.caget()) return target except: print "Error returning target position" return 0 def rawAsynchronousMoveTo(self,new_position): try: if not self.incli.isConfigured(): self.incli.configure() self.incli.caput(new_position) self.incli.clearup() else: self.incli.caput(new_position) except: print "error moving to position" def rawIsBusy(self): return ( not abs(self.rawGetPosition() - self.getTargetPosition()) < self._tolerance) def atScanEnd(self): if self.incli.isConfigured(): self.incli.clearup() if self.outcli.isConfigured(): self.outcli.clearup() if self.stopcli.isConfigured(): self.stopcli.clearup() def stop(self): if not self.stopcli.isConfigured(): self.stopcli.configure() self.stopcli.caput(1) self.stopcli.clearup() else: self.stopcli.caput(1) def toString(self): return self.name + " : " + str(self.getPosition())
class PositionCompareMotorWithLimitsClass(ScannableMotionBase): '''Create a scannable for a single motor''' def __init__(self, name, pvinstring, pvoutstring, pvstopstring, tolerance, unitstring, formatstring, upperlimit, lowerlimit): self.setName(name); self.setInputNames([name]) self.Units=[unitstring] self.setOutputFormat([formatstring]) self.setLevel(5) self.incli=CAClient(pvinstring) self.outcli=CAClient(pvoutstring) self.stopcli=CAClient(pvstopstring) self._tolerance=tolerance self.setUpperGdaLimits(upperlimit) self.setLowerGdaLimits(lowerlimit) def setLowerGdaLimits(self, lowerlimit): ScannableMotionBase.setLowerGdaLimits(lowerlimit) def getLowerGdaLimits(self): return ScannableMotionBase.getLowerGdaLimits() def setUpperGdaLimits(self, upperlimit): ScannableMotionBase.setUpperGdaLimits(upperlimit) def getUpperGdaLimits(self): return ScannableMotionBase.getUpperGdaLimits() def setTolerance(self, tolerance): self._tolerance=tolerance def getTolerance(self): return self._tolerance def atScanStart(self): if not self.incli.isConfigured(): self.incli.configure() if not self.outcli.isConfigured(): self.outcli.configure() if not self.stopcli.isConfigured(): self.stopcli.configure() def rawGetPosition(self): try: if not self.outcli.isConfigured(): self.outcli.configure() output=float(self.outcli.caget()) self.outcli.clearup() else: output=float(self.outcli.caget()) return output except: print "Error returning current position" return 0 def getTargetPosition(self): try: if not self.incli.isConfigured(): self.incli.configure() target=float(self.incli.caget()) self.incli.clearup() else: target=float(self.incli.caget()) return target except: print "Error returning target position" return 0 def rawAsynchronousMoveTo(self,new_position): try: if not self.incli.isConfigured(): self.incli.configure() self.incli.caput(new_position) self.incli.clearup() else: self.incli.caput(new_position) except: print "error moving to position" def isBusy(self): return ( not abs(self.rawGetPosition() - self.getTargetPosition()) < self._tolerance) def atScanEnd(self): if self.incli.isConfigured(): self.incli.clearup() if self.outcli.isConfigured(): self.outcli.clearup() if self.stopcli.isConfigured(): self.stopcli.clearup() def stop(self): if not self.stopcli.isConfigured(): self.stopcli.configure() self.stopcli.caput(1) self.stopcli.clearup() else: self.stopcli.caput(1) def toString(self): return self.name + " : " + str(self.getPosition())
class AlicatMassFlowController(ScannableMotionBase): ''' scannable for set and get mass flow in a scannable way. It also provides method to query other mass flow properties. ''' def __init__(self,name, rootPV, tolerance=0.01, formatstring="%.3f"): ''' Constructor ''' self.setName(name) self.setInputNames([name]) self.setOutputFormat([formatstring]) self.setLevel(5) self.currentflowcli=CAClient(rootPV+READ_MASS_FLOW) self.setflowtargetcli=CAClient(rootPV+SET_MASS_FLOW_TARGET) self.readflowtargetcli=CAClient(rootPV+READ_MASS_FLOW_TARGET) self.currentgastypecli=CAClient(rootPV+READ_GAS_TYPE) self.setfgastype1cli=CAClient(rootPV+SELECT_GAS_TYPE_1) self.setfgastype2cli=CAClient(rootPV+SELECT_GAS_TYPE_2) self.setgastypenumbercli=CAClient(rootPV+SET_GAS_TYPE_BY_NUMBER) self.pressurecli=CAClient(rootPV+READ_PRESSURE_IN_BAR) self.temperaturecli=CAClient(rootPV+READ_TEMPERATURE) self.volumetricflowcli=CAClient(rootPV+READ_VOLUMETRIC_FLOW) self.setproportionalgaincli=CAClient(rootPV+SET_PROPORTIONAL_GAIN) self.readproportionalgaincli=CAClient(rootPV+READ_PROPORTIONAL_GAIN) self.setderivativegaincli=CAClient(rootPV+SET_DERIVATIVE_GAIN) self.readderivativegaincli=CAClient(rootPV+READ_DERIVATIVE_GAIN) self.mytolerance=tolerance def getTolerance(self): return self.mytolerance def setTolerance(self, value): self.mytolerance=value def getCurrentFlow(self): try: if not self.currentflowcli.isConfigured(): self.currentflowcli.configure() output=float(self.currentflowcli.caget()) self.currentflowcli.clearup() else: output=float(self.currentflowcli.caget()) return output except: print "Error returning current flow value" return 0 def setTarget(self, target): try: if not self.setflowtargetcli.isConfigured(): self.setflowtargetcli.configure() self.setflowtargetcli.caput(target) self.setflowtargetcli.clearup() else: self.setflowtargetcli.caput(target) except: print "error set to target flow value" def getTarget(self): try: if not self.readflowtargetcli.isConfigured(): self.readflowtargetcli.configure() output=float(self.currentflowcli.caget()) self.readflowtargetcli.clearup() else: output=float(self.readflowtargetcli.caget()) return output except: print "Error returning flow target value" return 0 def getGasType(self): #self.currentgastypecli does not work in EPICS try: if not self.setgastypenumbercli.isConfigured(): self.setgastypenumbercli.configure() output=int(self.setgastypenumbercli.caget()) self.setgastypenumbercli.clearup() else: output=int(self.setgastypenumbercli.caget()) return gasTypes[output] except: print "Error returning current gas type" return 0 def setGasType(self,name): key=gasTypes.keys()[(gasTypes.values()).index(name)] if int(key)>=0 or int(key) <16: try: if not self.setfgastype1cli.isConfigured(): self.setfgastype1cli.configure() self.setfgastype1cli.caput(name) self.setfgastype1cli.clearup() else: self.setfgastype1cli.caput(name) except: print "error set to gas type 1" else: try: if not self.setfgastype2cli.isConfigured(): self.setfgastype2cli.configure() self.setfgastype2cli.caput(name) self.setfgastype2cli.clearup() else: self.setfgastype2cli.caput(name) except: print "error set to gas type 2" def getPressure(self): try: if not self.pressurecli.isConfigured(): self.pressurecli.configure() output=float(self.pressurecli.caget()) self.pressurecli.clearup() else: output=float(self.pressurecli.caget()) return output except: print "Error returning pressure" return 0 def getTemperature(self): try: if not self.temperaturecli.isConfigured(): self.temperaturecli.configure() output=float(self.temperaturecli.caget()) self.temperaturecli.clearup() else: output=float(self.temperaturecli.caget()) return output except: print "Error returning temperature" return 0 def getVolumetricFlow(self): try: if not self.volumetricflowcli.isConfigured(): self.volumetricflowcli.configure() output=float(self.volumetricflowcli.caget()) self.volumetricflowcli.clearup() else: output=float(self.volumetricflowcli.caget()) return output except: print "Error returning volumetric flow" return 0 def getProportionalGain(self): try: if not self.readproportionalgaincli.isConfigured(): self.readproportionalgaincli.configure() output=float(self.readproportionalgaincli.caget()) self.readproportionalgaincli.clearup() else: output=float(self.readproportionalgaincli.caget()) return output except: print "Error returning Proportional Gain" return 0 def setProportionalGain(self, gain): try: if not self.setproportionalgaincli.isConfigured(): self.setproportionalgaincli.configure() self.setproportionalgaincli.caput(gain) self.setproportionalgaincli.clearup() else: self.setproportionalgaincli.caput(gain) except: print "error set to proportional gain" def getDerivativeGain(self): try: if not self.readderivativegaincli.isConfigured(): self.readderivativegaincli.configure() output=float(self.readderivativegaincli.caget()) self.readderivativegaincli.clearup() else: output=float(self.readderivativegaincli.caget()) return output except: print "Error returning Derivative Gain" return 0 def setDerivativeGain(self, gain): try: if not self.setderivativegaincli.isConfigured(): self.setderivativegaincli.configure() self.setderivativegaincli.caput(gain) self.setderivativegaincli.clearup() else: self.setderivativegaincli.caput(gain) except: print "error set to derivative gain" #### methods for scannable def getPosition(self): return self.getCurrentFlow() def asynchronousMoveTo(self, posi): self.setTarget(float(posi)) def isBusy(self): return (abs(self.getPosition()-self.getTarget())>self.getTolerance()) def atScanStart(self): pass def atPointStart(self): pass def stop(self): pass def atPointEnd(self): pass def atScanEnd(self): pass
class PilatusOverEpics(Pilatus): def __init__(self, name): Pilatus.__init__(self, name) self.detectorInfo = 'Pilatus Over Epics' self.chAcquire = None self.chAabort = None self.chFilePath = None self.chFileName = None self.chFileFormat = None self.chFileNumber = None self.chExposureTime = None self.chExposurePeriod = None self.chNumImages = None self.chGain = None self.chThresholdEnergy = None def setup(self, rootPV): self.ClientRoot = rootPV self.chAcquire = CAClient(self.ClientRoot + ':Acquire') self.chAcquire.configure() self.chAabort = CAClient(self.ClientRoot + ':Abort') self.chAabort.configure() self.chFilePath = CAClient(self.ClientRoot + ':FilePath') self.chFilePath.configure() self.chFileName = CAClient(self.ClientRoot + ':Filename') self.chFileName.configure() self.chFileNumber = CAClient(self.ClientRoot + ':FileNumber') self.chFileNumber.configure() self.chFileFormat = CAClient(self.ClientRoot + ':FileFormat') self.chFileFormat.configure() self.chNumImages = CAClient(self.ClientRoot + ':NImages') self.chNumImages.configure() self.chExposureTime = CAClient(self.ClientRoot + ':ExposureTime') self.chExposureTime.configure() self.chExposurePeriod = CAClient(self.ClientRoot + ':ExposurePeriod') self.chExposurePeriod.configure() self.chThresholdEnergy = CAClient(self.ClientRoot + ':ThresholdEnergy') self.chThresholdEnergy.configure() self.chGain = CAClient(self.ClientRoot + ':Gain') self.chGain.configure() self.chNumImages.caput(1) self.numImages = 1 self.fileFormat = self.chFileFormat.caget() def rebootIOC(self, iocRootPV): #Use the EDM screen reboot button: for example: "caput BL07I-EA-IOC-03:SYSRESET 1" cmd = "caput " + iocRootPV + ":SYSRESET 1" print cmd os.system(cmd) sleep(10) def setNumOfImages(self, number): self.numImages = number self.chNumImages.caput(number) def setFilePath(self, newFilePath): """Set file path""" self.filePath = newFilePath self.chFilePath.caput(self.filePath) def getFilePath(self): self.filePath = self.chFilePath.caget() return self.filePath def setFilePrefix(self, filePrefix): self.filePrefix = filePrefix self.chFileName.caput(self.filePrefix) self.fileNumber = self.getFileNumber() def getFilePrefix(self): self.filePrefix = self.chFileName.caget() return self.filePrefix def getFileNumber(self): self.fileNumber = int(float(self.chFileNumber.caget())) - 1 return self.fileNumber # Only to deal with the epics bug, no need if the bug fixed # def getFullFileName(self): # """Returns file path of the LAST CREATED image""" # self.fileNumber=self.getFileNumber(); # return self.filePath + self.filePrefix + "%04.0f" % (self.fileNumber) + self.fileFormat[-4:] # Palitus Detector Interface Implementation def getCollectionTime(self): self.exposureTime = float(self.chExposureTime.caget()) return self.exposureTime def setCollectionTime(self, newExpos): if self.exposureTime != newExpos: #send command to change exposure time if required self.exposureTime = newExpos self.chExposureTime.caput(self.exposureTime) return self.exposureTime def collectData(self): self.chAcquire.caput(1) return def setThreshold(self, newGain, newThresholdEnergy): self.chGain.caput(PilatusInfo.GAIN_THRESHOLD.index(newGain)) self.chThresholdEnergy.caput(newThresholdEnergy) return def getThreshold(self): self.gain = int(float(self.chGain.caget())) self.thresholdEnergy = float(self.chThresholdEnergy.caget()) print 'Gain: ' + PilatusInfo.EPICS_GAIN_THRESHOLD[ self.gain] + ', Threshold Energy: ' + str(self.thresholdEnergy) return [self.gain, self.thresholdEnergy] def setExposurePeriod(self, newExpp): self.exposurePeriod = newExpp self.chExposurePeriod.caput(newExpp) return def getExposurePeriod(self): self.exposurePeriod = float(self.chExposurePeriod.caget()) return self.exposurePeriod def getStatus(self): isbusy = int(float(self.chAcquire.caget())) isbusy = int(float(self.chAcquire.caget())) isbusy = int(float(self.chAcquire.caget())) if isbusy == 0: self.status = PilatusInfo.DETECTOR_STATUS_IDLE else: self.status = PilatusInfo.DETECTOR_STATUS_BUSY return self.status
class GasRigClass(ScannableMotionBase): '''Create a scannable for a gas injection rig''' def __init__(self, name, rootPV): self.setName(name); self.setInputNames([name]) self.setLevel(5) self.setsequencecli=CAClient(rootPV+SEQUENCE_CONTROL) self.statecli=CAClient(rootPV+SEQUENCE_STATUS) self.systemincli=CAClient(SystemTargetPressure) self.sampleincli=CAClient(SampleTargetPressure) def vacSample(self, samplePressure=dvpc): print "Vacuum the sample ..." samplePressure.setMode(0) self.on() increment=0.005 target=float(samplePressure.getPosition())-increment try: if not self.sampleincli.isConfigured(): self.sampleincli.configure() while float(samplePressure.getPosition()) > target: # final sample pressure in bar # interruptable() self.sampleincli.caput(target) target = target-increment # increments in bar sleep(5.0) # wait time in seconds if target<=0.0: break if self.sampleincli.isConfigured(): self.sampleincli.clearup() except: print "error moving to position" samplePressure.moveTo(0.0) print "sample is under vacuum now." def vacSystem(self, systemPressure=bpr): print "Vacuum the system ..." systemPressure.setMode(0) self.on() increment=0.005 target=float(systemPressure.getPosition())-increment try: if not self.systemincli.isConfigured(): self.systemincli.configure() while target > 0: # interruptable() self.systemincli.caput(target) target = target-increment # increments in bar sleep(5.0) # wait time in seconds if self.systemincli.isConfigured(): self.systemincli.clearup() except: print "error moving to position" systemPressure.moveTo(0.0) print "system is under vacuum now." def gasin(self, mfc=mfc1, flow=0.1, pressuretarget=1.0, systemPressure=bpr): '''select gas flow control and set system pressure''' print "inject gas %s into the system." % (mfc.getGasType()) mfc.asynchronousMoveTo(flow) sleep(1) systemPressure.moveTo(pressuretarget) sleep(1) mfc.asynchronousMoveTo(0) print "The system reaches at target pressure %f" % (pressuretarget) def complete(self,valve=ventvalve,systemPressure=bpr, samplePressure=sampleP): print "complete this sample, vent the system" self.off() valve.on() systemPressure.asynchronousMoveTo(0) samplePressure.asynchronousMoveTo(0) mfc1.asynchronousMoveTo(0) mfc2.asynchronousMoveTo(0) mfc3.asynchronousMoveTo(0) def flushSystem(self,repeat, mfc=mfc1, flow=0.5, duration=60.0, isolation=isolationvalve, vent=ventvalve, systemPressure=bpr): print "flushing the system for "+str(duration)+" seconds for "+ str(repeat)+ " times ..." isolation.off() vent.on() for i in range(repeat): mfc.asynchronousMoveTo(flow) sleep(1) systemPressure.moveTo(4) sleep(1) mfc.asynchronousMoveTo(0) sleep(duration) systemPressure.asynchronousMoveTo(0) sleep(10.0) print "flush system completed." def getState(self): try: if not self.statecli.isConfigured(): self.statecli.configure() output=int(self.statecli.caget()) self.statecli.clearup() else: output=int(self.statecli.caget()) return sequencestat[output] except: print "Error returning current state" return 0 def setSequence(self,new_position): try: if not self.setsequencecli.isConfigured(): self.setsequencecli.configure() self.setsequencecli.caput(new_position) self.setsequencecli.clearup() else: self.setsequencecli.caput(new_position) except: print "error setting sequence" def on(self): self.setSequence(0) def off(self): self.setSequence(1) def reset(self): self.setSequence(2) #### methods for scannable def getPosition(self): return self.getState() def asynchronousMoveTo(self, new_position): self.setSequence(float(new_position)) def isBusy(self): return False def atScanStart(self): pass def atPointStart(self): pass def stop(self): pass def atPointEnd(self): pass def atScanEnd(self): pass #gasrig=GasRigClass("gasrig", "BL11I-EA-GIR-01:") def xgasin(self, mfc=mfc1, flow=0.1, pressuretarget=1.0, systemPressure=bpr, sleepdelta=1, sleepmove=0.5): '''select gas flow control and set system pressure''' print "xgasin: inject gas %s into the system." % (mfc.getGasType()) mfc.asynchronousMoveTo(flow) #systemPressure.moveTo(pressuretarget) sleep(sleepdelta) systemPressure.moveTo(pressuretarget, sleepmove) #mfc.asynchronousMoveTo(flow) sleep(sleepdelta) mfc.asynchronousMoveTo(0) print "The system reaches at target pressure %f" % (pressuretarget)
class ID_HarmonicClass(ScannableMotionBase): """ The Class for changing the ID Harmonic The PV is an Mbbinary elements that take the value "First" (1), "Third" (3) or "Fifth" (5) """ HARMONIC_NUMBERS = [1, 3, 5] HARMONIC_STRINGS = ['First', 'Third', 'Fifth'] def __init__(self, name, pvHarmonic): self.setName(name) self.setInputNames([]) self.setExtraNames([name]) # self.Units=[strUnit]; self.setLevel(7) # self.setOutputFormat(["%20.12f"]); self.chHarmonic = CAClient(pvHarmonic) self.configChannel(self.chHarmonic) self.harmonic = None def __del__(self): self.cleanChannel(self.chHarmonic) def configChannel(self, channel): if not channel.isConfigured(): channel.configure() def cleanChannel(self, channel): if channel.isConfigured(): channel.clearup() def getHarmonic(self): self.chHarmonic.caget() self.harmonic = int(float(self.chHarmonic.caget())) return self.harmonic def setHarmonic(self, newHarmonic): if newHarmonic in ID_HarmonicClass.HARMONIC_NUMBERS: harmonic_number = newHarmonic elif newHarmonic in ID_HarmonicClass.HARMONIC_STRINGS: harmonic_number = ID_HarmonicClass.HARMONIC_NUMBERS[ ID_HarmonicClass.HARMONIC_STRINGS.index(newHarmonic)] else: print "Wrong Harmonic, use either 1, 3, 5 or 'First', 'Third', 'Fifth' to change the ID harmonic" return self.chHarmonic.caput(harmonic_number) #ScannableMotionBase Implementations def getPosition(self): return self.getHarmonic() def asynchronousMoveTo(self, newPos): self.setHarmonic(newPos) def isBusy(self): sleep(1) return False def toString(self): ss = self.getName( ) + ": Current Harmonic is " + ID_HarmonicClass.HARMONIC_STRINGS[ ID_HarmonicClass.HARMONIC_NUMBERS.index( self.getPosition() )] + ". (Total three harmonic settings are: 'First', 'Third' and 'Fifth')" return ss