From cd7c88128dc2ce26f37c8158cc4f10f8d6dc7625 Mon Sep 17 00:00:00 2001 From: Florent Aden-Antoniow Date: Tue, 12 May 2026 11:31:09 +1200 Subject: [PATCH 1/2] catch error for single data point trace and ctypes error I used .get_waveforms for specific starttime and endtime, for any station and location available and HHZ,EHZ components. Some trace would contain a single point throwing a divided by zero error. I just added a if condition to catch the problem, only missing one or two stations max. I have observed another error related to the mseed package and ctypes that I haven't been able to catch: ```bash playback-1 | Exception ignored in: playback-1 | Traceback (most recent call last): playback-1 | File "/usr/local/lib/python3.10/site-packages/mseedlib/mstracelist.py", line 480, in __del__ playback-1 | for segment in traceid.segments(): playback-1 | File "/usr/local/lib/python3.10/site-packages/mseedlib/mstracelist.py", line 317, in segments playback-1 | current_segment.contents.info.traceid_address = ct.addressof(self) playback-1 | File "/usr/local/lib/python3.10/site-packages/mseedlib/mstracelist.py", line 102, in info playback-1 | self._prvtptr = ct.cast(raw_buffer, ct.POINTER(TraceSegInfo)) playback-1 | ValueError: ctypes object structure too deep ``` --- geonet_obspy_utils/clients/aws/client.py | 45 +++++++++++++++++++----- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/geonet_obspy_utils/clients/aws/client.py b/geonet_obspy_utils/clients/aws/client.py index 431a93f..2a63ab6 100644 --- a/geonet_obspy_utils/clients/aws/client.py +++ b/geonet_obspy_utils/clients/aws/client.py @@ -11,6 +11,7 @@ import yaml import os import boto3 +import logging from botocore import UNSIGNED from botocore.config import Config from botocore.exceptions import ClientError @@ -23,6 +24,8 @@ from parse import parse from itertools import product +# logger = logging.getLogger("AWS Client") +# logger.setLevel(logging.INFO) class Client(object): """ @@ -30,7 +33,7 @@ class Client(object): (only for GeoNet) data. """ - def __init__(self, client_name="GEONET"): + def __init__(self, client_name="GEONET", debug=False): """ Initialize the client with the configuration loaded from a YAML file. @@ -49,6 +52,10 @@ def __init__(self, client_name="GEONET"): config_path = os.path.join(os.path.dirname(__file__), "client_config.yml") + + self.debug = debug + # if self.debug: + # logger.setLevel(logging.DEBUG) with open(config_path, 'r') as f: base_config = yaml.safe_load(f) @@ -112,7 +119,7 @@ def _list_available_files(self, prefix): except self._s3.exceptions.NoSuchBucket: print(f"Bucket '{self.waveform_bucket_name}' does not exist.") except Exception as e: - print(f"Error accessing S3 bucket '{self.bucket_name}': {e}") + print(f"Error accessing S3 bucket '{self.waveform_bucket_name}': {e}") return file_list def get_waveforms(self, network, station, location, channel, starttime, @@ -535,13 +542,34 @@ def _fix_mseed_timing(mstl_traceids): """ stream = Stream() for traceid in mstl_traceids: - for segment in traceid.segments(): + try: + segments = list(traceid.segments()) + except ValueError as e: + n, s, l, c = sourceid2nslc(traceid.sourceid) + print(f"Skipping trace {n}.{s}.{l}.{c} due to mseedlib and ctypes error: {e}") + continue + for segment in segments: data = np.ctypeslib.as_array(segment.datasamples) # compute actual average sampling interval - dt = (UTCDateTime(segment.endtime_str()) - - UTCDateTime(segment.starttime_str()))/(len(data)-1) - trace = Trace() n, s, l, c = sourceid2nslc(traceid.sourceid) + + if len(data) <= 1: + print(f"Trace {n}.{s}.{l}.{c} has {len(data)} sample(s). " + "Skipping timing correction.") + continue + + total_time = (UTCDateTime(segment.endtime_str()) - + UTCDateTime(segment.starttime_str())) + + if total_time <= 0 or segment.samprate <= 0: + print(f"Trace {n}.{s}.{l}.{c} has degenerate timing " + f"(total_time={total_time}, samprate={segment.samprate}). " + "Skipping.") + continue + + dt = total_time / (len(data) - 1) + trace = Trace() + trace.data = data trace.stats.network = n trace.stats.station = s @@ -550,8 +578,9 @@ def _fix_mseed_timing(mstl_traceids): trace.stats.starttime = UTCDateTime(segment.starttime_str()) trace.stats.delta = dt - trace.resample(int(segment.samprate)) - trace.stats.sampling_rate = int(segment.samprate) + nominal_rate = round(segment.samprate) if segment.samprate >= 0.5 else segment.samprate + trace.resample(nominal_rate) + trace.stats.sampling_rate = nominal_rate stream += trace From 30e72125937bb230a8fca2b704c00ebe7dcbd944 Mon Sep 17 00:00:00 2001 From: Florent Aden-Antoniow Date: Tue, 12 May 2026 11:33:25 +1200 Subject: [PATCH 2/2] cleanup unused debug flag --- geonet_obspy_utils/clients/aws/client.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/geonet_obspy_utils/clients/aws/client.py b/geonet_obspy_utils/clients/aws/client.py index 2a63ab6..d16bc8e 100644 --- a/geonet_obspy_utils/clients/aws/client.py +++ b/geonet_obspy_utils/clients/aws/client.py @@ -11,7 +11,6 @@ import yaml import os import boto3 -import logging from botocore import UNSIGNED from botocore.config import Config from botocore.exceptions import ClientError @@ -24,16 +23,13 @@ from parse import parse from itertools import product -# logger = logging.getLogger("AWS Client") -# logger.setLevel(logging.INFO) - class Client(object): """ AWS Client to access waveform (all available clients) and event (only for GeoNet) data. """ - def __init__(self, client_name="GEONET", debug=False): + def __init__(self, client_name="GEONET"): """ Initialize the client with the configuration loaded from a YAML file. @@ -52,10 +48,6 @@ def __init__(self, client_name="GEONET", debug=False): config_path = os.path.join(os.path.dirname(__file__), "client_config.yml") - - self.debug = debug - # if self.debug: - # logger.setLevel(logging.DEBUG) with open(config_path, 'r') as f: base_config = yaml.safe_load(f)