Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions gravity_toolkit/legendre.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def legendre(l, x, NORMALIZE=False):
# Column-by-column recursion
for k,mm1 in enumerate(m1):
col = ind[k]
# Calculate twocot for underflow case
# Calculate two*cotangent for underflow case
twocot = -2.0*x[col]/s[col]
P[mm1-1:l+1,col] = 0.0
# Start recursion with proper sign
Expand All @@ -126,7 +126,7 @@ def legendre(l, x, NORMALIZE=False):
count = np.count_nonzero((x != 1) & (np.abs(sn) >= tol))
if (count > 0):
nind, = np.nonzero((x != 1) & (np.abs(sn) >= tol))
# Calculate twocot for normal case
# Calculate two*cotangent for normal case
twocot = -2.0*x[nind]/s[nind]
# Produce normalization constant for the m = l function
d = np.arange(2,2*l+2,2)
Expand Down
8 changes: 6 additions & 2 deletions gravity_toolkit/legendre_polynomials.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
u"""
legendre_polynomials.py
Written by Tyler Sutterley (03/2023)
Written by Tyler Sutterley (11/2024)

Computes fully normalized Legendre polynomials for an array of x values
and their first derivative
Expand Down Expand Up @@ -33,6 +33,7 @@
http://www.springerlink.com/content/978-3-211-33544-4

UPDATE HISTORY:
Updated 11/2024: add polar argument for x == +/-1 to prevent drift
Updated 03/2023: improve typing for variables in docstrings
Updated 04/2022: updated docstrings to numpy documentation format
Updated 05/2021: define int/float precision to prevent deprecation warning
Expand Down Expand Up @@ -92,7 +93,8 @@ def legendre_polynomials(lmax, x, ASTYPE=np.float64):
# for x=cos(th): u=sin(th)
u = np.sqrt(1.0 - x**2)
# update where u==0 to eps of data type to prevent invalid divisions
u[u == 0] = np.finfo(u.dtype).eps
u0, = np.nonzero(u == 0)
u[u0] = np.finfo(u.dtype).eps

# Initialize the recurrence relation
ptemp[0,:] = 1.0
Expand All @@ -104,6 +106,8 @@ def legendre_polynomials(lmax, x, ASTYPE=np.float64):
ptemp[l,:] = (((2.0*l)-1.0)/l)*x*ptemp[l-1,:] - ((l-1.0)/l)*ptemp[l-2,:]
# Normalization is geodesy convention
pl[l,:] = np.sqrt((2.0*l)+1.0)*ptemp[l,:]
# Overwrite polar case (x == +/-1)
pl[l,u0] = np.sqrt((2.0*l)+1.0)*x[u0]**l

# First derivative of Legendre polynomials
for l in range(1,lmax+1):
Expand Down
18 changes: 13 additions & 5 deletions gravity_toolkit/read_love_numbers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
u"""
read_love_numbers.py
Written by Tyler Sutterley (05/2024)
Written by Tyler Sutterley (11/2024)

Reads sets of load Love numbers from PREM and applies isomorphic parameters
Linearly interpolates load Love/Shida numbers for missing degrees
Expand Down Expand Up @@ -56,6 +56,7 @@
103(B12), 30205-30229, (1998)

UPDATE HISTORY:
Updated 11/2024: allow reading where degree is infinite
Updated 05/2024: make subscriptable and allow item assignment
Updated 08/2023: add string representation of the love_numbers class
Updated 05/2023: use pathlib to define and operate on paths
Expand Down Expand Up @@ -94,6 +95,9 @@
import numpy as np
from gravity_toolkit.utilities import get_data_path

# default maximum degree and order in case of infinite
_default_max_degree = 100000

