示例#1
0
    def __init__(
            self, name, pgm_grat_pitch, pgm_mirr_pitch,
            pgmpvroot):  # motors, maybe also detector to set the delay time
        self.logger = LoggerFactory.getLogger(
            "ContinuousPgmGratingEnergyMoveController:%s" % name)
        self.verbose = False

        self.name = name
        self._pgm_grat_pitch = pgm_grat_pitch
        self._pgm_mirr_pitch = pgm_mirr_pitch
        self._start_event = threading.Event()
        self._pgm_grat_pitch_speed_orig = None
        self._movelog_time = datetime.now()
        self._pgm_runupdown_time = None

        self.pvs = PvManager(
            {
                'grating_density': 'NLINES',
                'cff': 'CFF',
                'grating_offset': 'GRTOFFSET',
                'plane_mirror_offset': 'MIROFFSET',
                'pgm_energy': 'ENERGY',
                'grating_pitch': 'GRT:PITCH',
                'mirror_pitch': 'MIR:PITCH',
                'energy_calibration_gradient': 'MX',
                'energy_calibration_reference': 'REFERENCE'
            }, pgmpvroot)
        if installation.isLive():
            self.pvs.configure()
示例#2
0
    def __init__(self,
                 name,
                 pvroot,
                 filepath=None,
                 stdNotArr=True,
                 reconnect=True,
                 verbose=False,
                 acquireToCagetDelay_s=0.1):
        # BL07I-DI-PHDGN-06:CAM:DATA
        self.name = name
        self.extraNames = []
        self.outputFormat = []
        self.level = 9
        self.verbose = verbose
        self.acquireToCagetDelay_s = acquireToCagetDelay_s
        stdArr = "STD" if stdNotArr else "ARR"
        pvs = {
            "DATA": stdArr + ":ArrayData",
            "START": "CAM:Acquire",
            "WIDTH": "CAM:ArraySizeX_RBV",
            "HEIGHT": "CAM:ArraySizeY_RBV",
            "COLLECTTIME": "CAM:AcquireTime"
        }
        if reconnect:
            pvs["RECONNECT"] = "CAM:RESET.PROC"

        self.pvs = PvManager(pvs, pvroot)
        self.pvs.configure()

        self.filepath = filepath
        self.ds = None

        self.disableStop = False
示例#3
0
class CryojetController():

    def __init__(self, pvroot):
        if isinstance(pvroot, str):
            from gdascripts.scannable.epics.PvManager import PvManager
            
            self.pvs = PvManager({'setpoint':   'TTEMP:SET',
                                  'sensor':     'STEMP'}, pvroot)
            self.pvs.configure()
        else:
            self.pvs = pvroot
            self.pvs.pvroot = ""

    def __repr__(self):
        return "CryojetController(pvroot=%r)" % (
            self.pvs.pvroot)

    def __str__(self):
        return "setpoint=%f, sensor=%f" % (
            self.getTempSetPoint(), self.getSensorTemp())

    def setTempSetPoint(self, setpoint):
        self.pvs['setpoint'].caput(setpoint)

    def getTempSetPoint(self):
        return float(self.pvs['setpoint'].caget())

    def getTempSensor(self):
        return float(self.pvs['sensor'].caget())
示例#4
0
 def __init__(self, name, detsystem, type, meta, unit=None, pv=None):
     super(DetectorMetaWithPv, self).__init__(name, detsystem, type, meta, unit)
     self.pv = None
     if pv is not None:
         self.pv = PvManager(pv[1:], pv[0])
         self.pv.configure()
         self.pv_conversion = 1
示例#5
0
    def __init__(self, pvroot):
        if isinstance(pvroot, str):
            from gdascripts.scannable.epics.PvManager import PvManager

            self.pvs = PvManager(
                {
                    'setpoint': 'SET:SETPOINTFIELD',
                    'setpointRbv': 'RBV:SETPOINTFIELD',
                    'sweeprate': 'SET:FIELDSWEEPRATE',
                    'sweeprateRbv': 'RBV:FIELDSWEEPRATE',
                    'demand_field': 'RBV:DEMANDFIELD'
                }, pvroot)
            self.pvs.configure()
        else:
            self.pvs = pvroot
            self.pvs.pvroot = ""
示例#6
0
	def __init__(self, name, pvroot, filepath=None, determine_data_pv_based_on_zoom = False, numtracker_extension='tmp', filename_template='fire%d_%05d.png'):
		# BL07I-DI-PHDGN-06:CAM:DATA
		self.determine_data_pv_based_on_zoom = determine_data_pv_based_on_zoom
		
		self.name = name
		self.extraNames = []
		self.outputFormat = []
		self.level = 9

		self.pvs = PvManager(['SET_SHUTTR', 'WIDTH', 'HEIGHT', 'ZOOM'], pvroot)
		self.pv_data = []
		self.pv_data.append(gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot + 'DATA'))
		self.pv_data.append(gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot + 'DATA1'))
		self.pv_data.append(gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot + 'DATA2'))
		self.pv_data.append(gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot + 'DATA3'))
		self.pv_data.append(gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot + 'DATA4'))
		self.pvs.configure()
		
		self.filepath = filepath
		self.ds = None
		self.last_image_path = None
		self.last_filename = None
		self.last_image_number = 0
		self.numtracker_extension = numtracker_extension
		self.filename_template = filename_template
示例#7
0
class DetectorMetaWithPv(DetectorMeta, object):
    def __init__(self, name, detsystem, type, meta, unit=None, pv=None):
        super(DetectorMetaWithPv, self).__init__(name, detsystem, type, meta, unit)
        self.pv = None
        if pv is not None:
            self.pv = PvManager(pv[1:], pv[0])
            self.pv.configure()
            self.pv_conversion = 1

    def rawAsynchronousMoveTo(self, p):
        if p is not None:
            p = float(p)
            if p <= 0:
                p = None
        if self.pv:
            self.pv.caput(self.pv_conversion * p)
        super(DetectorMetaWithPv, self).rawAsynchronousMoveTo(p)
示例#8
0
class IntelligentPowerSupply():
    def __init__(self, pvroot):
        if isinstance(pvroot, str):
            from gdascripts.scannable.epics.PvManager import PvManager

            self.pvs = PvManager(
                {
                    'setpoint': 'SET:SETPOINTFIELD',
                    'setpointRbv': 'RBV:SETPOINTFIELD',
                    'sweeprate': 'SET:FIELDSWEEPRATE',
                    'sweeprateRbv': 'RBV:FIELDSWEEPRATE',
                    'demand_field': 'RBV:DEMANDFIELD'
                }, pvroot)
            self.pvs.configure()
        else:
            self.pvs = pvroot
            self.pvs.pvroot = ""

    def __repr__(self):
        return "IntelligentPowerSupplyScannable(%r)" % (self.pvs.pvroot)

    def __str__(self):
        return "setpoint=%f, demand_field=%f" % (self.getFieldSetPoint(),
                                                 self.getFieldDemand())

    def getFieldSetPoint(self):
        return float(self.pvs['setpoint'].caget())

    def setFieldSetPoint(self, setpoint):
        self.pvs['setpoint'].caput(setpoint)

    def getFieldSetPointRBV(self):
        return float(self.pvs['setpointRbv'].caget())

    def getSweepRate(self):
        return float(self.pvs['sweeprate'].caget())

    def setSweepRate(self, setpoint):
        self.pvs['sweeprate'].caput(setpoint)

    def getSweepRateRBV(self):
        return float(self.pvs['sweeprateRbv'].caget())

    def getFieldDemand(self):
        return float(self.pvs['demand_field'].caget())
示例#9
0
 def __init__(self, pvroot):
     if isinstance(pvroot, str):
         from gdascripts.scannable.epics.PvManager import PvManager
         
         self.pvs = PvManager({'setpoint':   'TTEMP:SET',
                               'sensor':     'STEMP'}, pvroot)
         self.pvs.configure()
     else:
         self.pvs = pvroot
         self.pvs.pvroot = ""
示例#10
0
    def __init__(self, name, pvroot, filepath, filename, fileformat):
        self.name = name
        self.inputNames = ['ExposureTime']
        self.extraNames = ['FileNum']
        self.outputFormat = ['%.2f', '%.0f']
        self.level = 9

        self.filepath = None
        self.filename = None
        self.fileformat = None
        self.filenum = None
        self.cached_exptime = None
        self.filenum = None

        self.pvs = PvManager([
            'Acquire', 'NImages', 'Abort', 'ExposureTime', 'FilePath',
            'Filename', 'FileNumber', 'FileFormat', 'ThresholdEnergy'
        ], pvroot)
        self.configure(filepath, filename, fileformat)
示例#11
0
    def __init__(self, name, pgm_grat_pitch, pgm_mirr_pitch, pgmpvroot, id_energy, idpvroot, move_pgm=True, move_id=True): # motors, maybe also detector to set the delay time
        self.logger = LoggerFactory.getLogger("ContinuousPgmGratingIDGapEnergyMoveController:%s" % name)
        self.verbose = False
        self.name = name
        self._start_event = threading.Event()
        self._movelog_time = datetime.now()
        #PGM
        self._pgm_grat_pitch = pgm_grat_pitch
        self._pgm_mirr_pitch = pgm_mirr_pitch
        self._pgm_grat_pitch_speed_orig = None
        self._pgm_runupdown_time = None
        self._move_pgm = move_pgm
        self._move_id  = move_id

        self.pvs = PvManager({'grating_density':                'NLINES',
                              'cff':                            'CFF',
                              'grating_offset':                 'GRTOFFSET',
                              'plane_mirror_offset':            'MIROFFSET',
                              'pgm_energy':                     'ENERGY',
                              'grating_pitch':                  'GRT:PITCH',
                              'mirror_pitch':                   'MIR:PITCH',
                              'energy_calibration_gradient':    'MX',
                              'energy_calibration_reference':   'REFERENCE'}, pgmpvroot)
        if installation.isLive():
            self.pvs.configure()
        #ID
        self._id_energy=id_energy
        self._id_gap = self._id_energy.id_gap
        self._id_gap_speed_orig=None
        self._id_runupdown_time = None
        self.idpvs = PvManager({'vel':'BLGSETVEL',
                                'acc':'IDGSETACC'}, idpvroot)
        if installation.isLive():
            self.idpvs.configure()
            
        self.grating_pitch_positions=[]
        self.mirror_pitch_positions=[]
        self.pgm_energy_positions=[]
        self._start_time = None
        self.k=1.0
        self.pgmspeedfactor=1.0
示例#12
0
    def __init__(
            self,
            name,
            energy,
            idgap,
            idpvroot,
            move_mono=True,
            move_id=True):  # motors, maybe also detector to set the delay time
        self.logger = LoggerFactory.getLogger(
            "ContinuousEnergyMoveController:%s" % name)
        self.verbose = False
        self.setName(name)
        self._start_event = threading.Event()
        self._movelog_time = datetime.now()
        self._energy = energy
        #PGM
        self._mono_energy = energy.mono_energy
        self._mono_energy_speed_orig = None
        self._mono_runupdown_time = None
        #ID
        self._id_gap = idgap
        self._id_gap_speed_orig = None
        self._id_runupdown_time = None
        self.idpvs = PvManager({
            'vel': 'BLGSETVEL',
            'acc': 'IDGSETACC'
        }, idpvroot)
        if installation.isLive():
            self.idpvs.configure()

        self.mono_energy_positions = []
        self.id_gap_positions = []
        self._start_time = None

        #behaviour properties
        self._move_mono = move_mono
        self._move_id = move_id
        self.idspeedfactor = 1.0
        self.monospeedfactor = 1.0
        self.idstartdelaytime = 0.0
        self.continuousMovingStarted = False
