コード例 #1
0
class AsciiScanfileSink(FileSink):
    """A data sink that writes to a plain ASCII data file."""
    parameters = {
        'commentchar':
        Param('Comment character', type=str, default='#', settable=True),
        'semicolon':
        Param('Whether to add a semicolon between X and Y '
              'values',
              type=bool,
              default=True),
    }

    handlerclass = AsciiScanfileSinkHandler

    parameter_overrides = {
        'settypes':
        Override(default=[SCAN, SUBSCAN]),
        'filenametemplate':
        Override(default=['%(proposal)s_%(scancounter)08d.dat']),
    }

    def doUpdateCommentchar(self, value):
        if len(value) > 1:
            raise ConfigurationError('comment character should only be '
                                     'one character')
コード例 #2
0
ファイル: safety.py プロジェクト: umithardal/nicos
class SafetyInputs(Readable):
    """The input devices for the safety system.

    The safety system has a lot of status lines which are connected to a
    separate input which is integrated into the NICOS system.
    """
    attached_devices = {
        'i7053': Attach('three 7053 modules', DigitalInput, multiple=3),
    }

    parameter_overrides = {
        'unit': Override(mandatory=False),
        'fmtstr': Override(default='%d'),
        'maxage': Override(default=0),
    }

    def _readHWState(self, maxage=0):
        state = 0
        for i, sdev in enumerate(self._attached_i7053):
            state |= (sdev.read(maxage) << (16 * i))
        return state

    def doRead(self, maxage=0):
        state = self._readHWState(maxage)
        self.log.info('val description')
        for i, bit in enumerate(bin(state)[2:][::-1]):
            self.log.info('%s   %s', bit, bit_description[i])
        return state

    def doStatus(self, maxage=0):
        # XXX define which bits may be active for normal state
        state = self._readHWState(maxage)
        return status.OK, str(state)
コード例 #3
0
ファイル: detector.py プロジェクト: ess-dmsc/nicos
class TimerChannelMixin(DeviceMixinBase):
    """Mixin for channels that return measured time."""

    is_timer = True

    parameter_overrides = {
        'unit': Override(default='s'),
        'fmtstr': Override(default='%.2f'),
    }

    def valueInfo(self):
        return Value(self.name,
                     unit=self.unit,
                     type='time',
                     fmtstr=self.fmtstr),

    def doTime(self, preset):
        if self.ismaster:
            return self.preselection
        return 0

    def doSimulate(self, preset):
        if self.ismaster:
            return [self.preselection]
        return [0.0]
コード例 #4
0
class BeamElement(HasTimeout, Moveable):
    """
    Class for readout of the MIRA shutter via digital input card, and closing
    the shutter via digital output (tied into Pilz security system).
    """

    valuetype = oneof('in', 'out')

    attached_devices = {
        'valve': Attach('in/out pressure valve', Moveable),
        'switch_in': Attach('limit switch for "in" position', Readable),
        'switch_out': Attach('limit switch for "out" position', Readable),
    }

    parameter_overrides = {
        'timeout': Override(default=10),
        'unit': Override(mandatory=False, default=''),
    }

    def doStatus(self, maxage=0):
        is_in = self._attached_switch_in.read(maxage)
        is_out = self._attached_switch_out.read(maxage)
        valvepos = self._attached_valve.read(maxage)
        if (is_in and valvepos == 'in') or (is_out and valvepos == 'out'):
            return status.OK, 'idle'
        return status.BUSY, 'moving'

    def doRead(self, maxage=0):
        return self._attached_valve.read(maxage)

    def doStart(self, target):
        self._attached_valve.start(target)

    def doReset(self):
        multiReset(self._adevs)
コード例 #5
0
class CCRSwitch(Moveable):
    """Class for FRM II sample environment CCR box switches (gas/vacuum).
    """

    attached_devices = {
        'write': Attach('TACO digital output device', DigitalOutput),
        'feedback': Attach('TACO digital input device (feedback)',
                           DigitalInput),
    }

    parameter_overrides = {
        'fmtstr': Override(default='%d'),
        'unit': Override(default='', mandatory=False),
    }

    valuetype = oneofdict({'on': 1, 'off': 0})

    def doStart(self, target):
        if self.read(0) != target:
            self._attached_write.start(1)

    def doStatus(self, maxage=0):
        return status.OK, ''

    def doRead(self, maxage=0):
        return self._attached_feedback.read(maxage)
