eqcorrscan / EQcorrscan

Earthquake detection and analysis in Python.
https://eqcorrscan.readthedocs.io/en/latest/
Other
166 stars 86 forks source link

no 'get_waveforms_bulk' attribute when using a SDS-type Client #394

Closed 19giovi87 closed 4 years ago

19giovi87 commented 4 years ago

Describe the bug Instead of using a FDSN client, waveforms stored in a local repository ("sds store") can be downloaded using the appropriate obspy client. In eqcorrscan, such client works correctly when making the templates but fails in downloading the waveforms for constructing the party/tribe. The error message is 'Client' object has no attribute 'get_waveforms_bulk'

To Reproduce 1) import the client from obspy.clients.filesystem.sds import Client 2) construct the client, using the path of the local repository CLIENT = Client("/pathToSdsStore") more info on sds datastore from obspy documentation 3) Create a party/tribe using this CLIENT

party, st = tribe.client_detect(
                                        client=CLIENT, starttime=t1, endtime=t2,
                                        threshold=THRESHOLD,threshold_type="MAD", trig_int=2.0,
                                        plot=False, return_stream=True,ignore_length = True,
                                        ignore_bad_data = True)

Expected behavior Continous waveforms would start being downloaded and events detected. Desktop (please complete the following information):

d-chambers commented 4 years ago

Hi @19giovi87,

This might be a good issue to raise with ObsPy. It wouldn't be hard to add a get_waveforms_bulk to the SDS client. In the meantime, you might consider just monkey patching a get_waveforms_bulk method onto the SDS client instance. Here is some code that should do it (but I haven't tested it):

def get_waveform_client(waveform_client):
    """
    Bind a `get_waveforms_bulk` method to waveform_client if it doesn't already have one.
    """
    def _get_waveforms_bulk_naive(self, bulk_arg):
        """ a naive implementation of get_waveforms_bulk that uses iteration. """
        st = obspy.Stream()
        for arg in bulk_arg:
            st += self.get_waveforms(*arg)
        return st

    # add waveform_bulk method dynamically if it doesn't exist already
    if not hasattr(waveform_client, "get_waveforms_bulk"):
        bound_method = _get_waveforms_bulk_naive.__get__(waveform_client)
        setattr(waveform_client, "get_waveforms_bulk", bound_method)

    return waveform_client

If you will excuse a bit of self promotion, you could also consider using ObsPlus, particularly the WaveBank which has a get_waveforms_bulk method.

It would also be good if EQCorrScan had a fallback implementation for clients that have a get_waveforms but not get_waveforms_bulk.

calum-chamberlain commented 4 years ago

Agreed! I will make a patch for EQcorrscan, but in the meantime, ObsPlus is great, or the patch @d-chambers suggested was what I would have suggested as well.

I will tag this issue with a PR soon so that you know what is going on.

Thanks all!

calum-chamberlain commented 4 years ago

Hey team, I got distracted by teaching, sorry. In the meantime, @d-chambers's patch will be the way to go and should get you going! Ideally all these from-client type things would use one function, I'm unsure why .client_detect isn't...

Sorry for being slow, I might be a while.

19giovi87 commented 4 years ago

@d-chambers Thank you for your quick reply! I'm going to test the patch you suggested.

Your self-promotion is forgiven...by the way, I already heard of ObsPlus. By the way, can you tell me how to index the (huge) datastore only once on the cluster? Best, Giovanni

d-chambers commented 4 years ago

Ah, if it is a "huge" datastore in a distributed environment WaveBank might not be the best solution (I haven't used ObsPlus in HPC environments much) but if want to discuss further its probably best to open an issue in the ObsPlus tracker. Did the patch function work for you on the SDS client?

19giovi87 commented 4 years ago

@d-chambers The patch worked perfectly. Only error is that st must be st = obspy.core.Stream()

Thank you!!

calum-chamberlain commented 4 years ago

Closed by #413.