示例#13
0
    def __init__(self,
                 name,
                 pvroot,
                 filepath=None,
                 determine_data_pv_based_on_zoom=False,
                 numtracker_extension='tmp',
                 filename_template='fire%d_%05d.png'):
        # BL07I-DI-PHDGN-06:CAM:DATA
        self.determine_data_pv_based_on_zoom = determine_data_pv_based_on_zoom

        self.name = name
        self.extraNames = []
        self.outputFormat = []
        self.level = 9

        self.pvs = PvManager(['SET_SHUTTR', 'WIDTH', 'HEIGHT', 'ZOOM'], pvroot)
        self.pv_data = []
        self.pv_data.append(
            gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot + 'DATA'))
        self.pv_data.append(
            gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot +
                                                              'DATA1'))
        self.pv_data.append(
            gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot +
                                                              'DATA2'))
        self.pv_data.append(
            gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot +
                                                              'DATA3'))
        self.pv_data.append(
            gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot +
                                                              'DATA4'))
        self.pvs.configure()

        self.filepath = filepath
        self.ds = None
        self.last_image_path = None
        self.last_filename = None
        self.last_image_number = 0
        self.numtracker_extension = numtracker_extension
        self.filename_template = filename_template
示例#14
0
 def __init__(self, name, rootPV, continuousMoveController):
     self.name = name
     self.setInputNames([name])
     self.setExtraNames(self._getExtraNames())
     self.setOutputFormat(self._getOutputFormat())
     self.setLevel(100)
     self.pvs = PvManager(pvroot=rootPV)
     self.continuousMoveController = continuousMoveController
     #from gda.device.zebra.controller.impl import ZebraImpl
     #self.zebra = ZebraImpl()
     self.verbose = False
     self.negative_offset = 0.05
     self.setDelayAfterRise(-0.01)
     self.setDelayAfterFall(-0.01)
     self.setAcquireTimePerPulse(0.02)
示例#15
0
	def __init__(self, name, pvroot, filepath, filename, fileformat):
		self.name = name
		self.inputNames = ['ExposureTime']
		self.extraNames = ['FileNum']
		self.outputFormat = ['%.2f', '%.0f']
		self.level = 9

		self.filepath = None
		self.filename = None
		self.fileformat = None
		self.filenum = None
		self.cached_exptime = None
		self.filenum = None

		self.pvs = PvManager(['Acquire','NImages','Abort','ExposureTime','FilePath','Filename','FileNumber','FileFormat','ThresholdEnergy'], pvroot)	
		self.configure(filepath, filename, fileformat)
示例#16
0
 def __init__(self, name, pvroot, filepath=None,
              stdNotArr=True, reconnect=True, verbose=False,
              acquireToCagetDelay_s = 0.1):
     # BL07I-DI-PHDGN-06:CAM:DATA
     self.name = name
     self.extraNames = []
     self.outputFormat = []
     self.level = 9
     self.verbose = verbose
     self.acquireToCagetDelay_s = acquireToCagetDelay_s
     stdArr = "STD" if stdNotArr else "ARR"
     pvs = { "DATA":stdArr+":ArrayData", "START":"CAM:Acquire",
             "WIDTH":"CAM:ArraySizeX_RBV", "HEIGHT":"CAM:ArraySizeY_RBV",
             "COLLECTTIME":"CAM:AcquireTime" }
     if reconnect:
         pvs["RECONNECT"]="CAM:RESET.PROC"
         
     self.pvs = PvManager(pvs, pvroot)
     self.pvs.configure()
     
     self.filepath = filepath
     self.ds = None
     
     self.disableStop = False
示例#17
0
class ContinuousPgmGratingEnergyMoveController(ConstantVelocityMoveController,
                                               DeviceBase):
    def __init__(
            self, name, pgm_grat_pitch, pgm_mirr_pitch,
            pgmpvroot):  # motors, maybe also detector to set the delay time
        self.logger = LoggerFactory.getLogger(
            "ContinuousPgmGratingEnergyMoveController:%s" % name)
        self.verbose = False

        self.name = name
        self._pgm_grat_pitch = pgm_grat_pitch
        self._pgm_mirr_pitch = pgm_mirr_pitch
        self._start_event = threading.Event()
        self._pgm_grat_pitch_speed_orig = None
        self._movelog_time = datetime.now()
        self._pgm_runupdown_time = None

        self.pvs = PvManager(
            {
                'grating_density': 'NLINES',
                'cff': 'CFF',
                'grating_offset': 'GRTOFFSET',
                'plane_mirror_offset': 'MIROFFSET',
                'pgm_energy': 'ENERGY',
                'grating_pitch': 'GRT:PITCH',
                'mirror_pitch': 'MIR:PITCH',
                'energy_calibration_gradient': 'MX',
                'energy_calibration_reference': 'REFERENCE'
            }, pgmpvroot)
        if installation.isLive():
            self.pvs.configure()

    # Implement: public interface ConstantVelocityMoveController extends ContinuousMoveController

    def setStart(self, start):  # double
        self._move_start = start
        if self.verbose: self.logger.info('setStart(%r)' % start)

    def setEnd(self, end):  # double
        self._move_end = end
        if self.verbose: self.logger.info('setEnd(%r)' % end)

    def setStep(self, step):  # double
        self._move_step = step
        if self.verbose: self.logger.info('setStep(%r)' % step)

    # Implement: public interface ContinuousMoveController extends HardwareTriggerProvider

    def getPgmEnergyParameters(self):
        grating_densityFromEnum = {'0': 400., '1': 400., '2': 1200.}
        return (grating_densityFromEnum[self.pvs['grating_density'].caget()],
                float(self.pvs['cff'].caget()),
                float(self.pvs['grating_offset'].caget()),
                float(self.pvs['plane_mirror_offset'].caget()),
                float(self.pvs['energy_calibration_gradient'].caget()),
                float(self.pvs['energy_calibration_reference'].caget()))

    def getPgmEnergyParametersFixed(self):
        # Hard code these values until we can work out a nice way of getting at the PVs
        # TODO: Get the values from their Epics PVs
        """
        caget BL10I-OP-PGM-01:NLINES BL10I-OP-PGM-01:CFF BL10I-OP-PGM-01:GRTOFFSET BL10I-OP-PGM-01:MIROFFSET BL10I-OP-PGM-01:MX BL10I-OP-PGM-01:REFERENCE
        """
        grating_density = 400.  # caget BL10I-OP-PGM-01:NLINES
        cff = 2.25  # caget BL10I-OP-PGM-01:CFF
        grating_offset = -0.053747  # caget BL10I-OP-PGM-01:GRTOFFSET
        plane_mirror_offset = 0.002514  # caget BL10I-OP-PGM-01:MIROFFSET

        #pgm_energy                     = 712.300           # caget BL10I-OP-PGM-01:ENERGY
        #grating_pitch                  = 88.0151063265128  # caget -g15 BL10I-OP-PGM-01:GRT:PITCH
        #mirror_pitch                   = 88.2753263680692  # caget -g15 BL10I-OP-PGM-01:MIR:PITCH

        energy_calibration_gradient = 1.0178  # caget BL10I-OP-PGM-01:MX
        energy_calibration_reference = 392.555  # caget BL10I-OP-PGM-01:REFERENCE

        return grating_density, cff, grating_offset, plane_mirror_offset, energy_calibration_gradient, energy_calibration_reference

    def prepareForMove(self):
        if self.verbose: self.logger.info('prepareForMove()...')
        self._pgm_grat_pitch_speed_orig = self._pgm_grat_pitch.speed

        # Calculate the energy midpoint
        energy_midpoint = (self._move_end + self._move_start) / 2.
        if self.verbose:
            self.logger.info('prepareForMove:energy_midpoint=%r ' %
                             (energy_midpoint))

        if installation.isLive():
            (self.grating_density, self.cff, self.grating_offset,
             self.plane_mirror_offset, self.energy_calibration_gradient,
             self.energy_calibration_reference
             ) = self.getPgmEnergyParameters()
        else:
            (self.grating_density, self.cff, self.grating_offset,
             self.plane_mirror_offset, self.energy_calibration_gradient,
             self.energy_calibration_reference
             ) = self.getPgmEnergyParametersFixed()

        # Calculate plane mirror angle for given grating density, energy, cff and offsets
        self.mirr_pitch_midpoint = enecff2mirror(
            gd=self.grating_density,
            energy=energy_midpoint,
            cff=self.cff,
            groff=self.grating_offset,
            pmoff=self.plane_mirror_offset,
            ecg=self.energy_calibration_gradient,
            ecr=self.energy_calibration_reference)

        # Calculate grating angles for given grating density, energy, mirror angle and offsets
        self._grat_pitch_start = enemirror2grating(
            gd=self.grating_density,
            energy=self._move_start,
            pmang=self.mirr_pitch_midpoint,
            groff=self.grating_offset,
            pmoff=self.plane_mirror_offset,
            ecg=self.energy_calibration_gradient,
            ecr=self.energy_calibration_reference)

        self._grat_pitch_end = enemirror2grating(
            gd=self.grating_density,
            energy=self._move_end,
            pmang=self.mirr_pitch_midpoint,
            groff=self.grating_offset,
            pmoff=self.plane_mirror_offset,
            ecg=self.energy_calibration_gradient,
            ecr=self.energy_calibration_reference)

        ### Calculate main cruise moves & speeds from start/end/step
        self._pgm_grat_pitch_speed = (
            abs(self._grat_pitch_end - self._grat_pitch_start) /
            self.getTotalTime())
        ### Calculate ramp distance from required speed and ramp times
        # Set the speed before we read out ramp times in case it is dependent
        self._pgm_grat_pitch.speed = self._pgm_grat_pitch_speed
        # Should really be / | | | | | \ not /| | | | |\
        self._pgm_runupdown_time = self._pgm_grat_pitch.timeToVelocity
        self._pgm_runupdown = self._pgm_grat_pitch_speed / 2 * self._pgm_runupdown_time
        ### Move motor at full speed to start position
        if self.verbose:
            self.logger.info(
                'prepareForMove:_pgm_mirr_pitch.asynchronousMoveTo(%r) @ %r ' %
                (self.mirr_pitch_midpoint * 1000., self._pgm_mirr_pitch.speed))
        self._pgm_mirr_pitch.asynchronousMoveTo(self.mirr_pitch_midpoint *
                                                1000.)

        self._pgm_grat_pitch.speed = self._pgm_grat_pitch_speed_orig
        if self.getGratingMoveDirectionPositive():
            if self.verbose:
                self.logger.info(
                    'prepareForMove:asynchronousMoveTo(%r) @ %r (+ve)' %
                    ((self._grat_pitch_start - self._pgm_runupdown) * 1000.,
                     self._pgm_grat_pitch_speed_orig))
            self._pgm_grat_pitch.asynchronousMoveTo(
                (self._grat_pitch_start - self._pgm_runupdown) * 1000.)
        else:
            if self.verbose:
                self.logger.info(
                    'prepareForMove:asynchronousMoveTo(%r) @ %r (-ve)' %
                    ((self._grat_pitch_start + self._pgm_runupdown) * 1000.,
                     self._pgm_grat_pitch_speed_orig))
            self._pgm_grat_pitch.asynchronousMoveTo(
                (self._grat_pitch_start + self._pgm_runupdown) * 1000.)
        self.waitWhileMoving()
        ### Calculate trigger delays
        if self.verbose:
            self.logger.info('...prepareForMove')

    def startMove(self):
        if self.verbose: self.logger.info('startMove()...')

        # Notify all position callables to start waiting for their time
        self._start_time = datetime.now()
        self._start_event.set()
        # Start threads to start ID & PGM and at the correct times
        self._pgm_grat_pitch.speed = self._pgm_grat_pitch_speed
        if self.getGratingMoveDirectionPositive():
            if self.verbose:
                self.logger.info(
                    'startMove:asynchronousMoveTo(%r) @ %r (+ve)' %
                    ((self._grat_pitch_end + self._pgm_runupdown) * 1000.,
                     self._pgm_grat_pitch_speed))
            self._pgm_grat_pitch.asynchronousMoveTo(
                (self._grat_pitch_end + self._pgm_runupdown) * 1000.)
        else:
            if self.verbose:
                self.logger.info(
                    'startMove:asynchronousMoveTo(%r) @ %r (-ve)' %
                    ((self._grat_pitch_end - self._pgm_runupdown) * 1000.,
                     self._pgm_grat_pitch_speed))
            self._pgm_grat_pitch.asynchronousMoveTo(
                (self._grat_pitch_end - self._pgm_runupdown) * 1000.)
        # How do we trigger the detectors, since they are 'HardwareTriggerable'?
        if self.verbose: self.logger.info('...startMove')

    def isMoving(self):
        if self.verbose and (datetime.now() -
                             self._movelog_time) > timedelta(seconds=1):
            self.logger.info(
                'isMoving() _pgm_grat_pitch=%r @ %r, _pgm_mirr_pitch=%r @ %r' %
                (self._pgm_grat_pitch.isBusy(), self._pgm_grat_pitch(),
                 self._pgm_mirr_pitch.isBusy(), self._pgm_mirr_pitch()))
            self._movelog_time = datetime.now()
        return self._pgm_grat_pitch.isBusy() or self._pgm_mirr_pitch.isBusy()

    def waitWhileMoving(self):
        if self.verbose: self.logger.info('waitWhileMoving()...')
        while self.isMoving():
            time.sleep(1)
        if self.verbose: self.logger.info('...waitWhileMoving()')

    def stopAndReset(self):
        self._start_time = None
        self._start_event.clear()
        if self.verbose: self.logger.info('stopAndReset()')
        self._pgm_grat_pitch.stop()
        self._restore_orig_speed()

    # Implement: public interface HardwareTriggerProvider extends Device

    def setTriggerPeriod(self, seconds):  # double
        self._triggerPeriod = seconds
        if self.verbose: self.logger.info('setTriggerPeriod(%r)' % seconds)

    def getNumberTriggers(self):
        triggers = self.getTotalMove() / self._move_step
        if self.verbose:
            self.logger.info('getNumberTriggers()=%r (%r)' %
                             (int(triggers), triggers))
        return int(triggers)

    def getTotalTime(self):
        totalTime = self.getNumberTriggers() * self._triggerPeriod
        if self.verbose: self.logger.info('getTotalTime()=%r' % totalTime)
        return totalTime

    def getTimeToVelocity(self):
        return self._pgm_runupdown_time

    # Override: public abstract class DeviceBase extends ConfigurableBase implements Device

    # None needed

    # Other functions

    def getTotalMove(self):
        totalMove = abs(self._move_end - self._move_start)
        if self.verbose: self.logger.info('getTotalMove()=%r' % totalMove)
        return totalMove

    def getGratingMoveDirectionPositive(self):
        return (self._grat_pitch_end - self._grat_pitch_start) > 0

    class DelayableCallable(Callable):
        def __init__(self, controller, demand_position):
            #self.start_event = threading.Event()
            self.start_event = controller._start_event
            self._controller, self._demand_position = controller, demand_position
            self.logger = LoggerFactory.getLogger(
                "ContinuousPgmGratingEnergyMoveController:%s:DelayableCallable[%r]"
                % (controller.name, demand_position))
            if self._controller.verbose:
                self.logger.info('__init__(%r, %r)...' %
                                 (controller.name, demand_position))

        def call(self):
            if self._controller.verbose: self.logger.info('call...')
            # Wait for controller to start all motors moving and set start time
            if self._controller._start_time:
                if self._controller.verbose:
                    self.logger.info('start_time=%r' %
                                     (self._controller._start_time))
            else:
                if self._controller.verbose: self.logger.info('wait()...')
                timeout = 60
                self.start_event.wait(timeout)
                if not self.start_event.isSet():
                    raise Exception(
                        "%rs timeout waiting for startMove() to be called on %s at position %r."
                        % (timeout, self._controller.name,
                           self._demand_position))
                if self._controller.verbose: self.logger.info('...wait()')
            # Wait for delay before actually move start and then a time given by
            # how far through the scan this point is

            grat_pitch = enemirror2grating(
                gd=self._controller.grating_density,
                energy=self._demand_position,
                pmang=self._controller.mirr_pitch_midpoint,
                groff=self._controller.grating_offset,
                pmoff=self._controller.plane_mirror_offset,
                ecg=self._controller.energy_calibration_gradient,
                ecr=self._controller.energy_calibration_reference)

            complete = abs((grat_pitch - self._controller._grat_pitch_start) /
                           (self._controller._grat_pitch_end -
                            self._controller._grat_pitch_start))
            sleeptime_s = (self._controller._pgm_runupdown_time +
                           (complete * self._controller.getTotalTime()))

            delta = datetime.now() - self._controller._start_time
            delta_s = delta.seconds + delta.microseconds / 1000000.
            if delta_s > sleeptime_s:
                self.logger.warn(
                    'Sleep time already past!!! sleeptime_s=%r, delta_s=%r, sleeptime_s-delta_s=%r'
                    % (sleeptime_s, delta_s, sleeptime_s - delta_s))
            else:
                if self._controller.verbose:
                    self.logger.info(
                        'sleeping... sleeptime_s=%r, delta_s=%r, sleeptime_s-delta_s=%r'
                        % (sleeptime_s, delta_s, sleeptime_s - delta_s))
                time.sleep(sleeptime_s - delta_s)

            energy = angles2energy(
                gd=self._controller.grating_density,
                grang=self._controller._pgm_grat_pitch() / 1000.,
                pmang=self._controller._pgm_mirr_pitch() / 1000.,
                groff=self._controller.grating_offset,
                pmoff=self._controller.plane_mirror_offset,
                ecg=self._controller.energy_calibration_gradient,
                ecr=self._controller.energy_calibration_reference)
            if self._controller.verbose:
                self.logger.info('...DelayableCallable:call returning %r, %r' %
                                 (self._demand_position, energy))
            return self._demand_position, energy

    def getPositionCallableExtraNames(self):
        return ['readback']

    def getPositionCallableFormat(self):
        return ['%f', '%f']

    # public Callable<T> getPositionCallable() throws DeviceException;
    def getPositionCallableFor(self, position):
        if self.verbose:
            self.logger.info('getPositionCallableFor(%r)...' % position)
        # TODO: return actual positions back calculated from energy positions
        return self.DelayableCallable(self, position)

    def _restore_orig_speed(self):
        if self._pgm_grat_pitch_speed_orig:
            if self.verbose:
                self.logger.info('Restoring original speed %r, was %r' %
                                 (self._pgm_grat_pitch_speed_orig,
                                  self._pgm_grat_pitch.speed))
            self._pgm_grat_pitch.speed = self._pgm_grat_pitch_speed_orig
            self._pgm_grat_pitch_speed_orig = None

    def atScanEnd(self):
        if self.verbose: self.logger.info('atScanEnd()...')
        self._restore_orig_speed()
