Ejemplo n.º 1
0
    def __init__(self, shell, config):
        super(ECLIxmlrpc, self).__init__(shell=shell, config=config,
                                         init_traits=False)

        logging.info('Initializing ECLI xmlrpc server plugin')
        self._scan_number = 0

        scan_plugin = get_plugin(self.SCAN_PLUGIN)
        callbacks = [(scan_plugin.CB_PRE_SCAN,  self.pre_scan),
                     (scan_plugin.CB_POST_SCAN, self.post_scan),
                     (scan_plugin.CB_SCAN_STEP, self.single_step)]

        for cb_name, fcn in callbacks:
            scan_plugin.add_callback(cb_name, fcn)

        self.server_functions = self._find_functions(prefix='server_')
        self.server_thread = None
        self.server = None
        self.handler = None
        self._scan_info = {}
        self._scan_data = {}
        self._new_scan = {}
        self._scan_key = 0

        self._reset()
        self._port_changed()
Ejemplo n.º 2
0
    def __init__(self, shell, config):
        super(ECLIScanPrinter, self).__init__(shell=shell, config=config)
        if self.outfile is None:
            self.outfile = sys.stdout

        logger.info('ECLI Scan printer writing to: file=%s' % self.outfile)
        self._scan_number = 0
        self._last_point = None

        scan_plugin = get_plugin(SCAN_PLUGIN)
        scan_plugin.add_callback(scan_plugin.CB_PRE_SCAN, self.pre_scan)
        scan_plugin.add_callback(scan_plugin.CB_POST_SCAN, self.post_scan)
        scan_plugin.add_callback(scan_plugin.CB_SCAN_STEP, self.single_step)
Ejemplo n.º 3
0
    def get_save_files(self):
        files = []
        base = 'ECLIScanWriter'
        plugins = ('HDF5', 'SPEC')
        for plugin_name in plugins:
            plugin_name = '%s%s' % (base, plugin_name)
            try:
                plugin = get_plugin(plugin_name)
            except:
                pass
            else:
                files.append(plugin.filename)

        return files
Ejemplo n.º 4
0
    def __init__(self, pv, **kwargs):
        pv = str(pv)  # aliasedpv bugfix TODO

        if pv.endswith(".VAL"):
            pv = pv[:-4]

        super(ECLIPositioner, self).__init__(pv, **kwargs)

        self.move_time = 0

        motor_plugin = get_plugin("ECLIMotor")
        if pv in motor_plugin.motor_list:
            self.motor_rec = motor_plugin.get_motor(pv)
            self.motor_rec.SYNC = 1
        else:
            self.motor_rec = None
Ejemplo n.º 5
0
    def __init__(self, shell, config):
        super(ECLIScanWriterHDF5, self).__init__(shell=shell, config=config)
        logger.info('Initializing ECLI HDF5 file writer plugin')
        self._scan_number = 0
        self._scans_group = None  # Group for all scans
        self._scan_group = None  # Group for single scan (under scans_group)
        self._open_file(self.filename)

        scan_plugin = get_plugin(self.SCAN_PLUGIN)
        callbacks = [(scan_plugin.CB_PRE_SCAN,  self.pre_scan),
                     (scan_plugin.CB_POST_SCAN, self.post_scan),
                     (scan_plugin.CB_SCAN_STEP, self.single_step),
                     (scan_plugin.CB_SAVE_PATH, self.save_path_set),
                     ]

        self.scan_plugin = scan_plugin

        for cb_name, fcn in callbacks:
            scan_plugin.add_callback(cb_name, fcn)
Ejemplo n.º 6
0
    def __init__(self, shell, config):
        logger.info('Initializing ECLI SPEC file writer plugin')
        self._scan_number = 0
        self._new_scan = True
        scan_plugin = get_plugin(self.SCAN_PLUGIN)
        self.scan_plugin = scan_plugin
        self._motors = []

        super(ECLIScanWriterSPEC, self).__init__(shell=shell, config=config)

        if self.filename:
            self._file = SPECFileWriter(self.filename)
        else:
            self._file = None

        callbacks = [(scan_plugin.CB_PRE_SCAN, self.pre_scan),
                     (scan_plugin.CB_POST_SCAN, self.post_scan),
                     (scan_plugin.CB_SCAN_STEP, self.single_step),
                     (scan_plugin.CB_SAVE_PATH, self.save_path_set),
                     ]

        for cb_name, fcn in callbacks:
            scan_plugin.add_callback(cb_name, fcn)