コード例 #6
0
ファイル: gkssjson.py プロジェクト: umithardal/nicos
class SdsRatemeter(JsonBase):
    """Read the count rates for the different input channels of the SDS."""

    parameters = {
        'channel':
        Param('Channel to be rated',
              type=oneof('a', 'x', 'y'),
              default='a',
              settable=False)
    }

    parameter_overrides = {
        'fmtstr': Override(default='%d'),
        'unit': Override(default='cps'),
    }

    def doStatus(self, maxage=0):
        try:
            res = self._read_controller([self.valuekey])
            if int(res[self.valuekey]) == 0:
                return status.OK, ''
            else:
                return status.ERROR, 'System tripped! please clear'
        except CommunicationError:
            return status.WARN, 'Timeout during talk to the hardware.'
        except NicosError:
            return status.ERROR, 'Could not talk to hardware.'

    def doRead(self, maxage=0):
        res = self._read_controller(['mon_counts_cps_%s' % self.channel])
        res = int(res.values()[0])
        ret = int(res / 2.46)
        self.log.info('system %dfoo countrate %dcps', res, ret)
        return ret
コード例 #7
0
ファイル: ccmsans.py プロジェクト: umithardal/nicos
class AsymmetricMagnet(HasTimeout, CurrentSupply):
    """Class for the asymmetric ccmsans.

    Provides the ability to set the current field, and the asymmetry ratio.
    """

    parameters = {
        'asymmetry':
        Param('Asymmetry ratio',
              type=oneof(0.0, 0.11, 0.25, 0.39, 0.53, 0.70),
              settable=True,
              volatile=True),
    }

    parameter_overrides = {
        # default timeout: doTime() + 5 mins
        'timeout': Override(mandatory=False, default=300),
    }

    parameter_overrides = {
        # max range * max ramp + 5'
        'timeout': Override(mandatory=False, default=5400 + 300)
    }

    busystates = (status.BUSY, status.ERROR)
    valuetype = float

    def doReadAsymmetry(self):
        return float(
            self._taco_guard(self._dev.deviceQueryResource, 'asymmetry'))

    def doWriteAsymmetry(self, value):
        self._taco_update_resource('asymmetry', str(value))
コード例 #8
0
class VirtualTemperature(VirtualMotor):
    """A virtual temperature regulation device."""

    parameters = {
        'setpoint':  Param('Last setpoint', settable=True, unit='main',
                           category='general'),
    }

    parameter_overrides = {
        'unit':      Override(mandatory=False, default='K'),
        'jitter':    Override(default=0.1),
        'curvalue':  Override(default=10),
        'precision': Override(default=1),
    }

    def doStart(self, pos):
        self.setpoint = pos
        VirtualMotor.doStart(self, pos)

    def _step(self, start, end, elapsed, speed):
        # calculate an exponential approximation to the setpoint with a time
        # constant given by self.speed
        gamma = speed / 10.
        cval = end + (start - end) * exp(-gamma*elapsed)
        if abs(cval - end) < self.jitter:
            return end
        return cval
コード例 #9
0
ファイル: beamstop.py プロジェクト: umithardal/nicos
class BeamStopAxis(Axis):
    """special Axis, which always has an offset of 0
    """
    parameter_overrides = {
        'fixed': Override(type=oneof(''), default=''),
        'offset': Override(type=oneof(0.0), default=0.0),
        'lowlevel': Override(default=True),
        'maxtries': Override(default=1000, settable=False),
    }

    def doInit(self, mode):
        Axis.doInit(self, mode)
        if self.maxtries < 1000:
            self._setROParam('maxtries', 1000)
        self._setROParam('userlimits', self.abslimits)
        if mode not in (SIMULATION, SLAVE
                        ) and self._attached_motor.status()[0] != status.BUSY:
            self._attached_motor.doSetPosition(self._attached_coder.read())
            self._attached_motor.userlimits = self._attached_motor.abslimits

    def doReadOffset(self):
        return 0.

    def doWriteOffset(self, value):
        return 0.

    def doReadUserlimits(self):
        return Axis.doReadAbslimits(self)