示例#18
0
class ContinuousPgmGratingIDGapEnergyMoveController(ConstantVelocityMoveController, DeviceBase):
    '''Controller for constant velocity scan moving both PGM Grating Pitch and ID Gap at same time at constant speed respectively.
        It works for both Live and Dummy mode.
    '''
    def __init__(self, name, pgm_grat_pitch, pgm_mirr_pitch, pgmpvroot, id_energy, idpvroot, move_pgm=True, move_id=True): # motors, maybe also detector to set the delay time
        self.logger = LoggerFactory.getLogger("ContinuousPgmGratingIDGapEnergyMoveController:%s" % name)
        self.verbose = False
        self.name = name
        self._start_event = threading.Event()
        self._movelog_time = datetime.now()
        #PGM
        self._pgm_grat_pitch = pgm_grat_pitch
        self._pgm_mirr_pitch = pgm_mirr_pitch
        self._pgm_grat_pitch_speed_orig = None
        self._pgm_runupdown_time = None
        self._move_pgm = move_pgm
        self._move_id  = move_id

        self.pvs = PvManager({'grating_density':                'NLINES',
                              'cff':                            'CFF',
                              'grating_offset':                 'GRTOFFSET',
                              'plane_mirror_offset':            'MIROFFSET',
                              'pgm_energy':                     'ENERGY',
                              'grating_pitch':                  'GRT:PITCH',
                              'mirror_pitch':                   'MIR:PITCH',
                              'energy_calibration_gradient':    'MX',
                              'energy_calibration_reference':   'REFERENCE'}, pgmpvroot)
        if installation.isLive():
            self.pvs.configure()
        #ID
        self._id_energy=id_energy
        self._id_gap = self._id_energy.id_gap
        self._id_gap_speed_orig=None
        self._id_runupdown_time = None
        self.idpvs = PvManager({'vel':'BLGSETVEL',
                                'acc':'IDGSETACC'}, idpvroot)
        if installation.isLive():
            self.idpvs.configure()
            
        self.grating_pitch_positions=[]
        self.mirror_pitch_positions=[]
        self.pgm_energy_positions=[]
        self._start_time = None
        self.k=1.0
        self.pgmspeedfactor=1.0
    
    def setPGMSpeedFactor(self,val):
        self.pgmspeedfactor=val
        
    def getPGMSpeedFactor(self):
        return self.pgmspeedfactor
        
    #https://jira.diamond.ac.uk/browse/I10-301
    def enableIDMove(self):
        self._move_id=True
    
    def disableIDMove(self):
        self._move_id=False
        
    def isIDMoveEnabled(self):
        return self._move_id

    def enablePGMMove(self):
        self._move_pgm=True
    
    def disablePGMMove(self):
        self._move_pgm=False
        
    def isPGMMoveEnabled(self):
        return self._move_pgm

    # Implement: public interface ConstantVelocityMoveController extends ContinuousMoveController

    def setStart(self, start): # double
        self._move_start = start
        if self.verbose: self.logger.info('setStart(%r)' % start)
    
    def setEnd(self, end): # double
        self._move_end = end
        if self.verbose: self.logger.info('setEnd(%r)' % end)
    
    def setStep(self, step): # double
        self._move_step = step
        if self.verbose: self.logger.info('setStep(%r)' % step)

    # Implement: public interface ContinuousMoveController extends HardwareTriggerProvider

    def getPgmEnergyParameters(self):
        grating_densityFromEnum = {'0' : 400., '1':400., '2':1200.}
        return (grating_densityFromEnum[self.pvs['grating_density'].caget()],
                float(self.pvs['cff'].caget()), 
                float(self.pvs['grating_offset'].caget()), 
                float(self.pvs['plane_mirror_offset'].caget()), 
                float(self.pvs['energy_calibration_gradient'].caget()), 
                float(self.pvs['energy_calibration_reference'].caget()))
        
    def getPgmEnergyParametersFixed(self):
        # Hard code these values until we can work out a nice way of getting at the PVs
        # TODO: Get the values from their Epics PVs
        """
        caget BL10I-OP-PGM-01:NLINES BL10I-OP-PGM-01:CFF BL10I-OP-PGM-01:GRTOFFSET BL10I-OP-PGM-01:MIROFFSET BL10I-OP-PGM-01:MX BL10I-OP-PGM-01:REFERENCE
        """
        grating_density                 = 400.              # caget BL10I-OP-PGM-01:NLINES
        cff                             = 2.25              # caget BL10I-OP-PGM-01:CFF
        grating_offset                  = -0.053747         # caget BL10I-OP-PGM-01:GRTOFFSET
        plane_mirror_offset             = 0.002514          # caget BL10I-OP-PGM-01:MIROFFSET

        #pgm_energy                     = 712.300           # caget BL10I-OP-PGM-01:ENERGY
        #grating_pitch                  = 88.0151063265128  # caget -g15 BL10I-OP-PGM-01:GRT:PITCH
        #mirror_pitch                   = 88.2753263680692  # caget -g15 BL10I-OP-PGM-01:MIR:PITCH

        energy_calibration_gradient     = 1.0178            # caget BL10I-OP-PGM-01:MX
        energy_calibration_reference    = 392.555           # caget BL10I-OP-PGM-01:REFERENCE

        return grating_density, cff, grating_offset, plane_mirror_offset, energy_calibration_gradient, energy_calibration_reference


    def PreparePGMForMove(self):
        self._pgm_grat_pitch_speed_orig = 0.018
        self._pgm_grat_pitch.speed=self._pgm_grat_pitch_speed_orig
