3 from logging
import getLogger; log =
getLogger(
"DQDefects.defect_ids")
5 from ctypes
import Structure, c_uint, Union
as cUnion
7 from DQUtils.channel_mapping
import get_channel_ids_names
9 from .exceptions
import (DefectUnknownError,
12 from typing
import Set, Iterable, Tuple, Union, List
13 from collections.abc
import Mapping, MutableMapping
17 _fields_ = [(
"defect", c_uint, 31),
18 (
"is_virtual", c_uint, 1),
22 args = (
bool(self.is_virtual), self.defect)
23 return "(is_virtual=%s, defect=%i)" % args
27 _fields_ = [(
"as_int", c_uint),
28 (
"as_bitfield", DefectIDBitfield)]
34 if any(what == field[0]
for field
in DefectIDBitfield._fields_):
35 return getattr(self.as_bitfield, what)
36 raise AttributeError(what)
39 if any(what == field[0]
for field
in DefectIDBitfield._fields_):
40 return setattr(self.as_bitfield, what, value)
41 return super(DefectID, self).
__setattr__(what, value)
44 args = self.as_int, self.as_bitfield
45 return '<DefectID value=0x%08x fields=%r>' % args
48 defect_name: str, virtual: bool =
False) -> int:
50 Function to create a new defect ID.
52 We're abandoning the mapping of defect names to IDs (Oct 2012).
53 Hence here we just ask for the first open gap in ID numbers.
54 It works for virtual IDs as well, though via a bit of an edge case for
57 existing =
sorted(_
for _
in existing_map.values()
if not isinstance(_, str))
58 if len(existing) == 0:
62 for i, v
in enumerate(existing[1:]):
67 newid = existing[-1] + 1
69 did.is_virtual=virtual
70 log.debug(
"Chose new id: %r", did)
75 Contains the logic for storing knowledge of which defects exist, and their
81 self.
_defect_id_map: MutableMapping[Union[str,int], Union[str,int]] = {}
87 super(DefectsDBIDsNamesMixin, self).
__init__()
91 Called the first time any of defect_{ids,names,id_map,etc} is called,
92 and populates internal variables to store the channel ids/names for the
93 life of the DefectsDB instance.
102 Called the first time any of virtual_defect_{ids,names,id_map,etc} is called,
103 and populates internal variables to store the channel ids/names for the
104 life of the DefectsDB instance.
112 if item[0]
in all_defects)
113 except InvalidLogicTagError:
122 Internal function used to keep defect IDs/names uptodate.
131 Internal function used to keep defect IDs/names uptodate.
143 Gives the set of defect IDs that exist in COOL
153 Gives the set of defect names that exist in COOL
164 Gives the dictionary relating COOL channel ids to defect names and vice
165 versa, retrieving them from the database if necessary.
175 Returns the set of existing virtual defect IDs
185 Returns the set of existing virtual defect names
195 Returns a dict() mapping virtual defect names to IDs and vice-versa.
204 Returns the defect ID for a virtual defect.
205 Accepts a `channel` as an integer/string and returns it as an integer.
207 Will raise DefectUnknownError if `channel` is an unknown ID or string.
209 This function first checks against non-virtual defects, then virutal
210 defects. Thus virtual-defects are lazily loaded.
212 from builtins
import int
213 if isinstance(channel, int):
218 elif isinstance(channel, str):
224 raise RuntimeError(
"Invalid `channel` type, got %s, expected integer"
225 " or string" %
type(channel))
229 Returns a list of channels as IDs
233 def get_channels(self) -> Tuple[Set[int], Set[str], Mapping[Union[str, int], Union[str, int]]]:
235 Return channel IDs, names, and dict relating the two
241 Return channel IDs, names, and dict relating the two
247 For the list of channel IDs "channels", return dict mapping ID to
250 get_desc = self.defects_folder.channelDescription
252 for channel
in channels}
256 For the list of channel IDs "channels", return dict mapping ID to
259 get_desc = self.defect_logic_folder.channelDescription
261 for channel
in channels}
266 A dictionary of all (virtual and primary) defect descriptions
275 Set a defect description
279 folder = self.defect_logic_folder
281 folder = self.defects_folder
282 folder.setChannelDescription(chan_id, description.encode(
'utf-8'))
286 Returns True if the `defect_id` represents a virtual defect, False if it
287 is not and raises if it doesn't exist
290 `defect_id` : defect channel id or name
292 from builtins
import int
293 if isinstance(defect_id, int):
294 return DefectID(defect_id).is_virtual
296 if not isinstance(defect_id, str):
297 raise RuntimeError(
"Invalid defect_id, expected int or string")
309 Returns correct name(s) of defects, given name(s) that possibly differ
310 from the correct ones by case. Raises if an input name doesn't map to
311 any existing defect. You can pass either a string or an iterable
312 object as `defect_id`.
315 if isinstance(defect_id, str):
316 defect_id = [defect_id]
318 if any(
not isinstance(i, str)
for i
in defect_id):
319 raise ValueError(
'All input values must be strings')
321 uppered_defects = dict((i.upper(), i)
for i
in self.
defect_names)
327 if up
in uppered_defects:
328 rv.append(uppered_defects[up])