コード例 #10
0
class YamlDatafileSink(AsciiScanfileSink):
    """A data sink that writes to a YAML compatible data file.

    The `lastpoint` parameter is managed automatically.

    The current file counter as well as the name of the most recently written
    scanfile is managed by the experiment device.
    """

    handlerclass = YamlDatafileSinkHandler

    parameters = {
        'filenametemplate':
        Param(
            'Name template for the files written',
            type=listof(str),
            userparam=False,
            settable=False,
            default=['%(proposal)s_'
                     '%(scancounter)08d.yaml'],
        ),
    }

    parameter_overrides = {
        'settypes': Override(default=[SCAN, SUBSCAN]),
        'semicolon': Override(default=''),
        'commentchar': Override(default='', )
    }
コード例 #11
0
class Detector(Moveable):
    """Combination device for the detector axes."""

    valuetype = tupleof(float, float, float)

    attached_devices = {
        'x': Attach('X motor', Moveable),
        'y': Attach('Y motor', Moveable),
        'z': Attach('Z motor', Moveable),
    }

    parameter_overrides = {
        'unit':   Override(mandatory=False, default='mm'),
        'fmtstr': Override(default='%.1f, %.2f, %.0f'),
    }

    def doRead(self, maxage=0):
        return (self._attached_x.read(maxage),
                self._attached_y.read(maxage),
                self._attached_z.read(maxage))

    def doIsAllowed(self, pos):
        for (i, name, dev) in [(0, 'x', self._attached_x),
                               (1, 'y', self._attached_y),
                               (2, 'z', self._attached_z)]:
            ok, why = dev.isAllowed(pos[i])
            if not ok:
                return False, name + ': ' + why
        return True, ''

    def doStart(self, pos):
        self._attached_x.start(pos[0])
        self._attached_y.start(pos[1])
        self._attached_z.start(pos[2])
コード例 #12
0
class Sans1ColliSwitcher(Switcher):
    """Switcher, specially adapted to Sans1 needs"""
    parameter_overrides = {
        'precision': Override(default=0.1, mandatory=False),
        'fallback': Override(default='Unknown', mandatory=False),
        'blockingmove': Override(default='False', mandatory=False),
    }

    def _mapReadValue(self, pos):
        """Override default inverse mapping to allow a deviation <= precision"""
        prec = self.precision

        def myiter(mapping):
            # use position names beginning with P as last option
            for name, value in mapping.items():
                if name[0] != 'P':
                    yield name, value
            for name, value in mapping.items():
                if name[0] == 'P':
                    yield name, value

        for name, value in myiter(self.mapping):
            if prec:
                if abs(pos - value) <= prec:
                    return name
            elif pos == value:
                return name
        if self.fallback is not None:
            return self.fallback
        if self.relax_mapping:
            return self._attached_moveable.format(pos, True)
        raise PositionError(self,
                            'unknown position of %s' % self._attached_moveable)
コード例 #13
0
class ComtecHeaderSink(ImageSink):
    """Base class for sinks that save arrays to "image" files."""

    attached_devices = {
        'detector': Attach('Fast Detector', ComtecTimer),
    }

    parameters = {
        'fast_basepaths': Param('Mount point(s) of the fast data storage',
                                type=listof(str), default=['/'],
                                settable=False),
    }

    parameter_overrides = {
        'settypes': Override(default=[POINT, SCAN]),
        'filenametemplate': Override(mandatory=False, settable=False,
                                     userparam=False,
                                     default=COMTEC_TEMPLATES),
        'subdir': Override(default='comtec'),
    }

    handlerclass = ComtecHeaderSinkHandler

    def doInit(self, mode):
        if mode != SIMULATION:
            # XXX: check existence of 'fast_basepath'
            pass