#         if self._pgm_grat_pitch_speed_orig != 0.018:
#             raise Exception("PGM Grit Pitch motor speed %f is not at maximum 0.018!" % (self._pgm_grat_pitch_speed_orig))
        
        # Calculate the energy midpoint
        energy_midpoint = (self._move_end + self._move_start) / 2.
        if self.verbose:
            self.logger.info('preparePGMForMove:energy_midpoint=%r ' % (energy_midpoint))

        if installation.isLive():
            self.grating_density, self.cff, self.grating_offset, self.plane_mirror_offset, self.energy_calibration_gradient, self.energy_calibration_reference = self.getPgmEnergyParameters()
        else:
            self.grating_density, self.cff, self.grating_offset, self.plane_mirror_offset, self.energy_calibration_gradient, self.energy_calibration_reference = self.getPgmEnergyParametersFixed()
            
        # Calculate plane mirror angle for given grating density, energy, cff and offsets
        self.mirr_pitch_midpoint = enecff2mirror(gd=self.grating_density, 
                                                 energy=energy_midpoint, 
                                                 cff=self.cff, 
                                                 groff=self.grating_offset, 
                                                 pmoff=self.plane_mirror_offset, 
                                                 ecg=self.energy_calibration_gradient, 
                                                 ecr=self.energy_calibration_reference)
        # Calculate grating angles for given grating density, energy, mirror angle and offsets
        self._grat_pitch_start = enemirror2grating(gd=self.grating_density, 
                                                   energy=self._move_start, 
                                                   pmang=self.mirr_pitch_midpoint, 
                                                   groff=self.grating_offset, 
                                                   pmoff=self.plane_mirror_offset, 
                                                   ecg=self.energy_calibration_gradient, 
                                                   ecr=self.energy_calibration_reference)
        self._grat_pitch_end = enemirror2grating(gd=self.grating_density, 
                                                 energy=self._move_end, 
                                                 pmang=self.mirr_pitch_midpoint, 
                                                 groff=self.grating_offset, 
                                                 pmoff=self.plane_mirror_offset, 
                                                 ecg=self.energy_calibration_gradient, 
                                                 ecr=self.energy_calibration_reference)
        if not self.isIDMoveEnabled():
            self.k=1.0
            
        
        print self.k
        ### Calculate main cruise moves & speeds from start/end/step
        self._pgm_grat_pitch_speed = abs(self._grat_pitch_end - self._grat_pitch_start) / self.getTotalTime()
        print self._pgm_grat_pitch_speed
        self._pgm_grat_pitch_speed=self._pgm_grat_pitch_speed*self.k * self.pgmspeedfactor
        print self._pgm_grat_pitch_speed
        
        ### Calculate ramp distance from required speed and ramp times
        #check speed within limits
        if self._pgm_grat_pitch_speed<=0.000 or self._pgm_grat_pitch_speed>0.018:
            raise Exception("Calculated PGM Grit Pitch motor speed %f is outside limits [%f, %f]!" % (self._pgm_grat_pitch_speed, 0.000, 0.018))
        
        # Set the speed before we read out ramp times in case it is dependent
        self._pgm_grat_pitch.speed = self._pgm_grat_pitch_speed 
        # Should really be / | | | | | \ not /| | | | |\
        self._pgm_runupdown_time = self._pgm_grat_pitch.timeToVelocity
        self._pgm_runupdown = self._pgm_grat_pitch_speed / 2 * self._pgm_runupdown_time
        ### Move motor at full speed to start position
        if self.verbose:
            self.logger.info('preparePGMForMove:_pgm_mirr_pitch.asynchronousMoveTo(%r) @ %r ' % (self.mirr_pitch_midpoint * 1000., self._pgm_mirr_pitch.speed))
        self._pgm_mirr_pitch.asynchronousMoveTo(self.mirr_pitch_midpoint * 1000.)
        self._pgm_grat_pitch.speed = self._pgm_grat_pitch_speed_orig
        if self.getGratingMoveDirectionPositive():
            if self.verbose:
                self.logger.info('preparePGMForMove:asynchronousMoveTo(%r) @ %r (+ve)' % ((self._grat_pitch_start - self._pgm_runupdown) * 1000., self._pgm_grat_pitch_speed_orig))
            self._pgm_grat_pitch.asynchronousMoveTo((self._grat_pitch_start - self._pgm_runupdown) * 1000.)
        else:
            if self.verbose:
                self.logger.info('preparePGMForMove:asynchronousMoveTo(%r) @ %r (-ve)' % ((self._grat_pitch_start + self._pgm_runupdown) * 1000., self._pgm_grat_pitch_speed_orig))
            self._pgm_grat_pitch.asynchronousMoveTo((self._grat_pitch_start + self._pgm_runupdown) * 1000.)

    def PrepareIDForMove(self):
        if installation.isLive():
            self._id_gap_speed_orig = float(self.idpvs['vel'].caget())
        else:
            self._id_gap_speed_orig = self._id_gap.speed
            
        # Calculate the energy midpoint
        energy_midpoint = (self._move_end + self._move_start) / 2.
        if self.verbose:
            self.logger.info('prepareIDForMove:energy_midpoint=%r ' % (energy_midpoint))

        # Calculate rowphase motor positions for given polarisation at energy midpoint
        self.id_rowphase1_midpoint = self._id_energy.rowphase1_from_energy(energy_midpoint)
        self.id_rowphase2_midpoint = self._id_energy.rowphase2_from_energy(energy_midpoint)
        self.id_rowphase3_midpoint = self._id_energy.rowphase3_from_energy(energy_midpoint)
        self.id_rowphase4_midpoint = self._id_energy.rowphase4_from_energy(energy_midpoint)
        
        # Calculate grating angles for given grating density, energy, mirror angle and offsets
        self._id_gap_start = self._id_energy.gap_from_energy(self._move_start)
        self._id_gap_end = self._id_energy.gap_from_energy(self._move_end)
        
            ### Calculate main cruise moves & speeds from start/end/step
        self._id_gap_speed = abs(self._id_gap_end - self._id_gap_start) / self.getTotalTime()
        
        print self._id_gap_speed
        self._id_gap_speed_rounded = Math.round(self._id_gap_speed*500.0)/500.0
        print self._id_gap_speed_rounded
        
        self.k=self._id_gap_speed_rounded/self._id_gap_speed
        
        ### Calculate ramp distance from required speed and ramp times
        #check speed within limits
        if self._id_gap_speed_rounded<0.004 or self._id_gap_speed_rounded>1.0:
            raise Exception("Calculated ID gap speed %f is outside limits [%f, %f]!" % (self._id_gap_speed_rounded, 0.004, 1.0))
        if installation.isLive():
            #self._id_gap.speed = self._id_gap_speed #Cannot set id_gap.speed through soft motor which in EPICS is read-only 
            self.idpvs['vel'].caput(self._id_gap_speed_rounded)
        else:
            self._id_gap.speed = self._id_gap_speed_rounded 
            
        #acceleration time per axis
        self._id_axis_speed=self._id_gap_speed_rounded/2
        self._id_runupdown_time_per_axis=self._id_axis_speed*4
        # Should really be / | | | | | \ not /| | | | |\
        self._id_runupdown_per_axis = self._id_axis_speed / 2 * self._id_runupdown_time_per_axis
        self._id_gap_runupdown = self._id_runupdown_per_axis * 2
        ### Move motor at full speed to start position
        if self.verbose:
            self.logger.info('prepareIDForMove:%s.asynchronousMoveTo(%r) ' % (self._id_energy.id_rowphase1.getName(),self.id_rowphase1_midpoint))
            self.logger.info('prepareIDForMove:%s.asynchronousMoveTo(%r) ' % (self._id_energy.id_rowphase2.getName(),self.id_rowphase2_midpoint))
            self.logger.info('prepareIDForMove:%s.asynchronousMoveTo(%r) ' % (self._id_energy.id_rowphase3.getName(),self.id_rowphase3_midpoint))
            self.logger.info('prepareIDForMove:%s.asynchronousMoveTo(%r) ' % (self._id_energy.id_rowphase4.getName(),self.id_rowphase4_midpoint))
        self._id_energy.id_rowphase1.asynchronousMoveTo(self.id_rowphase1_midpoint)
        self._id_energy.id_rowphase2.asynchronousMoveTo(self.id_rowphase2_midpoint)
        self._id_energy.id_rowphase3.asynchronousMoveTo(self.id_rowphase3_midpoint)
        self._id_energy.id_rowphase4.asynchronousMoveTo(self.id_rowphase4_midpoint)
        
        if installation.isLive():
            self.idpvs['vel'].caput(self._id_gap_speed_orig)
        else:
            self._id_gap.speed = self._id_gap_speed_orig 
            
        if self.getIDGapMoveDirectionPositive():
            if self.verbose:
                self.logger.info('prepareIDForMove:asynchronousMoveTo(%r) @ %r (+ve)' % ((self._id_gap_start - self._id_gap_runupdown), self._id_gap_speed_orig))
            self._id_energy.id_gap.asynchronousMoveTo((self._id_gap_start - self._id_gap_runupdown))
        else:
            if self.verbose:
                self.logger.info('prepareIDForMove:asynchronousMoveTo(%r) @ %r (-ve)' % ((self._id_gap_start + self._id_gap_runupdown), self._id_gap_speed_orig))
            self._id_energy.id_gap.asynchronousMoveTo((self._id_gap_start + self._id_gap_runupdown))

    def prepareForMove(self):
        if self.verbose: self.logger.info('prepareForMove()...')
        
        if self.isIDMoveEnabled():
            self.PrepareIDForMove()
        else:
            if self.verbose:
                self.logger.info('ID move is disabled in %r' % (self.getName()))
                
        if self.isPGMMoveEnabled():
            self.PreparePGMForMove()
        else:
            if self.verbose:
                self.logger.info('PGM move is disabled in %r' % (self.getName()))

            
        if not self.isPGMMoveEnabled() and not self.isIDMoveEnabled():
            raise Exception("Both PGM and ID moves are disabled so no scan will occur!")
        
        self.waitWhileMoving()
        ### Calculate trigger delays
        if self.verbose:
            self.logger.info('...prepareForMove')

    def startMove(self):
        if self.verbose: self.logger.info('startMove()...')
        
        # Notify all position callables to start waiting for their time
        self._start_time = datetime.now()
        self._start_event.set()
        # Start threads to start ID & PGM and at the correct times
        if self.isPGMMoveEnabled():
            self._pgm_grat_pitch.speed = self._pgm_grat_pitch_speed
        
        if self.isIDMoveEnabled():
            if installation.isLive():
                self.idpvs['vel'].caput(self._id_gap_speed_rounded)
            else:
                self._id_gap.speed = self._id_gap_speed_rounded
        
        if self.isPGMMoveEnabled():
            if self.getGratingMoveDirectionPositive():
                if self.verbose: self.logger.info('startMove PGM Grating Pitch: asynchronousMoveTo(%r) @ %r (+ve)' % (
                                                        (self._grat_pitch_end + self._pgm_runupdown)*1000., self._pgm_grat_pitch_speed))
                self._pgm_grat_pitch.asynchronousMoveTo((self._grat_pitch_end + self._pgm_runupdown)*1000.)
            else:
                if self.verbose: self.logger.info('startMove PGM Grating Pitch: asynchronousMoveTo(%r) @ %r (-ve)' % (
                                                        (self._grat_pitch_end - self._pgm_runupdown)*1000., self._pgm_grat_pitch_speed))
                self._pgm_grat_pitch.asynchronousMoveTo((self._grat_pitch_end - self._pgm_runupdown)*1000.)
        if self.isIDMoveEnabled():
            if self.getIDGapMoveDirectionPositive():
                if self.verbose: self.logger.info('startMove ID Gap: asynchronousMoveTo(%r) @ %r (+ve)' % (
                                                        (self._id_gap_end + 0.05 + self._id_gap_runupdown), self._id_gap_speed))
                self._id_energy.id_gap.asynchronousMoveTo((self._id_gap_end + 0.05 + self._id_gap_runupdown))
            else:
                if self.verbose: self.logger.info('startMove ID Gap: asynchronousMoveTo(%r) @ %r (-ve)' % (
                                                        (self._id_gap_end - 0.05 - self._id_gap_runupdown), self._id_gap_speed))
                self._id_energy.id_gap.asynchronousMoveTo((self._id_gap_end - 0.05 - self._id_gap_runupdown))
        # How do we trigger the detectors, since they are 'HardwareTriggerable'?
        if self.verbose: self.logger.info('...startMove')

    def isMoving(self):
        if self.verbose and (datetime.now() - self._movelog_time) > timedelta(seconds=1):
            self.logger.info('isMoving() _pgm_grat_pitch=%r @ %r, _pgm_mirr_pitch=%r @ %r, _id_gap=%r @ %r' % (
                self._pgm_grat_pitch.isBusy(), self._pgm_grat_pitch(),
                self._pgm_mirr_pitch.isBusy(), self._pgm_mirr_pitch(),
                self._id_energy.id_gap.isBusy(), self._id_energy.id_gap()))
            self._movelog_time = datetime.now()
        return self._pgm_grat_pitch.isBusy() or self._pgm_mirr_pitch.isBusy() or self._id_energy.id_gap.isBusy()

    def waitWhileMoving(self):
        if self.verbose: self.logger.info('waitWhileMoving()...')
        while self.isMoving():
            time.sleep(1)
        if self.verbose: self.logger.info('...waitWhileMoving()')

    def stopAndReset(self):
        self._start_time = None
        self._start_event.clear()
        if self.verbose: self.logger.info('stopAndReset()')
        if self.isPGMMoveEnabled():
            self._pgm_grat_pitch.stop()
        if self.isIDMoveEnabled():
            self._id_energy.id_gap.stop()
        self._restore_orig_speed()

    # Implement: public interface HardwareTriggerProvider extends Device

    def setTriggerPeriod(self, seconds): # double
        self._triggerPeriod = seconds
        if self.verbose: self.logger.info('setTriggerPeriod(%r)' % seconds)

    def getNumberTriggers(self):
        triggers = self.getTotalMove() / abs(self._move_step)
        if self.verbose: self.logger.info('getNumberTriggers()=%r (%r)' % (int(triggers), triggers))
        return int(triggers)

    def getTotalTime(self):
        totalTime = self.getNumberTriggers() * self._triggerPeriod
        if self.verbose: self.logger.info('getTotalTime()=%r' % totalTime)
        return totalTime

    def getTimeToVelocity(self):
        return self._pgm_runupdown_time

    # Override: public abstract class DeviceBase extends ConfigurableBase implements Device

        # None needed

    # Other functions

    def getTotalMove(self):
        totalMove = abs(self._move_end - self._move_start)
        if self.verbose: self.logger.info('getTotalMove()=%r' % totalMove)
        return totalMove

    def getGratingMoveDirectionPositive(self):
        return (self._grat_pitch_end - self._grat_pitch_start) > 0

    def getIDGapMoveDirectionPositive(self):
        return (self._id_gap_end - self._id_gap_start) > 0

    class DelayableCallable(Callable):
    
        def __init__(self, controller, demand_position):
            #self.start_event = threading.Event()
            self.start_event = controller._start_event
            self._controller, self._demand_position = controller, demand_position
            self.logger = LoggerFactory.getLogger("ContinuousPgmGratingIDGapEnergyMoveController:%s:DelayableCallable[%r]" % (controller.name, demand_position))
            if self._controller.verbose:
                self.logger.info('__init__(%r, %r)...' % (controller.name, demand_position))
    
        def call(self):
            if self._controller.verbose: self.logger.info('call...')
            # Wait for controller to start all motors moving and set start time
            if self._controller._start_time:
                if self._controller.verbose: self.logger.info('start_time=%r' % (self._controller._start_time))
            else:
                if self._controller.verbose: self.logger.info('wait()...')
                timeout=60
                self.start_event.wait(timeout)
                if not self.start_event.isSet():
                    raise Exception("%rs timeout waiting for startMove() to be called on %s at position %r." % (timeout, self._controller.name, self._demand_position))
                if self._controller.verbose: self.logger.info('...wait()')
            # Wait for delay before actually move start and then a time given by
            # how far through the scan this point is
            
            grat_pitch = enemirror2grating(gd     = self._controller.grating_density,
                                           energy = self._demand_position,
                                           pmang  = self._controller.mirr_pitch_midpoint,
                                           groff  = self._controller.grating_offset,
                                           pmoff  = self._controller.plane_mirror_offset,
                                           ecg    = self._controller.energy_calibration_gradient,
                                           ecr    = self._controller.energy_calibration_reference)
            
            complete = abs( (grat_pitch - self._controller._grat_pitch_start) /
                            (self._controller._grat_pitch_end - self._controller._grat_pitch_start) )
            sleeptime_s = (self._controller._pgm_runupdown_time
                + (complete * self._controller.getTotalTime()))
            
            delta = datetime.now() - self._controller._start_time
            delta_s = delta.seconds + delta.microseconds/1000000.
            if delta_s > sleeptime_s:
                self.logger.warn('Sleep time already past!!! sleeptime_s=%r, delta_s=%r, sleeptime_s-delta_s=%r' % (sleeptime_s, delta_s, sleeptime_s-delta_s))
            else:
                if self._controller.verbose:
                    self.logger.info('sleeping... sleeptime_s=%r, delta_s=%r, sleeptime_s-delta_s=%r' % (sleeptime_s, delta_s, sleeptime_s-delta_s))
                time.sleep(sleeptime_s-delta_s)
            
            energy = angles2energy(gd       = self._controller.grating_density,
                                   grang    = self._controller._pgm_grat_pitch()/1000.,
                                   pmang    = self._controller._pgm_mirr_pitch()/1000.,
                                   groff    = self._controller.grating_offset,
                                   pmoff    = self._controller.plane_mirror_offset,
                                   ecg      = self._controller.energy_calibration_gradient,
                                   ecr      = self._controller.energy_calibration_reference)
            if self._controller.verbose:
                self.logger.info('...DelayableCallable:call returning %r, %r' % (self._demand_position, energy))
            return self._demand_position, energy

    def getPositionCallableExtraNames(self):
        return ['readback']

    def getPositionCallableFormat(self):
        return ['%f', '%f']

    # public Callable<T> getPositionCallable() throws DeviceException;
    def getPositionCallableFor(self, position):
        if self.verbose: self.logger.info('getPositionCallableFor(%r)...' % position)
        # TODO: return actual positions back calculated from energy positions
        return self.DelayableCallable(self, position)

    def _restore_orig_speed(self):
        if self.isPGMMoveEnabled():
            if self._pgm_grat_pitch_speed_orig:
                if self.verbose: self.logger.info('Restoring original PGM Grating Pitch speed %r, was %r' % (self._pgm_grat_pitch_speed_orig, self._pgm_grat_pitch.speed))
                self._pgm_grat_pitch.speed = self._pgm_grat_pitch_speed_orig
                self._pgm_grat_pitch_speed_orig = None
        if self.isIDMoveEnabled():
            if self._id_gap_speed_orig:
                if installation.isLive():
                    if self.verbose: self.logger.info('Restoring original ID gap speed %r, was %r' % (self._id_gap_speed_orig, self.idpvs['vel'].caget()))
                    self.idpvs['vel'].caput(self._id_gap_speed_orig)
                else:
                    if self.verbose: self.logger.info('Restoring original ID gap speed %r, was %r' % (self._id_gap_speed_orig, self._id_gap.speed))
                    self._id_gap.speed = self._id_gap_speed_orig 
                self._id_gap_speed_orig = None

    def atScanEnd(self):
        if self.verbose: self.logger.info('atScanEnd()...')
        self._restore_orig_speed()
