Ejemplo n.º 1
0
def RGF_from_SW4(path_to_green=".",
                 t0=0,
                 file_name=None,
                 origin_time=None,
                 event_lat=None,
                 event_lon=None,
                 depth=None,
                 station_name=None,
                 station_lat=None,
                 station_lon=None,
                 output_directory="sw4out"):
    """
    Function to convert reciprocal Green's functions from SW4 to tensor format
    
    Reads the reciprocal Green's functions (displacement/unit force) from SW4 and
    performs the summation to get the Green's function tensor.
    RGFs from SW4 are oriented north, east and positive down by setting az=0.
    
    Assumes the following file structure:
    f[x,y,z]/station_name/event_name.[x,y,z]
    """

    import os
    from obspy.core import read, Stream
    from obspy.geodetics.base import gps2dist_azimuth
    from obspy.core.util.attribdict import AttribDict

    # Defined variables (do not change)
    dirs = ["fz", "fx", "fy"]  # directory to displacement per unit force
    du = [
        "duxdx", "duydy", "duzdz", "duydx", "duxdy", "duzdx", "duxdz", "duzdy",
        "duydz"
    ]
    orientation = ["Z", "N", "E"]  # set az=0 in SW4 so x=north, y=east
    cmpaz = [0, 0, 90]
    cmpinc = [0, 90, 90]

    # Create a new output directory under path_to_green
    dirout = "%s/%s" % (path_to_green, output_directory)
    if os.path.exists(dirout):
        print("Warning: output directory '%s' already exists." % dirout)
    else:
        print("Creating output directory '%s'." % dirout)
        os.mkdir(dirout)

    # Loop over each directory fx, fy, fz
    nsta = len(station_name)
    for i in range(3):
        # Set headers according to the orientation
        if dirs[i][-1].upper() == "Z":
            scale = -1  # change to positive up
        else:
            scale = 1

        # Loop over each station
        for j in range(nsta):
            station = station_name[j]
            stlo = station_lon[j]
            stla = station_lat[j]
            dirin = "%s/%s/%s" % (path_to_green, dirs[i], station)
            print("Reading RGFs from %s:" % (dirin))
            st = Stream()
            for gradient in du:
                fname = "%s/%s.%s" % (dirin, file_name, gradient)
                st += read(fname, format="SAC")

            # Set station headers
            starttime = origin_time - t0
            dist, az, baz = gps2dist_azimuth(event_lat, event_lon, stla, stlo)

            # SAC headers
            sacd = AttribDict()
            sacd.stla = stla
            sacd.stlo = stlo
            sacd.evla = event_lat
            sacd.evlo = event_lon
            sacd.az = az
            sacd.baz = baz
            sacd.dist = dist / 1000  # convert to kilometers
            sacd.o = 0
            sacd.b = -1 * t0
            sacd.cmpaz = cmpaz[i]
            sacd.cmpinc = cmpinc[i]
            sacd.kstnm = station

            # Update start time
            for tr in st:
                tr.stats.starttime = starttime
                tr.stats.distance = dist
                tr.stats.back_azimuth = baz

            # Sum displacement gradients to get reciprocal Green's functions
            tensor = Stream()
            for gradient, element in zip(["duxdx", "duydy", "duzdz"],
                                         ["XX", "YY", "ZZ"]):
                trace = st.select(channel=gradient)[0].copy()
                trace.stats.channel = "%s%s" % (orientation[i], element)
                tensor += trace

            trace = st.select(channel="duydx")[0].copy()
            trace.data += st.select(channel="duxdy")[0].data
            trace.stats.channel = "%s%s" % (orientation[i], "XY")
            tensor += trace

            trace = st.select(channel="duzdx")[0].copy()
            trace.data += st.select(channel="duxdz")[0].data
            trace.stats.channel = "%s%s" % (orientation[i], "XZ")
            tensor += trace

            trace = st.select(channel="duzdy")[0].copy()
            trace.data += st.select(channel="duydz")[0].data
            trace.stats.channel = "%s%s" % (orientation[i], "YZ")
            tensor += trace

            # Set sac headers before saving
            print("    Saving GFs to %s" % dirout)
            for tr in tensor:
                tr.trim(origin_time, tr.stats.endtime)
                tr.data = scale * tr.data
                tr.stats.sac = sacd
                sacout = "%s/%s.%.4f.%s" % (dirout, station, depth,
                                            tr.stats.channel)
                #print("Writing %s to file."%sacout)
                tr.write(sacout, format="SAC")