# PURPOSE: read load Love/Shida numbers from PREM
def read_love_numbers(love_numbers_file, LMAX=None, HEADER=2,
COLUMNS=['l','hl','kl','ll'], REFERENCE='CE', FORMAT='tuple'):
Expand Down Expand Up @@ -179,12 +183,15 @@ def read_love_numbers(love_numbers_file, LMAX=None, HEADER=2,
file_contents = extract_love_numbers(love_numbers_file)

# compile regular expression operator to find numerical instances
regex_pattern = r'[-+]?(?:(?:\d*\.\d+)|(?:\d+\.?))(?:[Ee][+-]?\d+)?'
regex_pattern = r'[-+]?(?:(?:\d*\.\d+)|(?:\d+\.?)|(?:inf))(?:[Ee][+-]?\d+)?'
rx = re.compile(regex_pattern, re.VERBOSE)

# extract maximum spherical harmonic degree from final line in file
if LMAX is None:
LMAX = np.int64(rx.findall(file_contents[-1])[COLUMNS.index('l')])
degree = rx.findall(file_contents[-1])[COLUMNS.index('l')]
if LMAX is None and (degree == 'inf'):
LMAX = np.copy(_default_max_degree)
elif LMAX is None:
LMAX = int(degree)

# dictionary of output Love/Shida numbers
love = {}
Expand All @@ -203,7 +210,8 @@ def read_love_numbers(love_numbers_file, LMAX=None, HEADER=2,
# replacing fortran double precision exponential
love_numbers = rx.findall(file_line.replace('D','E'))
# spherical harmonic degree
l = np.int64(love_numbers[COLUMNS.index('l')])
degree = love_numbers[COLUMNS.index('l')]
l = _default_max_degree if (degree == 'inf') else int(degree)
# truncate to spherical harmonic degree LMAX
if (l <= LMAX):
# convert Love/Shida numbers to float
Expand Down
17 changes: 9 additions & 8 deletions gravity_toolkit/tools.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
u"""
tools.py
Written by Tyler Sutterley (04/2024)
Written by Tyler Sutterley (11/2024)
Jupyter notebook, user interface and plotting tools

PYTHON DEPENDENCIES:
Expand All @@ -27,6 +27,7 @@
utilities.py: download and management utilities for files

UPDATE HISTORY:
Updated 11/2024: fix deprecated widget object copies
Updated 04/2024: add widget for setting endpoint for accessing PODAAC data
place colormap registration within try/except to check for existing
Updated 05/2023: use pathlib to define and operate on paths
Expand Down Expand Up @@ -123,7 +124,7 @@ def select_directory(self, **kwargs):
self.directory_button
])
else:
self.directory = copy.copy(self.directory_label)
self.directory = self.directory_label
# connect directory select button with action
self.directory_button.on_click(self.set_directory)

Expand Down Expand Up @@ -154,7 +155,7 @@ def set_directory(self, b):
root.withdraw()
root.call('wm', 'attributes', '.', '-topmost', True)
b.directory = filedialog.askdirectory()
self.directory_label.value = copy.copy(b.directory)
self.directory_label.value = b.directory

def select_product(self):
"""
Expand Down Expand Up @@ -520,7 +521,7 @@ def select_corrections(self, **kwargs):
self.GIA_button
])
else:
self.GIA_file = copy.copy(self.GIA_label)
self.GIA_file = self.GIA_label
# connect fileselect button with action
self.GIA_button.on_click(self.select_GIA_file)

Expand Down Expand Up @@ -567,7 +568,7 @@ def select_corrections(self, **kwargs):
self.remove_button
])
else:
self.remove_file = copy.copy(self.remove_label)
self.remove_file = self.remove_label
# connect fileselect button with action
self.remove_button.on_click(self.select_remove_file)
self.remove_label.observe(self.set_removefile)
Expand Down Expand Up @@ -615,7 +616,7 @@ def select_corrections(self, **kwargs):
self.mask_button
])
else:
self.mask = copy.copy(self.mask_label)
self.mask = self.mask_label
# connect fileselect button with action
self.mask_button.on_click(self.select_mask_file)

Expand Down Expand Up @@ -684,7 +685,7 @@ def select_GIA_file(self, b):
b.files = filedialog.askopenfilename(
filetypes=filetypes,
multiple=False)
self.GIA_label.value = copy.copy(b.files)
self.GIA_label.value = b.files

