Applying age models#

In this scenario, the challenge is to apply an age model to a new selection of depths. This situation may occur when sampling a core.

from pathlib import Path
import pandas as pd
import plotly
import plotly.graph_objects as go
import paleos.agemodel as pam
import paleos.common as pcm

Begin by defining the location of our age model data and the selection of depths for which to calculate ages.

data_path = Path("data")
age_model_path = data_path / "667.csv"
depths_path = data_path / "depth_667.csv"

if not age_model_path.exists():
    raise FileExistsError(f"Unable to find age model {age_model_path}")
if not data_path.exists():
    raise FileExistsError(f"Unable to find data file {data_path}")

Next, read in the age model, remove NaNs and provide column names

age_model_df = pd.read_csv(age_model_path, header=None)
age_model_df = age_model_df.dropna()
age_model_df.columns = ["depth", "age"]
print(age_model_df)

Out:

     depth     age
0     6.75   0.440
1    23.15   1.600
2    23.16   1.930
3    25.90   2.155
4    33.00   2.390
5    36.05   2.490
6    41.10   2.800
7    42.10   3.130
8    49.20   3.540
9    51.90   3.700
10   77.05   5.120
11   82.40   5.350
12   84.65   5.590
13  101.05   6.080
14  107.55   7.420
15  119.15   8.120
16  129.55   9.830
17  157.80  13.270
18  158.10  13.280
19  160.60  13.530
20  166.40  14.910
21  207.85  17.710
22  211.50  17.950
23  237.25  19.030
24  254.10  22.820
25  293.20  24.430
26  347.75  26.840
27  370.40  29.620

Set the index to depth, and create a pandas Series by explicitly taking the age column

Out:

depth
6.75       0.440
23.15      1.600
23.16      1.930
25.90      2.155
33.00      2.390
36.05      2.490
41.10      2.800
42.10      3.130
49.20      3.540
51.90      3.700
77.05      5.120
82.40      5.350
84.65      5.590
101.05     6.080
107.55     7.420
119.15     8.120
129.55     9.830
157.80    13.270
158.10    13.280
160.60    13.530
166.40    14.910
207.85    17.710
211.50    17.950
237.25    19.030
254.10    22.820
293.20    24.430
347.75    26.840
370.40    29.620
Name: age, dtype: float64

Add a (0,0) origin point and remove any duplicated depths

age_model = pam.add_point(age_model, depth=0, age=0, sort_result=True)
age_model = pcm.average_duplicated(age_model)
print(age_model)

Out:

0.00       0.000
6.75       0.440
23.15      1.600
23.16      1.930
25.90      2.155
33.00      2.390
36.05      2.490
41.10      2.800
42.10      3.130
49.20      3.540
51.90      3.700
77.05      5.120
82.40      5.350
84.65      5.590
101.05     6.080
107.55     7.420
119.15     8.120
129.55     9.830
157.80    13.270
158.10    13.280
160.60    13.530
166.40    14.910
207.85    17.710
211.50    17.950
237.25    19.030
254.10    22.820
293.20    24.430
347.75    26.840
370.40    29.620
dtype: float64

The next step is to get the depths to calculate ages for

new_depths = pd.read_csv(depths_path, header=None).squeeze("columns")
print(new_depths)

Out:

0       0.00
1      11.20
2      39.70
3      68.21
4      90.20
5      96.70
6     102.70
7     109.20
8     112.20
9     115.70
10    121.70
11    128.20
12    131.20
13    134.70
14    139.20
15    142.31
16    144.20
17    147.20
18    150.20
19    153.70
20    156.70
21    158.20
22    161.20
23    163.20
24    164.70
25    166.20
26    169.20
27    174.68
28    177.68
29    182.20
30    188.20
31    196.20
32    199.20
33    202.88
34    208.50
35    210.70
36    213.70
37    214.92
38    220.20
39    223.20
40    224.70
41    229.69
42    231.20
43    233.70
44    239.20
45    240.70
46    243.70
47    248.70
48    251.70
49    258.20
50    264.20
Name: 0, dtype: float64

Now we have both the age model and the depths we want to apply it to, we can do the application using linear resampling from paleos. In this example, linear resampling on to depths is used but there are other options.

Out:

depth
0.00       0.000000
11.20      0.754756
39.70      2.714059
68.21      4.620883
90.20      5.755823
96.70      5.950030
102.70     6.420154
109.20     7.519569
112.20     7.700603
115.70     7.911810
121.70     8.539279
128.20     9.608029
131.20    10.030920
134.70    10.457115
139.20    11.005080
142.31    11.383784
144.20    11.613929
147.20    11.979239
150.20    12.344549
153.70    12.770743
156.70    13.136053
158.20    13.290000
161.20    13.672759
163.20    14.148621
164.70    14.505517
166.20    14.862414
169.20    15.099144
174.68    15.469324
177.68    15.671978
182.20    15.977310
188.20    16.382618
196.20    16.923028
199.20    17.125682
202.88    17.374270
208.50    17.752740
210.70    17.897397
213.70    18.042272
214.92    18.093441
220.20    18.314893
223.20    18.440718
224.70    18.503631
229.69    18.712920
231.20    18.776252
233.70    18.881107
239.20    19.468605
240.70    19.805994
243.70    20.480772
248.70    21.605401
251.70    22.280178
258.20    22.988824
264.20    23.235882
Name: age, dtype: float64

Finally plot the original age model and the interpolated values on the new depths

fig = go.Figure()
fig.add_trace(
    go.Scatter(
        x=age_model.values,
        y=age_model.index,
        mode="lines+markers",
        marker=dict(color="red", symbol="circle", size=10),
        name="age model",
    )
)
fig.add_trace(
    go.Scatter(
        x=new_depth_age.values,
        y=new_depth_age.index,
        mode="markers",
        marker=dict(color="blue", symbol="x"),
        name="depth with age model",
    )
)
fig.update_layout(
    title_text=f"{data_path.stem} with age model {age_model_path.stem}",
    height=800,
    yaxis_title="Depth (m)",
    xaxis_title="Age (Ma)",
)
fig.update_yaxes(autorange="reversed")
plotly.io.show(fig)

Total running time of the script: ( 0 minutes 0.241 seconds)

Gallery generated by Sphinx-Gallery