Skip to content

Commit f9983a8

Browse files
committed
fix: deprecated widget object copies for #150
fix: add polar argument for x == +/-1 to prevent drift feat: allow reading love numbers where degree is infinite
1 parent 2d8807d commit f9983a8

13 files changed

+39
-26
lines changed

gravity_toolkit/legendre.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def legendre(l, x, NORMALIZE=False):
103103
# Column-by-column recursion
104104
for k,mm1 in enumerate(m1):
105105
col = ind[k]
106-
# Calculate twocot for underflow case
106+
# Calculate two*cotangent for underflow case
107107
twocot = -2.0*x[col]/s[col]
108108
P[mm1-1:l+1,col] = 0.0
109109
# Start recursion with proper sign
@@ -126,7 +126,7 @@ def legendre(l, x, NORMALIZE=False):
126126
count = np.count_nonzero((x != 1) & (np.abs(sn) >= tol))
127127
if (count > 0):
128128
nind, = np.nonzero((x != 1) & (np.abs(sn) >= tol))
129-
# Calculate twocot for normal case
129+
# Calculate two*cotangent for normal case
130130
twocot = -2.0*x[nind]/s[nind]
131131
# Produce normalization constant for the m = l function
132132
d = np.arange(2,2*l+2,2)

gravity_toolkit/legendre_polynomials.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python
22
u"""
33
legendre_polynomials.py
4-
Written by Tyler Sutterley (03/2023)
4+
Written by Tyler Sutterley (11/2024)
55
66
Computes fully normalized Legendre polynomials for an array of x values
77
and their first derivative
@@ -33,6 +33,7 @@
3333
http://www.springerlink.com/content/978-3-211-33544-4
3434
3535
UPDATE HISTORY:
36+
Updated 11/2024: add polar argument for x == +/-1 to prevent drift
3637
Updated 03/2023: improve typing for variables in docstrings
3738
Updated 04/2022: updated docstrings to numpy documentation format
3839
Updated 05/2021: define int/float precision to prevent deprecation warning
@@ -92,7 +93,8 @@ def legendre_polynomials(lmax, x, ASTYPE=np.float64):
9293
# for x=cos(th): u=sin(th)
9394
u = np.sqrt(1.0 - x**2)
9495
# update where u==0 to eps of data type to prevent invalid divisions
95-
u[u == 0] = np.finfo(u.dtype).eps
96+
u0, = np.nonzero(u == 0)
97+
u[u0] = np.finfo(u.dtype).eps
9698

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

108112
# First derivative of Legendre polynomials
109113
for l in range(1,lmax+1):

gravity_toolkit/read_love_numbers.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python
22
u"""
33
read_love_numbers.py
4-
Written by Tyler Sutterley (05/2024)
4+
Written by Tyler Sutterley (11/2024)
55
66
Reads sets of load Love numbers from PREM and applies isomorphic parameters
77
Linearly interpolates load Love/Shida numbers for missing degrees
@@ -56,6 +56,7 @@
5656
103(B12), 30205-30229, (1998)
5757
5858
UPDATE HISTORY:
59+
Updated 11/2024: allow reading where degree is infinite
5960
Updated 05/2024: make subscriptable and allow item assignment
6061
Updated 08/2023: add string representation of the love_numbers class
6162
Updated 05/2023: use pathlib to define and operate on paths
@@ -94,6 +95,9 @@
9495
import numpy as np
9596
from gravity_toolkit.utilities import get_data_path
9697

