class SliceDhvController(BaseInterface, Device): """ Class for the Vescent Photonics Slice-DHV piezo driver controller PVs. """ _command = Cpt(EpicsSignal, ':CMD', kind='omitted') _reply = Cpt(EpicsSignalRO, ':REPLY', kind='omitted') version = Cpt(EpicsSignalRO, ':VERSION', kind='omitted') reset_ch1 = Cpt(EpicsSignal, ':FACTORY_RESET_CH1', kind='omitted') set_metadata(reset_ch1, dict(variety='command-proc', value=1)) reset_ch2 = Cpt(EpicsSignal, ':FACTORY_RESET_CH2', kind='omitted') set_metadata(reset_ch2, dict(variety='command-proc', value=1)) save_config = Cpt(EpicsSignal, ':SAVE_CONFIG', kind='config') set_metadata(save_config, dict(variety='command-proc', value=1)) save_status = Cpt(EpicsSignalRO, ':SAVE_STATUS', kind='config') manufacturer = Cpt(EpicsSignalRO, ':MANUFACTURER', kind='omitted') model = Cpt(EpicsSignalRO, ':MODEL', kind='omitted') serial = Cpt(EpicsSignalRO, ':SERIAL', kind='omitted') ctl_fw = Cpt(EpicsSignalRO, ':CTL_FW', kind='omitted') dhv_fw = Cpt(EpicsSignalRO, ':DHV_FW', kind='omitted')
class Variants(ophyd.Device): soft_delta = Cpt(ophyd.Signal, value=1) tweakable_delta_source_by_name = Cpt(EpicsSignal, 'tweakable') set_metadata( tweakable_delta_source_by_name, { 'variety': 'scalar-tweakable', 'delta.signal': 'soft_delta', 'delta.source': 'signal', 'range.source': 'value', 'range.value': [-10, 10], }) tweakable_delta_source_by_component = Cpt(EpicsSignal, 'tweakable') set_metadata( tweakable_delta_source_by_component, { 'variety': 'scalar-tweakable', 'delta.signal': soft_delta, 'delta.source': 'signal', 'range.source': 'value', 'range.value': [-10, 10], }) array_tabular = Cpt(EpicsSignal, 'array-tabular') set_metadata(array_tabular, { 'variety': 'array-tabular', 'shape': (3, 3), })
class Ell9(Ell6): """ Class for Thorlabs ELL9 4 position filter slider. Parameters ---------- prefix : str The PV base of the stage. channel : str The motor channel on the controller (0-F) port : str The port of the Elliptec controller (typically 0) Examples -------- ell9 = Ell9('LM1K4:COM_DP1_TF1_SL1:ELL', port=0, channel=1, name='ell9') """ home = FCpt(EpicsSignal, '{prefix}:M{self._channel}:HOME', kind='config') set_metadata(home, dict(variety='command-proc', value=1)) # Names for slider positions name_2 = FCpt(EpicsSignal, '{prefix}:M{self._channel}:NAME2', kind='config') name_3 = FCpt(EpicsSignal, '{prefix}:M{self._channel}:NAME3', kind='config')
class Agilent53210A(BaseInterface, Device): """ Agililent 53210A frequency counter class. For use with IOC ioc/common/agilent5322. """ protocol = Cpt(EpicsSignal, ':PROTOCOL_RBV', write_pv=':PROTOCOL', kind='omitted') freq_rbck = Cpt(EpicsSignalRO, ':FREQ_RBCK', kind='normal') freq_rbck_raw = Cpt(EpicsSignalRO, ':FREQ_RBCK_RAW', kind='omitted') auto_level = Cpt(EpicsSignal, ':GET_AUTO_LEVEL', write_pv=':SET_AUTO_LEVEL', kind='config') coupling = Cpt(EpicsSignal, ':GET_COUPLING', write_pv=':SET_COUPLING', kind='config') impedance = Cpt(EpicsSignal, ':GET_IMPEDANCE', write_pv=':SET_IMPEDANCE', kind='config') noise_rej = Cpt(EpicsSignal, ':GET_NOISE_REJ', write_pv=':SET_NOISE_REJ', kind='config') trig_level = Cpt(EpicsSignal, ':GET_TRIG_LEVEL', write_pv=':SET_TRIG_LEVEL', kind='config') trig_percent = Cpt(EpicsSignal, ':GET_TRIG_PERCENT', write_pv=':SET_TRIG_PERCENT', kind='config') identity = Cpt(EpicsSignalRO, ':IDENTITY', kind='omitted') reset = Cpt(EpicsSignal, ':RESET', kind='config') set_metadata(reset, dict(variety='command-proc', value=1))
class Wave8V2EventBuilder(BaseInterface, Device): """ Class for controlling the LCLS-II Wave8 event builder registers. """ cnt_rst = Cpt(EpicsSignal, ':CntRst', kind='config') set_metadata(cnt_rst, dict(variety='command-proc', value=1)) hard_rst = Cpt(EpicsSignal, ':HardRst', kind='config') set_metadata(hard_rst, dict(variety='command-proc', value=1)) soft_rst = Cpt(EpicsSignal, ':SoftRst', kind='config') set_metadata(soft_rst, dict(variety='command-proc', value=1)) timer_rst = Cpt(EpicsSignal, ':TimerRst', kind='config') set_metadata(timer_rst, dict(variety='command-proc', value=1)) blowoff_ext = Cpt(EpicsSignalRO, ':BlowoffExt', kind='config') blowoff = Cpt(EpicsSignal, ':Blowoff_RBV', write_pv=':Blowoff', kind='config') bypass = Cpt(EpicsSignal, ':Bypass_RBV', write_pv=':Bypass', kind='config') # DataCnt1 through DataCnt9 are the raw waveforms; captured elsewhere. datacnt0 = Cpt(EpicsSignalRO, ':DataCnt0', kind='config') datacnt10 = Cpt(EpicsSignalRO, ':DataCnt10', kind='config') # NullCnt1 through NullCnt9 are not needed here. nullcnt0 = Cpt(EpicsSignalRO, ':NullCnt0', kind='config') nullcnt10 = Cpt(EpicsSignalRO, ':NullCnt10', kind='config') # TimeoutDropCnt1 through TimeoutDropCnt9 are not needed here. timeout_dropcnt0 = Cpt(EpicsSignalRO, ':NullCnt0', kind='config') timeout_dropcnt10 = Cpt(EpicsSignalRO, ':NullCnt10', kind='config') timeout = Cpt(EpicsSignal, ':Timeout_RBV', write_pv=':Timeout', kind='config') num_slaves_g = Cpt(EpicsSignalRO, ':NUM_SLAVES_G', kind='config') trans_tdest_g = Cpt(EpicsSignalRO, ':TRANS_TDEST_G', kind='config') state = Cpt(EpicsSignalRO, ':State', kind='config') transaction_cnt = Cpt(EpicsSignalRO, ':TransactionCnt', kind='config')
class EllBase(Device): """ Base class for Elliptec stages. """ set_position = FCpt(EpicsSignal, '{prefix}:M{self._channel}:CURPOS', write_pv='{prefix}:M{self._channel}:MOVE', kind='normal') jog_fwd = FCpt(EpicsSignal, '{prefix}:M{self._channel}:MOVE_FWD', kind='normal') set_metadata(jog_fwd, dict(variety='command-proc', value=1)) jog_bwd = FCpt(EpicsSignal, '{prefix}:M{self._channel}:MOVE_BWD', kind='normal') set_metadata(jog_bwd, dict(variety='command-proc', value=1)) status = FCpt(EpicsSignalRO, '{prefix}:M{self._channel}:STATUS', kind='normal') optimize = FCpt(EpicsSignal, '{prefix}:M{self._channel}:OPTIMIZE', kind='omitted') set_metadata(optimize, dict(variety='command-proc', value=1)) _from_addr = FCpt(EpicsSignal, '{prefix}:PORT{self._port}:FROM_ADDR', kind='omitted') _to_addr = FCpt(EpicsSignal, '{prefix}:PORT{self._port}:TO_ADDR', kind='omitted') _save = FCpt(EpicsSignal, '{prefix}:PORT{self._port}:SAVE', kind='omitted') _command = FCpt(EpicsSignal, '{prefix}:PORT{self._port}:CMD', kind='omitted') _response = FCpt(EpicsSignalRO, '{prefix}:PORT{self._port}:RESPONSE', kind='omitted') def __init__(self, prefix, port=0, channel=1, **kwargs): self._port = port self._channel = channel super().__init__(prefix, **kwargs)
class Qadc134(QadcBase): """ Class for the Abaco FMC134 digitizer card. """ sparsification = Cpt(Qadc134Sparsification, '', kind='omitted') full_en = Cpt(EpicsSignal, ":FULL_EN_RBV", write_pv=":FULL_EN", kind="config", doc="Enable full size output arrays") ichan = Cpt(EpicsSignal, ":ICHAN_RBV", write_pv=":ICHAN", kind="config", doc="Interleave channel") interleave = Cpt(EpicsSignal, ":INTERLEAVE_RBV", write_pv=":INTERLEAVE", kind="config", doc="Enable interleaving on ichan") length = Cpt(EpicsSignal, ":LENGTH_RBV", write_pv=":LENGTH", kind="config") prescale = Cpt(EpicsSignal, ":PRESCALE_RBV", write_pv=":PRESCALE", kind="config") trig_delay = Cpt(EpicsSignal, ":TRIG_DELAY_RBV", write_pv=":TRIG_DELAY", kind="config", doc="Delay in 156.17 MHz ticks") trig_event = Cpt(EpicsSignal, ":TRIG_EVENT_RBV", write_pv=":TRIG_EVENT", kind="config") clear_config = Cpt(EpicsSignal, ":CLEAR_CONFIG", kind="config") set_metadata(clear_config, dict(variety='command-proc', value=1)) out0 = Cpt(EpicsSignalRO, ":OUT0", kind="normal", doc="Signal in Volts") out1 = Cpt(EpicsSignalRO, ":OUT1", kind="normal", doc="Signal in Volts") rawdata0 = Cpt(EpicsSignalRO, ":RAWDATA0", kind="normal", doc="Signal in ADU") rawdata1 = Cpt(EpicsSignalRO, ":RAWDATA1", kind="normal", doc="Signal in ADU") start = Cpt(EpicsSignal, ":START", kind="normal")
class EllLinear(EllBase): """ Class for Thorlabs ELL17/20 (28/60mm) linear stage. Parameters ---------- prefix : str The PV base of the stage. channel : str The motor channel on the controller (0-F) port : str The port of the Elliptec controller (typically 0) Examples -------- ell17 = EllLinear('LM1K4:COM_DP1_TF1_LIN1:ELL', port=0, channel=1, name='ell17') """ home = FCpt(EpicsSignal, '{prefix}:M{self._channel}:HOME', kind='config') set_metadata(home, dict(variety='command-proc', value=1)) jog_step = FCpt(EpicsSignal, '{prefix}:M{self._channel}:GET_JOG', write_pv='{prefix}:M{self._channel}:SET_JOG', kind='config') clean = FCpt(EpicsSignal, '{prefix}:M{self._channel}:CLEAN_MECH', kind='omitted') set_metadata(clean, dict(variety='command-proc', value=1)) stop_optimize = FCpt(EpicsSignal, '{prefix}:M{self._channel}:STOP', kind='omitted') set_metadata(stop_optimize, dict(variety='command-proc', value=1)) current_egu = FCpt(EpicsSignal, '{prefix}:M{self._channel}:CURPOS.EGU', kind='omitted') target_egu = FCpt(EpicsSignal, '{prefix}:M{self._channel}:MOVE.EGU', kind='omitted')
class QadcBase(BaseInterface, Device): """ Base class common to all qadc digitizers. """ ch0 = Cpt(EpicsSignalRO, ":CH0", kind="normal") ch1 = Cpt(EpicsSignalRO, ":CH1", kind="normal") ch2 = Cpt(EpicsSignalRO, ":CH2", kind="normal") ch3 = Cpt(EpicsSignalRO, ":CH3", kind="normal") config = Cpt(EpicsSignal, ":CONFIG", kind="config") set_metadata(config, dict(variety='command-proc', value=1))
class Wave8V2Simple(BaseInterface, Device): """ Simple class for viewing Wave8 waveforms, and stopping/starting acquisition. """ run_start = Cpt(EpicsSignal, ':SeqStartRun.PROC', kind='normal') set_metadata(run_start, dict(variety='command-proc', value=1)) run_stop = Cpt(EpicsSignal, ':SeqStopRun.PROC', kind='normal') set_metadata(run_stop, dict(variety='command-proc', value=1)) ch0 = Cpt(EpicsSignalRO, ':CH0:ArrayData', kind='normal') ch1 = Cpt(EpicsSignalRO, ':CH1:ArrayData', kind='normal') ch2 = Cpt(EpicsSignalRO, ':CH2:ArrayData', kind='normal') ch3 = Cpt(EpicsSignalRO, ':CH3:ArrayData', kind='normal') ch4 = Cpt(EpicsSignalRO, ':CH4:ArrayData', kind='normal') ch5 = Cpt(EpicsSignalRO, ':CH5:ArrayData', kind='normal') ch6 = Cpt(EpicsSignalRO, ':CH6:ArrayData', kind='normal') ch7 = Cpt(EpicsSignalRO, ':CH7:ArrayData', kind='normal')
class BaslerBase(Device): """ Base class with Basler specific PVs. Intended to be sub-classed, not used stand-alone. """ reset = Cpt(EpicsSignal, 'RESET.PROC', kind='config', doc='Reset the camera') set_metadata(reset, dict(variety='command-proc', value=1)) packet_size = Cpt(EpicsSignal, 'GevSCPSPacketSiz_RBV', write_pv='GevSCPSPacketSiz', kind='config', doc='Set Ethernet Packet Size (typ. 9000)') enet_bw = Cpt(EpicsSignalRO, 'GevSCDCT_RBV', kind='config', doc='Current Ethernet bandwidth')
class DiconSwitch(BaseInterface, Device): """ Class for controlling the DiCon fiber matrix switch. """ chan1 = Cpt(EpicsSignal, ':getChan1', write_pv=':setOut1', kind='normal') chan2 = Cpt(EpicsSignal, ':getChan2', write_pv=':setOut2', kind='normal') chan3 = Cpt(EpicsSignal, ':getChan3', write_pv=':setOut3', kind='normal') chan4 = Cpt(EpicsSignal, ':getChan4', write_pv=':setOut4', kind='normal') chan5 = Cpt(EpicsSignal, ':getChan5', write_pv=':setOut5', kind='normal') chan6 = Cpt(EpicsSignal, ':getChan6', write_pv=':setOut6', kind='normal') chan7 = Cpt(EpicsSignal, ':getChan7', write_pv=':setOut7', kind='normal') chan8 = Cpt(EpicsSignal, ':getChan8', write_pv=':setOut8', kind='normal') version = Cpt(EpicsSignalRO, ':getVers', kind='config') error_str = Cpt(EpicsSignalRO, ':ErrStr', kind='config') error_num = Cpt(EpicsSignalRO, ':ErrorNum', kind='config') reset = Cpt(EpicsSignal, ':reset', kind='omitted') set_metadata(reset, dict(variety='command-proc', value=1))
class Wave8V2AxiVersion(BaseInterface, Device): """ Class for LCLS-II Wave8 AxiVersion registers. """ build_stamp = Cpt(EpicsSignalRO, ':BuildStamp', kind='config') fpga_reload = Cpt(EpicsSignal, ':FpgaReload', kind='config') set_metadata(fpga_reload, dict(variety='command-proc', value=1)) fpga_version = Cpt(EpicsSignalRO, ':FpgaVersion', kind='config') scratch_pad = Cpt(EpicsSignal, ':ScratchPad_RBV', write_pv=':ScratchPad', kind='config') user_reset = Cpt(EpicsSignal, ':UserReset_RBV', write_pv=':UserReset', kind='config') uptime = Cpt(EpicsSignalRO, ':UpTime', kind='config')
class PCDSAreaDetectorTyphos(Device): """ A 'bare' PCDS areadetector class specifically for Typhos screens. Implements only the most commonly used PVs for areadetector IOCS. Includes a simple image viewer. """ # Status and specifications manufacturer = Cpt(EpicsSignalRO, 'Manufacturer_RBV', kind='config') camera_model = Cpt(EpicsSignalRO, 'Model_RBV', kind='normal') sensor_size_x = Cpt(EpicsSignalRO, 'MaxSizeX_RBV', kind='config') sensor_size_y = Cpt(EpicsSignalRO, 'MaxSizeY_RBV', kind='config') data_type = Cpt(EpicsSignalWithRBV, 'DataType', kind='config') # Acquisition settings exposure = Cpt(EpicsSignalWithRBV, 'AcquireTime', kind='config') gain = Cpt(EpicsSignalWithRBV, 'Gain', kind='config') num_images = Cpt(EpicsSignalWithRBV, 'NumImages', kind='config') image_mode = Cpt(EpicsSignalWithRBV, 'ImageMode', kind='config') trigger_mode = Cpt(EpicsSignalWithRBV, 'TriggerMode', kind='config') acquisition_period = Cpt(EpicsSignalWithRBV, 'AcquirePeriod', kind='config') # Image collection settings acquire = Cpt(EpicsSignal, 'Acquire', kind='normal') acquire_rbv = Cpt(EpicsSignalRO, 'DetectorState_RBV', kind='normal') image_counter = Cpt(EpicsSignalRO, 'NumImagesCounter_RBV', kind='normal') # TJ: removing from the class for now. May be useful later. # Image data # ndimensions = Cpt(EpicsSignalRO, 'IMAGE2:NDimensions_RBV', kind='omitted') # width = Cpt(EpicsSignalRO, 'IMAGE2:ArraySize0_RBV', kind='omitted') # height = Cpt(EpicsSignalRO, 'IMAGE2:ArraySize1_RBV', kind='omitted') # depth = Cpt(EpicsSignalRO, 'IMAGE2:ArraySize2_RBV', kind='omitted') # array_data = Cpt(EpicsSignal, 'IMAGE2:ArrayData', kind='omitted') # cam_image = Cpt(NDDerivedSignal, derived_from='array_data', # shape=('height', # 'width', # 'depth'), # num_dimensions='ndimensions', # kind='normal') def open_viewer(self): """ Launch the python camera viewer for this camera. """ arglist = [ '/reg/g/pcds/pyps/apps/camviewer/latest/run_viewer.sh', '--instrument', '{}.format(get_hutch_name())', '--oneline', 'GE:16,{0}:IMAGE1;{0},,{0}'.format(self.prefix[0:-1]) ] subprocess.run(arglist, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True) # Make viewer available in Typhos screen cam_viewer = Cpt(AttributeSignal, attr='_open_screen', kind='normal') set_metadata(cam_viewer, dict(variety='command-proc', value=1)) @property def _open_screen(self): return 0 @_open_screen.setter def _open_screen(self, value): self.open_viewer()
class QminiSpectrometer(Device): """ Qmini Spectrometer Device for the Qmini spectrometer by RGB Photonics. Parameters ---------- prefix : str Base prefix of the Qmini name : str Name of Qmini object """ # General control status = Cpt(EpicsSignalRO, ':STATUS', kind='normal') temperature = Cpt(EpicsSignalRO, ':TEMP', kind='config') exposure = Cpt(EpicsSignal, ':GET_EXPOSURE_TIME', write_pv=':SET_EXPOSURE_TIME', kind='config') trig_mode = Cpt(EpicsSignal, ':TRIG_MODE_RBV', write_pv=':TRIG_MODE', kind='config') trig_delay = Cpt(EpicsSignal, ':GET_TRIG_DELAY', write_pv=':SET_TRIG_DELAY', kind='config') trig_pin = Cpt(EpicsSignal, ':TRIG_PIN_RBV', write_pv=':SET_TRIG_PIN', kind='config') trig_edge = Cpt(EpicsSignal, ':TRIG_EDGE_RBV', write_pv=':SET_TRIG_EDGE', kind='config') trig_enable = Cpt(EpicsSignal, ':GET_TRIG_ENABLE', write_pv=':SET_TRIG_ENABLE', kind='config') scan_rate = Cpt(EpicsSignal, ':GET_SPECTRUM.SCAN', kind='config') reset = Cpt(EpicsSignal, ':CLEAR_SPECTROMETER', kind='config') set_metadata(reset, dict(variety='command-proc', value=1)) spectrum = Cpt(EpicsSignalRO, ':SPECTRUM', kind='normal') wavelengths = Cpt(EpicsSignalRO, ':WAVELENGTHS', kind='normal') model = Cpt(EpicsSignalRO, ':MODEL_CODE', kind='config') set_metadata(model, dict(variety='scalar', display_format='hex')) serial_number = Cpt(EpicsSignalRO, ':SERIAL_NUMBER', kind='config') # Processing Steps adjust_offset = Cpt(EpicsSignal, ':ADJUST_OFFSET', kind='omitted') correct_nonlinearity = Cpt(EpicsSignal, ':CORRECT_NONLINEARITY', kind='omitted') remove_bad_pixels = Cpt(EpicsSignal, ':REMOVE_BAD_PIXELS', kind='omitted') subtract_dark = Cpt(EpicsSignal, ':SUBTRACT_DARK', kind='omitted') remove_temp_bad_pixels = Cpt(EpicsSignal, ':REMOVE_TEMP_BAD_PIXELS', kind='omitted') normalize_exposure = Cpt(EpicsSignal, ':NORMALIZE_EXPOSURE', kind='omitted') sensitivity_cal = Cpt(EpicsSignal, ':SENSITIVITY_CAL', kind='omitted') correct_prnu = Cpt(EpicsSignal, ':CORRECT_PRNU', kind='omitted') additional_filtering = Cpt(EpicsSignal, ':ADDITIONAL_FILTERING', kind='omitted') scale_to_16_bit = Cpt(EpicsSignal, ':SCALE_TO_16BIT', kind='omitted') set_processing_steps = Cpt(EpicsSignal, ':SET_PROCESSING_STEPS', kind='omitted') get_processing_steps = Cpt(EpicsSignalRO, ':GET_PROCESSING_STEPS', kind='omitted') # Spectral fitting fit_on = Cpt(EpicsSignal, ':FIT_ON', kind='config') fit_width = Cpt(EpicsSignal, ':WIDTH', kind='config') w0_guess = Cpt(EpicsSignal, ':W0_GUESS', kind='config') w0_fit = Cpt(EpicsSignalRO, ':W0_FIT', kind='normal') fit_fwhm = Cpt(EpicsSignalRO, ':FWHM', kind='config') fit_amplitude = Cpt(EpicsSignalRO, ':AMPLITUDE', kind='config') fit_stdev = Cpt(EpicsSignalRO, ':STDEV', kind='config') fit_chisq = Cpt(EpicsSignalRO, ':CHISQ', kind='config')
class MyDevice(ophyd.Device): cpt = ophyd.Component(ophyd.Signal) set_metadata(cpt, None) unset_cpt = ophyd.Component(ophyd.Signal)
class MyDevice(ophyd.Device): command = Cpt(EpicsSignal, 'command-with-enum') set_metadata(command, { 'variety': 'command', 'tags': {'confirm', 'protected'}, 'value': 1, }) command_proc = Cpt(EpicsSignal, 'command-without-enum') set_metadata(command_proc, {'variety': 'command-proc'}) command_enum = Cpt(EpicsSignal, 'command-without-enum') set_metadata( command_enum, { 'variety': 'command-enum', 'enum_dict': { 0: 'No', 1: 'Yes', 3: 'Metadata-defined' }, }) command_setpoint_tracks_readback = Cpt(EpicsSignal, 'command-setpoint-tracks-readback') set_metadata(command_setpoint_tracks_readback, {'variety': 'command-setpoint-tracks-readback'}) tweakable = Cpt(EpicsSignal, 'tweakable') set_metadata( tweakable, { 'variety': 'scalar-tweakable', 'delta.value': 0.5, 'delta.range': [-1, 1], 'range.source': 'value', 'range.value': [-1, 1], }) array_timeseries = Cpt(EpicsSignal, 'array-timeseries') set_metadata(array_timeseries, {'variety': 'array-timeseries'}) array_histogram = Cpt(EpicsSignal, 'array-histogram') set_metadata(array_histogram, {'variety': 'array-histogram'}) array_image = Cpt(EpicsSignal, 'array-image') set_metadata(array_image, {'variety': 'array-image', 'shape': (32, 32)}) array_nd = Cpt(EpicsSignal, 'array-nd') set_metadata(array_nd, {'variety': 'array-nd', 'shape': (16, 16, 4)}) scalar = Cpt(EpicsSignal, 'scalar') set_metadata(scalar, {'variety': 'scalar'}) scalar_range = Cpt(EpicsSignal, 'scalar-range') set_metadata(scalar_range, {'variety': 'scalar-range'}) bitmask = Cpt(EpicsSignal, 'bitmask') set_metadata( bitmask, { 'variety': 'bitmask', 'bits': 4, 'style': dict(shape='circle', on_color='yellow', off_color='white'), 'meaning': ['A', 'B', 'C'], }) text = Cpt(EpicsSignal, 'text', string=True) set_metadata(text, {'variety': 'text'}) text_multiline = Cpt(EpicsSignal, 'text-multiline', string=True) set_metadata(text_multiline, {'variety': 'text-multiline'}) text_enum = Cpt(EpicsSignal, 'text-enum', string=True) set_metadata(text_enum, {'variety': 'text-enum'}) enum = Cpt(EpicsSignal, 'enum') set_metadata(enum, {'variety': 'enum'}) variants = Cpt(Variants, '')