utdquake 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.
utdquake/__init__.py ADDED
File without changes
File without changes
File without changes
@@ -0,0 +1,123 @@
1
+ # /**
2
+ # * @author Emmanuel Castillo
3
+ # * @email [castillo.280997@gmail.com]
4
+ # * @create date 2024-09-22 22:07:55
5
+ # * @modify date 2024-09-22 22:07:55
6
+ # * @desc [description]
7
+ # */
8
+
9
+
10
+
11
+
12
+ # import objects
13
+ import os
14
+ import glob
15
+ import sqlite3
16
+ import pandas as pd
17
+ from obspy import UTCDateTime
18
+ from datetime import timedelta
19
+ from obspy.core.util.misc import BAND_CODE
20
+ from scan.stats import get_rolling_stats
21
+ from obspy.clients.fdsn import Client as FDSNClient
22
+ from obspy.clients.filesystem.sds import Client
23
+
24
+ class LocalClient(Client):
25
+
26
+ def __init__(self,root,fmt,**kwargs):
27
+ """
28
+ This script is an example to make a client class
29
+ for specific data structure archive on local filesystem.
30
+
31
+ The mandatory parameters for LocalClient class is: root_path and field_name
32
+ Example:
33
+ ---------
34
+ root = "/home/emmanuel/myarchive"
35
+ fmt = "{year}-{month:02d}/{year}-{month:02d}-{day:02d}/{network}.{station}.{location}.{channel}.{year}.{julday:03d}"
36
+ client = LocalClient(root,fmt)
37
+ st = client.get_waveforms("YY","XXXX","00",
38
+ channel="HHZ",starttime = UTCDateTime("20220102T000100"),
39
+ endtime = UTCDateTime("20220102T000200"))
40
+
41
+ Parameters:
42
+ -----------
43
+ root: str
44
+ Path where is located the Local structure
45
+ fmt: str
46
+ The parameter should name the corresponding keys of the stats object, e.g.
47
+ "{year}-{month:02d}/{year}-{month:02d}-{day:02d}/{network}.{station}.{location}.{channel}.{year}.{julday:03d}"
48
+
49
+ **kwargs SDS client additional args
50
+ """
51
+ self.root = root
52
+ self.fmt = fmt
53
+ super().__init__(root,**kwargs)
54
+
55
+ def _get_filenames(self, network, station, location, channel, starttime,
56
+ endtime, sds_type=None):
57
+ """
58
+ Get list of filenames for certain waveform and time span.
59
+ :type network: str
60
+ :param network: Network code of requested data (e.g. "IU").
61
+ :type station: str
62
+ :param station: Station code of requested data (e.g. "ANMO").
63
+ :type location: str
64
+ :param location: Location code of requested data (e.g. "").
65
+ :type channel: str
66
+ :param channel: Channel code of requested data (e.g. "HHZ").
67
+ :type time: :class:`~obspy.core.utcdatetime.UTCDateTime`
68
+ :param time: Time of interest.
69
+ :type sds_type: str
70
+ :param sds_type: None
71
+ :rtype: str
72
+ """
73
+ sds_type = sds_type or self.sds_type
74
+ # SDS has data sometimes in adjacent days, so also try to read the
75
+ # requested data from those files. Usually this is only a few seconds
76
+ # of data after midnight, but for now we play safe here to catch all
77
+ # requested data (and with MiniSEED - the usual SDS file format - we
78
+ # can use starttime/endtime kwargs anyway to read only desired parts).
79
+ year_doy = set()
80
+ # determine how far before starttime/after endtime we should check
81
+ # other dayfiles for the data
82
+ t_buffer = self.fileborder_samples / BAND_CODE.get(channel[:1], 20.0)
83
+ t_buffer = max(t_buffer, self.fileborder_seconds)
84
+ t = starttime - t_buffer
85
+ t_max = endtime + t_buffer
86
+ # make a list of year/doy combinations that covers the whole requested
87
+ # time window (plus day before and day after)
88
+ while t < t_max:
89
+ year_doy.add((t.year,t.month,t.day, t.julday))
90
+ t += timedelta(days=1)
91
+ year_doy.add((t_max.year,t_max.month,t_max.day, t_max.julday))
92
+
93
+ full_paths = set()
94
+ for year,month,day,doy in year_doy:
95
+ filename = self.fmt.format(
96
+ network=network, station=station, location=location,
97
+ channel=channel, year=year, month=month,
98
+ day=day, julday=doy,sds_type=sds_type)
99
+ full_path = os.path.join(self.sds_root, filename)
100
+ full_paths = full_paths.union(glob.glob(full_path))
101
+
102
+ return full_paths
103
+
104
+ def _get_filename(self, network, station, location, channel, time, sds_type=None):
105
+ """
106
+ Get filename for certain waveform.
107
+ :type network: str
108
+ :param network: Network code of requested data (e.g. "IU").
109
+ :type station: str
110
+ :param station: Station code of requested data (e.g. "ANMO").
111
+ :type location: str
112
+ :param location: Location code of requested data (e.g. "").
113
+ :type channel: str
114
+ :param channel: Channel code of requested data (e.g. "HHZ").
115
+ :type time: :class:`~obspy.core.utcdatetime.UTCDateTime`
116
+ :param time: Time of interest.
117
+ """
118
+ sds_type = sds_type or self.sds_type
119
+ filename = self.fmt.format(
120
+ network=network, station=station, location=location,
121
+ channel=channel, year=time.year, month=time.month,
122
+ day=time.day, doy=time.julday,sds_type=sds_type)
123
+ return os.path.join(self.sds_root, filename)
File without changes
@@ -0,0 +1,154 @@
1
+
2
+ import os
3
+ import pandas as pd
4
+ from .utils import get_event_ids, get_custom_info, save_info
5
+ from utdquake.tools.stats import get_rolling_stats
6
+ from obspy.clients.fdsn import Client as FDSNClient
7
+
8
+ class Client(FDSNClient):
9
+ """
10
+ A client class for retrieving and calculating rolling statistics on seismic data.
11
+
12
+ Inherits from:
13
+ FDSNClient: Base class for FDSN web service clients.
14
+
15
+ Attributes:
16
+ output (str): Path to the SQLite database file for saving results.
17
+ step (int): Step size for the rolling window in seconds.
18
+ """
19
+
20
+ def __init__(self,*args, **kwargs):
21
+ """
22
+ Initializes the Client class by calling the constructor
23
+ of the base FDSN Client class.
24
+
25
+ Parameters:
26
+ *args : variable length argument list
27
+ Positional arguments passed to the base class constructor.
28
+ **kwargs : variable length keyword arguments
29
+ Keyword arguments passed to the base class constructor.
30
+ """
31
+ super().__init__(*args, **kwargs)
32
+
33
+ def get_custom_events(self, *args, max_events_in_ram=1e6,
34
+ output_folder=None, drop_level=True,
35
+ **kwargs):
36
+ """
37
+ Retrieves custom seismic event data including origins, picks,
38
+ and magnitudes.
39
+
40
+ Parameters:
41
+ *args : variable length argument list
42
+ Positional arguments passed to the get_events method.
43
+ max_events_in_ram : int, optional, default=1e6
44
+ Maximum number of events to hold in memory (RAM) before stopping or
45
+ prompting to save the data to disk.
46
+ output_folder : str, optional, default=None
47
+ Folder path where the event data will be saved if provided. If not
48
+ specified, data will only be stored in memory.
49
+ drop_level : bool, optional, default=True
50
+ True if you want to have only one level in your origin dataframe.
51
+ **kwargs : variable length keyword arguments
52
+ Keyword arguments passed to the get_events method.
53
+
54
+ Returns:
55
+ tuple
56
+ A tuple containing:
57
+ - DataFrame of origins for all events.
58
+ - DataFrame of picks for all events.
59
+ - DataFrame of magnitudes for all events.
60
+ """
61
+ # Retrieve the catalog of events using the get_events method
62
+ catalog = self.get_events(*args, **kwargs)
63
+
64
+ # Extract event IDs from the catalog
65
+ ev_ids = get_event_ids(catalog)
66
+
67
+ # Initialize lists to store origins, picks, and magnitudes
68
+ all_origins, all_picks, all_mags = [], [], []
69
+
70
+ # Loop through each event ID to gather detailed event information
71
+ for ev_id in ev_ids[::-1]:
72
+ # Catalog with arrivals. This is a workaround to retrieve
73
+ # arrivals by specifying the event ID.
74
+ cat = self.get_events(eventid=ev_id)
75
+
76
+ # Get the first event from the catalog
77
+ event = cat[0]
78
+
79
+ # Extract custom information for the event
80
+ origin, picks, mags = get_custom_info(event, drop_level)
81
+
82
+ info = {
83
+ "origin": origin,
84
+ "picks": picks,
85
+ "mags": mags
86
+ }
87
+
88
+ # Save information to the output folder, if specified
89
+ if output_folder is not None:
90
+ if not os.path.isdir(output_folder):
91
+ os.makedirs(output_folder)
92
+ save_info(output_folder, info=info)
93
+
94
+ # Append information to the lists or break if memory limit is reached
95
+ if len(all_origins) < max_events_in_ram:
96
+ all_origins.append(origin)
97
+ all_picks.append(picks)
98
+ all_mags.append(mags)
99
+ else:
100
+ if output_folder is not None:
101
+ print(f"max_events_in_ram: {max_events_in_ram} is reached. "
102
+ "But it is still saving on disk.")
103
+ else:
104
+ print(f"max_events_in_ram: {max_events_in_ram} is reached. "
105
+ "It is recommended to save the data on disk using the 'output_folder' parameter.")
106
+ break
107
+
108
+ # Concatenate data from all events, if multiple events are found
109
+ if len(ev_ids) > 1:
110
+ all_origins = pd.concat(all_origins, axis=0)
111
+ all_picks = pd.concat(all_picks, axis=0)
112
+ all_mags = pd.concat(all_mags, axis=0)
113
+ else:
114
+ # If only one event is found, retain the single DataFrame
115
+ all_origins = all_origins[0]
116
+ all_picks = all_picks[0]
117
+ all_mags = all_mags[0]
118
+
119
+ return all_origins, all_picks, all_mags
120
+
121
+ def get_stats(self, output, step, starttime, endtime, **kwargs):
122
+ """
123
+ Retrieve waveforms and compute rolling statistics for the specified time interval.
124
+
125
+ Args:
126
+ output (str): Path to the SQLite database file for saving results.
127
+ step (int): Step size for the rolling window in seconds.
128
+ starttime (UTCDateTime): Start time of the data.
129
+ endtime (UTCDateTime): End time of the data.
130
+ **kwargs: Keyword arguments for retrieving waveforms, including:
131
+ - Additional arguments required by `self.get_waveforms`.
132
+
133
+ Returns:
134
+ pd.DataFrame: A DataFrame containing rolling statistics for each interval, with columns including:
135
+ - Availability percentage
136
+ - Gaps duration
137
+ - Overlaps duration
138
+ - Gaps count
139
+ - Overlaps count
140
+ """
141
+ # Extract start and end times from keyword arguments
142
+ # Retrieve waveforms using base class method
143
+ st = self.get_waveforms(**kwargs)
144
+
145
+ # Compute rolling statistics for the retrieved waveforms
146
+ stats = get_rolling_stats(
147
+ st=st,
148
+ step=step,
149
+ starttime=starttime.datetime,
150
+ endtime=endtime.datetime,
151
+ sqlite_output=output
152
+ )
153
+
154
+ return stats