bool substituteSafeTaxaLabels(PublicNexusReader &nexusReader, std::string filepath, bool evenTrivial) { std::ostream * outStrPtr = 0L; std::ofstream outStream; const unsigned nTaxaBlocks = nexusReader.GetNumTaxaBlocks(); bool someChanged = false; std::set<std::string> safeNameSet; try { for (unsigned t = 0; t < nTaxaBlocks; ++t) { NxsTaxaBlock * tb = nexusReader.GetTaxaBlock(t); std::vector<std::string> safeLabelsVec; bool changed = constructSafeLabels(*tb, &safeLabelsVec, safeNameSet); someChanged = someChanged | changed; if (changed || evenTrivial) { if (outStrPtr == 0L) { outStream.open(filepath.c_str()); if (!outStream.good()) { NxsString eMessage; eMessage << "Could not open the file \"" << filepath << "\""; throw NxsException(eMessage); } outStrPtr = &outStream; outStream << "#NEXUS\n"; } tb->WriteAsNexus(*outStrPtr); std::vector<NxsString> oldNameVec; const unsigned numTaxa = tb->GetNTaxTotal(); for (unsigned i = 0; i < numTaxa; ++i) { NxsString oldName = tb->GetTaxonLabel(i); oldNameVec.push_back(oldName); NxsString newName; newName << safeLabelsVec[i]; tb->ChangeTaxonLabel(i, newName); } NxsString title; title << tb->GetTitle(); NxsString nt; nt << "Renamed " << title; tb->SetTitle(nt, false); tb->WriteAsNexus(*outStrPtr); // We can't just create a TaxaAssociationBlock instance here, // and call WriteAsNexus because it first and second taxa block pointers // would refer to the same instance... NxsString taTitle; taTitle << "Renaming " << title; *outStrPtr << "BEGIN TaxaAssociation;\n Title " << NxsString::GetEscaped(taTitle) << " ;\n"; *outStrPtr << " Taxa " << NxsString::GetEscaped(title) << " , " << NxsString::GetEscaped(nt) << " ;\n"; *outStrPtr << " Associates "; for (unsigned i = 0; i < numTaxa; ++i) { if (i > 0) *outStrPtr << " ,\n "; *outStrPtr << NxsString::GetEscaped(oldNameVec[i]) << " / " << NxsString::GetEscaped(safeLabelsVec[i]); } *outStrPtr << " ;\nEND;\n" ; } } } catch (...) { if (outStrPtr != 0L) outStream.close(); throw; } if (outStrPtr != 0L) outStream.close(); return someChanged; }