Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

This tutorial will guide you through adding a new example command to PhyloNet that can be executed from within the PhyloNet PHYLONET block of a NEXUS file.

Step 1. Prepare Existing Source

...

Code Block
package com.example;

import edu.rice.cs.bioinfo.programs.phylonet.commands.*;
import edu.rice.cs.bioinfo.library.language.pyson._1_0.ir.blockcontents.*;
import edu.rice.cs.bioinfo.library.language.richnewick._1_0.ast.*;
import edu.rice.cs.bioinfo.library.programming.*;
import java.io.*;
import java.util.*;

public class CountNodes extends CommandBase
{
   public CountNodes(SyntaxCommand motivatingCommand, ArrayList<Parameter> params, 
                     Map<String,NetworkNonEmpty>  sourceIdentToNetwork, Proc3<String, Integer, Integer> errorDetected)
    {
      super(motivatingCommand, params, sourceIdentToNetwork, errorDetected); 
    }
    ...
}

Your first step should be to provide the illustrated public four argument constructor with corresponding call to super. When your command is encountered in a PhyloNet block, it is this constructor that will be called to create your command.

...

Code Block
protected boolean checkParamsForCommand()
{
   int expectedNetworkNameParameterIndex = 0; // network ident should be first parameter in command.

   // automatically checks for network existance and reports any errors to this.errorDetected.
   NetworkNonEmpty network = this.assertAndGetNetwork(expectedNetworkNameParameterIndex); 
      
   if(network == null) // user specified network name is invalid
   {
       return false;
   }
  _networkToScan = network; // added field to class to retain network to scan.
  return true;
      
}

Note that we have added a field to our class _networkToScan to point to the user specified network to scan. This will be useful in our next step.

...

Code Block
protected void executeCommandHelp(Proc<String> displayResult) throws IOException
{
    String eNewickNetwork = NetworkTransformer.toENewick(_networkToScan); // convert NEXUS network to extended newick string
    
    /*
     * convert extended network string to Network
     */
    edu.rice.cs.bioinfo.programs.phylonet.structs.network.io.ExNewickReader<String> enr = 
      new edu.rice.cs.bioinfo.programs.phylonet.structs.network.io.ExNewickReader<String>(
          newStringReader(eNewickNetwork));
    
    edu.rice.cs.bioinfo.programs.phylonet.structs.network.Network<String> net;
    try
    {
      net = enr.readNetwork();
    }
    catch(Exception e)
    {
      throw new RuntimeException(e);
    }
    
    /*
     * count and display number of nodes in network
     */
    Iterable<edu.rice.cs.bioinfo.programs.phylonet.structs.network.NetNode<String>> allNodes = net.dfs();
    int nodeCount = 0;
    for(Object node : net.dfs())
    {
      nodeCount++;
    }
    
    displayResult.execute("\nNetwork contains " + nodeCount + " nodes.");
}

...

The next step is to update edu.rice.cs.bioinfo.programs.phylonet.commands.CommandFactory to construct instances of the CountNodes command. When examining the existing structure of the CommandFactory you will discover an if/else if chain within the make method:

Code Block


public class CommandFactory {



    public static Command make(SyntaxCommand directive, Map<String,NetworkNonEmpty> sourceIdentToNetwork, 
                               Proc3<String, Integer, Integer> errorDetected, Random rand)
    {
        ...

        if(lowerCommandName.equals("symmetricdifference") || lowerCommandName.equals("rf"))
        {
            return new SymmetricDifference(directive, params, sourceIdentToNetwork, errorDetected);
        }
        else if(lowerCommandName.equals("lca"))
        {
            return new LCA(directive, params, sourceIdentToNetwork, errorDetected);
        }
        ...
    }

...

Code Block
public class CommandFactory {



    public static Command make(SyntaxCommand directive, Map<String,NetworkNonEmpty> sourceIdentToNetwork, 
                               Proc3<String, Integer, Integer> errorDetected, Random rand)
    {
        ...
        else if(lowerCommandName.equals("nexus_out"))
        {
            return new NexusOut(directive, params, sourceIdentToNetwork, errorDetected);
        }
        else if(lowerCommandName.equals("countnodes"))
        {
           return new CountNodes(directive, params, sourceIdentToNetwork, errorDetected);
        }
        ...

...

At this point inclusion of a new command is complete. After recompiling PhyloNet the new command should be available. For example, the following NEXUS file will now be processed by PhyloNet:

Code Block
langhtml

#NEXUS

BEGIN NETWORKS;

Network net = ((a,(b,(c)x#1)M)N,((x#1,d)J,e)Z)R;

END;


BEGIN PHYLONET;

CountNodes net;

END;