Skip to content

Commit 1c3a230

Browse files
authored
feat: add function to create HTML representations of custom classes (#179)
1 parent 2adaf13 commit 1c3a230

12 files changed

Lines changed: 208 additions & 44 deletions

doc/source/notebooks/GRACE-Geostrophic-Maps.ipynb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
"# if updating the local data\n",
8181
"if widgets.update.value:\n",
8282
" # run podaac sync program to get latest data\n",
83-
" !podaac_cumulus.py --directory=$widgets.base_directory --endpoint=$widgets.endpoint\n",
83+
" !podaac_cumulus.py --directory=$widgets.base_directory --endpoint=$widgets.endpoint.value\n",
8484
" # run GRACE date program to verify months\n",
8585
" !run_grace_date.py --directory=$widgets.base_directory --verbose\n",
8686
" # get geocenter data from Sutterley and Velicogna (2019)\n",
@@ -233,7 +233,9 @@
233233
"# number of time steps\n",
234234
"nt = len(months)\n",
235235
"# flag for spherical harmonic order\n",
236-
"order_str = f'M{MMAX:d}' if (MMAX != LMAX) else ''"
236+
"order_str = f'M{MMAX:d}' if (MMAX != LMAX) else ''\n",
237+
"# inspect GRACE harmonics\n",
238+
"GRACE_Ylms"
237239
]
238240
},
239241
{

doc/source/notebooks/GRACE-Harmonic-Plots.ipynb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
"# if updating the local data\n",
7979
"if widgets.update.value:\n",
8080
" # run podaac sync program to get latest data\n",
81-
" !podaac_cumulus.py --directory=$widgets.base_directory --endpoint=$widgets.endpoint\n",
81+
" !podaac_cumulus.py --directory=$widgets.base_directory --endpoint=$widgets.endpoint.value\n",
8282
" # run GRACE date program to verify months\n",
8383
" !run_grace_date.py --directory=$widgets.base_directory --verbose\n",
8484
" # get geocenter data from Sutterley and Velicogna (2019)\n",
@@ -228,7 +228,9 @@
228228
"GRACE_Ylms = gravtk.harmonics().from_dict(Ylms)\n",
229229
"GRACE_Ylms.mean(apply=True)\n",
230230
"# number of time steps\n",
231-
"nt = len(months)"
231+
"nt = len(months)\n",
232+
"# inspect GRACE harmonics\n",
233+
"GRACE_Ylms"
232234
]
233235
},
234236
{
@@ -552,11 +554,9 @@
552554
}
553555
],
554556
"metadata": {
555-
"interpreter": {
556-
"hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
557-
},
558557
"kernelspec": {
559-
"display_name": "Python 3.8.10 64-bit",
558+
"display_name": "py13",
559+
"language": "python",
560560
"name": "python3"
561561
},
562562
"language_info": {
@@ -569,7 +569,7 @@
569569
"name": "python",
570570
"nbconvert_exporter": "python",
571571
"pygments_lexer": "ipython3",
572-
"version": "3.10.6"
572+
"version": "3.13.0"
573573
}
574574
},
575575
"nbformat": 4,

doc/source/notebooks/GRACE-Spatial-Error.ipynb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
"# if updating the local data\n",
7676
"if widgets.update.value:\n",
7777
" # run podaac sync program to get latest data\n",
78-
" !podaac_cumulus.py --directory=$widgets.base_directory --endpoint=$widgets.endpoint\n",
78+
" !podaac_cumulus.py --directory=$widgets.base_directory --endpoint=$widgets.endpoint.value\n",
7979
" # run GRACE date program to verify months\n",
8080
" !run_grace_date.py --directory=$widgets.base_directory --verbose\n",
8181
" # get geocenter data from Sutterley and Velicogna (2019)\n",
@@ -225,7 +225,9 @@
225225
"GRACE_Ylms = gravtk.harmonics().from_dict(Ylms)\n",
226226
"GRACE_Ylms.mean(apply=True)\n",
227227
"# number of time steps\n",
228-
"nt = len(months)"
228+
"nt = len(months)\n",
229+
"# inspect GRACE harmonics\n",
230+
"GRACE_Ylms"
229231
]
230232
},
231233
{

doc/source/notebooks/GRACE-Spatial-Maps.ipynb

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
"# if updating the local data\n",
9191
"if widgets.update.value:\n",
9292
" # run podaac sync program to get latest data\n",
93-
" !podaac_cumulus.py --directory=$widgets.base_directory --endpoint=$widgets.endpoint\n",
93+
" !podaac_cumulus.py --directory=$widgets.base_directory --endpoint=$widgets.endpoint.value\n",
9494
" # run GRACE date program to verify months\n",
9595
" !run_grace_date.py --directory=$widgets.base_directory --verbose\n",
9696
" # get geocenter data from Sutterley and Velicogna (2019)\n",
@@ -270,7 +270,9 @@
270270
"# number of time steps\n",
271271
"nt = len(months)\n",
272272
"# flag for spherical harmonic order\n",
273-
"order_str = f'M{MMAX:d}' if (MMAX != LMAX) else ''"
273+
"order_str = f'M{MMAX:d}' if (MMAX != LMAX) else ''\n",
274+
"# inspect GRACE harmonics\n",
275+
"GRACE_Ylms"
274276
]
275277
},
276278
{
@@ -990,7 +992,7 @@
990992
],
991993
"metadata": {
992994
"kernelspec": {
993-
"display_name": "Python 3.8.10 64-bit",
995+
"display_name": "py13",
994996
"language": "python",
995997
"name": "python3"
996998
},
@@ -1004,12 +1006,7 @@
10041006
"name": "python",
10051007
"nbconvert_exporter": "python",
10061008
"pygments_lexer": "ipython3",
1007-
"version": "3.9.9"
1008-
},
1009-
"vscode": {
1010-
"interpreter": {
1011-
"hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
1012-
}
1009+
"version": "3.13.0"
10131010
}
10141011
},
10151012
"nbformat": 4,

