File: xgm.py

package info (click to toggle)
extra-data 1.20.0-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 952 kB
  • sloc: python: 10,421; makefile: 4
file content (85 lines) | stat: -rw-r--r-- 3,408 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import numpy as np

from .base import DeviceBase

class XGM(DeviceBase):
    control_keys = [
        ('beamPosition/ixPos', 'f4', ()),
        ('beamPosition/iyPos', 'f4', ()),
        ('current/bottom/output', 'f4', ()),
        ('current/bottom/rangeCode', 'i4', ()),
        ('current/left/output', 'f4', ()),
        ('current/left/rangeCode', 'i4', ()),
        ('current/right/output', 'f4', ()),
        ('current/right/rangeCode', 'i4', ()),
        ('current/top/output', 'f4', ()),
        ('current/top/rangeCode', 'i4', ()),
        ('gasDosing/measuredPressure', 'f4', ()),
        ('gasDosing/pressureSetPoint', 'f4', ()),
        ('gasSupply/gasTypeId', 'i4', ()),
        ('gasSupply/gsdCompatId', 'i4', ()),
        ('pollingInterval', 'i4', ()),
        ('pressure/dcr', 'f4', ()),
        ('pressure/gasType', 'i4', ()),
        ('pressure/pressure1', 'f4', ()),
        ('pressure/pressureFiltered', 'f4', ()),
        ('pressure/rd', 'f4', ()),
        ('pressure/rsp', 'f4', ()),
        ('pulseEnergy/conversion', 'f8', ()),
        ('pulseEnergy/crossUsed', 'f4', ()),
        ('pulseEnergy/gammaUsed', 'f4', ()),
        ('pulseEnergy/gmdError', 'i4', ()),
        ('pulseEnergy/nummberOfBrunches', 'f4', ()),
        ('pulseEnergy/photonFlux', 'f4', ()),
        ('pulseEnergy/pressure', 'f4', ()),
        ('pulseEnergy/temperature', 'f4', ()),
        ('pulseEnergy/usedGasType', 'i4', ()),
        ('pulseEnergy/wavelengthUsed', 'f4', ()),
        ('signalAdaption/dig', 'i4', ()),
    ]

    extra_run_values = [
        ('classId', None, 'DoocsXGM'),
    ]

    # Technically, only the part before the / is the output channel.
    # But there is a structure associated with the part one level after that,
    # and we don't know what else to call it.
    output_channels = ('output/data',)

    instrument_keys = [
        ('intensityTD', 'f4', (1000,)),
        ('intensityAUXTD', 'f4', (1000,)),
        ('intensitySigma/x_data', 'f4', (1000,)),
        ('intensitySigma/y_data', 'f4', (1000,)),
        ('xTD', 'f4', (1000,)),
        ('yTD', 'f4', (1000,)),
    ]

    def write_instrument(self, f):
        super().write_instrument(f)

        # Annotate intensityTD with some units to test retrieving them
        # Karabo stores ASCII strings, assigning bytes is a shortcut to mimic that
        ds = f[f'INSTRUMENT/{self.device_id}:output/data/intensityTD']
        ds.attrs['metricPrefixEnum']= np.array([14], dtype=np.int32)
        ds.attrs['metricPrefixName'] = b'micro'
        ds.attrs['metricPrefixSymbol'] = b'u'
        ds.attrs['unitEnum'] = np.array([15], dtype=np.int32)
        ds.attrs['unitName'] = b'joule'
        ds.attrs['unitSymbol'] = b'J'

        # Also annotate a CONTROL key, where attributes are split across
        # the parent key group and the value dataset.
        # (The timestamp dataset has its own, but distinct attributes)
        # Specific examples taken from p5696, r32
        grp = f[f'CONTROL/{self.device_id}/beamPosition/ixPos']
        grp.attrs['alias'] = b'IX.POS'
        grp.attrs['description'] = b'Calculated X position [mm]'
        grp.attrs['daqPolicy'] = np.array([-1], dtype=np.int32)

        # daqPolicy is intentionally different, the correct schema value
        # is -1 as above!
        ds = grp['value']
        ds.attrs['alias'] = b'IX.POS'
        ds.attrs['daqPolicy'] = np.array([1], dtype=np.int32)