Skip to content

Commit 8f34b32

Browse files
keewisbenbovy
andauthored
indexes section in the HTML repr (#7185)
* borrow `Index._repr_inline_` and `inline_index_repr` from a different PR * implement a crude HTML repr for indexes * css fixes and tweaks * escape inline repr * show one section item per unique index Show the names of all corresponding coordinates in the same item (separated by line return). * also add the indexes section to the DataArray html repr * make the grouper a bit easier to understand * add documentation for the display_expand_indexes option * collapse the indexes section by default * update the HTML formatting tests * Update xarray/core/options.py Co-authored-by: Benoit Bovy <[email protected]> * whats-new.rst * improve the index preview contrast * add the repr_inline PR to the changelog [skip-ci] Co-authored-by: Benoit Bovy <[email protected]> Co-authored-by: Benoit Bovy <[email protected]>
1 parent 7379923 commit 8f34b32

File tree

5 files changed

+92
-16
lines changed

5 files changed

+92
-16
lines changed

doc/whats-new.rst

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ New Features
2525

2626
- Add static typing to plot accessors (:issue:`6949`, :pull:`7052`).
2727
By `Michael Niklas <https://github.com/headtr1ck>`_.
28+
- Display the indexes in a new section of the text and HTML reprs
29+
(:pull:`6795`, :pull:`7183`, :pull:`7185`)
30+
By `Justus Magin <https://github.com/keewis>`_ and `Benoît Bovy <https://github.com/benbovy>`_.
2831

2932
Breaking changes
3033
~~~~~~~~~~~~~~~~

xarray/core/formatting_html.py

+53-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from html import escape
77
from importlib.resources import read_binary
88

9-
from .formatting import inline_variable_array_repr, short_data_repr
9+
from .formatting import inline_index_repr, inline_variable_array_repr, short_data_repr
1010
from .options import _get_boolean_with_default
1111

1212
STATIC_FILES = (
@@ -125,6 +125,40 @@ def summarize_vars(variables):
125125
return f"<ul class='xr-var-list'>{vars_li}</ul>"
126126

127127

128+
def short_index_repr_html(index):
129+
if hasattr(index, "_repr_html_"):
130+
return index._repr_html_()
131+
132+
return f"<pre>{escape(repr(index))}</pre>"
133+
134+
135+
def summarize_index(coord_names, index):
136+
name = "<br>".join([escape(str(n)) for n in coord_names])
137+
138+
index_id = f"index-{uuid.uuid4()}"
139+
preview = escape(inline_index_repr(index))
140+
details = short_index_repr_html(index)
141+
142+
data_icon = _icon("icon-database")
143+
144+
return (
145+
f"<div class='xr-index-name'><div>{name}</div></div>"
146+
f"<div class='xr-index-preview'>{preview}</div>"
147+
f"<div></div>"
148+
f"<input id='{index_id}' class='xr-index-data-in' type='checkbox'/>"
149+
f"<label for='{index_id}' title='Show/Hide index repr'>{data_icon}</label>"
150+
f"<div class='xr-index-data'>{details}</div>"
151+
)
152+
153+
154+
def summarize_indexes(indexes):
155+
indexes_li = "".join(
156+
f"<li class='xr-var-item'>{summarize_index(v, i)}</li>"
157+
for v, i in indexes.items()
158+
)
159+
return f"<ul class='xr-var-list'>{indexes_li}</ul>"
160+
161+
128162
def collapsible_section(
129163
name, inline_details="", details="", n_items=None, enabled=True, collapsed=False
130164
):
@@ -213,6 +247,13 @@ def array_section(obj):
213247
expand_option_name="display_expand_data_vars",
214248
)
215249

250+
index_section = partial(
251+
_mapping_section,
252+
name="Indexes",
253+
details_func=summarize_indexes,
254+
max_items_collapse=0,
255+
expand_option_name="display_expand_indexes",
256+
)
216257

217258
attr_section = partial(
218259
_mapping_section,
@@ -223,6 +264,12 @@ def array_section(obj):
223264
)
224265

225266

267+
def _get_indexes_dict(indexes):
268+
return {
269+
tuple(index_vars.keys()): idx for idx, index_vars in indexes.group_by_index()
270+
}
271+
272+
226273
def _obj_repr(obj, header_components, sections):
227274
"""Return HTML repr of an xarray object.
228275
@@ -266,6 +313,10 @@ def array_repr(arr):
266313
if hasattr(arr, "coords"):
267314
sections.append(coord_section(arr.coords))
268315

316+
if hasattr(arr, "xindexes"):
317+
indexes = _get_indexes_dict(arr.xindexes)
318+
sections.append(index_section(indexes))
319+
269320
sections.append(attr_section(arr.attrs))
270321

271322
return _obj_repr(arr, header_components, sections)
@@ -280,6 +331,7 @@ def dataset_repr(ds):
280331
dim_section(ds),
281332
coord_section(ds.coords),
282333
datavar_section(ds.data_vars),
334+
index_section(_get_indexes_dict(ds.xindexes)),
283335
attr_section(ds.attrs),
284336
]
285337

xarray/core/options.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -169,34 +169,41 @@ class set_options:
169169
Colormap to use for nondivergent data plots. If string, must be
170170
matplotlib built-in colormap. Can also be a Colormap object
171171
(e.g. mpl.cm.magma)
172-
display_expand_attrs : {"default", True, False}:
172+
display_expand_attrs : {"default", True, False}
173173
Whether to expand the attributes section for display of
174174
``DataArray`` or ``Dataset`` objects. Can be
175175
176176
* ``True`` : to always expand attrs
177177
* ``False`` : to always collapse attrs
178178
* ``default`` : to expand unless over a pre-defined limit
179-
display_expand_coords : {"default", True, False}:
179+
display_expand_coords : {"default", True, False}
180180
Whether to expand the coordinates section for display of
181181
``DataArray`` or ``Dataset`` objects. Can be
182182
183183
* ``True`` : to always expand coordinates
184184
* ``False`` : to always collapse coordinates
185185
* ``default`` : to expand unless over a pre-defined limit
186-
display_expand_data : {"default", True, False}:
186+
display_expand_data : {"default", True, False}
187187
Whether to expand the data section for display of ``DataArray``
188188
objects. Can be
189189
190190
* ``True`` : to always expand data
191191
* ``False`` : to always collapse data
192192
* ``default`` : to expand unless over a pre-defined limit
193-
display_expand_data_vars : {"default", True, False}:
193+
display_expand_data_vars : {"default", True, False}
194194
Whether to expand the data variables section for display of
195195
``Dataset`` objects. Can be
196196
197197
* ``True`` : to always expand data variables
198198
* ``False`` : to always collapse data variables
199199
* ``default`` : to expand unless over a pre-defined limit
200+
display_expand_indexes : {"default", True, False}
201+
Whether to expand the indexes section for display of
202+
``DataArray`` or ``Dataset``. Can be
203+
204+
* ``True`` : to always expand indexes
205+
* ``False`` : to always collapse indexes
206+
* ``default`` : to expand unless over a pre-defined limit (always collapse for html style)
200207
display_max_rows : int, default: 12
201208
Maximum display rows.
202209
display_values_threshold : int, default: 200

xarray/static/css/style.css

+15-4
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,11 @@ body.vscode-dark {
244244
grid-column: 4;
245245
}
246246

247+
.xr-index-preview {
248+
grid-column: 2 / 5;
249+
color: var(--xr-font-color2);
250+
}
251+
247252
.xr-var-name,
248253
.xr-var-dims,
249254
.xr-var-dtype,
@@ -265,14 +270,16 @@ body.vscode-dark {
265270
}
266271

267272
.xr-var-attrs,
268-
.xr-var-data {
273+
.xr-var-data,
274+
.xr-index-data {
269275
display: none;
270276
background-color: var(--xr-background-color) !important;
271277
padding-bottom: 5px !important;
272278
}
273279

274280
.xr-var-attrs-in:checked ~ .xr-var-attrs,
275-
.xr-var-data-in:checked ~ .xr-var-data {
281+
.xr-var-data-in:checked ~ .xr-var-data,
282+
.xr-index-data-in:checked ~ .xr-index-data {
276283
display: block;
277284
}
278285

@@ -282,13 +289,16 @@ body.vscode-dark {
282289

283290
.xr-var-name span,
284291
.xr-var-data,
292+
.xr-index-name div,
293+
.xr-index-data,
285294
.xr-attrs {
286295
padding-left: 25px !important;
287296
}
288297

289298
.xr-attrs,
290299
.xr-var-attrs,
291-
.xr-var-data {
300+
.xr-var-data,
301+
.xr-index-data {
292302
grid-column: 1 / -1;
293303
}
294304

@@ -326,7 +336,8 @@ dl.xr-attrs {
326336
}
327337

328338
.xr-icon-database,
329-
.xr-icon-file-text2 {
339+
.xr-icon-file-text2,
340+
.xr-no-icon {
330341
display: inline-block;
331342
vertical-align: middle;
332343
width: 1em;

xarray/tests/test_formatting_html.py

+10-7
Original file line numberDiff line numberDiff line change
@@ -102,20 +102,20 @@ def test_repr_of_dataarray(dataarray) -> None:
102102
assert "dim_0" in formatted
103103
# has an expanded data section
104104
assert formatted.count("class='xr-array-in' type='checkbox' checked>") == 1
105-
# coords and attrs don't have an items so they'll be be disabled and collapsed
105+
# coords, indexes and attrs don't have an items so they'll be be disabled and collapsed
106106
assert (
107-
formatted.count("class='xr-section-summary-in' type='checkbox' disabled >") == 2
107+
formatted.count("class='xr-section-summary-in' type='checkbox' disabled >") == 3
108108
)
109109

110110
with xr.set_options(display_expand_data=False):
111111
formatted = fh.array_repr(dataarray)
112112
assert "dim_0" in formatted
113-
# has an expanded data section
113+
# has a collapsed data section
114114
assert formatted.count("class='xr-array-in' type='checkbox' checked>") == 0
115-
# coords and attrs don't have an items so they'll be be disabled and collapsed
115+
# coords, indexes and attrs don't have an items so they'll be be disabled and collapsed
116116
assert (
117117
formatted.count("class='xr-section-summary-in' type='checkbox' disabled >")
118-
== 2
118+
== 3
119119
)
120120

121121

@@ -130,19 +130,22 @@ def test_repr_of_dataset(dataset) -> None:
130130
assert (
131131
formatted.count("class='xr-section-summary-in' type='checkbox' checked>") == 3
132132
)
133+
# indexes is collapsed
134+
assert formatted.count("class='xr-section-summary-in' type='checkbox' >") == 1
133135
assert "&lt;U4" in formatted or "&gt;U4" in formatted
134136
assert "&lt;IA&gt;" in formatted
135137

136138
with xr.set_options(
137139
display_expand_coords=False,
138140
display_expand_data_vars=False,
139141
display_expand_attrs=False,
142+
display_expand_indexes=True,
140143
):
141144
formatted = fh.dataset_repr(dataset)
142-
# coords, attrs, and data_vars are collapsed
145+
# coords, attrs, and data_vars are collapsed, indexes is expanded
143146
assert (
144147
formatted.count("class='xr-section-summary-in' type='checkbox' checked>")
145-
== 0
148+
== 1
146149
)
147150
assert "&lt;U4" in formatted or "&gt;U4" in formatted
148151
assert "&lt;IA&gt;" in formatted

0 commit comments

Comments
 (0)