def __init__(self, name, pgm_grat_pitch, pgm_mirr_pitch, pgmpvroot, energy, idupvroot, iddpvroot, 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.setName(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.energy = energy self.idd = energy.idd self.idu = energy.idu self._id_gap_speed_orig=None self._id_runupdown_time = None self.idupvs = PvManager({'vel':'BLGSETVEL', 'acc':'IDGSETACC'}, idupvroot) if installation.isLive(): self.idupvs.configure() self.iddpvs = PvManager({'vel':'BLGSETVEL', 'acc':'IDGSETACC'}, iddpvroot) if installation.isLive(): self.iddpvs.configure() self.grating_pitch_positions=[] self.mirror_pitch_positions=[] self.pgm_energy_positions=[] self._start_time = None self.idspeedfactor=1.0 self.pgmspeedfactor=1.0 self.idstartdelaytime=0.0 self._move_start = 0.0 self._move_end = 1.0 self._move_step = 0.1 self._triggerPeriod = 0.0 self.idcontrols = None self.continuousMovingStarted = False
def prepareID(self, idcontrols, idpvs): if installation.isLive(): self._id_gap_speed_orig = float(idpvs['vel'].caget()) else: self._id_gap_speed_orig = idcontrols['gap'].speed # Calculate the energy midpoint energy_midpoint = (self._move_end + self._move_start) / 2. if self.verbose: self.logger.info('prepareID: energy_midpoint = %r ' % (energy_midpoint)) # Calculate phase position for current X-ray source and polarisation at energy midpoint gap_midpoint, phase_midpoint = self.energy.get_ID_gap_phase_at_current_source_polarisation(energy_midpoint) # @UnusedVariable # Calculate ID gap at start energy and end energy for current X-ray source and polarisation self._id_gap_start, phase_start = self.energy.get_ID_gap_phase_at_current_source_polarisation(self._move_start) # @UnusedVariable self._id_gap_end, phase_end = self.energy.get_ID_gap_phase_at_current_source_polarisation(self._move_end) # @UnusedVariable ### Calculate main cruise move speed from start/end/step self._id_gap_speed = abs(self._id_gap_end - self._id_gap_start) / self.getTotalTime()*self.idspeedfactor ### Calculate ramp distance from required speed and ramp times # check to ensure speed within limits if self._id_gap_speed<0.004 or self._id_gap_speed>1.0: raise ValueError("Calculated ID gap speed %f is outside limits [%f, %f]!" % (self._id_gap_speed, 0.004, 1.0)) if installation.isLive(): # Cannot set id_gap.speed through soft motor which in EPICS is read-only idpvs['vel'].caput(self._id_gap_speed) else: idcontrols['gap'].speed = self._id_gap_speed #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 ### Move motor at full speed to start position if installation.isLive(): idpvs['vel'].caput(self._id_gap_speed_orig) else: idcontrols['gap'].speed = self._id_gap_speed_orig if self.getIDGapMoveDirectionPositive(): if self.verbose: self.logger.info('prepareID:move_id_to_positions([%s, %f, %f, %s]) @ %r mm/sec (+ve)' % (self.energy.source.getPosition(), (self._id_gap_start - self._id_gap_runupdown), phase_midpoint, self.energy.polarisation, self._id_gap_speed_orig)) self.energy.move_id_to_positions(idcontrols, self._id_gap_start - self._id_gap_runupdown, phase_midpoint, self.energy.polarisation) else: if self.verbose: self.logger.info('prepareID:move_id_to_positions([%s, %f, %f, %s]) @ %r mm/sec (-ve)' % (self.energy.source.getPosition(), (self._id_gap_start + self._id_gap_runupdown), phase_midpoint, self.energy.polarisation, self._id_gap_speed_orig)) self.energy.move_id_to_positions(idcontrols, self._id_gap_start + self._id_gap_runupdown, phase_midpoint, self.energy.polarisation)
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 __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()
def configure(self): if installation.isLive(): self.pv_waveform.configure() self.pv_count.configure() else: self.logger.info("DUMMY mode: pv_count at configure() is %r" % self.pv_count)
def erase_and_start(self): if self.verbose: self.logger.info("%s %s" % (self.name, 'erase_and_start()...')) if installation.isLive(): self.pv_stop.caput(1) # scaler won't start if already running if self.channelAdvanceInternalNotExternal: self.pv_dwell.caput( TIMEOUT, self.exposure_time ) # Set the exposure time per nominal position self.pv_channeladvance.caput(TIMEOUT, self.channelAdvanceInternal) self.pv_presetReal.caput( (self.number_of_positions * self.exposure_time) + self.exposure_time_offset) # Set the total capture time else: self.pv_channeladvance.caput(TIMEOUT, self.channelAdvanceExternal) self.pv_erasestart.caput(TIMEOUT, 1) else: #Scaler not used in Dummy mode pass # Since the mca NORD value could take some time to be updated and will continue returning the NORD of the last acquire, # wait before setting started to True, so WaveformChannelPollingInputStream doesn't try to use stale data. startedTimer = Timer( 1.5, self._delayed_start_complete) # Failed at 0.5s, Ok at 1.5s. startedTimer.start() if self.verbose: self.logger.info("%s %s" % (self.name, '...erase_and_start()'))
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 erase_and_start(self): if self.verbose: self.logger.info("%s %s" % (self.name, 'erase_and_start()...')) if installation.isLive(): self.pv_erasestart.caput(1) self.started = True if self.verbose: self.logger.info("%s %s" % (self.name, '...erase_and_start()'))
def read(self, max_to_read_in_one_go): if self.verbose: self.logger.info('read(%r)... elements_read=%r' % (max_to_read_in_one_go, self.elements_read)) if self.hardwareTriggerProvider is None: self.hardwareTriggerProvider = self._controller.getHardwareTriggerProvider( ) if installation.isLive(): new_available = self._waitForNewElements() all_data = self.pv_waveform.cagetArrayDouble(self.elements_read + new_available) else: if self.hardwareTriggerProvider._start_time is not None and not self.startTimeSet: self.start_time = time.time() self.startTimeSet = True new_available = self._waitForNewElements() if self.channel in ['GRT:PITCH:', 'MIR:PITCH:', 'PGM:ENERGY:']: if self.channel == 'GRT:PITCH:': # print "%s waveform is %r" % (self.channel, self.hardwareTriggerProvider.grating_pitch_positions) all_data = self.hardwareTriggerProvider.grating_pitch_positions[: self . elements_read + new_available] elif self.channel == 'MIR:PITCH:': # print "%s waveform is %r" % (self.channel, self.hardwareTriggerProvider.mirror_pitch_positions) all_data = self.hardwareTriggerProvider.mirror_pitch_positions[: self . elements_read + new_available] elif self.channel == 'PGM:ENERGY:': # print "%s waveform is %r" % (self.channel, self.hardwareTriggerProvider.pgm_energy_positions) all_data = self.hardwareTriggerProvider.pgm_energy_positions[: self . elements_read + new_available] else: all_data = self.pv_waveform.generateData( self.channel, self.elements_read + new_available) self.logger.debug("DUMMY mode: generate %r elements" % (new_available)) new_data = all_data[self.elements_read:self.elements_read + new_available] self.elements_read += new_available if self.verbose: self.logger.info('...read() all_data[0:6] = %r' % (all_data[0:6])) if self.verbose: self.logger.info( '...read() (elements_read=%r) new data = %r' % (self.elements_read, java.util.Vector([self.type(el) for el in new_data]))) return java.util.Vector([self.type(el) for el in new_data])
def getChannelInputStreamCAClients(self, channel_pv_suffix): if installation.isLive(): pv_waveform = CAClient(self.binpoint_root_pv + channel_pv_suffix + 'BINPOINT') pv_count = CAClient(self.binpoint_root_pv + channel_pv_suffix + 'BINPOINT:NLAST.B') else: pv_waveform = [] pv_count = self.number_of_positions return pv_waveform, pv_count
def stop(self): if self.verbose: self.logger.info("%s %s" % (self.name, 'stop()...')) if installation.isLive(): self.pv_stop.caput(1) else: #MCA not available in Dummy mode pass if self.stream: self.stream.stop() # stop waveform polling stream. self.started = False if self.verbose: self.logger.info("%s %s" % (self.name, '...stop()'))
def stop(self): if self.verbose: self.logger.info("%s %s" % (self.name, 'stop()...')) if installation.isLive(): self.pv_stop.caput(1) else: #MCA not available in Dummy mode pass if self.stream: self.stream.stop( ) # enable stop the element polling loop when stop is called. self.started = False if self.verbose: self.logger.info("%s %s" % (self.name, '...stop()'))
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) else: self._id_gap.speed = self._id_gap_speed 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(): sleep(self.getIDStartDelayTime()) 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 configure(self): if self.verbose: self.logger.info("%s %s" % (self.name, 'configure()...')) if installation.isLive(): self.pv_stop.configure() self.pv_dwell.configure() self.pv_channeladvance.configure() self.pv_presetReal.configure() self.pv_erasestart.configure() else: if self.verbose: self.logger.info("configure '%s' for dummy operation...')" % (countTimer.getName()))
def getChannelInputStreamCAClients(self, channel): if installation.isLive(): pv_waveform = CAClient(self.mca_root_pv + 'mca' + ` channel `) pv_count = CAClient(self.mca_root_pv + 'mca' + ` channel ` + '.NORD') else: waveform = WaveformDataGenerator() waveform.useGaussian = True if waveform.useGaussian and waveform.gaussian is None: waveform.initializeGaussian() waveform.data = [] waveform.channel = channel pv_waveform = waveform pv_count = self.number_of_positions return pv_waveform, pv_count
def read(self, max_to_read_in_one_go): if self.verbose: self.logger.info('read(%r)... elements_read=%r' % (max_to_read_in_one_go, self.elements_read)) if self.hardwareTriggerProvider is None: self.hardwareTriggerProvider = self._controller.getHardwareTriggerProvider( ) new_available = self._waitForNewElements() if installation.isLive() and new_available is not None: all_data = self.pv_waveform.cagetArrayDouble(self.elements_read + new_available) else: if self.channel in ['B1:', 'B2:', 'B4:', 'B5:' ] and new_available is not None: if self.channel in ['B2:', 'B5:']: all_data = self.hardwareTriggerProvider.id_gap_positions[: self . elements_read + new_available] elif self.channel in ['B1:', 'B4:']: all_data = self.hardwareTriggerProvider.mono_energy_positions[: self . elements_read + new_available] else: all_data = self.pv_waveform.generateData( self.channel, self.elements_read + new_available) self.logger.debug("DUMMY mode: generate %r elements" % (new_available)) new_data = all_data[self.elements_read:self.elements_read + new_available] self.elements_read += new_available if self.verbose: self.logger.info('...read() all_data[0:6] = %r' % (all_data[0:6])) if self.verbose: self.logger.info( '...read() (elements_read=%r) new data = %r' % (self.elements_read, java.util.Vector([self.type(el) for el in new_data]))) return java.util.Vector([self.type(el) for el in new_data])
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
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 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 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 _waitForNewElements(self): """return the number of new elements available, polling until some are""" #if self.verbose: self.logger.info('_waitForNewElements()... elements_read=%r' % (self.elements_read)) acquiring_old = self._controller.getChannelInputStreamAcquiring() exposure_time = self._controller.getExposureTime() sleep_time = exposure_time if exposure_time > 0.2 else 0.2 log_timeout = exposure_time + 5 log_time = last_element_time = datetime.now() new_element_timeout = exposure_time + 20.0 while True and not self.stoppedExplicitly: if installation.isLive(): elements_available = int(float(self.pv_count.caget())) from scannable.waveform_channel.BinpointWaveformChannelController import BinpointWaveformChannelController if isinstance(self._controller, BinpointWaveformChannelController): elements_available = elements_available + 1 #BINPOINT:NLAST.B index starts at 0, -1 is waveform empty else: self.logger.info( "DUMMY mode: number of positions set in WaveformChannelScannable to its controller is %r" % self._controller.number_of_positions) #the following line does not ensure cvscan complete 100% #elements_available = sum(x<=float(self.hardwareTriggerProvider._pgm_grat_pitch.getPosition()/1000.0) for x in self.hardwareTriggerProvider.grating_pitch_positions) if not self.startTimeSet: elements_available = int( self._controller.number_of_positions) else: elapsedTime = time.time() - self.start_time if elapsedTime < self._controller.getHardwareTriggerProvider( ).getTotalTime(): elements_available = int( self._controller.number_of_positions * elapsedTime / self._controller. getHardwareTriggerProvider().getTotalTime()) else: elements_available = int( self._controller.number_of_positions) #print "self.elements_read = %d" % self.elements_read #print "element_available = %d" % elements_available # check continuous move started then poll the data so far acquiring = self._controller.getChannelInputStreamAcquiring() if acquiring: if acquiring_old <> acquiring: self.logger.info( '_waitForNewElements() elements_available=%r, elements_read=%r, acquiring now %r, was %r' % (elements_available, self.elements_read, acquiring, acquiring_old)) acquiring_old = acquiring last_element_time = log_time = datetime.now() if elements_available > self.elements_read: last_element_time = log_time = datetime.now() if self.verbose: self.logger.info( '_waitForNewElements() elements_available=%r, elements_read=%r, acquiring %r, %r new_elements available' % (elements_available, self.elements_read, acquiring, elements_available - self.elements_read)) return elements_available - self.elements_read elif (datetime.now() - last_element_time) > timedelta( seconds=new_element_timeout): self.logger.error( "_waitForNewElements() no new elements for %r seconds, raising an exception..." % new_element_timeout) raise NoSuchElementException( "no new elements for %r seconds" % new_element_timeout) if self.verbose and (datetime.now() - log_time) > timedelta(seconds=log_timeout): self.logger.info( '_waitForNewElements() elements_available=%r, elements_read=%r, acquiring %r, no new elements for %r seconds!' % (elements_available, self.elements_read, acquiring, log_timeout)) log_time = datetime.now() if elements_available == self.elements_read and self.elements_read == self._controller.number_of_positions: self.logger.info( '_waitForNewElements() elements_available=%r, elements_read=%r, number_of_positions_expected=%r, Data collection should finish now!' % (elements_available, self.elements_read, self._controller.number_of_positions)) self.stop( ) #all elements are already read, so this thread can stop time.sleep(sleep_time)
def configure(self): if self.verbose: self.logger.info("%s %s" % (self.name, 'configure()...')) if installation.isLive(): self.pv_erasestart.configure()
def _waitForNewElements(self): """return the number of new elements available, polling until some are""" #if self.verbose: self.logger.info('_waitForNewElements()... elements_read=%r' % (self.elements_read)) acquiring_old = self._controller.getChannelInputStreamAcquiring() exposure_time = self._controller.getExposureTime() sleep_time = exposure_time if exposure_time > 0.2 else 0.2 log_timeout = exposure_time + 5 log_time = last_element_time = datetime.now() new_element_timeout = exposure_time + 5.0 # it takes about 200 second to complete a full range move of pgm_grit_pitch. while True and not self.stoppedExplicitly: if installation.isLive(): elements_available = int(float(self.pv_count.caget())) else: self.logger.info( "DUMMY mode: number of positions set in WaveformChannelScannable to its controller is %r" % self._controller.number_of_positions) elements_available = sum( x <= float( self.hardwareTriggerProvider._energy.getPosition()) for x in self.hardwareTriggerProvider.mono_energy_positions) # Some waveform PVs keep returning old data for a short time even after a new acq is started and even retain the old count # for some time after the new acq has started, so check with the controller before trusting the count # check continuous move started then poll the data so far acquiring = self._controller.getChannelInputStreamAcquiring() if acquiring: if acquiring_old <> acquiring: self.logger.info( '_waitForNewElements() elements_available=%r, elements_read=%r, acquiring now %r, was %r' % (elements_available, self.elements_read, acquiring, acquiring_old)) acquiring_old = acquiring last_element_time = log_time = datetime.now() if elements_available > self.elements_read: last_element_time = log_time = datetime.now() if self.verbose: self.logger.info( '_waitForNewElements() elements_available=%r, elements_read=%r, acquiring %r, %r new_elements available' % (elements_available, self.elements_read, acquiring, elements_available - self.elements_read)) return elements_available - self.elements_read elif (datetime.now() - last_element_time) > timedelta( seconds=new_element_timeout): self.logger.error( "_waitForNewElements() no new elements for %r seconds, raising an exception..." % new_element_timeout) raise NoSuchElementException( "no new elements for %r seconds" % new_element_timeout) if self.verbose and (datetime.now() - log_time) > timedelta(seconds=log_timeout): self.logger.info( '_waitForNewElements() elements_available=%r, elements_read=%r, acquiring %r, no new elements for %r seconds!' % (elements_available, self.elements_read, acquiring, log_timeout)) log_time = datetime.now() if elements_available == self.elements_read and self.elements_read == self._controller.number_of_positions: self.logger.info( '_waitForNewElements() elements_available=%r, elements_read=%r, number_of_positions_expected=%r, Data collection should finish now!' % (elements_available, self.elements_read, self._controller.number_of_positions)) self.stop( ) #all elements are already read, so this thread can stop time.sleep(sleep_time)
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 stop(self): self.mono_energy.stop() if installation.isLive(): print("ID motion stop is not supported according to ID-Group instruction. Please wait for the Gap motion to complete!") else: self.idscannable.stop()
findpeak = FindScanPeak findcentroid = FindScanCentroid from gdascripts.scan.installStandardScansWithProcessing import * #@UnusedWildImport scan_processor.rootNamespaceDict = globals() ############################################################################### ### Configure camera bases ### ############################################################################### from pseudodevices.CameraExposureChanger import CameraExposureChanger print "\nCreating camera exposure object ('sd1_camera_exposure')for SD1 camera" sd1_camera_exposure = CameraExposureChanger(sd1_cam) if installation.isLive(): print "\nCreating camera exposure object ('sd3_camera_exposure')for SD3 camera" sd3_camera_exposure = PVScannable("sd3_camera_exposure", "BL09J-MO-SD-03:CAM:AcquireTime") sd3_camera_exposure.configure() print "\nCreating camera exposure object ('xbpm_camera_exposure')for XBPM camera" xbpm_camera_exposure = PVScannable("xbpm_camera_exposure", "BL09I-EA-XBPM-01:CAM:AcquireTime") xbpm_camera_exposure.configure() else: print "\nCreating camera exposure object ('sd3_camera_exposure')for SD3 camera" sd3_camera_exposure = CameraExposureChanger(sd3_cam) ############################################################################### ### Configure scannable output formats ###
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)