gravity_toolkit/geocenter.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
1717
UPDATE HISTORY:
1818
Updated 07/2026: add dunder (magic) methods for mathematical operations
19+
add HTML representation of geocenter class
1920
Updated 06/2024: use wrapper to importlib for optional dependencies
2021
Updated 05/2024: make subscriptable and allow item assignment
2122
Updated 09/2023: add group option to netCDF read function
@@ -54,7 +55,7 @@
5455
import pathlib
5556
import numpy as np
5657
import gravity_toolkit.time
57-
from gravity_toolkit.utilities import import_dependency
58+
from gravity_toolkit.utilities import import_dependency, html_repr
5859

5960
# attempt imports
6061
netCDF4 = import_dependency('netCDF4')
@@ -1289,11 +1290,25 @@ def fields(self):
12891290
def __str__(self):
12901291
"""String representation of the ``geocenter`` object"""
12911292
properties = ['gravity_toolkit.geocenter']
1292-
if self.month:
1293-
properties.append(f' start_month: {min(self.month)}')
1294-
properties.append(f' end_month: {max(self.month)}')
1293+
if np.any(self.month):
1294+
properties.append(f' start_month: {np.min(self.month)}')
1295+
properties.append(f' end_month: {np.max(self.month)}')
12951296
return '\n'.join(properties)
12961297

1298+
def __repr__(self):
1299+
"""Representation of the ``geocenter`` object"""
1300+
return self.__str__()
1301+
1302+
def _repr_html_(self):
1303+
"""HTML representation of the ``geocenter`` object"""
1304+
header = 'gravity_toolkit.geocenter'
1305+
properties = {}
1306+
if np.any(self.month):
1307+
properties['start_month'] = np.min(self.month)
1308+
properties['end_month'] = np.max(self.month)
1309+
properties['slices'] = self.__len__()
1310+
return html_repr(header, properties)
1311+
12971312
def __add__(self, other):
12981313
"""Add values to a ``geocenter`` object"""
12991314
temp = self.copy()
@@ -1361,7 +1376,7 @@ def __truediv__(self, other):
13611376

13621377
def __len__(self):
13631378
"""Number of months"""
1364-
return len(self.month) if np.any(self.month) else 0
1379+
return len(np.atleast_1d(self.month)) if np.any(self.month) else 0
13651380

13661381
def __iter__(self):
13671382
"""Iterate over GRACE/GRACE-FO months"""

gravity_toolkit/harmonics.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
2727
UPDATE HISTORY:
2828
Updated 07/2026: add dunder (magic) methods for mathematical operations
29+
add HTML representation of harmonics class
2930
Updated 06/2024: use wrapper to importlib for optional dependencies
3031
Updated 05/2024: make subscriptable and allow item assignment
3132
Updated 10/2023: place time and month variables in try/except block
@@ -110,7 +111,7 @@
110111
from gravity_toolkit.destripe_harmonics import destripe_harmonics
111112
from gravity_toolkit.read_gfc_harmonics import read_gfc_harmonics
112113
from gravity_toolkit.read_GRACE_harmonics import read_GRACE_harmonics
113-
from gravity_toolkit.utilities import import_dependency, reify
114+
from gravity_toolkit.utilities import import_dependency, reify, html_repr
114115

115116
# attempt imports
116117
geoidtk = import_dependency('geoid_toolkit')
@@ -1976,11 +1977,28 @@ def __str__(self):
19761977
properties.append(f' max_degree: {self.lmax}')
19771978
if self.mmax and (self.mmax != self.lmax):
19781979
properties.append(f' max_order: {self.mmax}')
1979-
if self.month:
1980-
properties.append(f' start_month: {min(self.month)}')
1981-
properties.append(f' end_month: {max(self.month)}')
1980+
if np.any(self.month):
1981+
properties.append(f' start_month: {np.min(self.month)}')
1982+
properties.append(f' end_month: {np.max(self.month)}')
19821983
return '\n'.join(properties)
19831984

