class Counter(Saveable): """simple scan counter object -- a value that will be counted at each point in the scan""" def __init__(self, pvname, label=None, units=''): Saveable.__init__(self, pvname, label=label, units=units) self.pv = PV(pvname) if label is None: label = pvname self.label = label self.units = units self.clear() def __repr__(self): return "<Counter %s (%s)>" % (self.label, self.pv.pvname) def read(self, **kws): val = self.pv.get(**kws) self.buff.append(val) return val def clear(self): self.buff = [] def get_buffers(self): return {self.label: self.buff}
class Xspress3Trigger(Trigger): """Triggers for Xspress3 + MCS, a detector combination without a proper Busy record to use as a Trigger. This requires a 'stop' method (that is not None) as for Xspress3, which does not have a real Busy record for a trigger. """ def __init__(self, prefix, mcs=None, value=1, label=None, **kws): Trigger.__init__(self, prefix, label=label, value=value, mcs=mcs, **kws) self.xsp3_start = PV(prefix + 'Acquire') self.xsp3_erase = PV(prefix + 'ERASE') self.xsp3_ison = PV(prefix + 'Acquire_RBV') self.xsp3_update = PV(prefix + 'UPDATE') self.mcs_start = PV(mcs + 'EraseStart') self.prefix = prefix self.mcs_prefix = mcs self._val = value self.done = False self._t0 = 0 self.runtime = -1 def __repr__(self): return "<Xspress3Trigger(%s, mcs=%s)>" % (self.prefix, self.mcs_prefix) def __onComplete(self, pvname=None, **kws): self.xsp3_start.put(0) time.sleep(0.025) self.xsp3_update.put(1) self.done = True self.runtime = time.time() - self._t0 def start(self, value=None): """triggers MCS in internal mode to trigger Xspress3""" self.done = False runtime = -1 self._t0 = time.time() self.xsp3_erase.put(1) if value is None: value = self._val self.xsp3_start.put(value) time.sleep(0.010) count = 0 while self.xsp3_ison.get() != 1 and count < 100: time.sleep(0.010) self.mcs_start.put(1, callback=self.__onComplete) time.sleep(0.001) poll()
class Positioner(Saveable): """a positioner for a scan This sets an ordinate value for scan. Not that it does *NOT* implay a readback on this position -- add a Counter for that! """ def __init__(self, pvname, label=None, array=None, units=None, extra_pvs=None, **kws): Saveable.__init__(self, pvname, label=label, units=units, array=array, extra_pvs=extra_pvs, **kws) if isinstance(pvname, PV): self.pv = pvname else: self.pv = PV(pvname) self.pv.connect() self.units = units if self.pv.connected: self.pv.get_ctrlvars() if units is None: self.units = self.pv.units self.label = label if label is None and self.pv.connected: desc = pvname if '.' in pvname: idot = pvname.index('.') descpv = pvname[:idot] + '.DESC' else: descpv = pvname + '.DESC' try: desc = caget(descpv) except: pass self.label = desc if array is None: array = [] self.array = array if extra_pvs is None: extra_pvs = {} self.extra_pvs = extra_pvs def __repr__(self): out = "<Positioner '%s'" % (self.pv.pvname) if len(self.array) > 0: npts = len(self.array) amin = '%g' % (min(self.array)) amax = '%g' % (max(self.array)) out = "%s: %i points, min/max: [%s, %s]" % (out, npts, amin, amax) return "%s>" % out def __onComplete(self, pvname=None, **kws): self.done = True def set_array(self, start, stop, npts): """set positioner array with start/stop/step/npts""" self.array = np.linspace(start, stop, npts) def move_to_start(self, wait=False): """ move to starting position""" return self.move_to_pos(0, wait=wait) def current(self): "return current position" return self.pv.get() def verify_array(self): """return True if array is within the """ array = self.array if array is None: return True if self.pv.upper_ctrl_limit == self.pv.lower_ctrl_limit: return True if ((self.pv.upper_ctrl_limit is not None and self.pv.upper_ctrl_limit < max(array)) or (self.pv.lower_ctrl_limit is not None and self.pv.lower_ctrl_limit > min(array))): return False return True def move_to(self, value, wait=False, timeout=600): """move to a value, optionally waiting""" self.pv.put(value, wait=wait, timeout=timeout) def move_to_pos(self, i, wait=False, timeout=600): """move to i-th position in positioner array""" if self.array is None or not self.pv.connected: return self.done = False self.pv.put(self.array[i], callback=self.__onComplete) time.sleep(1.e-4) if wait: t0 = time.time() while not self.done and time.time()-t0 < timeout: time.sleep(1.e-4) def pre_scan(self, **kws): "method to run prior to scan: override for real action" pass def post_scan(self, **kws): "method to run after to scan: override for real action" pass def at_break(self, breakpoint=None, **kws): "method to run at break points: override for real action" pass