anss-formats 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,23 @@
1
+ Metadata-Version: 2.4
2
+ Name: anss-formats
3
+ Version: 0.0.1
4
+ Summary: Python implementation of the library used to communicate seismic event detection information between systems
5
+ License: CC0-1.0
6
+ Keywords: anss,earthquakes,formats,detection
7
+ Author: John Patton
8
+ Author-email: jpatton@usgs.gov
9
+ Requires-Python: >3.9.1,<3.12
10
+ Classifier: License :: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Provides-Extra: pycurl
15
+ Requires-Dist: certifi (>=2024.07.04,<2025.0.0)
16
+ Requires-Dist: cryptography (>=44.0.1,<45.0.0)
17
+ Requires-Dist: docutils (!=0.21.post1)
18
+ Requires-Dist: dparse (>=0.6.2,<0.7.0)
19
+ Requires-Dist: pydantic (>=2.6.0,<3.0.0)
20
+ Requires-Dist: requests (>=2.32.2,<3.0.0)
21
+ Requires-Dist: twine (>=5.1.1,<6.0.0)
22
+ Project-URL: Homepage, https://gitlab.com/anss-netops/anss-data-formats
23
+ Project-URL: Repository, https://gitlab.com/anss-netops/anss-data-formats
@@ -0,0 +1,15 @@
1
+ anssformats/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ anssformats/amplitude.py,sha256=DCtkc6siT8dj0C3ynBM01rfaSpKOeHTc-51CDmspELg,647
3
+ anssformats/association.py,sha256=UjDmr213kSzCCIWHMDce06Xjzut3-l1IYKexxJR_C_I,1173
4
+ anssformats/beam.py,sha256=lKmdXi_9Y9kglXPrsDG8WT2_41ssX92PrLxxjws7wT4,1004
5
+ anssformats/channel.py,sha256=AQ6wrBCtMhXwN3gdxWQKkiutqnVB9H2FmbMrOY6CTC8,2240
6
+ anssformats/eventType.py,sha256=6DHjovVVGug5AU1WRKX3RxQbrnwSPlg2KNtH2sLX1Q0,1216
7
+ anssformats/filter.py,sha256=uOAUteSWeBvDcB12_9E_9sqe0wb6iR_lHZdjLv5agNM,675
8
+ anssformats/formatbasemodel.py,sha256=naZFyuL6YOIMdpYpxD91l7MbbG6eafz3-itzLilSoG8,1933
9
+ anssformats/machineLearning.py,sha256=6xwmv_F2VuxZl-ng7qUKlV7Mrlw6aQ-LKg6A6x3vdfo,3261
10
+ anssformats/pick.py,sha256=Spaw7Paw_UCkVxNSJxJSirmiXM3e2KEY8-nIwVgk2Vg,2867
11
+ anssformats/quality.py,sha256=PK5sPAoJTUgCrmQkiWTerEB2klWbR1ECAU-qIABpcjA,389
12
+ anssformats/source.py,sha256=G78YUwY2fimi8Uy0d1mKjaIIsEDUue50wdHpACQsSMU,398
13
+ anss_formats-0.0.1.dist-info/METADATA,sha256=zs6fyxG-cyhnIQb6n3wqGM0JDo8p0RnLEoNnwUerKMo,1006
14
+ anss_formats-0.0.1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
15
+ anss_formats-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.2.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
File without changes
@@ -0,0 +1,24 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import Field
4
+
5
+ from anssformats.formatbasemodel import FormatBaseModel
6
+
7
+
8
+ class Amplitude(FormatBaseModel):
9
+ """A conversion class used to create, parse, and validate amplitude data as part of
10
+ detection data.
11
+
12
+ Attributes
13
+ ----------
14
+
15
+ amplitude: optional float containing the amplitude
16
+
17
+ period: optional float containing the period
18
+
19
+ snr: optional float containing the signal to noise ratio, capped at 1E9
20
+ """
21
+
22
+ amplitude: Optional[float] = None
23
+ period: Optional[float] = Field(None, ge=0.0)
24
+ snr: Optional[float] = Field(None, ge=0.0, le=1e9)
@@ -0,0 +1,35 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import Field
4
+
5
+ from anssformats.formatbasemodel import FormatBaseModel
6
+
7
+
8
+ class Association(FormatBaseModel):
9
+ """A conversion class used to create, parse, and validate association data as part
10
+ of detection data.
11
+
12
+ Attributes
13
+ ----------
14
+
15
+ phase: optional string containing the associated phase name
16
+
17
+ distance: optional float containing the associated distance in degrees between the
18
+ detection's and the data's locations if associated
19
+
20
+ azimuth: optional float containing the associated azimuth in degrees between the
21
+ detection's and the data's locations if associated
22
+
23
+ residual: optional float containing the associated residual in seconds of the data
24
+ if associated
25
+
26
+ sigma: optional float containing the number of standard deviations of the data from
27
+ the calculated value if associated
28
+ """
29
+
30
+ phase: Optional[str] = Field(None, pattern=r"^[A-Za-z]+$")
31
+
32
+ distance: Optional[float] = Field(None, ge=0.0)
33
+ azimuth: Optional[float] = Field(None, ge=0.0)
34
+ residual: Optional[float] = None
35
+ sigma: Optional[float] = None
anssformats/beam.py ADDED
@@ -0,0 +1,34 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import Field
4
+
5
+ from anssformats.formatbasemodel import FormatBaseModel
6
+
7
+
8
+ class Beam(FormatBaseModel):
9
+ """A conversion class used to create, parse, and validate beam detection data.
10
+
11
+ Attributes
12
+ ----------
13
+
14
+ backAzimuth: float containing the back azimuth in degrees
15
+
16
+ backAzimuthError: optional float containing the back azimuth error
17
+
18
+ slowness: float containing the horizontal slowness
19
+
20
+ slownessError: optional float containing the horizontal slowness error
21
+
22
+ powerRatio: optional float containing the power ratio
23
+
24
+ powerRatioError: optional float containing the power ratio error
25
+ """
26
+
27
+ backAzimuth: float = Field(ge=0.0)
28
+ backAzimuthError: Optional[float] = Field(None, ge=0.0)
29
+
30
+ slowness: float = Field(ge=0.0)
31
+ slownessError: Optional[float] = Field(None, ge=0.0)
32
+
33
+ powerRatio: Optional[float] = Field(None, ge=0.0)
34
+ powerRatioError: Optional[float] = Field(None, ge=0.0)
anssformats/channel.py ADDED
@@ -0,0 +1,76 @@
1
+ from typing import Optional, List, Literal
2
+
3
+ from pydantic import Field, field_validator, ValidationInfo
4
+ from anssformats.formatbasemodel import FormatBaseModel
5
+
6
+
7
+ class ChannelGeometry(FormatBaseModel):
8
+ """A class holding the geojson geometry for the channel
9
+
10
+ type: string containing the type of this geometry
11
+
12
+ coordinates: List of floats containing the longitude in degrees, latitude in degrees, and elevation in meters, in that order
13
+ """
14
+
15
+ type: str = "Point"
16
+ coordinates: List[float]
17
+
18
+ # check that coordinates are valid
19
+ @field_validator("coordinates")
20
+ @classmethod
21
+ def validate_coordinates(
22
+ cls, value: List[float], info: ValidationInfo
23
+ ) -> List[float]:
24
+ if value is None:
25
+ raise ValueError("Missing coordinates")
26
+
27
+ if len(value) != 3:
28
+ raise ValueError("Incomplete coordinates")
29
+
30
+ # longitude
31
+ if value[0] < -180.0 or value[0] > 180.0:
32
+ raise ValueError("Longitude coordinate out of valid range")
33
+
34
+ # latitude
35
+ if value[1] < -90.0 or value[1] > 90.0:
36
+ raise ValueError("Latitude coordinate out of valid range")
37
+
38
+ # don't bother validating elevation
39
+ # value[2]
40
+
41
+ return value
42
+
43
+
44
+ class ChannelProperties(FormatBaseModel):
45
+ """A class holding the channe specific custom properties for a geojson point feature
46
+
47
+ Station: string containing the station code
48
+
49
+ Channel: optional string containing the channel code
50
+
51
+ Network: string containing the network code
52
+
53
+ Location: optional string containing the location code
54
+ """
55
+
56
+ station: str
57
+ channel: Optional[str] = None
58
+ network: str
59
+ location: Optional[str] = None
60
+
61
+
62
+ class Channel(FormatBaseModel):
63
+ """A conversion class used to create, parse, and validate geojson Channel data as part of
64
+ detection data.
65
+
66
+ type: string containing the type of this geojson
67
+
68
+ geometry: ChannelGeometry object containing the geojson geometry for this feature
69
+
70
+ properties: ChannelProperties object containing the channel properties
71
+ """
72
+
73
+ type: str = "Feature"
74
+
75
+ geometry: ChannelGeometry
76
+ properties: ChannelProperties
@@ -0,0 +1,37 @@
1
+ from typing import Literal, Optional
2
+
3
+ from anssformats.formatbasemodel import FormatBaseModel
4
+
5
+
6
+ class EventType(FormatBaseModel):
7
+ """A conversion class used to create, parse, and validate source data as part of
8
+ detection data. Detection formats supports a subset of the QuakeML 1.2 event types
9
+ that are automatically classifiable.
10
+
11
+ Attributes
12
+ ----------
13
+
14
+ type: optional string containing the type of detection that was found; allowed type
15
+ strings are: "Earthquake", "MineCollapse", "NuclearExplosion", "QuarryBlast",
16
+ "InducedOrTriggered", "RockBurst", "FluidInjection", "IceQuake", and
17
+ "VolcanicEruption"
18
+
19
+ certainty: optional string containing the certainty of the event type; allowed
20
+ strings are "Suspected" and "Confirmed"
21
+ """
22
+
23
+ type: Optional[
24
+ Literal[
25
+ "Earthquake",
26
+ "MineCollapse",
27
+ "NuclearExplosion",
28
+ "QuarryBlast",
29
+ "InducedOrTriggered",
30
+ "RockBurst",
31
+ "FluidInjection",
32
+ "IceQuake",
33
+ "VolcanicEruption",
34
+ ]
35
+ ] = None
36
+
37
+ certainty: Optional[Literal["Suspected", "Confirmed"]] = None
anssformats/filter.py ADDED
@@ -0,0 +1,25 @@
1
+ from typing import Optional
2
+
3
+ from anssformats.formatbasemodel import FormatBaseModel
4
+
5
+
6
+ class Filter(FormatBaseModel):
7
+ """A conversion class used to create, parse, and validate filter data as part of
8
+ detection data.
9
+
10
+ Attributes
11
+ ----------
12
+
13
+ type: optional string containing the type of filter
14
+
15
+ highPass: optional float containing the high pass frequency
16
+
17
+ lowPass: optional float containing the low pass frequency
18
+
19
+ units: optional string containing the filter frequency units
20
+ """
21
+
22
+ type: Optional[str] = None
23
+ highPass: Optional[float] = None
24
+ lowPass: Optional[float] = None
25
+ units: Optional[str] = None
@@ -0,0 +1,57 @@
1
+ from datetime import datetime
2
+ from typing import Any
3
+
4
+ from pydantic import BaseModel, GetCoreSchemaHandler
5
+ from pydantic_core import CoreSchema, core_schema
6
+
7
+
8
+ def convert_datetime_to_iso8601_with_z_suffix(dt: datetime) -> str:
9
+ """Convert provided datetime to an ISO 8601 UTC time string
10
+
11
+ Parameters
12
+ ----------
13
+ dt: Datetime containing the date time to convert
14
+
15
+ Returns
16
+ -------
17
+ A str containing the ISO 8601 UTC formatted time string
18
+ """
19
+ return dt.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z"
20
+
21
+
22
+ class FormatBaseModel(BaseModel):
23
+ """A Pydantic BaseModel used for any required formatting of keys and values"""
24
+
25
+ class Config:
26
+ # conversion for datetime to datetime string
27
+ json_encoders = {datetime: convert_datetime_to_iso8601_with_z_suffix}
28
+
29
+ def model_dump(self):
30
+ """Override the default model_dump method to always exclude None values"""
31
+ return super().model_dump(exclude_none=True)
32
+
33
+ def model_dump_json(self):
34
+ """Override the default model_dump_json method to always exclude None values"""
35
+ return super().model_dump_json(exclude_none=True)
36
+
37
+
38
+ class CustomDT(datetime):
39
+ """A convenience class used to strip all datetime objects of timezone information,
40
+ required to bypass Pydantic's automatic inclusion of timezone when parsing JSON
41
+ strings.
42
+ """
43
+
44
+ @classmethod
45
+ def validate_no_tz(cls, v: Any, info: core_schema.ValidationInfo) -> Any:
46
+ if isinstance(v, str):
47
+ return datetime.strptime(v, "%Y-%m-%dT%H:%M:%S.%fZ").replace(tzinfo=None)
48
+ else:
49
+ return v.replace(tzinfo=None)
50
+
51
+ @classmethod
52
+ def __get_pydantic_core_schema__(
53
+ cls, source_type: Any, handler: GetCoreSchemaHandler
54
+ ) -> CoreSchema:
55
+ return core_schema.with_info_plain_validator_function(
56
+ function=cls.validate_no_tz
57
+ )
@@ -0,0 +1,89 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import Field
4
+
5
+ from anssformats.eventType import EventType as EventTypeFormat
6
+ from anssformats.formatbasemodel import FormatBaseModel
7
+ from anssformats.source import Source as SourceFormat
8
+
9
+
10
+ class MachineLearning(FormatBaseModel):
11
+ """A conversion class used to create, parse, and validate value added MachineLearning
12
+ data from advanced algorithms such as machine learning as part of detection formats
13
+ data.
14
+
15
+ Attributes
16
+ ----------
17
+
18
+ phase: optional string containing MachineLearning phase name
19
+
20
+ phaseProbability: optional float containing the probability of the MachineLearning
21
+ phase name
22
+
23
+ distance: optional float containing the MachineLearning distance in degrees
24
+
25
+ distanceProbability: optional float containing the probability of the MachineLearning
26
+ distance
27
+
28
+ backAzimuth: optional float containing the MachineLearning back azimuth in degrees
29
+
30
+ backAzimuthProbability: optional float containing the probability of the
31
+ MachineLearning back azimuth
32
+
33
+ magnitude: optional float containing the MachineLearning magnitude
34
+
35
+ magnitudeType: optional string containing the MachineLearning magnitude type
36
+
37
+ magnitudeProbability: optional float containing the probability of the
38
+ MachineLearning magnitude
39
+
40
+ depth: optional float containing the MachineLearning depth in kilometers
41
+
42
+ depthProbability: optional float containing the probability of the MachineLearning
43
+ depth
44
+
45
+ eventType: optional EventType object containing the MachineLearning event type
46
+
47
+ eventTypeProbability: optional float containing the probability of the
48
+ MachineLearning event type
49
+
50
+ repickShift: optional float containing the repick shift value in seconds
51
+
52
+ repickSTD: optional float containing the repick shift standard deviation
53
+
54
+ repickCredibleIntervalLower: optional float containing the repick shift lower credible interval
55
+
56
+ repickCredibleIntervalUpper: optional float containing the repick shift upper credible interval
57
+
58
+ source: optional Source object containing the source of the MachineLearning
59
+ information
60
+ """
61
+
62
+ phase: Optional[str] = Field(None, pattern=r"^[A-Za-z]+$")
63
+ phaseProbability: Optional[float] = None
64
+
65
+ distance: Optional[float] = Field(None, ge=0.0)
66
+ distanceProbability: Optional[float] = None
67
+
68
+ backAzimuth: Optional[float] = Field(None, ge=0.0)
69
+ backAzimuthProbability: Optional[float] = None
70
+
71
+ magnitude: Optional[float] = Field(None, ge=-2.0, le=10.0)
72
+ magnitudeType: Optional[str] = None
73
+ magnitudeProbability: Optional[float] = None
74
+
75
+ depth: Optional[float] = Field(None, ge=-100.0, le=1500.0)
76
+ depthProbability: Optional[float] = None
77
+
78
+ eventType: Optional[EventTypeFormat] = None
79
+ eventTypeProbability: Optional[float] = None
80
+
81
+ distanceRangeHalfWidth: Optional[float] = None
82
+ distanceRangeSigma: Optional[float] = None
83
+
84
+ repickShift: Optional[float] = None
85
+ repickSTD: Optional[float] = None
86
+ repickCredibleIntervalLower: Optional[float] = None
87
+ repickCredibleIntervalUpper: Optional[float] = None
88
+
89
+ source: Optional[SourceFormat] = None
anssformats/pick.py ADDED
@@ -0,0 +1,79 @@
1
+ from typing import List, Literal, Optional
2
+
3
+ from pydantic import Field
4
+
5
+ from anssformats.amplitude import Amplitude
6
+ from anssformats.association import Association
7
+ from anssformats.beam import Beam
8
+ from anssformats.machineLearning import MachineLearning
9
+ from anssformats.filter import Filter
10
+ from anssformats.formatbasemodel import CustomDT, FormatBaseModel
11
+ from anssformats.channel import Channel, ChannelProperties
12
+ from anssformats.source import Source
13
+ from anssformats.quality import Quality
14
+
15
+
16
+ class Pick(FormatBaseModel):
17
+ """A conversion class used to create, parse, and validate pick detection data.
18
+
19
+ type: string identifying this message as a pick
20
+
21
+ id: string containing a unique identifier for this pick
22
+
23
+ channel: Channel object containing the station where the pick was made
24
+
25
+ source: Source object containing the source of the pick
26
+
27
+ time: datetime containing the arrival time of the phase that was picked
28
+
29
+ phase: optional string containing the seismic phase that was picked
30
+
31
+ polarity: optional string containing the phase polarity; allowed strings are "up"
32
+ and "down"
33
+
34
+ onset: optional string containing the phase onset; allowed strings are "impulsive",
35
+ "emergent", and "questionable"
36
+
37
+ pickerType: optional string containing the type of picker; allowed strings are "manual",
38
+ "raypicker", "filterpicker", "earthworm", and "other"
39
+
40
+ filterInfo: optional list of Filter objects containing the filter frequencies when the
41
+ pick was made
42
+
43
+ amplitude: optional Amplitude object containing the amplitude associated with the
44
+ pick
45
+
46
+ beamInfo: optional Beam object containing the waveform beam information associated with
47
+ the pick
48
+
49
+ associationInfo: optional Association object containing the association information
50
+ if this pick is used as data in a Detection
51
+
52
+ machineLearningInfo: optional machineLearning object containing the machineLearning
53
+ information of this pick
54
+
55
+ qualityInfo: optional quality object containing the quality
56
+ information of this pick
57
+ """
58
+
59
+ type: Literal["Pick"]
60
+ id: str
61
+
62
+ channel: Channel
63
+ source: Source
64
+ time: CustomDT
65
+
66
+ phase: Optional[str] = Field(None, pattern=r"^[A-Za-z]+$")
67
+ polarity: Optional[Literal["up", "down"]] = None
68
+ onset: Optional[Literal["impulsive", "emergent", "questionable"]] = None
69
+ pickerType: Optional[
70
+ Literal["manual", "raypicker", "filterpicker", "earthworm", "other"]
71
+ ] = None
72
+
73
+ filterInfo: Optional[List[Filter]] = None
74
+ amplitudeInfo: Optional[Amplitude] = None
75
+ beamInfo: Optional[Beam] = None
76
+
77
+ associationInfo: Optional[Association] = None
78
+ machineLearningInfo: Optional[MachineLearning] = None
79
+ qualityInfo: Optional[List[Quality]] = None
anssformats/quality.py ADDED
@@ -0,0 +1,17 @@
1
+ from anssformats.formatbasemodel import FormatBaseModel
2
+
3
+
4
+ class Quality(FormatBaseModel):
5
+ """A conversion class used to create, parse, and validate Quality data as part of
6
+ detection data.
7
+
8
+ Attributes
9
+ ----------
10
+
11
+ standard: string containing the name of the quality standard used
12
+
13
+ value: float containing the Quality value
14
+ """
15
+
16
+ standard: str
17
+ value: float
anssformats/source.py ADDED
@@ -0,0 +1,17 @@
1
+ from anssformats.formatbasemodel import FormatBaseModel
2
+
3
+
4
+ class Source(FormatBaseModel):
5
+ """A conversion class used to create, parse, and validate source data as part of
6
+ detection data.
7
+
8
+ Attributes
9
+ ----------
10
+
11
+ agencyID: string containing the originating agency FDSN ID
12
+
13
+ author: string containing the source author
14
+ """
15
+
16
+ agencyID: str
17
+ author: str