Newer
Older
from datetime import timedelta
from obspy import UTCDateTime
from pydantic import BaseModel, Field, field_validator
from ...pydantic_utcdatetime import CustomUTCDateTimeType
Wernle, Alexandra Nicole
committed
class FlagCategory(str, Enum):
ARTIFICIAL_DISTURBANCE = "ARTIFICIAL_DISTURBANCE"
GAP = "GAP"
EVENT = "EVENT"
Wernle, Alexandra Nicole
committed
FIELD_WORK = "FIELD_WORK"
Wernle, Alexandra Nicole
committed
OTHER = "OTHER"
class Flag(BaseModel):
"""
Base class for flagging features in magnetic timeseries data.
Flag example:
```
automatic_flag = Metadata(
created_by='ex_algorithm',
start_time=UTCDateTime('2023-01-01T03:05:10'),
Wernle, Alexandra Nicole
committed
end_time=UTCDateTime('2023-01-01T03:10:11'),
network='NT',
station='BOU',
channel='BEH',
category=MetadataCategory.FLAG,
comment="spike detected",
priority=1,
Wernle, Alexandra Nicole
committed
data_valid=True,
metadata= ArtificialDisturbance{
Wernle, Alexandra Nicole
committed
"description": "Spikes in magnetic field strength",
Wernle, Alexandra Nicole
committed
"flag_category": ARTIFICIAL_DISTURBANCE,
"artificial_disturbance_type": ArtificialDisturbanceType.SPIKE,
"deviation": None,
Wernle, Alexandra Nicole
committed
"spikes": ['2023-01-01T03:05:10','2023-01-01T03:07:20','2023-01-01T03:10:11']
}
)
```
"""
description: str = Field(..., description="Description of the flag")
Wernle, Alexandra Nicole
committed
flag_category: FlagCategory = "OTHER"
class ArtificialDisturbanceType(str, Enum):
SPIKES = "SPIKES"
OFFSET = "OFFSET"
ARTIFICIAL_DISTURBANCES = "ARTIFICIAL_DISTURBANCES"
class ArtificialDisturbance(Flag):
"""
This class is used to flag artificial disturbances.
Artificial disturbances consist of the following types:
SPIKES = Single data points that are outliers in the timeseries.
OFFSET = A relatively constant shift or deviation in the baseline magnetic field.
ARTIFICIAL_DISTURBANCES = A catch-all for a continuous period of unwanted variations, may include multiple spikes, offsets and/or gaps.
Attributes
----------
artificial_disturbance_type:ArtificialDisturbanceType
The type of artificial disturbance(s).
deviation: float
Deviation of an offset in nt.
Wernle, Alexandra Nicole
committed
Array of timestamps as UTCDateTime. Can be a single spike or many spikes.
"""
artificial_disturbance_type: ArtificialDisturbanceType
spikes: Optional[List[CustomUTCDateTimeType]] = None
Wernle, Alexandra Nicole
committed
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.flag_category = FlagCategory.ARTIFICIAL_DISTURBANCE
Wernle, Alexandra Nicole
committed
Wernle, Alexandra Nicole
committed
def check_spikes_duration(cls, spikes):
if spikes is None or len(spikes) < 2:
return spikes
duration = spikes[-1] - spikes[0]
if duration > timedelta(days=1).total_seconds():
raise ValueError(
f"The duration between the first and last spike timestamp must not exceed 1 day. Duration: {duration} seconds"
)
return spikes
@classmethod
def check_spikes_match_times(cls, spikes, values):
metadata_starttime = values.get("starttime")
metadata_endtime = values.get("endtime")
if spikes[0] != metadata_starttime:
raise ValueError(
f"The first spike timestamp {spikes[0]} does not match the starttime {metadata_starttime}."
)
if spikes[-1] != metadata_endtime:
raise ValueError(
f"The last spike timestamp {spikes[-1]} does not match the endtime {metadata_endtime}."
)
class Gap(Flag):
"""
This class is used to flag gaps in data.
A gap is a period where data is missing or not recorded.
Attributes
----------
cause: str
Cause of gap, e.g., network outage.
handling: str
How the gap is being handled, e.g., backfilled.
"""
cause: Optional[str] = None
handling: Optional[str] = None
Wernle, Alexandra Nicole
committed
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Wernle, Alexandra Nicole
committed
class EventType(str, Enum):
GEOMAGNETIC_STORM = "GEOMAGNETIC_STORM"
GEOMAGNETIC_SUBSTORM = "GEOMAGNETIC_SUBSTORM"
EARTHQUAKE = "EARTHQUAKE"
OTHER = "OTHER"
class Event(Flag):
"""
This class is used to flag an event of interest such as a geomagnetic storm or earthquake.
Attributes
----------
event_type : EventType
The type of event.
scale : str
Geomagnetic storm scale or Richter scale magnitude.
index : int
Planetary K-index, DST index or some other index.
url : str
A url related to the event. Could be NOAA SWPC, USGS Earthquakes page or another site.
"""
event_type: EventType
index: Optional[int] = None
scale: Optional[str] = None
url: Optional[str] = None
Wernle, Alexandra Nicole
committed
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Wernle, Alexandra Nicole
committed
Wernle, Alexandra Nicole
committed
timestamps_array = [
UTCDateTime("2023-11-16T12:00:0"),
UTCDateTime("2023-11-16T12:01:10"),
UTCDateTime("2023-11-16T12:02:30"),
]
spikes_data = {
"starttime": "2023-11-16 12:00:00",
"endtime": "2023-11-16 12:02:30",
"description": "Spikes description",
"disturbance_type": ArtificialDisturbanceType.SPIKES,
"spikes": timestamps_array,
}
offset_data = {
"description": "Offset description",
"disturbance_type": ArtificialDisturbanceType.OFFSET,
"deviation": 10.0,
}
geomagnetic_storm_data = {
"description": "Geomagnetic storm",
"event_type": EventType.GEOMAGNETIC_STORM,
"scale": "G3",
"index": 7,
"url": "https://www.swpc.noaa.gov/products/planetary-k-index",
}