Skip to content

qubic.results.primitives

PrimitiveResult

Bases: ABC, NDArrayOperatorsMixin

Class template for primitive (raw) results; essentially a wrapper around np.ndarray. Constructor accepts a bytes-like object (assumed to be read from FPGA memory), which is then unpacked into a numpy.ndarray like object. Class has built-in support for basic array operations using array_ufunc and array_function. Specific ufunc or array_function implementations can be overriden as needed in child classes. np.lib.mixins.NDArrayOperatorsMixin is inherited to support python operators such as +, *, etc.

Child classes must implement: _unpack(self, data): convert binary data into a numpy array word_size(self): static method that returns the number of 32-bit words per datum

Source code in qubic/results/primitives.py
 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
86
87
88
89
90
91
class PrimitiveResult(ABC, np.lib.mixins.NDArrayOperatorsMixin):
    """
    Class template for primitive (raw) results; essentially a wrapper around np.ndarray. 
    Constructor accepts a bytes-like object (assumed to be read from FPGA memory), 
    which is then unpacked into a numpy.ndarray like object. Class has built-in support
    for basic array operations using __array_ufunc__ and __array_function__. Specific 
    ufunc or array_function implementations can be overriden as needed in child classes.
    np.lib.mixins.NDArrayOperatorsMixin is inherited to support python operators such 
    as +, *, etc.

    Child classes must implement:
        _unpack(self, data): convert binary data into a numpy array
        word_size(self): static method that returns the number of 32-bit words per datum

    """
    def __init__(self, data: bytes | np.ndarray, n_total_shots: int = None):
        if isinstance(data, bytes):
            self._array = self._unpack(data)
        else:
            self._array = data

    @abstractmethod
    def word_size(self):
        """
        size of a single datum in 32-bit words
        """
        pass

    @abstractmethod
    def _unpack(self, data: bytes) -> np.ndarray:
        pass

    def __array__(self) -> np.ndarray:
        return self._array

    @property
    def __array_interface__(self):
        return self._array.__array_interface__

    def __getitem__(self, index):
        return self._array[index]

    def __setitem__(self, index, item):
        self._array[index] = item

    def __len__(self):
        return len(self._array)

    def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
        if 'out' in kwargs:
            assert isinstance(kwargs['out'], tuple)
            outtup = ()
            for i, out in enumerate(kwargs['out']):
                if isinstance(out, Number):
                    outtup += (out,)
                elif isinstance(out, self.__class__):
                    outtup += (out._array,)
                else:
                    return NotImplemented
            kwargs['out'] = outtup

        if method == '__call__':
            fnargs = []
            for input in inputs:
                if isinstance(input, Number):
                    fnargs.append(input)
                elif isinstance(input, self.__class__):
                    fnargs.append(self._array)
                else:
                    return NotImplemented
            result = ufunc(*fnargs, **kwargs)
            return self.__class__(result)
        else:
            return NotImplemented

    def __array_function__(self, func, types, args, kwargs):
        args = [np.asarray(x) for x in args]
        return func(*args, **kwargs)

    @property
    def shape(self):
        return self._array.shape

    def __repr__(self):
        return f'{type(self).__name__}({self._array})'

word_size() abstractmethod

size of a single datum in 32-bit words

Source code in qubic/results/primitives.py
28
29
30
31
32
33
@abstractmethod
def word_size(self):
    """
    size of a single datum in 32-bit words
    """
    pass

S11

Bases: PrimitiveResult

Accumulated S11 data

Source code in qubic/results/primitives.py
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
class S11(PrimitiveResult):
    """
    Accumulated S11 data
    """

    def __init__(self, data: bytes | np.ndarray, n_total_shots=None):
        super().__init__(data, n_total_shots)
        if n_total_shots is not None:
            self._array = np.reshape(self._array, (n_total_shots, -1))

    @staticmethod
    def word_size():
        """
        Returns
        -------
        int:
            size of each sample in (unit is 32-bit word)
        """
        return 2

    def _unpack(self, data: bytes) -> np.ndarray:
        data = np.frombuffer(data, dtype=np.uint32)
        signed_data = np.reshape(twoscomp_to_signed(data.astype(int), nbits=32), (-1, 2))
        return 1j*signed_data[:, 0] + signed_data[:, 1]

    @property
    def real(self) -> np.ndarray:
        return self._array.real

    @property
    def imag(self) -> np.ndarray:
        return self._array.imag

word_size() staticmethod

Returns:

Name Type Description
int

size of each sample in (unit is 32-bit word)

Source code in qubic/results/primitives.py
104
105
106
107
108
109
110
111
112
@staticmethod
def word_size():
    """
    Returns
    -------
    int:
        size of each sample in (unit is 32-bit word)
    """
    return 2

Sdbuf

Bases: PrimitiveResult

Data that has been state-discriminated using QubiCML.

Source code in qubic/results/primitives.py
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
class Sdbuf(PrimitiveResult):
    """
    Data that has been state-discriminated using QubiCML.
    """
    def __init__(self, data: bytes | np.ndarray, n_total_shots=None):
        super().__init__(data, n_total_shots)
        if n_total_shots is not None:
            self._array = np.reshape(self._array, (n_total_shots, -1))

    @staticmethod
    def word_size():
        return 1

    def _unpack(self, data: bytes) -> np.ndarray:
        data = np.frombuffer(data, dtype=np.int32)
        return (((data>>30)&0x3) + 1j*(data&0x3fffffff))

U32

Bases: PrimitiveResult

Generic uint32 type

Source code in qubic/results/primitives.py
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
class U32(PrimitiveResult):
    """
    Generic uint32 type
    """
    def __init__(self, data: bytes | np.ndarray, n_total_shots=None):
        super().__init__(data, n_total_shots)
        if n_total_shots is not None:
            self._array = np.reshape(self._array, (n_total_shots, -1))

    @staticmethod
    def word_size():
        return 1

    def _unpack(self, data: bytes) -> np.ndarray:
        return np.frombuffer(data, dtype=np.uint32)

get_result_class(name)

Given a name (usually dtype field in distproc.executable.ResultChannel), return the class representing that datatype. Converts from snake_case to CamelCase.

Source code in qubic/results/primitives.py
161
162
163
164
165
166
def get_result_class(name):
    """
    Given a `name` (usually `dtype` field in `distproc.executable.ResultChannel`), return 
    the class representing that datatype. Converts from snake_case to CamelCase.
    """
    return getattr(sys.modules[__name__], ''.join(word.capitalize() for word in name.split('_')))