def edm(margs, self, args): """ $ edm pv [display] [-e] [-b] """ macros = self.macros_from_pv(args.pv, allow_partial=False) if args.display is not None: display = args.display else: rtype = util.get_record_type(args.pv) display = EDM_DEFAULT_DISPLAYS[rtype] plugin = ECLIopi.get_plugin() exe = os.path.join(plugin.edm_path, 'edm') m_str = edm_display_macros(display, macros) logger.debug("Display: %s Macros: %s Macro string: %s" % (display, macros, m_str)) if sys.platform.startswith('win'): to_run = ['"%s"' % exe] else: to_run = [exe] if args.edit: pass else: to_run.append('-x') to_run.append('-m "%s"' % m_str) to_run.append(display) to_run = ' '.join(to_run) print('Running: %s' % to_run) if args.background: plugin.managers[plugin.OPI_EDM].run(to_run) else: shell = self.core.shell shell.system(to_run)
def fields(self, pv, string, max_interest=4, values=True): ''' Search the field information database for 'text'. If the first argument is a PV it will detect its record type, otherwise use a record type (.RTYP) to start with. ''' try: rf = util.get_record_fields(pv) except IOError: # not a record type, or not one we have information on # try it as a PV instead: rtype = util.get_record_type(pv) rf = util.get_record_fields(rtype) else: rtype = pv if isinstance(string, (list, tuple)): text = ' '.join(string) else: text = string headers = ['Field'] + [col.capitalize() for col in rf.columns] table = SimpleTable(headers) rows = list([name] + info for name, info in rf.find(text)) for row in rows: table.add_row(row) remove_rows = [] if rtype != pv and values: # this means a PV was passed in and the RTYP was determined table.add_column('Value', index=1, fill='') for i, row in enumerate(table.rows): if i == 0: continue field = row[0] try: interest = int(table['Interest', i]) except: interest = 0 else: if interest > max_interest: remove_rows.append(i) continue if interest > 3: timeout = self.fields_timeout / 2 else: timeout = self.fields_timeout value = epics.caget('%s.%s' % (pv, field), connection_timeout=timeout, verbose=True) if value is None: value = '' table[1, i] = '%s' % value removed = 0 for row in remove_rows: table.remove_row(row - removed) removed += 1 return rtype, table
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