code: def uppass(tree, feature):
      
  
      ps_feature = get_personalized_feature_name(feature, BU_PARS_STATES)
  
      for node in tree.traverse('postorder'):
          if not node.is_leaf():
              children_states = get_most_common_states(getattr(child, ps_feature) for child in node.children)
              node_states = getattr(node, ps_feature)
              state_intersection = node_states & children_states
              node.add_feature(ps_feature, state_intersection if state_intersection else node_states)
docs: UPPASS traverses the tree starting from the tips and going up till the root,
      and assigns to each parent node a state based on the states of its child nodes.
  
      if N is a tip:
      S(N) <- state of N
      else:
        L, R <- left and right children of N
        UPPASS(L)
        UPPASS(R)
        if S(L) intersects with S(R):
           S(N) <- intersection(S(L), S(R))
        else:
           S(N) <- union(S(L), S(R))
  
      :param tree: ete3.Tree, the tree of interest
      :param feature: str, character for which the parsimonious states are reconstructed
      :return: void, adds get_personalized_feature_name(feature, BU_PARS_STATES) feature to the tree nodes