예제 #1
0
def run_parallel_synthetics(home,
                            project_name,
                            station_file,
                            model_name,
                            integrate,
                            static,
                            tsunami,
                            time_epi,
                            beta,
                            custom_stf,
                            impulse,
                            rank,
                            size,
                            insar=False,
                            okada=False,
                            mu_okada=45e9):
    '''
    Use green functions and compute synthetics at stations for a single source
    and multiple stations. This code makes an external system call to syn.c first it
    will make the external call for the strike-slip component then a second externall
    call will be made for the dip-slip component. The unit amount of moment is 1e15
    which corresponds to Mw=3.9333...
    
    IN:
        source: 1-row numpy array containig informaiton aboutt he source, lat, lon, depth, etc...
        station_file: File name with the station coordinates
        green_path: Directopry where GFs are stored
        model_file: File containing the Earth velocity structure
        integrate: =0 if youw ant velocity waveforms, =1 if you want displacements
        static: =0 if computing full waveforms, =1 if computing only the static field
        subfault: String indicating the subfault being worked on
        coord_type: =0 if problem is in cartesian coordinates, =1 if problem is in lat/lon
        
    OUT:
        log: Sysytem standard output and standard error for log
    '''

    import os
    import subprocess
    from mudpy.forward import get_mu
    from numpy import array, genfromtxt, loadtxt, savetxt, log10
    from obspy import read
    from shlex import split
    from mudpy.green import src2sta, rt2ne, origin_time, okada_synthetics
    from glob import glob
    from mudpy.green import silentremove
    from os import remove

    #What parameters are we using?
    if rank == 0:
        out = '''Running all processes with:
        home = %s
        project_name = %s
        station_file = %s
        model_name = %s
        integrate = %s
        static = %s
        tsunami = %s
        time_epi = %s
        beta = %d
        custom_stf = %s
        impulse = %s
        insar = %s
        okada = %s
        mu = %.2e
        ''' % (home, project_name, station_file, model_name, str(integrate),
               str(static), str(tsunami), str(time_epi), beta, custom_stf,
               impulse, insar, okada, mu_okada)
        print(out)

    #Read your corresponding source file
    mpi_source = genfromtxt(home + project_name +
                            '/data/model_info/mpi_source.' + str(rank) +
                            '.fault')

    #Constant parameters
    rakeDS = 90 + beta  #90 is thrust, -90 is normal
    rakeSS = 0 + beta  #0 is left lateral, 180 is right lateral
    tb = 50  #Number of samples before first arrival (should be 50, NEVER CHANGE, if you do then adjust in fk.pl)

    #Figure out custom STF
    if custom_stf.lower() != 'none':
        custom_stf = home + project_name + '/GFs/STFs/' + custom_stf
    else:
        custom_stf = None

    #Load structure
    model_file = home + project_name + '/structure/' + model_name
    structure = loadtxt(model_file, ndmin=2)

    for ksource in range(len(mpi_source)):

        source = mpi_source[ksource, :]

        #Parse the soruce information
        num = str(int(source[0])).rjust(4, '0')
        xs = source[1]
        ys = source[2]
        zs = source[3]
        strike = source[4]
        dip = source[5]
        rise = source[6]
        if impulse == True:
            duration = 0
        else:
            duration = source[7]
        ss_length = source[8]
        ds_length = source[9]
        ss_length_in_km = ss_length / 1000.
        ds_length_in_km = ds_length / 1000.
        strdepth = '%.4f' % zs
        subfault = str(int(source[0])).rjust(4, '0')
        if static == 0 and tsunami == 0:  #Where to save dynamic waveforms
            green_path = home + project_name + '/GFs/dynamic/' + model_name + "_" + strdepth + ".sub" + subfault + "/"
        if static == 1 and tsunami == 1:  #Where to save dynamic waveforms
            green_path = home + project_name + '/GFs/tsunami/' + model_name + "_" + strdepth + ".sub" + subfault + "/"
        if static == 1 and tsunami == 0:  #Where to save statics
            green_path = home + project_name + '/GFs/static/' + model_name + "_" + strdepth + ".sub" + subfault + "/"
        staname = genfromtxt(station_file, dtype="U", usecols=0)
        if staname.shape == ():  #Single staiton file
            staname = array([staname])
        #Compute distances and azimuths
        d, az, lon_sta, lat_sta = src2sta(station_file,
                                          source,
                                          output_coordinates=True)

        #Get moment corresponding to 1 meter of slip on subfault
        mu = get_mu(structure, zs)
        Mo = mu * ss_length * ds_length * 1.0
        Mw = (2. / 3) * (log10(Mo) - 9.1)

        #Move to output folder
        os.chdir(green_path)
        print('Processor ' + str(rank) + ' is working on subfault ' +
              str(int(source[0])) + ' and ' + str(len(d)) + ' stations ')
        for k in range(len(d)):
            if static == 0:  #Compute full waveforms
                diststr = '%.6f' % d[
                    k]  #Need current distance in string form for external call
                #Form the strings to be used for the system calls according to user desired options
                if integrate == 1:  #Make displ.
                    #First Stike-Slip GFs
                    if custom_stf == None:
                        commandSS="syn -I -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+" -D"+str(duration)+ \
                            "/"+str(rise)+" -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".SS.disp.x -G"+green_path+diststr+".grn.0"
                        commandSS = split(
                            commandSS
                        )  #Split string into lexical components for system call
                        #Now dip slip
                        commandDS="syn -I -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+" -D"+str(duration)+ \
                            "/"+str(rise)+" -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".DS.disp.x -G"+green_path+diststr+".grn.0"
                        commandDS = split(commandDS)
                    else:
                        commandSS="syn -I -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+" -S"+custom_stf+ \
                            " -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".SS.disp.x -G"+green_path+diststr+".grn.0"
                        commandSS = split(
                            commandSS
                        )  #Split string into lexical components for system call
                        #Now dip slip
                        commandDS="syn -I -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+" -S"+custom_stf+ \
                            " -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".DS.disp.x -G"+green_path+diststr+".grn.0"
                        commandDS = split(commandDS)
                else:  #Make vel.
                    #First Stike-Slip GFs
                    if custom_stf == None:
                        commandSS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+" -D"+str(duration)+ \
                            "/"+str(rise)+" -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".SS.vel.x -G"+green_path+diststr+".grn.0"
                        commandSS = split(commandSS)
                        #Now dip slip
                        commandDS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+" -D"+str(duration)+ \
                            "/"+str(rise)+" -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".DS.vel.x -G"+green_path+diststr+".grn.0"
                        commandDS = split(commandDS)
                    else:
                        commandSS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+" -S"+custom_stf+ \
                            " -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".SS.vel.x -G"+green_path+diststr+".grn.0"
                        commandSS = split(commandSS)
                        #Now dip slip
                        commandDS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+" -S"+custom_stf+ \
                            " -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".DS.vel.x -G"+green_path+diststr+".grn.0"
                        commandDS = split(commandDS)
                #Run the strike- and dip-slip commands (make system calls)
                p = subprocess.Popen(commandSS)
                p.communicate()
                p = subprocess.Popen(commandDS)
                p.communicate()
                #Result is in RTZ system (+Z is down) rotate to NEZ with +Z up and scale to m or m/s
                if integrate == 1:  #'tis displacememnt
                    #Strike slip
                    if duration > 0:  #Is there a source time fucntion? Yes!
                        r = read(staname[k] + ".subfault" + num + '.SS.disp.r')
                        t = read(staname[k] + ".subfault" + num + '.SS.disp.t')
                        z = read(staname[k] + ".subfault" + num + '.SS.disp.z')
                    else:  #No! This is the impulse response!
                        r = read(staname[k] + ".subfault" + num +
                                 '.SS.disp.ri')
                        t = read(staname[k] + ".subfault" + num +
                                 '.SS.disp.ti')
                        z = read(staname[k] + ".subfault" + num +
                                 '.SS.disp.zi')
                    ntemp, etemp = rt2ne(r[0].data, t[0].data, az[k])
                    #Scale to m and overwrite with rotated waveforms
                    n = r.copy()
                    n[0].data = ntemp / 100
                    e = t.copy()
                    e[0].data = etemp / 100
                    z[0].data = z[0].data / 100
                    n = origin_time(n, time_epi, tb)
                    e = origin_time(e, time_epi, tb)
                    z = origin_time(z, time_epi, tb)
                    n.write(staname[k] + ".subfault" + num + '.SS.disp.n',
                            format='SAC')
                    e.write(staname[k] + ".subfault" + num + '.SS.disp.e',
                            format='SAC')
                    z.write(staname[k] + ".subfault" + num + '.SS.disp.z',
                            format='SAC')
                    silentremove(staname[k] + ".subfault" + num + '.SS.disp.r')
                    silentremove(staname[k] + ".subfault" + num + '.SS.disp.t')
                    if impulse == True:
                        silentremove(staname[k] + ".subfault" + num +
                                     '.SS.disp.ri')
                        silentremove(staname[k] + ".subfault" + num +
                                     '.SS.disp.ti')
                        silentremove(staname[k] + ".subfault" + num +
                                     '.SS.disp.zi')
                    #Dip Slip
                    if duration > 0:  #Is there a source time fucntion? Yes!
                        r = read(staname[k] + ".subfault" + num + '.DS.disp.r')
                        t = read(staname[k] + ".subfault" + num + '.DS.disp.t')
                        z = read(staname[k] + ".subfault" + num + '.DS.disp.z')
                    else:  #No! This is the impulse response!
                        r = read(staname[k] + ".subfault" + num +
                                 '.DS.disp.ri')
                        t = read(staname[k] + ".subfault" + num +
                                 '.DS.disp.ti')
                        z = read(staname[k] + ".subfault" + num +
                                 '.DS.disp.zi')
                    ntemp, etemp = rt2ne(r[0].data, t[0].data, az[k])
                    n = r.copy()
                    n[0].data = ntemp / 100
                    e = t.copy()
                    e[0].data = etemp / 100
                    z[0].data = z[0].data / 100
                    n = origin_time(n, time_epi, tb)
                    e = origin_time(e, time_epi, tb)
                    z = origin_time(z, time_epi, tb)
                    n.write(staname[k] + ".subfault" + num + '.DS.disp.n',
                            format='SAC')
                    e.write(staname[k] + ".subfault" + num + '.DS.disp.e',
                            format='SAC')
                    z.write(staname[k] + ".subfault" + num + '.DS.disp.z',
                            format='SAC')
                    silentremove(staname[k] + ".subfault" + num + '.DS.disp.r')
                    silentremove(staname[k] + ".subfault" + num + '.DS.disp.t')
                    if impulse == True:
                        silentremove(staname[k] + ".subfault" + num +
                                     '.DS.disp.ri')
                        silentremove(staname[k] + ".subfault" + num +
                                     '.DS.disp.ti')
                        silentremove(staname[k] + ".subfault" + num +
                                     '.DS.disp.zi')
                else:  #Waveforms are velocity, as before, rotate from RT-Z to NE+Z and scale to m/s
                    #Strike slip
                    if duration > 0:  #Is there a source time fucntion? Yes!
                        r = read(staname[k] + ".subfault" + num + '.SS.vel.r')
                        t = read(staname[k] + ".subfault" + num + '.SS.vel.t')
                        z = read(staname[k] + ".subfault" + num + '.SS.vel.z')
                    else:  #No! This is the impulse response!
                        r = read(staname[k] + ".subfault" + num + '.SS.vel.ri')
                        t = read(staname[k] + ".subfault" + num + '.SS.vel.ti')
                        z = read(staname[k] + ".subfault" + num + '.SS.vel.zi')
                    ntemp, etemp = rt2ne(r[0].data, t[0].data, az[k])
                    n = r.copy()
                    n[0].data = ntemp / 100
                    e = t.copy()
                    e[0].data = etemp / 100
                    z[0].data = z[0].data / 100
                    n = origin_time(n, time_epi, tb)
                    e = origin_time(e, time_epi, tb)
                    z = origin_time(z, time_epi, tb)
                    n.write(staname[k] + ".subfault" + num + '.SS.vel.n',
                            format='SAC')
                    e.write(staname[k] + ".subfault" + num + '.SS.vel.e',
                            format='SAC')
                    z.write(staname[k] + ".subfault" + num + '.SS.vel.z',
                            format='SAC')
                    silentremove(staname[k] + ".subfault" + num + '.SS.vel.r')
                    silentremove(staname[k] + ".subfault" + num + '.SS.vel.t')
                    if impulse == True:
                        silentremove(staname[k] + ".subfault" + num +
                                     '.SS.vel.ri')
                        silentremove(staname[k] + ".subfault" + num +
                                     '.SS.vel.ti')
                        silentremove(staname[k] + ".subfault" + num +
                                     '.SS.vel.zi')
                    #Dip Slip
                    if duration > 0:  #Is there a source time fucntion? Yes!
                        r = read(staname[k] + ".subfault" + num + '.DS.vel.r')
                        t = read(staname[k] + ".subfault" + num + '.DS.vel.t')
                        z = read(staname[k] + ".subfault" + num + '.DS.vel.z')
                    else:  #No! This is the impulse response!
                        r = read(staname[k] + ".subfault" + num + '.DS.vel.ri')
                        t = read(staname[k] + ".subfault" + num + '.DS.vel.ti')
                        z = read(staname[k] + ".subfault" + num + '.DS.vel.zi')
                    ntemp, etemp = rt2ne(r[0].data, t[0].data, az[k])
                    n = r.copy()
                    n[0].data = ntemp / 100
                    e = t.copy()
                    e[0].data = etemp / 100
                    z[0].data = z[0].data / 100
                    n = origin_time(n, time_epi, tb)
                    e = origin_time(e, time_epi, tb)
                    z = origin_time(z, time_epi, tb)
                    n.write(staname[k] + ".subfault" + num + '.DS.vel.n',
                            format='SAC')
                    e.write(staname[k] + ".subfault" + num + '.DS.vel.e',
                            format='SAC')
                    z.write(staname[k] + ".subfault" + num + '.DS.vel.z',
                            format='SAC')
                    silentremove(staname[k] + ".subfault" + num + '.DS.vel.r')
                    silentremove(staname[k] + ".subfault" + num + '.DS.vel.t')
                    if impulse == True:
                        silentremove(staname[k] + ".subfault" + num +
                                     '.DS.vel.ri')
                        silentremove(staname[k] + ".subfault" + num +
                                     '.DS.vel.ti')
                        silentremove(staname[k] + ".subfault" + num +
                                     '.DS.vel.zi')
            else:  #Compute static synthetics
                if okada == False:  #Layered earth model
                    temp_pipe = []
                    diststr = '%.1f' % d[
                        k]  #Need current distance in string form for external call
                    if insar == True:
                        green_file = green_path + model_name + ".static." + strdepth + ".sub" + subfault + '.insar'  #Output dir
                    else:  #GPS
                        green_file = green_path + model_name + ".static." + strdepth + ".sub" + subfault + '.gps'  #Output dir
                    statics = loadtxt(green_file)  #Load GFs
                    if len(statics) < 1:
                        print('ERROR: Empty GF file')
                        break
                    #Print static GFs into a pipe and pass into synthetics command
                    try:
                        temp_pipe = statics[k, :]
                    except:
                        temp_pipe = statics
                    inpipe = ''
                    for j in range(len(temp_pipe)):
                        inpipe = inpipe + ' %.6e' % temp_pipe[j]
                    #Form command for external call
                    commandDS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+\
                            " -A"+str(az[k])+" -P"
                    commandSS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+\
                            " -A"+str(az[k])+" -P"
                    commandSS = split(commandSS)  #Lexical split
                    commandDS = split(commandDS)
                    #Make system calls, one for DS, one for SS
                    ps = subprocess.Popen(
                        ['printf', inpipe], stdout=subprocess.PIPE
                    )  #This is the statics pipe, pint stdout to syn's stdin
                    p = subprocess.Popen(
                        commandSS,
                        stdin=ps.stdout,
                        stdout=open(
                            green_path + staname[k] + '.subfault' + num +
                            '.SS.static.rtz', 'w'))
                    p.communicate()
                    ps = subprocess.Popen(
                        ['printf', inpipe], stdout=subprocess.PIPE
                    )  #This is the statics pipe, pint stdout to syn's stdin
                    p = subprocess.Popen(
                        commandDS,
                        stdin=ps.stdout,
                        stdout=open(
                            green_path + staname[k] + '.subfault' + num +
                            '.DS.static.rtz', 'w'))
                    p.communicate()
                    #Rotate radial/transverse to East/North, correct vertical and scale to m
                    statics = loadtxt(green_path + staname[k] + '.subfault' +
                                      num + '.SS.static.rtz')
                    u = statics[2] / 100
                    r = statics[3] / 100
                    t = statics[4] / 100
                    ntemp, etemp = rt2ne(array([r, r]), array([t, t]), az[k])
                    n = ntemp[0]
                    e = etemp[0]
                    savetxt(
                        green_path + staname[k] + '.subfault' + num +
                        '.SS.static.neu', (n, e, u, beta))
                    statics = loadtxt(green_path + staname[k] + '.subfault' +
                                      num + '.DS.static.rtz')
                    u = statics[2] / 100
                    r = statics[3] / 100
                    t = statics[4] / 100
                    ntemp, etemp = rt2ne(array([r, r]), array([t, t]), az[k])
                    n = ntemp[0]
                    e = etemp[0]
                    savetxt(green_path + staname[k] + '.subfault' + num +
                            '.DS.static.neu', (n, e, u, beta),
                            header='north(m),east(m),up(m),beta(degs)')
                else:  #Okada half space solutions
                    #SS
                    n, e, u = okada_synthetics(strike, dip, rakeSS,
                                               ss_length_in_km,
                                               ds_length_in_km, xs, ys, zs,
                                               lon_sta[k], lat_sta[k],
                                               mu_okada)
                    savetxt(staname[k] + '.subfault' + num + '.SS.static.neu',
                            (n, e, u, beta),
                            header='north(m),east(m),up(m),beta(degs)')
                    #DS
                    n, e, u = okada_synthetics(strike, dip, rakeDS,
                                               ss_length_in_km,
                                               ds_length_in_km, xs, ys, zs,
                                               lon_sta[k], lat_sta[k],
                                               mu_okada)
                    savetxt(staname[k] + '.subfault' + num + '.DS.static.neu',
                            (n, e, u, beta),
                            header='north(m),east(m),up(m),beta(degs)')