コード例 #14
0
class ComtecCounter(CounterChannelMixin, TacoBaseChannel, PassiveChannel):
    taco_class = Counter

    parameter_overrides = {
        'type':   Override(type=oneof('counter'), mandatory=False,
                           default='counter'),
        'mode':   Override(type=oneof('normal'), mandatory=False,
                           default='normal'),
        'fmtstr': Override(default='%d'),
    }

    def doReadMode(self):
        return 'normal'

    def doWriteMode(self, value):
        return 'normal'

    def doReadIsmaster(self):
        return False

    def doWriteIsmaster(self, value):
        return False

    def valueInfo(self):
        return Value(self.name, unit='cts', errors='sqrt',
                     type='counter', fmtstr='%d'),
コード例 #15
0
class McStasImage(BaseImage):

    parameter_overrides = {
        'size': Override(default=(625, 450)),
        'mcstasprog': Override(default='biodiff_fast'),
        'mcstasfile': Override(default='PSD_BIODIFF_total.psd'),
        'writedelay': Override(default=0.3),
    }

    attached_devices = {
        'sample': Attach('Mirror sample', SXTalSample),
        's1': Attach('Slit 1', Readable),
        's2': Attach('Slit 2', Readable),
        'omega': Attach('Sample omega rotation', Readable),
        'wavelength': Attach('Incoming wavelength', Readable),
        # 'sample_x': Attach('Sample position x', Readable),
        # 'sample_y': Attach('Sample position y', Readable),
        # 'sample_z': Attach('Sample position z', Readable),
        # 'beamstop': Attach('Beam stop positon', Readable),
    }

    def _prepare_params(self):
        params = []
        params.append('SLIT_S1=%s' % self._attached_s1.read(0))
        params.append('SLIT_S2=%s' % self._attached_s2.read(0))
        params.append('omega=%s' % self._attached_omega.read(0))
        sample = self._attached_sample
        params.append('cell_a=%s' % sample.a)
        params.append('cell_b=%s' % sample.b)
        params.append('cell_c=%s' % sample.c)
        params.append('Lam=%s' % self._attached_wavelength.read(0))
        params.append('dLam=%s' % 0.05)
        params.append('REP=%s' % 1000)
        return params
コード例 #16
0
class Switcher(GenericSwitcher):
    """
    Switcher, specially adapted to TOFTOF needs

    The neutron guide switcher has two different guides and the job is to
    change between them. Since there is no encoder mounted to check the
    position each change has to start with a reference move, followed by
    the move to the target position.
    """

    parameter_overrides = {
        'precision': Override(default=0.1, mandatory=False),
        'fallback': Override(default='Unknown', mandatory=False),
        'blockingmove': Override(default='False', mandatory=False),
    }

    def _startRaw(self, target):
        """Initiate movement of the moveable to the translated raw value."""
        if isinstance(self._attached_moveable, CanReference):
            self.log.info('referencing %s...', self._attached_moveable)
            self._attached_moveable.reference()
        else:
            self.log.warning('%s cannot be referenced!',
                             self._attached_moveable)
        self._attached_moveable.start(target)
        if self.blockingmove:
            self._attached_moveable.wait()
コード例 #17
0
class CaressScanfileSink(FileSink):
    """A data sink that writes the CARESS file format."""

    handlerclass = CaressScanfileSinkHandler

    parameters = {
        # Since some devices gives strings back as read values, but the CARESS
        # format does not accept strings they must be mapped to numbers
        'mapping':
        Param('Mapping of (string) device values to float values',
              unit='',
              settable=False,
              type=dictof(str, float),
              default={
                  'on': 1,
                  'off': 0,
                  'open': 1,
                  'closed': 0
              }),
    }

    parameter_overrides = {
        'settypes':
        Override(default=[SCAN, SUBSCAN]),
        # 'settypes': Override(default=[SCAN, SUBSCAN, POINT]),
        'filenametemplate':
        Override(
            default=['m2%(pointcounter)08d.dat', 'm2%(scancounter)08d.dat']),
    }
