Пример #1
0
 /**
  * Copy the list of nodes that need copying when adding a new split into a network.
  *
  * @param nodesToCopy ArrayList of nodes in the network that need to be copied
  * @param network Network we are working in
  * @param incompatibleEdges Edges that are in the path that joins up the nodes that are being
  *     copied
  * @param splitToAdd Split that we are currently adding in by copying these nodes
  */
 public void CopyNode(
     ArrayList<CNetworkNode> nodesToCopy,
     CNetworkSplit splitToAdd,
     CNetwork network,
     ArrayList<CNetworkEdge> incompatibleEdges) {
   // Copy Node:
   for (CNetworkNode nodeToCopy : nodesToCopy) {
     CNetworkNode newNode = new CNetworkNode();
     // create a new node with a name that indicates it has been added (we can output node names by
     // modifying later code)
     newNode.Taxaname = "added0" + Integer.toString(network.nodes.size());
     // below should NEVER happen... but will leave in just in case as was at one time an issue:
     if (nodeToCopy == null || newNode == null) {
       System.out.println("Null pointer in terms of node that we want to copy to...");
     }
     // Reference the new node on the old one
     nodeToCopy.CopiedToNode = newNode;
     // Add new node to network
     network.nodes.add(newNode);
     // Add an edge between old and new node
     CNetworkEdge edgeToAdd = new CNetworkEdge();
     edgeToAdd.networkNodeA = newNode;
     edgeToAdd.networkNodeB = nodeToCopy;
     edgeToAdd.split = splitToAdd;
     splitToAdd.edges.add(edgeToAdd);
   }
   // Go through and move links over depending on which side the splits are a subset of.
   for (CNetworkNode nodeToCopy : nodesToCopy) {
     // look at each join on each old node
     for (int i = 0; i < nodeToCopy.joins.size(); i++) {
       CNetworkEdge edgeToConsider = nodeToCopy.joins.get(i);
       // if it joins another copied node then we will duplicate the edge later...
       if (edgeToConsider.networkNodeA.CopiedToNode == null
           || edgeToConsider.networkNodeB.CopiedToNode == null) {
         // if on "0" side of new split then keep it, otherwise move it to the new node.
         if (splitToAdd.OnZeroSide(edgeToConsider.split, noOfTaxa) == false) {
           // Replace the appropriate edge reference...
           if (edgeToConsider.networkNodeA == nodeToCopy) {
             edgeToConsider.networkNodeA = nodeToCopy.CopiedToNode;
             // System.out.println("moved link to "+edgeToConsider.networkNodeB.Taxaname+" from
             // "+nodeToCopy.Taxaname+" to "+nodeToCopy.CopiedToNode.Taxaname);
           } else if (edgeToConsider.networkNodeB == nodeToCopy) {
             edgeToConsider.networkNodeB = nodeToCopy.CopiedToNode;
             // System.out.println("moved link to "+edgeToConsider.networkNodeA.Taxaname+" from
             // "+nodeToCopy.Taxaname+" to "+nodeToCopy.CopiedToNode.Taxaname);
           }
           // Add it to the new node list
           nodeToCopy.CopiedToNode.joins.add(edgeToConsider);
           // delete it from the list of the old nodes:
           nodeToCopy.joins.remove(i);
           // go back one in the list!
           i--;
         }
       }
     }
   }
   // Add in the edges between copied nodes to the old nodes to their node join lists now we have
   // done all the moving about!
   for (CNetworkEdge edgeToLink : splitToAdd.edges) {
     edgeToLink.networkNodeA.joins.add(edgeToLink);
     edgeToLink.networkNodeB.joins.add(edgeToLink);
   }
   // Add in the edges to the copied nodes that are in the list of incompatible splits.
   for (CNetworkEdge incompatibleEdge : incompatibleEdges) {
     // Check to see if we have an edge that is incompatible (this SHOULD always be the case... )
     if (incompatibleEdge.networkNodeA.CopiedToNode != null
         && incompatibleEdge.networkNodeB.CopiedToNode != null) {
       // Create new edge
       CNetworkEdge newEdge = new CNetworkEdge();
       // Update node info.
       newEdge.networkNodeA = incompatibleEdge.networkNodeA.CopiedToNode;
       newEdge.networkNodeB = incompatibleEdge.networkNodeB.CopiedToNode;
       newEdge.networkNodeA.joins.add(newEdge);
       newEdge.networkNodeB.joins.add(newEdge);
       // Update split info.
       newEdge.split = incompatibleEdge.split;
       incompatibleEdge.split.edges.add(newEdge);
     }
   }
   // Now remove the CopiedToNode link now we are done...
   for (CNetworkNode nodeToCopy : nodesToCopy) {
     nodeToCopy.CopiedToNode = null;
   }
 }