示例#19
0
class EpicsPilatus(PseudoDetector):
	'''Pilatus PD
	obj=PilatusClass(name,pvroot,filepath,filename)
	e.g. pilatus=PilatusClass('P100k','BL16I-EA-PILAT-01:','/dls/i16/data/Pilatus/','p')
	pilatus.getThesholdEnergy to print threshhold
	Make sure camserver is runnning
	ssh -X det@i16-pilatus1  (password Pilatus2)
 	ps aux | grep cam   to see if camserver running
	to start camserver...
	cd p2_1mod
	camonly
	self.display_data=0 removes data plotting and data summary for faster aquisition
	self.setFileName(name) sets data file name e.g. 'p'
	self.setFilePath(name) sets data file path e.g. '/dls/i16/data/Pilatus/'
	self.defaultFileName()/ self.defaultFilePath()sets data file name/path back to the name given when the device was created
	'''

	def __init__(self, name, pvroot, filepath, filename, fileformat):
		self.name = name
		self.inputNames = ['ExposureTime']
		self.extraNames = ['FileNum']
		self.outputFormat = ['%.2f', '%.0f']
		self.level = 9

		self.filepath = None
		self.filename = None
		self.fileformat = None
		self.filenum = None
		self.cached_exptime = None
		self.filenum = None

		self.pvs = PvManager(['Acquire','NImages','Abort','ExposureTime','FilePath','Filename','FileNumber','FileFormat','ThresholdEnergy'], pvroot)	
		self.configure(filepath, filename, fileformat)

	def configure(self, filepath = None, filename=None, fileformat = None):
		self.pvs.configure()
		if filepath:
			self.setFilepath(filepath)
		if filename:
			self.setFilename(filename)
		if fileformat:
			self.setFileformat(fileformat)
		self.setNumberImages(1)
		self.updateFilenumber()
		self.cached_exptime = 0
		sleep(1)

# DETECTOR INTERFACE
	def createsOwnFiles(self):
		return True

	def setCollectionTime(self, t):
		if t != self.cached_exptime:
			self.setCollectionTimeCommand(t)
		self.cached_exptime = t
	
	def getCollectionTime(self):
		return self.cached_exptime
	
	def collectData(self):
		self.acquireCommand()
	
	def getStatus(self):
		if self.isBusyCommand():
			return BUSY
		else:
			return IDLE
	
	def readout(self):
		self.updateFilenumber()
		return self.fileformat % (self.filepath, self.filename, self.filenum)

# SCANNABLE INTERFACE (currently used by pos but not scan ??)

	def stop(self):
		self.stopCommand()

	def getPosition(self):
		self.updateFilenumber()
		self.readout()
		return [self.cached_exptime, self.filenum]

	def asynchronousMoveTo(self, t):
		self.setCollectionTime(t)
		self.collectData()

	def getFilepath(self):
		return self.filepath
# PILATUS COMMANDS
	# Note: Command appended where name already taken
	def setFilename(self, filename):
		self.pvs['Filename'].caput(filename)
		self.filename = filename

	def setFilepath(self, filepath):
		self.filepath=filepath		
		self.pvs['FilePath'].caput(filepath)
		
	def setFileformat(self, fileformat):
		self.fileformat = fileformat
		self.pvs['FileFormat'].caput(fileformat)
		
	def updateFilenumber(self):
		self.filenum = float(self.pvs['FileNumber'].caget())-1

	def setNumberImages(self, n):
		self.pvs['NImages'].caput(n)

	def setCollectionTimeCommand(self, t):
		self.pvs['ExposureTime'].caput(t)
		sleep(1)

	def isBusyCommand(self):
		return float(self.pvs['Acquire'].caget())

	def stopCommand(self):
		self.pvs['Abort'].caput(1)
		
	def acquireCommand(self):
		self.pvs['Acquire'].caput(1)
		
	def getThresholdEnergy(self):
		print "WARNING: this method returns before the underlying hardware has been updated"
		return float(self.pvs['ThresholdEnergy'].caget())
