anta-database 0.3.1__tar.gz → 0.3.3__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.
Files changed (49) hide show
  1. {anta_database-0.3.1 → anta_database-0.3.3}/PKG-INFO +2 -1
  2. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/compiling/compile.py +5 -3
  3. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/compiling/reconnect.py +1 -1
  4. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/database/database.py +24 -17
  5. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/indexing/index_database.py +24 -11
  6. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/plotting/plotting.py +167 -90
  7. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database.egg-info/PKG-INFO +2 -1
  8. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database.egg-info/requires.txt +1 -0
  9. {anta_database-0.3.1 → anta_database-0.3.3}/pyproject.toml +1 -0
  10. {anta_database-0.3.1 → anta_database-0.3.3}/.github/workflows/deploy.yml +0 -0
  11. {anta_database-0.3.1 → anta_database-0.3.3}/.github/workflows/release.yml +0 -0
  12. {anta_database-0.3.1 → anta_database-0.3.3}/.gitignore +0 -0
  13. {anta_database-0.3.1 → anta_database-0.3.3}/LICENSE +0 -0
  14. {anta_database-0.3.1 → anta_database-0.3.3}/README.md +0 -0
  15. {anta_database-0.3.1 → anta_database-0.3.3}/ROADMAP.md +0 -0
  16. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/__init__.py +0 -0
  17. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/anta_database.py +0 -0
  18. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/compiling/__init__.py +0 -0
  19. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/data/ANT_Basins_IMBIE2_v1.6.cpg +0 -0
  20. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/data/ANT_Basins_IMBIE2_v1.6.dbf +0 -0
  21. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/data/ANT_Basins_IMBIE2_v1.6.prj +0 -0
  22. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/data/ANT_Basins_IMBIE2_v1.6.shp +0 -0
  23. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/data/ANT_Basins_IMBIE2_v1.6.shx +0 -0
  24. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/data/GL.pkl +0 -0
  25. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/data/centeroid_coords_basins.cpg +0 -0
  26. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/data/centeroid_coords_basins.dbf +0 -0
  27. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/data/centeroid_coords_basins.prj +0 -0
  28. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/data/centeroid_coords_basins.shp +0 -0
  29. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/data/centeroid_coords_basins.shx +0 -0
  30. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/data/site-coords.pkl +0 -0
  31. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/database/__init__.py +0 -0
  32. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/figures/AntA_38ka.png +0 -0
  33. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/indexing/__init__.py +0 -0
  34. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database/plotting/__init__.py +0 -0
  35. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database.egg-info/SOURCES.txt +0 -0
  36. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database.egg-info/dependency_links.txt +0 -0
  37. {anta_database-0.3.1 → anta_database-0.3.3}/anta_database.egg-info/top_level.txt +0 -0
  38. {anta_database-0.3.1 → anta_database-0.3.3}/book/_config.yml +0 -0
  39. {anta_database-0.3.1 → anta_database-0.3.3}/book/_toc.yml +0 -0
  40. {anta_database-0.3.1 → anta_database-0.3.3}/book/advanced.md +0 -0
  41. {anta_database-0.3.1 → anta_database-0.3.3}/book/contact.md +0 -0
  42. {anta_database-0.3.1 → anta_database-0.3.3}/book/contribute.md +0 -0
  43. {anta_database-0.3.1 → anta_database-0.3.3}/book/figures/Overview_all.png +0 -0
  44. {anta_database-0.3.1 → anta_database-0.3.3}/book/intro.md +0 -0
  45. {anta_database-0.3.1 → anta_database-0.3.3}/book/logo.png +0 -0
  46. {anta_database-0.3.1 → anta_database-0.3.3}/book/quick_start.ipynb +0 -0
  47. {anta_database-0.3.1 → anta_database-0.3.3}/book/references.bib +0 -0
  48. {anta_database-0.3.1 → anta_database-0.3.3}/book/requirements.txt +0 -0
  49. {anta_database-0.3.1 → anta_database-0.3.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anta_database
3
- Version: 0.3.1
3
+ Version: 0.3.3
4
4
  Summary: SQLite database for the AntArchitecture Community Data
5
5
  Author: Antoine Hermant
6
6
  Author-email: antoine.hermant@etik.com
@@ -27,6 +27,7 @@ Requires-Dist: scipy
27
27
  Requires-Dist: matplotlib
28
28
  Requires-Dist: colormaps
29
29
  Requires-Dist: tqdm
30
+ Requires-Dist: pyshp
30
31
  Dynamic: license-file
31
32
 
32
33
  <h1 align="center">
@@ -863,6 +863,8 @@ class CompileDatabase:
863
863
  max_depth[i] = depth_slice[max_idx]
864
864
  age_max_depth[i] = ds.IRH_AGE.values[max_idx]
865
865
 
866
+ age_max_depth = np.abs(age_max_depth)
867
+ max_depth = np.abs(max_depth)
866
868
  flight_id = ds.attrs["flight ID"]
867
869
  acq_year = ds.attrs["acquisition year"]
868
870
  project = ds.attrs["project"]
@@ -872,10 +874,10 @@ class CompileDatabase:
872
874
  df = gpd.GeoDataFrame({
873
875
  "geometry": [Point(x, y) for x, y in zip(ds.PSX.values, ds.PSY.values)],
874
876
  "irh_num": N.astype('int16'),
875
- "max_age": age_max_depth.astype('int16'),
877
+ "max_age": age_max_depth.astype('int32'),
876
878
  "max_depth": max_depth.astype('int16'),
877
- "flight_id": [flight_id] * len(N),
878
- "doi_data": [doi_data] * len(N),
879
+ # "flight_id": [flight_id] * len(N),
880
+ # "doi_data": [doi_data] * len(N),
879
881
  }, crs="EPSG:3031")
880
882
 
881
883
  all_dfs.append(df)
@@ -43,7 +43,7 @@ class Reconnect:
43
43
 
44
44
 
45
45
  def process(self, df_connect: pd.DataFrame, tree, file_path: str):
46
- data_dir = self._db.db_dir
46
+ data_dir = self._db._db_dir
47
47
  full_path = os.path.join(data_dir, file_path)
48
48
  with h5py.File(full_path, 'a') as f:
49
49
  with xr.open_dataset(f, engine='h5netcdf') as ds:
@@ -5,6 +5,7 @@ import numpy as np
5
5
  import xarray as xr
6
6
  import h5py
7
7
  from typing import Union, List, Dict, Tuple, Optional, Generator
8
+ from tqdm import tqdm
8
9
 
9
10
  from anta_database.plotting.plotting import Plotting
10
11
 
@@ -17,6 +18,7 @@ class Database:
17
18
  self._plotting = None
18
19
  self._max_displayed_flight_ids = max_displayed_flight_ids
19
20
  self._include_BM = include_BEDMAP
21
+ self._disable_tqdm = os.getenv("JUPYTER_BOOK_BUILD", False)
20
22
  self._excluded = {
21
23
  'dataset': [],
22
24
  'institute': [],
@@ -90,11 +92,13 @@ class Database:
90
92
  LEFT JOIN
91
93
  variables v ON dv.variable_id = v.id
92
94
  LEFT JOIN
93
- dataset_ages da ON d.id = da.dataset_id
95
+ dataset_ages da ON d.id = da.dataset_id AND v.name = 'IRH_DEPTH'
94
96
  LEFT JOIN
95
97
  ages a ON da.age_id = a.id
96
98
  LEFT JOIN
97
- regions r ON da.region_id = r.id
99
+ dataset_regions dr ON d.id = dr.dataset_id
100
+ LEFT JOIN
101
+ regions r ON dr.region_id = r.id
98
102
  '''
99
103
  conditions = []
100
104
  params = []
@@ -413,21 +417,21 @@ class Database:
413
417
  Helper method to build the SQL query and parameters for filtering.
414
418
  Returns the query string and parameters list.
415
419
  """
416
- select_clause = 's.name AS dataset, \
420
+ select_clause = "s.name AS dataset, \
417
421
  s.citation, \
418
422
  s.DOI_dataset, \
419
423
  s.DOI_publication, \
420
424
  institutes_list.institutes, \
421
425
  projects_list.projects, \
422
426
  d.acq_year, \
423
- a.age, \
424
- a.age_unc, \
427
+ CASE WHEN v.name = 'IRH_DEPTH' THEN a.age ELSE NULL END AS age, \
428
+ CASE WHEN v.name = 'IRH_DEPTH' THEN a.age_unc ELSE NULL END AS age_unc, \
425
429
  v.name AS var, \
426
430
  d.flight_id, \
427
431
  r.region, \
428
432
  r.IMBIE_basin, \
429
433
  radar_instruments_list.radar_instruments \
430
- '
434
+ "
431
435
  query = f'''
432
436
  SELECT {select_clause}
433
437
  FROM
@@ -472,11 +476,13 @@ class Database:
472
476
  LEFT JOIN
473
477
  variables v ON dv.variable_id = v.id
474
478
  LEFT JOIN
475
- dataset_ages da ON d.id = da.dataset_id
479
+ dataset_ages da ON d.id = da.dataset_id AND v.name = 'IRH_DEPTH'
476
480
  LEFT JOIN
477
481
  ages a ON da.age_id = a.id
478
482
  LEFT JOIN
479
- regions r ON da.region_id = r.id
483
+ dataset_regions dr ON d.id = dr.dataset_id
484
+ LEFT JOIN
485
+ regions r ON dr.region_id = r.id
480
486
  '''
481
487
  conditions = []
482
488
  params = []
@@ -534,21 +540,21 @@ class Database:
534
540
  retain_query: Optional[bool] = True,
535
541
  ) -> 'MetadataResult':
536
542
 
537
- select_clause = 's.name AS dataset, \
543
+ select_clause = "s.name AS dataset, \
538
544
  s.citation, \
539
545
  s.DOI_dataset, \
540
546
  s.DOI_publication, \
541
547
  institutes_list.institutes, \
542
548
  projects_list.projects, \
543
549
  d.acq_year, \
544
- a.age, \
545
- a.age_unc, \
550
+ CASE WHEN v.name = 'IRH_DEPTH' THEN a.age ELSE NULL END AS age, \
551
+ CASE WHEN v.name = 'IRH_DEPTH' THEN a.age_unc ELSE NULL END AS age_unc, \
546
552
  v.name AS var, \
547
553
  d.flight_id, \
548
554
  r.region, \
549
555
  r.IMBIE_basin, \
550
556
  radar_instruments_list.radar_instruments \
551
- '
557
+ "
552
558
  query, params = self._build_query_and_params(age, var, dataset, institute, project, acquisition_year, flight_id, region, IMBIE_basin, radar_instrument, select_clause)
553
559
 
554
560
  conn = sqlite3.connect(self._file_db_path)
@@ -684,18 +690,18 @@ class Database:
684
690
 
685
691
  def get_files(
686
692
  self,
687
- metadata: Union[None, Dict, 'MetadataResult'] = None,
688
- data_dir: Union[None, str] = None,
693
+ metadata: Optional[Union[None, Dict, 'MetadataResult']] = None,
694
+ data_dir: Optional[Union[None, str]] = None,
689
695
  ):
690
696
 
691
697
  md = metadata or self._md
692
698
  if not md:
693
- print('Please provide metadata of the files you want to generate the data from. Exiting...')
699
+ print('Please provide metadata of the files you want to generate the data from.')
694
700
  return
695
701
 
696
702
  data_dir = data_dir or self._db_dir
697
703
  if not data_dir:
698
- print('No data directory provided. Exiting...')
704
+ print('No data directory provided.')
699
705
  return
700
706
 
701
707
  file_paths = self._get_file_paths_from_metadata(metadata=md)
@@ -710,6 +716,7 @@ class Database:
710
716
  metadata: Union[None, Dict, 'MetadataResult'] = None,
711
717
  data_dir: Optional[str] = None,
712
718
  downscale_factor: Optional[str] = None,
719
+ disable_tqdm: bool = False,
713
720
  ) -> Generator[Tuple[pd.DataFrame, Dict]]:
714
721
  """
715
722
  Generates xarray Datasets from HDF5 files, one at a time, with lazy loading.
@@ -737,7 +744,7 @@ class Database:
737
744
  file_paths = self._get_file_paths_from_metadata(metadata=md)
738
745
  file_paths = np.unique(file_paths) # Be carefull as many pointers point to the same file
739
746
 
740
- for file_path in file_paths:
747
+ for file_path in tqdm(file_paths, desc='Generating dataframes', total=len(file_paths), unit='file', disable=disable_tqdm):
741
748
  full_path = os.path.join(data_dir, file_path)
742
749
  file_md = self._get_file_metadata(file_path)
743
750
  ds = h5py.File(full_path, 'r')
@@ -126,11 +126,9 @@ class IndexDatabase:
126
126
  CREATE TABLE IF NOT EXISTS dataset_ages (
127
127
  dataset_id INTEGER,
128
128
  age_id INTEGER,
129
- region_id INTEGER,
130
129
  FOREIGN KEY (dataset_id) REFERENCES datasets (id),
131
130
  FOREIGN KEY (age_id) REFERENCES ages (id),
132
- FOREIGN KEY (region_id) REFERENCES regions (id),
133
- PRIMARY KEY (dataset_id, age_id, region_id)
131
+ PRIMARY KEY (dataset_id, age_id)
134
132
  )
135
133
  ''')
136
134
 
@@ -164,6 +162,16 @@ class IndexDatabase:
164
162
  )
165
163
  ''')
166
164
 
165
+ cursor.execute('''
166
+ CREATE TABLE IF NOT EXISTS dataset_regions (
167
+ dataset_id INTEGER,
168
+ region_id INTEGER,
169
+ FOREIGN KEY (dataset_id) REFERENCES datasets (id),
170
+ FOREIGN KEY (region_id) REFERENCES regions (id),
171
+ PRIMARY KEY (dataset_id, region_id)
172
+ )
173
+ ''')
174
+
167
175
  for f in tqdm(h5_files, desc="Indexing files"):
168
176
  _, file_name = os.path.split(f)
169
177
 
@@ -281,7 +289,7 @@ class IndexDatabase:
281
289
  # Insert variables
282
290
  var_list = ['ICE_THK', 'SURF_ELEV', 'BED_ELEV', 'BASAL_UNIT', 'IRH_NUM', 'IRH_DEPTH']
283
291
  for var in var_list:
284
- if var in ds_vars or var == 'IRH_DEPTH':
292
+ if var in ds_vars:
285
293
  cursor.execute('INSERT OR IGNORE INTO variables (name) VALUES (?)', (var,))
286
294
  var_id = cursor.execute('SELECT id FROM variables WHERE name = ?', (var,)).fetchone()[0]
287
295
  cursor.execute('''
@@ -294,13 +302,18 @@ class IndexDatabase:
294
302
  for age, age_unc in age_uncs.iterrows():
295
303
  cursor.execute('INSERT OR IGNORE INTO ages (age, age_unc) VALUES (?, ?)', (str(age), str(age_unc['age_unc'])))
296
304
  age_id = cursor.execute('SELECT id FROM ages WHERE age = ? AND age_unc = ?', (str(age), str(age_unc['age_unc']))).fetchone()[0]
297
- for basin, region in basin_mapping.items():
298
- cursor.execute('INSERT OR IGNORE INTO regions (region, IMBIE_basin) VALUES (?, ?)', (region, basin))
299
- region_id = cursor.execute('SELECT id FROM regions WHERE region = ? AND IMBIE_basin = ?', (region, basin)).fetchone()[0]
300
- cursor.execute('''
301
- INSERT OR IGNORE INTO dataset_ages (dataset_id, age_id, region_id)
302
- VALUES (?, ?, ?)
303
- ''', (dataset_row_id, age_id, region_id))
305
+ cursor.execute('''
306
+ INSERT OR IGNORE INTO dataset_ages (dataset_id, age_id)
307
+ VALUES (?, ?)
308
+ ''', (dataset_row_id, age_id))
309
+
310
+ for basin, region in basin_mapping.items():
311
+ cursor.execute('INSERT OR IGNORE INTO regions (region, IMBIE_basin) VALUES (?, ?)', (region, basin))
312
+ region_id = cursor.execute('SELECT id FROM regions WHERE region = ? AND IMBIE_basin = ?', (region, basin)).fetchone()[0]
313
+ cursor.execute('''
314
+ INSERT OR IGNORE INTO dataset_regions (dataset_id, region_id)
315
+ VALUES (?, ?)
316
+ ''', (dataset_row_id, region_id))
304
317
 
305
318
  conn.commit()
306
319
  conn.close()
@@ -1,10 +1,12 @@
1
1
  import os
2
2
  import h5py
3
3
  import pandas as pd
4
- import geopandas as gpd
5
4
  import numpy as np
6
5
  import matplotlib.pyplot as plt
7
6
  from matplotlib.colors import BoundaryNorm, ListedColormap, LinearSegmentedColormap
7
+ import shapefile
8
+ from matplotlib.patches import Polygon
9
+ from matplotlib.collections import PatchCollection
8
10
  from matplotlib import patheffects as path_effects
9
11
  import colormaps as cmaps
10
12
  from contextlib import contextmanager
@@ -22,6 +24,7 @@ class Plotting:
22
24
  self._site_coords_path = files('anta_database.data').joinpath('site-coords.pkl')
23
25
  self._imbie_path = files('anta_database.data').joinpath('ANT_Basins_IMBIE2_v1.6.shp')
24
26
  self._center_coords = files('anta_database.data').joinpath('centeroid_coords_basins.shp')
27
+ self._disable_tqdm = os.getenv("JUPYTER_BOOK_BUILD", False)
25
28
 
26
29
  def _pre_plot_check(self,
27
30
  metadata: Union[None, Dict, 'MetadataResult'] = None
@@ -61,11 +64,12 @@ class Plotting:
61
64
  metadata: Union[None, Dict, 'MetadataResult'] = None,
62
65
  downscale_factor: Optional[int] = None,
63
66
  title: Optional[str] = None,
64
- xlim: tuple = (None, None),
65
- ylim: tuple = (None, None),
67
+ xlim: Optional[tuple] = (None, None),
68
+ ylim: Optional[tuple] = (None, None),
69
+ vmin: Optional[float] = None,
70
+ vmax: Optional[float] = None,
66
71
  scale_factor: float = 1.0,
67
72
  marker_size: Optional[float] = 0.5,
68
- latex: bool = False,
69
73
  cmap: Optional['LinearSegmentedColormap'] = None,
70
74
  grounding_line: Optional[bool] = True,
71
75
  basins: Optional[bool] = True,
@@ -83,8 +87,9 @@ class Plotting:
83
87
  title=title,
84
88
  xlim=xlim,
85
89
  ylim=ylim,
90
+ vmin=vmin,
91
+ vmax=vmax,
86
92
  scale_factor=scale_factor,
87
- latex=latex,
88
93
  cmap=cmap,
89
94
  grounding_line=grounding_line,
90
95
  basins=basins,
@@ -97,11 +102,12 @@ class Plotting:
97
102
  metadata: Union[None, Dict, 'MetadataResult'] = None,
98
103
  downscale_factor: Optional[int] = None,
99
104
  title: Optional[str] = None,
100
- xlim: tuple = (None, None),
101
- ylim: tuple = (None, None),
105
+ xlim: Optional[tuple] = (None, None),
106
+ ylim: Optional[tuple] = (None, None),
107
+ vmin: Optional[float] = None,
108
+ vmax: Optional[float] = None,
102
109
  scale_factor: float = 1.0,
103
110
  marker_size: Optional[float] = 0.1,
104
- latex: bool = False,
105
111
  cmap: Optional['LinearSegmentedColormap'] = None,
106
112
  grounding_line: Optional[bool] = True,
107
113
  basins: Optional[bool] = True,
@@ -119,8 +125,9 @@ class Plotting:
119
125
  title=title,
120
126
  xlim=xlim,
121
127
  ylim=ylim,
128
+ vmin=vmin,
129
+ vmax=vmax,
122
130
  scale_factor=scale_factor,
123
- latex=latex,
124
131
  cmap=cmap,
125
132
  grounding_line=grounding_line,
126
133
  basins=basins,
@@ -133,11 +140,12 @@ class Plotting:
133
140
  metadata: Union[None, Dict, 'MetadataResult'] = None,
134
141
  downscale_factor: Optional[int] = None,
135
142
  title: Optional[str] = None,
136
- xlim: tuple = (None, None),
137
- ylim: tuple = (None, None),
143
+ xlim: Optional[tuple] = (None, None),
144
+ ylim: Optional[tuple] = (None, None),
145
+ vmin: Optional[float] = None,
146
+ vmax: Optional[float] = None,
138
147
  scale_factor: float = 1.0,
139
148
  marker_size: Optional[float] = 0.1,
140
- latex: bool = False,
141
149
  cmap: Optional['LinearSegmentedColormap'] = None,
142
150
  grounding_line: Optional[bool] = True,
143
151
  basins: Optional[bool] = True,
@@ -156,7 +164,8 @@ class Plotting:
156
164
  title=title,
157
165
  xlim=xlim,
158
166
  ylim=ylim,
159
- latex=latex,
167
+ vmin=vmin,
168
+ vmax=vmax,
160
169
  cmap=cmap,
161
170
  grounding_line=grounding_line,
162
171
  basins=basins,
@@ -169,11 +178,12 @@ class Plotting:
169
178
  metadata: Union[None, Dict, 'MetadataResult'] = None,
170
179
  downscale_factor: Optional[int] = None,
171
180
  title: Optional[str] = None,
172
- xlim: tuple = (None, None),
173
- ylim: tuple = (None, None),
181
+ xlim: Optional[tuple] = (None, None),
182
+ ylim: Optional[tuple] = (None, None),
183
+ vmin: Optional[float] = None,
184
+ vmax: Optional[float] = None,
174
185
  scale_factor: float = 1.0,
175
186
  marker_size: Optional[float] = 0.3,
176
- latex: bool = False,
177
187
  cmap: Optional['LinearSegmentedColormap'] = None,
178
188
  grounding_line: Optional[bool] = True,
179
189
  basins: Optional[bool] = True,
@@ -190,9 +200,10 @@ class Plotting:
190
200
  title=title,
191
201
  xlim=xlim,
192
202
  ylim=ylim,
203
+ vmin=vmin,
204
+ vmax=vmax,
193
205
  scale_factor=scale_factor,
194
206
  marker_size=marker_size,
195
- latex=latex,
196
207
  cmap=cmap,
197
208
  grounding_line=grounding_line,
198
209
  basins=basins,
@@ -200,16 +211,16 @@ class Plotting:
200
211
  save=save,
201
212
  )
202
213
 
203
- def transect(
214
+ def transect_1D(
204
215
  self,
205
216
  metadata: Union[None, Dict, 'MetadataResult'] = None,
217
+ elevation: Optional[bool] = False,
206
218
  downscale_factor: Optional[int] = None,
207
219
  title: Optional[str] = None,
208
- xlim: tuple = (None, None),
209
- ylim: tuple = (3500, 0),
220
+ xlim: Optional[tuple] = (None, None),
221
+ ylim: Optional[tuple] = (None, None),
210
222
  scale_factor: float = 1.0,
211
223
  marker_size: Optional[float] = 2,
212
- latex: bool = False,
213
224
  cmap: Optional['LinearSegmentedColormap'] = None,
214
225
  grounding_line: Optional[bool] = True,
215
226
  basins: Optional[bool] = True,
@@ -220,7 +231,8 @@ class Plotting:
220
231
  Plot the color-coded values of the given variable on Antarcitic map
221
232
  """
222
233
  self._base_plot(
223
- color_by='transect',
234
+ color_by='transect_1D',
235
+ elevation=elevation,
224
236
  metadata=metadata,
225
237
  downscale_factor=downscale_factor,
226
238
  title=title,
@@ -228,7 +240,6 @@ class Plotting:
228
240
  ylim=ylim,
229
241
  scale_factor=scale_factor,
230
242
  marker_size=marker_size,
231
- latex=latex,
232
243
  cmap=cmap,
233
244
  grounding_line=grounding_line,
234
245
  basins=basins,
@@ -247,22 +258,24 @@ class Plotting:
247
258
  plt.close()
248
259
 
249
260
  def _base_plot(
250
- self,
251
- metadata: Union[None, Dict, 'MetadataResult'] = None,
252
- downscale_factor: Optional[int] = None,
253
- title: Optional[str] = None,
254
- xlim: tuple = (None, None),
255
- ylim: tuple = (None, None),
256
- scale_factor: float = 1.0,
257
- marker_size: Optional[float] = 0.1,
258
- latex: bool = False,
259
- save: Optional[str] = None,
260
- color_by: str = 'dataset', # 'dataset', 'flight_id', 'depth', 'density'
261
- cmap: Optional['LinearSegmentedColormap'] = None,
262
- grounding_line: Optional[bool] = True,
263
- basins: Optional[bool] = True,
264
- stations: Optional[bool] = True,
265
- ncol: Optional[int] = None,
261
+ self,
262
+ metadata: Union[None, Dict, 'MetadataResult'] = None,
263
+ elevation: Optional[bool] = False,
264
+ downscale_factor: Optional[int] = None,
265
+ title: Optional[str] = None,
266
+ xlim: Optional[tuple] = (None, None),
267
+ ylim: Optional[tuple] = (None, None),
268
+ vmin: Optional[float] = None,
269
+ vmax: Optional[float] = None,
270
+ scale_factor: float = 1.0,
271
+ marker_size: Optional[float] = 0.1,
272
+ save: Optional[str] = None,
273
+ color_by: str = 'dataset', # 'dataset', 'flight_id', 'depth', 'density'
274
+ cmap: Optional['LinearSegmentedColormap'] = None,
275
+ grounding_line: Optional[bool] = True,
276
+ basins: Optional[bool] = True,
277
+ stations: Optional[bool] = True,
278
+ ncol: Optional[int] = None,
266
279
  ) -> None:
267
280
  # --- Setup ---
268
281
  if metadata is None:
@@ -274,11 +287,6 @@ class Plotting:
274
287
 
275
288
  total_traces = len(metadata['flight_id'])
276
289
 
277
- if latex:
278
- from matplotlib import rc
279
- rc('font', **{'family': 'serif', 'serif': ['Computer Modern']})
280
- rc('text', usetex=True)
281
-
282
290
  if not self._pre_plot_check(metadata):
283
291
  return
284
292
 
@@ -292,7 +300,7 @@ class Plotting:
292
300
  if basins:
293
301
  grounding_line = False
294
302
  # --- Plot Grounding Line ---
295
- if True and color_by != 'transect': # FIXME
303
+ if True and color_by != 'transect_1D': # FIXME
296
304
  gl = pd.read_pickle(self._gl_path)
297
305
  ax.plot(gl.x/1000, gl.y/1000, linewidth=1, color='k')
298
306
 
@@ -302,8 +310,6 @@ class Plotting:
302
310
  values = None
303
311
  label = None
304
312
  extend = None
305
- vmin = 0
306
- vmax = 10
307
313
 
308
314
  if color_by == 'dataset':
309
315
  if not title:
@@ -325,7 +331,7 @@ class Plotting:
325
331
  colors.update(bedmap_colors)
326
332
 
327
333
  flight_ids = metadata['flight_id']
328
- for dataset in tqdm(datasets, desc="Plotting", total=len(datasets), unit='dataset'):
334
+ for dataset in tqdm(datasets, desc="Plotting", total=len(datasets), unit='dataset', disable=self._disable_tqdm):
329
335
  metadata_impl = self._db.query(dataset=dataset, flight_id=flight_ids, retain_query=False)
330
336
  file_paths = self._db._get_file_paths_from_metadata(metadata_impl)
331
337
  file_paths = np.unique(file_paths)
@@ -363,7 +369,7 @@ class Plotting:
363
369
  colors = {dataset: cmap(i) for i, dataset in zip(color_indices, institutes)}
364
370
 
365
371
  flight_ids = metadata['flight_id']
366
- for institute in tqdm(institutes, desc="Plotting", total=len(institutes), unit='institute'):
372
+ for institute in tqdm(institutes, desc="Plotting", total=len(institutes), unit='institute', disable=self._disable_tqdm):
367
373
  metadata_impl = self._db.query(institute=institute, flight_id=flight_ids, retain_query=False)
368
374
  file_paths = self._db._get_file_paths_from_metadata(metadata_impl)
369
375
  file_paths = np.unique(file_paths)
@@ -398,7 +404,7 @@ class Plotting:
398
404
 
399
405
 
400
406
  all_dfs = []
401
- for ds, _ in tqdm(self._db.data_generator(metadata, downscale_factor=downscale_factor), desc="Plotting", total=total_traces, unit='trace'):
407
+ for ds, _ in tqdm(self._db.data_generator(metadata, downscale_factor=downscale_factor, disable_tqdm=True), desc="Plotting", total=total_traces, unit='trace', disable=self._disable_tqdm):
402
408
  all_dfs.append(ds)
403
409
  df = pd.concat(all_dfs)
404
410
 
@@ -442,43 +448,42 @@ class Plotting:
442
448
  if cmap == None:
443
449
  cmap = cmaps.bukavu
444
450
  extend = 'both'
445
- vmin = -1000
446
- vmax = 1000
451
+ if not vmin: vmin = -1000
452
+ if not vmax: vmax = 1000
447
453
  if not title:
448
454
  title = f'AntADatabase Bed Elevation'
449
455
  elif var == 'ICE_THK':
450
456
  if cmap == None:
451
457
  cmap = cmaps.torch_r
452
458
  extend = 'max'
453
- vmin = 0
454
- vmax = 4000
459
+ if not vmin: vmin = 0
460
+ if not vmax: vmax = 4000
455
461
  if not title:
456
462
  title = f'AntADatabase Ice Thickness'
457
463
  elif var == 'SURF_ELEV':
458
464
  if cmap == None:
459
465
  cmap = cmaps.torch_r
460
466
  extend = 'max'
461
- vmin = 2000
462
- vmax = 4000
467
+ if not vmin: vmin = 2000
468
+ if not vmax: vmax = 4000
463
469
  if not title:
464
470
  title = f'AntADatabase Surface Elevation'
465
471
  elif var == 'BASAL_UNIT':
466
472
  if cmap == None:
467
473
  cmap = cmaps.torch_r
468
474
  extend = 'both'
469
- vmin = 2000
470
- vmax = 4000
475
+ if not vmin: vmin = 2000
476
+ if not vmax: vmax = 400
471
477
  if not title:
472
478
  title = f'AntADatabase Basal Unit'
473
479
  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)
474
480
 
475
481
  elif var in ['IRH_DEPTH', 'IRH_FRAC_DEPTH']:
476
482
  if var == 'IRH_DEPTH':
483
+ label = f'IRH Depth [m]'
477
484
  if cmap == None:
478
485
  cmap = cmaps.torch_r
479
486
  extend = 'both'
480
- vmin = None
481
- vmax = None
482
487
  age = list(metadata['age'])
483
488
  if not title:
484
489
  title = f'AntADatabase IRH Depth'
@@ -492,8 +497,6 @@ class Plotting:
492
497
  if cmap == None:
493
498
  cmap = cmaps.torch_r
494
499
  extend = 'both'
495
- vmin = None
496
- vmax = None
497
500
  age = list(metadata['age'])
498
501
  if len(age) > 1:
499
502
  print('WARNING: Multiple layers provided: ', age,
@@ -507,7 +510,7 @@ class Plotting:
507
510
  for age in metadata['age']:
508
511
  scatter = plt.scatter(df['PSX']/1000, df['PSY']/1000, c=df[int(age)], cmap=cmap, s=marker_size, vmin=vmin, vmax=vmax, linewidths=0, rasterized=True)
509
512
 
510
- if color_by == 'transect':
513
+ if color_by == 'transect_1D':
511
514
  flight_id = list(metadata['flight_id'])
512
515
  if len(flight_id) > 1:
513
516
  flight_id = flight_id[0]
@@ -518,7 +521,7 @@ class Plotting:
518
521
 
519
522
  metadata_impl = self._db.query(flight_id=flight_id, dataset=metadata['dataset'], retain_query=False)
520
523
  if not title:
521
- title = f'Transect {metadata['flight_id'][0]} from {metadata['reference'][0]}'
524
+ title = f'Transect {metadata_impl['flight_id'][0]} from {metadata_impl['reference'][0]}'
522
525
 
523
526
  f = self._db._get_file_paths_from_metadata(metadata_impl)[0]
524
527
  full_path = os.path.join(self._db._db_dir, f)
@@ -529,15 +532,49 @@ class Plotting:
529
532
  print('Distance not in varibles, cannot plot along transect')
530
533
  return
531
534
 
535
+ if elevation:
536
+ if 'SURF_ELEV' in ds.variables:
537
+ ds['IRH_DEPTH'] = ds.SURF_ELEV - ds.IRH_DEPTH
538
+
539
+ elif 'ICE_THK' in ds.variables and 'BED_ELEV' in ds.variables:
540
+ ds['SURF_ELEV'] = (ds.ICE_THK + ds.BED_ELEV) - ds.IRH_DEPTH
541
+ ds['IRH_DEPTH'] = ds.SURF_ELEV - ds.IRH_DEPTH
542
+ else:
543
+ print('Cannot plot IRH Elevation from the variables in the file, missing either ICE_THK and BED_ELEV or SURF_ELEV')
544
+ return
545
+
532
546
  cmap = self._custom_cmap_density()
533
- colors = [cmap(i) for i in np.linspace(0.1, 0.9, ds.sizes['IRH_AGE'])]
534
- for age, color in zip(ds.IRH_AGE, colors):
547
+ colors = [cmap(i) for i in np.linspace(0.1, 0.9, len(metadata_impl['age']))]
548
+ for age, color in zip(list(map(int, metadata['age'])), colors):
549
+ if age not in ds.IRH_AGE:
550
+ print(f'{metadata_impl['flight_id'][0]} does not contain age {age}, skipping')
551
+ continue
552
+
535
553
  ax.scatter(ds.Distance/1000, ds.IRH_DEPTH.sel(IRH_AGE=age),
536
- color=color, s=marker_size, linewidths=0.1)
537
- plt.plot([], [], color=color, label=age.values, linewidth=3)
538
- # ds.IRH_DEPTH.sel(IRH_AGE=age).where(~np.isnan(ds.IRH_DEPTH.sel(IRH_AGE=age)), drop=True).plot()
539
- scatter = ax.scatter(ds.Distance/1000, ds.ICE_THK, color='k', s=marker_size, linewidths=0.1)
540
- plt.plot([], [], color='k', label='Bed Depth', linewidth=3)
554
+ color=color, s=marker_size, linewidths=0.1)
555
+ plt.plot([], [], color=color, label=age, linewidth=3)
556
+
557
+ if elevation:
558
+ if 'BED_ELEV' in ds.variables:
559
+ scatter = ax.scatter(ds.Distance/1000, ds.BED_ELEV, color='k', s=marker_size, linewidths=0.1)
560
+ plt.plot([], [], color='k', label='Bed Elevation', linewidth=3)
561
+ elif 'ICE_THK' in ds.variables and 'SURF_ELEV' in ds.variables:
562
+ ds['BED_ELEV'] = ds.SURF_ELEV - ds.ICE_THK
563
+ scatter = ax.scatter(ds.Distance/1000, ds.BED_ELEV, color='k', s=marker_size, linewidths=0.1)
564
+ plt.plot([], [], color='k', label='Bed Elevation', linewidth=3)
565
+ else:
566
+ print('Cannot plot Bed Elevation from the variables in the file')
567
+ ax.scatter(ds.Distance/1000, ds.SURF_ELEV, color='grey', s=marker_size, linewidths=0.1)
568
+ plt.plot([], [], color='grey', label='Surface Elevation', linewidth=3)
569
+
570
+ else:
571
+ scatter = ax.scatter(ds.Distance/1000, ds.ICE_THK, color='k', s=marker_size, linewidths=0.1)
572
+ plt.plot([], [], color='k', label='Bed Depth', linewidth=3)
573
+
574
+ if elevation:
575
+ ylim = (ds.BED_ELEV.min() - 200, ds.SURF_ELEV.max()+200) if ylim == (None, None) else ylim
576
+ else:
577
+ ylim = (ds.ICE_THK.max() + 200, 0) if ylim == (None, None) else ylim
541
578
 
542
579
  if ncol == None:
543
580
  if ds.sizes['IRH_AGE'] > 7:
@@ -556,7 +593,7 @@ class Plotting:
556
593
 
557
594
  datasets = list(metadata['dataset'])
558
595
  flight_ids = metadata['flight_id']
559
- for flight_id in tqdm(flight_ids, desc="Plotting", total=len(flight_ids), unit='flight_id'):
596
+ for flight_id in tqdm(flight_ids, desc="Plotting", total=len(flight_ids), unit='flight_id', disable=self._disable_tqdm):
560
597
  metadata_impl = self._db.query(flight_id=flight_id, retain_query=False)
561
598
  file_paths = self._db._get_file_paths_from_metadata(metadata_impl)
562
599
  file_paths = np.unique(file_paths)
@@ -578,7 +615,7 @@ class Plotting:
578
615
 
579
616
  ax.set_xlim(*xlim)
580
617
  ax.set_ylim(*ylim)
581
- if color_by != 'transect':
618
+ if color_by != 'transect_1D':
582
619
  x0, x1 = ax.get_xlim() if xlim == (None, None) else xlim
583
620
  y0, y1 = ax.get_ylim() if ylim == (None, None) else ylim
584
621
  x_extent = x1 - x0
@@ -606,30 +643,70 @@ class Plotting:
606
643
  cbar.ax.xaxis.set_ticks_position('bottom')
607
644
  if label:
608
645
  cbar.set_label(label)
609
- elif color_by == 'transect':
646
+ elif color_by == 'transect_1D':
610
647
  ax.legend(ncols=2)
611
- ax.set_xlabel('Distance [km]')
612
- ax.set_ylabel('Depth below surface [m]')
648
+ ax.set_xlabel('Distance along transect [km]')
649
+ if elevation:
650
+ ax.set_ylabel('Elevation above sea level [m]')
651
+ else:
652
+ ax.set_ylabel('Depth below surface [m]')
613
653
  plt.gcf().set_size_inches(10 * scale_factor, 10 * 2/3)
614
654
 
615
655
  plt.tight_layout()
616
656
 
617
657
  # --- Plot IMBIE basins ---
618
- if basins and color_by != 'transect':
619
- basins = gpd.read_file(self._imbie_path)
620
- basins.geometry = basins.geometry.scale(xfact=0.001, yfact=0.001, origin=(0, 0))
621
- basins.plot(ax=ax, color='none', edgecolor='black', linewidth=0.5)
622
- center_coords = gpd.read_file(self._center_coords)
623
- center_coords.geometry = center_coords.geometry.scale(xfact=0.001, yfact=0.001, origin=(0, 0))
624
- center_coords['x'] = center_coords['geometry'].x
625
- center_coords['y'] = center_coords['geometry'].y
626
- for x, y, sub in zip(center_coords['x'], center_coords['y'], center_coords['Subregion']):
627
- if x0 <= x <= x1 and y0 <= y <= y1: # Only plot if within current view
628
- ax.text(x, y, sub, fontsize=12, color='k', ha='center',
629
- path_effects=[path_effects.withStroke(linewidth=5, foreground=(1,1,1,0.7))]
630
- )
658
+ if basins and color_by != 'transect_1D':
659
+ sf_basins = shapefile.Reader(self._imbie_path)
660
+ basin_patches = []
661
+
662
+ for shape_rec in sf_basins.shapeRecords():
663
+ shp = shape_rec.shape
664
+ pts = shp.points
665
+ parts = list(shp.parts) + [len(pts)] # add sentinel end index
666
+
667
+ # build one polygon per part
668
+ for i in range(len(parts) - 1):
669
+ start, end = parts[i], parts[i + 1]
670
+ ring = pts[start:end]
671
+
672
+ # scale coordinates
673
+ scaled = [(x * 0.001, y * 0.001) for x, y in ring]
674
+
675
+ poly = Polygon(scaled, closed=True, fill=False)
676
+ basin_patches.append(poly)
677
+
678
+ pc = PatchCollection(
679
+ basin_patches,
680
+ facecolor='none',
681
+ edgecolor='black',
682
+ linewidth=0.5,
683
+ )
684
+ ax.add_collection(pc)
685
+
686
+ # ---- CENTERS: read + scale + label ----
687
+ sf_centers = shapefile.Reader(self._center_coords)
688
+
689
+ # find the field index for "Subregion" in the DBF
690
+ fields = sf_centers.fields[1:] # first is DeletionFlag
691
+ field_names = [f[0] for f in fields]
692
+ sub_idx = field_names.index('Subregion')
693
+
694
+ for shape_rec in sf_centers.shapeRecords():
695
+ # assuming center_coords are points
696
+ x_raw, y_raw = shape_rec.shape.points[0]
697
+ x = x_raw * 0.001
698
+ y = y_raw * 0.001
699
+ sub = shape_rec.record[sub_idx]
700
+
701
+ if x0 <= x <= x1 and y0 <= y <= y1:
702
+ ax.text(
703
+ x, y, sub, fontsize=12, color='k', ha='center',
704
+ path_effects=[path_effects.withStroke(
705
+ linewidth=5, foreground=(1, 1, 1, 0.7)
706
+ )]
707
+ )
631
708
  # --- Plot ice core sites ---
632
- if stations and color_by != 'transect':
709
+ if stations and color_by != 'transect_1D':
633
710
  site_coords = pd.read_pickle(self._site_coords_path)
634
711
  for i in site_coords.index:
635
712
  site = site_coords.loc[i]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anta_database
3
- Version: 0.3.1
3
+ Version: 0.3.3
4
4
  Summary: SQLite database for the AntArchitecture Community Data
5
5
  Author: Antoine Hermant
6
6
  Author-email: antoine.hermant@etik.com
@@ -27,6 +27,7 @@ Requires-Dist: scipy
27
27
  Requires-Dist: matplotlib
28
28
  Requires-Dist: colormaps
29
29
  Requires-Dist: tqdm
30
+ Requires-Dist: pyshp
30
31
  Dynamic: license-file
31
32
 
32
33
  <h1 align="center">
@@ -8,3 +8,4 @@ scipy
8
8
  matplotlib
9
9
  colormaps
10
10
  tqdm
11
+ pyshp
@@ -25,6 +25,7 @@ dependencies = [
25
25
  "matplotlib",
26
26
  "colormaps",
27
27
  "tqdm",
28
+ "pyshp",
28
29
  ]
29
30
 
30
31
  keywords = ["isochrones", "database", "IRH", "radar"]
File without changes
File without changes
File without changes
File without changes
File without changes