From d5348e2ac6c250b1f713961d0dc5bffb80c1fae9 Mon Sep 17 00:00:00 2001 From: Thomas Nicholas Date: Wed, 25 Oct 2023 13:47:17 -0400 Subject: [PATCH 1/5] tests --- datatree/tests/test_datatree.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/datatree/tests/test_datatree.py b/datatree/tests/test_datatree.py index 9dd601c8..e9f373d7 100644 --- a/datatree/tests/test_datatree.py +++ b/datatree/tests/test_datatree.py @@ -136,6 +136,16 @@ def test_has_data(self): john = DataTree(name="john", data=None) assert not john.has_data + def test_is_hollow(self): + john = DataTree(data=xr.Dataset({"a": 0})) + assert john.is_hollow + + eve = DataTree(children={"john": john}) + assert eve.is_hollow + + eve.ds = xr.Dataset({"a": 1}) + assert not eve.is_hollow + class TestVariablesChildrenNameCollisions: def test_parent_already_has_variable_with_childs_name(self): From 2ab6cc8f1e48f83710c32403c12e54202464362e Mon Sep 17 00:00:00 2001 From: Thomas Nicholas Date: Wed, 25 Oct 2023 13:47:28 -0400 Subject: [PATCH 2/5] implementation --- datatree/datatree.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/datatree/datatree.py b/datatree/datatree.py index f2618d2a..52049f47 100644 --- a/datatree/datatree.py +++ b/datatree/datatree.py @@ -505,6 +505,11 @@ def is_empty(self) -> bool: """False if node contains any data or attrs. Does not look at children.""" return not (self.has_data or self.has_attrs) + @property + def is_hollow(self) -> bool: + """True if only leaf nodes contain data.""" + return not any(node.has_data for node in self.subtree if not node.is_leaf) + @property def variables(self) -> Mapping[Hashable, Variable]: """Low level interface to node contents as dict of Variable objects. From 05aa145decda00e68025d05b80e82cc9297344a2 Mon Sep 17 00:00:00 2001 From: Thomas Nicholas Date: Wed, 25 Oct 2023 13:47:40 -0400 Subject: [PATCH 3/5] API docs --- docs/source/api.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/api.rst b/docs/source/api.rst index 54a98639..215105ef 100644 --- a/docs/source/api.rst +++ b/docs/source/api.rst @@ -64,6 +64,7 @@ This interface echoes that of ``xarray.Dataset``. DataTree.has_data DataTree.has_attrs DataTree.is_empty + DataTree.is_hollow .. From c48325399585cb0e6660a3c94da4278d3110c515 Mon Sep 17 00:00:00 2001 From: Thomas Nicholas Date: Wed, 25 Oct 2023 13:47:54 -0400 Subject: [PATCH 4/5] narrative docs --- docs/source/hierarchical-data.rst | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/source/hierarchical-data.rst b/docs/source/hierarchical-data.rst index f74a635d..51bcea56 100644 --- a/docs/source/hierarchical-data.rst +++ b/docs/source/hierarchical-data.rst @@ -369,6 +369,25 @@ You can see this tree is similar to the ``dt`` object above, except that it is m (If you want to keep the name of the root node, you will need to add the ``name`` kwarg to :py:class:`from_dict`, i.e. ``DataTree.from_dict(non_empty_nodes, name=dt.root.name)``.) +.. _Tree Contents: + +Tree Contents +------------- + +Hollow Trees +~~~~~~~~~~~~ + +A concept that can sometimes be useful is that of a "Hollow Tree", which means a tree with data stored only at the leaf nodes. +This is useful because certain useful tree manipulation operations only make sense for hollow trees. + +You can check if a tree is a hollow tree by using the :py:meth:`~DataTree.is_hollow` property. +We can see that the Simpson's family is not hollow because the data variable ``"age"`` is present at some nodes which +have children (i.e. Abe and Homer). + +.. ipython:: python + + simpsons.is_hollow + .. _manipulating trees: Manipulating Trees From cdeadd957458df60a77975e1c173abb775a9e107 Mon Sep 17 00:00:00 2001 From: Thomas Nicholas Date: Wed, 25 Oct 2023 13:53:10 -0400 Subject: [PATCH 5/5] whatsnew --- docs/source/whats-new.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/whats-new.rst b/docs/source/whats-new.rst index eb2c0340..e62c4379 100644 --- a/docs/source/whats-new.rst +++ b/docs/source/whats-new.rst @@ -25,6 +25,8 @@ New Features - New :py:meth:`DataTree.match` method for glob-like pattern matching of node paths. (:pull:`267`) By `Tom Nicholas `_. +- New :py:meth:`DataTree.is_hollow` property for checking if data is only contained at the leaf nodes. (:pull:`272`) + By `Tom Nicholas `_. - Indicate which node caused the problem if error encountered while applying user function using :py:func:`map_over_subtree` (:issue:`190`, :pull:`264`). Only works when using python 3.11 or later. By `Tom Nicholas `_.