示例#20
0
class EpicsFirewireCamera(PseudoDetector):

	#TODO: Known bug: only works when epics zoom turned off (read the zoom value)
	def __init__(self, name, pvroot, filepath=None, determine_data_pv_based_on_zoom = False, numtracker_extension='tmp', filename_template='fire%d_%05d.png'):
		# BL07I-DI-PHDGN-06:CAM:DATA
		self.determine_data_pv_based_on_zoom = determine_data_pv_based_on_zoom
		
		self.name = name
		self.extraNames = []
		self.outputFormat = []
		self.level = 9

		self.pvs = PvManager(['SET_SHUTTR', 'WIDTH', 'HEIGHT', 'ZOOM'], pvroot)
		self.pv_data = []
		self.pv_data.append(gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot + 'DATA'))
		self.pv_data.append(gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot + 'DATA1'))
		self.pv_data.append(gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot + 'DATA2'))
		self.pv_data.append(gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot + 'DATA3'))
		self.pv_data.append(gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot + 'DATA4'))
		self.pvs.configure()
		
		self.filepath = filepath
		self.ds = None
		self.last_image_path = None
		self.last_filename = None
		self.last_image_number = 0
		self.numtracker_extension = numtracker_extension
		self.filename_template = filename_template

	def createsOwnFiles(self):
		return False

	def setCollectionTime(self, t):
		self.pvs['SET_SHUTTR'].caput(int(t))

	def getCollectionTime(self):
		return float(self.pvs['SET_SHUTTR'].caget())
	
	def prepareForCollection(self):
		self.last_image_number = -1
	
	def collectData(self):
		#rawdata = self.pvs['DATA'].cagetArray()
		if self.determine_data_pv_based_on_zoom:
			zoom_ordinal = int(float(self.pvs['ZOOM'].caget()))
			rawdata = self.pv_data[zoom_ordinal].get()
		else:
			rawdata = self.pv_data[0].get()
		data = map(unsign2, rawdata )
		self.ds = DatasetFactory.zeros(int(float(self.pvs['HEIGHT'].caget())), int(float(self.pvs['WIDTH'].caget())), data)
		self.last_image_number += 1
		self.last_filename = self._generateCurrentFilename()
		if self.filepath is not None:
			self.saveImage(self.last_filename);
	
	def _getCurrentScanNumer(self):
		return NumTracker(self.numtracker_extension).getCurrentFileNumber();
	
	def _generateCurrentFilename(self):
		if isScanRunning():
			return self.filename_template % (self._getCurrentScanNumer(), self.last_image_number)
		else:
			return time.strftime("%Y%m%d%H%M%S", time.localtime()) + '%03d' % ((time.time()%1)*1000) + '.png'
	
	def getStatus(self):
		return IDLE
	
	def readout(self):
		if self.ds is None:
			raise Exception("Epics Firewire Camera %s has not acquired an image" % self.name)
		else:
			return self.ds
		
	def setFilepath(self, filepath):
		self.filepath=filepath
		
	def getFilepath(self):
		return self.filepath
	
	def getLastImagePath(self):
		return self.last_image_path
	
	def saveImage(self, filename):
		path = self.filepath + filename
		if self.ds is None:
			raise Exception("Epics Firewire Camera %s has not acquired an image" % self.name)
		else:
			sfh = ScanFileHolder()
			sfh.addDataSet("Image",self.ds)
			sfh.save(PNGSaver(path))
			self.last_image_path = path
示例#21
0
class EpicsGigECamera(PseudoDetector):

    #TODO: Known bug: only works when epics zoom turned off (read the zoom value)
    def __init__(self,
                 name,
                 pvroot,
                 filepath=None,
                 stdNotArr=True,
                 reconnect=True,
                 verbose=False,
                 acquireToCagetDelay_s=0.1):
        # BL07I-DI-PHDGN-06:CAM:DATA
        self.name = name
        self.extraNames = []
        self.outputFormat = []
        self.level = 9
        self.verbose = verbose
        self.acquireToCagetDelay_s = acquireToCagetDelay_s
        stdArr = "STD" if stdNotArr else "ARR"
        pvs = {
            "DATA": stdArr + ":ArrayData",
            "START": "CAM:Acquire",
            "WIDTH": "CAM:ArraySizeX_RBV",
            "HEIGHT": "CAM:ArraySizeY_RBV",
            "COLLECTTIME": "CAM:AcquireTime"
        }
        if reconnect:
            pvs["RECONNECT"] = "CAM:RESET.PROC"

        self.pvs = PvManager(pvs, pvroot)
        self.pvs.configure()

        self.filepath = filepath
        self.ds = None

        self.disableStop = False

    def createsOwnFiles(self):
        return False

    def setCollectionTime(self, t):
        #self.pvs["COLLECTTIME"].caput(int(t))
        self.pvs["COLLECTTIME"].caput(float(t))

    def getCollectionTime(self):
        return float(self.pvs['COLLECTTIME'].caget())

    def setDisableStop(self, disable):
        self.disableStop = disable

    def stop(self):
        if self.verbose:
            print "%s.stop()" % self.name

        if not self.disableStop:
            self.pvs["START"].caput(0)

    def collectData(self):
        """
>>>pos cam1 1.5
cam1det.collectData() acquiring...
cam1det.collectData() (1.604000s) ended
cam1det.readout() getting...
cam1det.readout() (0.340000s) sign correction...
cam1det.readout() (6.910000s) creating DataSet...
cam1det.readout() (0.352000s) saving...
cam1det.readout() (0.581000s) ended
Move completed: cam1 : t: 1.500000 path: 122201.0
"""
        if self.verbose:
            print "%s.collectData() acquiring..." % self.name
            t = time.time()

        self.ds = None

        self.pvs["START"].caput(1)
        sleep(self.getCollectionTime() + self.acquireToCagetDelay_s)

        if self.verbose:
            dt, t = time.time() - t, time.time()
            print "%s.collectData() (%fs) ended" % (self.name, dt)

    def getStatus(self):
        return IDLE

    def readout(self):
        if self.ds is None:
            if self.verbose:
                print "%s.readout() getting..." % self.name
                t = time.time()

            rawdata = self.pvs['DATA'].cagetArray()

            if self.verbose:
                dt, t = time.time() - t, time.time()
                print "%s.readout() (%fs) sign correction..." % (self.name, dt)

            data = map(unsign2, rawdata)

            if self.verbose:
                dt, t = time.time() - t, time.time()
                print "%s.readout() (%fs) creating DataSet..." % (self.name,
                                                                  dt)

            self.ds = DatasetFactory.createFromObject(data, [
                int(float(self.pvs['HEIGHT'].caget())),
                int(float(self.pvs['WIDTH'].caget()))
            ])

            if self.verbose:
                dt, t = time.time() - t, time.time()
                print "%s.readout() (%fs) saving..." % (self.name, dt)

            if self.filepath is not None:
                self.saveImage(
                    time.strftime("%Y%m%d%H%M%S.png", time.localtime()))

            if self.verbose:
                dt, t = time.time() - t, time.time()
                print "%s.readout() (%fs) ended" % (self.name, dt)

        return self.ds

    def setFilepath(self, filepath):
        self.filepath = filepath

    def getFilepath(self):
        return self.filepath

    def saveImage(self, filename):
        path = self.filepath + filename
        if self.ds is None:
            raise Exception("Epics GigE Camera %s has not acquired an image" %
                            self.name)
        else:
            sfh = ScanFileHolder()
            sfh.addDataSet("Image", self.ds)
            sfh.save(PNGSaver(path))
示例#22
0
class EpicsGigECamera(PseudoDetector):

    #TODO: Known bug: only works when epics zoom turned off (read the zoom value)
    def __init__(self, name, pvroot, filepath=None,
                 stdNotArr=True, reconnect=True, verbose=False,
                 acquireToCagetDelay_s = 0.1):
        # BL07I-DI-PHDGN-06:CAM:DATA
        self.name = name
        self.extraNames = []
        self.outputFormat = []
        self.level = 9
        self.verbose = verbose
        self.acquireToCagetDelay_s = acquireToCagetDelay_s
        stdArr = "STD" if stdNotArr else "ARR"
        pvs = { "DATA":stdArr+":ArrayData", "START":"CAM:Acquire",
                "WIDTH":"CAM:ArraySizeX_RBV", "HEIGHT":"CAM:ArraySizeY_RBV",
                "COLLECTTIME":"CAM:AcquireTime" }
        if reconnect:
            pvs["RECONNECT"]="CAM:RESET.PROC"
            
        self.pvs = PvManager(pvs, pvroot)
        self.pvs.configure()
        
        self.filepath = filepath
        self.ds = None
        
        self.disableStop = False
        
    def createsOwnFiles(self):
        return False

    def setCollectionTime(self, t):
        #self.pvs["COLLECTTIME"].caput(int(t))
        self.pvs["COLLECTTIME"].caput(float(t))

    def getCollectionTime(self):
        return float(self.pvs['COLLECTTIME'].caget())
    
    def setDisableStop(self, disable):
        self.disableStop = disable
    
    def stop(self):
        if self.verbose:
            print "%s.stop()" % self.name
        
        if not self.disableStop:
            self.pvs["START"].caput(0)
    
    def collectData(self):
        """
>>>pos cam1 1.5
cam1det.collectData() acquiring...
cam1det.collectData() (1.604000s) ended
cam1det.readout() getting...
cam1det.readout() (0.340000s) sign correction...
cam1det.readout() (6.910000s) creating DataSet...
cam1det.readout() (0.352000s) saving...
cam1det.readout() (0.581000s) ended
Move completed: cam1 : t: 1.500000 path: 122201.0
"""
        if self.verbose:
            print "%s.collectData() acquiring..." % self.name
            t = time.time()
        
        self.ds = None
        
        self.pvs["START"].caput(1)
        sleep(self.getCollectionTime()+self.acquireToCagetDelay_s)
        
        if self.verbose:
            dt, t = time.time()-t, time.time()
            print "%s.collectData() (%fs) ended" % (self.name, dt)
    
    def getStatus(self):
        return IDLE
    
    def readout(self):
        if self.ds is None:
            if self.verbose:
                print "%s.readout() getting..." % self.name
                t = time.time()
            
            rawdata = self.pvs['DATA'].cagetArray()
            
            if self.verbose:
                dt, t = time.time()-t, time.time()
                print "%s.readout() (%fs) sign correction..." % (self.name, dt)
            
            data = map(unsign2, rawdata )
            
            if self.verbose:
                dt, t = time.time()-t, time.time()
                print "%s.readout() (%fs) creating DataSet..." % (self.name, dt)
            
            self.ds = DatasetFactory.createFromObject(data, [int(float(self.pvs['HEIGHT'].caget())), int(float(self.pvs['WIDTH'].caget()))])
            
            if self.verbose:
                dt, t = time.time()-t, time.time()
                print "%s.readout() (%fs) saving..." % (self.name, dt)
            
            if self.filepath is not None:
                self.saveImage(time.strftime("%Y%m%d%H%M%S.png", time.localtime()))
            
            if self.verbose:
                dt, t = time.time()-t, time.time()
                print "%s.readout() (%fs) ended" % (self.name, dt)
        
        return self.ds
        
    def setFilepath(self, filepath):
        self.filepath=filepath
        
    def getFilepath(self):
        return self.filepath
    
    def saveImage(self, filename):
        path = self.filepath + filename
        if self.ds is None:
            raise Exception("Epics GigE Camera %s has not acquired an image" % self.name)
        else:
            sfh = ScanFileHolder()
            sfh.addDataSet("Image",self.ds)
            sfh.save(PNGSaver(path))
示例#23
0
class EpicsPilatus(PseudoDetector):
    '''Pilatus PD
	obj=PilatusClass(name,pvroot,filepath,filename)
	e.g. pilatus=PilatusClass('P100k','BL16I-EA-PILAT-01:','/dls/i16/data/Pilatus/','p')
	pilatus.getThesholdEnergy to print threshhold
	Make sure camserver is runnning
	ssh -X det@i16-pilatus1  (password Pilatus2)
 	ps aux | grep cam   to see if camserver running
	to start camserver...
	cd p2_1mod
	camonly
	self.display_data=0 removes data plotting and data summary for faster aquisition
	self.setFileName(name) sets data file name e.g. 'p'
	self.setFilePath(name) sets data file path e.g. '/dls/i16/data/Pilatus/'
	self.defaultFileName()/ self.defaultFilePath()sets data file name/path back to the name given when the device was created
	'''
    def __init__(self, name, pvroot, filepath, filename, fileformat):
        self.name = name
        self.inputNames = ['ExposureTime']
        self.extraNames = ['FileNum']
        self.outputFormat = ['%.2f', '%.0f']
        self.level = 9

        self.filepath = None
        self.filename = None
        self.fileformat = None
        self.filenum = None
        self.cached_exptime = None
        self.filenum = None

        self.pvs = PvManager([
            'Acquire', 'NImages', 'Abort', 'ExposureTime', 'FilePath',
            'Filename', 'FileNumber', 'FileFormat', 'ThresholdEnergy'
        ], pvroot)
        self.configure(filepath, filename, fileformat)

    def configure(self, filepath=None, filename=None, fileformat=None):
        self.pvs.configure()
        if filepath:
            self.setFilepath(filepath)
        if filename:
            self.setFilename(filename)
        if fileformat:
            self.setFileformat(fileformat)
        self.setNumberImages(1)
        self.updateFilenumber()
        self.cached_exptime = 0
        sleep(1)