Ejemplo n.º 7
0
 def xmlrpc_url(self):
     return get_plugin('ECLIxmlrpc').server_url
Ejemplo n.º 8
0
Archivo: cas.py Proyecto: klauer/ECLI
 def get_pv_manager():
     return get_plugin('ECLIcas').manager
Ejemplo n.º 9
0
Archivo: cas.py Proyecto: klauer/ECLI
 def get_plugin():
     return get_plugin('ECLIcas')
Ejemplo n.º 10
0
    def scan_run(
        self,
        positioners,
        dwell_time,
        move_back=True,
        command="",
        dimensions=None,
        breakpoints=[],
        counters=[],
        detectors=[],
        triggers=[],
        run=True,
        **kwargs
    ):
        """
        Perform a generic scan

        :param positioners: Motors to scan, with absolute position arrays
                            previously set
        :param dwell_time: Seconds at each point
        :param move_back: Move all positioners back to their starting position
                          post scan
        :param command: the command-line command used to start the scan
        :param dimensions: the scan dimensions
        :param counters: additional counters not normally included (can be a PV name)
        :param detectors: additional detectors not normally included
        :param triggers: additional triggers not normally included (can be a PV name)
        :param run: run the scan (or just return one ready to run)
        :param kwargs: passed onto the scan's ECLI info
        :returns: the scan instance
        """
        array_shapes = set([pos.array.shape for pos in positioners])
        if len(array_shapes) != 1:
            raise ValueError("Positioners must have the same position array dimensions")

        data_points = np.size(positioners[0].array)

        self.scan = sc = stepscan.StepScan()
        if dimensions is None or not isinstance(dimensions, (list, tuple)):
            dimensions = (data_points,)

        for positioner in positioners:
            sc.add_positioner(positioner)

        for counter in counters:
            sc.add_counter(counter)

        for trigger in triggers:
            sc.add_trigger(trigger)

        motor_plugin = get_plugin("ECLIMotor")
        for motor in motor_plugin.motor_list:
            motor_rec = motor_plugin.get_motor(motor)
            sc.add_extra_pvs([(motor, motor_rec.PV("RBV"))])

        for pv in self.extra_pvs:
            if pv in self.core.aliases:
                name, pv = pv, self.core.aliases[pv]
            else:
                name = self.core.get_aliased_name(pv)

            sc.add_extra_pvs([(name, pv)])

        mca_calib = {}

        for det_pv in set(self.detectors + list(detectors) + list(self.trigger_detectors.keys())):
            type_ = self.detector_types.get(det_pv, None)
            det = stepscan.get_detector(util.expand_alias(det_pv), kind=type_, label=det_pv)
            if det is None:
                logger.error("Scan %s invalid detector: %s" % (sc, det_pv))
                return None

            logger.debug("Scan %s added detector: %s" % (sc, det))
            sc.add_detector(det)

            # TODO bug report - hardware triggered detectors
            if det.trigger is not None:
                sc.triggers.remove(det.trigger)
                if det_pv in self.trigger_detectors:
                    trigger_value = self.trigger_detectors[det_pv]
                    logger.debug("Added detector trigger: %s = %s" % (det.trigger, trigger_value))
                    sc.add_trigger(det.trigger, value=trigger_value)

                if isinstance(det, stepscan.McaDetector):
                    det_pv = util.expand_alias(det_pv)
                    calib_pvs = ["%s.CALO", "%s.CALS", "%s.CALQ"]
                    prefix = det.prefix
                    calib = [epics.caget(pv % prefix) for pv in calib_pvs]
                    mca_calib[det_pv] = calib

        # TODO StepScan bug report:
        #  add_trigger needs to check for None (as in SimpleDetector)
        sc.triggers = [trigger for trigger in sc.triggers if trigger is not None]

        sc.set_dwelltime(dwell_time)

        start_pos = [pos.current() for pos in positioners]

        for counter in sc.counters:
            counter.label = str(counter.label)

        self._scan_number += 1
        sc.ecli_info = {
            "command": command,
            "scan_number": self._scan_number,
            "dimensions": dimensions,
            "ndim": calc_ndim(dimensions),
            "scanning": [str(pos.label) for pos in positioners],
            "mca_calib": mca_calib,
        }

        if hasattr(sc, "timestamps"):
            # Added timestamps in ECLI stepscan fork
            sc.ecli_info["timestamps"] = sc.timestamps
            sc.get_timestamp = lambda i: sc.timestamps[i]
        else:
            sc.get_timestamp = lambda i: None

        sc.ecli_info.update(kwargs)

        sc.pos_settle_time = self.pos_settle_time
        sc.det_settle_time = self.det_settle_time

        if not run:
            return sc

        ex_raised = None
        # TODO: check all PVs prior to scan
        # Run the scan
        try:
            sc.run(None)
        except Exception as ex:
            if sc.message_thread is not None:
                sc.message_thread.cpt = None
            logger.error("Scan failed: (%s) %s" % (ex.__class__.__name__, ex))
            ex_raised = ex
        finally:
            # Wait for the message thread to catch up
            if sc.message_thread is not None:
                sc.message_thread.join(1.0)

        if move_back:
            # Move the positioners back to their starting positions
            for pos, start in zip(positioners, start_pos):
                logger.info("Moving %s back to the starting position %g" % (pos, start))
                try:
                    pos.move_to(start, wait=True)
                except KeyboardInterrupt as ex:
                    print("%s move to %g cancelled (current position=%s)" % (pos.label, start, pos.current()))
                    ex_raised = ex

        if self.core.script_running:
            raise ex

        # Make a simple dictionary holding the scan data
        data = {}
        for counter in sc.counters:
            data[counter.label] = counter.buff

        # And export that data back to the user namespace as `scan_data`
        self.core.set_variable("scan_data", data)
        return sc