예제 #2
0
def run_parallel_synthetics(home,project_name,station_file,model_name,integrate,static,tsunami,time_epi,
                beta,custom_stf,impulse,rank,size,insar=False,okada=False,mu_okada=45e9):
    '''
    Use green functions and compute synthetics at stations for a single source
    and multiple stations. This code makes an external system call to syn.c first it
    will make the external call for the strike-slip component then a second externall
    call will be made for the dip-slip component. The unit amount of moment is 1e15
    which corresponds to Mw=3.9333...
    
    IN:
        source: 1-row numpy array containig informaiton aboutt he source, lat, lon, depth, etc...
        station_file: File name with the station coordinates
        green_path: Directopry where GFs are stored
        model_file: File containing the Earth velocity structure
        integrate: =0 if youw ant velocity waveforms, =1 if you want displacements
        static: =0 if computing full waveforms, =1 if computing only the static field
        subfault: String indicating the subfault being worked on
        coord_type: =0 if problem is in cartesian coordinates, =1 if problem is in lat/lon
        
    OUT:
        log: Sysytem standard output and standard error for log
    '''

    import os
    import subprocess
    from pandas import DataFrame as df
    from mudpy.forward import get_mu
    from numpy import array,genfromtxt,loadtxt,savetxt,log10,zeros,sin,cos,ones,deg2rad
    from obspy import read
    from shlex import split
    from mudpy.green import src2sta,rt2ne,origin_time,okada_synthetics
    from glob import glob
    from mudpy.green import silentremove
    from os import remove
    
    #What parameters are we using?
    if rank==0:
        out='''Running all processes with:
        home = %s
        project_name = %s
        station_file = %s
        model_name = %s
        integrate = %s
        static = %s
        tsunami = %s
        time_epi = %s
        beta = %d
        custom_stf = %s
        impulse = %s
        insar = %s
        okada = %s
        mu = %.2e
        ''' %(home,project_name,station_file,model_name,str(integrate),str(static),str(tsunami),str(time_epi),beta,custom_stf,impulse,insar,okada,mu_okada)
        print(out)
        
    #Read your corresponding source file
    mpi_source=genfromtxt(home+project_name+'/data/model_info/mpi_source.'+str(rank)+'.fault')
    
    #Constant parameters
    rakeDS=90+beta #90 is thrust, -90 is normal
    rakeSS=0+beta #0 is left lateral, 180 is right lateral
    tb=50 #Number of samples before first arrival (should be 50, NEVER CHANGE, if you do then adjust in fk.pl)
    
    #Figure out custom STF
    if custom_stf.lower()!='none':
        custom_stf=home+project_name+'/GFs/STFs/'+custom_stf
    else:
        custom_stf=None
    
    #Load structure
    model_file=home+project_name+'/structure/'+model_name
    structure=loadtxt(model_file,ndmin=2)
    
    #this keeps track of statics dataframe
    write_df=False
    
    for ksource in range(len(mpi_source)):
        
        source=mpi_source[ksource,:]
        
        #Parse the soruce information
        num=str(int(source[0])).rjust(4,'0')
        xs=source[1]
        ys=source[2]
        zs=source[3]
        strike=source[4]
        dip=source[5]
        rise=source[6]
        if impulse==True:
            duration=0
        else:
            duration=source[7]
        ss_length=source[8]
        ds_length=source[9]
        ss_length_in_km=ss_length/1000.
        ds_length_in_km=ds_length/1000.
        strdepth='%.4f' % zs
        subfault=str(int(source[0])).rjust(4,'0')
        if static==0 and tsunami==0:  #Where to save dynamic waveforms
            green_path=home+project_name+'/GFs/dynamic/'+model_name+"_"+strdepth+".sub"+subfault+"/"
        if static==1 and tsunami==1:  #Where to save dynamic waveforms
            green_path=home+project_name+'/GFs/tsunami/'+model_name+"_"+strdepth+".sub"+subfault+"/"
        if static==1 and tsunami==0:  #Where to save statics
            green_path=home+project_name+'/GFs/static/'+model_name+"_"+strdepth+".sub"+subfault+"/"
        staname=genfromtxt(station_file,dtype="U",usecols=0)
        if staname.shape==(): #Single staiton file
            staname=array([staname])
        #Compute distances and azimuths
        d,az,lon_sta,lat_sta=src2sta(station_file,source,output_coordinates=True)
        
        #Get moment corresponding to 1 meter of slip on subfault
        mu=get_mu(structure,zs)
        Mo=mu*ss_length*ds_length*1.0
        Mw=(2./3)*(log10(Mo)-9.1)
        
        #Move to output folder
        os.chdir(green_path)
        print('Processor '+str(rank)+' is working on subfault '+str(int(source[0]))+' and '+str(len(d))+' stations ')
        
        #This is looping over "sites"
        for k in range(len(d)):
            
            if static==0: #Compute full waveforms
                diststr='%.6f' % d[k] #Need current distance in string form for external call
                #Form the strings to be used for the system calls according to user desired options
                if integrate==1: #Make displ.
                    #First Stike-Slip GFs
                    if custom_stf==None:
                        commandSS="syn -I -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+" -D"+str(duration)+ \
                            "/"+str(rise)+" -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".SS.disp.x -G"+green_path+diststr+".grn.0"
                        commandSS=split(commandSS) #Split string into lexical components for system call
                        #Now dip slip
                        commandDS="syn -I -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+" -D"+str(duration)+ \
                            "/"+str(rise)+" -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".DS.disp.x -G"+green_path+diststr+".grn.0"
                        commandDS=split(commandDS)
                    else:
                        commandSS="syn -I -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+" -S"+custom_stf+ \
                            " -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".SS.disp.x -G"+green_path+diststr+".grn.0"
                        commandSS=split(commandSS) #Split string into lexical components for system call
                        #Now dip slip
                        commandDS="syn -I -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+" -S"+custom_stf+ \
                            " -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".DS.disp.x -G"+green_path+diststr+".grn.0"
                        commandDS=split(commandDS)
                else: #Make vel.
                    #First Stike-Slip GFs
                    if custom_stf==None:
                        commandSS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+" -D"+str(duration)+ \
                            "/"+str(rise)+" -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".SS.vel.x -G"+green_path+diststr+".grn.0"
                        commandSS=split(commandSS)
                        #Now dip slip
                        commandDS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+" -D"+str(duration)+ \
                            "/"+str(rise)+" -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".DS.vel.x -G"+green_path+diststr+".grn.0"
                        commandDS=split(commandDS)
                    else:
                        commandSS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+" -S"+custom_stf+ \
                            " -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".SS.vel.x -G"+green_path+diststr+".grn.0"
                        commandSS=split(commandSS)
                        #Now dip slip
                        commandDS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+" -S"+custom_stf+ \
                            " -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".DS.vel.x -G"+green_path+diststr+".grn.0"
                        commandDS=split(commandDS)
                #Run the strike- and dip-slip commands (make system calls)
                p=subprocess.Popen(commandSS)
                p.communicate() 
                p=subprocess.Popen(commandDS)
                p.communicate()
                #Result is in RTZ system (+Z is down) rotate to NEZ with +Z up and scale to m or m/s
                if integrate==1: #'tis displacememnt
                    #Strike slip
                    if duration>0: #Is there a source time fucntion? Yes!
                        r=read(staname[k]+".subfault"+num+'.SS.disp.r')
                        t=read(staname[k]+".subfault"+num+'.SS.disp.t')
                        z=read(staname[k]+".subfault"+num+'.SS.disp.z')
                    else: #No! This is the impulse response!
                        r=read(staname[k]+".subfault"+num+'.SS.disp.ri')
                        t=read(staname[k]+".subfault"+num+'.SS.disp.ti')
                        z=read(staname[k]+".subfault"+num+'.SS.disp.zi')
                    ntemp,etemp=rt2ne(r[0].data,t[0].data,az[k])
                    #Scale to m and overwrite with rotated waveforms
                    n=r.copy()
                    n[0].data=ntemp/100
                    e=t.copy()
                    e[0].data=etemp/100
                    z[0].data=z[0].data/100
                    # get rid of numerical "noise" in the first tb samples
                    n[0].data[0:tb]=0
                    e[0].data[0:tb]=0
                    z[0].data[0:tb]=0
                    n=origin_time(n,time_epi,tb)
                    e=origin_time(e,time_epi,tb)
                    z=origin_time(z,time_epi,tb)
                    n.write(staname[k]+".subfault"+num+'.SS.disp.n',format='SAC')
                    e.write(staname[k]+".subfault"+num+'.SS.disp.e',format='SAC')
                    z.write(staname[k]+".subfault"+num+'.SS.disp.z',format='SAC')
                    silentremove(staname[k]+".subfault"+num+'.SS.disp.r')
                    silentremove(staname[k]+".subfault"+num+'.SS.disp.t')
                    if impulse==True:
                        silentremove(staname[k]+".subfault"+num+'.SS.disp.ri')
                        silentremove(staname[k]+".subfault"+num+'.SS.disp.ti')
                        silentremove(staname[k]+".subfault"+num+'.SS.disp.zi')
                    #Dip Slip
                    if duration>0: #Is there a source time fucntion? Yes!
                        r=read(staname[k]+".subfault"+num+'.DS.disp.r')
                        t=read(staname[k]+".subfault"+num+'.DS.disp.t')
                        z=read(staname[k]+".subfault"+num+'.DS.disp.z')
                    else: #No! This is the impulse response!
                        r=read(staname[k]+".subfault"+num+'.DS.disp.ri')
                        t=read(staname[k]+".subfault"+num+'.DS.disp.ti')
                        z=read(staname[k]+".subfault"+num+'.DS.disp.zi')
                    ntemp,etemp=rt2ne(r[0].data,t[0].data,az[k])
                    n=r.copy()
                    n[0].data=ntemp/100
                    e=t.copy()
                    e[0].data=etemp/100
                    z[0].data=z[0].data/100
                    n=origin_time(n,time_epi,tb)
                    e=origin_time(e,time_epi,tb)
                    z=origin_time(z,time_epi,tb)
                    n.write(staname[k]+".subfault"+num+'.DS.disp.n',format='SAC')
                    e.write(staname[k]+".subfault"+num+'.DS.disp.e',format='SAC')
                    z.write(staname[k]+".subfault"+num+'.DS.disp.z',format='SAC')
                    silentremove(staname[k]+".subfault"+num+'.DS.disp.r')
                    silentremove(staname[k]+".subfault"+num+'.DS.disp.t')
                    if impulse==True:
                        silentremove(staname[k]+".subfault"+num+'.DS.disp.ri')
                        silentremove(staname[k]+".subfault"+num+'.DS.disp.ti')
                        silentremove(staname[k]+".subfault"+num+'.DS.disp.zi')
                else: #Waveforms are velocity, as before, rotate from RT-Z to NE+Z and scale to m/s
                    #Strike slip
                    if duration>0: #Is there a source time fucntion? Yes!
                        r=read(staname[k]+".subfault"+num+'.SS.vel.r')
                        t=read(staname[k]+".subfault"+num+'.SS.vel.t')
                        z=read(staname[k]+".subfault"+num+'.SS.vel.z')
                    else: #No! This is the impulse response!
                        r=read(staname[k]+".subfault"+num+'.SS.vel.ri')
                        t=read(staname[k]+".subfault"+num+'.SS.vel.ti')
                        z=read(staname[k]+".subfault"+num+'.SS.vel.zi')
                    ntemp,etemp=rt2ne(r[0].data,t[0].data,az[k])
                    n=r.copy()
                    n[0].data=ntemp/100
                    e=t.copy()
                    e[0].data=etemp/100
                    z[0].data=z[0].data/100
                    n=origin_time(n,time_epi,tb)
                    e=origin_time(e,time_epi,tb)
                    z=origin_time(z,time_epi,tb)
                    n.write(staname[k]+".subfault"+num+'.SS.vel.n',format='SAC')
                    e.write(staname[k]+".subfault"+num+'.SS.vel.e',format='SAC')
                    z.write(staname[k]+".subfault"+num+'.SS.vel.z',format='SAC')
                    silentremove(staname[k]+".subfault"+num+'.SS.vel.r')
                    silentremove(staname[k]+".subfault"+num+'.SS.vel.t')
                    if impulse==True:
                        silentremove(staname[k]+".subfault"+num+'.SS.vel.ri')
                        silentremove(staname[k]+".subfault"+num+'.SS.vel.ti')
                        silentremove(staname[k]+".subfault"+num+'.SS.vel.zi')
                    #Dip Slip
                    if duration>0: #Is there a source time fucntion? Yes!
                        r=read(staname[k]+".subfault"+num+'.DS.vel.r')
                        t=read(staname[k]+".subfault"+num+'.DS.vel.t')
                        z=read(staname[k]+".subfault"+num+'.DS.vel.z')
                    else: #No! This is the impulse response!
                        r=read(staname[k]+".subfault"+num+'.DS.vel.ri')
                        t=read(staname[k]+".subfault"+num+'.DS.vel.ti')
                        z=read(staname[k]+".subfault"+num+'.DS.vel.zi')
                    ntemp,etemp=rt2ne(r[0].data,t[0].data,az[k])
                    n=r.copy()
                    n[0].data=ntemp/100
                    e=t.copy()
                    e[0].data=etemp/100
                    z[0].data=z[0].data/100
                    n=origin_time(n,time_epi,tb)
                    e=origin_time(e,time_epi,tb)
                    z=origin_time(z,time_epi,tb)
                    n.write(staname[k]+".subfault"+num+'.DS.vel.n',format='SAC')
                    e.write(staname[k]+".subfault"+num+'.DS.vel.e',format='SAC')
                    z.write(staname[k]+".subfault"+num+'.DS.vel.z',format='SAC')
                    silentremove(staname[k]+".subfault"+num+'.DS.vel.r')
                    silentremove(staname[k]+".subfault"+num+'.DS.vel.t')
                    if impulse==True:
                        silentremove(staname[k]+".subfault"+num+'.DS.vel.ri')
                        silentremove(staname[k]+".subfault"+num+'.DS.vel.ti')
                        silentremove(staname[k]+".subfault"+num+'.DS.vel.zi')
            else: #Compute static synthetics
                if okada==False:  #Layered earth model
                    
                    #this is because when I first wrote this code it processed each
                    #source/station pair independently but now that it's vectorized
                    #it's does ALL stations in one fell swoop, given the logic it's 
                    #easier to just keep this inside the for loop and use the if to
                    #run it jsut the first time for all sites
                    if k==0:   
                        
                        #initalize output variables
                        staticsSS = zeros((len(d),4))
                        staticsDS = zeros((len(d),4))
                        write_df=True
                        
                        #read GFs file
                        if insar==True:
                            green_file=green_path+model_name+".static."+strdepth+".sub"+subfault+'.insar' #Output dir
                        else: #GPS
                            green_file=green_path+model_name+".static."+strdepth+".sub"+subfault+'.gps' #Output 

                        statics=loadtxt(green_file) #Load GFs
                        Nsites=len(statics) 
                        
                        if len(statics)<1:
                            print('ERROR: Empty GF file')
                            break
                        
                        #Now get radiation pattern terms, there will be 3 terms
                        #for each direction so 9 terms total. THis comes from funtion
                        #dc_radiat() in radiats.c from fk
                        radiation_pattern_ss = zeros((Nsites,9))
                        radiation_pattern_ds = zeros((Nsites,9))
                        
                        rakeSSrad = deg2rad(rakeSS)
                        rakeDSrad = deg2rad(rakeDS)
                        dip_rad = deg2rad(dip)
                        pseudo_strike = deg2rad(az-strike)
                        
                        #Let's do SS first
                        r = rakeSSrad
                        
                        #trigonometric terms following nomenclature used in radiats.c
                        sstk=sin(pseudo_strike) ; cstk=cos(pseudo_strike)
                        sdip=sin(dip_rad) ; cdip=cos(dip_rad)
                        srak=sin(r) ; crak=cos(r)
                        sstk2=2*sstk*cstk ; cstk2=cstk*cstk-sstk*sstk
                        sdip2=2*sdip*cdip ; cdip2=cdip*cdip-sdip*sdip
                        
                        # terms for up component
                        u_dd = 0.5*srak*sdip2*ones(Nsites)
                        u_ds = -sstk*srak*cdip2+cstk*crak*cdip
                        u_ss = -sstk2*crak*sdip-0.5*cstk2*srak*sdip2
                        
                        #terms for r component
                        r_dd = u_dd.copy()
                        r_ds = u_ds.copy()
                        r_ss = u_ss.copy()
                        
                        #terms for t component
                        t_dd = zeros(Nsites)
                        t_ds = cstk*srak*cdip2+sstk*crak*cdip
                        t_ss = cstk2*crak*sdip-0.5*sstk2*srak*sdip2

                        #assemble in one variable
                        radiation_pattern_ss[:,0] = u_dd
                        radiation_pattern_ss[:,1] = u_ds
                        radiation_pattern_ss[:,2] = u_ss
                        
                        radiation_pattern_ss[:,3] = r_dd
                        radiation_pattern_ss[:,4] = r_ds
                        radiation_pattern_ss[:,5] = r_ss
                        
                        radiation_pattern_ss[:,6] = t_dd
                        radiation_pattern_ss[:,7] = t_ds
                        radiation_pattern_ss[:,8] = t_ss
                        
                        
                        #Now radiation pattern for DS
                        r = rakeDSrad
                        
                        #trigonometric terms following nomenclature used in radiats.c
                        sstk=sin(pseudo_strike) ; cstk=cos(pseudo_strike)
                        sdip=sin(dip_rad) ; cdip=cos(dip_rad)
                        srak=sin(r) ; crak=cos(r)
                        sstk2=2*sstk*cstk ; cstk2=cstk*cstk-sstk*sstk
                        sdip2=2*sdip*cdip ; cdip2=cdip*cdip-sdip*sdip
                        
                        # terms for up component
                        u_dd = 0.5*srak*sdip2*ones(Nsites)
                        u_ds = -sstk*srak*cdip2+cstk*crak*cdip
                        u_ss = -sstk2*crak*sdip-0.5*cstk2*srak*sdip2
                        
                        #terms for r component
                        r_dd = u_dd.copy()
                        r_ds = u_ds.copy()
                        r_ss = u_ss.copy()
                        
                        #terms for t component
                        t_dd = zeros(Nsites)
                        t_ds = cstk*srak*cdip2+sstk*crak*cdip
                        t_ss = cstk2*crak*sdip-0.5*sstk2*srak*sdip2
                        
                        #assemble in one variable
                        radiation_pattern_ds[:,0] = u_dd
                        radiation_pattern_ds[:,1] = u_ds
                        radiation_pattern_ds[:,2] = u_ss
                        
                        radiation_pattern_ds[:,3] = r_dd
                        radiation_pattern_ds[:,4] = r_ds
                        radiation_pattern_ds[:,5] = r_ss
                        
                        radiation_pattern_ds[:,6] = t_dd
                        radiation_pattern_ds[:,7] = t_ds
                        radiation_pattern_ds[:,8] = t_ss
                        
                        
                        #Now define the scalng based on magnitude this is variable
                        #"coef" in the syn.c original source code
                        scale = 10**(1.5*Mw+16.1-20) #definition used in syn.c
                        
                        #Scale radiation patterns accordingly
                        radiation_pattern_ss *= scale
                        radiation_pattern_ds *= scale
                        
                        #Now multiply each GF component by the appropriate SCALED
                        #radiation pattern term and add em up to get the displacements
                        # also /100 to convert  to meters
                        up_ss = radiation_pattern_ss[:,0:3]*statics[:,[1,4,7]] 
                        up_ss = up_ss.sum(axis=1) / 100
                        up_ds = radiation_pattern_ds[:,0:3]*statics[:,[1,4,7]] 
                        up_ds = up_ds.sum(axis=1)    / 100                     

                        radial_ss = radiation_pattern_ss[:,3:6]*statics[:,[2,5,8]] 
                        radial_ss = radial_ss.sum(axis=1) / 100
                        radial_ds = radiation_pattern_ds[:,3:6]*statics[:,[2,5,8]] 
                        radial_ds = radial_ds.sum(axis=1) / 100 
                        
                        tangential_ss = radiation_pattern_ss[:,6:9]*statics[:,[3,6,9]] 
                        tangential_ss = tangential_ss.sum(axis=1) / 100
                        tangential_ds = radiation_pattern_ds[:,6:9]*statics[:,[3,6,9]] 
                        tangential_ds = tangential_ds.sum(axis=1) / 100
                        
                        #rotate to neu
                        n_ss,e_ss=rt2ne(radial_ss,tangential_ss,az)
                        n_ds,e_ds=rt2ne(radial_ds,tangential_ds,az)

                        #put in output variables
                        staticsSS[:,0]=n_ss
                        staticsSS[:,1]=e_ss
                        staticsSS[:,2]=up_ss
                        staticsSS[:,3]=beta*ones(Nsites)
                        
                        staticsDS[:,0]=n_ds
                        staticsDS[:,1]=e_ds
                        staticsDS[:,2]=up_ds
                        staticsDS[:,3]=beta*ones(Nsites)
                        
                    else:
                        pass
            

                else: #Okada half space solutions
                #SS
                    n,e,u=okada_synthetics(strike,dip,rakeSS,ss_length_in_km,ds_length_in_km,xs,ys,
                        zs,lon_sta[k],lat_sta[k],mu_okada)
                    savetxt(staname[k]+'.subfault'+num+'.SS.static.neu',(n,e,u,beta),header='north(m),east(m),up(m),beta(degs)')
                    #DS
                    n,e,u=okada_synthetics(strike,dip,rakeDS,ss_length_in_km,ds_length_in_km,xs,ys,
                        zs,lon_sta[k],lat_sta[k],mu_okada)
                    savetxt(staname[k]+'.subfault'+num+'.DS.static.neu',(n,e,u,beta),header='north(m),east(m),up(m),beta(degs)')

        
        if write_df==True and static ==1: #Note to self: stop using 0,1 and swithc to True/False
            
            #Strike slip
            SSdf = df(data=None, index=None, columns=['staname','n','e','u','beta'])
            SSdf.staname=staname
            SSdf.n=staticsSS[:,0]
            SSdf.e=staticsSS[:,1]
            SSdf.u=staticsSS[:,2]
            SSdf.beta=staticsSS[:,3]
            SSdf.to_csv(green_path+'subfault'+num+'.SS.static.neu',sep='\t',index=False,header=False)
            
            DSdf = df(data=None, index=None, columns=['staname','n','e','u','beta'])     
            DSdf.staname=staname
            DSdf.n=staticsDS[:,0]
            DSdf.e=staticsDS[:,1]
            DSdf.u=staticsDS[:,2]
            DSdf.beta=staticsDS[:,3]
            DSdf.to_csv(green_path+'subfault'+num+'.DS.static.neu',sep='\t',index=False,header=False)