# DETECTOR INTERFACE

    def createsOwnFiles(self):
        return True

    def setCollectionTime(self, t):
        if t != self.cached_exptime:
            self.setCollectionTimeCommand(t)
        self.cached_exptime = t

    def getCollectionTime(self):
        return self.cached_exptime

    def collectData(self):
        self.acquireCommand()

    def getStatus(self):
        if self.isBusyCommand():
            return BUSY
        else:
            return IDLE

    def readout(self):
        self.updateFilenumber()
        return self.fileformat % (self.filepath, self.filename, self.filenum)

# SCANNABLE INTERFACE (currently used by pos but not scan ??)

    def stop(self):
        self.stopCommand()

    def getPosition(self):
        self.updateFilenumber()
        self.readout()
        return [self.cached_exptime, self.filenum]

    def asynchronousMoveTo(self, t):
        self.setCollectionTime(t)
        self.collectData()

    def getFilepath(self):
        return self.filepath
# PILATUS COMMANDS
# Note: Command appended where name already taken

    def setFilename(self, filename):
        self.pvs['Filename'].caput(filename)
        self.filename = filename

    def setFilepath(self, filepath):
        self.filepath = filepath
        self.pvs['FilePath'].caput(filepath)

    def setFileformat(self, fileformat):
        self.fileformat = fileformat
        self.pvs['FileFormat'].caput(fileformat)

    def updateFilenumber(self):
        self.filenum = float(self.pvs['FileNumber'].caget()) - 1

    def setNumberImages(self, n):
        self.pvs['NImages'].caput(n)

    def setCollectionTimeCommand(self, t):
        self.pvs['ExposureTime'].caput(t)
        sleep(1)

    def isBusyCommand(self):
        return float(self.pvs['Acquire'].caget())

    def stopCommand(self):
        self.pvs['Abort'].caput(1)

    def acquireCommand(self):
        self.pvs['Acquire'].caput(1)

    def getThresholdEnergy(self):
        print "WARNING: this method returns before the underlying hardware has been updated"
        return float(self.pvs['ThresholdEnergy'].caget())
示例#24
0
class ContinuousEnergyMoveController(ConstantVelocityMoveController,
                                     DeviceBase):
    '''Controller for constant velocity scan moving both PGM Energy and JID Gap, or DCM energy and IID gap at same time at constant speed respectively.
        It works for both Live and Dummy mode.
    '''
    def __init__(
            self,
            name,
            energy,
            idgap,
            idpvroot,
            move_mono=True,
            move_id=True):  # motors, maybe also detector to set the delay time
        self.logger = LoggerFactory.getLogger(
            "ContinuousEnergyMoveController:%s" % name)
        self.verbose = False
        self.setName(name)
        self._start_event = threading.Event()
        self._movelog_time = datetime.now()
        self._energy = energy
        #PGM
        self._mono_energy = energy.mono_energy
        self._mono_energy_speed_orig = None
        self._mono_runupdown_time = None
        #ID
        self._id_gap = idgap
        self._id_gap_speed_orig = None
        self._id_runupdown_time = None
        self.idpvs = PvManager({
            'vel': 'BLGSETVEL',
            'acc': 'IDGSETACC'
        }, idpvroot)
        if installation.isLive():
            self.idpvs.configure()

        self.mono_energy_positions = []
        self.id_gap_positions = []
        self._start_time = None

        #behaviour properties
        self._move_mono = move_mono
        self._move_id = move_id
        self.idspeedfactor = 1.0
        self.monospeedfactor = 1.0
        self.idstartdelaytime = 0.0
        self.continuousMovingStarted = False

    # Implement: public interface ConstantVelocityMoveController extends ContinuousMoveController
    def setStart(self, start):  # double
        self._move_start = start
        if self.verbose: self.logger.info('setStart(%r)' % start)

    def setEnd(self, end):  # double
        self._move_end = end
        if self.verbose: self.logger.info('setEnd(%r)' % end)

    def setStep(self, step):  # double
        self._move_step = step
        if self.verbose: self.logger.info('setStep(%r)' % step)

    # Implement: public interface ContinuousMoveController extends HardwareTriggerProvider
    def PrepareMonoForMove(self):

        if self._mono_energy.getName() == "pgmenergy":
            self.energy_scale = 1000.0  #convert energy from keV to eV
        else:
            self.energy_scale = 1.0

        self._mono_energy_speed_orig = self._mono_energy.speed  #current speed in EPICS

        ### Calculate main cruise moves & speeds from start/end/step in eV
        self._mono_energy_speed = (
            abs(self._move_end - self._move_start) * self.energy_scale /
            self.getTotalTime()) * self.getMonoSpeedFactor()

        #check speed within limits
        if self._mono_energy_speed <= 0.000 or self._mono_energy_speed > 10.0:  #eV/sec
            raise DeviceException(
                "Calculated %s speed %f is outside limits [%f, %f]!" %
                (self._mono_energy.getName(), self._mono_energy_speed, 0.000,
                 10.0))

        ### Calculate ramp distance from required speed and ramp times
        # Set the speed before we read out ramp times in case it is dependent
        self._mono_energy.speed = self._mono_energy_speed
        # Should really be / | | | | | \ not /| | | | |\
        self._mono_runupdown_time = self._mono_energy.timeToVelocity
        self._mono_runupdown = self._mono_energy_speed / 2 * self._mono_runupdown_time
        ### Move motor at full speed to start position
        self._mono_energy.speed = self._mono_energy_speed_orig
        if self.isEnergyMoveDirectionPositive():
            if self.verbose:
                self.logger.info(
                    'prepareMonoForMove: %s.asynchronousMoveTo(%r) @ %r (+ve)'
                    % (self._mono_energy.getName(),
                       (self._move_start * self.energy_scale -
                        self._mono_runupdown), self._mono_energy_speed_orig))
            self._mono_energy.asynchronousMoveTo(
                (self._move_start * self.energy_scale - self._mono_runupdown))
        else:
            if self.verbose:
                self.logger.info(
                    'prepareMonoForMove: %s.asynchronousMoveTo(%r) @ %r (-ve)'
                    % (self._mono_energy.getName(),
                       (self._energy_start * self.energy_scale +
                        self._mono_runupdown), self._mono_energy_speed_orig))
            self._mono_energy.asynchronousMoveTo(
                (self._move_start * self.energy_scale + self._mono_runupdown))

    def id_speed_limits(self):
        if self._id_gap.getName() == 'jgap':
            return JID_GAP_SPEED_LOWER_LIMIT, JID_GAP_SPEED_UPPER_LIMIT
        else:
            return IID_GAP_SPEED_LOWER_LIMIT, IID_GAP_SPEED_UPPER_LIMIT

    def PrepareIDForMove(self):
        GAP_SPEED_LOWER_LIMIT, GAP_SPEED_UPPER_LIMIT = self.id_speed_limits()

        if installation.isLive():
            #get ID gap speed from EPICS PV
            self._id_gap_speed_orig = float(self.idpvs['vel'].caget())
        else:
            self._id_gap_speed_orig = self._id_gap.speed

        #assume no row phase motors need to move during continuous energy move

        self._id_gap_start = self._energy.idgap(
            self._move_start)  #idgap calculation using energy in keV
        self._id_gap_end = self._energy.idgap(self._move_end)

        ### Calculate main cruise moves & speeds from start/end/step
        self._id_gap_speed = abs(self._id_gap_end - self._id_gap_start
                                 ) / self.getTotalTime() * self.idspeedfactor

        #check speed within limits
        if self._id_gap_speed < GAP_SPEED_LOWER_LIMIT or self._id_gap_speed > GAP_SPEED_UPPER_LIMIT:
            raise DeviceException(
                "Calculated ID gap speed %f is outside limits [%f, %f]!" %
                (self._id_gap_speed, GAP_SPEED_LOWER_LIMIT,
                 GAP_SPEED_UPPER_LIMIT))

        if installation.isLive():
            #Cannot set id_gap.speed through soft motor which in EPICS is read-only
            self.idpvs['vel'].caput(self._id_gap_speed)
        else:
            self._id_gap.speed = self._id_gap_speed

        ### Calculate ramp distance from required speed and ramp times
        #acceleration time per axis
        self._id_axis_speed = self._id_gap_speed / 2
        self._id_runupdown_time_per_axis = self._id_axis_speed * 4
        # Should really be / | | | | | \ not /| | | | |\
        self._id_runupdown_per_axis = self._id_axis_speed / 2 * self._id_runupdown_time_per_axis
        self._id_gap_runupdown = self._id_runupdown_per_axis * 2

        if installation.isLive():
            self.idpvs['vel'].caput(self._id_gap_speed_orig)
        else:
            self._id_gap.speed = self._id_gap_speed_orig

        if self.isIDGapMoveDirectionPositive():
            if self.verbose:
                self.logger.info(
                    'prepareIDForMove: _id_gap.asynchronousMoveTo(%r) @ %r (+ve)'
                    % ((self._id_gap_start - self._id_gap_runupdown),
                       self._id_gap_speed_orig))
            self._id_gap.asynchronousMoveTo(self._id_gap_start -
                                            self._id_gap_runupdown)
        else:
            if self.verbose:
                self.logger.info(
                    'prepareIDForMove: _id_gap.asynchronousMoveTo(%r) @ %r (-ve)'
                    % ((self._id_gap_start + self._id_gap_runupdown),
                       self._id_gap_speed_orig))
            self._id_gap.asynchronousMoveTo(self._id_gap_start +
                                            self._id_gap_runupdown)

    def prepareForMove(self):
        if self.verbose: self.logger.info('prepareForMove()...')
        self.continuousMovingStarted = False
        if self.isMonoMoveEnabled():
            self.PrepareMonoForMove()
        else:
            if self.verbose:
                self.logger.info('%s move is disabled in %r' %
                                 (self._mono_energy.getName(), self.getName()))

        if self.isIDMoveEnabled():
            self.PrepareIDForMove()
        else:
            if self.verbose:
                self.logger.info('ID %s move is disabled in %r' %
                                 (self._id_gap.getName(), self.getName()))

        if not self.isMonoMoveEnabled() and not self.isIDMoveEnabled():
            print("Both PGM and ID moves are disabled so no scan will occur!")
            raise DeviceException(
                "Both PGM and ID moves are disabled so no scan will occur!")

        self.waitWhileMoving()
        if self.verbose:
            self.logger.info('...prepareForMove')

    def startMove(self):
        if self.verbose: self.logger.info('startMove()...')

        # Notify all position callables to start waiting for their time
        self._start_time = datetime.now()
        self._start_event.set()
        # Start threads to start ID & PGM and at the correct times
        if self.isMonoMoveEnabled():
            self._mono_energy.speed = self._mono_energy_speed

        if self.isIDMoveEnabled():
            if installation.isLive():
                self.idpvs['vel'].caput(self._id_gap_speed)
            else:
                self._id_gap.speed = self._id_gap_speed

        if self.isMonoMoveEnabled():
            if self.isEnergyMoveDirectionPositive():
                if self.verbose:
                    self.logger.info(
                        'startMove Mono Energy: _mono_energy.asynchronousMoveTo(%r) @ %r (+ve)'
                        % ((self._move_end * self.energy_scale +
                            self._mono_runupdown), self._mono_energy_speed))
                self._mono_energy.asynchronousMoveTo(
                    (self._move_end * self.energy_scale +
                     self._mono_runupdown))
            else:
                if self.verbose:
                    self.logger.info(
                        'startMove Mono Energy: _mono_energy.asynchronousMoveTo(%r) @ %r (-ve)'
                        % ((self._move_end * self.energy_scale -
                            self._mono_runupdown), self._mono_energy_speed))
                self._mono_energy.asynchronousMoveTo(
                    (self._move_end * self.energy_scale -
                     self._mono_runupdown))

        if self.isIDMoveEnabled():
            sleep(self.getIDStartDelayTime())
            if self.isIDGapMoveDirectionPositive():
                if self.verbose:
                    self.logger.info(
                        'startMove ID Gap: _id_gap.asynchronousMoveTo(%r) @ %r (+ve)'
                        % ((self._id_gap_end + ID_GAP_END_OFFSET +
                            self._id_gap_runupdown), self._id_gap_speed))
                self._id_gap.asynchronousMoveTo(
                    (self._id_gap_end + ID_GAP_END_OFFSET +
                     self._id_gap_runupdown))
            else:
                if self.verbose:
                    self.logger.info(
                        'startMove ID Gap: _id_gap.asynchronousMoveTo(%r) @ %r (-ve)'
                        % ((self._id_gap_end - ID_GAP_END_OFFSET -
                            self._id_gap_runupdown), self._id_gap_speed))
                self._id_gap.asynchronousMoveTo(
                    (self._id_gap_end - ID_GAP_END_OFFSET -
                     self._id_gap_runupdown))

        self.continuousMovingStarted = True
        if self.verbose: self.logger.info('...startMove')

    def isMoving(self):
        if self.isIDMoveEnabled():
            if self.verbose and (datetime.now() -
                                 self._movelog_time) > timedelta(seconds=1):
                self.logger.info(
                    'isMoving() _mono_energy=%r @ %r, _id_gap=%r @ %r' %
                    (self._mono_energy.isBusy(), self._mono_energy(),
                     self._id_gap.isBusy(), self._id_gap()))
                self._movelog_time = datetime.now()
            return self._mono_energy.isBusy() or self._id_gap.isBusy()
        else:
            if self.verbose and (datetime.now() -
                                 self._movelog_time) > timedelta(seconds=1):
                self.logger.info(
                    'isMoving() _mono_energy=%r @ %r' %
                    (self._mono_energy.isBusy(), self._mono_energy()))
                self._movelog_time = datetime.now()
            return self._mono_energy.isBusy()

    def waitWhileMoving(self):
        if self.verbose: self.logger.info('waitWhileMoving()...')
        while self.isMoving():
            time.sleep(1)
        if self.verbose: self.logger.info('...waitWhileMoving()')

    def stopAndReset(self):
        if self.verbose: self.logger.info('stopAndReset()')
        self._start_time = None
        self._start_event.clear()
        if self.isMonoMoveEnabled():
            self._mono_energy.stop()
        if self.isIDMoveEnabled() and installation.isDummy():
            self._id_gap.stop()
        self._restore_orig_speed()

    # Implement: public interface HardwareTriggerProvider extends Device
    def setTriggerPeriod(self, seconds):  # double
        self._triggerPeriod = seconds
        if self.verbose: self.logger.info('setTriggerPeriod(%r)' % seconds)

    def getNumberTriggers(self):
        triggers = self.getTotalMove() / abs(self._move_step)
        if self.verbose:
            self.logger.info('getNumberTriggers()=%r (%r)' %
                             (int(triggers), triggers))
        return int(triggers)

    def getTotalTime(self):
        total_time = self.getNumberTriggers() * self._triggerPeriod
        if self.verbose: self.logger.info('getTotalTime()=%r' % total_time)
        return total_time

    def getTimeToVelocity(self):
        return self._mono_runupdown_time

    # Override: public abstract class DeviceBase implements Device, ConditionallyConfigurable, Localizable
    # None needed

    # Other functions
    def getTotalMove(self):
        total_move = abs(self._move_end - self._move_start)
        if self.verbose: self.logger.info('getTotalMove()=%r' % total_move)
        return total_move

    def isEnergyMoveDirectionPositive(self):
        return (self._move_end - self._move_start) > 0

    def isIDGapMoveDirectionPositive(self):
        return (self._id_gap_end - self._id_gap_start) > 0

    class DelayableCallable(Callable):
        def __init__(self, controller, demand_position):
            #self.start_event = threading.Event()
            self.start_event = controller._start_event
            self._controller, self._demand_position = controller, demand_position
            self.logger = LoggerFactory.getLogger(
                "ContinuousPgmEnergyIDGapMoveController:%s:DelayableCallable[%r]"
                % (controller.name, demand_position))
            if self._controller.verbose:
                self.logger.info('__init__(%r, %r)...' %
                                 (controller.name, demand_position))

        def call(self):
            if self._controller.verbose: self.logger.info('call...')
            # Wait for controller to start all motors moving and set start time
            if self._controller._start_time:
                if self._controller.verbose:
                    self.logger.info('start_time=%r' %
                                     (self._controller._start_time))
            else:
                if self._controller.verbose: self.logger.info('wait()...')
                timeout = 60
                self.start_event.wait(timeout)
                if not self.start_event.isSet():
                    raise RuntimeError(
                        "%rs timeout waiting for startMove() to be called on %s at position %r."
                        % (timeout, self._controller.name,
                           self._demand_position))
                if self._controller.verbose: self.logger.info('...wait()')
            # Wait for delay before actually move start and then a time given by
            # how far through the scan this point is

            complete = abs(
                (self._demand_position - self._controller._move_start) /
                (self._controller._move_end - self._controller._move_start))
            sleeptime_s = (self._controller._mono_runupdown_time +
                           (complete * self._controller.getTotalTime()))

            delta = datetime.now() - self._controller._start_time
            delta_s = delta.seconds + delta.microseconds / 1000000.
            if delta_s > sleeptime_s:
                self.logger.warn(
                    'Sleep time already past!!! sleeptime_s=%r, delta_s=%r, sleeptime_s-delta_s=%r'
                    % (sleeptime_s, delta_s, sleeptime_s - delta_s))
            else:
                if self._controller.verbose:
                    self.logger.info(
                        'sleeping... sleeptime_s=%r, delta_s=%r, sleeptime_s-delta_s=%r'
                        % (sleeptime_s, delta_s, sleeptime_s - delta_s))
                time.sleep(sleeptime_s - delta_s)

            energy = self._controller._mono_energy()

            if self._controller.verbose:
                self.logger.info('...DelayableCallable:call returning %r, %r' %
                                 (self._demand_position, energy))
            return self._demand_position, energy

    def getPositionCallableExtraNames(self):
        return ['readback']

    def getPositionCallableFormat(self):
        return ['%f', '%f']

    # public Callable<T> getPositionCallable() throws DeviceException;
    def getPositionCallableFor(self, position):
        if self.verbose:
            self.logger.info('getPositionCallableFor(%r)...' % position)
        return self.DelayableCallable(self, position)

    def _restore_orig_speed(self):
        if self.isMonoMoveEnabled() and self._mono_energy_speed_orig:
            if self.verbose:
                self.logger.info(
                    'Restoring original PGM Energy speed %r, was %r' %
                    (self._mono_energy_speed_orig, self._mono_energy.speed))
            self._mono_energy.speed = self._mono_energy_speed_orig
            self._mono_energy_speed_orig = None
        if self.isIDMoveEnabled() and self._id_gap_speed_orig:
            if installation.isLive():
                if self.verbose:
                    self.logger.info(
                        'Restoring original ID gap speed %r, was %r' %
                        (self._id_gap_speed_orig, self.idpvs['vel'].caget()))
                self.idpvs['vel'].caput(self._id_gap_speed_orig)
            else:
                if self.verbose:
                    self.logger.info(
                        'Restoring original ID gap speed %r, was %r' %
                        (self._id_gap_speed_orig, self._id_gap.speed))
                self._id_gap.speed = self._id_gap_speed_orig
            self._id_gap_speed_orig = None

    def atScanEnd(self):
        if self.verbose: self.logger.info('atScanEnd()...')
        self._restore_orig_speed()
        # Should we also move the pgm_energy to a known value too, such as the midpoint?

    def setIDStartDelayTime(self, t):
        self.idstartdelaytime = t

    def getIDStartDelayTime(self):
        return self.idstartdelaytime

    def setIDSpeedFactor(self, val):
        self.idspeedfactor = val

    def getIDSpeedFactor(self):
        return self.idspeedfactor

    def setMonoSpeedFactor(self, val):
        self.monospeedfactor = val

    def getMonoSpeedFactor(self):
        return self.monospeedfactor

    #https://jira.diamond.ac.uk/browse/I10-301
    def enableIDMove(self):
        self._move_id = True

    def disableIDMove(self):
        self._move_id = False

    def isIDMoveEnabled(self):
        return self._move_id

    def enableMonoMove(self):
        self._move_mono = True

    def disableMonoMove(self):
        self._move_mono = False

    def isMonoMoveEnabled(self):
        return self._move_mono
