Exemplo n.º 1
0
def run_get_waveform(c,
                     event,
                     idb,
                     ref_time_place,
                     min_dist=20,
                     max_dist=300,
                     min_az=0,
                     max_az=360,
                     before=100,
                     after=300,
                     network='*',
                     station='*',
                     channel='BH*',
                     ifresample=False,
                     resample_freq=20,
                     ifrotateRTZ=True,
                     ifrotateUVW=False,
                     ifCapInp=True,
                     ifRemoveResponse=True,
                     ifDetrend=True,
                     ifDemean=True,
                     Taper=False,
                     ifEvInfo=True,
                     scale_factor=10.0**2,
                     ipre_filt=1,
                     pre_filt=(0.005, 0.006, 10.0, 15.0),
                     icreateNull=1,
                     ifFilter=False,
                     fmin=.02,
                     fmax=1,
                     filter_type='bandpass',
                     zerophase=False,
                     corners=4,
                     iplot_response=False,
                     ifplot_spectrogram=False,
                     outformat='VEL',
                     ifsave_sacpaz=False):
    """
    Get SAC waveforms for an event

    basic usage:
        run_get_waveform(event)

    event -       obspy Event object

    min_dist - minimum station distance (default = 20)
    max_dist - maximum station distance (default =300)
    before -   time window length before the event time (default= 100)
    after  -   time window length after the event time (default = 300)
    network -  network codes of potential stations (default=*)
    channel -  component(s) to get, accepts comma separated (default='BH*')
    ifresample_TF   - Boolean. Request resample or not. Default = False
    resample_freq   - sampling frequency to resample waveforms (default 20.0)
    ifrotate - Boolean, if true will output sac files rotated to baz
               unrotated sac files will also be written
    ifCapInp - Boolean, make weight files for CAP
    ifEvInfo - Boolean, output 'ev_info.dat' containg event info (True)
    ifRemoveResponse - Boolean, will remove response (True)
    ifDetrend - Boolean, will remove linear trend from data (True)
    ifDemean  - Boolean, will insult the data (True)
    scale_factor - scale all data by one value (10.0**2)
                    This usually puts the data in the units required by CAP
                    From m/s to cm/s
    pre_filt  - list, corner frequencies of filter to apply before deconv
                a good idea when deconvolving (ifRemoveResponse=True)
    """

    evtime = event.origins[0].time
    reftime = ref_time_place.origins[0].time

    if idb == 1:
        print("Preparing request for IRIS ...")
        # BK network doesn't return data when using the IRIS client.
        # this option switches to NCEDC if BK is
        if "BK" in network:
            client_name = "NCEDC"
            print(
                "\nWARNING. Request for BK network. Switching to NCEDC client")
            c = Client("NCEDC")
        else:
            client_name = "IRIS"

        print("Download stations...")
        stations = c.get_stations(network=network,
                                  station=station,
                                  channel=channel,
                                  starttime=reftime - before,
                                  endtime=reftime + after,
                                  level="response")
        inventory = stations  # so that llnl and iris scripts can be combined
        print("Printing stations")
        print(stations)
        print("Done Printing stations...")
        sta_limit_distance(ref_time_place,
                           stations,
                           min_dist=min_dist,
                           max_dist=max_dist,
                           min_az=min_az,
                           max_az=max_az)

        print("Downloading waveforms...")
        bulk_list = make_bulk_list_from_stalist(stations,
                                                reftime - before,
                                                reftime + after,
                                                channel=channel)
        stream_raw = c.get_waveforms_bulk(bulk_list)

    elif idb == 3:
        client_name = "LLNL"
        print("Preparing request for LLNL ...")

        # Get event an inventory from the LLNL DB.
        event_number = int(event.event_descriptions[0].text)
        # event = llnl_db_client.get_obspy_event(event)
        inventory = c.get_inventory()

        print("--> Total stations in LLNL DB: %i" %
              (len(inventory.get_contents()["stations"])))
        sta_limit_distance(event,
                           inventory,
                           min_dist=min_dist,
                           max_dist=max_dist,
                           min_az=min_az,
                           max_az=max_az)
        print("--> Stations after filtering for distance: %i" %
              (len(inventory.get_contents()["stations"])))

        stations = set([sta.code for net in inventory for sta in net])

        _st = c.get_waveforms_for_event(event_number)
        stream_raw = obspy.Stream()
        for tr in _st:
            if tr.stats.station in stations:
                stream_raw.append(tr)

    # set reftime
    stream = obspy.Stream()
    stream = set_reftime(stream_raw, evtime)

    print("--> Adding SAC metadata...")
    st2 = add_sac_metadata(stream, idb=idb, ev=event, stalist=inventory)

    # Do some waveform QA
    # - (disabled) Throw out traces with missing data
    # - log waveform lengths and discrepancies
    # - Fill-in missing data -- Carl request
    do_waveform_QA(st2, client_name, event, evtime, before, after)

    if ifDemean:
        st2.detrend('demean')

    if ifDetrend:
        st2.detrend('linear')

    if ifFilter:
        prefilter(st2, fmin, fmax, zerophase, corners, filter_type)

    if ifRemoveResponse:
        resp_plot_remove(st2, ipre_filt, pre_filt, iplot_response,
                         scale_factor, stations, outformat)
    else:
        # output RAW waveforms
        decon = False
        print("WARNING -- NOT correcting for instrument response")

    if scale_factor > 0:
        amp_rescale(st2, scale_factor)
        if idb == 3:
            amp_rescale_llnl(st2, scale_factor)

    # Set the sac header KEVNM with event name
    # This applies to the events from the LLNL database
    # NOTE this command is needed at the time of writing files, so it has to
    # be set early
    st2, evname_key = rename_if_LLNL_event(st2, evtime)

    # Get list of unique stations + locaiton (example: 'KDAK.00')
    stalist = []
    for tr in st2.traces:
        #stalist.append(tr.stats.station)
        stalist.append(tr.stats.network + '.' + tr.stats.station + '.' +
                       tr.stats.location + '.' + tr.stats.channel[:-1])

    # Crazy way of getting a unique list of stations
    stalist = list(set(stalist))

    # match start and end points for all traces
    st2 = trim_maxstart_minend(stalist, st2, client_name, event, evtime,
                               ifresample, resample_freq, before, after)
    if len(st2) == 0:
        raise ValueError("no waveforms left to process!")

    if ifresample == True:
        # NOTE !!! tell the user if BOTH commands are disabled NOTE !!!
        if (client_name == "IRIS"):
            resample(st2, freq=resample_freq)
        elif (client_name == "LLNL"):
            resample_cut(st2, resample_freq, evtime, before, after)
    else:
        print("WARNING. Will not resample. Using original rate from the data")

    # save raw waveforms in SAC format
    path_to_waveforms = evname_key + "/RAW"
    write_stream_sac_raw(stream_raw,
                         path_to_waveforms,
                         evname_key,
                         idb,
                         event,
                         stations=inventory)

    # Taper waveforms (optional; Generally used when data is noisy- example: HutchisonGhosh2016)
    # https://docs.obspy.org/master/packages/autogen/obspy.core.trace.Trace.taper.html
    # To get the same results as the default taper in SAC, use max_percentage=0.05 and leave type as hann.
    if Taper:
        st2.taper(max_percentage=Taper,
                  type='hann',
                  max_length=None,
                  side='both')

    # save processed waveforms in SAC format
    path_to_waveforms = evname_key
    write_stream_sac(st2, path_to_waveforms, evname_key)

    if ifrotateRTZ:
        rotate_and_write_stream(st2, evname_key, icreateNull, ifrotateUVW)

    if ifCapInp:
        write_cap_weights(st2, evname_key, client_name, event)

    if ifEvInfo:
        write_ev_info(event, evname_key)

    if ifplot_spectrogram:
        plot_spectrogram(st2, evname_key)

    if ifsave_sacpaz:
        write_resp(inventory, evname_key)

    # save station inventory as XML file
    xmlfilename = evname_key + "/stations.xml"
    stations.write(xmlfilename, format="stationxml", validate=True)