98+
# default maximum degree and order in case of infinite
99+
_default_max_degree = 100000
100+
97101
# PURPOSE: read load Love/Shida numbers from PREM
98102
def read_love_numbers(love_numbers_file, LMAX=None, HEADER=2,
99103
COLUMNS=['l','hl','kl','ll'], REFERENCE='CE', FORMAT='tuple'):
@@ -179,12 +183,15 @@ def read_love_numbers(love_numbers_file, LMAX=None, HEADER=2,
179183
file_contents = extract_love_numbers(love_numbers_file)
180184

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

185189
# extract maximum spherical harmonic degree from final line in file
186-
if LMAX is None:
187-
LMAX = np.int64(rx.findall(file_contents[-1])[COLUMNS.index('l')])
190+
degree = rx.findall(file_contents[-1])[COLUMNS.index('l')]
191+
if LMAX is None and (degree == 'inf'):
192+
LMAX = np.copy(_default_max_degree)
193+
elif LMAX is None:
194+
LMAX = int(degree)
188195

189196
# dictionary of output Love/Shida numbers
190197
love = {}
@@ -203,7 +210,8 @@ def read_love_numbers(love_numbers_file, LMAX=None, HEADER=2,
203210
# replacing fortran double precision exponential
204211
love_numbers = rx.findall(file_line.replace('D','E'))
205212
# spherical harmonic degree
206-
l = np.int64(love_numbers[COLUMNS.index('l')])
213+
degree = love_numbers[COLUMNS.index('l')]
214+
l = _default_max_degree if (degree == 'inf') else int(degree)
207215
# truncate to spherical harmonic degree LMAX
208216
if (l <= LMAX):
209217
# convert Love/Shida numbers to float

gravity_toolkit/tools.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python
22
u"""
33
tools.py
4-
Written by Tyler Sutterley (04/2024)
4+
Written by Tyler Sutterley (11/2024)
55
Jupyter notebook, user interface and plotting tools
66
77
PYTHON DEPENDENCIES:
@@ -27,6 +27,7 @@
2727
utilities.py: download and management utilities for files
2828
2929
UPDATE HISTORY:
30+
Updated 11/2024: fix deprecated widget object copies
3031
Updated 04/2024: add widget for setting endpoint for accessing PODAAC data
3132
place colormap registration within try/except to check for existing
3233
Updated 05/2023: use pathlib to define and operate on paths
@@ -123,7 +124,7 @@ def select_directory(self, **kwargs):
123124
self.directory_button
124125
])
125126
else:
126-
self.directory = copy.copy(self.directory_label)
127+
self.directory = self.directory_label
127128
# connect directory select button with action
128129
self.directory_button.on_click(self.set_directory)
129130

@@ -154,7 +155,7 @@ def set_directory(self, b):
154155
root.withdraw()
155156
root.call('wm', 'attributes', '.', '-topmost', True)
156157
b.directory = filedialog.askdirectory()
157-
self.directory_label.value = copy.copy(b.directory)
158+
self.directory_label.value = b.directory
158159

159160
def select_product(self):
160161
"""
@@ -520,7 +521,7 @@ def select_corrections(self, **kwargs):
520521
self.GIA_button
521522
])
522523
else:
523-
self.GIA_file = copy.copy(self.GIA_label)
524+
self.GIA_file = self.GIA_label
524525
# connect fileselect button with action
525526
self.GIA_button.on_click(self.select_GIA_file)
526527

@@ -567,7 +568,7 @@ def select_corrections(self, **kwargs):
567568
self.remove_button
568569
])
569570
else:
570-
self.remove_file = copy.copy(self.remove_label)
571+
self.remove_file = self.remove_label
571572
# connect fileselect button with action
572573
self.remove_button.on_click(self.select_remove_file)
573574
self.remove_label.observe(self.set_removefile)
@@ -615,7 +616,7 @@ def select_corrections(self, **kwargs):
615616
self.mask_button
616617
])
617618
else:
618-
self.mask = copy.copy(self.mask_label)
619+
self.mask = self.mask_label
619620
# connect fileselect button with action
620621
self.mask_button.on_click(self.select_mask_file)
621622

@@ -684,7 +685,7 @@ def select_GIA_file(self, b):
684685
b.files = filedialog.askopenfilename(
685686
filetypes=filetypes,
686687
multiple=False)
687-
self.GIA_label.value = copy.copy(b.files)
688+
self.GIA_label.value = b.files
688689

689690
def select_remove_file(self, b):
690691
"""function for removed file selection
@@ -730,7 +731,7 @@ def select_mask_file(self, b):
730731
defaultextension='nc',
731732
filetypes=filetypes,
732733
multiple=False)
733-
self.mask_label.value = copy.copy(b.files)
734+
self.mask_label.value = b.files
734735

735736
def select_output(self, **kwargs):
736737
"""

