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,
13 from typing
import Set, Iterable, Tuple, Union, List
14 from collections.abc
import Mapping, MutableMapping
18 _fields_ = [(
"defect", c_uint, 31),
19 (
"is_virtual", c_uint, 1),
23 args = (
bool(self.is_virtual), self.defect)
24 return "(is_virtual=%s, defect=%i)" % args
28 _fields_ = [(
"as_int", c_uint),
29 (
"as_bitfield", DefectIDBitfield)]
35 if any(what == field[0]
for field
in DefectIDBitfield._fields_):
36 return getattr(self.as_bitfield, what)
37 raise AttributeError(what)
40 if any(what == field[0]
for field
in DefectIDBitfield._fields_):
41 return setattr(self.as_bitfield, what, value)
42 return super(DefectID, self).
__setattr__(what, value)
45 args = self.as_int, self.as_bitfield
46 return '<DefectID value=0x%08x fields=%r>' % args
49 defect_name: str, virtual: bool =
False) -> int:
51 Function to create a new defect ID.
53 We're abandoning the mapping of defect names to IDs (Oct 2012).
54 Hence here we just ask for the first open gap in ID numbers.
55 It works for virtual IDs as well, though via a bit of an edge case for
58 existing =
sorted(_
for _
in six.itervalues(existing_map)
if not isinstance(_, six.string_types))
59 if len(existing) == 0:
63 for i, v
in enumerate(existing[1:]):
68 newid = existing[-1] + 1
70 did.is_virtual=virtual
71 log.debug(
"Chose new id: %r", did)
76 Contains the logic for storing knowledge of which defects exist, and their
82 self.
_defect_id_map: MutableMapping[Union[str,int], Union[str,int]] = {}
88 super(DefectsDBIDsNamesMixin, self).
__init__()
92 Called the first time any of defect_{ids,names,id_map,etc} is called,
93 and populates internal variables to store the channel ids/names for the
94 life of the DefectsDB instance.
103 Called the first time any of virtual_defect_{ids,names,id_map,etc} is called,
104 and populates internal variables to store the channel ids/names for the
105 life of the DefectsDB instance.
113 if item[0]
in all_defects)
114 except InvalidLogicTagError:
123 Internal function used to keep defect IDs/names uptodate.
132 Internal function used to keep defect IDs/names uptodate.
144 Gives the set of defect IDs that exist in COOL
154 Gives the set of defect names that exist in COOL
165 Gives the dictionary relating COOL channel ids to defect names and vice
166 versa, retrieving them from the database if necessary.
176 Returns the set of existing virtual defect IDs
186 Returns the set of existing virtual defect names
196 Returns a dict() mapping virtual defect names to IDs and vice-versa.
205 Returns the defect ID for a virtual defect.
206 Accepts a `channel` as an integer/string and returns it as an integer.
208 Will raise DefectUnknownError if `channel` is an unknown ID or string.
210 This function first checks against non-virtual defects, then virutal
211 defects. Thus virtual-defects are lazily loaded.
213 from builtins
import int
214 if isinstance(channel, int):
219 elif isinstance(channel, six.string_types):
225 raise RuntimeError(
"Invalid `channel` type, got %s, expected integer"
226 " or string" %
type(channel))
230 Returns a list of channels as IDs
234 def get_channels(self) -> Tuple[Set[int], Set[str], Mapping[Union[str, int], Union[str, int]]]:
236 Return channel IDs, names, and dict relating the two
242 Return channel IDs, names, and dict relating the two
248 For the list of channel IDs "channels", return dict mapping ID to
251 get_desc = self.defects_folder.channelDescription
253 for channel
in channels}
257 For the list of channel IDs "channels", return dict mapping ID to
260 get_desc = self.defect_logic_folder.channelDescription
262 for channel
in channels}
267 A dictionary of all (virtual and primary) defect descriptions
276 Set a defect description
280 folder = self.defect_logic_folder
282 folder = self.defects_folder
283 folder.setChannelDescription(chan_id, description.encode(
'utf-8'))
287 Returns True if the `defect_id` represents a virtual defect, False if it
288 is not and raises if it doesn't exist
291 `defect_id` : defect channel id or name
293 from builtins
import int
294 if isinstance(defect_id, int):
295 return DefectID(defect_id).is_virtual
297 if not isinstance(defect_id, six.string_types):
298 raise RuntimeError(
"Invalid defect_id, expected int or string")
310 Returns correct name(s) of defects, given name(s) that possibly differ
311 from the correct ones by case. Raises if an input name doesn't map to
312 any existing defect. You can pass either a string or an iterable
313 object as `defect_id`.
316 if isinstance(defect_id, six.string_types):
317 defect_id = [defect_id]
319 if any(
not isinstance(i, six.string_types)
for i
in defect_id):
320 raise ValueError(
'All input values must be strings')
322 uppered_defects = dict((i.upper(), i)
for i
in self.
defect_names)
328 if up
in uppered_defects:
329 rv.append(uppered_defects[up])