catm-python-lib
Loading...
Searching...
No Matches
xcfgreader.py
Go to the documentation of this file.
1"""!
2@file xcfgreader.py
3@version 1
4@author Fumitaka ENDO
5@date 2025-06-28T04:42:00+09:00
6@brief reading utillities for configuration file of GET electronics
7"""
8import xml.etree.ElementTree as ET
9import pandas as pd
10import sys
11import numpy as np
12import os
13from collections import defaultdict
14
15def classify_indices(values):
16 """!
17 @brief Classify indices by values in a list.
18
19 This function groups the indices of elements in the input list by their values.
20
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.
23 """
24 index_dict = defaultdict(list)
25 for idx, val in enumerate(values):
26 index_dict[val].append(idx)
27 return dict(index_dict)
28
29def get_tree(input_path):
30 """!
31 @brief Parse an XML configuration file and return its root element.
32
33 @param input_path Path to the XML configuration file.
34 @return Root element of the parsed XML tree.
35 """
36 tree = ET.parse(input_path)
37 root = tree.getroot()
38 return root
39
40def get_node(root, node_id_name='CoBo'):
41 """!
42 @brief Retrieve a specific <Node> element by its ID from the XML tree.
43
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.
47 """
48 root = get_tree()
49 cobo_node = root.find(f".//Node[@id='{node_id_name}']")
50 return cobo_node
51
52def get_instance(node, instance_id_name='*'):
53 """!
54 @brief Retrieve a specific <Instance> element by its ID within a given <Node>.
55
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.
59 """
60 instance = node.find(f".//Instance[@id='{instance_id_name}']")
61 return instance
62
63def get_block(instance, label_name='AsAd', block_name='0' ):
64 """!
65 @brief Retrieve a specific block element (e.g., AsAd or Aget) by tag and ID within an Instance.
66
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.
71 """
72 block_data = instance.find(f".//{label_name}[@id='{block_name}']")
73 return block_data
74
75def print_tree(element, indent=0, indent_label=1):
76 """!
77 @brief Recursively print elements at a specified depth level in an XML tree.
78
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.
82 """
83 if indent == indent_label:
84 print(" " * indent + f"{element.tag}: {element.attrib}")
85
86 for child in element:
87 print_tree(child, indent + 1, indent_label)
88
89def write_text(input_path, output_path):
90 root = get_tree(input_path)
91 cobo_node = get_node(root)
92
93 cobos_list = ['*','0','1','2','3']
94 asads_list = ['*','0','1','2','3']
95 agets_list = ['*','0','1','2','3']
96
97 threshold_map = []
98
99 for i in range(len(cobos_list)):
100 instance = get_instance(cobo_node, cobos_list[i])
101 if instance is not None:
102
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
105
106 for j in range(len(asads_list)):
107 asad = get_block(instance,'AsAd', asads_list[j])
108 if asad is not None:
109
110 for k in range(len(agets_list)):
111 aget = get_block(asad,'Aget', agets_list[k])
112 if aget is not None:
113
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
116
117 channels = aget.findall('channel')
118
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
122
123 threshold_map.append(
124 [
125 cobos_list[i],
126 asads_list[j],
127 agets_list[k],
128 channels[l].attrib.get("id"),
129 cobo_id,
130 global_threshold,
131 lsb_threshold
132 ]
133 )
134
135 pd_label_name = ['cobo', 'asad', 'aget', 'channel','coboId','global_threshold','LSB_threshold']
136
137 data = pd.DataFrame(threshold_map, columns=pd_label_name)
138 data.to_csv(output_path, index=False, sep='\t')
139
140def read_text(intput_path=None):
141 """!
142 @brief Reads a tab-separated text file into a pandas DataFrame.
143
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.
146 """
147 if intput_path is not None:
148 data = pd.read_csv(intput_path,sep='\t')
149 return data
150
151def get_matching_indices(data, cobo_value, asad_value, aget_value, channel_value):
152 """!
153 @brief Get indices of rows in a DataFrame that match specified values.
154
155 Each parameter can be set to a specific value (non-negative) to filter, or a negative value to ignore the filter.
156
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.
163 """
164 matching_indices = []
165
166 for i in range(len(data.ids)):
167 if cobo_value >= 0:
168 cobo_flag = data.cobos[i] == cobo_value
169 else:
170 cobo_flag = True
171
172 if asad_value >= 0:
173 asad_flag = data.asads[i] == asad_value
174 else:
175 asad_flag = True
176
177 if aget_value >= 0:
178 aget_flag = data.agets[i] == aget_value
179 else:
180 aget_flag = True
181
182 if channel_value >= 0:
183 chan_flag = data.channels[i] == channel_value
184 else:
185 chan_flag = True
186
187 if chan_flag * aget_flag * asad_flag * cobo_flag == True:
188 matching_indices.append(i)
189
190 return matching_indices