def select_remove_file(self, b):
"""function for removed file selection
Expand Down Expand Up @@ -730,7 +731,7 @@ def select_mask_file(self, b):
defaultextension='nc',
filetypes=filetypes,
multiple=False)
self.mask_label.value = copy.copy(b.files)
self.mask_label.value = b.files

def select_output(self, **kwargs):
"""
Expand Down
2 changes: 1 addition & 1 deletion notebooks/GRACE-Spatial-Maps.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.6"
"version": "3.9.9"
},
"vscode": {
"interpreter": {
Expand Down
2 changes: 1 addition & 1 deletion scripts/calc_degree_one.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ def calc_degree_one(base_dir, PROC, DREL, MODEL, LMAX, RAD,
dfactor = factors.cmwe
# add attributes for earth parameters
attributes['earth_radius'] = f'{factors.rad_e:0.3f} cm'
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm'
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm^3'
attributes['earth_gravity_constant'] = f'{factors.GM:0.3f} cm^3/s^2'

# Read Smoothed Ocean and Land Functions
Expand Down
2 changes: 1 addition & 1 deletion scripts/combine_harmonics.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ def combine_harmonics(INPUT_FILE, OUTPUT_FILE,
dfactor = factors.get(units)
# add attributes for earth parameters
attributes['ROOT']['earth_radius'] = f'{factors.rad_e:0.3f} cm'
attributes['ROOT']['earth_density'] = f'{factors.rho_e:0.3f} g/cm'
attributes['ROOT']['earth_density'] = f'{factors.rho_e:0.3f} g/cm^3'
attributes['ROOT']['earth_gravity_constant'] = f'{factors.GM:0.3f} cm^3/s^2'

# Computing plms for converting to spatial domain
Expand Down
2 changes: 1 addition & 1 deletion scripts/convert_harmonics.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def convert_harmonics(INPUT_FILE, OUTPUT_FILE,
# add attributes for earth parameters
factors = gravtk.units(lmax=LMAX)
attributes['earth_radius'] = f'{factors.rad_e:0.3f} cm'
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm'
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm^3'
attributes['earth_gravity_constant'] = f'{factors.GM:0.3f} cm^3/s^2'

# calculate associated Legendre polynomials
Expand Down
2 changes: 1 addition & 1 deletion scripts/dealiasing_global_uplift.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ def dealiasing_global_uplift(base_dir,
# add attributes for earth parameters
factors = gravtk.units(lmax=LMAX).harmonic(*LOVE)
attributes['ROOT']['earth_radius'] = f'{factors.rad_e:0.3f} cm'
attributes['ROOT']['earth_density'] = f'{factors.rho_e:0.3f} g/cm'
attributes['ROOT']['earth_density'] = f'{factors.rho_e:0.3f} g/cm^3'
attributes['ROOT']['earth_gravity_constant'] = f'{factors.GM:0.3f} cm^3/s^2'
# degree dependent factors for converting to output units
dfactor = factors.get(UNITS)
Expand Down
2 changes: 1 addition & 1 deletion scripts/grace_raster_grids.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ def grace_raster_grids(base_dir, PROC, DREL, DSET, LMAX, RAD,
units_name, units_longname = gravtk.units.get_attributes(units)
# add attributes for earth parameters
attributes['ROOT']['earth_radius'] = f'{factors.rad_e:0.3f} cm'
attributes['ROOT']['earth_density'] = f'{factors.rho_e:0.3f} g/cm'
attributes['ROOT']['earth_density'] = f'{factors.rho_e:0.3f} g/cm^3'
attributes['ROOT']['earth_gravity_constant'] = f'{factors.GM:0.3f} cm^3/s^2'

# projection attributes
Expand Down
2 changes: 1 addition & 1 deletion scripts/grace_spatial_error.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ def grace_spatial_error(base_dir, PROC, DREL, DSET, LMAX, RAD,
units_name, units_longname = gravtk.units.get_attributes(units)
# add attributes for earth parameters
attributes['earth_radius'] = f'{factors.rad_e:0.3f} cm'
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm'
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm^3'
attributes['earth_gravity_constant'] = f'{factors.GM:0.3f} cm^3/s^2'
# add attributes to output spatial object
attributes['reference'] = f'Output from {pathlib.Path(sys.argv[0]).name}'
Expand Down
2 changes: 1 addition & 1 deletion scripts/grace_spatial_maps.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ def grace_spatial_maps(base_dir, PROC, DREL, DSET, LMAX, RAD,
units_name, units_longname = gravtk.units.get_attributes(units)
# add attributes for earth parameters
attributes['earth_radius'] = f'{factors.rad_e:0.3f} cm'
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm'
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm^3'
attributes['earth_gravity_constant'] = f'{factors.GM:0.3f} cm^3/s^2'
# add attributes to output spatial object
attributes['reference'] = f'Output from {pathlib.Path(sys.argv[0]).name}'
Expand Down
2 changes: 1 addition & 1 deletion scripts/monte_carlo_degree_one.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ def monte_carlo_degree_one(base_dir, PROC, DREL, LMAX, RAD,
dfactor = factors.get('cmwe')
# add attributes for earth parameters
attributes['earth_radius'] = f'{factors.rad_e:0.3f} cm'
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm'
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm^3'
attributes['earth_gravity_constant'] = f'{factors.GM:0.3f} cm^3/s^2'

# Read Smoothed Ocean and Land Functions
Expand Down