/*.................................................................................................................*/
  void zapData(CharacterData data, int it) {
    Taxa taxa = data.getTaxa();
    if (it < 0 || it >= taxa.getNumTaxa()) return;
    Associable tInfo = data.getTaxaInfo(false);
    int myColumn = -1;
    if (getEmployer() instanceof ListModule) {

      myColumn = ((ListModule) getEmployer()).getMyColumn(this);
    }
    if (tInfo != null) tInfo.deassignAssociated(it);
    for (int ic = 0; ic < data.getNumChars(); ic++) data.deassign(ic, it);

    data.notifyListeners(this, new Notification(MesquiteListener.DATA_CHANGED));
    outputInvalid();
    parametersChanged();
  }
 /*.................................................................................................................*/
 public void setTaxonTranslation(Taxa taxa) {
   int countTaxa = 0;
   for (int it = 0; it < data.getNumTaxa(); it++)
     if ((!selectedTaxaOnly || taxa.getSelected(it)) && (data.hasDataForTaxon(it, false))) {
       setTaxonNumberInTree(taxa, it, countTaxa);
       countTaxa++;
     } else setTaxonNumberInTree(taxa, it, -1);
 }
 /*...............................................................................................................*/
 boolean selected(Taxa taxa, int it, int myColumn) {
   if (taxa.getSelected(it)) {
     return true;
   }
   if (table != null && myColumn >= 0) {
     if (table.isCellSelectedAnyWay(myColumn, it)) return true;
   }
   return false;
 }
  public void doCalcs() {
    if (bits != null) bits.clearAllBits();
    if (taxa == null) return;
    if (bits == null) bits = new Bits(taxa.getNumTaxa());
    else bits.resetSize(taxa.getNumTaxa());
    if (observedStates == null) {
      tInfo = null;
      observedStates = matrixSourceTask.getCurrentMatrix(taxa);
      if (observedStates != null) {
        captureCharacterDataFromObservedStates();

        if (data != null) tInfo = data.getTaxaInfo(true);
      }
    }
    if (observedStates == null) return;
    for (int it = 0; it < taxa.getNumTaxa(); it++) {
      if (hasData(it)) bits.setBit(it);
    }
  }
 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 int[] getTaxonNumberTranslation(Taxa taxa) {
   int max = -1;
   for (int it = 0; it < taxa.getNumTaxa(); it++) {
     long translateNumber = getTaxonNumberInTree(taxa, it);
     if (MesquiteLong.isCombinable(translateNumber) && translateNumber > max) {
       max = (int) translateNumber;
     }
   }
   int[] translate = new int[max + 1];
   for (int it = 0; it < data.getNumTaxa(); it++) {
     long translateNumber = getTaxonNumberInTree(taxa, it);
     if (MesquiteLong.isCombinable(translateNumber) && translateNumber >= 0) {
       translate[(int) translateNumber] = it;
     }
   }
   return translate;
 }
  /*.................................................................................................................*/
  public Object doCommand(String commandName, String arguments, CommandChecker checker) {
    if (checker.compare(
        this.getClass(), "Returns the matrix source", null, commandName, "getMatrixSource")) {
      return matrixSourceTask;
    } else if (checker.compare(
        this.getClass(), "Copies the data for selected taxon", null, commandName, "copyData")) {
      if (observedStates == null) return null;
      CharacterData data = observedStates.getParentData();
      if (data == null) return null;
      int it = MesquiteInteger.fromString(parser.getFirstToken(arguments));
      if (MesquiteInteger.isCombinable(it)) {
        StringBuffer sb = new StringBuffer();
        data.copyDataFromRowIntoBuffer(it, sb);
        if (StringUtil.notEmpty(sb.toString())) {
          localCopyDataClipboard = sb.toString();
          localCopyData = data;
          localCopyDataTaxon = data.getTaxa().getTaxonName(it);
        } else {
          localCopyDataClipboard = null;
          localCopyData = null;
          localCopyDataTaxon = null;
        }
      }
      return null;
    } else if (checker.compare(
        this.getClass(), "Pastes the data for selected taxon", null, commandName, "pasteData")) {
      if (observedStates == null) return null;
      CharacterData data = observedStates.getParentData();
      if (data == null) return null;
      int it = MesquiteInteger.fromString(parser.getFirstToken(arguments));
      if (MesquiteInteger.isCombinable(it) && StringUtil.notEmpty(localCopyDataClipboard)) {
        data.pasteDataFromStringIntoTaxon(it, localCopyDataClipboard);
      }
      return null;
    } else if (checker.compare(
        this.getClass(),
        "Pastes the data for selected taxon",
        null,
        commandName,
        "deleteDataTouched")) {
      if (observedStates == null) return null;
      CharacterData data = observedStates.getParentData();
      if (data == null) return null;
      int it = MesquiteInteger.fromString(parser.getFirstToken(arguments));
      Debugg.println("prepare to delete row: " + it);
      if (MesquiteInteger.isCombinable(it)) {
        if (!AlertDialog.query(
            containerOfModule(),
            "Delete Data?",
            "Are you sure you want to delete the data for taxon "
                + data.getTaxa().getTaxonName(it)
                + " in the matrix \""
                + data.getName()
                + "\"",
            "No",
            "Yes")) {
          zapData(data, it);
        }
      }
      return null;
    } else if (checker.compare(
        this.getClass(), "Deletes the data for selected taxa", null, commandName, "deleteData")) {
      if (observedStates == null) return null;
      captureCharacterDataFromObservedStates();
      if (data == null) return null;
      if (!AlertDialog.query(
          containerOfModule(),
          "Delete Data?",
          "Are you sure you want to delete the data for these taxa in the matrix \""
              + data.getName()
              + "\"",
          "No",
          "Yes")) zapData(data);
      return null;
    } else if (checker.compare(
        this.getClass(),
        "deleteds () and anything between",
        null,
        commandName,
        "deletePrepended")) {
      if (observedStates == null || taxa == null) return null;
      boolean anySelected = taxa.anySelected();
      int myColumn = -1;
      if (getEmployer() instanceof ListModule) {

        myColumn = ((ListModule) getEmployer()).getMyColumn(this);
        if (table != null)
          anySelected = anySelected || table.anyCellSelectedInColumnAnyWay(myColumn);
      }

      for (int it = 0; it < taxa.getNumTaxa(); it++) {
        if ((!anySelected || selected(taxa, it, myColumn))) {
          String note = getNote(it);
          while (!StringUtil.blank(note) && note.indexOf("(") >= 0) {
            int start = note.indexOf("(");
            int end = note.indexOf(")");
            String firstBit = "";
            if (start > 0) firstBit = note.substring(0, start);
            note = firstBit + note.substring(end + 1, note.length());
          }
          setNote(it, note);
        }
      }
      outputInvalid();
      parametersChanged();
      return null;
    } else if (checker.compare(this.getClass(), "deletes *", null, commandName, "deleteStar")) {
      if (observedStates == null || taxa == null) return null;
      boolean anySelected = taxa.anySelected();
      int myColumn = -1;
      if (getEmployer() instanceof ListModule) {

        myColumn = ((ListModule) getEmployer()).getMyColumn(this);
        if (table != null)
          anySelected = anySelected || table.anyCellSelectedInColumnAnyWay(myColumn);
      }
      for (int it = 0; it < taxa.getNumTaxa(); it++) {
        if ((!anySelected || selected(taxa, it, myColumn))) {
          String note = getNote(it);
          while (!StringUtil.blank(note) && note.indexOf("*") >= 0) {
            int start = note.indexOf("*");
            String firstBit = "";
            if (start > 0) firstBit = note.substring(0, start);
            note = firstBit + note.substring(start + 1, note.length());
          }
          setNote(it, note);
        }
      }
      outputInvalid();
      parametersChanged();
      return null;
    } else if (checker.compare(
        this.getClass(),
        "Prepends to the note the sequence length (including N\'s and ?\'s) for the selected taxa",
        null,
        commandName,
        "prependLength")) {
      if (observedStates == null || taxa == null) return null;
      boolean anySelected = taxa.anySelected();
      int myColumn = -1;
      if (getEmployer() instanceof ListModule) {

        myColumn = ((ListModule) getEmployer()).getMyColumn(this);
        if (table != null)
          anySelected = anySelected || table.anyCellSelectedInColumnAnyWay(myColumn);
      }
      for (int it = 0; it < taxa.getNumTaxa(); it++) {
        if (hasData(it) && (!anySelected || selected(taxa, it, myColumn))) {
          String note = getNote(it);
          if (StringUtil.blank(note)) note = "(" + sequenceLength(it) + ")";
          else note = "(" + sequenceLength(it) + ") " + note;
          setNote(it, note);
        }
      }
      outputInvalid();
      parametersChanged();
      return null;
    } else if (checker.compare(
        this.getClass(),
        "Prepends to the note the number of non-missing sites (not including N\'s and ?\'s) for the selected taxa",
        null,
        commandName,
        "prependNumSites")) {
      if (observedStates == null || taxa == null) return null;
      boolean anySelected = taxa.anySelected();
      int myColumn = -1;
      if (getEmployer() instanceof ListModule) {

        myColumn = ((ListModule) getEmployer()).getMyColumn(this);
        if (table != null)
          anySelected = anySelected || table.anyCellSelectedInColumnAnyWay(myColumn);
      }
      for (int it = 0; it < taxa.getNumTaxa(); it++) {
        if (hasData(it) && (!anySelected || selected(taxa, it, myColumn))) {
          String note = getNote(it);
          if (StringUtil.blank(note)) note = "(" + numSites(it) + ")";
          else note = "(" + numSites(it) + ") " + note;
          setNote(it, note);
        }
      }
      outputInvalid();
      parametersChanged();
      return null;
    } else if (checker.compare(
        this.getClass(),
        "Deletes the notes for the selected taxa",
        null,
        commandName,
        "deleteAnnotation")) {
      if (observedStates == null || taxa == null) return null;
      boolean anySelected = taxa.anySelected();
      int myColumn = -1;
      if (getEmployer() instanceof ListModule) {

        myColumn = ((ListModule) getEmployer()).getMyColumn(this);
        if (table != null)
          anySelected = anySelected || table.anyCellSelectedInColumnAnyWay(myColumn);
      }
      for (int it = 0; it < taxa.getNumTaxa(); it++) {
        if (hasData(it) && (!anySelected || selected(taxa, it, myColumn))) {
          setNote(it, null);
        }
      }
      outputInvalid();
      parametersChanged();
      return null;
    } else return super.doCommand(commandName, arguments, checker);
  }
 public CharacterData makeCharacterData(CharMatrixManager manager, Taxa taxa) {
   GeographicData data = new GeographicData(getMatrixManager(), taxa.getNumTaxa(), 0, taxa);
   data.setItemsAs(this);
   return data;
 }
  /*.................................................................................................................*/
  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;
  }