# TimeAssociation.jl
#=
 this script reads in csv files from the timing (pixels to seconds) of the Korbel 1954 accelerograms
 at Ferndale and Eureka and applies them to xy positions extracted using DigitSeis from the same records

 Written by: Thomas Lee
 Created on: 7/25/2024
=#


## PACKAGES
using Seis
import Dates
using Plots
using NaNStatistics
using Statistics
using Interpolations

## SETTINGS
# csv with xy positions
c_xy = [
    "/Users/thomaslee/Downloads/KorbelSeismicRecords/EurekaFerndale/xy_DigitSeis_19541221_EUREKA_ACC_NE.csv",
    "/Users/thomaslee/Downloads/KorbelSeismicRecords/EurekaFerndale/xy_DigitSeis_19541221_EUREKA_ACC_SE.csv",
    "/Users/thomaslee/Downloads/KorbelSeismicRecords/EurekaFerndale/xy_DigitSeis_19541221_EUREKA_ACC_Z.csv",
    "/Users/thomaslee/Downloads/KorbelSeismicRecords/EurekaFerndale/xy_DigitSeis_19541221_FERNDALE_ACC_NW.csv",
    "/Users/thomaslee/Downloads/KorbelSeismicRecords/EurekaFerndale/xy_DigitSeis_19541221_FERNDALE_ACC_SW.csv",
    "/Users/thomaslee/Downloads/KorbelSeismicRecords/EurekaFerndale/xy_DigitSeis_19541221_FERNDALE_ACC_Z.csv",
]
c_names = [
    "EUREKA_N79E",
    "EUREKA_S11E",
    "EUREKA_UP",
    "FERNDALE_N46W",
    "FERNDALE_S44W",
    "FERNDALE_UP"
]
# corresponding times for each
c_time = [
    "/Users/thomaslee/Downloads/KorbelSeismicRecords/EurekaFerndale/1954EurekaTiming.csv",
    "/Users/thomaslee/Downloads/KorbelSeismicRecords/EurekaFerndale/1954EurekaTiming.csv",
    "/Users/thomaslee/Downloads/KorbelSeismicRecords/EurekaFerndale/1954EurekaTiming.csv",
    "/Users/thomaslee/Downloads/KorbelSeismicRecords/EurekaFerndale/1954FerndaleTiming.csv",
    "/Users/thomaslee/Downloads/KorbelSeismicRecords/EurekaFerndale/1954FerndaleTiming.csv",
    "/Users/thomaslee/Downloads/KorbelSeismicRecords/EurekaFerndale/1954FerndaleTiming.csv",
]
# corresponding column of relevant data for each
c_time_column = [5, 6, 4, 6, 5, 4]
# start times
stimes = [
    Dates.DateTime(1954,12,21,19,56,33,200), #EUR
    Dates.DateTime(1954,12,21,19,56,33,200),
    Dates.DateTime(1954,12,21,19,56,33,200),
    Dates.DateTime(1954,12,21,19,56,24,500), # FER
    Dates.DateTime(1954,12,21,19,56,24,500),
    Dates.DateTime(1954,12,21,19,56,24,500),
]
# use zpos
use_zpos = [0, 0, 0, 0, 0, 0]
# instrument metadata
lon = [-124.164, -124.164, -124.164, -124.264, -124.264, -124.264]
lat = [  40.801,   40.801,   40.801,   40.576,   40.576,   40.576]
dep = [       0,        0,        0,        0,        0,        0]
elv = [       5,        5,        5,       16,       16,       16]
azi = [      79,      169,        0,      314,      224,        0] # CW from north
inc = [      90,       90,        0,       90,       90,        0] # from vertical
sta = [   "EUR",    "EUR",    "EUR",    "FER",    "FER",    "FER"]
# output location
c_dataout = "/Users/thomaslee/Downloads/KorbelSeismicRecords/EurekaFerndale/output/"
if !isdir(c_dataout)
    mkdir(c_dataout)
end