コード例 #18
0
class IPCSwitches(Input):
    """ IPC motor card read out for the limit switches and reference switch """

    parameter_overrides = {
        'first': Override(mandatory=False, default=5, settable=False),
        'last': Override(mandatory=False, default=7, settable=False),
    }

    def doInit(self, mode):
        Input.doInit(self, mode)  # init _mask
        if mode != SIMULATION:
            self._attached_bus.ping(self.addr)

    def doStatus(self, maxage=0):
        try:
            self._attached_bus.get(self.addr, 134)
            return status.OK, ''
        except NicosError:
            return status.ERROR, 'Hardware not found'

    def doRead(self, maxage=0):
        """ returns 0 if no switch is set
                    1 if the lower limit switch is set
                    2 if the upper limit switch is set
                    4 if the reference switch is set
        """
        try:
            # temp & 32 'low limit switch'
            # temp & 64 'high limit switch'
            # temp & 128 'ref switch'
            temp = self._attached_bus.get(self.addr, 134)
            return (temp & self._mask) >> self.first
        except Exception as err:
            raise NicosError(self,
                             'cannot evaluate status byte of stepper') from err
コード例 #19
0
ファイル: lens.py プロジェクト: umithardal/nicos
class Lenses(Moveable):
    """High-level lens control."""

    valuetype = oneof(*LENS_CONFIGS)

    hardware_access = False

    attached_devices = {
        'io': Attach('Lens I/O device', Moveable),
    }

    parameters = {
        'values':
        Param('Possible values (for GUI)',
              internal=True,
              type=listof(str),
              default=LENS_CONFIGS),
    }

    parameter_overrides = {
        'fmtstr': Override(default='%s'),
        'unit': Override(mandatory=False, default=''),
    }

    def doRead(self, maxage=0):
        lens_read = int(self._attached_io.read(maxage))
        configs = [('in' if lens_read & (1 << i) else 'out') for i in range(3)]
        return '-'.join(configs)

    def doStart(self, target):
        configs = [(v == 'in') for v in target.split('-')]
        bits = configs[0] + 2 * configs[1] + 4 * configs[2]
        self._attached_io.start(bits)
コード例 #20
0
ファイル: detector.py プロジェクト: ess-dmsc/nicos
class CounterChannelMixin(DeviceMixinBase):
    """Mixin for channels that return a single counts value."""

    is_timer = False

    parameters = {
        'type':
        Param('Type of channel: monitor or counter',
              type=oneof('monitor', 'counter', 'other'),
              mandatory=True),
    }

    parameter_overrides = {
        'unit': Override(default='cts'),
        'fmtstr': Override(default='%d'),
        'preselection': Override(type=int),
    }

    def valueInfo(self):
        return Value(self.name,
                     unit=self.unit,
                     errors='sqrt',
                     type=self.type,
                     fmtstr=self.fmtstr),

    def doSimulate(self, preset):
        if self.ismaster:
            return [int(self.preselection)]
        return [0]
コード例 #21
0
class Spectrum(VirtualImage):

    parameters = {
        'preselection': Param('Preset value for this channel', type=float,
                              settable=True),
    }

    parameter_overrides = {
        'sizes': Override(type=tupleof(intrange(1, 1), intrange(1, 16384)),
                          default=(1, 16384)),
        'ismaster': Override(settable=True),
    }

    # set to True to get a simplified doEstimateTime
    is_timer = False

    def doEstimateTime(self, elapsed):
        if not self.ismaster or self.doStatus()[0] != status.BUSY:
            return None
        if self.is_timer:
            return self.preselection - elapsed
        else:
            counted = float(self.doRead()[0])
            # only estimated if we have more than 3% or at least 100 counts
            if counted > 100 or counted > 0.03 * self.preselection:
                if 0 <= counted <= self.preselection:
                    return (self.preselection - counted) * elapsed / counted

    def doReadArray(self, _quality):
        return self._buf[0]
