package statalign.base; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import javax.swing.SwingUtilities; import mpi.MPI; import statalign.MPIUtils; import statalign.base.mcmc.StatAlignMcmc; import statalign.base.mcmc.StatAlignParallelMcmc; import statalign.base.thread.MainThread; import statalign.base.thread.StoppedException; import statalign.io.DataManager; import statalign.io.RawSequences; import statalign.model.ext.ModelExtManager; import statalign.model.subst.SubstitutionModel; import statalign.postprocess.Postprocess; import statalign.postprocess.PostprocessManager; import statalign.postprocess.gui.InputGUI; import statalign.ui.MainFrame; /** * * This is the central class in the information flow amongst classes. * * This class also manages the main thread that runs the MCMC. * * @author miklos, novak * */ public class MainManager { /** * Reference to all input data required to run StatAlign */ public InputData inputData = new InputData(); /** * This is the postprocess-manager of our program, which handles the * postprocesses applied on the MCMC run. */ public PostprocessManager postProcMan; /** * Data manager that handles all input files. */ public DataManager dataMan; /** * Manager for model extension plugins */ public ModelExtManager modelExtMan; /** * Array of substitution model classes that can be selected for an analysis. */ public Class<? extends SubstitutionModel>[] substModels; /** * The main window of the program. */ public MainFrame frame; /** * The graphical interface of the Input panel */ public InputGUI inputgui; /** * Main (background) calculation thread of the application */ public MainThread thread; /** * The full path of the input file from which we read the sequences. */ public String fullPath; /** * After adding on extensions from ModelExtension objects. */ public String fullPathWithExtensions; /** * Alignment formats in which StatAlign can generate output * * Implemented formats currently are <tt>StatAlign</tt> (our own format), * <tt>Clustal</tt>, <tt>Fasta</tt>, <tt>Phylip</tt>, <tt>Nexus</tt> */ public static String[] alignmentTypes = new String[] { "Fasta", "StatAlign", "Clustal", "Phylip", "Nexus" }; /** * A trivial constructor that only sets <tt>MainFrame</tt> and substModels. * * The MainFrame creates its MainManager, and the MainManager knows who is * its owner MainFrame, so it can access GUIs on the MainFrame * * @param frame * The owner of the MainManager, the main window of the graphical * interface. */ public MainManager(MainFrame frame) { this.frame = frame; postProcMan = new PostprocessManager(this); dataMan = new DataManager(); dataMan.init(); modelExtMan = new ModelExtManager(this); } /** * Initialises submanagers after the command line has been processed. This is separated from * the constructor as some plugins require input from the command line. * @param params plugin parameters */ public void init(ArrayList<String> args) { modelExtMan.init(args); postProcMan.init(modelExtMan); } /** * This function starts a new MCMC run. * * It asks files for writing outputs, and it launches a <tt>MainThread</tt> * that handles the MCMC run. */ public void start() { try { String filenameExtension = modelExtMan.getFilenameExtension(); if (!filenameExtension.isEmpty()) { filenameExtension += "."; } postProcMan.logFile = new FileWriter(fullPath + "." + filenameExtension + "log"); postProcMan.setBaseFileName(fullPath + "." + filenameExtension); postProcMan.createPluginFiles(); thread = new MainThread(this); thread.start(); } catch (IOException e) { e.printStackTrace(); } } public void startParallel(int noOfProcesses, int rank) { // TODO: Parallel GUI. if (frame != null) { frame.statusText.setText(" Generating initial tree and alignment..."); } // Sets up the logging for the master process. if (MPIUtils.isMaster(rank)) { MPIUtils.println(rank, "Setting up log files for the plugins:"); try { postProcMan.logFile = new FileWriter(fullPath + ".log"); for (Postprocess p : postProcMan.getPlugins()) { if (p.postprocessWrite) { String name = fullPath + "." + p.getFileExtension(); MPIUtils.println(rank, "Output file for " + p.getTabName() + ": " + name); p.outputFile = new FileWriter(name); } } } catch (IOException ioex) { ioex.printStackTrace(); } MPIUtils.println(rank, "Generating initial tree and alignment..."); } // Determines the heat of the chain. double heat = 1.0d / (1.0d + ((double) rank / noOfProcesses));; try { // remove gaps and whitespace RawSequences seqs = inputData.seqs; inputData.title = new File(fullPath).getName(); String[] nongapped = new String[seqs.size()]; StringBuilder builder = new StringBuilder(); int i, j; char ch; for(i = 0; i < nongapped.length; i++) { builder.setLength(0); String seq = seqs.getSequence(i); for(j = 0; j < seq.length(); j++) { ch = seq.charAt(j); if(Character.isWhitespace(ch) || ch == '-') continue; builder.append(ch); } nongapped[i] = builder.toString(); } String[] names = seqs.getSeqnames().toArray(new String[seqs.size()]); TreeAlgo treeAlgo = new TreeAlgo(); Tree tree; if(inputData.useTree > 0) { tree = treeAlgo.rearrangeTree(inputData.tree, names); treeAlgo.addAlignSeqsToTree(tree, nongapped, names, inputData.model, new File(fullPath).getName()); } else { tree = treeAlgo.buildNJTree(nongapped, seqs.getSeqnames().toArray(new String[seqs.size()]), inputData.model, new File(fullPath).getName()); } Mcmc mcmc = new StatAlignParallelMcmc(tree, inputData.pars, postProcMan, modelExtMan, noOfProcesses, rank, heat); mcmc.doMCMC(); // Sets up a barrier. MPI.COMM_WORLD.Barrier(); // Retrieve the log-likelihood ratio from all of the workers double[] logLikelihood = new double[] { modelExtMan.totalLogLike(tree) }; double[] maxLogLikelihood = new double[1]; MPI.COMM_WORLD.Reduce(logLikelihood, 0, maxLogLikelihood, 0, 1, MPI.DOUBLE, MPI.MAX, 0); MPIUtils.println( rank, "My loglikelihood ratio: " + Double.toString(logLikelihood[0])); if (MPIUtils.isMaster(rank)) { MPIUtils.println(rank, "Max loglikelihood ratio: " + Double.toString(maxLogLikelihood[0])); } System.out.println(mcmc.getInfoString() + " Heat: " + mcmc.tree.heat); finished(0, null); System.out.println("Ready."); } catch (StoppedException stex) { stex.printStackTrace(System.err); finished(1, null); } } /** * Called when the MCMC thread terminates, signals end of the process back * to MainFrame. * @param errorCode -1: error 0: completed 1: stopped after sampling 2: stopped before sampling */ public void finished(final int errorCode, final Exception ex) { if (frame != null) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { frame.finished(errorCode, ex); } }); } } public void deactivateRNA() { frame.deactivateRNA(); } }