+
+ public final static Map<Long, Integer> calculateDepths( final Phylogeny phy ) {
+ final Map<Long, Integer> depths = new HashMap<Long, Integer>();
+ calculateDepthsHelper( phy.getRoot(), 0, depths );
+ return depths;
+ }
+
+ private final static void calculateDepthsHelper( final PhylogenyNode n, int d, final Map<Long, Integer> depths ) {
+ depths.put( n.getId(), d );
+ ++d;
+ final List<PhylogenyNode> descs = n.getDescendants();
+ for( final PhylogenyNode desc : descs ) {
+ calculateDepthsHelper( desc, d, depths );
+ }
+ }
+
+ public final static void collapseToDepth( final Phylogeny phy, final int depth ) {
+ if ( phy.getNumberOfExternalNodes() < 3 ) {
+ return;
+ }
+ collapseToDepthHelper( phy.getRoot(), 0, depth );
+ }
+
+ private final static void collapseToDepthHelper( final PhylogenyNode n, int d, final int depth ) {
+ if ( n.isExternal() ) {
+ n.setCollapse( false );
+ return;
+ }
+ if ( d >= depth ) {
+ n.setCollapse( true );
+ final PhylogenyNodeIterator it = new PreorderTreeIterator( n );
+ while ( it.hasNext() ) {
+ it.next().setCollapse( true );
+ }
+ }
+ else {
+ n.setCollapse( false );
+ ++d;
+ final List<PhylogenyNode> descs = n.getDescendants();
+ for( final PhylogenyNode desc : descs ) {
+ collapseToDepthHelper( desc, d, depth );
+ }
+ }
+ }
+
+
+
+ public final static void collapseToRank( final Phylogeny phy, final int rank ) {
+ if ( phy.getNumberOfExternalNodes() < 3 ) {
+ return;
+ }
+ if ( rank < 0 || rank >= TaxonomyUtil.RANKS.length ) {
+ throw new IllegalArgumentException( "Rank " + rank + " is out of range" );
+ }
+ collapseToRankHelper( phy.getRoot(), rank );
+ }
+
+ private final static void collapseToRankHelper( final PhylogenyNode n, final int target_rank ) {
+ if ( n.isExternal() ) {
+ n.setCollapse( false );
+ return;
+ }
+ if ( ( n.getNodeData().getTaxonomy() != null )
+ && !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getRank() ) ) {
+ final String current_rank = n.getNodeData().getTaxonomy().getRank();
+ if ( !TaxonomyUtil.RANK_TO_INT.containsKey( current_rank ) ) {
+ System.out.println( "Don't know rank \"" + current_rank + "\", ignoring." );
+ }
+ else {
+ if ( TaxonomyUtil.RANK_TO_INT.get( current_rank ) >= target_rank ) {
+ n.setCollapse( true );
+
+ final PhylogenyNodeIterator it = new PreorderTreeIterator( n );
+ while ( it.hasNext() ) {
+ it.next().setCollapse( true );
+ }
+ return;
+ }
+ }
+ }
+ n.setCollapse( false );
+ final List<PhylogenyNode> descs = n.getDescendants();
+ for( final PhylogenyNode desc : descs ) {
+ collapseToRankHelper( desc, target_rank );
+ }
+ }
+
+ public final static PhylogenyNode getFirstExternalNode( final PhylogenyNode node ) {
+ PhylogenyNode n = node;
+ while ( n.isInternal() ) {
+ n = n.getFirstChildNode();
+ }
+ return n;
+ }
+
+ public final static PhylogenyNode getLastExternalNode( final PhylogenyNode node ) {
+ PhylogenyNode n = node;
+ while ( n.isInternal() ) {
+ n = n.getLastChildNode();
+ }
+ return n;
+ }
+
+ public final static boolean isHasCollapsedNodes( final Phylogeny phy ) {
+ for( final PhylogenyNodeIterator iter = phy.iteratorPreorder(); iter.hasNext(); ) {
+ final PhylogenyNode n = iter.next();
+ if ( !n.isExternal() && ( n.isCollapse() ) ) {
+ return true;
+ }
+ }
+ return false;
+ }
+