コード例 #22
0
ファイル: ubahn.py プロジェクト: umithardal/nicos
class UBahn(Readable):

    parameters = {
        'station':      Param('Name of the U-Bahn station', type=str,
                              settable=True,
                              default='Garching-Forschungszentrum'),
    }

    parameter_overrides = {
        'unit':         Override(mandatory=False, default='min'),
        'fmtstr':       Override(default='%s'),
        'pollinterval': Override(default=60),
        'maxage':       Override(default=70),
    }

    def doRead(self, maxage=0):
        if parse is None:
            raise NicosError(self, 'cannot parse web page, lxml is not '
                             'installed on this system')
        try:
            tree = parse(URL % self.station)
            return ', '.join(n.text for n in
                             tree.findall('//td[@class="inMinColumn"]'))
        except Exception as err:
            raise NicosError(self, 'MVG site not responding or changed format:'
                             ' %s' % err)

    def doStatus(self, maxage=0):
        return status.OK, ''
コード例 #23
0
ファイル: detector.py プロジェクト: ess-dmsc/nicos
class RectROIChannel(PostprocessPassiveChannel):
    """Calculates counts for a rectangular region of interest."""

    parameters = {
        'roi':
        Param('Rectangular region of interest (x, y, width, height)',
              tupleof(int, int, int, int),
              settable=True,
              category='general'),
    }

    parameter_overrides = {
        'unit': Override(default='cts'),
        'fmtstr': Override(default='%d'),
    }

    def getReadResult(self, arrays, _results, _quality):
        if any(self.roi):
            x, y, w, h = self.roi
            return [arr[y:y + h, x:x + w].sum() for arr in arrays]
        return [arr.sum() for arr in arrays]

    def valueInfo(self):
        if len(self.readresult) > 1:
            return tuple(
                Value(name=self.name + '[%d]' % i, type='counter', fmtstr='%d')
                for i in range(1,
                               len(self.readresult) + 1))
        return Value(name=self.name, type='counter', fmtstr='%d'),
コード例 #24
0
ファイル: roichan.py プロジェクト: umithardal/nicos
class LinearROIChannel(PostprocessPassiveChannel):
    """Calculates counts for a region of interest in a 1D spectrum."""

    parameters = {
        'roi':
        Param('Region of interest (start, end) including end',
              tupleof(int, int),
              settable=True,
              category='general'),
    }

    parameter_overrides = {
        'unit': Override(default='cts'),
        'fmtstr': Override(default='%d'),
    }

    def getReadResult(self, arrays, _results, _quality):
        if any(self.roi):
            return [arr[self.roi[0]:self.roi[1] + 1].sum() for arr in arrays]
        return [arr.sum() for arr in arrays]

    def valueInfo(self):
        if len(self.readresult) > 1:
            return tuple(
                Value(name=self.name + '[%d]' % i, type='counter', fmtstr='%d')
                for i in range(1,
                               len(self.readresult) + 1))
        return Value(name=self.name, type='counter', fmtstr='%d'),
コード例 #25
0
class ResedaHDF5Sink(FileSink):
    parameters = {
        'subscangrouptmpl':
        Param('Name of the sub scan specific group',
              type=str,
              default='echo_%(subscancounter)d'),
        'scalarstmpl':
        Param('Name of the scalars dataset',
              type=str,
              default='scalars_%(pointcounter)d'),
        'imagetmpl':
        Param('Name of the image dataset',
              type=str,
              default='image_%(pointcounter)d'),
    }

    parameter_overrides = {
        'filenametemplate':
        Override(mandatory=False,
                 settable=False,
                 userparam=False,
                 default=['%(scancounter)08d.hdf5']),
        'settypes':
        Override(default=[SCAN, SUBSCAN]),
    }

    handlerclass = ResedaHDF5SinkHandler

    def doInit(self, mode):
        self._current_scan_file = None

    def isActive(self, dataset):
        if dataset.settype != SCAN and self._current_scan_file is None:
            return False
        return FileSink.isActive(self, dataset)
