1
1
#!/usr/bin/env python
2
2
u"""
3
- ATL03.py (12/2022 )
3
+ ATL03.py (11/2023 )
4
4
Read ICESat-2 ATL03 and ATL09 data files to calculate average segment surfaces
5
5
ATL03 datasets: Global Geolocated Photons
6
6
ATL09 datasets: Atmospheric Characteristics
15
15
https://www.h5py.org/
16
16
17
17
UPDATE HISTORY:
18
+ Updated 11/2023: drop DIMENSION_LIST, CLASS and NAME attributes
18
19
Updated 12/2022: place some imports behind try/except statements
19
20
refactor ICESat-2 data product read programs under io
20
21
Updated 04/2022: updated docstrings to numpy documentation format
@@ -127,27 +128,32 @@ def read_granule(FILENAME, ATTRIBUTES=False, **kwargs):
127
128
IS2_atl03_attrs [gtx ]['geophys_corr' ] = {}
128
129
# Global Group Attributes
129
130
for att_name ,att_val in fileID [gtx ].attrs .items ():
130
- IS2_atl03_attrs [gtx ][att_name ] = att_val
131
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
132
+ IS2_atl03_attrs [gtx ][att_name ] = att_val
131
133
# ICESat-2 Measurement Group
132
134
for key ,val in fileID [gtx ]['heights' ].items ():
133
135
IS2_atl03_attrs [gtx ]['heights' ][key ] = {}
134
136
for att_name ,att_val in val .attrs .items ():
135
- IS2_atl03_attrs [gtx ]['heights' ][key ][att_name ]= att_val
137
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
138
+ IS2_atl03_attrs [gtx ]['heights' ][key ][att_name ]= att_val
136
139
# ICESat-2 Geolocation Group
137
140
for key ,val in fileID [gtx ]['geolocation' ].items ():
138
141
IS2_atl03_attrs [gtx ]['geolocation' ][key ] = {}
139
142
for att_name ,att_val in val .attrs .items ():
140
- IS2_atl03_attrs [gtx ]['geolocation' ][key ][att_name ]= att_val
143
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
144
+ IS2_atl03_attrs [gtx ]['geolocation' ][key ][att_name ]= att_val
141
145
# ICESat-2 Background Photon Rate Group
142
146
for key ,val in fileID [gtx ]['bckgrd_atlas' ].items ():
143
147
IS2_atl03_attrs [gtx ]['bckgrd_atlas' ][key ] = {}
144
148
for att_name ,att_val in val .attrs .items ():
145
- IS2_atl03_attrs [gtx ]['bckgrd_atlas' ][key ][att_name ]= att_val
149
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
150
+ IS2_atl03_attrs [gtx ]['bckgrd_atlas' ][key ][att_name ]= att_val
146
151
# ICESat-2 Geophysical Corrections Group
147
152
for key ,val in fileID [gtx ]['geophys_corr' ].items ():
148
153
IS2_atl03_attrs [gtx ]['geophys_corr' ][key ] = {}
149
154
for att_name ,att_val in val .attrs .items ():
150
- IS2_atl03_attrs [gtx ]['geophys_corr' ][key ][att_name ]= att_val
155
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
156
+ IS2_atl03_attrs [gtx ]['geophys_corr' ][key ][att_name ]= att_val
151
157
152
158
# ICESat-2 spacecraft orientation at time
153
159
IS2_atl03_mds ['orbit_info' ] = {}
@@ -158,11 +164,13 @@ def read_granule(FILENAME, ATTRIBUTES=False, **kwargs):
158
164
if ATTRIBUTES :
159
165
# Global Group Attributes
160
166
for att_name ,att_val in fileID ['orbit_info' ].attrs .items ():
161
- IS2_atl03_attrs ['orbit_info' ][att_name ] = att_val
167
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
168
+ IS2_atl03_attrs ['orbit_info' ][att_name ] = att_val
162
169
# Variable Attributes
163
170
IS2_atl03_attrs ['orbit_info' ][key ] = {}
164
171
for att_name ,att_val in val .attrs .items ():
165
- IS2_atl03_attrs ['orbit_info' ][key ][att_name ] = att_val
172
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
173
+ IS2_atl03_attrs ['orbit_info' ][key ][att_name ] = att_val
166
174
167
175
# information ancillary to the data product
168
176
# number of GPS seconds between the GPS epoch (1980-01-06T00:00:00Z UTC)
@@ -185,7 +193,8 @@ def read_granule(FILENAME, ATTRIBUTES=False, **kwargs):
185
193
# Variable Attributes
186
194
IS2_atl03_attrs ['ancillary_data' ][key ] = {}
187
195
for att_name ,att_val in fileID ['ancillary_data' ][key ].attrs .items ():
188
- IS2_atl03_attrs ['ancillary_data' ][key ][att_name ] = att_val
196
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
197
+ IS2_atl03_attrs ['ancillary_data' ][key ][att_name ] = att_val
189
198
190
199
# transmit-echo-path (tep) parameters
191
200
IS2_atl03_mds ['ancillary_data' ]['tep' ] = {}
@@ -198,7 +207,8 @@ def read_granule(FILENAME, ATTRIBUTES=False, **kwargs):
198
207
# Variable Attributes
199
208
IS2_atl03_attrs ['ancillary_data' ]['tep' ][key ] = {}
200
209
for att_name ,att_val in val .attrs .items ():
201
- IS2_atl03_attrs ['ancillary_data' ]['tep' ][key ][att_name ] = att_val
210
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
211
+ IS2_atl03_attrs ['ancillary_data' ]['tep' ][key ][att_name ] = att_val
202
212
203
213
# channel dead time and first photon bias derived from ATLAS calibration
204
214
cal1 ,cal2 = ('ancillary_data' ,'calibrations' )
@@ -218,12 +228,14 @@ def read_granule(FILENAME, ATTRIBUTES=False, **kwargs):
218
228
# Variable Attributes
219
229
IS2_atl03_attrs [cal1 ][var ][key ] = {}
220
230
for att_name ,att_val in val .attrs .items ():
221
- IS2_atl03_attrs [cal1 ][var ][key ][att_name ] = att_val
231
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
232
+ IS2_atl03_attrs [cal1 ][var ][key ][att_name ] = att_val
222
233
if isinstance (val , h5py .Group ):
223
234
for k ,v in val .items ():
224
235
IS2_atl03_attrs [cal1 ][var ][key ][k ] = {}
225
236
for att_name ,att_val in val .attrs .items ():
226
- IS2_atl03_attrs [cal1 ][var ][key ][k ][att_name ]= att_val
237
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
238
+ IS2_atl03_attrs [cal1 ][var ][key ][k ][att_name ]= att_val
227
239
228
240
# get ATLAS impulse response variables for the transmitter echo path (TEP)
229
241
tep1 ,tep2 = ('atlas_impulse_response' ,'tep_histogram' )
@@ -239,21 +251,24 @@ def read_granule(FILENAME, ATTRIBUTES=False, **kwargs):
239
251
if ATTRIBUTES :
240
252
# Global Group Attributes
241
253
for att_name ,att_val in fileID [tep1 ][pce ][tep2 ].attrs .items ():
242
- IS2_atl03_attrs [tep1 ][pce ][tep2 ][att_name ] = att_val
254
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
255
+ IS2_atl03_attrs [tep1 ][pce ][tep2 ][att_name ] = att_val
243
256
# Variable Attributes
244
257
IS2_atl03_attrs [tep1 ][pce ][tep2 ][key ] = {}
245
258
for att_name ,att_val in val .attrs .items ():
246
- IS2_atl03_attrs [tep1 ][pce ][tep2 ][key ][att_name ] = att_val
259
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
260
+ IS2_atl03_attrs [tep1 ][pce ][tep2 ][key ][att_name ] = att_val
247
261
248
262
# Global File Attributes
249
263
if ATTRIBUTES :
250
264
for att_name ,att_val in fileID .attrs .items ():
251
- IS2_atl03_attrs [att_name ] = att_val
265
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
266
+ IS2_atl03_attrs [att_name ] = att_val
252
267
253
268
# Closing the HDF5 file
254
269
fileID .close ()
255
270
# Return the datasets and variables
256
- return (IS2_atl03_mds ,IS2_atl03_attrs ,IS2_atl03_beams )
271
+ return (IS2_atl03_mds , IS2_atl03_attrs , IS2_atl03_beams )
257
272
258
273
# PURPOSE: read ICESat-2 ATL09 HDF5 data file for specific variables
259
274
def interpolate_ATL09 (FILENAME , pfl , dtime , ATTRIBUTES = True , ** kwargs ):
@@ -311,22 +326,25 @@ def interpolate_ATL09(FILENAME, pfl, dtime, ATTRIBUTES=True, **kwargs):
311
326
IS2_atl09_attrs [pfl ] = dict (high_rate = {})
312
327
# Global Group Attributes
313
328
for att_name ,att_val in fileID [pfl ].attrs .items ():
314
- IS2_atl09_attrs [pfl ][att_name ] = att_val
329
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
330
+ IS2_atl09_attrs [pfl ][att_name ] = att_val
315
331
# Variable Attributes
316
332
for key in high_rate_keys :
317
333
IS2_atl09_attrs [pfl ]['high_rate' ][key ] = {}
318
334
for att_name ,att_val in fileID [pfl ]['high_rate' ][key ].attrs .items ():
319
- IS2_atl09_attrs [pfl ]['high_rate' ][key ][att_name ] = att_val
335
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
336
+ IS2_atl09_attrs [pfl ]['high_rate' ][key ][att_name ] = att_val
320
337
321
338
# Global File Attributes
322
339
if ATTRIBUTES :
323
340
for att_name ,att_val in fileID .attrs .items ():
324
- IS2_atl09_attrs [att_name ] = att_val
341
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
342
+ IS2_atl09_attrs [att_name ] = att_val
325
343
326
344
# Closing the HDF5 file
327
345
fileID .close ()
328
346
# Return the datasets and variables
329
- return (IS2_atl09_mds ,IS2_atl09_attrs )
347
+ return (IS2_atl09_mds , IS2_atl09_attrs )
330
348
331
349
# PURPOSE: find valid beam groups within ICESat-2 ATL03 HDF5 data files
332
350
def find_beams (FILENAME , ** kwargs ):
@@ -425,11 +443,13 @@ def read_main(FILENAME, ATTRIBUTES=False, **kwargs):
425
443
if ATTRIBUTES :
426
444
# Global Group Attributes
427
445
for att_name ,att_val in fileID ['orbit_info' ].attrs .items ():
428
- IS2_atl03_attrs ['orbit_info' ][att_name ] = att_val
446
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
447
+ IS2_atl03_attrs ['orbit_info' ][att_name ] = att_val
429
448
# Variable Attributes
430
449
IS2_atl03_attrs ['orbit_info' ][key ] = {}
431
450
for att_name ,att_val in val .attrs .items ():
432
- IS2_atl03_attrs ['orbit_info' ][key ][att_name ] = att_val
451
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
452
+ IS2_atl03_attrs ['orbit_info' ][key ][att_name ] = att_val
433
453
434
454
# information ancillary to the data product
435
455
# number of GPS seconds between the GPS epoch (1980-01-06T00:00:00Z UTC)
@@ -452,7 +472,8 @@ def read_main(FILENAME, ATTRIBUTES=False, **kwargs):
452
472
# Variable Attributes
453
473
IS2_atl03_attrs ['ancillary_data' ][key ] = {}
454
474
for att_name ,att_val in fileID ['ancillary_data' ][key ].attrs .items ():
455
- IS2_atl03_attrs ['ancillary_data' ][key ][att_name ] = att_val
475
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
476
+ IS2_atl03_attrs ['ancillary_data' ][key ][att_name ] = att_val
456
477
457
478
# transmit-echo-path (tep) parameters
458
479
IS2_atl03_mds ['ancillary_data' ]['tep' ] = {}
@@ -465,7 +486,8 @@ def read_main(FILENAME, ATTRIBUTES=False, **kwargs):
465
486
# Variable Attributes
466
487
IS2_atl03_attrs ['ancillary_data' ]['tep' ][key ] = {}
467
488
for att_name ,att_val in val .attrs .items ():
468
- IS2_atl03_attrs ['ancillary_data' ]['tep' ][key ][att_name ] = att_val
489
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
490
+ IS2_atl03_attrs ['ancillary_data' ]['tep' ][key ][att_name ] = att_val
469
491
470
492
# channel dead time and first photon bias derived from ATLAS calibration
471
493
cal1 ,cal2 = ('ancillary_data' ,'calibrations' )
@@ -485,12 +507,14 @@ def read_main(FILENAME, ATTRIBUTES=False, **kwargs):
485
507
# Variable Attributes
486
508
IS2_atl03_attrs [cal1 ][var ][key ] = {}
487
509
for att_name ,att_val in val .attrs .items ():
488
- IS2_atl03_attrs [cal1 ][var ][key ][att_name ] = att_val
510
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
511
+ IS2_atl03_attrs [cal1 ][var ][key ][att_name ] = att_val
489
512
if isinstance (val , h5py .Group ):
490
513
for k ,v in val .items ():
491
514
IS2_atl03_attrs [cal1 ][var ][key ][k ] = {}
492
515
for att_name ,att_val in val .attrs .items ():
493
- IS2_atl03_attrs [cal1 ][var ][key ][k ][att_name ]= att_val
516
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
517
+ IS2_atl03_attrs [cal1 ][var ][key ][k ][att_name ]= att_val
494
518
495
519
# get ATLAS impulse response variables for the transmitter echo path (TEP)
496
520
tep1 ,tep2 = ('atlas_impulse_response' ,'tep_histogram' )
@@ -506,21 +530,24 @@ def read_main(FILENAME, ATTRIBUTES=False, **kwargs):
506
530
if ATTRIBUTES :
507
531
# Global Group Attributes
508
532
for att_name ,att_val in fileID [tep1 ][pce ][tep2 ].attrs .items ():
509
- IS2_atl03_attrs [tep1 ][pce ][tep2 ][att_name ] = att_val
533
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
534
+ IS2_atl03_attrs [tep1 ][pce ][tep2 ][att_name ] = att_val
510
535
# Variable Attributes
511
536
IS2_atl03_attrs [tep1 ][pce ][tep2 ][key ] = {}
512
537
for att_name ,att_val in val .attrs .items ():
513
- IS2_atl03_attrs [tep1 ][pce ][tep2 ][key ][att_name ] = att_val
538
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
539
+ IS2_atl03_attrs [tep1 ][pce ][tep2 ][key ][att_name ] = att_val
514
540
515
541
# Global File Attributes
516
542
if ATTRIBUTES :
517
543
for att_name ,att_val in fileID .attrs .items ():
518
- IS2_atl03_attrs [att_name ] = att_val
544
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
545
+ IS2_atl03_attrs [att_name ] = att_val
519
546
520
547
# Closing the HDF5 file
521
548
fileID .close ()
522
549
# Return the datasets and variables
523
- return (IS2_atl03_mds ,IS2_atl03_attrs ,IS2_atl03_beams )
550
+ return (IS2_atl03_mds , IS2_atl03_attrs , IS2_atl03_beams )
524
551
525
552
# PURPOSE: read ICESat-2 ATL03 HDF5 data files for beam variables
526
553
def read_beam (FILENAME , gtx , ATTRIBUTES = False , ** kwargs ):
@@ -595,29 +622,34 @@ def read_beam(FILENAME, gtx, ATTRIBUTES=False, **kwargs):
595
622
IS2_atl03_attrs ['Atlas_impulse_response' ] = {}
596
623
# Global Group Attributes
597
624
for att_name ,att_val in fileID [gtx ].attrs .items ():
598
- IS2_atl03_attrs [att_name ] = att_val
625
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
626
+ IS2_atl03_attrs [att_name ] = att_val
599
627
# ICESat-2 Measurement Group
600
628
for key ,val in fileID [gtx ]['heights' ].items ():
601
629
IS2_atl03_attrs ['heights' ][key ] = {}
602
630
for att_name ,att_val in val .attrs .items ():
603
- IS2_atl03_attrs ['heights' ][key ][att_name ]= att_val
631
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
632
+ IS2_atl03_attrs ['heights' ][key ][att_name ]= att_val
604
633
# ICESat-2 Geolocation Group
605
634
for key ,val in fileID [gtx ]['geolocation' ].items ():
606
635
IS2_atl03_attrs ['geolocation' ][key ] = {}
607
636
for att_name ,att_val in val .attrs .items ():
608
- IS2_atl03_attrs ['geolocation' ][key ][att_name ]= att_val
637
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
638
+ IS2_atl03_attrs ['geolocation' ][key ][att_name ]= att_val
609
639
# ICESat-2 Background Photon Rate Group
610
640
for key ,val in fileID [gtx ]['bckgrd_atlas' ].items ():
611
641
IS2_atl03_attrs ['bckgrd_atlas' ][key ] = {}
612
642
for att_name ,att_val in val .attrs .items ():
613
- IS2_atl03_attrs ['bckgrd_atlas' ][key ][att_name ]= att_val
643
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
644
+ IS2_atl03_attrs ['bckgrd_atlas' ][key ][att_name ]= att_val
614
645
# ICESat-2 Geophysical Corrections Group
615
646
for key ,val in fileID [gtx ]['geophys_corr' ].items ():
616
647
IS2_atl03_attrs ['geophys_corr' ][key ] = {}
617
648
for att_name ,att_val in val .attrs .items ():
618
- IS2_atl03_attrs ['geophys_corr' ][key ][att_name ]= att_val
649
+ if att_name not in ('DIMENSION_LIST' ,'CLASS' ,'NAME' ):
650
+ IS2_atl03_attrs ['geophys_corr' ][key ][att_name ]= att_val
619
651
620
652
# Closing the HDF5 file
621
653
fileID .close ()
622
654
# Return the datasets and variables
623
- return (IS2_atl03_mds ,IS2_atl03_attrs )
655
+ return (IS2_atl03_mds , IS2_atl03_attrs )
0 commit comments