This Jupyter notebook demonstrates the Chron.jl
Julia package for integrated Bayesian Pb-loss-aware eruption age and stratigraphic age-depth modelling, based in part on the work of Keller, Schoene, and Samperton (2018), with age-depth modelling capabilities extended for use in Schoene et al. (2019), Deino et al. (2019a) and Deino et al. (2019b). For more information, see github.com/brenhinkeller/Chron.jl and and doi.org/10.17605/osf.io/TQX3F
If running this notebook as an online Binder notebook and the webpage times out, click the badge at left to relaunch (refreshing will not work). Note that any changes will be lost!
Hint: shift
-enter
to run a single cell, or from the Cell
menu select Run All
to run the whole file. Any code from this notebook can be copied and pasted into the Julia REPL or a .jl
script.
# Load (and install if necessary) the Chron.jl package
using Chron
using Plots, DelimitedFiles
First, let's enter some basic information about your samples. How many are there, what are the sample names (needs to be a valid filename, BTW), and what are the stratigraphic heights and uncertainties? Then, we'll enter the ages as .csv files.
nSamples = 3 # The number of samples you have data for
smpl = ChronAgeData(nSamples)
smpl.Name = ("KR18-04", "KR18-01", "KR18-05")
smpl.Height .= [ 0.0, 100.0, 200.0] # Arbitrary example heights
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?
smpl.inputSigmaLevel = 1 # 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 = "m" # Unit of measurement for Height and Height_sigma
"m"
Note that smpl.Height must increase with increasing stratigraphic height -- i.e., stratigraphically younger samples must be more positive. For this reason, it is convenient to represent depths below surface as negative numbers.
Now let's see what's in our current directory (we'll use ;
to activate Julia's command-line shell mode, followed by a unix command, in this case ls
;ls
Chron1.0Coupled.ipynb Chron1.0Coupled.jl Chron1.0CoupledConcordia.ipynb Chron1.0CoupledConcordia.jl Chron1.0CoupledSystematic.jl Chron1.0DistOnly.ipynb Chron1.0DistOnly.jl Chron1.0Radiocarbon.ipynb Chron1.0Radiocarbon.jl Chron1.0StratOnly.ipynb Chron1.0StratOnly.jl ConcordiaExampleData DenverUPbExampleData EruptionDepositionAgeDemonstration.ipynb EruptionDepositionAgeDemonstration.jl FCT Manifest.toml MyData PlutonEmplacement.ipynb Project.toml archive.tar.gz ffsend
Equivalently, we can also run unix commands using the run()
function, i.e.,
run(`ls`);
Now that we know how to access the command line, let's make a new folder for our example data. This can be called whatever you want, just make sure it matches smpl.Path
above
;mkdir -p MyData/
Now, let's make some files and paste in csv data for each one. For now, I'm pasting in example data from MacLennan et al. (2020), 10.1126/sciadv.aay6647
# You can just paste your data in here, in the following five-column format:
# ²⁰⁷Pb/²³⁵U, ²⁰⁷Pb/²³⁵U sigma, ²⁰⁶Pb/²³⁸U, ²⁰⁶Pb/²³⁸U sigma, correlation
# You should generally exclude all systematic uncertainties here, and all uncertainties
# (sigma) must be absolute uncertainties
data = [
1.1002 0.00060511 0.123908 0.00001982528 0.333
1.1003 0.0005226425 0.123893 0.000020442345 0.421
1.1 0.0011 0.123874 0.00002353606 0.281
1.1002 0.00060511 0.123845 0.000025388225 0.418
1.1007 0.0005338395 0.123833 0.000025385765 0.534
1.0991 0.001154055 0.123797 0.000031568235 0.298
1.09931 0.0004067447 0.123762 0.00003898503 0.709
1.09947 0.0004617774 0.123752 0.00002598792 0.579
1.0986 0.00093381 0.123738 0.00003650271 0.288
1.09883 0.00047799105 0.123735 0.0000222723 0.506
1.09904 0.000384664 0.123733 0.000021653275 0.404
1.0758 0.0005379 0.121175 0.00002302325 0.427
]
# Now, let's write this data to a file, delimited by commas (',')
# In this example the filename is KR18-01.csv, in the folder called MyData
writedlm("MyData/KR18-01.csv", data, ',')
data = [
1.1009 0.000935765 0.123906 0.00002849838 0.319
1.1003 0.00077021 0.123901 0.000035311785 0.415
1.0995 0.000494775 0.123829 0.000025384945 0.434
1.0992 0.00060456 0.123813 0.000036524835 0.616
1.1006 0.00071539 0.123813 0.00002228634 0.321
1.0998 0.00076986 0.123802 0.00002537941 0.418
1.0992 0.00065952 0.123764 0.00003589156 0.509
1.0981 0.0010981 0.123727 0.00003959264 0.232
1.0973 0.000526704 0.123612 0.00002966688 0.47
1.0985 0.0008788 0.123588 0.00002842524 0.341
1.0936 0.0005468 0.123193 0.000032646145 0.575
1.0814 0.000513665 0.121838 0.0000304595 0.587
]
writedlm("MyData/KR18-04.csv",data,',')
data = [
1.09741 0.00038958055 0.123676 0.00002226168 0.601
1.097 0.00060335 0.123629 0.000024107655 0.575
1.0967 0.00054835 0.123618 0.0000247236 0.41
1.0952 0.00120472 0.123594 0.00003151647 0.366
1.0969 0.000712985 0.123553 0.000035212605 0.581
1.0956 0.0005478 0.123547 0.000032739955 0.562
1.0958 0.00071227 0.123546 0.00002779785 0.489
1.09621 0.00046588925 0.123539 0.000033973225 0.75
1.09612 0.0004822928 0.123533 0.000032736245 0.747
1.0969 0.00076783 0.123505 0.0000419917 0.552
1.0958 0.00060269 0.123469 0.00002345911 0.342
1.09517 0.00037783365 0.123447 0.000030244515 0.783
1.0948 0.000525504 0.123352 0.00003885588 0.737
1.09413 0.0003720042 0.123288 0.00002527404 0.508
1.09321 0.00046461425 0.123179 0.00003202654 0.69
1.08592 0.0004017904 0.122429 0.00002938296 0.634
]
writedlm("MyData/KR18-05.csv",data,',')
Alternatively, you could download .csv files that you have posted somewhere online using the Julia download()
function, or using the unix command curl
throught the command-line interface
For each sample in smpl.Name
, we must have a .csv
file in smpl.Path
which contains each individual mineral age and uncertainty.
To learn more about the eruption/deposition age estimation model, see also Keller, Schoene, and Samperton (2018) and for the Pb-loss-aware version we are using in this notebook, Isoplot.jl
# Bootstrap a KDE of the pre-eruptive (or pre-deposition) zircon distribution
# shape from individual sample datafiles using a KDE of stacked upper intercepts
# for each sample given an estimated time of Pb-loss
BootstrappedDistribution = BootstrapCrystDistributionKDE(smpl, tpbloss=0)
h = plot(range(0,1,length=length(BootstrappedDistribution)), BootstrappedDistribution,
label="Bootstrapped distribution", xlabel="Time (arbitrary units)", ylabel="Probability Density",
fg_color_legend=:white, framestyle=:box)
savefig(h, joinpath(smpl.Path,"BootstrappedDistribution.pdf"))
display(h)
┌ Info: Interpreting the five columns of KR18-04.csv as: └ | ²⁰⁷Pb/²³⁵U | 1-sigma 𝑎𝑏𝑠𝑜𝑙𝑢𝑡𝑒 | ²⁰⁶Pb/²³⁸U | 1-sigma 𝑎𝑏𝑠𝑜𝑙𝑢𝑡𝑒 | correlation coefficient | ┌ Info: Interpreting the five columns of KR18-01.csv as: └ | ²⁰⁷Pb/²³⁵U | 1-sigma 𝑎𝑏𝑠𝑜𝑙𝑢𝑡𝑒 | ²⁰⁶Pb/²³⁸U | 1-sigma 𝑎𝑏𝑠𝑜𝑙𝑢𝑡𝑒 | correlation coefficient | ┌ Info: Interpreting the five columns of KR18-05.csv as: └ | ²⁰⁷Pb/²³⁵U | 1-sigma 𝑎𝑏𝑠𝑜𝑙𝑢𝑡𝑒 | ²⁰⁶Pb/²³⁸U | 1-sigma 𝑎𝑏𝑠𝑜𝑙𝑢𝑡𝑒 | correlation coefficient |
# Number of steps to run in distribution MCMC
distSteps = 10^6
distBurnin = distSteps÷100
# Choose the form of the prior closure/crystallization distribution to use
dist = HalfNormalDistribution
## You might alternatively consider:
# dist = BootstrappedDistribution
# dist = UniformDistribution # A reasonable default
# dist = MeltsVolcanicZirconDistribution # A single magmatic pulse, truncated by eruption
# 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(joinpath(smpl.Path, "results.csv"), results, ',');
[ Info: Estimating eruption/deposition age distributions... ┌ Info: 1: KR18-04 │ Interpreting the five columns of KR18-04.csv as: └ | ²⁰⁷Pb/²³⁵U | 1-sigma 𝑎𝑏𝑠𝑜𝑙𝑢𝑡𝑒 | ²⁰⁶Pb/²³⁸U | 1-sigma 𝑎𝑏𝑠𝑜𝑙𝑢𝑡𝑒 | correlation coefficient | ┌ Info: 2: KR18-01 │ Interpreting the five columns of KR18-01.csv as: └ | ²⁰⁷Pb/²³⁵U | 1-sigma 𝑎𝑏𝑠𝑜𝑙𝑢𝑡𝑒 | ²⁰⁶Pb/²³⁸U | 1-sigma 𝑎𝑏𝑠𝑜𝑙𝑢𝑡𝑒 | correlation coefficient | ┌ Info: 3: KR18-05 │ Interpreting the five columns of KR18-05.csv as: └ | ²⁰⁷Pb/²³⁵U | 1-sigma 𝑎𝑏𝑠𝑜𝑙𝑢𝑡𝑒 | ²⁰⁶Pb/²³⁸U | 1-sigma 𝑎𝑏𝑠𝑜𝑙𝑢𝑡𝑒 | correlation coefficient |
# Let's see what that did
run(`ls $(smpl.Path)`);
results = readdlm(joinpath(smpl.Path, "results.csv"),',')
AgeDepthModel.pdf AgeDepthModel.svg BootstrappedDistribution.pdf DepositionRateModelCI.pdf DepositionRateModelCI.svg KJ04-70.csv KJ04-70_distribution.pdf KJ04-70_distribution.svg KJ04-70_rankorder.pdf KJ04-70_rankorder.svg KJ04-72.csv KJ04-72_distribution.pdf KJ04-72_distribution.svg KJ04-72_rankorder.pdf KJ04-72_rankorder.svg KJ04-75.csv KJ04-75_distribution.pdf KJ04-75_distribution.svg KJ04-75_rankorder.pdf KJ04-75_rankorder.svg KJ08-157.csv KJ08-157_distribution.pdf KJ08-157_distribution.svg KJ08-157_rankorder.pdf KJ08-157_rankorder.svg KJ09-66.csv KJ09-66_distribution.pdf KJ09-66_distribution.svg KJ09-66_rankorder.pdf KJ09-66_rankorder.svg KR18-01.csv KR18-01_Concordia.pdf KR18-01_Concordia.svg KR18-01_Pbloss.pdf KR18-01_Pbloss.svg KR18-01_distribution.pdf KR18-01_distribution.svg KR18-04.csv KR18-04_Concordia.pdf KR18-04_Concordia.svg KR18-04_Pbloss.pdf KR18-04_Pbloss.svg KR18-04_distribution.pdf KR18-04_distribution.svg KR18-05.csv KR18-05_Concordia.pdf KR18-05_Concordia.svg KR18-05_Pbloss.pdf KR18-05_Pbloss.svg KR18-05_distribution.pdf KR18-05_distribution.svg agedist.csv distresults.csv height.csv lldist.csv results.csv
4×5 Matrix{Any}: "Sample" "Age" "2.5% CI" "97.5% CI" "sigma" "KR18-04" 751.96 751.274 752.449 0.304138 "KR18-01" 752.126 751.698 752.494 0.200616 "KR18-05" 750.723 750.381 750.964 0.148518
To see what one of these plots looks like, try pasting this into a markdown cell like the one below
<img src="MyData/KR18-01_Concordia.svg" align="left" width="600"/>
For each sample, the eruption/deposition age distribution is inherently asymmetric, because of the one-sided relationship between mineral closure and eruption/deposition. For example (KJ04-70):
(if no figure appears, double-click to enter this markdown cell and re-evaluate (shift
-enter
) after running the model above
Consequently, rather than simply taking a mean and standard deviation of the stationary distribtuion of the Markov Chain, the histogram of the stationary distribution is fit to an empirical distribution function of the form
$ \begin{align} f(x) = a * \exp\left[d e \frac{x - b}{c}\left(\frac{1}{2} - \frac{\arctan\left(\frac{x - b}{c}\right)}{\pi}\right) - \frac{d}{e}\frac{x - b}{c}\left(\frac{1}{2} + \frac{\arctan\left(\frac{x - b}{c}\right)}{\pi}\right)\right] \end{align} $
where
$ \begin{align} \{a,c,d,e\} \geq 0 \end{align} $
i.e., an asymmetric exponential function with two log-linear segments joined with an arctangent sigmoid. After fitting, the five parameters $a$ - $e$ are stored in smpl.params
and passed to the stratigraphic model
To run the stratigraphic MCMC model, we call the StratMetropolisDist
function. If you want to skip the first step and simply input run the stratigraphic model with Gaussian mean age and standard deviation for some number of stratigraphic horizons, then you can set smpl.Age
and smpl.Age_sigma
directly, but then you'll need to call StratMetropolis
instead of StratMetropolisDist
# Configure the stratigraphic Monte Carlo model
config = StratAgeModelConfiguration()
# If you in doubt, you can probably leave these parameters as-is
config.resolution = 10.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), framestyle=:box)
[ Info: Generating stratigraphic age-depth model... [ Info: Burn-in: 840000 steps Burn-in... 100%|█████████████████████████████████████████| Time: 0:00:00 [ Info: Collecting sieved stationary distribution: 1260000 steps Collecting... 100%|██████████████████████████████████████| Time: 0:00:00
The most important output of this process is agedist
, which contains the full stationary distribution of the age-depth model. We can save it to a file, but if this notebook is running remotely, you may have trouble getting it out of here (see section Getting your data out)!
writedlm(joinpath(smpl.Path,"agedist.csv"), agedist, ',') # Stationary distribution of the age-depth model
writedlm(joinpath(smpl.Path,"height.csv"), mdl.Height, ',') # Stratigraphic heights corresponding to each row of agedist
writedlm(joinpath(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))", framestyle=:box)
savefig(hdl,joinpath(smpl.Path,"AgeDepthModel.svg"))
savefig(hdl,joinpath(smpl.Path,"AgeDepthModel.pdf"))
display(hdl)
# Interpolate results at a given height
height = 50
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)
Interpolated age: 752.0700313718455 +0.3446157426226364/-0.34727421019431404 Ma
There are other things we can plot as well, such as deposition rate:
# 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(dhdt_16p),0.2,:darkblue), linealpha=0, label="68% CI")
plot!(hdl,[bincenters; reverse(bincenters)],[dhdt_20p; reverse(dhdt_80p)], fill=(minimum(dhdt_20p),0.2,:darkblue), linealpha=0, label="")
plot!(hdl,[bincenters; reverse(bincenters)],[dhdt_25p; reverse(dhdt_75p)], fill=(minimum(dhdt_25p),0.2,:darkblue), linealpha=0, label="")
plot!(hdl,[bincenters; reverse(bincenters)],[dhdt_30p; reverse(dhdt_70p)], fill=(minimum(dhdt_30p),0.2,:darkblue), linealpha=0, label="")
plot!(hdl,[bincenters; reverse(bincenters)],[dhdt_35p; reverse(dhdt_65p)], fill=(minimum(dhdt_35p),0.2,:darkblue), linealpha=0, label="")
plot!(hdl,[bincenters; reverse(bincenters)],[dhdt_40p; reverse(dhdt_60p)], fill=(minimum(dhdt_40p),0.2,:darkblue), linealpha=0, label="")
plot!(hdl,[bincenters; reverse(bincenters)],[dhdt_45p; reverse(dhdt_55p)], fill=(minimum(dhdt_45p),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, framestyle=:box)
savefig(hdl,joinpath(smpl.Path,"DepositionRateModelCI.svg"))
savefig(hdl,joinpath(smpl.Path,"DepositionRateModelCI.pdf"))
display(hdl)
0.522807 seconds (1.71 M allocations: 234.527 MiB, 9.51% gc time, 73.11% compilation time)
As before, we can use the unix command ls
to see all the files we have written. Actually getting them out of here may be harder though.
;ls MyData
AgeDepthModel.pdf AgeDepthModel.svg BootstrappedDistribution.pdf DepositionRateModelCI.pdf DepositionRateModelCI.svg KJ04-70.csv KJ04-70_distribution.pdf KJ04-70_distribution.svg KJ04-70_rankorder.pdf KJ04-70_rankorder.svg KJ04-72.csv KJ04-72_distribution.pdf KJ04-72_distribution.svg KJ04-72_rankorder.pdf KJ04-72_rankorder.svg KJ04-75.csv KJ04-75_distribution.pdf KJ04-75_distribution.svg KJ04-75_rankorder.pdf KJ04-75_rankorder.svg KJ08-157.csv KJ08-157_distribution.pdf KJ08-157_distribution.svg KJ08-157_rankorder.pdf KJ08-157_rankorder.svg KJ09-66.csv KJ09-66_distribution.pdf KJ09-66_distribution.svg KJ09-66_rankorder.pdf KJ09-66_rankorder.svg KR18-01.csv KR18-01_Concordia.pdf KR18-01_Concordia.svg KR18-01_Pbloss.pdf KR18-01_Pbloss.svg KR18-01_distribution.pdf KR18-01_distribution.svg KR18-04.csv KR18-04_Concordia.pdf KR18-04_Concordia.svg KR18-04_Pbloss.pdf KR18-04_Pbloss.svg KR18-04_distribution.pdf KR18-04_distribution.svg KR18-05.csv KR18-05_Concordia.pdf KR18-05_Concordia.svg KR18-05_Pbloss.pdf KR18-05_Pbloss.svg KR18-05_distribution.pdf KR18-05_distribution.svg agedist.csv distresults.csv height.csv lldist.csv results.csv
We could use the trick we learned before to view the SVG files in markdown cells, which you should then be able to right click and download as real vector graphics. e.g. pasting something like
<img src="AgeDepthModel.svg" align="left" width="600"/>
in a markdown cell such as this one
Meanwhile, for the csv files we could try something like ; cat agedist.csv
, but agedist is probably too big to print. Let's try using ffsend instead, which should give you a download link. In fact, while we're at it, we might as well archive and zip the entire directory!
# Make gzipped tar archive of the the whole MyData directory
run(`tar -zcf archive.tar.gz ./MyData`);
# Download prebuilt ffsend linux binary
isfile("ffsend") || 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
/bin/bash: ./ffsend: cannot execute binary file
You could alternatively use the ffsend command in this way to transfer individual files, for instance ; ./ffsend upload MyData/agedist.csv
Keep in mind that, if running online, any changes you make to this notebook won't persist after you close the tab (or after it times out) even if you save your changes! You have to either copy-paste or file
>Download as
a copy.