コード例 #26
0
class Input(Readable):
    """IPC I/O card digital input class."""

    parameters = {
        'addr':
        Param('Bus address of the card',
              type=intrange(32, 255),
              mandatory=True),
        'first':
        Param('First bit to read', type=intrange(0, 15), mandatory=True),
        'last':
        Param('Last bit to read', type=intrange(0, 15), mandatory=True),
    }

    parameter_overrides = {
        'unit': Override(mandatory=False, default=''),
        'fmtstr': Override(default='%d'),
    }

    attached_devices = {
        'bus': Attach('The communication bus', IPCModBus),
    }

    def doInit(self, mode):
        self._mask = ((1 << (self.last - self.first + 1)) - 1) << self.first

    def doRead(self, maxage=0):
        high = self._attached_bus.get(self.addr, 181) << 8
        low = self._attached_bus.get(self.addr, 180)
        return ((high + low) & self._mask) >> self.first

    def doStatus(self, maxage=0):
        return status.OK, ''
コード例 #27
0
class FPLCTrigger(HasTimeout, Moveable):
    """Trigger the FPLC flow and then wait for the sample to be
    ready inside the cell.

    Used as a sample environment device in kwscount().
    """

    valuetype = oneof('triggered', 'waiting')

    hardware_access = True

    attached_devices = {
        'output': Attach('start output to FPLC', Moveable),
        'input':  Attach('trigger input from FPLC', Readable),
    }

    parameters = {
        'started':   Param('Time when device was started',
                           internal=True, settable=True),
        'triggered': Param('Time when input was triggered after a start',
                           internal=True, settable=True),
    }

    parameter_overrides = {
        'fmtstr':    Override(default='%s'),
        'timeout':   Override(default=120),
        'unit':      Override(mandatory=False, default=''),
    }

    def doInit(self, mode):
        if mode == MASTER:
            self.triggered = self.started = 0

    def doStart(self, target):
        if target == 'triggered':
            self._attached_output.start(1)
            sleep(0.1)
            self._attached_output.start(0)
            self.started = currenttime()

    def doStatus(self, maxage=0):
        if self.started:
            if self.mode == MASTER and self._attached_input.read(maxage):
                self.started = 0
                self.triggered = currenttime()
                return status.OK, 'triggered'
            else:
                return status.BUSY, 'waiting'
        elif self.triggered:
            if self.mode == MASTER and currenttime() > self.triggered + 5:
                self.triggered = 0
            return status.OK, 'triggered'
        return status.OK, ''

    def doRead(self, maxage=0):
        if self.started:
            return 'waiting'
        return 'triggered'
コード例 #28
0
class PolSwitcher(SequencerMixin, MultiSwitcher):
    """The turntable that contains the polarizer or neutron guide.

    Changing the table positions has to be done in a certain order, so that
    the final positions of the polarizer or guide are always reproducible.
    """

    parameters = {
        'movepos':  Param('Position (xv, yv, xh, yh) while rotating',
                          type=tupleof(float, float, float, float),
                          default=(5., 5., 5., 5.)),
    }

    parameter_overrides = {
        'fmtstr':     Override(default='%s'),
        'unit':       Override(mandatory=False, default=''),
    }

    def doInit(self, mode):
        MultiSwitcher.doInit(self, mode)
        if len(self._attached_moveables) != 5:
            raise ConfigurationError(self, 'must have exactly 5 moveables')
        self._mot_rot, self._mot_xv, self._mot_yv, self._mot_xh, \
            self._mot_yh = self._attached_moveables
        self.valuetype = oneof(*sorted(self.mapping, key=num_sort))

    def _generateSequence(self, target):
        seq = []
        targets = self.mapping[target]
        rot_target, xv_target, xh_target, yv_target, yh_target = targets
        # move translation units to move pos (in parallel)
        seq.append(tuple(SeqDev(m, p) for (m, p)
                         in zip(self._attached_moveables[1:], self.movepos)))
        # move rotation stage
        seq.append(SeqDev(self._mot_rot, rot_target))
        # move Y axes to final position with backlash
        seq.append((SeqDev(self._mot_yv, yv_target + 0.1),
                    SeqDev(self._mot_yh, yh_target + 0.1)))
        seq.append(SeqDev(self._mot_yv, yv_target))
        seq.append(SeqDev(self._mot_yh, yh_target))
        # move X axes to 0.1 and then to final position
        seq.append((SeqDev(self._mot_xv, 0.1),
                    SeqDev(self._mot_xh, 0.1)))
        seq.append(SeqDev(self._mot_xv, xv_target))
        seq.append(SeqDev(self._mot_xh, xh_target))
        # move rotation stage again, if it changed
        seq.append(SeqDev(self._mot_rot, rot_target))
        return seq

    def doStart(self, target):
        if self._seq_is_running():
            if self._mode == SIMULATION:
                self._seq_thread.join()
                self._seq_thread = None
            else:
                raise MoveError(self, 'Cannot start device, sequence is still '
                                      'running (at %s)!' % self._seq_status[1])
        self._startSequence(self._generateSequence(target))