1985+
def __repr__(self):
1986+
"""Representation of the ``harmonics`` object"""
1987+
return self.__str__()
1988+
1989+
def _repr_html_(self):
1990+
"""HTML representation of the ``harmonics`` object"""
1991+
header = 'gravity_toolkit.harmonics'
1992+
properties = {}
1993+
properties['max_degree'] = self.lmax
1994+
if self.mmax and (self.mmax != self.lmax):
1995+
properties['max_order'] = self.mmax
1996+
if np.any(self.month):
1997+
properties['start_month'] = np.min(self.month)
1998+
properties['end_month'] = np.max(self.month)
1999+
properties['slices'] = self.__len__()
2000+
return html_repr(header, properties)
2001+
19842002
def __add__(self, other):
19852003
"""Add values to a ``harmonics`` object"""
19862004
temp = self.copy()
@@ -2048,7 +2066,7 @@ def __truediv__(self, other):
20482066

20492067
def __len__(self):
20502068
"""Number of months"""
2051-
return len(self.month) if np.any(self.month) else 0
2069+
return len(np.atleast_1d(self.month)) if np.any(self.month) else 0
20522070

20532071
def __iter__(self):
20542072
"""Iterate over GRACE/GRACE-FO months"""

gravity_toolkit/read_GIA_model.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python
22
"""
33
read_GIA_model.py
4-
Written by Tyler Sutterley (05/2023)
4+
Written by Tyler Sutterley (07/2026)
55
66
Reads GIA data files that can come in various formats depending on the group
77
Outputs spherical harmonics for the GIA rates and the GIA model parameters
@@ -96,6 +96,7 @@
9696
https://doi.org/10.1002/2016JB013844
9797
9898
UPDATE HISTORY:
99+
Updated 07/2026: add string and HTML representations of gia class
99100
Updated 05/2023: use pathlib to define and operate on paths
100101
Updated 03/2023: case insensitive searching for HDF5 and netCDF4 attributes
101102
convert shape and ndim to harmonic class properties
@@ -148,6 +149,7 @@
148149
import pathlib
149150
import numpy as np
150151
from gravity_toolkit.harmonics import harmonics
152+
from gravity_toolkit.utilities import html_repr
151153

152154
_known_gia_types = [
153155
'IJ05-R2',
@@ -785,3 +787,32 @@ def from_GIA(self, filename, **kwargs):
785787
# assign degree and order fields
786788
self.update_dimensions()
787789
return self
790+
791+
def __str__(self):
792+
"""String representation of the ``gia`` object"""
793+
properties = ['gravity_toolkit.gia']
794+
properties.append(f' title: {self.title}')
795+
properties.append(f' citation: {self.citation}')
796+
properties.append(f' max_degree: {self.lmax}')
797+
if self.mmax and (self.mmax != self.lmax):
798+
properties.append(f' max_order: {self.mmax}')
799+
properties.append(f' reference: {self.reference}')
800+
properties.append(f' url: {self.url}')
801+
return '\n'.join(properties)
802+
803+
def __repr__(self):
804+
"""Representation of the ``gia`` object"""
805+
return self.__str__()
806+
807+
def _repr_html_(self):
808+
"""HTML representation of the ``gia`` object"""
809+
header = 'gravity_toolkit.gia'
810+
properties = {}
811+
properties['title'] = self.title
812+
properties['citation'] = self.citation
813+
properties['max_degree'] = self.lmax
814+
if self.mmax and (self.mmax != self.lmax):
815+
properties['max_order'] = self.mmax
816+
properties['reference'] = self.reference
817+
properties['url'] = self.url
818+
return html_repr(header, properties)

gravity_toolkit/read_love_numbers.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python
22
"""
33
read_love_numbers.py
4-
Written by Tyler Sutterley (11/2024)
4+
Written by Tyler Sutterley (07/2026)
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 07/2026: add HTML representation of love_numbers class
5960
Updated 11/2024: allow reading where degree is infinite
6061
Updated 05/2024: make subscriptable and allow item assignment
6162
Updated 08/2023: add string representation of the love_numbers class
@@ -94,7 +95,7 @@
9495
import logging
9596
import pathlib
9697
import numpy as np
97-
from gravity_toolkit.utilities import get_data_path
98+
from gravity_toolkit.utilities import get_data_path, html_repr
9899

99100
# default maximum degree and order in case of infinite
100101
_default_max_degree = 100000
@@ -582,6 +583,20 @@ def __str__(self):
582583
properties.append(f' reference: {self.reference}')
583584
return '\n'.join(properties)
584585

586+
def __repr__(self):
587+
"""Representation of the ``love_numbers`` object"""
588+
return self.__str__()
589+
590+
def _repr_html_(self):
591+
"""HTML representation of the ``love_numbers`` object"""
592+
header = 'gravity_toolkit.love_numbers'
593+
properties = {}
594+
properties['citation'] = self.citation
595+
properties['earth_model'] = self.model
596+
properties['max_degree'] = self.lmax
597+
properties['reference'] = self.reference
598+
return html_repr(header, properties)
599+
585600
def __len__(self):
586601
"""Number of degrees"""
587602
return len(self.l)

0 commit comments

Comments
 (0)