Пример #2
0
  /**
   * Constructs the network beginning with the consensus tree and then calls the network drawing
   * function to calculate positions
   *
   * @param tree Consensus tree already calculated
   */
  public CNetwork constructNetwork(CTree tree) {
    // Create a new network...
    CNetwork network = new CNetwork(noOfTaxa);
    // Let's copy over all of the splits from the tree into the network format.
    // Until noted, the node lists in tree and network MUST match and the first lot of nodes (after
    // the root) in the tree are assumed to be the taxa.
    for (int i = 0; i < tree.nodeList.size(); i++) {
      TreeNode treeNode = tree.nodeList.get(i);
      // create a new node
      CNetworkNode networkNode = new CNetworkNode();
      // copy over the required data and add it...
      networkNode.Taxaname = treeNode.name;
      network.nodes.add(networkNode);
    }
    // Now add in the splits... (ignore 1st cluster as is for star tree)
    for (int i = 1; i < tree.clusters.size(); i++) {
      Cluster cluster = tree.clusters.get(i);
      if (cluster.isMajority == true) {
        CNetworkSplit networkSplit = new CNetworkSplit();
        CNetworkEdge networkEdge = new CNetworkEdge();
        networkEdge.split = networkSplit;
        networkEdge.networkNodeA = network.nodes.get(cluster.nodeRefA);
        networkEdge.networkNodeB = network.nodes.get(cluster.nodeRefB);
        networkSplit.edges.add(networkEdge);
        // Maybe we shouldn't be copying this over... but it at least clarifies things in code.
        networkSplit.edgelength = cluster.edgeLength;
        networkSplit.noOfOccurences = cluster.noOfOccurrences;
        networkSplit.split = cluster.aboveSplit;
        network.nodes.get(cluster.nodeRefA).joins.add(networkEdge);
        network.nodes.get(cluster.nodeRefB).joins.add(networkEdge);
        network.splits.add(networkSplit);
        cluster.added = true;
      }
    }
    // Now add in the taxa length splits.... NOTE i=0 is root?!  Tried and tested anyway...
    for (int i = 1; i <= noOfTaxa; i++) {
      CNetworkSplit networkSplit = new CNetworkSplit();
      CNetworkEdge networkEdge = new CNetworkEdge();
      networkEdge.split = networkSplit;
      int taxonParent = tree.parentList.get(tree.nodeList.get(i).name);
      networkEdge.networkNodeA = network.nodes.get(taxonParent);
      networkEdge.networkNodeB = network.nodes.get(i);
      networkSplit.edges.add(networkEdge);
      networkSplit.edgelength = tree.nodeList.get(i).edgeLength;
      networkSplit.noOfOccurences = noOfTrees;
      BitSet trivialSplit = new BitSet(noOfTaxa);
      trivialSplit.set(i - 1);
      networkSplit.split = trivialSplit;
      network.nodes.get(taxonParent).joins.add(networkEdge);
      network.nodes.get(i).joins.add(networkEdge);
      network.splits.add(networkSplit);
    }
    // NOTE: From now on the indices on Network & Tree may no longer match!!
    // Remove the root if it is simply disecting an edge (only 2 edges on either side).
    // NOTE: root is assumed to be the first position in the node list in CNetwork and CTree
    if (network.nodes.get(0).joins.size() == 2) {
      // find the nodes on either side of the root...
      CNetworkNode[] redundant = new CNetworkNode[2];
      for (int h = 0; h < 2; h++) {
        if (network.nodes.get(0).joins.get(h).networkNodeA == network.nodes.get(0)) {
          redundant[h] = network.nodes.get(0).joins.get(h).networkNodeB;
        } else {
          redundant[h] = network.nodes.get(0).joins.get(h).networkNodeA;
        }
      }
      // correct the edge in the one list to go to the zero node.
      if (network.nodes.get(0).joins.get(1).networkNodeA == network.nodes.get(0)) {
        network.nodes.get(0).joins.get(1).networkNodeA = redundant[0];
      } else {
        network.nodes.get(0).joins.get(1).networkNodeB = redundant[0];
      }
      // find the edge in the list in zero and remove it..
      for (int h = 0; h < redundant[0].joins.size(); h++) {
        if (redundant[0].joins.get(h).networkNodeA == network.nodes.get(0)
            || redundant[0].joins.get(h).networkNodeB == network.nodes.get(0)) {
          redundant[0].joins.remove(h);
          h--;
        }
      }
      // remove the edge from the split list
      for (int h = 0; h < network.nodes.get(0).joins.get(0).split.edges.size(); h++) {
        if (network.nodes.get(0).joins.get(0).split.edges.get(h)
            == network.nodes.get(0).joins.get(0)) {
          network.nodes.get(0).joins.get(0).split.edges.remove(h);
          h--;
        }
      }
      // add the other edge in the zero list
      redundant[0].joins.add(network.nodes.get(0).joins.get(1));
      // remove the node at last, and any reference to the removed edge also goes!
      network.nodes.remove(0);
    }

    // TODO: Optional: sort the list in terms of frequency of occurrence to select only most
    // frequent if less than 33.34% occurences....!
    // IGNORE the first one as it is the star network...
    // Now let's go through the remaining splits and try and add them into the network.
    for (int i = 0; i < tree.clusters.size(); i++) {
      Cluster cluster = tree.clusters.get(i);
      // for clusters that haven't been added yet, let's add them...
      if (cluster.added == false) {
        // define new split and copy over info.
        CNetworkSplit addSplit = new CNetworkSplit();
        addSplit.split = cluster.aboveSplit;
        addSplit.edgelength = cluster.edgeLength;
        // now findout if is incompatible with any existing splits in the network
        ArrayList<CNetworkSplit> incompatibleSplits = new ArrayList<CNetworkSplit>();
        for (CNetworkSplit compSplit : network.splits) {
          if (compSplit.isCompatible(addSplit, noOfTaxa) == false) {
            incompatibleSplits.add(compSplit);
          }
        }
        // Now we need to find the nodes we need to copy, so create a list of them
        ArrayList<CNetworkNode> nodesToCopy = new ArrayList<CNetworkNode>();
        // go through the incompatible splits one by one and add them to chains.
        ArrayList<CNetworkPath> chains = new ArrayList<CNetworkPath>();
        // note all nodes that will be stored in paths for more efficient path claering up
        ArrayList<CNetworkNode> nodesToClearUp = new ArrayList<CNetworkNode>();
        // Loop through incompatible splits
        for (CNetworkSplit currentSplit : incompatibleSplits) {
          // Loop through all the edges in this split
          for (CNetworkEdge currentEdge : currentSplit.edges) {
            // create a new path and add it to the list...
            CNetworkPath newPath = new CNetworkPath();
            newPath.pathOfEdges.add(currentEdge);
            newPath.pathOfNodes.add(currentEdge.networkNodeA);
            newPath.pathOfNodes.add(currentEdge.networkNodeB);
            currentEdge.networkNodeA.AddToPaths(newPath, nodesToClearUp);
            currentEdge.networkNodeB.AddToPaths(newPath, nodesToClearUp);
            chains.add(newPath);
            // Now extend any existing paths...
            // create a list of paths to extend found paths with...
            ArrayList<CNetworkPath> extendPathsWith = new ArrayList<CNetworkPath>();
            extendPathsWith.add(newPath);
            // Hack to go from NodeA & NodeB to a for loop...
            CNetworkNode[] edgeNodes =
                new CNetworkNode[] {currentEdge.networkNodeA, currentEdge.networkNodeB};
            // For the first node, add the standard
            for (int l = 0; l <= 1; l++) {
              // get ready to make this part of the nodes with paths to clear up... (should be
              // already done?)
              if (edgeNodes[l].paths.isEmpty() == true) {
                nodesToClearUp.add(edgeNodes[l]);
              }
              // Look at each path that the node is involved in...
              int pathCount = edgeNodes[l].paths.size();
              for (int g = 0; g < pathCount; g++) {
                CNetworkPath currentPath = edgeNodes[l].paths.get(g);
                // for the case that we may want to add the edge to the start/end of a path on the
                // node...
                if (currentPath.endNode() == edgeNodes[l]
                    || currentPath.startNode() == edgeNodes[l]) {
                  // check we haven't already added this split yet...
                  if (currentPath.checkForSplit(currentEdge) == false) {
                    // create a new combined path with all paths to extend with...
                    // Don't forget to make this add the new path to all the nodes as well as
                    // combining over the correct node & removing one instance of it...
                    for (CNetworkPath pathToAdd : extendPathsWith) {
                      chains.add(currentPath.combineWith(pathToAdd, edgeNodes[l]));
                    }
                  }
                }
              }
            }
          }
        }
        for (CNetworkNode nodeToClearUp : nodesToClearUp) {
          nodeToClearUp.paths.clear();
        }
        ArrayList<CNetworkEdge> incompatibleEdges = new ArrayList<CNetworkEdge>();
        // Case that there are no incompatible splits... just add in the split!
        // Note that SOME splits appear to contain the whole tree (perhaps due to a hack earlier),
        // so lets just ignore these....  This could be described as a hack induced hack...
        if (incompatibleSplits.isEmpty() == true
            && (addSplit.split.cardinality() != noOfTaxa && addSplit.split.cardinality() != 0)) {
          // we have no idea which taxon is actually on the side we want, but we will use some cool
          // functions of BitSet to help reduce the time it takes...
          CNetworkNode beginNode;
          // Start searching from the adding side of the split containing zeros?
          boolean zeroSide;
          if (addSplit.split.cardinality() <= (noOfTaxa) / 2) {
            // if there are more set to 0 than 1 go from a taxon on the 1 side:
            // Search through the nodes for this using predefined function...
            beginNode = TaxonRefToNode(addSplit.split.nextSetBit(0), network);
            zeroSide = false;
          } else {
            // if there are more set to 1 than 0, then go from a taxon on the 0 side:
            beginNode = TaxonRefToNode(addSplit.split.nextClearBit(0), network);
            zeroSide = true;
          }
          // recursively go along the edges until a node is found that has an edge that satisfies.
          ArrayList<CNetworkNode> consideredNodes = new ArrayList<CNetworkNode>();
          CNetworkNode CopyNode2 =
              beginNode.findFirstNonSubset(addSplit, consideredNodes, zeroSide, noOfTaxa);
          nodesToCopy.add(CopyNode2);
        } else {
          // Copy over the list of nodes from the longest path...ERROR if we have a too big path...
          if (chains.size() > 0) {
            // Store the max paths...
            ArrayList<CNetworkPath> currentMaxPaths = new ArrayList<CNetworkPath>();
            // initialise with first one, which only serves as to store length...:
            currentMaxPaths.add(chains.get(0));
            for (CNetworkPath chain : chains) {
              if (chain.pathOfNodes.size() > currentMaxPaths.get(0).pathOfNodes.size()) {
                currentMaxPaths.clear();
                currentMaxPaths.add(chain);
              }
              // Yes, still add it if we already added it!
              if (chain.pathOfNodes.size() == currentMaxPaths.get(0).pathOfNodes.size()) {
                currentMaxPaths.add(chain);
              }
            }
            // now remove any max path that requires all edges to be copied or none at all...
            for (int m = 1; m < currentMaxPaths.size(); m++) {
              if (currentMaxPaths.get(m).isSplitSide(addSplit, noOfTaxa) == false) {
                currentMaxPaths.remove(m);
                m--;
              }
            }
            if (currentMaxPaths.size() > 2) {
              // ERROR!!! Now in >2d....!
              System.out.println("Potential Error: Network now in > 2 dimensions....!");
            }
            // Now create the copyNode list:
            // Store those that have been copied.... err
            // Go through all the paths
            // DOES START AT 1 as first just stored length!
            for (int m = 1; m < currentMaxPaths.size(); m++) {
              incompatibleEdges.addAll(currentMaxPaths.get(m).pathOfEdges);
              CNetworkPath currentMaxPath = currentMaxPaths.get(m);
              // Go through all the nodes
              for (CNetworkNode currentNodeCopy : currentMaxPath.pathOfNodes) {
                if (currentNodeCopy.consideration == false) {
                  currentNodeCopy.consideration = true;
                  nodesToCopy.add(currentNodeCopy);
                }
              }
            }
            // remove the considered flag from the node:
            for (CNetworkNode currentNodeClean : nodesToCopy) {
              currentNodeClean.consideration = false;
            }
          }
        }
        // actually call the function that copies the nodes
        CopyNode(nodesToCopy, addSplit, network, incompatibleEdges);
        // and add the new split at last to the network.
        network.splits.add(addSplit);
      }
    }
    // fill in the network positions (hopefully)...
    network.FindPositions(noOfTaxa);
    // printDetails(tree,network);
    return network;
  }