## LOOP OVER EACH xy FILE
for i = 1:lastindex(c_xy)
    # print(string("i=",i,"\n"))
    # LOAD xy DATA
    ln = open(c_xy[i]) do f
        readlines(f)
    end
    xpos = []
    ypos = []
    zpos = [] # zero line position (THIS IS NOT VERY RELIABLE LIKELY)
    for il = 2:lastindex(ln) # skip header line
        commas = findall(map(x->ln[il][x]==',',1:lastindex(ln[il])))
        if length(commas)>=3
            push!(xpos,parse(Float64,ln[il][1:commas[1]-1]))
            push!(ypos,parse(Float64,ln[il][(commas[1]+1):(commas[2]-1)]))
            push!(zpos,parse(Float64,ln[il][(commas[3]+1):end]))
        else
            error(string("Unexpected number of commas in ",c_xy[i],"\n"))
        end
    end

    # CONVERT TO FLOAT64
    xpos = convert.(Float64,xpos)
    ypos = convert.(Float64,ypos)
    zpos = convert.(Float64,zpos)

    # GET NEW zpos IF NEEDED
    if use_zpos[i]==0
        zpos = fill!(Vector{Float64}(undef,length(ypos)),NaN)
        idxtmp = findall(.!isnan.(ypos))
        zpos[idxtmp] = movmean(ypos[idxtmp],convert(Int,round(length(idxtmp)/5)))
    end

    # REMOVE ZERO LINE
    ypos0 = deepcopy(ypos)
    ypos = ypos .- zpos

    # PLOT PIXEL SPACE TIMING
    hp_pixel = plot(xpos,zpos,lc=:red,ls=:dash,
        label="zeroline",title=c_names[i],
        xlabel="time (pix)",ylabel="amplitude (pix)",)
    plot!(hp_pixel,xpos,ypos0,lc=:black,label="data")
    hp_pixel_zero = plot(xpos,zeros(length(xpos)),lc=:red,ls=:dash,
        label="zeroline",title=string(c_names[i]," (zeroed)"),
        xlabel="time (pix)",ylabel="amplitude (pix)",)
    plot!(hp_pixel_zero,xpos,ypos,lc=:black,label="data")

    # LOAD RELEVANT TIMING
    ln = open(c_time[i]) do f
        readlines(f)
    end
    tpix = [] # time in pixels
    tsec = [] # time in seconds
    wdth = [] # width of segment 
    for il = 2:lastindex(ln) # skip header line
        commas = findall(map(x->ln[il][x]==',',1:lastindex(ln[il])))
        if length(commas)>=3
            push!(tsec,parse(Float64,ln[il][1:commas[1]-1]))
            push!(wdth,parse(Float64,ln[il][(commas[2]+1):(commas[3]-1)]))
            if c_time_column[i]==4
                idxtmp = (commas[3]+1):(commas[4]-1)
            elseif c_time_column[i]==5
                idxtmp = (commas[4]+1):(commas[5]-1)
            elseif c_time_column[i]==6
                idxtmp = (commas[5]+1):lastindex(ln[il])
            else
                error(string("Unrecognized column specified for ",c_time[i],"\n"))
            end
            push!(tpix,parse(Float64,ln[il][idxtmp]))
        else
            error(string("Unexpected number of commas in ",c_xy[i],"\n"))
        end
    end

    # CONVERT TO FLOAT64
    tpix = convert.(Float64,tpix)
    wdth = convert.(Float64,wdth)
    tsec = convert.(Float64,tsec)

    # GET THE ROLLING AVERAGE OF THE WIDTHS
    wdth0 = deepcopy(wdth)
    wdth = movmean(wdth0,convert(Int,round(length(wdth0)/5)))

    # MAKE PLOT OF 0.25s PIXEL WIDTH AS FUNCTION OF X-POSITION
    hp_wdth = plot(tpix,wdth0,lc=:gray,label="widths",
        title=string("0.25s Pixel Equivalent (avg: ",
            convert(Int,round(mean(filter(!isnan,wdth0)))),"; std: ",
            convert(Int,round(std(filter(!isnan,wdth0)))),")"),
        xlabel="time (pix)",ylabel="0.25s width in pixels",)
    plot!(hp_wdth,tpix[1:2:end],wdth0[1:2:end],lc=:blue,label="gaps",)
    plot!(hp_wdth,tpix[2:2:end],wdth0[2:2:end],lc=:red,label="dashes")
    plot!(hp_wdth,tpix,wdth,lc=:black,label="averaged")

    # CREATE NEW TIME VECTOR IN PIXELS WITH SMOOTHED VERSION
    tpix0 = deepcopy(tpix)
    tpix = [tpix0[1]]
    for ii = 2:lastindex(wdth)
        push!(tpix,tpix[ii-1]+wdth[ii])
    end

    # OFFSET tsec PROPERLY
    tsec0 = deepcopy(tsec)
    tsec = tsec0 .- argmin(abs.(tpix))*0.25

    # INTERPOLATE tsec TO SAME AS xpos
    tsecint = fill!(Vector{Float64}(undef,length(xpos)),NaN)
    itpt = LinearInterpolation(tpix,tsec)
    idxtmp = findall(minimum(tpix).<=xpos.<=maximum(tpix))
    tsecint[idxtmp] = itpt(xpos[idxtmp])
    
    # INTERPOLATE TO STANDARD TIMING STEP (100sps, 0.01s)
    t = 0:0.01:floor(maximum(filter(!isnan,tsecint)),digits=2)
    d = fill!(Vector{Float64}(undef,length(t)),NaN)
    idxtmp = findall(.!isnan.(tsecint) .& .!isnan.(ypos))
    itpd = LinearInterpolation(tsecint[idxtmp],ypos[idxtmp])
    idxtmp2 = findall(minimum(filter(!isnan,tsecint[idxtmp])).<=
        t.<=maximum(filter(!isnan,tsecint[idxtmp])))
    d[idxtmp2] = itpd(t[idxtmp2])
    # trim
    idxtmp = findall(.!isnan.(d))
    d = d[idxtmp]; t = t[idxtmp]

    # PLOT TIME TRACE
    hp_time = plot(stimes[i].+Dates.Millisecond.(convert.(Int,round.(t*1000))),d,lc=:black,
        label="",xlabel="time",ylabel="amplitude (pix)",title=string(c_names[i]," (timed; 100sps)"),
    )

    # WRITE OUT PLOTS
    hp_all = plot(hp_pixel,hp_pixel_zero,hp_wdth,hp_time,layout=grid(2,2),size=(1400,1000))
    savefig(hp_all,string(c_dataout,c_names[i],".pdf"))

    # WRITE OUT AS SAC
    # trace
    S = Trace(t[1], 0.01, d)
    # start time
    S.evt.time = stimes[i]
    # metadata for station
    S.sta.lon = lon[i]
    S.sta.lat = lat[i]
    S.sta.dep = dep[i]
    S.sta.elev = elv[i]
    S.sta.azi = azi[i]# clockwise from N
    S.sta.inc = inc[i]
    S.sta.sta = sta[i]
    # write
    write_sac(S,string(c_dataout,c_names[i],".sac"))
    print(string("Wrote out ",length(d)," samples to ",c_dataout,c_names[i],".sac\n"))
end

# save a copy of the script
cp(
    "/Users/thomaslee/Downloads/KorbelSeismicRecords/EurekaFerndale/TimeAssociation.jl",
    string(c_dataout,"script_snapshot_",Dates.format(Dates.now(),"yyymmdd_HHMM"),".txt"),force=true)
print("Done!\n")