Coverage for C: \ Users \ peaco \ OneDrive \ Documents \ GitHub \ mt_metadata \ mt_metadata \ transfer_functions \ io \ jfiles \ metadata \ header.py: 92%
78 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-10 00:11 -0800
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-10 00:11 -0800
1# =====================================================
2# Imports
3# =====================================================
4from typing import Annotated
6from pydantic import Field
8from mt_metadata.common import BasicLocation
10from . import BirrpAngles, BirrpBlock, BirrpParameters
13# =====================================================
14class Header(BasicLocation):
15 title: Annotated[
16 str,
17 Field(
18 default="",
19 description="title of file",
20 alias=None,
21 json_schema_extra={
22 "units": None,
23 "required": True,
24 "examples": ["BIRRP Version 5 basic mode output"],
25 },
26 ),
27 ]
29 station: Annotated[
30 str,
31 Field(
32 default="",
33 description="station name",
34 alias=None,
35 json_schema_extra={
36 "units": None,
37 "required": True,
38 "examples": ["mt001"],
39 },
40 ),
41 ]
43 azimuth: Annotated[
44 float,
45 Field(
46 default=0.0,
47 description="rotation of full impedance tensor",
48 alias=None,
49 json_schema_extra={
50 "units": "degrees",
51 "required": True,
52 "examples": ["0"],
53 },
54 ),
55 ]
57 birrp_parameters: Annotated[
58 BirrpParameters,
59 Field(
60 default_factory=BirrpParameters, # type: ignore
61 description="BIRRP parameters",
62 alias=None,
63 json_schema_extra={
64 "units": None,
65 "required": True,
66 "examples": ["BirrpParameters(...)"],
67 },
68 ),
69 ]
71 data_blocks: Annotated[
72 list[BirrpBlock],
73 Field(
74 default_factory=list,
75 description="BIRRP data blocks",
76 alias=None,
77 json_schema_extra={
78 "units": None,
79 "required": True,
80 "examples": ["BirrpBlock(...)"],
81 },
82 ),
83 ]
85 angles: Annotated[
86 list[BirrpAngles],
87 Field(
88 default_factory=list,
89 description="BIRRP angles",
90 alias=None,
91 json_schema_extra={
92 "units": None,
93 "required": True,
94 "examples": ["BirrpAngles(...)"],
95 },
96 ),
97 ]
99 def _read_header_line(self, line: str) -> dict:
100 """
101 Parse a single header line from the BIRRP output.
103 Parameters
104 ----------
105 line : str
106 A line from the BIRRP header.
108 Returns
109 -------
110 dict
111 A dictionary with the parsed key-value pairs.
112 """
114 line = " ".join(line[1:].strip().split())
116 new_line = ""
118 # need to restructure the string so its readable, at least the way
119 # that birrp outputs the file
120 e_find = 0
121 for ii in range(len(line)):
122 if line[ii] == "=":
123 e_find = ii
124 new_line += line[ii]
125 elif line[ii] == " ":
126 if abs(e_find - ii) == 1:
127 pass
128 else:
129 new_line += ","
130 else:
131 new_line += line[ii]
132 # now that we have a useful line, split it into its parts
133 line_list = new_line.split(",")
135 # try to split up the parts into a key=value setup
136 # and try to make the values floats if they can be
137 l_dict = {}
138 key = "null"
139 for ll in line_list:
140 ll_list = ll.split("=")
141 if len(ll_list) == 1:
142 continue
143 # some times there is just a list of numbers, need a way to read
144 # that.
145 if len(ll_list) != 2:
146 if type(l_dict[key]) is not list:
147 l_dict[key] = list([l_dict[key]])
148 try:
149 l_dict[key].append(float(ll))
150 except ValueError:
151 l_dict[key].append(ll)
152 else:
153 key = ll_list[0]
154 try:
155 value = float(ll_list[1])
156 except ValueError:
157 value = ll_list[1]
158 l_dict[key] = value
159 return l_dict
161 def read_header(self, j_lines: list[str]) -> None:
162 """
163 Parsing the header lines of a j-file to extract processing information.
165 Parameters
166 ----------
167 j_lines : str
168 The lines of the j-file as a string.
170 """
172 self.data_blocks = []
173 self.angles = []
175 header_lines = [j_line for j_line in j_lines if "#" in j_line]
176 self.title = header_lines[0][1:].strip()
178 fn_count = -1
179 theta_count = -1
180 # put the information into a dictionary
181 for h_line in header_lines[1:]:
182 h_dict = self._read_header_line(h_line)
183 for key, value in h_dict.items():
184 if key in [
185 "filnam",
186 "nskip",
187 "nread",
188 "ncomp",
189 "indices",
190 "nfil",
191 ]:
192 if key in ["nfil"]:
193 fn_count += 1
194 if len(self.data_blocks) != fn_count + 1:
195 self.data_blocks.append(BirrpBlock())
196 self.data_blocks[fn_count].update_attribute(key, value)
197 # if its the line of angles, put them all in a list with a unique key
198 elif key in ["theta1", "theta2", "phi"]:
199 if key == "theta1":
200 theta_count += 1
201 if len(self.angles) != theta_count + 1:
202 self.angles.append(BirrpAngles())
203 self.angles[theta_count].update_attribute(key, value)
204 else:
205 self.birrp_parameters.update_attribute(key, value)
207 def read_metadata(self, j_lines: list[str]) -> None:
208 """
209 Read in the metadata of the station, or information of station
210 logistics like: lat, lon, elevation
212 Parameters
213 ----------
214 j_lines : str
215 The lines of the j-file as a string.
217 Not really needed for a birrp output since all values are nan's
218 """
220 metadata_lines = [j_line for j_line in j_lines if ">" in j_line]
222 for m_line in metadata_lines:
223 m_list = m_line.strip().split("=")
224 m_key = m_list[0][1:].strip().lower()
225 try:
226 m_value = float(m_list[0].strip())
227 except ValueError:
228 m_value = 0.0
229 self.update_attribute(m_key, m_value)