class ScalerDetector(DetectorMixin): trigger_suffix = '.CNT' def __init__(self, prefix, nchan=8, use_calc=True, **kws): DetectorMixin.__init__(self, prefix, **kws) nchan = int(nchan) self.scaler = Scaler(prefix, nchan=nchan) self._counter = ScalerCounter(prefix, nchan=nchan, use_calc=use_calc) self.dwelltime_pv = PV('%s.TP' % prefix) self.dwelltime = None self.counters = self._counter.counters self.extra_pvs = [('Scaler.frequency', '%s.FREQ' % prefix), ('Scaler.read_delay', '%s.DLY' % prefix)] self._repr_extra = ', nchans=%i, use_calc=%s' % (nchan, repr(use_calc)) self.extra_pvs.extend(self._counter.extra_pvs) def pre_scan(self, scan=None, **kws): self.scaler.OneShotMode() if (self.dwelltime is not None and isinstance(self.dwelltime_pv, PV)): self.dwelltime_pv.put(self.dwelltime) def post_scan(self, **kws): self.scaler.AutoCountMode()
class MultiMcaDetector(DetectorMixin): trigger_suffix = "EraseStart" collect_mode = "CollectMode" repr_fmt = ", nmcas=%i, nrois=%i, use_net=%s, use_full=%s" def __init__( self, prefix, label=None, nmcas=4, nrois=32, search_all=False, use_net=False, use=True, use_unlabeled=False, use_full=False, **kws ): DetectorMixin.__init__(self, prefix, label=label) nmcas, nrois = int(nmcas), int(nrois) if not prefix.endswith(":"): prefix = "%s:" % prefix self.prefix = prefix self.dwelltime_pv = PV("%sPresetReal" % prefix) self.trigger = Trigger("%sEraseStart" % prefix) self.dwelltime = None self.extra_pvs = None self._counter = None self._connect_args = dict( nmcas=nmcas, nrois=nrois, search_all=search_all, use_net=use_net, use_unlabeled=use_unlabeled, use_full=use_full, ) self._repr_extra = self.repr_fmt % (nmcas, nrois, repr(use_net), repr(use_full)) def connect_counters(self): self._counter = MultiMcaCounter(self.prefix, **self._connect_args) self.counters = self._counter.counters self.extra_pvs = self._counter.extra_pvs def pre_scan(self, scan=None, **kws): if self._counter is None: self.connect_counters() if self.dwelltime is not None and isinstance(self.dwelltime_pv, PV): self.dwelltime_pv.put(self.dwelltime) caput("%sCollectMode" % (self.prefix), 0) # mca spectra caput("%sPresetMode" % (self.prefix), 1) # real time caput("%sReadBaselineHistograms.SCAN" % (self.prefix), 0) caput("%sReadTraces.SCAN" % (self.prefix), 0) caput("%sReadLLParams.SCAN" % (self.prefix), 0) caput("%sReadAll.SCAN" % (self.prefix), 9) caput("%sStatusAll.SCAN" % (self.prefix), 9)
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 __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
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}
def __init__( self, prefix, label=None, nmcas=4, nrois=32, search_all=False, use_net=False, use=True, use_unlabeled=False, use_full=False, **kws ): DetectorMixin.__init__(self, prefix, label=label) nmcas, nrois = int(nmcas), int(nrois) if not prefix.endswith(":"): prefix = "%s:" % prefix self.prefix = prefix self.dwelltime_pv = PV("%sPresetReal" % prefix) self.trigger = Trigger("%sEraseStart" % prefix) self.dwelltime = None self.extra_pvs = None self._counter = None self._connect_args = dict( nmcas=nmcas, nrois=nrois, search_all=search_all, use_net=use_net, use_unlabeled=use_unlabeled, use_full=use_full, ) self._repr_extra = self.repr_fmt % (nmcas, nrois, repr(use_net), repr(use_full))
def __init__(self, pvname, value=1, label=None, **kws): Saveable.__init__(self, pvname, label=label, value=value, **kws) self.pv = PV(pvname) self._val = value self.done = False self._t0 = 0 self.runtime = -1
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()
class Trigger(Saveable): """Detector Trigger for a scan. The interface is: trig = Trigger(pvname, value=1) defines a trigger PV and trigger value trig.start(value=None) starts the trigger (value will override value set on creation) trig.done True if the start has completed. trig.runtime time for last .start() to complete Example usage: trig = ScanTrigger(pvname) trig.start() while not trig.done: time.sleep(1.e-4) <read detector data> """ def __init__(self, pvname, value=1, label=None, **kws): Saveable.__init__(self, pvname, label=label, value=value, **kws) self.pv = PV(pvname) self._val = value self.done = False self._t0 = 0 self.runtime = -1 self.stop = None def __repr__(self): return "<Trigger (%s)>" % (self.pv.pvname) def __onComplete(self, pvname=None, **kws): self.done = True self.runtime = time.time() - self._t0 def start(self, value=1): """triggers detector""" self.done = False self.runtime = -1 self._t0 = time.time() if value is None: value = self._val self.pv.put(value, callback=self.__onComplete) time.sleep(0.001) poll()
class McaDetector(DetectorMixin): trigger_suffix = "EraseStart" repr_fmt = ", nrois=%i, use_net=%s, use_full=%s" def __init__(self, prefix, save_spectra=True, nrois=32, use_net=False, use_full=False, **kws): nrois = int(nrois) DetectorMixin.__init__(self, prefix, **kws) self.mca = MCA(prefix) self.dwelltime_pv = PV("%s.PRTM" % prefix) self.dwelltime = None self.trigger = Trigger("%sEraseStart" % prefix) self._counter = McaCounter(prefix, nrois=nrois, use_full=use_full, use_net=use_net) self.counters = self._counter.counters self._repr_extra = self.repr_fmt % (nrois, repr(use_net), repr(use_full)) def pre_scan(self, scan=None, **kws): if self.dwelltime is not None and isinstance(self.dwelltime_pv, PV): self.dwelltime_pv.put(self.dwelltime)
def __init__(self, prefix, save_spectra=True, nrois=32, use_net=False, use_full=False, **kws): nrois = int(nrois) DetectorMixin.__init__(self, prefix, **kws) self.mca = MCA(prefix) self.dwelltime_pv = PV("%s.PRTM" % prefix) self.dwelltime = None self.trigger = Trigger("%sEraseStart" % prefix) self._counter = McaCounter(prefix, nrois=nrois, use_full=use_full, use_net=use_net) self.counters = self._counter.counters self._repr_extra = self.repr_fmt % (nrois, repr(use_net), repr(use_full))
class AreaDetector(DetectorMixin): """very simple area detector interface... trigger / dwelltime, uses array counter as only counter """ trigger_suffix = 'Acquire' def __init__(self, prefix, file_plugin=None, **kws): if not prefix.endswith(':'): prefix = "%s:" % prefix DetectorMixin.__init__(self, prefix, **kws) self.dwelltime_pv = PV('%scam1:AcquireTime' % prefix) self.dwelltime = None self.file_plugin = None self.counters = [Counter("%scam1:ArrayCounter_RBV" % prefix, label='Image Counter')] if file_plugin in AD_FILE_PLUGINS: self.file_plugin = file_plugin f_counter = Counter("%s%s:FileNumebr_RBV" % (prefix, file_plugin), label='File Counter') self.counters.append(f_counter) self._repr_extra = ', file_plugin=%s' % repr(file_plugin) def pre_scan(self, scan=None, **kws): if (self.dwelltime is not None and isinstance(self.dwelltime_pv, PV)): self.dwelltime_pv.put(self.dwelltime) caput("%scam1:ImageMode" % (self.prefix), 0) # single image capture caput("%scam1:ArrayCallbacks" % (self.prefix), 1) # enable callbacks if self.file_plugin is not None: fpre = "%s%s" % (sself.prefix, self.file_plugin) pref = scan.filename.replace('.', '_') ext = self.file_plugin[:-1] caput("%s:FileName" % fpre, pref) caput("%s:FileTemplate" % fpre, '%%s%%s_%%4.4d.%s' % ext) caput("%s:EnableCallbacks" % fpre, 1) caput("%s:AutoIncrement" % fpre, 1) caput("%s:AutoSave" % fpre, 1) def post_scan(self, **kws): if self.file_plugin is not None: fpre = "%s%s" % (sself.prefix, self.file_plugin) caput("%s:EnableCallbacks" % fpre, 0) caput("%s:AutoSave" % fpre, 0)
def __init__(self, prefix, nchan=8, use_calc=True, **kws): DetectorMixin.__init__(self, prefix, **kws) nchan = int(nchan) self.scaler = Scaler(prefix, nchan=nchan) self._counter = ScalerCounter(prefix, nchan=nchan, use_calc=use_calc) self.dwelltime_pv = PV("%s.TP" % prefix) self.dwelltime = None self.counters = self._counter.counters self.extra_pvs = [("Scaler.frequency", "%s.FREQ" % prefix), ("Scaler.read_delay", "%s.DLY" % prefix)] self._repr_extra = ", nchans=%i, use_calc=%s" % (nchan, repr(use_calc)) self.extra_pvs.extend(self._counter.extra_pvs)
def __init__(self, prefix, file_plugin=None, **kws): if not prefix.endswith(":"): prefix = "%s:" % prefix DetectorMixin.__init__(self, prefix, **kws) self.dwelltime_pv = PV("%scam1:AcquireTime" % prefix) self.dwelltime = None self.file_plugin = None self.counters = [Counter("%scam1:ArrayCounter_RBV" % prefix, label="Image Counter")] if file_plugin in AD_FILE_PLUGINS: self.file_plugin = file_plugin f_counter = Counter("%s%s:FileNumebr_RBV" % (prefix, file_plugin), label="File Counter") self.counters.append(f_counter) self._repr_extra = ", file_plugin=%s" % repr(file_plugin)
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
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()