Source code for gravity_toolkit.grace_months_index

#!/usr/bin/env python
u"""
grace_months_index.py
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)
Shows which months are missing for each dataset as **missing**

INPUTS:
    base_dir: Working data directory for GRACE/GRACE-FO data

OPTIONS:
    DREL: GRACE/GRACE-FO/Swarm data release (RL04, RL05, RL06)
    MODE: Permissions mode of output index file

OUTPUTS:
    GRACE_months.txt
    Column 1: GRACE Month
    Column 2: Calendar Month and Year
    Column 3: CSR RL06 Dates
    Column 4: GFZ RL06 Dates
    Column 5: GSFC v02.4 Mascon Dates
    Column 6: JPL RL06 Dates

COMMAND LINE OPTIONS:
    --help: list the command line options
    -D X, --directory X: Working GRACE/GRACE-FO data directory
    -r X, --release X: GRACE/GRACE-FO Data Releases to run (RL06)
    --mode X: permissions mode of output GRACE month file

PYTHON DEPENDENCIES:
    numpy: Scientific Computing Tools For Python
        https://numpy.org
        https://numpy.org/doc/stable/user/numpy-for-matlab-users.html
    dateutil: powerful extensions to datetime
        https://dateutil.readthedocs.io/en/stable/

PROGRAM DEPENDENCIES:
    time.py: utilities for calculating time operations

UPDATE HISTORY:
    Updated 05/2023: use formatting for reading from date file
        use pathlib to define and operate on paths
    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
    Updated 04/2022: updated docstrings to numpy documentation format
    Updated 09/2021: use functions for converting to and from GRACE months
    Updated 05/2021: define int/float precision to prevent deprecation warning
    Updated 10/2020: use argparse to set command line parameters
    Updated 09/2020: add column for GSFC v02.4 GRACE mascons
    Updated 07/2020: added function docstrings
    Updated 05/2020 for public release
    Updated 05-06/2018: GRACE release 6 (not all processing centers have RL06)
    Updated 01/2017: added MODE to set file and directory permissions
    Updated 05-06/2016: using __future__ print function. format month lines
    Updated 03/2016: using getopt to set RL04 parameter, added new help module
    Updated 10/2015: cleaned up and added a few comments
    Updated 11/2014: minor updates to code. added main definition
    Updated 10/2014: updated comments
    Updated 05/2014: added OPTION to not run RL04
    Updated 05/2013: added years to month label
    Written 07/2012
"""
from __future__ import print_function

import pathlib
import argparse
import calendar
import numpy as np
from gravity_toolkit.time import grace_to_calendar

[docs] def grace_months_index(base_dir, DREL=['RL06','rl06v2.0'], MODE=None): """ Creates a file with the start and end days for each dataset Shows the range of each month for each data center and release Shows which months are missing for each dataset as ``**missing**`` Parameters ---------- base_dir: str Working data directory for GRACE/GRACE-FO data DREL: list GRACE/GRACE-FO/Swarm data release MODE: oct or NoneType, default None Permissions mode of output index file """ # Output GRACE months file base_dir = pathlib.Path(base_dir).expanduser().absolute() grace_months_file = base_dir.joinpath('GRACE_months.txt') fid = grace_months_file.open(mode='w', encoding='utf8') # Initial parameters # processing centers PROC = ['CSR', 'GFZ', 'GSFC', 'JPL'] # read from GSM datasets DSET = 'GSM' # maximum month of the datasets # checks for the maximum month between processing centers max_mon = 0 # contain the information for each dataset var_info = {} # Looping through data releases first (all RL04 then all RL05) # for each considered data release (RL04,RL05) for rl in DREL: # for each processing centers (CSR, GFZ, JPL) for pr in PROC: # Setting the data directory for processing center and release grace_dir = base_dir.joinpath(pr, rl, DSET) # read GRACE/GRACE-FO date ascii file grace_date_file = grace_dir.joinpath(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 grace_date_file.exists(): # Setting the dictionary key e.g. 'CSR_RL04' var_name = f'{pr}_{rl}' # 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 # than the previously read datasets max_mon = np.int64(var_info[var_name]['mon'].max()) # sort datasets alphanumerically var_name = sorted(var_info.keys()) txt = ''.join([f'{d:^21}' for d in var_name]) # printing header to file print(f'{"MONTH":^11} {txt}', file=fid) # for each possible month # GRACE starts at month 004 (April 2002) # max_mon+1 to include max_mon for m in range(4, max_mon+1): # finding the month name e.g. Apr calendar_year,calendar_month = grace_to_calendar(m) month_string = calendar.month_abbr[calendar_month] # create list object for output string output_string = [] # for each processing center and data release for var in var_name: # find if the month of data exists # exists will be greater than 0 if there is a match exists = np.count_nonzero(var_info[var]['mon'] == m) if (exists != 0): # if there is a matching month # indice of matching month ind, = np.nonzero(var_info[var]['mon'] == m) # start date st_yr, = var_info[var]['styr'][ind] st_day, = var_info[var]['stday'][ind] # end date end_yr, = var_info[var]['endyr'][ind] end_day, = var_info[var]['endday'][ind] # output string is the date range # string format: 2002_102--2002_120 output_string.append(f'{st_yr:4d}_{st_day:03d}--' f'{end_yr:4d}_{end_day:03d}') else: # if there is no matching month = missing output_string.append(' ** missing ** ') # create single string with output string components # formatting the strings to be 20 characters in length data_string = ' '.join([f'{s:>20}' for s in output_string]) # printing data line to file args = (m, month_string, calendar_year, data_string) print('{0:03d} {1:>3}{2:4d} {3}'.format(*args), file=fid) # close months file fid.close() # set the permissions level of the output file grace_months_file.chmod(mode=MODE)
# PURPOSE: create argument parser def arguments(): parser = argparse.ArgumentParser( description="""Creates a file with the start and end days for each month of GRACE/GRACE-FO data """ ) # command line parameters # working data directory parser.add_argument('--directory','-D', type=pathlib.Path, default=pathlib.Path.cwd(), help='Working data directory') # GRACE/GRACE-FO data release parser.add_argument('--release','-r', metavar='DREL', type=str, nargs='+', default=['RL06','rl06v2.0'], help='GRACE/GRACE-FO Data Release') # permissions mode of the local directories and files (number in octal) parser.add_argument('--mode','-M', type=lambda x: int(x,base=8), default=0o775, help='Permissions mode of output files') # return the parser return parser # This is the main part of the program that calls the individual functions def main(): # Read the system arguments listed after the program parser = arguments() args,_ = parser.parse_known_args() # run GRACE/GRACE-FO months program grace_months_index(args.directory, DREL=args.release, MODE=args.mode) # run main program if __name__ == '__main__': main()