/*.................................................................................................................*/
  public Object getProgramArguments(
      String dataFileName, String configFileName, boolean isPreflight) {

    MesquiteString arguments = new MesquiteString();
    if (externalProcRunner.isWindows()) arguments.setValue(" --batch " + configFileName);
    else
      arguments.setValue(
          ""); // GARLI command is very simple as all of the arguments are in the config file
    return arguments;
  }
  /*.................................................................................................................*/
  public void calculateNumber(
      Tree tree1, Tree tree2, MesquiteNumber result, MesquiteString resultString) {
    if (result == null) return;
    clearResultAndLastResult(result);
    if (tree1 == null) return;
    if (tree2 == null) return;

    int numTaxa = tree1.getTaxa().getNumTaxa();

    double[][] patristic1 = null;
    patristic1 =
        p1.calculatePatristic(
            tree1,
            numTaxa,
            patristic1); // for this tree calculate patristic distances (number of nodes separating
                         // terminals; no branch lengths)
    double[][] patristic2 = null;
    patristic2 =
        p2.calculatePatristic(
            tree2,
            numTaxa,
            patristic2); // for this tree calculate patristic distances (number of nodes separating
                         // terminals; no branch lengths)

    double correl = offDiagonalPMCorrelationFILTERED(patristic1, patristic2);
    if (isDistance && (MesquiteDouble.isCombinable(correl)))
      correl = -correl + 1.0; // shifting 1 to -1 to be 0 to 2 to act as distance
    result.setValue(correl);
    if (resultString != null) {
      if (isDistance)
        resultString.setValue(
            "Patristic correlation (converted to distance): " + result.toString());
      else resultString.setValue("Patristic correlation: " + result.toString());
    }
    saveLastResult(result);
    saveLastResultString(resultString);
  }
 /*.................................................................................................................*/
 public Object doCommand(String commandName, String arguments, CommandChecker checker) {
   if (checker.compare(
       this.getClass(),
       "Sets module supplying characters",
       "[name of module]",
       commandName,
       "setCharacterSource")) {
     CharacterObedSource newCharacterSourceTask;
     if (hiringCondition != null)
       newCharacterSourceTask =
           (CharacterObedSource)
               replaceCompatibleEmployee(
                   CharacterObedSource.class,
                   arguments,
                   characterSourceTask,
                   hiringCondition); // , "Source of characters"
     else
       newCharacterSourceTask =
           (CharacterObedSource)
               replaceEmployee(
                   CharacterObedSource.class,
                   arguments,
                   "Source of characters",
                   characterSourceTask);
     if (newCharacterSourceTask != null) {
       characterSourceTask = newCharacterSourceTask;
       characterSourceTask.setHiringCommand(cstC);
       charSourceName.setValue(characterSourceTask.getName());
       resetContainingMenuBar();
       parametersChanged();
       return characterSourceTask;
     } else {
       discreetAlert(
           "Unable to activate character source \""
               + arguments
               + "\"  for use by "
               + employer.getName());
     }
   } else if (characterSourceTask != null) { // todo: temporary, for snapshot conversions
     return characterSourceTask.doCommand(commandName, arguments, checker);
   } else return super.doCommand(commandName, arguments, checker);
   return null;
 }
 public void calculateNumber(Taxon taxon, MesquiteNumber result, MesquiteString resultString) {
   if (result == null) return;
   clearResultAndLastResult(result);
   Taxa taxa = taxon.getTaxa();
   int it = taxa.whichTaxonNumber(taxon);
   if (taxa != currentTaxa || observedStates == null) {
     observedStates = matrixSourceTask.getCurrentMatrix(taxa);
     currentTaxa = taxa;
   }
   if (observedStates == null || !(observedStates.getParentData() instanceof DNAData)) return;
   DNAData data = (DNAData) observedStates.getParentData();
   int count = data.getAminoAcidNumbers(it, ProteinData.TER, countEvenIfOthers.getValue());
   if (result != null) result.setValue(count);
   if (resultString != null)
     resultString.setValue(
         "Number of stop codons in taxon " + observedStates.getName() + ": " + count);
   saveLastResult(result);
   saveLastResultString(resultString);
 }
  /*.................................................................................................................*/
  private void recordSourceProject() {
    MesquiteString s = new MesquiteString();
    s.setValue(getProject().getHomeFileName());
    if (!QueryDialogs.queryString(
        containerOfModule(),
        "Name to Stamp",
        "Indicate source file name to stamp on matrix rows",
        s)) return;

    int numMatrices = getProject().getNumberCharMatrices();
    NameReference sourceRef = NameReference.getNameReference("SourceFile");

    for (int im = 0; im < numMatrices; im++) {
      CharacterData data = getProject().getCharacterMatrix(im);
      Taxa taxa = data.getTaxa();
      Associable tInfo = data.getTaxaInfo(true);
      boolean anySelected = taxa.anySelected();
      for (int it = 0; it < taxa.getNumTaxa(); it++) {
        if (data.hasDataForTaxon(it) && (!anySelected || taxa.getSelected(it)))
          tInfo.setAssociatedObject(sourceRef, it, s.getValue());
      }
    }
  }
  /*.................................................................................................................*/
  public Tree getTrees(
      TreeVector trees,
      Taxa taxa,
      MCharactersDistribution matrix,
      long seed,
      MesquiteDouble finalScore) {
    if (!initializeGetTrees(CategoricalData.class, taxa, matrix)) return null;
    setTNTSeed(seed);
    isProtein = data instanceof ProteinData;

    // David: if isDoomed() then module is closing down; abort somehow

    // write data file
    String tempDir =
        MesquiteFileUtil.createDirectoryForFiles(
            this, MesquiteFileUtil.IN_SUPPORT_DIR, "TNT", "-Run.");
    if (tempDir == null) return null;
    String dataFileName = "data.ss"; // replace this with actual file name?
    String dataFilePath = tempDir + dataFileName;

    FileInterpreterI exporter = ZephyrUtil.getFileInterpreter(this, "#InterpretTNT");
    if (exporter == null) return null;
    boolean fileSaved = false;
    String translationTable = namer.getTranslationTable(taxa);
    ((InterpretHennig86Base) exporter).setTaxonNamer(namer);

    fileSaved = ZephyrUtil.saveExportFile(this, exporter, dataFilePath, data, selectedTaxaOnly);
    if (!fileSaved) return null;

    String translationFileName = IOUtil.translationTableFileName;
    setTaxonTranslation(taxa);
    taxonNumberTranslation = getTaxonNumberTranslation(taxa);
    namer.setNumberTranslationTable(taxonNumberTranslation);

    setFileNames();

    TaxaSelectionSet outgroupSet =
        (TaxaSelectionSet) taxa.getSpecsSet(outgroupTaxSetString, TaxaSelectionSet.class);
    int firstOutgroup = MesquiteInteger.unassigned;
    if (outgroupSet != null) firstOutgroup = outgroupSet.firstBitOn();
    formCommandFile(dataFileName, firstOutgroup);
    logln("\n\nCommands given to TNT:");
    logln(commands);
    logln("");

    MesquiteString arguments = new MesquiteString();
    arguments.setValue(" proc " + commandsFileName);

    String programCommand = externalProcRunner.getExecutableCommand();

    int numInputFiles = 3;
    String[] fileContents = new String[numInputFiles];
    String[] fileNames = new String[numInputFiles];
    for (int i = 0; i < numInputFiles; i++) {
      fileContents[i] = "";
      fileNames[i] = "";
    }
    fileContents[0] = MesquiteFile.getFileContentsAsString(dataFilePath);
    fileNames[0] = dataFileName;
    fileContents[1] = commands;
    fileNames[1] = commandsFileName;
    fileContents[2] = translationTable;
    fileNames[2] = translationFileName;

    // ----------//
    boolean success =
        runProgramOnExternalProcess(
            programCommand, arguments, fileContents, fileNames, ownerModule.getName());

    if (!isDoomed()) {
      if (success) {
        desuppressProjectPanelReset();
        return retrieveTreeBlock(trees, finalScore); // here's where we actually process everything.
      } else {
        if (!beanWritten) postBean("unsuccessful [1]", false);
        beanWritten = true;
      }
    }
    desuppressProjectPanelReset();
    if (data == null) data.decrementEditInhibition();
    externalProcRunner.finalCleanup();
    return null;
  }