Coverage for C: \ Users \ peaco \ OneDrive \ Documents \ GitHub \ mt_metadata \ mt_metadata \ processing \ aurora \ stations.py: 94%
71 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
6import pandas as pd
7from pydantic import Field, field_validator, ValidationInfo
9from mt_metadata.base import MetadataBase
10from mt_metadata.processing.aurora.station import Station
13# =====================================================
14class Stations(MetadataBase):
15 remote: Annotated[
16 list[Station],
17 Field(
18 default_factory=list,
19 description="list of remote sites",
20 alias=None,
21 json_schema_extra={
22 "units": None,
23 "required": True,
24 "examples": ["10"],
25 },
26 ),
27 ]
29 local: Annotated[
30 Station,
31 Field(
32 default_factory=Station, # type: ignore
33 description="local site",
34 alias=None,
35 json_schema_extra={
36 "units": None,
37 "required": True,
38 "examples": ["10"],
39 },
40 ),
41 ]
43 @field_validator("remote", mode="before")
44 def validate_remote(
45 cls, value: list[Station], info: ValidationInfo
46 ) -> list[Station]:
47 """
48 Method for unpacking rr_station info into mt_metadata object.
50 Developmnent Notes:
51 This function was raising an exception when trying to populate an aurora.Processing object
52 from a json.loads() dict.
53 TODO: add a description of input variable and use cases, ... it seems that we may not want
54 to support multiple rr stations yet.
56 Parameters
57 ----------
58 rr_station
60 Returns
61 -------
62 list of Station objects
64 """
65 remote = []
66 if isinstance(value, list):
67 for item in value:
68 if isinstance(item, Station):
69 remote.append(item)
70 elif isinstance(item, dict):
71 try:
72 station = Station() # type: ignore
73 station.from_dict(item)
74 remote.append(station)
75 except Exception as e:
76 raise ValueError("could not unpack dict to a Station object")
77 else:
78 raise TypeError(
79 f"list item must be Station object not {type(item)}"
80 )
82 elif isinstance(value, dict):
83 station = Station()
84 station.from_dict(value)
85 station.remote = True
86 remote.append(station)
88 elif isinstance(value, Station):
89 value.remote = True
90 remote.append(value)
92 elif isinstance(
93 value, str
94 ): # TODO: Add doc; what is this doing? This does not affect self._remote.
95 if len(value) > 4:
96 raise ValueError(f"not sure to do with {type(value)}")
97 # TODO: Add doc explaining what happens when rr_station is str of length 3.
99 else:
100 raise ValueError(f"not sure to do with {type(value)}")
102 return remote
104 def add_remote(self, rr: Station | dict):
105 """
106 add a remote station
108 Parameters
109 ----------
110 rr: Station | dict
111 remote station to add
112 """
114 if not isinstance(rr, (Station, dict)):
115 raise TypeError(f"List entry must be a Station object not {type(rr)}")
116 if isinstance(rr, dict):
117 obj = Station() # type: ignore
118 obj.from_dict(rr)
120 else:
121 obj = rr
123 obj.remote = True
125 self.remote.append(obj)
127 @property
128 def remote_dict(self) -> dict[str, Station]:
129 """
130 need to have a dictionary, but it can't be an attribute cause that
131 gets confusing when reading in a json file
133 Returns
134 -------
135 dict[str, Station]
136 dictionary of remote stations
138 """
139 return dict([(rr.id, rr) for rr in self.remote])
141 def from_dataset_dataframe(self, df: pd.DataFrame):
142 """
143 from a dataset dataframe
145 Parameters
146 ----------
147 df: pd.DataFrame
148 dataset dataframe to read from
150 Returns
151 -------
152 None
153 """
155 # Handle empty DataFrame case
156 if df.empty:
157 return
159 station = df[df.remote == False].station.unique()[0]
160 rr_stations = df[df.remote == True].station.unique()
162 self.local.from_dataset_dataframe(df[df.station == station])
164 for rr_station in rr_stations:
165 rr = Station() # type: ignore
166 rr.from_dataset_dataframe(df[df.station == rr_station])
167 self.add_remote(rr)
169 def to_dataset_dataframe(self) -> pd.DataFrame:
170 """
171 output a dataframe
173 Returns
174 -------
175 pd.DataFrame
176 dataframe representation of the station
177 """
179 df = self.local.to_dataset_dataframe()
180 for rr in self.remote:
181 remote_df = rr.to_dataset_dataframe()
182 df = pd.concat([df, remote_df]) # , axis=1, ignore_index=True)
184 df.reset_index(inplace=True, drop=True)
186 return df
188 def get_station(self, station_id: str) -> Station:
189 """
190 get a station object from the id
192 Parameters
193 ----------
194 station_id: str
195 ID of the station to retrieve
197 Returns
198 -------
199 Station
200 Station object corresponding to the given ID
202 """
204 if self.local.id == station_id:
205 return self.local
207 elif station_id in self.remote_dict.keys():
208 return self.remote_dict[station_id]
210 raise KeyError(f"could not find {station_id}")