Skip to content

Commit

Permalink
feat: split S2 tidal aliasing terms into GRACE and GRACE-FO eras (#121)
Browse files Browse the repository at this point in the history
feat: add reify decorator for evaluation of properties
refactor: use formatting for reading from date file
  • Loading branch information
tsutterley committed May 15, 2023
1 parent fcc7cda commit 5715166
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 99 deletions.
8 changes: 4 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ References

T. C. Sutterley, I. Velicogna, and C.-W. Hsu, "Self-Consistent Ice Mass Balance
and Regional Sea Level From Time-Variable Gravity", *Earth and Space Science*, 7,
(2020). `doi:10.1029/2019EA000860 <https://doi.org/10.1029/2019EA000860>`_
(2020). `doi: 10.1029/2019EA000860 <https://doi.org/10.1029/2019EA000860>`_

T. C. Sutterley and I. Velicogna, "Improved estimates of geocenter variability
from time-variable gravity and ocean model outputs", *Remote Sensing*, 11(18),
2108, (2019). `doi:10.3390/rs11182108 <https://doi.org/10.3390/rs11182108>`_
2108, (2019). `doi: 10.3390/rs11182108 <https://doi.org/10.3390/rs11182108>`_

J. Wahr, S. C. Swenson, and I. Velicogna, "Accuracy of GRACE mass estimates",
*Geophysical Research Letters*, 33(6), L06401, (2006).
Expand All @@ -81,11 +81,11 @@ Data Repositories

T. C. Sutterley, I. Velicogna, and C.-W. Hsu, "Ice Mass and Regional Sea Level
Estimates from Time-Variable Gravity", (2020).
`doi:10.6084/m9.figshare.9702338 <https://doi.org/10.6084/m9.figshare.9702338>`_
`doi: 10.6084/m9.figshare.9702338 <https://doi.org/10.6084/m9.figshare.9702338>`_

T. C. Sutterley and I. Velicogna, "Geocenter Estimates from Time-Variable
Gravity and Ocean Model Outputs", (2019).
`doi:10.6084/m9.figshare.7388540 <https://doi.org/10.6084/m9.figshare.7388540>`_
`doi: 10.6084/m9.figshare.7388540 <https://doi.org/10.6084/m9.figshare.7388540>`_

Download
########
Expand Down
3 changes: 3 additions & 0 deletions doc/source/api_reference/utilities.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ General Methods

.. autofunction:: gravity_toolkit.utilities.get_data_path

.. autoclass:: gravity_toolkit.utilities.reify
:members:

.. autofunction:: gravity_toolkit.utilities.get_hash

.. autofunction:: gravity_toolkit.utilities.get_git_revision_hash
Expand Down
6 changes: 3 additions & 3 deletions doc/source/getting_started/Citations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ most recently to the following work:
E. Rignot, T. C. Sutterley, M. van den Broeke, J. M. van Wessem, and D. Wiese,
"Continuity of ice sheet mass loss in Greenland and Antarctica from the GRACE
and GRACE Follow-On missions", *Geophysical Research Letters*, 47,
(2020). `doi:10.1029/2020GL087291 <https://doi.org/10.1029/2020GL087291>`_
(2020). `doi: 10.1029/2020GL087291 <https://doi.org/10.1029/2020GL087291>`_

T. C. Sutterley, I. Velicogna, and C.-W. Hsu, "Self-Consistent Ice Mass Balance
and Regional Sea Level From Time-Variable Gravity", *Earth and Space Science*, 7,
(2020). `doi:10.1029/2019EA000860 <https://doi.org/10.1029/2019EA000860>`_
(2020). `doi: 10.1029/2019EA000860 <https://doi.org/10.1029/2019EA000860>`_

T. C. Sutterley and I. Velicogna, "Improved estimates of geocenter variability
from time-variable gravity and ocean model outputs", *Remote Sensing*, 11(18),
2108, (2019). `doi:10.3390/rs11182108 <https://doi.org/10.3390/rs11182108>`_
2108, (2019). `doi: 10.3390/rs11182108 <https://doi.org/10.3390/rs11182108>`_

Some of the text within this documentation are modifications from these
original works, which is allowed under the
Expand Down
31 changes: 20 additions & 11 deletions gravity_toolkit/grace_find_months.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
u"""
grace_find_months.py
Written by Tyler Sutterley (11/2022)
Written by Tyler Sutterley (05/2023)
Parses date index file from grace_date program
Finds the months available for a GRACE/GRACE-FO/Swarm product
Expand Down Expand Up @@ -36,6 +36,7 @@
grace_date.py: reads GRACE index file and calculates dates for each month
UPDATE HISTORY:
Updated 05/2023: use formatting for reading from date file
Updated 11/2022: use f-strings for formatting verbose or ascii output
Updated 04/2022: updated docstrings to numpy documentation format
Updated 05/2021: define int/float precision to prevent deprecation warning
Expand Down Expand Up @@ -109,22 +110,30 @@ def grace_find_months(base_dir, PROC, DREL, DSET='GSM'):
if not os.access(date_file, os.F_OK):
grace_date(base_dir, PROC=PROC, DREL=DREL, DSET=DSET, OUTPUT=True)

# read GRACE/GRACE-FO date ascii file from grace_date.py
# names and formats of GRACE/GRACE-FO date ascii file
names = ('t','mon','styr','stday','endyr','endday','total')
formats = ('f','i','i','i','i','i','i')
dtype = np.dtype({'names':names, 'formats':formats})
# read GRACE/GRACE-FO date ascii file
# skip the header row and extract dates (decimal format) and months
date_input = np.loadtxt(date_file, skiprows=1)
tdec = date_input[:,0]
months = date_input[:,1].astype(np.int64)
date_input = np.loadtxt(date_file, skiprows=1, dtype=dtype)
# date info dictionary
var_info = {}
var_info['time'] = date_input['t']
var_info['months'] = date_input['mon']
var_info['start'] = np.min(date_input['mon'])
var_info['end'] = np.max(date_input['mon'])

# array of all possible months (or in case of CNES RL01/2: 10-day sets)
all_months = np.arange(1,months.max(),dtype=np.int64)
all_months = np.arange(1, var_info['end'], dtype=np.int64)
# missing months (values in all_months but not in months)
missing = sorted(set(all_months)-set(months))
var_info['missing'] = sorted(set(all_months) - set(date_input['mon']))
# If CNES RL01/2: simply convert into numpy array
# else: remove months 1-3 and convert into numpy array
if ((PROC == 'CNES') & (DREL in ('RL01','RL02'))):
missing = np.array(missing,dtype=np.int64)
var_info['missing'] = np.array(var_info['missing'], dtype=np.int64)
else:
missing = np.array(missing[3:],dtype=np.int64)
var_info['missing'] = np.array(var_info['missing'][3:], dtype=np.int64)

return {'time':tdec, 'start':months[0], 'end':months[-1], 'months':months,
'missing':missing}
# return the date information dictionary
return var_info
40 changes: 13 additions & 27 deletions gravity_toolkit/grace_months_index.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
u"""
grace_months_index.py
Written by Tyler Sutterley (11/2022)
Written by Tyler Sutterley (05/2023)
Creates a file with the start and end days for each dataset
Shows the range of each month for (CSR/GFZ/JPL) (RL04/RL05/RL06)
Expand Down Expand Up @@ -40,6 +40,7 @@
time.py: utilities for calculating time operations
UPDATE HISTORY:
Updated 05/2023: use formatting for reading from date file
Updated 11/2022: use f-strings for formatting verbose or ascii output
Updated 05/2022: use argparse descriptions within documentation
use new GSFC release 6 version 2 mascons as the default
Expand Down Expand Up @@ -108,34 +109,19 @@ def grace_months_index(base_dir, DREL=['RL06','rl06v2.0'], MODE=None):
for pr in PROC:
# Setting the data directory for processing center and release
grace_dir = os.path.join(base_dir, pr, rl, DSET)
# read GRACE date ascii file
# file created in read_grace.py or grace_dates.py
grace_date_file = f'{pr}_{rl}_DATES.txt'
if os.access(os.path.join(grace_dir,grace_date_file), os.F_OK):
# skip the header line
date_input = np.loadtxt(os.path.join(grace_dir,grace_date_file),
skiprows=1)
# number of months
nmon = np.shape(date_input)[0]

# read GRACE/GRACE-FO date ascii file
grace_date_file = os.path.join(grace_dir,f'{pr}_{rl}_DATES.txt')
# names and formats of GRACE/GRACE-FO date ascii file
names = ('t','mon','styr','stday','endyr','endday','total')
formats = ('f','i','i','i','i','i','i')
dtype = np.dtype({'names':names, 'formats':formats})
# check that the GRACE/GRACE-FO date file exists
if os.access(grace_date_file, os.F_OK):
# Setting the dictionary key e.g. 'CSR_RL04'
var_name = f'{pr}_{rl}'

# Creating a python dictionary for each dataset with parameters:
# month #, start year, start day, end year, end day
# Purpose is to get all of the dates loaded for each dataset
# Adding data to dictionary for data processing and release
var_info[var_name] = {}
# allocate for output variables
var_info[var_name]['mon'] = np.zeros((nmon),dtype=np.int64)
var_info[var_name]['styr'] = np.zeros((nmon),dtype=np.int64)
var_info[var_name]['stday'] = np.zeros((nmon),dtype=np.int64)
var_info[var_name]['endyr'] = np.zeros((nmon),dtype=np.int64)
var_info[var_name]['endday'] = np.zeros((nmon),dtype=np.int64)
# place output variables in dictionary
for i,key in enumerate(['mon','styr','stday','endyr','endday']):
# first column is date in decimal form (start at 1 not 0)
var_info[var_name][key] = date_input[:,i+1].astype(np.int64)
# skip the header line
var_info[var_name] = np.loadtxt(grace_date_file,
skiprows=1, dtype=dtype)
# Finding the maximum month measured
if (var_info[var_name]['mon'].max() > max_mon):
# if the maximum month in this dataset is greater
Expand Down
8 changes: 5 additions & 3 deletions gravity_toolkit/harmonics.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
u"""
harmonics.py
Written by Tyler Sutterley (03/2023)
Written by Tyler Sutterley (05/2023)
Contributions by Hugo Lecomte
Spherical harmonic data class for processing GRACE/GRACE-FO Level-2 data
Expand All @@ -25,6 +25,7 @@
destripe_harmonics.py: filters spherical harmonics for correlated errors
UPDATE HISTORY:
Updated 05/2023: use reify decorators for complex form and amplitude
Updated 03/2023: customizable file-level attributes to netCDF4 and HDF5
add attributes fetching to the from_dict and to_dict functions
retrieve all root attributes from HDF5 and netCDF4 datasets
Expand Down Expand Up @@ -101,6 +102,7 @@
from gravity_toolkit.destripe_harmonics import destripe_harmonics
from gravity_toolkit.read_gfc_harmonics import read_gfc_harmonics
from gravity_toolkit.read_GRACE_harmonics import read_GRACE_harmonics
from gravity_toolkit.utilities import reify

# attempt imports
try:
Expand Down Expand Up @@ -1806,7 +1808,7 @@ def destripe(self, **kwargs):
# return the destriped field
return temp

@property
@reify
def amplitude(self):
"""
Degree amplitude of the spherical harmonics
Expand Down Expand Up @@ -1852,7 +1854,7 @@ def ndim(self):
"""
return np.ndim(self.clm)

@property
@reify
def ilm(self):
"""
Complex form of the spherical harmonics
Expand Down
18 changes: 17 additions & 1 deletion gravity_toolkit/utilities.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#!/usr/bin/env python
u"""
utilities.py
Written by Tyler Sutterley (04/2023)
Written by Tyler Sutterley (05/2023)
Download and management utilities for syncing time and auxiliary files
PYTHON DEPENDENCIES:
lxml: processing XML and HTML in Python
https://pypi.python.org/pypi/lxml
UPDATE HISTORY:
Updated 05/2023: add reify decorator for evaluation of properties
Updated 04/2023: use release-03 GFZ GravIS SLR and geocenter files
Updated 03/2023: place boto3 import within try/except statement
Updated 01/2023: add default ssl context attribute with protocol
Expand Down Expand Up @@ -104,6 +105,21 @@ def get_data_path(relpath):
elif isinstance(relpath,str):
return os.path.join(filepath,relpath)

class reify(object):
"""Class decorator that puts the result of the method it
decorates into the instance"""
def __init__(self, wrapped):
self.wrapped = wrapped
self.__name__ = wrapped.__name__
self.__doc__ = wrapped.__doc__

def __get__(self, inst, objtype=None):
if inst is None:
return self
val = self.wrapped(inst)
setattr(inst, self.wrapped.__name__, val)
return val

# PURPOSE: get the hash value of a file
def get_hash(local, algorithm='MD5'):
"""
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
boto3
future
lxml
matplotlib
numpy
python-dateutil
pyyaml
Expand Down
27 changes: 16 additions & 11 deletions scripts/dealiasing_monthly_mean.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
u"""
dealiasing_monthly_mean.py
Written by Tyler Sutterley (03/2023)
Written by Tyler Sutterley (05/2023)
Reads GRACE/GRACE-FO AOD1B datafiles for a specific product and outputs monthly
the mean for a specific GRACE/GRACE-FO processing center and data release
Expand Down Expand Up @@ -48,6 +48,7 @@
time.py: utilities for calculating time operations
UPDATE HISTORY:
Updated 05/2023: use formatting for reading from date file
Updated 03/2023: read data into flattened harmonics objects
debug-level logging of member names and header lines
convert shape and ndim to harmonic class properties
Expand Down Expand Up @@ -103,7 +104,7 @@ def dealiasing_monthly_mean(base_dir, PROC=None, DREL=None, DSET=None,
aod1b_products = dict(GAA='atm',GAB='ocn',GAC='glo',GAD='oba')
# compile regular expressions operator for the clm/slm headers
# for the specific AOD1b product
hx = re.compile(r'^DATA.*SET.*{0}'.format(aod1b_products[DSET]),re.VERBOSE)
hx = re.compile(fr'^DATA.*SET.*{aod1b_products[DSET]}',re.VERBOSE)
# compile regular expression operator to find numerical instances
# will extract the data from the file
regex_pattern = r'[-+]?(?:(?:\d*\.\d+)|(?:\d+\.?))(?:[Ee][+-]?\d+)?'
Expand Down Expand Up @@ -163,16 +164,20 @@ def dealiasing_monthly_mean(base_dir, PROC=None, DREL=None, DSET=None,
CENTER = default_center

# read input DATE file from GSM data product
grace_datefile = '{0}_{1}_DATES.txt'.format(PROC, DREL)
date_input = np.loadtxt(os.path.join(grace_dir,'GSM',grace_datefile),
skiprows=1)
grace_month = date_input[:,1].astype(np.int64)
start_yr = date_input[:,2]
start_day = date_input[:,3].astype(np.int64)
end_yr = date_input[:,4]
end_day = date_input[:,5].astype(np.int64)
grace_date_file = f'{PROC}_{DREL}_DATES.txt'
# names and formats of GRACE/GRACE-FO date ascii file
names = ('t','mon','styr','stday','endyr','endday','total')
formats = ('f','i','i','i','i','i','i')
dtype = np.dtype({'names':names, 'formats':formats})
date_input = np.loadtxt(os.path.join(grace_dir,'GSM',grace_date_file),
skiprows=1, dtype=dtype)
grace_month = date_input['mon']
start_yr = date_input['styr']
start_day = date_input['stday']
end_yr = date_input['endyr']
end_day = date_input['endday']
# output date file reduced to months with complete AOD
f_out = open(os.path.join(grace_dir,DSET,grace_datefile),
f_out = open(os.path.join(grace_dir,DSET,grace_date_file),
mode='w', encoding='utf8')
# date file header information
args = ('Mid-date','Month','Start_Day','End_Day','Total_Days')
Expand Down
Loading

0 comments on commit 5715166

Please sign in to comment.