示例#25
0
class EpicsFirewireCamera(PseudoDetector):

    #TODO: Known bug: only works when epics zoom turned off (read the zoom value)
    def __init__(self,
                 name,
                 pvroot,
                 filepath=None,
                 determine_data_pv_based_on_zoom=False,
                 numtracker_extension='tmp',
                 filename_template='fire%d_%05d.png'):
        # BL07I-DI-PHDGN-06:CAM:DATA
        self.determine_data_pv_based_on_zoom = determine_data_pv_based_on_zoom

        self.name = name
        self.extraNames = []
        self.outputFormat = []
        self.level = 9

        self.pvs = PvManager(['SET_SHUTTR', 'WIDTH', 'HEIGHT', 'ZOOM'], pvroot)
        self.pv_data = []
        self.pv_data.append(
            gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot + 'DATA'))
        self.pv_data.append(
            gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot +
                                                              'DATA1'))
        self.pv_data.append(
            gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot +
                                                              'DATA2'))
        self.pv_data.append(
            gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot +
                                                              'DATA3'))
        self.pv_data.append(
            gda.epics.LazyPVFactory.newReadOnlyIntegerArrayPV(pvroot +
                                                              'DATA4'))
        self.pvs.configure()

        self.filepath = filepath
        self.ds = None
        self.last_image_path = None
        self.last_filename = None
        self.last_image_number = 0
        self.numtracker_extension = numtracker_extension
        self.filename_template = filename_template

    def createsOwnFiles(self):
        return False

    def setCollectionTime(self, t):
        self.pvs['SET_SHUTTR'].caput(int(t))

    def getCollectionTime(self):
        return float(self.pvs['SET_SHUTTR'].caget())

    def prepareForCollection(self):
        self.last_image_number = -1

    def collectData(self):
        #rawdata = self.pvs['DATA'].cagetArray()
        if self.determine_data_pv_based_on_zoom:
            zoom_ordinal = int(float(self.pvs['ZOOM'].caget()))
            rawdata = self.pv_data[zoom_ordinal].get()
        else:
            rawdata = self.pv_data[0].get()
        data = map(unsign2, rawdata)
        self.ds = DatasetFactory.zeros(int(float(self.pvs['HEIGHT'].caget())),
                                       int(float(self.pvs['WIDTH'].caget())),
                                       data)
        self.last_image_number += 1
        self.last_filename = self._generateCurrentFilename()
        if self.filepath is not None:
            self.saveImage(self.last_filename)

    def _getCurrentScanNumer(self):
        return NumTracker(self.numtracker_extension).getCurrentFileNumber()

    def _generateCurrentFilename(self):
        if isScanRunning():
            return self.filename_template % (self._getCurrentScanNumer(),
                                             self.last_image_number)
        else:
            return time.strftime("%Y%m%d%H%M%S", time.localtime()) + '%03d' % (
                (time.time() % 1) * 1000) + '.png'

    def getStatus(self):
        return IDLE

    def readout(self):
        if self.ds is None:
            raise Exception(
                "Epics Firewire Camera %s has not acquired an image" %
                self.name)
        else:
            return self.ds

    def setFilepath(self, filepath):
        self.filepath = filepath

    def getFilepath(self):
        return self.filepath

    def getLastImagePath(self):
        return self.last_image_path

    def saveImage(self, filename):
        path = self.filepath + filename
        if self.ds is None:
            raise Exception(
                "Epics Firewire Camera %s has not acquired an image" %
                self.name)
        else:
            sfh = ScanFileHolder()
            sfh.addDataSet("Image", self.ds)
            sfh.save(PNGSaver(path))
            self.last_image_path = path