Ejemplo n.º 11
0
 def get_plugin(cls):
     return get_plugin(cls.__name__)
Ejemplo n.º 12
0
    def create_motors(self, create=[], aliases={},
                      desc='', rotary=[],
                      **kwargs):
        """
        Create pseudomotors that mimic an EPICS motor records

        For example,

            >>> create_motors(create=['pseudo1', 'pseudo2'],
            ...               m1='pseudo1 / 2.0',
            ...               pseudo1='m1 * 2',
            ...               pseudo2='(m1 * 2) + 0.1',
            ...               aliases={'m1': 'IOC:m1'},
            ...               )

        Assuming the CAS prefix is set to ECLI:, this will create two pseudomotors
        `ECLI:pseudo1` and `ECLI:pseudo2`. Their readback values will be updated
        each time `m1` (which has a full record name of `IOC:m1`) is updated,
        showing twice m1's readback value (and with a slight offset).

            % caget IOC:m1.RBV ECLI:pseudo1.RBV ECLI:pseudo2.RBV
            IOC:m1.RBV        1.0
            ECLI:pseudo1.RBV   2.0
            ECLI:pseudo2.RBV   2.1

            % caput ECLI:pseudo 3.0
            % caget IOC:m1.RBV ECLI:pseudo1.RBV ECLI:pseudo2.RBV
            IOC:m1.RBV        1.5
            ECLI:pseudo1.RBV   3.0
            ECLI:pseudo2.RBV   3.1

        :param create: The pseudo motor names (appended onto PCASpy prefix)
                       The expression to be evaluated for the pseudomotor readback value
                       should be set as a keyword argument.
        :param aliases: Define aliases for motors
                        e.g., {'m1': 'IOC:m1'}
        :type aliases: dict
        :param rotary: If a motor is the rotary list, motor values will be displayed in degrees,
                       but automatically converted to radians when doing calculations.
        :type rotary: list
        :param kwargs: Each time the pseudomotor is commanded to move, all related
                       motors specified in the kwargs will be commanded to move.

        :returns: tuple containing (Pseudomotor instance list, MotorGroup instance)
        .. note:: Expressions cannot have colons (:) in them -- that is, motors
                  must be valid Python identifiers. Prior to adding the
                  pseudomotor, either add aliases via the `aliases` parameter or
                  use normal ECLI aliasing.
        """

        if not create:
            raise ValueError('No motors to create')

        mplugin = get_plugin('ECLIMotor')
        cas_plugin = get_plugin('ECLIcas')

        core = self.core

        all_aliases = copy.deepcopy(core.aliases)
        all_aliases.update(aliases)

        group = pseudo.MotorGroup(aliases=all_aliases)

        pseudo_names = list(create)

        for pseudo_name in pseudo_names:
            if pseudo_name in self.pseudo_to_group:
                logger.info('Removing previously created pseudomotor of the same name (%s)' % pseudo_name)
                self.delete_pseudomotor(pseudo_name)

        pseudos_full = [all_aliases.get(pseudo_name, pseudo_name)
                        for pseudo_name in pseudo_names]

        for pseudo_name, pseudo_full in zip(pseudo_names, pseudos_full):

            readback_expr = kwargs[pseudo_name]
            logger.info('Pseudomotor: %s (%s) Readback expression: %s' %
                        (pseudo_name, pseudo_full, readback_expr))

            # Add the pseudomotor expressions
            group.add_motor(pseudo_name, pseudo_full, readback_expr)

        # And all of the related motor expressions
        for motor, expression in kwargs.items():
            if motor in pseudo_names:
                continue

            full_pv = all_aliases.get(motor, motor)
            logger.info('Motor: %s (%s) Expression: %s' %
                        (motor, full_pv, expression))

            group.add_motor(motor, full_pv, expression)

        # Check all of the equations first
        group.start()
        logger.debug('Equations checked')

        for param in kwargs.keys():
            if param in pseudo_names:
                continue

            logger.debug('Adding record %s' % param)

            full_param = all_aliases.get(param, param)
            rtype = util.get_record_type(full_param)
            if rtype == 'motor':
                record = mplugin.get_motor(full_param)
                group.set_record(param, record)

        logger.debug('Rotary motors: %s' % ', '.join(rotary))

        pseudos = []
        # Create the pseudomotor instance itself
        for pseudo_name, pseudo_full in zip(pseudo_names, pseudos_full):
            p = pseudo.PseudoMotor(cas_plugin.manager, group,
                                   pseudo_full, pseudo_name,
                                   rotary=pseudo_name in rotary)
            pseudos.append(p)
            group.set_record(pseudo_name, p)

        # And start them up
        for pseudomotor in pseudos:
            pseudomotor.startup()

        for pseudo_name, pseudomotor in zip(pseudo_names, pseudos):
            pseudomotor.update_readback()

            self.pseudo_to_group[pseudo_name] = group

        self.groups.append(group)
        return pseudos, group
Ejemplo n.º 13
0
            logging.error('Scaler list undefined (see %%config ECLIScaler.scalers)')
            return

        if seconds is None:
            seconds = self.default_count_time

        for scaler in scalers:
            if self.show_timestamp:
                print(' %s' % util.timestamp_string())
                print()

            dev = self._get_device(scaler)
            table = self.scaler_counts_table(dev, seconds)
            table.print_()

show_elapsed = ShowElapsed(lambda: get_plugin('ECLIScaler').show_elapsed)


@show_elapsed.wrapper
@ecli_magic_args(ECLIScaler)
@argument('seconds', type=float, nargs='?',
          help='PV')
@argument('-r', '--record', type=AliasedPV, nargs='?',
          help='Record to use')
def ct(margs, self, args):
    """
    $ ct [seconds] [-r/--record record]
    """
    if args.record is not None:
        scalers = [args.record]
    else: