class EpicsBssDevice(Device): """ Ophyd device for info from APS Proposal and ESAF databases. .. autosummary:: ~clear """ esaf = Component(EpicsEsafDevice, "esaf:") proposal = Component(EpicsProposalDevice, "proposal:") status_msg = Component(EpicsSignal, "status", string=True, kind="omitted") def clear(self): """Clear the proposal and ESAF info.""" self.esaf.clear() self.proposal.clear() self.status_msg.put("Cleared")
class MyDevice(Device): sub1 = Component(SubDevice, '1') attrsig = Component(AttributeSignal, 'prop') sub_attrsig = Component(AttributeSignal, 'sub1.prop', write_access=False) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._value = init_value @property def prop(self): return self._value @prop.setter def prop(self, value): self._value = value
class DAC(PVPositionerSoftDone): """ Setup DAC as a PVPositioner """ setpoint = Component(EpicsSignal, '.VAL', put_complete=True, kind='normal') readback = Component(EpicsSignalRO, '_rbv.VAL', auto_monitor=True, kind='hinted') low_limit = Component(EpicsSignal, '.DRVL', kind='config') high_limit = Component(EpicsSignal, '.DRVH', kind='config') def __init__(self, *args, **kwargs): super().__init__(*args, tolerance=0.001, **kwargs) @property def limits(self): return (self.low_limit.get(), self.high_limit.get())
class HXNStage(Device): x_start = Component(EpicsSignal, 'XStart-RB', write_pv='XStart') x_stop = Component(EpicsSignal, 'XStop-RB', write_pv='XStop') nx = Component(EpicsSignal, 'NX-RB', write_pv='NX') y_start = Component(EpicsSignal, 'YStart-RB', write_pv='YStart') y_stop = Component(EpicsSignal, 'YStop-RB', write_pv='YStop') ny = Component(EpicsSignal, 'NY-RB', write_pv='NY') trigger_rate = Component(EpicsSignal, 'TriggerRate-RB', write_pv='TriggerRate') start_scan = Component(EpicsSignal, 'StartScan.PROC')
class Magnet6T(Device): tabth = Component(EpicsMotor,'m53', labels=('motor','6T magnet')) # 4T Mag Th tabx = Component(EpicsMotor,'m49', labels=('motor','6T magnet')) # 4T MagTab X taby = Component(EpicsMotor,'m50', labels=('motor','6T magnet')) # 4T MagTab Y tabth2 = Component(EpicsMotor,'m56', labels=('motor','6T magnet')) # AMIMagnetPhi tabz2 = Component(EpicsMotor,'m51', labels=('motor','6T magnet')) # AMIMagnetZ tabx2 = Component(EpicsMotor,'m52', labels=('motor','6T magnet')) # AMIMagenetX sampy = Component(EpicsMotor,'m63', labels=('motor','6T magnet')) # CIATRA sampth = Component(EpicsMotor,'m58', labels=('motor','6T magnet')) # CIA ROT
class FlyScanParameters(Device): """FlyScan values""" number_points = Component(EpicsSignal, "9idcLAX:USAXS:FS_NumberOfPoints") scan_time = Component(EpicsSignal, "9idcLAX:USAXS:FS_ScanTime") use_flyscan = Component(EpicsSignal, "9idcLAX:USAXS:UseFlyscan") asrp_calc_SCAN = Component(EpicsSignal, "9idcLAX:userStringCalc2.SCAN") order_number = Component(EpicsSignal, "9idcLAX:USAXS:FS_OrderNumber") elapsed_time = Component(EpicsSignal, "9idcLAX:USAXS:FS_ElapsedTime") setpoint_up = Component(Signal, value=6000) # decrease range setpoint_down = Component(Signal, value=850000) # increase range
class TomoCamStage(MotorBundle): """ Motor stacks used for Tomo Camera _____________ | Tomo Y | ============= | Tomo X | ============= | Tomo Z | ------------- """ # TODO: # update with acutal set up tomoy = Component(EpicsMotor, "6idhedm:m48", name='tomoy') # x motion with kohzu stage tomox = Component(EpicsMotor, "6idhedm:m45", name='tomox') # y motion with kohzu stage tomoz = Component(EpicsMotor, "6idhedm:m46", name='tomoz') # z motion with kohzu stage @property def status(self): """return full pv list and corresponding values""" # TODO: # once acutal PVs are known, the implementation should go here # my thought is to list useful PV status for users, # a full list should be implemented in the Ultima for dev /JasonZ # Maybe print StateAero.position_cached ? pass def cache_position(self): """cache current motor positions""" # Add other motors if any (i.e. Kohzu tilt) # TODO: # We need to consider what to do when cached positions are not the same # as the physical positions when a motor is manually moved self.position_cached = { "tomoy": self.tomoy.position, "tomox": self.tomox.position, "tomoz": self.tomoz.position, }
class SampleRotator(Device): """ Use an EPICS motor to rotate sample while collecting data. Rotate sample with appropriate speed while collecting data to integrate over same area on sample for each point. Do not interface with normal motor API, but add some of the attributes. This motor is intentionally NOT controlled by spec and presumably also is not in BS (as a motor). Pushing jog button starts rotation at speed which is setup in epics. Switching off and on (with resets) is needed since else epics runs out of counters and stops mid way. """ home = Component(SampleRotatorHoming, "") jog_forward = Component(EpicsSignal, ".JOGF", kind='omitted', auto_monitor=True) jog_reverse = Component(EpicsSignal, ".JOGR", kind='omitted', auto_monitor=True) motor_done_move = Component(EpicsSignalRO, ".DMOV", kind='omitted', auto_monitor=True) motor_is_moving = Component(EpicsSignalRO, '.MOVN', kind='omitted', auto_monitor=True) motor_stop = Component(EpicsSignal, ".STOP", kind='omitted', auto_monitor=True) speed = Component(EpicsSignal, ".S", kind='config') user_readback = Component(EpicsSignalRO, '.RBV', kind='hinted', auto_monitor=True) velocity = Component(EpicsSignal, ".VELO", kind='config') @raise_if_disconnected def stop(self, *, success=False): self.motor_stop.put(1, wait=False) super().stop(success=success)
class FilterStatistics(Device): # TODO: How to not re-run the filter for each statistic, # by re-assigning _img below? components = {} # use functools.partial to input all parameters but the data array # generate the filter numerator and denominator here order = 1 # db/octave = order*6dB sample_rate = 400e3/64/16*8 # with on-board oscillator tau = 10e-3 # consistent with SR810 func_list = ['filter_6dB', 'filter_24dB'] num, denom = create_filter(order=order, sample_rate=sample_rate, tau=tau) func_name = 'filter_6dB' stat_funcs = [np.mean, np.std] for stat_func in stat_funcs: func = functools.partial(apply_filter, num=num, denom=denom, sample_rate=sample_rate, tau=tau, final_stat_function=stat_func) components[func_name + '_' + stat_func.__name__] = Component(StatCalculator, name=func, img=None, stat_func=func, kind=Kind.hinted, precision=5) order = 4 # db/octave = order*24dB num, denom = create_filter(order=order, sample_rate=sample_rate, tau=tau) func_name = 'filter_24dB' for stat_func in stat_funcs: func = functools.partial(apply_filter, num=num, denom=denom, sample_rate=sample_rate, tau=tau, final_stat_function=stat_func) components[func_name + '_' + stat_func.__name__] = Component(StatCalculator, name=func, img=None, stat_func=func, kind=Kind.hinted, precision=5) locals().update(components) def __init__(self, array_source, *args, **kwargs): super().__init__(*args, **kwargs) for func in self.func_list: for stat_func in self.stat_funcs: getattr(self, func + '_' + stat_func.__name__)._img = array_source.get_array # update the name getattr(self, func + '_' + stat_func.__name__).name = array_source.name + getattr(self, func + '_' + stat_func.__name__).name
class UsaxsSlitDevice(MotorBundle): """ USAXS slit just before the sample * center of slit: (x, y) * aperture: (h_size, v_size) """ h_size = Component(UsaxsMotor, '9idcLAX:m58:c2:m8', labels=("uslit", )) x = Component(UsaxsMotor, '9idcLAX:m58:c2:m6', labels=("uslit", )) v_size = Component(UsaxsMotor, '9idcLAX:m58:c2:m7', labels=("uslit", )) y = Component(UsaxsMotor, '9idcLAX:m58:c2:m5', labels=("uslit", )) def set_size(self, *args, h=None, v=None): """move the slits to the specified size""" if h is None: raise ValueError("must define horizontal size") if v is None: raise ValueError("must define vertical size") move_motors(self.h_size, h, self.v_size, v)
class Monochromator(KohzuSeqCtl_Monochromator): """ Tweaks from apstools mono """ wavelength = Component(KohzuPositioner, "", readback_pv="BraggLambdaRdbkAO", setpoint_pv="BraggLambdaAO") energy = Component(KohzuPositioner, "", readback_pv="BraggERdbkAO", setpoint_pv="BraggEAO") theta = Component(KohzuPositioner, "", readback_pv="BraggThetaRdbkAO", setpoint_pv="BraggThetaAO") # No y1 at 4-ID-D y1 = None x2 = Component(EpicsMotor, 'm6', labels=('motors', 'mono')) y2 = Component(EpicsSignalRO, 'KohzuYRdbkAI', labels=('motors', 'mono')) z2 = Component(EpicsSignalRO, 'KohzuZRdbkAI', labels=('motors', 'mono')) thf2 = Component(EpicsMotor, 'm4', labels=('motors', 'mono')) chi2 = Component(EpicsMotor, 'm5', labels=('motors', 'mono')) table_x = Component(EpicsMotor, 'm7', labels=('motors', 'mono')) table_y = Component(EpicsMotor, 'm8', labels=('motors', 'mono')) feedback = FormattedComponent(MonoFeedback, '4id:') def calibrate_energy(self, value): """Calibrate the mono energy. Parameters ---------- value: float New energy for the current monochromator position. """ self.use_set.put('Set', use_complete=True) self.energy.put(value) self.use_set.put('Use', use_complete=True)
class EpicsMotorWithDial(EpicsMotor): """ add motor record's dial coordinates to EpicsMotor USAGE:: m1 = EpicsMotorWithDial('xxx:m1', name='m1') """ dial = Component(EpicsSignal, ".DRBV", write_pv=".DVAL")
class EpicsEsafExperimenterDevice(Device): """ Ophyd device for experimenter info from APS ESAF. .. autosummary:: ~clear """ badge_number = Component(EpicsSignal, "badgeNumber", string=True) email = Component(EpicsSignal, "email", string=True) first_name = Component(EpicsSignal, "firstName", string=True) last_name = Component(EpicsSignal, "lastName", string=True) def clear(self): """Clear the fields for this user.""" self.badge_number.put("") self.email.put("") self.first_name.put("") self.last_name.put("")
class TaxiFlyScanDevice(Device): """ BlueSky Device for APS taxi & fly scans Some EPICS fly scans at APS are triggered by a pair of EPICS busy records. The busy record is set, which triggers the external controls to do the fly scan and then reset the busy record. The first busy is called taxi and is responsible for preparing the hardware to fly. The second busy performs the actual fly scan. In a third (optional) phase, data is collected from hardware and written to a file. """ taxi = Component(EpicsSignal, "taxi", put_complete=True) fly = Component(EpicsSignal, "fly", put_complete=True) expected_triggers = Component(EpicsSignalRO, "calcNumTriggers") actual_triggers = Component(EpicsSignalRO, "numTrigsSent")
class Newport(PCDSMotorBase): """ PCDS implementation of the Motor Record for Newport motors This is a subclass of `PCDSMotorBase` that overwrites missings signals and disables the ``home`` method, because it will not work the same way for Newport motors. """ __doc__ += basic_positioner_init offset_freeze_switch = Component(Signal) home_forward = Component(Signal) home_reverse = Component(Signal) def home(self, *args, **kwargs): # This function should eventually be used. There is a way to home # Newport motors to a reference mark raise NotImplementedError("Homing is not yet implemented for Newport " "motors")
class FourCircleDiffractometer(DiffractometerMixin, E4CV): h = Component(PseudoSingle, '', labels=("hkl", "fourc")) k = Component(PseudoSingle, '', labels=("hkl", "fourc")) l = Component(PseudoSingle, '', labels=("hkl", "fourc")) omega = Component(EpicsMotor, MOTOR_PV_OMEGA, labels=("motor", "fourc")) chi = Component(EpicsMotor, MOTOR_PV_CHI, labels=("motor", "fourc")) phi = Component(EpicsMotor, MOTOR_PV_PHI, labels=("motor", "fourc")) tth = Component(EpicsMotor, MOTOR_PV_TTH, labels=("motor", "fourc"))
class MyMotor(EpicsMotorLimitsMixin, EpicsMotor): "add support for setting/changing motor limits and resolution" description = Component(EpicsSignal, ".DESC", kind="omitted") steps_per_rev = Component(EpicsSignal, ".SREV", kind="omitted") def initial_reconfig(self, egu, srev, lo, hi): """ initial motor record configuration, not a plan Don't do this on production IOCs since these parameters are usually required by hardware configurations. """ self.description.put(self.name) self.motor_egu.put(egu) self.steps_per_rev.put(srev) self.soft_limit_hi.put(max(lo, hi)) # short wait to let CA monitors update time.sleep(0.001) self.soft_limit_lo.put(min(lo, hi))
class FlatMirror(Device): """ Beamline flat mirror components. """ y_upstream = Component(EpicsMotor, 'm39', labels=('motor', 'mirrors'), kind='config') y_downstream = Component(EpicsMotor, 'm40', labels=('motor', 'mirrors'), kind='config') y = Component(EpicsSignal, 'M2t2.D', write_pv='M2avg', labels=('mirrors', ), kind='config') angle = Component(EpicsSignal, 'M2t2.C', write_pv='M2angl', labels=('mirrors', ), kind='config') x_upstream = Component(EpicsMotor, 'm37', labels=('motor', 'mirrors'), kind='config') x_downstream = Component(EpicsMotor, 'm38', labels=('motor', 'mirrors'), kind='config') x = Component(EpicsSignal, 'M2xt2.D', write_pv='M1xavg', labels=('mirrors', ), kind='config') x_angle = Component(EpicsSignal, 'M1xt2.C', write_pv='M1xangl', labels=('mirrors', ), kind='config') stripe = Component(EpicsSignal, 'DMir:Xpos:Mir2.VAL', string=True, labels=('mirrors', ), kind='config')
class Magnet6T(Device): """ 6T magnet setup """ # Motors # tabth = Component(EpicsMotor, 'm53', labels=('motors', 'magnets')) tabx = Component(EpicsMotor, 'm49', labels=('motors', 'magnets')) taby = Component(EpicsMotor, 'm50', labels=('motors', 'magnets')) tabth2 = Component(EpicsMotor, 'm56', labels=('motors', 'magnets')) tabz2 = Component(EpicsMotor, 'm51', labels=('motors', 'magnets')) tabx2 = Component(EpicsMotor, 'm52', labels=('motors', 'magnets')) sampy = Component(EpicsMotor, 'm63', labels=('motors', 'magnets')) sampth = Component(EpicsMotor, 'm58', labels=('motors', 'magnets')) # Magnetic field controller field = Component(AMIController, '4idd:AMI430:', add_prefix='')
class EnsemblePSOFlyDevice(TaxiFlyScanDevice): """ PSOfly control wrapper """ motor_pv_name = Component(EpicsSignalRO, "motorName") start = Component(EpicsSignal, "startPos") end = Component(EpicsSignal, "endPos") slew_speed = Component(EpicsSignal, "slewSpeed") # scan_delta: output a trigger pulse when motor moves this increment scan_delta = Component(EpicsSignal, "scanDelta") # advanced controls delta_time = Component(EpicsSignalRO, "deltaTime") detector_setup_time = Component(EpicsSignal, "detSetupTime") pulse_type = Component(EpicsSignal, "pulseType") scan_control = Component(EpicsSignal, "scanControl")
class TaxiFlyScanDevice(Device): """ BlueSky Device for APS taxi & fly scans Some EPICS fly scans at APS are triggered by a pair of EPICS busy records. The busy record is set, which triggers the external controls to do the fly scan and then reset the busy record. The first busy is called taxi and is responsible for preparing the hardware to fly. The second busy performs the actual fly scan. In a third (optional) phase, data is collected from hardware and written to a file. """ taxi = Component(EpicsSignal, "taxi", put_complete=True) fly = Component(EpicsSignal, "fly", put_complete=True) def plan(self): yield from bps.mv(self.taxi, self.taxi.enum_strs[1]) yield from bps.mv(self.fly, self.fly.enum_strs[1])
class DiffractionDetector(Device): # exposure_time = Component(Signal, value=1) image = Component(Signal, value=numpy.zeros(SHAPE)) signal_to_noise = Component(Signal, value=0) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.delay = 2 # simulated exposure time delay def trigger(self): "Generate a simulated reading with noise for the current sample." sample_number = sample_selector.get() arr, snr = generate_measured_image(sample_number) # Update the internal signal with a simulated image. self.image.set(arr) self.signal_to_noise.set(snr) # Simulate the exposure and readout time with a tunable "delay". return TimerStatus(self, self.delay) def collect_asset_docs(self): yield from []
class SRS340(Device): frequency = Component(EpicsSignal, 'FREQ.VAL', write_pv='SetFREQ.A', kind='config') amplitude = Component(EpicsSignal, 'AMPL.VAL', write_pv='SetAMPL.A', kind='config') offset = Component(EpicsSignal, 'OFFS.VAL', write_pv='SetOFFS.A', kind='config') function = Component(EpicsSignal, 'FUNC.SVAL', write_pv='FUNCs.VAL', kind='config')
class sim_s2(MotorBundle): h_ib = Component(EpicsMotor, "6iddSIM:m16", name='h_ib') h_ob = Component(EpicsMotor, "6iddSIM:m16", name='h_ob') h_size = Component(EpicsMotor, "6iddSIM:m16", name='h_size') v_tp = Component(EpicsMotor, "6iddSIM:m16", name='v_tp') v_bt = Component(EpicsMotor, "6iddSIM:m16", name='v_bt') v_size = Component(EpicsMotor, "6iddSIM:m16", name='v_size')
class sim_l2(MotorBundle): l2x = Component(EpicsMotor, "6iddSIM:m16", name='l2x') l2y = Component(EpicsMotor, "6iddSIM:m16", name='l2y') l2z = Component(EpicsMotor, "6iddSIM:m16", name='l2z') l2rot = Component(EpicsMotor, "6iddSIM:m16", name='l2rot') l2tx = Component(EpicsMotor, "6iddSIM:m16", name='l2tx') l2tz = Component(EpicsMotor, "6iddSIM:m16", name='l2tz')
class sim_l3(MotorBundle): l3x = Component(EpicsMotor, "6iddSIM:m16", name='l3x') l3y = Component(EpicsMotor, "6iddSIM:m16", name='l3y') l3z = Component(EpicsMotor, "6iddSIM:m16", name='l3z') l3rot = Component(EpicsMotor, "6iddSIM:m16", name='l3rot') l3tx = Component(EpicsMotor, "6iddSIM:m16", name='l3tx') l3tz = Component(EpicsMotor, "6iddSIM:m16", name='l3tz')
class sim_l4(MotorBundle): l4x = Component(EpicsMotor, "6iddSIM:m16", name='l4x') l4y = Component(EpicsMotor, "6iddSIM:m16", name='l4y') l4z = Component(EpicsMotor, "6iddSIM:m16", name='l4z') l4rot = Component(EpicsMotor, "6iddSIM:m16", name='l4rot') l4tx = Component(EpicsMotor, "6iddSIM:m16", name='l4tx') l4tz = Component(EpicsMotor, "6iddSIM:m16", name='l4tz')
class CyberstarDevice(Device): """ Hold cyberstar parameters, it is read through scaler channel. """ hv = Component(EpicsSignal, 'HV.VAL', write_pv='SetHV.A', kind='config') remote_on = Component(EpicsSignal, 'Remote.VAL', kind='config') gain = Component(EpicsSignal, 'Gain.VAL', write_pv='SetGain.VAL', kind='config') peak_time = Component(EpicsSignal, 'Pktime.VAL', write_pv='SetPktime.VAL', kind='config') sca_low = Component(EpicsSignal, 'SCAlo.VAL', write_pv='SetSCAlo.VAL', kind='config') sca_window = Component(EpicsSignal, 'SCAhi.VAL', write_pv='SetSCAhi.VAL', kind='config')
class PostEdgeDevice(Device): num_regions = Component(Signal, value=0) region1 = Component(PostEdgeRegion) region2 = Component(PostEdgeRegion) region3 = Component(PostEdgeRegion) region4 = Component(PostEdgeRegion) region5 = Component(PostEdgeRegion)
class sim_l1(MotorBundle): l1x = Component(EpicsMotor, "6iddSIM:m16", name='l1x') l1y = Component(EpicsMotor, "6iddSIM:m16", name='l1y') l1z = Component(EpicsMotor, "6iddSIM:m16", name='l1z') l1rot = Component(EpicsMotor, "6iddSIM:m16", name='l1rot') l1tx = Component(EpicsMotor, "6iddSIM:m16", name='l1tx') l1tz = Component(EpicsMotor, "6iddSIM:m16", name='l1tz')