5@date 2025-06-28T04:42:00+09:00
6@brief reading utillities for configuration file of GET electronics
8import xml.etree.ElementTree
as ET
13from collections
import defaultdict
15def classify_indices(values):
17 @brief Classify indices by values in a list.
19 This function groups the indices of elements in the input list by their values.
21 @param values A list of values to be classified.
22 @return A dictionary where each key is a unique value and the value is a list of indices where it occurs.
24 index_dict = defaultdict(list)
25 for idx, val
in enumerate(values):
26 index_dict[val].append(idx)
27 return dict(index_dict)
29def get_tree(input_path):
31 @brief Parse an XML configuration file and return its root element.
33 @param input_path Path to the XML configuration file.
34 @return Root element of the parsed XML tree.
36 tree = ET.parse(input_path)
40def get_node(root, node_id_name='CoBo'):
42 @brief Retrieve a specific <Node> element by its ID from the XML tree.
44 @param root Root element of the XML tree.
45 @param node_id_name ID attribute value of the desired Node element (default is 'CoBo').
46 @return The Node element if found; otherwise, None.
49 cobo_node = root.find(f
".//Node[@id='{node_id_name}']")
52def get_instance(node, instance_id_name='*'):
54 @brief Retrieve a specific <Instance> element by its ID within a given <Node>.
56 @param node The parent Node element.
57 @param instance_id_name ID attribute value of the desired Instance element (default is '*').
58 @return The Instance element if found; otherwise, None.
60 instance = node.find(f
".//Instance[@id='{instance_id_name}']")
63def get_block(instance, label_name='AsAd', block_name='0' ):
65 @brief Retrieve a specific block element (e.g., AsAd or Aget) by tag and ID within an Instance.
67 @param instance The parent Instance element.
68 @param label_name The tag name of the block to find (e.g., 'AsAd', 'Aget').
69 @param block_name ID attribute of the block element to retrieve (default is '0').
70 @return The block element if found; otherwise, None.
72 block_data = instance.find(f
".//{label_name}[@id='{block_name}']")
75def print_tree(element, indent=0, indent_label=1):
77 @brief Recursively print elements at a specified depth level in an XML tree.
79 @param element The current element to print.
80 @param indent Current recursion depth (used internally).
81 @param indent_label Target depth level at which to print elements.
83 if indent == indent_label:
84 print(
" " * indent + f
"{element.tag}: {element.attrib}")
87 print_tree(child, indent + 1, indent_label)
89def write_text(input_path, output_path):
90 root = get_tree(input_path)
91 cobo_node = get_node(root)
93 cobos_list = [
'*',
'0',
'1',
'2',
'3']
94 asads_list = [
'*',
'0',
'1',
'2',
'3']
95 agets_list = [
'*',
'0',
'1',
'2',
'3']
99 for i
in range(len(cobos_list)):
100 instance = get_instance(cobo_node, cobos_list[i])
101 if instance
is not None:
103 cobo_id_block = instance.find(f
"./Module/coboId")
104 cobo_id = cobo_id_block.text
if cobo_id_block
is not None else -1
106 for j
in range(len(asads_list)):
107 asad = get_block(instance,
'AsAd', asads_list[j])
110 for k
in range(len(agets_list)):
111 aget = get_block(asad,
'Aget', agets_list[k])
114 global_threshold_block = aget.find(f
"./Global/Reg1/GlobalThresholdValue")
115 global_threshold = global_threshold_block.text
if (global_threshold_block
is not None)
else -1
117 channels = aget.findall(
'channel')
119 for l
in range(len(channels)):
120 lsb_threshold_block = channels[l].find(f
"./LSBThresholdValue")
121 lsb_threshold = lsb_threshold_block.text
if lsb_threshold_block
is not None else -1
123 threshold_map.append(
128 channels[l].attrib.get(
"id"),
135 pd_label_name = [
'cobo',
'asad',
'aget',
'channel',
'coboId',
'global_threshold',
'LSB_threshold']
137 data = pd.DataFrame(threshold_map, columns=pd_label_name)
138 data.to_csv(output_path, index=
False, sep=
'\t')
140def read_text(intput_path=None):
142 @brief Reads a tab-separated text file into a pandas DataFrame.
144 @param intput_path The path to the text file. If None, the function returns None.
145 @return A pandas DataFrame containing the loaded data, or None if no path is given.
147 if intput_path
is not None:
148 data = pd.read_csv(intput_path,sep=
'\t')
151def get_matching_indices(data, cobo_value, asad_value, aget_value, channel_value):
153 @brief Get indices of rows in a DataFrame that match specified values.
155 Each parameter can be set to a specific value (non-negative) to filter, or a negative value to ignore the filter.
157 @param data A pandas DataFrame that contains columns: `cobos`, `asads`, `agets`, `channels`.
158 @param cobo_value Integer. Cobo value to match (set < 0 to ignore).
159 @param asad_value Integer. Asad value to match (set < 0 to ignore).
160 @param aget_value Integer. Aget value to match (set < 0 to ignore).
161 @param channel_value Integer. Channel value to match (set < 0 to ignore).
162 @return A list of indices in the DataFrame where all specified values match.
164 matching_indices = []
166 for i
in range(len(data.ids)):
168 cobo_flag = data.cobos[i] == cobo_value
173 asad_flag = data.asads[i] == asad_value
178 aget_flag = data.agets[i] == aget_value
182 if channel_value >= 0:
183 chan_flag = data.channels[i] == channel_value
187 if chan_flag * aget_flag * asad_flag * cobo_flag ==
True:
188 matching_indices.append(i)
190 return matching_indices