Skip to content

Conversation

@gloriayma
Copy link
Collaborator

Rewrite of small_parsimony in tools module to work with TreeData

@codecov
Copy link

codecov bot commented Oct 23, 2025

Codecov Report

❌ Patch coverage is 74.40000% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.71%. Comparing base (2d024f1) to head (74c01b6).
⚠️ Report is 17 commits behind head on 3.0.0.

Files with missing lines Patch % Lines
src/cassiopeia/utils.py 45.83% 26 Missing ⚠️
src/cassiopeia/tools/small_parsimony.py 92.20% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            3.0.0     #276      +/-   ##
==========================================
- Coverage   84.94%   84.71%   -0.24%     
==========================================
  Files          76       76              
  Lines        5773     5881     +108     
==========================================
+ Hits         4904     4982      +78     
- Misses        869      899      +30     
Files with missing lines Coverage Δ
src/cassiopeia/tools/small_parsimony.py 96.12% <92.20%> (-2.38%) ⬇️
src/cassiopeia/utils.py 77.41% <45.83%> (-19.99%) ⬇️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@gloriayma gloriayma changed the base branch from master to 3.0.0 October 23, 2025 19:19
@mattjones315 mattjones315 self-requested a review October 30, 2025 19:17
@gloriayma gloriayma requested a review from colganwi October 30, 2025 19:49
Copy link
Collaborator

@colganwi colganwi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gloriayma were getting close! I've updated the tests to use pytest and treedata. Please review the failing tests and update your code accordingly. You should be updating the tests as you go to ensure that all added functionality is covered.

The major changes here are converting fitch_hartigan_bottom_up and fitch_hartigan_top_down to private methods that take an nx.DiGraph as input. The fitch_hartigan, score_small_parsimony, and fitch_count functions should all have

g, _ = _get_digraph(tree, treedata_key)

as the first line. This change will make these functions easier to implement since you won't have to think about the type of the tree variable.

Returns:
A new CassiopeiaTree if the copy is set to True, else None.
A new CassiopeiaTree/TreeData/nx DiGraph + meta_df if the copy is set to True, else None.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does not return meta_df so this should be removed from the docstring

return tree if copy else None


def fitch_hartigan_bottom_up(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make this a private _ method. It should only accept nx.Digraph as input. So you will need to call _get_digraph in fitch count rather than fitch_hartigan_bottom_up.

This will simplify the logic and remove redundant code.

if is_numeric_dtype(meta):
raise CassiopeiaError("Meta item is not a categorical variable.")

if not is_categorical_dtype(meta):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DeprecationWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, pd.CategoricalDtype) instead

return tree if copy else None


def fitch_hartigan_top_down(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as bottom_up. Private method that accepts nx.Digraph


parsimony = 0
for parent, child in cassiopeia_tree.depth_first_traverse_edges(source=root):
for parent, child in tree.depth_first_traverse_edges(source=root):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If tree is a TreeData object this will fail because TreeData does not have a depth_first_traverse_edges method.

if root != cassiopeia_tree.root:
cassiopeia_tree.subset_clade(root)
if root != tree.root:
tree.subset_clade(root)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nx does not have a subset_clade method. Use this instead:

tree = tree.subgraph(nx.descendants(tree, root) | {root}).copy()

)


def _set_attribute_treelike(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this helper since we will always be working with nx.DiGraphs

tree.nodes[attribute_name] = value

raise TypeError("Unsupported tree type. Must be CassiopeiaTree or TreeData.")


def _get_attribute_treelike(tree: TreeLike, node: str, attribute_name: str) -> Any:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again this is easy with nx

raise TypeError("Unsupported tree type. Must be CassiopeiaTree or TreeData.")


def _get_children_treelike(tree: TreeLike, node: str, tree_key: str | None = None) -> list[str]:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a one liner with nx

list(G.successors(node))

@gloriayma
Copy link
Collaborator Author

tests currently failing because fitch_hartigan doesn't support TreeData correctly.
small_parsimony should work if fitch_hartigan works
pausing work until we figure out what to do with fitch_hartigan

@mattjones315 mattjones315 removed their request for review November 4, 2025 22:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants