Skip to content

Commit

Permalink
fix: deprecated widget object copies for #150
Browse files Browse the repository at this point in the history
fix: add polar argument for x == +/-1 to prevent drift
feat: allow reading love numbers where degree is infinite
  • Loading branch information
tsutterley committed Nov 25, 2024
1 parent 2d8807d commit f9983a8
Show file tree
Hide file tree
Showing 13 changed files with 39 additions and 26 deletions.
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

0 comments on commit f9983a8

Please sign in to comment.