notebooks/GRACE-Spatial-Maps.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,7 @@
862862
"name": "python",
863863
"nbconvert_exporter": "python",
864864
"pygments_lexer": "ipython3",
865-
"version": "3.10.6"
865+
"version": "3.9.9"
866866
},
867867
"vscode": {
868868
"interpreter": {

scripts/calc_degree_one.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ def calc_degree_one(base_dir, PROC, DREL, MODEL, LMAX, RAD,
471471
dfactor = factors.cmwe
472472
# add attributes for earth parameters
473473
attributes['earth_radius'] = f'{factors.rad_e:0.3f} cm'
474-
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm'
474+
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm^3'
475475
attributes['earth_gravity_constant'] = f'{factors.GM:0.3f} cm^3/s^2'
476476

477477
# Read Smoothed Ocean and Land Functions

scripts/combine_harmonics.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ def combine_harmonics(INPUT_FILE, OUTPUT_FILE,
269269
dfactor = factors.get(units)
270270
# add attributes for earth parameters
271271
attributes['ROOT']['earth_radius'] = f'{factors.rad_e:0.3f} cm'
272-
attributes['ROOT']['earth_density'] = f'{factors.rho_e:0.3f} g/cm'
272+
attributes['ROOT']['earth_density'] = f'{factors.rho_e:0.3f} g/cm^3'
273273
attributes['ROOT']['earth_gravity_constant'] = f'{factors.GM:0.3f} cm^3/s^2'
274274

275275
# Computing plms for converting to spatial domain

scripts/convert_harmonics.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ def convert_harmonics(INPUT_FILE, OUTPUT_FILE,
183183
# add attributes for earth parameters
184184
factors = gravtk.units(lmax=LMAX)
185185
attributes['earth_radius'] = f'{factors.rad_e:0.3f} cm'
186-
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm'
186+
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm^3'
187187
attributes['earth_gravity_constant'] = f'{factors.GM:0.3f} cm^3/s^2'
188188

189189
# calculate associated Legendre polynomials

scripts/dealiasing_global_uplift.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ def dealiasing_global_uplift(base_dir,
213213
# add attributes for earth parameters
214214
factors = gravtk.units(lmax=LMAX).harmonic(*LOVE)
215215
attributes['ROOT']['earth_radius'] = f'{factors.rad_e:0.3f} cm'
216-
attributes['ROOT']['earth_density'] = f'{factors.rho_e:0.3f} g/cm'
216+
attributes['ROOT']['earth_density'] = f'{factors.rho_e:0.3f} g/cm^3'
217217
attributes['ROOT']['earth_gravity_constant'] = f'{factors.GM:0.3f} cm^3/s^2'
218218
# degree dependent factors for converting to output units
219219
dfactor = factors.get(UNITS)

scripts/grace_raster_grids.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ def grace_raster_grids(base_dir, PROC, DREL, DSET, LMAX, RAD,
418418
units_name, units_longname = gravtk.units.get_attributes(units)
419419
# add attributes for earth parameters
420420
attributes['ROOT']['earth_radius'] = f'{factors.rad_e:0.3f} cm'
421-
attributes['ROOT']['earth_density'] = f'{factors.rho_e:0.3f} g/cm'
421+
attributes['ROOT']['earth_density'] = f'{factors.rho_e:0.3f} g/cm^3'
422422
attributes['ROOT']['earth_gravity_constant'] = f'{factors.GM:0.3f} cm^3/s^2'
423423

424424
# projection attributes

scripts/grace_spatial_error.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ def grace_spatial_error(base_dir, PROC, DREL, DSET, LMAX, RAD,
411411
units_name, units_longname = gravtk.units.get_attributes(units)
412412
# add attributes for earth parameters
413413
attributes['earth_radius'] = f'{factors.rad_e:0.3f} cm'
414-
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm'
414+
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm^3'
415415
attributes['earth_gravity_constant'] = f'{factors.GM:0.3f} cm^3/s^2'
416416
# add attributes to output spatial object
417417
attributes['reference'] = f'Output from {pathlib.Path(sys.argv[0]).name}'

scripts/grace_spatial_maps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ def grace_spatial_maps(base_dir, PROC, DREL, DSET, LMAX, RAD,
443443
units_name, units_longname = gravtk.units.get_attributes(units)
444444
# add attributes for earth parameters
445445
attributes['earth_radius'] = f'{factors.rad_e:0.3f} cm'
446-
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm'
446+
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm^3'
447447
attributes['earth_gravity_constant'] = f'{factors.GM:0.3f} cm^3/s^2'
448448
# add attributes to output spatial object
449449
attributes['reference'] = f'Output from {pathlib.Path(sys.argv[0]).name}'

scripts/monte_carlo_degree_one.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ def monte_carlo_degree_one(base_dir, PROC, DREL, LMAX, RAD,
390390
dfactor = factors.get('cmwe')
391391
# add attributes for earth parameters
392392
attributes['earth_radius'] = f'{factors.rad_e:0.3f} cm'
393-
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm'
393+
attributes['earth_density'] = f'{factors.rho_e:0.3f} g/cm^3'
394394
attributes['earth_gravity_constant'] = f'{factors.GM:0.3f} cm^3/s^2'
395395

396396
# Read Smoothed Ocean and Land Functions

0 commit comments

Comments
 (0)