Exemplo n.º 2
0
    def run_get_waveform(self):
        """
        Get SAC waveforms for an event
        
        basic usage:
        run_get_waveform(event)
        
        c              -  client
        event          -  obspy Event object
        ref_time_place -  reference time and place (other than origin time and place - for station subsetting)
        """

        c = self.client
        event = self.ev
        ref_time_place = self.ref_time_place

        evtime = event.origins[0].time
        reftime = ref_time_place.origins[0].time

        if self.idb == 1:
            print("Preparing request for IRIS ...")
            # BK network doesn't return data when using the IRIS client.
            # this option switches to NCEDC if BK is
            if "BK" in self.network:
                client_name = "NCEDC"
                print(
                    "\nWARNING. Request for BK network. Switching to NCEDC client"
                )
                c = Client("NCEDC")
            else:
                client_name = "IRIS"

            print("Download stations...")
            stations = c.get_stations(network=self.network,
                                      station=self.station,
                                      channel=self.channel,
                                      starttime=reftime - self.tbefore_sec,
                                      endtime=reftime + self.tafter_sec,
                                      minlatitude=self.min_lat,
                                      maxlatitude=self.max_lat,
                                      minlongitude=self.min_lon,
                                      maxlongitude=self.max_lon,
                                      level="response")
            inventory = stations  # so that llnl and iris scripts can be combined

            if self.ifverbose:
                print("Printing stations")
                print(stations)
                print("Done Printing stations...")

            sta_limit_distance(ref_time_place,
                               stations,
                               min_dist=self.min_dist,
                               max_dist=self.max_dist,
                               min_az=self.min_az,
                               max_az=self.max_az,
                               ifverbose=self.ifverbose)
            #print("Printing stations NEW")
            #print(stations)
            #print("Done Printing stations...")

            #stations.plotprojection="local")
            # Find P and S arrival times
            phases = self.phases

            t1s, t2s = get_phase_arrival_times(stations, event, self.phases,
                                               self.phase_window,
                                               self.taupmodel, reftime,
                                               self.tbefore_sec,
                                               self.tafter_sec)

            print("Downloading waveforms...")
            # this needs to change
            bulk_list = make_bulk_list_from_stalist(stations,
                                                    t1s,
                                                    t2s,
                                                    channel=self.channel)

            stream_raw = c.get_waveforms_bulk(bulk_list)
            # save ev_info object
            pickle.dump(
                self,
                open(self.evname + '/' + self.evname + '_ev_info.obj', 'wb'))

        elif self.idb == 3:
            client_name = "LLNL"
            print("Preparing request for LLNL ...")

            # Get event an inventory from the LLNL DB.
            event_number = int(event.event_descriptions[0].text)
            # event = llnl_db_client.get_obspy_event(event)
            inventory = c.get_inventory()

            nsta_llnl = len(inventory.get_contents()["stations"])
            print("--> Total stations in LLNL DB: %i" % nsta_llnl)
            sta_limit_distance(event,
                               inventory,
                               min_dist=self.min_dist,
                               max_dist=self.max_dist,
                               min_az=self.min_az,
                               max_az=self.max_az)
            print("--> Stations after filtering for distance: %i" %
                  (len(inventory.get_contents()["stations"])))

            stations = set([sta.code for net in inventory for sta in net])

            _st = c.get_waveforms_for_event(event_number)
            stream_raw = obspy.Stream()
            for tr in _st:
                if tr.stats.station in stations:
                    stream_raw.append(tr)

        # set reftime
        stream = obspy.Stream()
        stream = set_reftime(stream_raw, evtime)

        print("--> Adding SAC metadata...")
        if self.ifverbose: print(inventory)
        st2 = add_sac_metadata(stream,
                               idb=self.idb,
                               ev=event,
                               stalist=inventory,
                               taup_model=self.taupmodel,
                               phases=phases,
                               phase_write=self.write_sac_phase)

        # Do some waveform QA
        do_waveform_QA(st2, client_name, event, evtime, self.tbefore_sec,
                       self.tafter_sec)

        if self.demean:
            st2.detrend('demean')

        if self.detrend:
            st2.detrend('linear')

        if self.ifFilter:
            prefilter(st2, self.f1, self.f2, self.zerophase, self.corners,
                      self.filter_type)

        if self.remove_response:
            resp_plot_remove(st2, self.ipre_filt, self.pre_filt,
                             self.iplot_response, self.water_level,
                             self.scale_factor, stations, self.outformat,
                             self.ifverbose)
        else:
            # output RAW waveforms
            decon = False
            print("WARNING -- NOT correcting for instrument response")

        if self.scale_factor > 0:
            amp_rescale(st2, self.scale_factor)
            if self.idb == 3:
                amp_rescale_llnl(st2, self.scale_factor)

        # Set the sac header KEVNM with event name
        # This applies to the events from the LLNL database
        # NOTE this command is needed at the time of writing files, so it has to
        # be set early
        st2, evname_key = rename_if_LLNL_event(st2, evtime)
        self.evname = evname_key

        # save station plot
        # Note: Plotted are stations in the inventory and NOT the ones with the traces
        # It could be possible that there might not be waveforms for some of these stations.
        try:
            fig = inventory.plot(projection="local",
                                 resolution="i",
                                 label=False,
                                 show=False)
            Catalog([self.ev]).plot(fig=fig,
                                    outfile=self.evname + '/station_map.pdf')
        except:
            print("There is a problem with creating the station map!")

        # Get list of unique stations + locaiton (example: 'KDAK.00')
        stalist = []
        for tr in stream.traces:
            if self.ifverbose: print(tr)
            station_key = "%s.%s.%s.%s" % (tr.stats.network, tr.stats.station,
                                           tr.stats.location,
                                           tr.stats.channel[:-1])
            stalist.append(station_key)

        # Crazy way of getting a unique list of stations
        stalist = list(set(stalist))

        #  Resample
        if self.resample_TF == True:
            # NOTE !!! tell the user if BOTH commands are disabled NOTE !!!
            if (client_name == "IRIS"):
                resample(st2, freq=self.resample_freq)
            elif (client_name == "LLNL"):
                resample_cut(st2, self.resample_freq, evtime, self.tbefore_sec,
                             self.tafter_sec)
        else:
            print(
                "WARNING. Will not resample. Using original rate from the data"
            )

        # match start and end points for all traces
        st2 = trim_maxstart_minend(stalist, st2, client_name, event, evtime,
                                   self.resample_TF, self.resample_freq,
                                   self.tbefore_sec, self.tafter_sec,
                                   self.ifverbose)
        if len(st2) == 0:
            raise ValueError("no waveforms left to process!")

        # save raw waveforms in SAC format
        if self.isave_raw:
            path_to_waveforms = evname_key + "/RAW"
            write_stream_sac_raw(stream_raw,
                                 path_to_waveforms,
                                 evname_key,
                                 self.idb,
                                 event,
                                 stations=inventory)

        # Taper waveforms (optional; Generally used when data is noisy- example: HutchisonGhosh2016)
        # https://docs.obspy.org/master/packages/autogen/obspy.core.trace.Trace.taper.html
        # To get the same results as the default taper in SAC, use max_percentage=0.05 and leave type as hann.
        # Note: Tapering also happens while resampling (see util_write_cap.py)
        if self.taper:
            st2.taper(max_percentage=self.taper,
                      type='hann',
                      max_length=None,
                      side='both')

        # save processed waveforms in SAC format
        # evname_key/RAW_processed = traces after waveform_QA + demean + detrend +
        #                            resample + remove response + filtering +
        #                            resampling + scaling + tapering
        # NOTE: The orientation is same as that of extracted waveforms
        #       Waveforms are rotated to ENZ, in case they are not already orientated,
        #       in the next step (self.rotateRTZ)
        if self.isave_raw_processed:
            path_to_waveforms = os.path.join(evname_key, 'RAW_processed')
            write_stream_sac(st2, path_to_waveforms, evname_key)

        # Rotate to ENZ (save: optional)
        #if self.rotateENZ:
        st2 = rotate2ENZ(st2, evname_key, self.isave_ENZ, self.icreateNull,
                         self.ifverbose)

        # rotate to UVW and save
        if self.rotateUVW:
            rotate2UVW(st2, evname_key)

        # Rotate to RTZ and save
        if self.rotateRTZ:
            rotate2RTZ(st2, evname_key, self.ifverbose)

        # save CAP weight files
        if self.output_cap_weight_file:
            write_cap_weights(st2, evname_key, client_name, event,
                              self.ifverbose)

        # save event info
        if self.output_event_info:
            write_ev_info(event, evname_key)

        # Plot spectrograms
        if self.ifplot_spectrogram:
            plot_spectrogram(st2, evname_key)

        # save pole zero file (Needed for MouseTrap)
        if self.ifsave_sacpaz:
            write_resp(inventory, evname_key)

        # save station inventory as XML file
        if self.ifsave_stationxml:
            xmlfilename = evname_key + "/stations.xml"
            try:
                inventory.write(xmlfilename,
                                format="stationxml",
                                validate=True)
            except:
                print('Could not create stationxml file')

        # Path to the asdf_converter script
        if self.ifsave_asdf:
            # save RTZ
            asdf_filename = evname_key + "/" + evname_key + ".h5"
            os.system("../asdf_converters/asdf_converters/sac2asdf.py " +
                      evname_key + " " + asdf_filename + " observed")
            # save NEZ
            nez_dir = evname_key + "/ENZ/"
            nez_asdf_filename = nez_dir + evname_key + ".h5"
            os.system("../asdf_converters/asdf_converters/sac2asdf.py " +
                      nez_dir + " " + nez_asdf_filename + " observed")
    def run_get_waveform(self):
        """
        Get SAC waveforms for an event
        
        basic usage:
        run_get_waveform(event)
        
        c              -  client
        event          -  obspy Event object
        ref_time_place -  reference time and place (other than origin time and place - for station subsetting)
        """

        c = self.client
        event = self.ev
        ref_time_place = self.ref_time_place

        evtime = event.origins[0].time
        reftime = ref_time_place.origins[0].time

        if (self.idb == 1) or (self.idb == 5):
            # 2019-03-12 I added idb #5 here and not in a separate block since
            # the station retrieval is common to #1 and #5 and I rather not repeat the same block.
            # note that CH stations may not provide all sensor metadata (required when using idb #1) and this crashes with later requests in the code
            # another option is to add sta retrieval after #3 below but unsure if this creates conflicts.
            # TODO use 'is' instead of 'in' to avoid wrong calls (eg FZ or GFZ)
            if ("BK" in self.network) or ("BG" in self.network) or (
                    "BP" in self.network):
                # NOTE BK network doesn't return data when using the IRIS client.
                # this option switches to NCEDC if BK is in networkname.
                client_name = "NCEDC"
            elif "CH" in self.network:
                client_name = "ETH"
            elif "GFZ" in self.network:
                client_name = "GFZ"
            elif "Z3" in self.network:  # 2019-07-31 for AlpArray
                client_name = "ORFEUS"
                #client_name = "GFZ"
                #client_name = "ETH"
            elif "IV" in self.network:
                client_name = "INGV"
            elif "DE" in self.network:
                client_name = "EMSC"  # or BGR GFZ LMU ...
            else:
                client_name = "IRIS"  # default

            c = Client(client_name)
            #-----------------------------------------------------------
            # Check if requesting AlpArray data
            # the following are ongoing TESTS (alparray data)
            #c = Client(client_name, password='******')
            #c = Client(client_name, password='******')
            #c = Client(client_name, password='******')
            #c = RoutingClient('iris-federator') # 2019-06-18 This downloads a list of station data, but no waveforms. Also it requires removing radius-related infor (below) and doesn't have a field for eidatoken.
            #c = RoutingClient('iris-federator', credentials={'EIDA_TOKEN': './eidatoken'}, debug=True)
            #c = RoutingClient('iris-federator', credentials={'EIDA_TOKEN': './eidatoken'})
            #c = RoutingClient('eida-routing',   credentials={'EIDA_TOKEN': '/home/calvizur/.eidatoken'}, debug=True) # 2019-07-31 TEST?
            ## try again AlpArray, arclink
            # NB doesnt work. 'response' level is not accepted which means I would have to prepare data manually
            # option: use script similar to Veronica's
            #c = Client(user='******') # test, AlpArray Client
            #c.max_status_requests = 2000
            if "Z3" in self.network:
                # 2019-07-31 WORKS! (bondo event)
                # replace client if requesting AlpArray data
                c = RoutingClient(
                    'iris-federator',
                    credentials={'EIDA_TOKEN': '/home/calvizur/.eidatoken'},
                    debug=True)
            #-----------------------------------------------------------
            print(c)
            print("\n** WARNING ** Preparing request for client", client_name)
            print("Download stations...")
            if "Z3" in self.network:
                # *** alparray only ***
                stations = c.get_stations(network=self.network,
                                          station=self.station,
                                          channel=self.channel,
                                          starttime=reftime - self.tbefore_sec,
                                          endtime=reftime + self.tafter_sec,
                                          level="response")
            else:
                # default
                stations = c.get_stations(
                    network=self.network,
                    station=self.station,
                    channel=self.channel,
                    starttime=reftime - self.tbefore_sec,
                    endtime=reftime + self.tafter_sec,
                    #----------------------------------------------------------
                    # NOTE RoutingClient (AlpArray) does not have the following
                    minlatitude=self.min_lat,
                    maxlatitude=self.max_lat,
                    minlongitude=self.min_lon,
                    maxlongitude=self.max_lon,
                    longitude=self.elon,  # required for maxradius
                    latitude=self.elat,  # required for maxradius 
                    maxradius=18,  # note 18 deg ~ 2000 km
                    #----------------------------------------------------------
                    level="response")
            inventory = stations  # so that llnl and iris scripts can be combined

            if self.ifverbose:
                print("Printing stations")
                print(stations)
                print("Done Printing stations...")

            sta_limit_distance(ref_time_place,
                               stations,
                               min_dist=self.min_dist,
                               max_dist=self.max_dist,
                               min_az=self.min_az,
                               max_az=self.max_az,
                               ifverbose=self.ifverbose)
            #print("Printing stations NEW")
            #print(stations)
            #print("Done Printing stations...")

            #stations.plotprojection="local")
            # Find P and S arrival times
            t1s = []
            t2s = []
            phases = self.phases
            if self.phase_window:

                #model = TauPyModel(model=taupmodel)
                model = TauPyModel(model=self.taupmodel)

                for net in stations:
                    for sta in net:
                        dist, az, baz = obspy.geodetics.gps2dist_azimuth(
                            event.origins[0].latitude,
                            event.origins[0].longitude, sta.latitude,
                            sta.longitude)
                        dist_deg = kilometer2degrees(dist / 1000, radius=6371)
                        Phase1arrivals = model.get_travel_times(
                            source_depth_in_km=event.origins[0].depth / 1000,
                            distance_in_degree=dist_deg,
                            phase_list=[phases[0]])
                        if len(Phase1arrivals) == 0:
                            if phases[0] == "P":
                                phases[0] = "p"
                            elif phases[0] == "p":
                                phases[0] = "P"
                            elif phases[0] == "S":
                                phases[0] = "s"
                            elif phases[0] == "s":
                                phases[0] = "S"
                            Phase1arrivals = model.get_travel_times(
                                source_depth_in_km=event.origins[0].depth /
                                1000,
                                distance_in_degree=dist_deg,
                                phase_list=[phases[0]])

                        Phase2arrivals = model.get_travel_times(
                            source_depth_in_km=event.origins[0].depth / 1000,
                            distance_in_degree=dist_deg,
                            phase_list=[phases[1]])
                        if len(Phase2arrivals) == 0:
                            if phases[1] == "P":
                                phases[1] = "p"
                            elif phases[1] == "p":
                                phases[1] = "P"
                            elif phases[1] == "S":
                                phases[1] = "s"
                            elif phases[1] == "s":
                                phases[1] = "S"
                            Phase2arrivals = model.get_travel_times(
                                source_depth_in_km=event.origins[0].depth /
                                1000,
                                distance_in_degree=dist_deg,
                                phase_list=[phases[1]])

                        #somearr = model.get_travel_times(source_depth_in_km=event.origins[0].depth/1000,distance_in_degree=dist_deg)
                        #print("Print arrivals")
                        #print(somearr)

                        try:
                            if Phase2arrivals[0].time < Phase1arrivals[0].time:
                                # You are assuming that the first index is the first arrival.  Check this later.
                                t1s.append(event.origins[0].time +
                                           Phase2arrivals[0].time -
                                           self.tbefore_sec)
                                t2s.append(event.origins[0].time +
                                           Phase1arrivals[0].time +
                                           self.tafter_sec)
                            else:
                                t1s.append(event.origins[0].time +
                                           Phase1arrivals[0].time -
                                           self.tbefore_sec)
                                t2s.append(event.origins[0].time +
                                           Phase2arrivals[0].time +
                                           self.tafter_sec)
                        except:
                            t1s.append(reftime - self.tbefore_sec)
                            t2s.append(reftime + self.tafter_sec)

            else:
                t1s = [reftime - self.tbefore_sec]
                t2s = [reftime + self.tafter_sec]

            print("Downloading waveforms...")
            # this needs to change
            bulk_list = make_bulk_list_from_stalist(stations,
                                                    t1s,
                                                    t2s,
                                                    channel=self.channel)

            stream_raw = c.get_waveforms_bulk(bulk_list)
            # save ev_info object
            pickle.dump(
                self,
                open(self.evname + '/' + self.evname + '_ev_info.obj', 'wb'))

        elif self.idb == 3:
            client_name = "LLNL"
            print("Preparing request for LLNL ...")

            # Get event an inventory from the LLNL DB.
            event_number = int(event.event_descriptions[0].text)
            # event = llnl_db_client.get_obspy_event(event)
            inventory = c.get_inventory()

            nsta_llnl = len(inventory.get_contents()["stations"])
            print("--> Total stations in LLNL DB: %i" % nsta_llnl)
            sta_limit_distance(event,
                               inventory,
                               min_dist=self.min_dist,
                               max_dist=self.max_dist,
                               min_az=self.min_az,
                               max_az=self.max_az)
            print("--> Stations after filtering for distance: %i" %
                  (len(inventory.get_contents()["stations"])))

            stations = set([sta.code for net in inventory for sta in net])

            _st = c.get_waveforms_for_event(event_number)
            stream_raw = obspy.Stream()
            for tr in _st:
                if tr.stats.station in stations:
                    stream_raw.append(tr)

        #-----------------------------------------------------------
        elif self.idb == 99:
            # IRIS federator to figure out who has waveform data for that
            # particular query and subsequently call the individual data
            # centers to actually get the data.
            # https://docs.obspy.org/packages/obspy.clients.fdsn.html
            print("Preparing request through iris-federator")
            c = RoutingClient('iris-federator', debug=True)
            stations = c.get_stations(
                #network     = self.network,
                #station     = self.station,
                channel=self.channel,
                starttime=reftime - self.tbefore_sec,
                endtime=reftime + self.tafter_sec,
                #minlatitude = self.min_lat,
                #maxlatitude = self.max_lat,
                #minlongitude = self.min_lon,
                #maxlongitude = self.max_lon,
                longitude=self.elon,  # required for maxradius
                latitude=self.elat,  # required for maxradius 
                #maxradius   = 18,         # note 18 deg ~ 2000 km
                maxradius=18,  # note 18 deg ~ 2000 km
                level="response")
            print("Downloading waveforms...")
            # this needs to change
            bulk_list = make_bulk_list_from_stalist(stations,
                                                    t1s,
                                                    t2s,
                                                    channel=self.channel)

            stream_raw = c.get_waveforms_bulk(bulk_list)
            # save ev_info object
            pickle.dump(
                self,
                open(self.evname + '/' + self.evname + '_ev_info.obj', 'wb'))
        #-----------------------------------------------------------

        # set reftime
        stream = obspy.Stream()
        stream = set_reftime(stream_raw, evtime)

        print("--> Adding SAC metadata...")
        if self.ifverbose: print(inventory)
        st2 = add_sac_metadata(stream,
                               idb=self.idb,
                               ev=event,
                               stalist=inventory,
                               taup_model=self.taupmodel,
                               phases=phases,
                               phase_write=self.write_sac_phase)

        # Do some waveform QA
        do_waveform_QA(st2, client_name, event, evtime, self.tbefore_sec,
                       self.tafter_sec)

        if self.demean:
            st2.detrend('demean')

        if self.detrend:
            st2.detrend('linear')

        if self.remove_response:
            resp_plot_remove(st2, self.ipre_filt, self.pre_filt,
                             self.iplot_response, self.scale_factor, stations,
                             self.outformat, self.ifverbose)
        else:
            # output RAW waveforms
            decon = False
            print("WARNING -- NOT correcting for instrument response")

        if self.ifFilter:
            prefilter(st2, self.f1, self.f2, self.zerophase, self.corners,
                      self.filter_type)

        if self.scale_factor > 0:
            amp_rescale(st2, self.scale_factor)
            if self.idb == 3:
                amp_rescale_llnl(st2, self.scale_factor)

        # Set the sac header KEVNM with event name
        # This applies to the events from the LLNL database
        # NOTE this command is needed at the time of writing files, so it has to
        # be set early
        st2, evname_key = rename_if_LLNL_event(st2, evtime)
        self.evname = evname_key

        # save station plot
        # Note: Plotted are stations in the inventory and NOT the ones with the traces
        # It could be possible that there might not be waveforms for some of these stations.
        try:
            fig = inventory.plot(projection="local",
                                 resolution="i",
                                 label=False,
                                 show=False)
            Catalog([self.ev]).plot(fig=fig,
                                    outfile=self.evname + '/station_map.pdf')
        except:
            print("There is a problem with creating the station map!")

        # Get list of unique stations + locaiton (example: 'KDAK.00')
        stalist = []
        for tr in stream.traces:
            if self.ifverbose: print(tr)
            station_key = "%s.%s.%s.%s" % (tr.stats.network, tr.stats.station,
                                           tr.stats.location,
                                           tr.stats.channel[:-1])
            stalist.append(station_key)

        # Crazy way of getting a unique list of stations
        stalist = list(set(stalist))

        #  Resample
        if self.resample_TF == True:
            # NOTE !!! tell the user if BOTH commands are disabled NOTE !!!
            if (client_name == "IRIS"):
                resample(st2, freq=self.resample_freq)
            elif (client_name == "LLNL"):
                resample_cut(st2, self.resample_freq, evtime, self.tbefore_sec,
                             self.tafter_sec)
        else:
            print(
                "WARNING. Will not resample. Using original rate from the data"
            )

        # match start and end points for all traces
        st2 = trim_maxstart_minend(stalist, st2, client_name, event, evtime,
                                   self.resample_TF, self.resample_freq,
                                   self.tbefore_sec, self.tafter_sec,
                                   self.ifverbose)
        if len(st2) == 0:
            raise ValueError("no waveforms left to process!")

        # save raw waveforms in SAC format
        if self.isave_raw:
            path_to_waveforms = evname_key + "/RAW"
            write_stream_sac_raw(stream_raw,
                                 path_to_waveforms,
                                 evname_key,
                                 self.idb,
                                 event,
                                 stations=inventory)

        # Taper waveforms (optional; Generally used when data is noisy- example: HutchisonGhosh2016)
        # https://docs.obspy.org/master/packages/autogen/obspy.core.trace.Trace.taper.html
        # To get the same results as the default taper in SAC, use max_percentage=0.05 and leave type as hann.
        if self.taper:
            st2.taper(max_percentage=self.taper,
                      type='hann',
                      max_length=None,
                      side='both')

        # save processed waveforms in SAC format
        # evname_key/RAW_processed = traces after waveform_QA + demean + detrend +
        #                            resample + remove response + filtering +
        #                            resampling + scaling + tapering
        # NOTE: The orientation is same as that of extracted waveforms
        #       Waveforms are rotated to ENZ, in case they are not already orientated,
        #       in the next step (self.rotateRTZ)
        if self.isave_raw_processed:
            path_to_waveforms = os.path.join(evname_key, 'RAW_processed')
            write_stream_sac(st2, path_to_waveforms, evname_key)

        # Rotate to ENZ (save: optional)
        #if self.rotateENZ:
        st2 = rotate2ENZ(st2, evname_key, self.isave_ENZ, self.icreateNull,
                         self.ifverbose)

        # rotate to UVW and save
        if self.rotateUVW:
            rotate2UVW(st2, evname_key)

        # Rotate to RTZ and save
        if self.rotateRTZ:
            rotate2RTZ(st2, evname_key, self.ifverbose)

        # save CAP weight files
        if self.output_cap_weight_file:
            write_cap_weights(st2, evname_key, client_name, event,
                              self.ifverbose)

        # save event info
        if self.output_event_info:
            write_ev_info(event, evname_key)

        # Plot spectrograms
        if self.ifplot_spectrogram:
            plot_spectrogram(st2, evname_key)

        # save pole zero file (Needed for MouseTrap)
        if self.ifsave_sacpaz:
            write_resp(inventory, evname_key)

        # save station inventory as XML file
        if self.ifsave_stationxml:
            xmlfilename = evname_key + "/stations.xml"
            try:
                inventory.write(xmlfilename,
                                format="stationxml",
                                validate=True)
            except:
                print('Could not create stationxml file')
        print("### DEBUG ###")