# Load (and install if necessary) the Chron.jl package try using Chron catch using Pkg Pkg.add("Chron") using Chron end using Statistics, StatsBase, DelimitedFiles, SpecialFunctions using Plots; gr(); default(fmt = :png) nSamples = 5 # The number of samples you have data for smpl = NewChronAgeData(nSamples) smpl.Name = ("KJ08-157", "KJ04-75", "KJ09-66", "KJ04-72", "KJ04-70",) # These have to match the names used above smpl.Height .= [ -52.0, 44.0, 54.0, 82.0, 93.0,] smpl.Height_sigma .= [ 3.0, 1.0, 3.0, 3.0, 3.0,] smpl.Age_Sidedness .= zeros(nSamples) # Sidedness (zeros by default: geochron constraints are two-sided). Use -1 for a maximum age and +1 for a minimum age, 0 for two-sided smpl.Path = "MyData/" # Where are the data files? Must match where you put the csv files below. smpl.inputSigmaLevel = 2 # i.e., are the data files 1-sigma or 2-sigma. Integer. smpl.Age_Unit = "Ma" # Unit of measurement for ages and errors in the data files smpl.Height_Unit = "cm"; # Unit of measurement for Height and Height_sigma ;ls run(`ls`); ;mkdir MyData/ # You can just paste your data in here, in the following two-column format. # The first column is age and the second column is two-sigma analytical uncertainty. # You should generally exclude all systematic uncertainties here. data = [ 66.12 0.14 66.115 0.048 66.11 0.1 66.11 0.17 66.096 0.056 66.088 0.081 66.085 0.076 66.073 0.084 66.07 0.11 66.055 0.043 66.05 0.16 65.97 0.12 ] # Now, let's write this data to a file, delimited by commas (',') # In this example the filename is KJ08-157.csv, in the folder called MyData writedlm("MyData/KJ08-157.csv", data, ',') data = [ 66.24 0.25 66.232 0.046 66.112 0.085 66.09 0.1 66.04 0.18 66.03 0.12 66.016 0.08 66.003 0.038 65.982 0.071 65.98 0.19 65.977 0.042 65.975 0.066 65.971 0.082 65.963 0.074 65.92 0.12 65.916 0.088 ] writedlm("MyData/KJ04-75.csv",data,',') data = [ 66.13 0.15 66.066 0.052 65.999 0.045 65.989 0.057 65.98 0.11 65.961 0.057 65.957 0.091 65.951 0.066 65.95 0.11 65.929 0.059 ] writedlm("MyData/KJ09-66.csv",data,',') data = [ 66.11 0.2 66.003 0.063 66.003 0.058 65.98 0.06 65.976 0.089 65.973 0.084 65.97 0.15 65.963 0.055 65.959 0.049 65.94 0.18 65.928 0.066 65.92 0.057 65.91 0.14 ] writedlm("MyData/KJ04-72.csv",data,',') data = [ 66.22 0.27 66.06 0.11 65.933 0.066 65.918 0.087 65.92 0.34 65.916 0.067 65.91 0.18 65.892 0.09 65.89 0.063 65.89 0.15 65.88 0.2 65.812 0.069 65.76 0.15 ] writedlm("MyData/KJ04-70.csv",data,',') # Bootstrap a KDE of the pre-eruptive (or pre-deposition) zircon distribution # shape from individual sample datafiles using a KDE of stacked sample data BootstrappedDistribution = BootstrapCrystDistributionKDE(smpl) h = plot(range(0,1,length=length(BootstrappedDistribution)), BootstrappedDistribution, label="Bootstrapped distribution", xlabel="Time (arbitrary units)", ylabel="Probability Density", fg_color_legend=:white) savefig(h, joinpath(smpl.Path,"BootstrappedDistribution.pdf")) display(h) # Number of steps to run in distribution MCMC distSteps = 10^6 distBurnin = distSteps÷100 # Choose the form of the prior distribution to use # Some pre-defined possiblilities include UniformDisribution, # TriangularDistribution, and MeltsVolcanicZirconDistribution # or you can define your own as with BootstrappedDistribution above dist = BootstrappedDistribution # Run MCMC to estimate saturation and eruption/deposition age distributions smpl = tMinDistMetropolis(smpl,distSteps,distBurnin,dist) results = vcat(["Sample" "Age" "2.5% CI" "97.5% CI" "sigma"], hcat(collect(smpl.Name),smpl.Age,smpl.Age_025CI,smpl.Age_975CI,smpl.Age_sigma)) writedlm(smpl.Path*"results.csv", results, ','); # Let's see what that did run(`ls $(smpl.Path)`); sleep(0.5) results = readdlm(smpl.Path*"results.csv",',') # Configure the stratigraphic Monte Carlo model config = NewStratAgeModelConfiguration() # If you in doubt, you can probably leave these parameters as-is config.resolution = 1.0 # Same units as sample height. Smaller is slower! config.bounding = 0.5 # how far away do we place runaway bounds, as a fraction of total section height (bottom, top) = extrema(smpl.Height) npoints_approx = round(Int,length(bottom:config.resolution:top) * (1 + 2*config.bounding)) config.nsteps = 30000 # Number of steps to run in distribution MCMC config.burnin = 20000*npoints_approx # Number to discard config.sieve = round(Int,npoints_approx) # Record one out of every nsieve steps # Run the stratigraphic MCMC model (mdl, agedist, lldist) = StratMetropolisDist(smpl, config); sleep(0.5) # Plot the log likelihood to make sure we're converged (n.b burnin isn't recorded) plot(lldist,xlabel="Step number",ylabel="Log likelihood",label="",line=(0.85,:darkblue)) writedlm(smpl.Path*"agedist.csv", agedist, ',') # Stationary distribution of the age-depth model writedlm(smpl.Path*"height.csv", mdl.Height, ',') # Stratigraphic heights corresponding to each row of agedist writedlm(smpl.Path*"lldist.csv", lldist, ',') # Log likelihood distribution (to check for stationarity) # Plot results (mean and 95% confidence interval for both model and data) hdl = plot([mdl.Age_025CI; reverse(mdl.Age_975CI)],[mdl.Height; reverse(mdl.Height)], fill=(round(Int,minimum(mdl.Height)),0.5,:blue), label="model") plot!(hdl, mdl.Age, mdl.Height, linecolor=:blue, label="", fg_color_legend=:white) # Center line t = smpl.Age_Sidedness .== 0 # Two-sided constraints (plot in black) any(t) && plot!(hdl, smpl.Age[t], smpl.Height[t], xerror=(smpl.Age[t]-smpl.Age_025CI[t],smpl.Age_975CI[t]-smpl.Age[t]),label="data",seriestype=:scatter,color=:black) t = smpl.Age_Sidedness .== 1 # Minimum ages (plot in cyan) any(t) && plot!(hdl, smpl.Age[t], smpl.Height[t], xerror=(smpl.Age[t]-smpl.Age_025CI[t],zeros(count(t))),label="",seriestype=:scatter,color=:cyan,msc=:cyan) any(t) && zip(smpl.Age[t], smpl.Age[t].+nanmean(smpl.Age_sigma[t])*4, smpl.Height[t]) .|> x-> plot!([x[1],x[2]],[x[3],x[3]], arrow=true, label="", color=:cyan) t = smpl.Age_Sidedness .== -1 # Maximum ages (plot in orange) any(t) && plot!(hdl, smpl.Age[t], smpl.Height[t], xerror=(zeros(count(t)),smpl.Age_975CI[t]-smpl.Age[t]),label="",seriestype=:scatter,color=:orange,msc=:orange) any(t) && zip(smpl.Age[t], smpl.Age[t].-nanmean(smpl.Age_sigma[t])*4, smpl.Height[t]) .|> x-> plot!([x[1],x[2]],[x[3],x[3]], arrow=true, label="", color=:orange) plot!(hdl, xlabel="Age ($(smpl.Age_Unit))", ylabel="Height ($(smpl.Height_Unit))") savefig(hdl,smpl.Path*"AgeDepthModel.svg") savefig(hdl,smpl.Path*"AgeDepthModel.pdf") display(hdl) # Interpolate results at a given height height = 0 interpolated_age = linterp1s(mdl.Height,mdl.Age,height) interpolated_age_min = linterp1s(mdl.Height,mdl.Age_025CI,height) interpolated_age_max = linterp1s(mdl.Height,mdl.Age_975CI,height) print("Interpolated age: $interpolated_age +$(interpolated_age_max-interpolated_age)/-$(interpolated_age-interpolated_age_min) Ma") # We can also interpolate the full distribution: interpolated_distribution = Array{Float64}(undef,size(agedist,2)) for i=1:size(agedist,2) interpolated_distribution[i] = linterp1s(mdl.Height,agedist[:,i],height) end histogram(interpolated_distribution, xlabel="Age ($(smpl.Age_Unit))", ylabel="N", label="", fill=(0.75,:darkblue), linecolor=:darkblue) # Set bin width and spacing binwidth = round(nanrange(mdl.Age)/10,sigdigits=1) # Can also set manually, commented out below # binwidth = 0.01 # Same units as smpl.Age binoverlap = 10 ages = collect(minimum(mdl.Age):binwidth/binoverlap:maximum(mdl.Age)) bincenters = ages[1+Int(binoverlap/2):end-Int(binoverlap/2)] spacing = binoverlap # Calculate rates for the stratigraphy of each markov chain step dhdt_dist = Array{Float64}(undef, length(ages)-binoverlap, config.nsteps) @time for i=1:config.nsteps heights = linterp1(reverse(agedist[:,i]), reverse(mdl.Height), ages) dhdt_dist[:,i] .= abs.(heights[1:end-spacing] .- heights[spacing+1:end]) ./ binwidth end # Find mean and 1-sigma (68%) CI dhdt = nanmean(dhdt_dist,dim=2) dhdt_50p = nanmedian(dhdt_dist,dim=2) dhdt_16p = nanpctile(dhdt_dist,15.865,dim=2) # Minus 1-sigma (15.865th percentile) dhdt_84p = nanpctile(dhdt_dist,84.135,dim=2) # Plus 1-sigma (84.135th percentile) # Other confidence intervals (10:10:50) dhdt_20p = nanpctile(dhdt_dist,20,dim=2) dhdt_80p = nanpctile(dhdt_dist,80,dim=2) dhdt_25p = nanpctile(dhdt_dist,25,dim=2) dhdt_75p = nanpctile(dhdt_dist,75,dim=2) dhdt_30p = nanpctile(dhdt_dist,30,dim=2) dhdt_70p = nanpctile(dhdt_dist,70,dim=2) dhdt_35p = nanpctile(dhdt_dist,35,dim=2) dhdt_65p = nanpctile(dhdt_dist,65,dim=2) dhdt_40p = nanpctile(dhdt_dist,40,dim=2) dhdt_60p = nanpctile(dhdt_dist,60,dim=2) dhdt_45p = nanpctile(dhdt_dist,45,dim=2) dhdt_55p = nanpctile(dhdt_dist,55,dim=2) # Plot results hdl = plot(bincenters,dhdt, label="Mean", color=:black, linewidth=2) plot!(hdl,[bincenters; reverse(bincenters)],[dhdt_16p; reverse(dhdt_84p)], fill=(minimum(mdl.Height),0.2,:darkblue), linealpha=0, label="68% CI") plot!(hdl,[bincenters; reverse(bincenters)],[dhdt_20p; reverse(dhdt_80p)], fill=(minimum(mdl.Height),0.2,:darkblue), linealpha=0, label="") plot!(hdl,[bincenters; reverse(bincenters)],[dhdt_25p; reverse(dhdt_75p)], fill=(minimum(mdl.Height),0.2,:darkblue), linealpha=0, label="") plot!(hdl,[bincenters; reverse(bincenters)],[dhdt_30p; reverse(dhdt_70p)], fill=(minimum(mdl.Height),0.2,:darkblue), linealpha=0, label="") plot!(hdl,[bincenters; reverse(bincenters)],[dhdt_35p; reverse(dhdt_65p)], fill=(minimum(mdl.Height),0.2,:darkblue), linealpha=0, label="") plot!(hdl,[bincenters; reverse(bincenters)],[dhdt_40p; reverse(dhdt_60p)], fill=(minimum(mdl.Height),0.2,:darkblue), linealpha=0, label="") plot!(hdl,[bincenters; reverse(bincenters)],[dhdt_45p; reverse(dhdt_55p)], fill=(minimum(mdl.Height),0.2,:darkblue), linealpha=0, label="") plot!(hdl,bincenters,dhdt_50p, label="Median", color=:grey, linewidth=1) plot!(hdl, xlabel="Age ($(smpl.Age_Unit))", ylabel="Depositional Rate ($(smpl.Height_Unit) / $(smpl.Age_Unit) over $binwidth $(smpl.Age_Unit))", fg_color_legend=:white) savefig(hdl,smpl.Path*"DepositionRateModelCI.svg") savefig(hdl,smpl.Path*"DepositionRateModelCI.pdf") display(hdl) ;ls MyData # Make gzipped tar archive of the the whole MyData directory run(`tar -zcf archive.tar.gz ./MyData`); # Download prebuilt ffsend linux binary download("https://github.com/timvisee/ffsend/releases/download/v0.2.65/ffsend-v0.2.65-linux-x64-static", "ffsend") # Make ffsend executable run(`chmod +x ffsend`); ; ./ffsend upload archive.tar.gz # Data about hiatuses nHiatuses = 2 # The number of hiatuses you have data for hiatus = NewHiatusData(nHiatuses) # Struct to hold data hiatus.Height = [20.0, 35.0 ] hiatus.Height_sigma = [ 0.0, 0.0 ] hiatus.Duration = [ 0.2, 0.43] hiatus.Duration_sigma = [ 0.05, 0.07] # Run the model. Note the new `hiatus` argument and `hiatusdist` result (mdl, agedist, hiatusdist, lldist) = StratMetropolisDist(smpl, hiatus, config); sleep(0.5) # Plot results (mean and 95% confidence interval for both model and data) hdl = plot([mdl.Age_025CI; reverse(mdl.Age_975CI)],[mdl.Height; reverse(mdl.Height)], fill=(minimum(mdl.Height),0.5,:blue), label="model") plot!(hdl, mdl.Age, mdl.Height, linecolor=:blue, label="", fg_color_legend=:white) plot!(hdl, smpl.Age, smpl.Height, xerror=(smpl.Age-smpl.Age_025CI,smpl.Age_975CI-smpl.Age),label="data",seriestype=:scatter,color=:black) plot!(hdl, xlabel="Age ($(smpl.Age_Unit))", ylabel="Height ($(smpl.Height_Unit))")