10
10
from typing import TYPE_CHECKING , Literal
11
11
12
12
from xarray .core .formatting import (
13
+ filter_nondefault_indexes ,
13
14
inherited_vars ,
14
15
inline_index_repr ,
15
16
inline_variable_array_repr ,
@@ -323,24 +324,33 @@ def array_repr(arr) -> str:
323
324
indexed_dims = {}
324
325
325
326
obj_type = f"xarray.{ type (arr ).__name__ } "
326
- arr_name = f"' { arr .name } '" if getattr (arr , "name" , None ) else ""
327
+ arr_name = escape ( repr ( arr .name )) if getattr (arr , "name" , None ) else ""
327
328
328
329
header_components = [
329
330
f"<div class='xr-obj-type'>{ obj_type } </div>" ,
330
- f"<div class='xr-array -name'>{ arr_name } </div>" ,
331
+ f"<div class='xr-obj -name'>{ arr_name } </div>" ,
331
332
format_dims (dims , indexed_dims ),
332
333
]
333
334
334
335
sections = [array_section (arr )]
335
336
336
337
if hasattr (arr , "coords" ):
337
- sections .append (coord_section (arr .coords ))
338
+ if arr .coords :
339
+ sections .append (coord_section (arr .coords ))
338
340
339
341
if hasattr (arr , "xindexes" ):
340
- indexes = _get_indexes_dict (arr .xindexes )
341
- sections .append (index_section (indexes ))
342
-
343
- sections .append (attr_section (arr .attrs ))
342
+ display_default_indexes = _get_boolean_with_default (
343
+ "display_default_indexes" , False
344
+ )
345
+ xindexes = filter_nondefault_indexes (
346
+ _get_indexes_dict (arr .xindexes ), not display_default_indexes
347
+ )
348
+ if xindexes :
349
+ indexes = _get_indexes_dict (arr .xindexes )
350
+ sections .append (index_section (indexes ))
351
+
352
+ if arr .attrs :
353
+ sections .append (attr_section (arr .attrs ))
344
354
345
355
return _obj_repr (arr , header_components , sections )
346
356
@@ -350,28 +360,85 @@ def dataset_repr(ds) -> str:
350
360
351
361
header_components = [f"<div class='xr-obj-type'>{ escape (obj_type )} </div>" ]
352
362
353
- sections = [
354
- dim_section (ds ),
355
- coord_section (ds .coords ),
356
- datavar_section (ds .data_vars ),
357
- index_section (_get_indexes_dict (ds .xindexes )),
358
- attr_section (ds .attrs ),
359
- ]
363
+ sections = []
364
+
365
+ sections .append (dim_section (ds ))
366
+
367
+ if ds .coords :
368
+ sections .append (coord_section (ds .coords ))
369
+
370
+ sections .append (datavar_section (ds .data_vars ))
371
+
372
+ display_default_indexes = _get_boolean_with_default (
373
+ "display_default_indexes" , False
374
+ )
375
+ xindexes = filter_nondefault_indexes (
376
+ _get_indexes_dict (ds .xindexes ), not display_default_indexes
377
+ )
378
+ if xindexes :
379
+ sections .append (index_section (xindexes ))
380
+
381
+ if ds .attrs :
382
+ sections .append (attr_section (ds .attrs ))
360
383
361
384
return _obj_repr (ds , header_components , sections )
362
385
363
386
387
+ def datatree_node_sections (node : DataTree , root : bool = False ) -> list [str ]:
388
+ from xarray .core .coordinates import Coordinates
389
+
390
+ ds = node ._to_dataset_view (rebuild_dims = False , inherit = True )
391
+ node_coords = node .to_dataset (inherit = False ).coords
392
+
393
+ # use this class to get access to .xindexes property
394
+ inherited_coords = Coordinates (
395
+ coords = inherited_vars (node ._coord_variables ),
396
+ indexes = inherited_vars (node ._indexes ),
397
+ )
398
+
399
+ # Only show dimensions if also showing a variable or coordinates section.
400
+ show_dims = (
401
+ node ._node_coord_variables
402
+ or (root and inherited_coords )
403
+ or node ._data_variables
404
+ )
405
+
406
+ sections = []
407
+
408
+ if node .children :
409
+ children_max_items = 1 if ds .data_vars else 6
410
+ sections .append (
411
+ children_section (node .children , max_items_collapse = children_max_items )
412
+ )
413
+
414
+ if show_dims :
415
+ sections .append (dim_section (ds ))
416
+
417
+ if node_coords :
418
+ sections .append (coord_section (node_coords ))
419
+
420
+ # only show inherited coordinates on the root
421
+ if root and inherited_coords :
422
+ sections .append (inherited_coord_section (inherited_coords ))
423
+
424
+ if ds .data_vars :
425
+ sections .append (datavar_section (ds .data_vars ))
426
+
427
+ if ds .attrs :
428
+ sections .append (attr_section (ds .attrs ))
429
+
430
+ return sections
431
+
432
+
364
433
def summarize_datatree_children (children : Mapping [str , DataTree ]) -> str :
365
434
MAX_CHILDREN = OPTIONS ["display_max_children" ]
366
435
n_children = len (children )
367
436
368
437
children_html = []
369
- for i , ( n , c ) in enumerate (children .items ()):
438
+ for i , child in enumerate (children .values ()):
370
439
if i < ceil (MAX_CHILDREN / 2 ) or i >= ceil (n_children - MAX_CHILDREN / 2 ):
371
440
is_last = i == (n_children - 1 )
372
- children_html .append (
373
- _wrap_datatree_repr (datatree_node_repr (n , c ), end = is_last )
374
- )
441
+ children_html .append (datatree_child_repr (child , end = is_last ))
375
442
elif n_children > MAX_CHILDREN and i == ceil (MAX_CHILDREN / 2 ):
376
443
children_html .append ("<div>...</div>" )
377
444
@@ -388,7 +455,6 @@ def summarize_datatree_children(children: Mapping[str, DataTree]) -> str:
388
455
_mapping_section ,
389
456
name = "Groups" ,
390
457
details_func = summarize_datatree_children ,
391
- max_items_collapse = 1 ,
392
458
max_option_name = "display_max_children" ,
393
459
expand_option_name = "display_expand_groups" ,
394
460
)
@@ -402,108 +468,58 @@ def summarize_datatree_children(children: Mapping[str, DataTree]) -> str:
402
468
)
403
469
404
470
405
- def datatree_node_repr (group_title : str , node : DataTree , show_inherited = False ) -> str :
406
- from xarray .core .coordinates import Coordinates
407
-
408
- header_components = [f"<div class='xr-obj-type'>{ escape (group_title )} </div>" ]
409
-
410
- ds = node ._to_dataset_view (rebuild_dims = False , inherit = True )
411
- node_coords = node .to_dataset (inherit = False ).coords
412
-
413
- # use this class to get access to .xindexes property
414
- inherited_coords = Coordinates (
415
- coords = inherited_vars (node ._coord_variables ),
416
- indexes = inherited_vars (node ._indexes ),
417
- )
418
-
419
- sections = [
420
- children_section (node .children ),
421
- dim_section (ds ),
422
- coord_section (node_coords ),
423
- ]
424
-
425
- # only show inherited coordinates on the root
426
- if show_inherited :
427
- sections .append (inherited_coord_section (inherited_coords ))
428
-
429
- sections += [
430
- datavar_section (ds .data_vars ),
431
- attr_section (ds .attrs ),
432
- ]
433
-
434
- return _obj_repr (ds , header_components , sections )
435
-
436
-
437
- def _wrap_datatree_repr (r : str , end : bool = False ) -> str :
471
+ def datatree_child_repr (node : DataTree , end : bool = False ) -> str :
472
+ # Wrap DataTree HTML representation with a tee to the left of it.
473
+ #
474
+ # Enclosing HTML tag is a <div> with :code:`display: inline-grid` style.
475
+ #
476
+ # Turns:
477
+ # [ title ]
478
+ # | details |
479
+ # |_____________|
480
+ #
481
+ # into (A):
482
+ # |─ [ title ]
483
+ # | | details |
484
+ # | |_____________|
485
+ #
486
+ # or (B):
487
+ # └─ [ title ]
488
+ # | details |
489
+ # |_____________|
490
+ end = bool (end )
491
+ height = "100%" if end is False else "1.2em" # height of line
492
+
493
+ path = escape (node .path )
494
+ sections = datatree_node_sections (node , root = False )
495
+ section_items = "" .join (f"<li class='xr-section-item'>{ s } </li>" for s in sections )
496
+
497
+ # TODO: Can we make the group name clickable to toggle the sections below?
498
+ # This looks like it would require the input/label pattern used above.
499
+ html = f"""
500
+ <div class='xr-group-box'>
501
+ <div class='xr-group-box-vline' style='height: { height } '></div>
502
+ <div class='xr-group-box-hline'></div>
503
+ <div class='xr-group-box-contents'>
504
+ <div class='xr-header'>
505
+ <div class='xr-group-name'>{ path } </div>
506
+ </div>
507
+ <ul class='xr-sections'>
508
+ { section_items }
509
+ </ul>
510
+ </div>
511
+ </div>
438
512
"""
439
- Wrap HTML representation with a tee to the left of it.
440
-
441
- Enclosing HTML tag is a <div> with :code:`display: inline-grid` style.
513
+ return "" .join (t .strip () for t in html .split ("\n " ))
442
514
443
- Turns:
444
- [ title ]
445
- | details |
446
- |_____________|
447
-
448
- into (A):
449
- |─ [ title ]
450
- | | details |
451
- | |_____________|
452
-
453
- or (B):
454
- └─ [ title ]
455
- | details |
456
- |_____________|
457
-
458
- Parameters
459
- ----------
460
- r: str
461
- HTML representation to wrap.
462
- end: bool
463
- Specify if the line on the left should continue or end.
464
-
465
- Default is True.
466
-
467
- Returns
468
- -------
469
- str
470
- Wrapped HTML representation.
471
-
472
- Tee color is set to the variable :code:`--xr-border-color`.
473
- """
474
- # height of line
475
- end = bool (end )
476
- height = "100%" if end is False else "1.2em"
477
- return "" .join (
478
- [
479
- "<div style='display: inline-grid; grid-template-columns: 0px 20px auto; width: 100%;'>" ,
480
- "<div style='" ,
481
- "grid-column-start: 1;" ,
482
- "border-right: 0.2em solid;" ,
483
- "border-color: var(--xr-border-color);" ,
484
- f"height: { height } ;" ,
485
- "width: 0px;" ,
486
- "'>" ,
487
- "</div>" ,
488
- "<div style='" ,
489
- "grid-column-start: 2;" ,
490
- "grid-row-start: 1;" ,
491
- "height: 1em;" ,
492
- "width: 20px;" ,
493
- "border-bottom: 0.2em solid;" ,
494
- "border-color: var(--xr-border-color);" ,
495
- "'>" ,
496
- "</div>" ,
497
- "<div style='" ,
498
- "grid-column-start: 3;" ,
499
- "'>" ,
500
- r ,
501
- "</div>" ,
502
- "</div>" ,
503
- ]
504
- )
505
515
516
+ def datatree_repr (node : DataTree ) -> str :
517
+ header_components = [
518
+ f"<div class='xr-obj-type'>xarray.{ type (node ).__name__ } </div>" ,
519
+ ]
520
+ if node .name is not None :
521
+ name = escape (repr (node .name ))
522
+ header_components .append (f"<div class='xr-obj-name'>{ name } </div>" )
506
523
507
- def datatree_repr (dt : DataTree ) -> str :
508
- obj_type = f"xarray.{ type (dt ).__name__ } "
509
- return datatree_node_repr (obj_type , dt , show_inherited = True )
524
+ sections = datatree_node_sections (node , root = True )
525
+ return _obj_repr (node , header_components , sections )
0 commit comments