anta-database 0.3.4__tar.gz → 0.3.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {anta_database-0.3.4 → anta_database-0.3.5}/PKG-INFO +1 -1
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/database/database.py +10 -1
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/plotting/plotting.py +25 -29
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database.egg-info/PKG-INFO +1 -1
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database.egg-info/SOURCES.txt +1 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/book/_toc.yml +1 -0
- anta_database-0.3.5/book/pism_example.ipynb +299 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/book/quick_start.ipynb +72 -58
- {anta_database-0.3.4 → anta_database-0.3.5}/.github/workflows/deploy.yml +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/.github/workflows/release.yml +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/.gitignore +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/LICENSE +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/README.md +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/ROADMAP.md +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/__init__.py +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/anta_database.py +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/compiling/__init__.py +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/compiling/compile.py +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/compiling/reconnect.py +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/data/ANT_Basins_IMBIE2_v1.6.cpg +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/data/ANT_Basins_IMBIE2_v1.6.dbf +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/data/ANT_Basins_IMBIE2_v1.6.prj +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/data/ANT_Basins_IMBIE2_v1.6.shp +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/data/ANT_Basins_IMBIE2_v1.6.shx +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/data/GL.pkl +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/data/centeroid_coords_basins.cpg +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/data/centeroid_coords_basins.dbf +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/data/centeroid_coords_basins.prj +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/data/centeroid_coords_basins.shp +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/data/centeroid_coords_basins.shx +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/data/site-coords.pkl +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/database/__init__.py +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/figures/AntA_38ka.png +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/indexing/__init__.py +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/indexing/index_database.py +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database/plotting/__init__.py +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database.egg-info/dependency_links.txt +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database.egg-info/requires.txt +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/anta_database.egg-info/top_level.txt +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/book/_config.yml +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/book/advanced.md +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/book/contact.md +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/book/contribute.md +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/book/figures/Overview_all.png +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/book/intro.md +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/book/logo.png +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/book/references.bib +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/book/requirements.txt +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/pyproject.toml +0 -0
- {anta_database-0.3.4 → anta_database-0.3.5}/setup.cfg +0 -0
|
@@ -717,6 +717,7 @@ class Database:
|
|
|
717
717
|
data_dir: Optional[str] = None,
|
|
718
718
|
downsampling_factor: Optional[str] = None,
|
|
719
719
|
disable_tqdm: bool = False,
|
|
720
|
+
fraction_depth: Optional[bool] = False,
|
|
720
721
|
) -> Generator[Tuple[pd.DataFrame, Dict]]:
|
|
721
722
|
"""
|
|
722
723
|
Generates xarray Datasets from HDF5 files, one at a time, with lazy loading.
|
|
@@ -770,13 +771,21 @@ class Database:
|
|
|
770
771
|
irh_index = irh_index[0]
|
|
771
772
|
age_impl.append(age)
|
|
772
773
|
|
|
773
|
-
df[
|
|
774
|
+
df[age] = ds[var][::downsampling_factor, irh_index]
|
|
775
|
+
if fraction_depth:
|
|
776
|
+
if 'ICE_THK' in ds.keys():
|
|
777
|
+
df[age] *= 100/ds['ICE_THK'][::downsampling_factor]
|
|
778
|
+
else:
|
|
779
|
+
df[age] = np.nan
|
|
780
|
+
# print(f'WARNING: flight line {file_md['flight_id']} in {file_md['dataset']} does not have ICE_THK, cannot compute fraction depth, will return NaN')
|
|
774
781
|
|
|
775
782
|
else:
|
|
776
783
|
if var in ds.keys():
|
|
777
784
|
var_impl.append(var)
|
|
778
785
|
df[var] = ds[var][::downsampling_factor]
|
|
779
786
|
|
|
787
|
+
if 0 < len(age_impl) <= 1:
|
|
788
|
+
age_impl = list(age_impl)[0]
|
|
780
789
|
metadata = {
|
|
781
790
|
'dataset': file_md['dataset'],
|
|
782
791
|
'var': var_impl,
|
|
@@ -177,6 +177,7 @@ class Plotting:
|
|
|
177
177
|
self,
|
|
178
178
|
metadata: Union[None, Dict, 'MetadataResult'] = None,
|
|
179
179
|
downsampling_factor: Optional[int] = None,
|
|
180
|
+
fraction_depth: Optional[bool] = False,
|
|
180
181
|
title: Optional[str] = None,
|
|
181
182
|
xlim: Optional[tuple] = (None, None),
|
|
182
183
|
ylim: Optional[tuple] = (None, None),
|
|
@@ -197,6 +198,7 @@ class Plotting:
|
|
|
197
198
|
color_by='var',
|
|
198
199
|
metadata=metadata,
|
|
199
200
|
downsampling_factor=downsampling_factor,
|
|
201
|
+
fraction_depth=fraction_depth,
|
|
200
202
|
title=title,
|
|
201
203
|
xlim=xlim,
|
|
202
204
|
ylim=ylim,
|
|
@@ -261,6 +263,7 @@ class Plotting:
|
|
|
261
263
|
self,
|
|
262
264
|
metadata: Union[None, Dict, 'MetadataResult'] = None,
|
|
263
265
|
elevation: Optional[bool] = False,
|
|
266
|
+
fraction_depth: Optional[bool] = False,
|
|
264
267
|
downsampling_factor: Optional[int] = None,
|
|
265
268
|
title: Optional[str] = None,
|
|
266
269
|
xlim: Optional[tuple] = (None, None),
|
|
@@ -402,9 +405,8 @@ class Plotting:
|
|
|
402
405
|
else:
|
|
403
406
|
var = var[0]
|
|
404
407
|
|
|
405
|
-
|
|
406
408
|
all_dfs = []
|
|
407
|
-
for ds, _ in tqdm(self._db.data_generator(metadata, downsampling_factor=downsampling_factor, disable_tqdm=True), desc="Plotting", total=total_traces, unit='trace', disable=self._disable_tqdm):
|
|
409
|
+
for ds, _ in tqdm(self._db.data_generator(metadata, downsampling_factor=downsampling_factor, disable_tqdm=True, fraction_depth=fraction_depth), desc="Plotting", total=total_traces, unit='trace', disable=self._disable_tqdm):
|
|
408
410
|
all_dfs.append(ds)
|
|
409
411
|
df = pd.concat(all_dfs)
|
|
410
412
|
|
|
@@ -478,37 +480,31 @@ class Plotting:
|
|
|
478
480
|
title = f'AntADatabase Basal Unit'
|
|
479
481
|
scatter = plt.scatter(df['PSX']/1000, df['PSY']/1000, c=df[var], cmap=cmap, s=marker_size, vmin=vmin, vmax=vmax, linewidths=0, rasterized=True)
|
|
480
482
|
|
|
481
|
-
elif var in ['IRH_DEPTH'
|
|
482
|
-
if
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
483
|
+
elif var in ['IRH_DEPTH']:
|
|
484
|
+
if cmap == None:
|
|
485
|
+
cmap = cmaps.torch_r
|
|
486
|
+
extend = 'both'
|
|
487
|
+
age = list(metadata['age'])
|
|
488
|
+
if not title:
|
|
489
|
+
if fraction_depth:
|
|
490
|
+
title = f'AntADatabase IRH Fraction Depth'
|
|
491
|
+
else:
|
|
489
492
|
title = f'AntADatabase IRH Depth'
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
if cmap == None:
|
|
498
|
-
cmap = cmaps.torch_r
|
|
499
|
-
extend = 'both'
|
|
500
|
-
age = list(metadata['age'])
|
|
501
|
-
if len(age) > 1:
|
|
502
|
-
print('WARNING: Multiple layers provided: ', age,
|
|
503
|
-
'\nSelect a unique age for better results')
|
|
504
|
-
elif len(age) == 0:
|
|
505
|
-
print('No layer provided, please provide a valid age.')
|
|
506
|
-
return
|
|
507
|
-
age = age[0]
|
|
493
|
+
if len(age) > 1:
|
|
494
|
+
print('WARNING: Multiple layers provided: ', age,
|
|
495
|
+
'\nSelect a unique age for better results')
|
|
496
|
+
elif len(age) == 0:
|
|
497
|
+
print('No layer provided, please provide a valid age.')
|
|
498
|
+
return
|
|
499
|
+
if fraction_depth:
|
|
508
500
|
label = r'IRH Fractional Depth [\%]'
|
|
501
|
+
if vmin is None: vmin = 0
|
|
502
|
+
if vmax is None: vmax = 100
|
|
503
|
+
else:
|
|
504
|
+
label = f'IRH Depth [m]'
|
|
509
505
|
|
|
510
506
|
for age in metadata['age']:
|
|
511
|
-
scatter = plt.scatter(df['PSX']/1000, df['PSY']/1000, c=df[
|
|
507
|
+
scatter = plt.scatter(df['PSX']/1000, df['PSY']/1000, c=df[age], cmap=cmap, s=marker_size, vmin=vmin, vmax=vmax, linewidths=0, rasterized=True)
|
|
512
508
|
|
|
513
509
|
if color_by == 'transect_1D':
|
|
514
510
|
flight_id = list(metadata['flight_id'])
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"id": "356c8b16",
|
|
6
|
+
"metadata": {},
|
|
7
|
+
"source": [
|
|
8
|
+
"# Model-data comparison (ex: PISM)\n",
|
|
9
|
+
"Example using the Parallel Ice Sheet Model\n",
|
|
10
|
+
"\n",
|
|
11
|
+
"PISM includes an englacial layer tracing scheme [(Born and Robinson 2021)](https://doi.org/10.5194/tc-15-4539-2021) since its version 2.1 [(PISM docs)](https://www.pism.io/docs/manual/modeling-choices/dynamics/age.html)\n",
|
|
12
|
+
"\n",
|
|
13
|
+
"This notebook shows how to make direct use of the AntADatabase and the anta_database module for comparing a model run with PISM and IRH data. It is not meant to be very efficient, but descriptive, and people should be able to take parts of the code to implement it in there diagnostic routines."
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"cell_type": "markdown",
|
|
18
|
+
"id": "e050b262",
|
|
19
|
+
"metadata": {},
|
|
20
|
+
"source": [
|
|
21
|
+
"# 2D Layer mismatch"
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"cell_type": "markdown",
|
|
26
|
+
"id": "516011f7",
|
|
27
|
+
"metadata": {},
|
|
28
|
+
"source": [
|
|
29
|
+
"## PISM output\n",
|
|
30
|
+
"\n",
|
|
31
|
+
"This example is using output from a regional domain setup around Dome C, East Antarctica. Layers were traced to match the Cavitte et al. 2020 dataset.\n",
|
|
32
|
+
"Note that PISM time is in second since year 0, while the dated IRHs are in years before 1950. So one has to be careful with the time reference between the dated IRH and the model time.\n",
|
|
33
|
+
"PISM outputs the 'isochronal_layer_thickness' variable, which needs to be converted to isochronal depth. Then we select the layer of interest. \n",
|
|
34
|
+
"Here is with xarray, but one can use netCDF4:"
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"cell_type": "code",
|
|
39
|
+
"execution_count": null,
|
|
40
|
+
"id": "aaaef681",
|
|
41
|
+
"metadata": {},
|
|
42
|
+
"outputs": [],
|
|
43
|
+
"source": [
|
|
44
|
+
"import xarray as xr\n",
|
|
45
|
+
"import numpy as np\n",
|
|
46
|
+
"\n",
|
|
47
|
+
"pism_out = xr.open_dataset('/home/anthe/documents/data/isochrones/pism_output_example/edc_pism_output.nc', engine='netcdf4', decode_times=False).squeeze()\n",
|
|
48
|
+
"pism_out['isochronal_layer_depth'] = pism_out['isochronal_layer_thickness'].copy() # creating a new variable for layer depths of same shape of layer thicknesses\n",
|
|
49
|
+
"\n",
|
|
50
|
+
"for i in range(pism_out.deposition_time.size):\n",
|
|
51
|
+
" pism_out['isochronal_layer_depth'][:,:,i] = pism_out.isochronal_layer_thickness.isel(deposition_time=slice(i, None)).sum(dim='deposition_time').values\n",
|
|
52
|
+
"\n",
|
|
53
|
+
"age = 38000 # note the age is different from the one used in Cavitte et al. 2020 due to different ice core age scale, please ignore\n",
|
|
54
|
+
"age_offset = -1950 # to account for difference between model time and age scale used for IRHs, the isochrones were seeded at age+1950, and the simulation ran until year 1950.\n",
|
|
55
|
+
"age_seconds = -(age+age_offset)*3600*24*365\n",
|
|
56
|
+
"pism_layer = pism_out.isochronal_layer_depth.sel(deposition_time=age_seconds).values.flatten()\n",
|
|
57
|
+
"X_pism, Y_pism = np.meshgrid(pism_out.x, pism_out.y)\n",
|
|
58
|
+
"pism_points = np.column_stack((X_pism.flatten(), Y_pism.flatten()))"
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"cell_type": "markdown",
|
|
63
|
+
"id": "d4ec0831",
|
|
64
|
+
"metadata": {},
|
|
65
|
+
"source": [
|
|
66
|
+
"## Query the AntADatabase\n",
|
|
67
|
+
"\n",
|
|
68
|
+
"One can query the Database and fetch the files containing the data to compare with:"
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"cell_type": "code",
|
|
73
|
+
"execution_count": null,
|
|
74
|
+
"id": "8fc030f2",
|
|
75
|
+
"metadata": {},
|
|
76
|
+
"outputs": [],
|
|
77
|
+
"source": [
|
|
78
|
+
"from anta_database import Database\n",
|
|
79
|
+
"\n",
|
|
80
|
+
"db = Database('/home/anthe/documents/data/isochrones/AntADatabase/')\n",
|
|
81
|
+
"db.filter_out(flight_id=['%RAID%', '2H%', '2V%', 'HR%', 'BH%', 'H4%'])\n",
|
|
82
|
+
"query = db.query(dataset='Cavitte_2020', age='38100') # compare with 38.1 ka layer\n",
|
|
83
|
+
"\n",
|
|
84
|
+
"irh_files = db.get_files()"
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"cell_type": "markdown",
|
|
89
|
+
"id": "851e80e6",
|
|
90
|
+
"metadata": {},
|
|
91
|
+
"source": [
|
|
92
|
+
"## Interpolate PISM\n",
|
|
93
|
+
"\n",
|
|
94
|
+
"Next we loop through the IRH flight line files, interpolate the PISM isochronal layer depth on each flight line coordinates and compute the difference in depth. We concatenate the results in a DataFrame for plotting. Here we show both with xarray, which is provides a convenient interface with the data, and with h5py, which is much faster:"
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"cell_type": "markdown",
|
|
99
|
+
"id": "f23c5879",
|
|
100
|
+
"metadata": {},
|
|
101
|
+
"source": [
|
|
102
|
+
"### xarray"
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"cell_type": "code",
|
|
107
|
+
"execution_count": null,
|
|
108
|
+
"id": "5a4db052",
|
|
109
|
+
"metadata": {},
|
|
110
|
+
"outputs": [],
|
|
111
|
+
"source": [
|
|
112
|
+
"from scipy.interpolate import griddata\n",
|
|
113
|
+
"import pandas as pd\n",
|
|
114
|
+
"\n",
|
|
115
|
+
"all_psx = []\n",
|
|
116
|
+
"all_psy = []\n",
|
|
117
|
+
"all_depth_diff = []\n",
|
|
118
|
+
"\n",
|
|
119
|
+
"for f in irh_files:\n",
|
|
120
|
+
" irh = xr.open_dataset(f, engine='h5netcdf')\n",
|
|
121
|
+
" for age in query['age']:\n",
|
|
122
|
+
" irh_layer = irh.IRH_DEPTH.sel(IRH_AGE=int(age))\n",
|
|
123
|
+
" fl_line_xy = np.column_stack((irh.PSX, irh.PSY))\n",
|
|
124
|
+
" pism_depth_interp = griddata(pism_points, pism_layer, fl_line_xy, method='linear')\n",
|
|
125
|
+
" depth_diff = pism_depth_interp - irh_layer\n",
|
|
126
|
+
"\n",
|
|
127
|
+
" all_psx.extend(irh.PSX.values)\n",
|
|
128
|
+
" all_psy.extend(irh.PSY.values)\n",
|
|
129
|
+
" all_depth_diff.extend(depth_diff)"
|
|
130
|
+
]
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"cell_type": "markdown",
|
|
134
|
+
"id": "92f4ea4c",
|
|
135
|
+
"metadata": {},
|
|
136
|
+
"source": [
|
|
137
|
+
"### h5py"
|
|
138
|
+
]
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"cell_type": "code",
|
|
142
|
+
"execution_count": null,
|
|
143
|
+
"id": "1001994c",
|
|
144
|
+
"metadata": {},
|
|
145
|
+
"outputs": [],
|
|
146
|
+
"source": [
|
|
147
|
+
"import h5py\n",
|
|
148
|
+
"\n",
|
|
149
|
+
"all_psx = []\n",
|
|
150
|
+
"all_psy = []\n",
|
|
151
|
+
"all_depth_diff = []\n",
|
|
152
|
+
"\n",
|
|
153
|
+
"for f in irh_files:\n",
|
|
154
|
+
" with h5py.File(f, 'r') as irh:\n",
|
|
155
|
+
" irh_values = irh['IRH_AGE'][:]\n",
|
|
156
|
+
" for age in query['age']:\n",
|
|
157
|
+
" irh_index = np.where(irh_values == int(age))[0]\n",
|
|
158
|
+
" irh_index = irh_index[0]\n",
|
|
159
|
+
" irh_layer = irh['IRH_DEPTH'][:, irh_index]\n",
|
|
160
|
+
"\n",
|
|
161
|
+
" fl_line_xy = np.column_stack((irh['PSX'][:], irh['PSY'][:]))\n",
|
|
162
|
+
" pism_depth_interp = griddata(pism_points, pism_layer, fl_line_xy, method='linear')\n",
|
|
163
|
+
" depth_diff = pism_depth_interp - irh_layer\n",
|
|
164
|
+
"\n",
|
|
165
|
+
" all_psx.extend(irh['PSX'][:])\n",
|
|
166
|
+
" all_psy.extend(irh['PSY'][:])\n",
|
|
167
|
+
" all_depth_diff.extend(depth_diff)"
|
|
168
|
+
]
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"cell_type": "markdown",
|
|
172
|
+
"id": "d384310a",
|
|
173
|
+
"metadata": {},
|
|
174
|
+
"source": [
|
|
175
|
+
"## Plotting"
|
|
176
|
+
]
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"cell_type": "code",
|
|
180
|
+
"execution_count": null,
|
|
181
|
+
"id": "2850b8a0",
|
|
182
|
+
"metadata": {},
|
|
183
|
+
"outputs": [],
|
|
184
|
+
"source": [
|
|
185
|
+
"import matplotlib.pyplot as plt\n",
|
|
186
|
+
"\n",
|
|
187
|
+
"# Create DataFrame\n",
|
|
188
|
+
"df = pd.DataFrame({\n",
|
|
189
|
+
" 'PSX': all_psx,\n",
|
|
190
|
+
" 'PSY': all_psy,\n",
|
|
191
|
+
" 'Depth_diff': all_depth_diff\n",
|
|
192
|
+
"})\n",
|
|
193
|
+
"\n",
|
|
194
|
+
"plt.figure(figsize=(10, 6))\n",
|
|
195
|
+
"sc = plt.scatter(\n",
|
|
196
|
+
" df['PSX']/1000,\n",
|
|
197
|
+
" df['PSY']/1000,\n",
|
|
198
|
+
" c=df['Depth_diff'],\n",
|
|
199
|
+
" cmap='RdBu_r',\n",
|
|
200
|
+
" s=1,\n",
|
|
201
|
+
" vmin=-100,\n",
|
|
202
|
+
" vmax=100\n",
|
|
203
|
+
")\n",
|
|
204
|
+
"plt.colorbar(sc, label='Iso Depth Difference (m)', extend='both')\n",
|
|
205
|
+
"plt.title('PISM vs Cavitte et al. 2020 Isochronal Depth Difference at 38.1 ka')\n",
|
|
206
|
+
"plt.xlabel('PSX [km]')\n",
|
|
207
|
+
"plt.ylabel('PSY [km]')\n",
|
|
208
|
+
"plt.show()"
|
|
209
|
+
]
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"cell_type": "markdown",
|
|
213
|
+
"id": "0fc0b7f0",
|
|
214
|
+
"metadata": {},
|
|
215
|
+
"source": [
|
|
216
|
+
"# 1D Transect mismatch \n",
|
|
217
|
+
"\n",
|
|
218
|
+
"It is also useful to simply plot the absolute isochronal layer depth in both PISM and the dataset as well as respective bed resolutions.\n",
|
|
219
|
+
"First we select a specific transect:"
|
|
220
|
+
]
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"cell_type": "code",
|
|
224
|
+
"execution_count": null,
|
|
225
|
+
"id": "c5129bb3",
|
|
226
|
+
"metadata": {},
|
|
227
|
+
"outputs": [],
|
|
228
|
+
"source": [
|
|
229
|
+
"db.query(dataset='Cavitte_2020', flight_id='DC_LDC_DIVIDE')\n",
|
|
230
|
+
"\n",
|
|
231
|
+
"f = db.get_files()[0] \n",
|
|
232
|
+
"irh = xr.open_dataset(f, engine='h5netcdf')"
|
|
233
|
+
]
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
"cell_type": "markdown",
|
|
237
|
+
"id": "6c3cc5de",
|
|
238
|
+
"metadata": {},
|
|
239
|
+
"source": [
|
|
240
|
+
"We select a few layers we want to plot for comparison (one can plot everything, but here there is a lot)"
|
|
241
|
+
]
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"cell_type": "code",
|
|
245
|
+
"execution_count": null,
|
|
246
|
+
"id": "c64d8111",
|
|
247
|
+
"metadata": {},
|
|
248
|
+
"outputs": [],
|
|
249
|
+
"source": [
|
|
250
|
+
"cavitte_ages = [10000, 29400, 38100, 46400, 73400, 96500, 121100, 166400, 277900]\n",
|
|
251
|
+
"irh_layers = irh.sel(IRH_AGE=cavitte_ages)\n",
|
|
252
|
+
"fl_line_xy = np.column_stack((irh.PSX, irh.PSY))\n",
|
|
253
|
+
"\n",
|
|
254
|
+
"pism_ages = [10000, 29300, 38000, 46600, 73100, 97400, 122800, 165200, 278000] # PISM ages differ slightly since I used a different ice core chronology for the dating than in the original Cavitte et al. 2020 paper\n",
|
|
255
|
+
"\n",
|
|
256
|
+
"plt.plot(irh.Distance/1000, irh_layers.IRH_DEPTH, label=irh_layers.IRH_AGE.values)\n",
|
|
257
|
+
"plt.plot(irh.Distance/1000, irh_layers.ICE_THK, color='gray', label='Bed Depth')\n",
|
|
258
|
+
"\n",
|
|
259
|
+
"for age in pism_ages:\n",
|
|
260
|
+
" age = -(age+age_offset)*(3600*24*365)\n",
|
|
261
|
+
" pism_layer = pism_out.isochronal_layer_depth.sel(deposition_time=age).values.flatten()\n",
|
|
262
|
+
" pism_depth_interp = griddata(pism_points, pism_layer, fl_line_xy, method='linear')\n",
|
|
263
|
+
" plt.plot(irh.Distance/1000, pism_depth_interp, linestyle='--', color='k')\n",
|
|
264
|
+
"plt.plot(0,0, color='black', linestyle='--', label='PISM Isochronal Layers') \n",
|
|
265
|
+
"\n",
|
|
266
|
+
"pism_bed_depth_interp = griddata(pism_points, pism_out.thk.values.flatten(), fl_line_xy, method='linear')\n",
|
|
267
|
+
"plt.plot(irh.Distance/1000, pism_bed_depth_interp, color='gray', linestyle='--', label='PISM Bed Depth') \n",
|
|
268
|
+
"\n",
|
|
269
|
+
"plt.ylim(3500, 0)\n",
|
|
270
|
+
"plt.xlabel('Distance along flight line [km]')\n",
|
|
271
|
+
"plt.ylabel('Isochronal Layer Depth [m]')\n",
|
|
272
|
+
"plt.title('Isochronal Layer Depth Comparison along Transect')\n",
|
|
273
|
+
"plt.legend(title='Cavitte et al. 2020 Ages [yr BP]', bbox_to_anchor=(1.05, 1), loc='upper left')\n",
|
|
274
|
+
"plt.show()"
|
|
275
|
+
]
|
|
276
|
+
}
|
|
277
|
+
],
|
|
278
|
+
"metadata": {
|
|
279
|
+
"kernelspec": {
|
|
280
|
+
"display_name": "processing",
|
|
281
|
+
"language": "python",
|
|
282
|
+
"name": "python3"
|
|
283
|
+
},
|
|
284
|
+
"language_info": {
|
|
285
|
+
"codemirror_mode": {
|
|
286
|
+
"name": "ipython",
|
|
287
|
+
"version": 3
|
|
288
|
+
},
|
|
289
|
+
"file_extension": ".py",
|
|
290
|
+
"mimetype": "text/x-python",
|
|
291
|
+
"name": "python",
|
|
292
|
+
"nbconvert_exporter": "python",
|
|
293
|
+
"pygments_lexer": "ipython3",
|
|
294
|
+
"version": "3.13.2"
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
"nbformat": 4,
|
|
298
|
+
"nbformat_minor": 5
|
|
299
|
+
}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"source": [
|
|
24
24
|
"\n",
|
|
25
|
-
"This Python module is designed to query and visualized data in a AntADatabase folder. The latter
|
|
25
|
+
"This Python module is designed to query and visualized data in a AntADatabase folder. The latter is not published yet, but you can contact me for access.\n",
|
|
26
26
|
"You can already have a look at this guide to have an idea of the features of this tool. This Jupyter Notebook can be directly downloaded (top bar) and ran locally (assuming you had downloaded or compiled the AntADatabase folder).\n"
|
|
27
27
|
]
|
|
28
28
|
},
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"id": "867679c7",
|
|
54
54
|
"metadata": {},
|
|
55
55
|
"source": [
|
|
56
|
-
"Use the query() function to browse the database. 'query()' without argument will return all metadata
|
|
56
|
+
"Use the query() function to browse the database. 'query()' without argument will return all the metadata from the database:"
|
|
57
57
|
]
|
|
58
58
|
},
|
|
59
59
|
{
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"- age: age(s) in yrs before present of the layer(s) of interest\n",
|
|
80
80
|
"- region: region(s) of interest. E.g.: 'EAIS', 'WAIS'\n",
|
|
81
81
|
"- IMBIE_basin: IMBIE basin(s) of interest. E.g.: 'G-H', 'Ap-B'.\n",
|
|
82
|
-
"- var: variables(s) of interest. Possible variables currently are: 'IRH_DEPTH', '
|
|
82
|
+
"- var: variables(s) of interest. Possible variables currently are: 'IRH_DEPTH', 'IRH_NUM', 'ICE_THK', 'BED_ELEV', 'SURF_ELEV'\n",
|
|
83
83
|
"- flight_id: ID of a particular flight line. This is useful for explicit flight IDs such as 'DC_LDC_DIVIDE'\n",
|
|
84
84
|
"\n",
|
|
85
85
|
"One can also combine field queries as well as providing lists. Use '%' for searching by regular expressions. Here are a few examples:"
|
|
@@ -94,8 +94,10 @@
|
|
|
94
94
|
"source": [
|
|
95
95
|
"#Examples of queries:\n",
|
|
96
96
|
"db.query(dataset='Cavitte_2020') # all data from Cavitte et al. 2020\n",
|
|
97
|
+
"db.query(institute='BAS') # all data that was acquired by BAS\n",
|
|
98
|
+
"db.query(project='OIB') # all data that was acquired during OIB campaigns\n",
|
|
97
99
|
"db.query(age='38100') # all datasets with the 38.1ka isochrone\n",
|
|
98
|
-
"db.query(var='ICE_THK') # all datasets with
|
|
100
|
+
"db.query(var='ICE_THK') # all datasets with ICE_THK variable\n",
|
|
99
101
|
"db.query(IMBIE_basin='G-H') # all flight lines that cross the G-H basin\n",
|
|
100
102
|
"db.query(flight_id='DC_LDC_DIVIDE') # all layers with the flight ID DC_LDC_DIVIDE\n",
|
|
101
103
|
"db.query(flight_id='%WSB%') # all flight lines with WSB in the flight ID\n",
|
|
@@ -141,9 +143,9 @@
|
|
|
141
143
|
"metadata": {},
|
|
142
144
|
"source": [
|
|
143
145
|
"Current implemented plotting functions are:\n",
|
|
144
|
-
"- plot.dataset(): plots locations of the data, with different colors for the different datasets
|
|
146
|
+
"- plot.dataset(): plots locations of the data, with different colors for the different datasets\n",
|
|
145
147
|
"- plot.institute(): plots locations of the data, with different colors for the different institutes\n",
|
|
146
|
-
"- plot.var(): color-coded scatter plot of the variable of
|
|
148
|
+
"- plot.var(): color-coded scatter plot of the variable of interest.\n",
|
|
147
149
|
"- plot.flight_id(): color-coded trace IDs. Useful for identifying specific traces of interest.\n",
|
|
148
150
|
"- plot.transect_1D(): plots depths of the IRH and Bed along a single flight line \n",
|
|
149
151
|
"\n",
|
|
@@ -166,6 +168,8 @@
|
|
|
166
168
|
"metadata": {},
|
|
167
169
|
"outputs": [],
|
|
168
170
|
"source": [
|
|
171
|
+
"# %matplotlib widget\n",
|
|
172
|
+
"%matplotlib inline\n",
|
|
169
173
|
"results = db.query(IMBIE_basin='G-H')\n",
|
|
170
174
|
"db.plot.dataset(results,\n",
|
|
171
175
|
" title='IRH data crossing the G-H IMBIE basin',\n",
|
|
@@ -188,7 +192,8 @@
|
|
|
188
192
|
"id": "e735309e",
|
|
189
193
|
"metadata": {},
|
|
190
194
|
"source": [
|
|
191
|
-
"### Plot variables"
|
|
195
|
+
"### Plot variables\n",
|
|
196
|
+
"Example of plotting the IRH depth of a specific layer found across multiple datasets. Here we still select multiple ages close from each other, which could be attributed to the same layer (but different dating method used maybe). Note the warning in the case, but we can ignore it:"
|
|
192
197
|
]
|
|
193
198
|
},
|
|
194
199
|
{
|
|
@@ -199,11 +204,39 @@
|
|
|
199
204
|
"lines_to_next_cell": 2
|
|
200
205
|
},
|
|
201
206
|
"outputs": [],
|
|
207
|
+
"source": [
|
|
208
|
+
"results = db.query(age=['37600', '38000', '38100', '38200', '38500'], var='IRH_DEPTH')\n",
|
|
209
|
+
"db.plot.var(results, title='AntArchitecture 38ka isochrone depth',\n",
|
|
210
|
+
" downsampling_factor=10, # downscale the datasets n times, which makes little visual difference but lighter to plot\n",
|
|
211
|
+
" xlim=(-500, 2400),\n",
|
|
212
|
+
" ylim=(-2200, 2200),\n",
|
|
213
|
+
" scale_factor=0.7, # adjust the size of the plot \n",
|
|
214
|
+
" marker_size=1.2,\n",
|
|
215
|
+
" # save='AntA_38ka_depth.png'\n",
|
|
216
|
+
" )"
|
|
217
|
+
]
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"cell_type": "markdown",
|
|
221
|
+
"id": "e5ada192",
|
|
222
|
+
"metadata": {},
|
|
223
|
+
"source": [
|
|
224
|
+
"The above plot shows the absolute IRH depth relative to the ice surface as it is traced. It is often more informative to look at the IRH fraction depth: the depth of a layer relative to the ice thickness (IRH_DEPTH/ICE_THK*100). The fraction depth variable is not directly stored in the database to reduce disk usage. It is probably more efficient to compute it when needed. For this, use the option fraction_depth=True:"
|
|
225
|
+
]
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
"cell_type": "code",
|
|
229
|
+
"execution_count": null,
|
|
230
|
+
"id": "f29343c3",
|
|
231
|
+
"metadata": {},
|
|
232
|
+
"outputs": [],
|
|
202
233
|
"source": [
|
|
203
234
|
"# %matplotlib widget\n",
|
|
204
235
|
"%matplotlib inline\n",
|
|
205
236
|
"results = db.query(age=['37600', '38000', '38100', '38200', '38500'], var='IRH_DEPTH')\n",
|
|
206
|
-
"db.plot.var(results,
|
|
237
|
+
"db.plot.var(results, \n",
|
|
238
|
+
" fraction_depth=True,\n",
|
|
239
|
+
" title='AntArchitecture 38ka isochrone fractional depth',\n",
|
|
207
240
|
" downsampling_factor=10, # downscale the datasets n times, which makes little visual difference but lighter to plot\n",
|
|
208
241
|
" xlim=(-500, 2400),\n",
|
|
209
242
|
" ylim=(-2200, 2200),\n",
|
|
@@ -213,6 +246,24 @@
|
|
|
213
246
|
" )"
|
|
214
247
|
]
|
|
215
248
|
},
|
|
249
|
+
{
|
|
250
|
+
"cell_type": "markdown",
|
|
251
|
+
"id": "16b53478",
|
|
252
|
+
"metadata": {},
|
|
253
|
+
"source": [
|
|
254
|
+
"Note that if the variable ICE_THK is not present in a dataset, the fractional depth cannot be computed. In the case, NaN values will be generated instead without warning. So if you get a blank plot, please check if the dataset you queried contains the ICE_THK with db.query(dataset='Author_YYYY')."
|
|
255
|
+
]
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"cell_type": "markdown",
|
|
259
|
+
"id": "ee330fa6",
|
|
260
|
+
"metadata": {},
|
|
261
|
+
"source": [
|
|
262
|
+
"### Plot datasets\n",
|
|
263
|
+
"\n",
|
|
264
|
+
"The IRH_NUM variable shows the number of traced isochrones (layers) per data point:"
|
|
265
|
+
]
|
|
266
|
+
},
|
|
216
267
|
{
|
|
217
268
|
"cell_type": "code",
|
|
218
269
|
"execution_count": null,
|
|
@@ -233,7 +284,9 @@
|
|
|
233
284
|
"id": "9185b390",
|
|
234
285
|
"metadata": {},
|
|
235
286
|
"source": [
|
|
236
|
-
"### Plot flight IDs"
|
|
287
|
+
"### Plot flight IDs\n",
|
|
288
|
+
"\n",
|
|
289
|
+
"This plot is useful when we want to identify a specific flight line. One can then identify a flight line of interest on the 2D map, then plot the traced IRHs along the transect (see below):"
|
|
237
290
|
]
|
|
238
291
|
},
|
|
239
292
|
{
|
|
@@ -380,7 +433,7 @@
|
|
|
380
433
|
"source": [
|
|
381
434
|
"## Generate data from the database\n",
|
|
382
435
|
"\n",
|
|
383
|
-
"Note: This part could be developed further in the future if there is the need. But for now, I am designing a separate Python module for constraining my ice sheet model of use, which is tailored to this database and other parallel processing libraries.\n",
|
|
436
|
+
"Note: This part could be developed further in the future if there is the need. But for now, I am designing a separate Python module for constraining my ice sheet model of use, which is tailored to this database and other parallel processing libraries. However, the [Model-comparison](https://antoinehermant.github.io/anta_database/pism_example.html) section already give some bits of code about it.\n",
|
|
384
437
|
"\n",
|
|
385
438
|
"The data_generator() function reads the query and 'yield' the dataframes for later use. It uses h5py to read all the data efficiently, and creates pandas dataframes, including all the variables and ages from the query. Columns for IRH DEPTH are named after the age. Basically, it reads the data with h5py as shown above and restructure it as bit, which can be easier to manage layers than with h5py dimensions.\n",
|
|
386
439
|
"Here is a quick example of how this can be used for computing the mean layer depth:"
|
|
@@ -401,63 +454,24 @@
|
|
|
401
454
|
"min_depth = float('inf')\n",
|
|
402
455
|
"max_depth = float('-inf')\n",
|
|
403
456
|
"for df, md in lazy_dfs:\n",
|
|
404
|
-
" depth_values = df[
|
|
405
|
-
" mean_depth_trs.append(np.
|
|
406
|
-
" min_depth = min(min_depth,
|
|
407
|
-
" max_depth = max(max_depth,
|
|
457
|
+
" depth_values = df[md['age']].values\n",
|
|
458
|
+
" mean_depth_trs.append(np.nanmean(depth_values))\n",
|
|
459
|
+
" min_depth = min(min_depth, np.nanmin(depth_values))\n",
|
|
460
|
+
" max_depth = max(max_depth, np.nanmax(depth_values))\n",
|
|
408
461
|
"\n",
|
|
409
462
|
"\n",
|
|
410
|
-
"mean_depth = np.
|
|
411
|
-
"std_dev = np.
|
|
463
|
+
"mean_depth = np.nanmean(mean_depth_trs)\n",
|
|
464
|
+
"std_dev = np.nanstd(mean_depth_trs, ddof=1)\n",
|
|
412
465
|
"print(f\"The mean depth of the 38ka isochrone across East Antarctica is {round(mean_depth, 2)} m ranging from {round(min_depth, 2)} m to {round(max_depth, 2)} m.\")"
|
|
413
466
|
]
|
|
414
467
|
},
|
|
415
468
|
{
|
|
416
469
|
"cell_type": "markdown",
|
|
417
|
-
"id": "
|
|
470
|
+
"id": "04e0f078",
|
|
418
471
|
"metadata": {},
|
|
419
472
|
"source": [
|
|
420
|
-
"
|
|
421
|
-
|
|
422
|
-
},
|
|
423
|
-
{
|
|
424
|
-
"cell_type": "markdown",
|
|
425
|
-
"id": "1051a179",
|
|
426
|
-
"metadata": {},
|
|
427
|
-
"source": [
|
|
428
|
-
"### Downscale the data\n",
|
|
429
|
-
"\n",
|
|
430
|
-
"The downsampling_factor argument in the data_generator reduces the size of the generated data by n times. This is useful when dealing with large data where the downscaling has a neglectable influence on the results.\n",
|
|
431
|
-
"Another solution, probably more straightforward, is the downsample_distance option, which allows to provide a distance in meters by which the data should be average along the transects:"
|
|
432
|
-
]
|
|
433
|
-
},
|
|
434
|
-
{
|
|
435
|
-
"cell_type": "code",
|
|
436
|
-
"execution_count": null,
|
|
437
|
-
"id": "11bbf439",
|
|
438
|
-
"metadata": {},
|
|
439
|
-
"outputs": [],
|
|
440
|
-
"source": [
|
|
441
|
-
"import matplotlib.pyplot as plt\n",
|
|
442
|
-
"\n",
|
|
443
|
-
"results = db.query(dataset='Cavitte_2020', age='277900', flight_id='DC_LDC_DIVIDE')\n",
|
|
444
|
-
"original = db.data_generator(results)\n",
|
|
445
|
-
"downscale_10 = db.data_generator(results, downsampling_factor=100)\n",
|
|
446
|
-
"# downsampled_by_distance = db.data_generator(results, downsample_distance=5000)\n",
|
|
447
|
-
"\n",
|
|
448
|
-
"list = [original, downscale_10] #, downsampled_by_distance]\n",
|
|
449
|
-
"labels = ['original', 'downscale 100'] #, 'downsample 5km']\n",
|
|
450
|
-
"\n",
|
|
451
|
-
"for i, lazy_dfs in enumerate(list):\n",
|
|
452
|
-
" for df, md in lazy_dfs:\n",
|
|
453
|
-
" plt.plot(df.Distance, df[277900],label=labels[i], linestyle='--')\n",
|
|
454
|
-
"\n",
|
|
455
|
-
"plt.ylim(2600, 1800)\n",
|
|
456
|
-
"plt.xlabel('Distance along DC_LDC_DIVIDE (km)')\n",
|
|
457
|
-
"plt.ylabel('Depth (m)')\n",
|
|
458
|
-
"plt.legend()\n",
|
|
459
|
-
"plt.title('Different downscaling methods for Cavitte 2020 278ka along DC_LDC_DIVIDE')\n",
|
|
460
|
-
"plt.show()"
|
|
473
|
+
"Note that the data_generator returns a simple pandas DataFrame for each flight line, containing all queried variables and ages (if exist). The IRH depth of each layer is stored by columns named by age (so the IRH_DEPTH of the layer 38000 is df['38000']). As shown above, one can use the metadata (md) of the current dataframe (df) to get its age (md['age']).\n",
|
|
474
|
+
"Furthermore, if one needs the fraction depth, one can compute it using the ICE_THK (has to be included in the query), or the data_generator has this option: db.data_generator(results, fraction_depth=True). With this option, the layer columns will now be IRH fraction depth instead of absolute IRH_DEPTH."
|
|
461
475
|
]
|
|
462
476
|
},
|
|
463
477
|
{
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|