コード例 #29
0
class VoltageSupply(PowerSupply):
    """work around a bug either in the taco server or in the hv supply itself

    basically the idle status is returned at the end of the ramp,
    even if the output voltage is nowhere near the target value
    """
    parameters = {
        '_stopflag':
        Param('Supply was stopped',
              type=bool,
              settable=True,
              mandatory=False,
              internal=True,
              default=False),
    }

    parameter_overrides = {
        'timeout': Override(default=90),
        'precision': Override(volatile=True),
    }

    _last_st = status.OK, ''

    def timeoutAction(self):
        if self.target is not None:
            self.log.warning('Timeout! retrying once to reach %s',
                             self.format(self.target, unit=True))
            # start() would clear timeoutActionCalled Flag
            self.start(self.target)

    def doStart(self, target):
        self._stopflag = False
        PowerSupply.doStart(self, target)

    def doStatus(self, maxage=0):
        # suppress intermittent tripped messages
        st = PowerSupply.doStatus(self, maxage)
        if st[0] == status.ERROR and 'trip' in st[1]:
            if 'trip' not in self._last_st[1]:
                st = (status.WARN, st[1])
        self._last_st = st
        return st

    def doStop(self):
        self._stopflag = True
        PowerSupply.doStop(self)
        self.wait()
        PowerSupply.doStart(self, self.read(0))
        self.wait()

    def doReset(self):
        self._stopflag = False
        self._dev.Reset()

    def doReadPrecision(self):
        if self.target == 1:
            return 69
        return 3
コード例 #30
0
class Polarizer(HasTimeout, Moveable):
    """Controls both the position of the polarizer and the spin flipper.
    """

    valuetype = oneof(*POL_SETTINGS)

    hardware_access = True

    attached_devices = {
        'output': Attach('output setter', Moveable),
        'input_in': Attach('input for limit switch "in" position', Readable),
        'input_out': Attach('input for limit switch "out" position', Readable),
        'flipper': Attach('3He flipper', Moveable),
    }

    parameter_overrides = {
        'fmtstr': Override(default='%s'),
        'timeout': Override(default=10),
        'unit': Override(mandatory=False, default=''),
    }

    parameters = {
        'values':
        Param('Possible values (for GUI)',
              internal=True,
              type=listof(str),
              default=POL_SETTINGS),
    }

    def doStatus(self, maxage=0):
        is_in = self._attached_input_in.read(maxage)
        is_out = self._attached_input_out.read(maxage)
        # check individual bits
        if is_in ^ is_out != 3:
            # inconsistent state, check switches
            if ((is_in & 2) and (is_out & 2)) or \
               ((is_in & 1) and (is_out & 1)):
                # both switches on?
                return status.ERROR, 'both switches on for element(s)'
            return status.BUSY, 'elements moving'
        # HasTimeout will check for target reached
        return self._attached_flipper.status(maxage)

    def doRead(self, maxage=0):
        is_in = self._attached_input_in.read(maxage)
        if is_in == 3:
            return self._attached_flipper.read()
        elif is_in > 0:
            return 'inconsistent'
        return 'out'

    def doStart(self, target):
        if target == 'out':
            self._attached_output.start(0)
        else:
            self._attached_output.start(3)
            self._attached_flipper.start(target)