00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <iomanip>
00020 #include <climits>
00021
00022 #include "ncl/nxsassumptionsblock.h"
00023
00024 #include "ncl/nxssetreader.h"
00025 #include "ncl/nxsreader.h"
00026 using namespace std;
00027
00028 class BogusToIndMapper: public NxsLabelToIndicesMapper
00029 {
00030 public:
00031 BogusToIndMapper()
00032 :queried(false)
00033 {}
00034 virtual ~BogusToIndMapper(){}
00035 virtual unsigned GetMaxIndex() const
00036 {
00037 return UINT_MAX;
00038 }
00039 virtual unsigned GetIndicesForLabel(const std::string &label, NxsUnsignedSet *) const
00040 {
00041 queried=true;
00042 NxsString e;
00043 e << "The symbol " << label << " was not recognized";
00044 throw NxsException(e);
00045 }
00046
00047 virtual unsigned GetIndexSet(const std::string &, NxsUnsignedSet * ) const
00048 {
00049 return 0;
00050 }
00051 virtual bool AddNewIndexSet(const std::string &, const NxsUnsignedSet & )
00052 {
00053 return false;
00054 }
00055 virtual bool AddNewPartition(const std::string &, const NxsPartition & )
00056 {
00057 return false;
00058 }
00059
00061 virtual unsigned AppendNewLabel(std::string &label)
00062 {
00063 queried=true;
00064 NxsString e;
00065 e << "The symbol " << label << " was not recognized";
00066 throw NxsException(e);
00067 }
00068
00069 std::vector<std::string> GetLabels() const
00070 {
00071 queried=true;
00072 NxsString e;
00073 throw NxsException(e);
00074 }
00075 mutable bool queried;
00076 };
00077
00078
00079 void NxsTransformationManager::Reset()
00080 {
00081 standardTypeNames.clear();
00082 standardTypeNames.insert("UNORD");
00083 standardTypeNames.insert("ORD");
00084 standardTypeNames.insert("IRREV");
00085 standardTypeNames.insert("IRREV.UP");
00086 standardTypeNames.insert("IRREV.DOWN");
00087 standardTypeNames.insert("DOLLO");
00088 standardTypeNames.insert("DOLLO.UP");
00089 standardTypeNames.insert("DOLLO.DOWN");
00090 standardTypeNames.insert("STRAT");
00091 standardTypeNames.insert("SQUARED");
00092 standardTypeNames.insert("LINEAR");
00093 allTypeNames.clear();
00094 allTypeNames.insert(standardTypeNames.begin(), standardTypeNames.end());
00095
00096 userTypeNames.clear();
00097 dblUserTypes.clear();
00098 intUserTypes.clear();
00099 dblWtSets.clear();
00100 intWtSets.clear();
00101 typeSets.clear();
00102 def_wtset.clear();
00103 def_typeset.clear();
00104 def_type.clear();
00105 }
00106
00107 void NxsTransformationManager::WriteUserType(std::ostream &out) const
00108 {
00109 if (dblUserTypes.empty() && intUserTypes.empty())
00110 return;
00111 for (std::map<std::string, NxsRealStepMatrix>::const_iterator csIt = dblUserTypes.begin(); csIt != dblUserTypes.end(); ++csIt)
00112 {
00113 out << " UserType ";
00114 out << NexusToken::EscapeString(csIt->first) << " (Stepmatrix) = ";
00115 const NxsRealStepMatrix & p = csIt->second;
00116 const std::vector<std::string> & states = p.GetSymbols();
00117 const NxsRealStepMatrix::DblMatrix & mat = p.GetMatrix();
00118 const unsigned nStates = (const unsigned)states.size();
00119 out << nStates;
00120 out << "\n ";
00121 for (std::vector<std::string>::const_iterator sIt = states.begin(); sIt != states.end(); ++sIt)
00122 out << " "<< NxsString::GetEscaped(*sIt) ;
00123 NxsString n;
00124 std::ios::fmtflags prevflags = out.setf(std::ios::showpoint);
00125 for (unsigned i = 0; i < nStates; ++i)
00126 {
00127 out << "\n ";
00128 for (unsigned j = 0; j < nStates; ++j)
00129 {
00130 const double el = mat.at(i).at(j);
00131 if (i == j && el == 0.0)
00132 out << " .";
00133 else
00134 {
00135 n.clear();
00136 if (el == DBL_MAX)
00137 n += "i";
00138 else
00139 n += el;
00140 out << " " << NxsString::GetEscaped(n);
00141 }
00142 }
00143 }
00144 out.flags(prevflags);
00145 out << ";\n";
00146 }
00147
00148 for (std::map<std::string, NxsIntStepMatrix>::const_iterator csIt = intUserTypes.begin(); csIt != intUserTypes.end(); ++csIt)
00149 {
00150 out << " UserType ";
00151 out << NexusToken::EscapeString(csIt->first) << " (Stepmatrix) = ";
00152 const NxsIntStepMatrix & p = csIt->second;
00153 const std::vector<std::string> & states = p.GetSymbols();
00154 const NxsIntStepMatrix::IntMatrix & mat = p.GetMatrix();
00155 const unsigned nStates = (const unsigned)states.size();
00156 out << nStates;
00157 out << "\n ";
00158 for (std::vector<std::string>::const_iterator sIt = states.begin(); sIt != states.end(); ++sIt)
00159 out << " "<< NxsString::GetEscaped(*sIt) ;
00160 NxsString n;
00161 for (unsigned i = 0; i < nStates; ++i)
00162 {
00163 out << "\n ";
00164 for (unsigned j = 0; j < nStates; ++j)
00165 {
00166 const int el = mat.at(i).at(j);
00167 if (i == j && el == 0)
00168 out << " .";
00169 else
00170 {
00171 if (el == INT_MAX)
00172 n = "i";
00173 else
00174 {
00175 n.clear();
00176 n += el;
00177 }
00178 out << " " << NxsString::GetEscaped(n);
00179 }
00180 }
00181 }
00182 out << ";\n";
00183 }
00184 }
00185
00186 void NxsTransformationManager::WriteWtSet(std::ostream &out) const
00187 {
00188 if (dblWtSets.empty() && intWtSets.empty())
00189 return;
00190 const char * dtp = (def_wtset.empty() ? NULL : def_wtset.c_str());
00191 for (std::map<std::string, ListOfDblWeights>::const_iterator csIt = dblWtSets.begin(); csIt != dblWtSets.end(); ++csIt)
00192 {
00193 out << " WtSet ";
00194 if (NxsString::case_insensitive_equals(csIt->first.c_str(), dtp))
00195 out << "* ";
00196 out << NexusToken::EscapeString(csIt->first) << " =";
00197 const ListOfDblWeights & p = csIt->second;
00198 bool first = true;
00199 for (ListOfDblWeights::const_iterator pIt = p.begin(); pIt != p.end(); ++pIt)
00200 {
00201 const DblWeightToIndexSet & g = *pIt;
00202 if (!first)
00203 out << ',';
00204 out << " \'" << g.first << "' :";
00205 NxsSetReader::WriteSetAsNexusValue(g.second, out);
00206 first = false;
00207 }
00208 out << ";\n";
00209 }
00210 for (std::map<std::string, ListOfIntWeights>::const_iterator csIt = intWtSets.begin(); csIt != intWtSets.end(); ++csIt)
00211 {
00212 out << " WtSet ";
00213 if (NxsString::case_insensitive_equals(csIt->first.c_str(), dtp))
00214 out << "* ";
00215 out << NexusToken::EscapeString(csIt->first) << " =";
00216 const ListOfIntWeights & p = csIt->second;
00217 bool first = true;
00218 for (ListOfIntWeights::const_iterator pIt = p.begin(); pIt != p.end(); ++pIt)
00219 {
00220 const IntWeightToIndexSet & g = *pIt;
00221 if (!first)
00222 out << ',';
00223 out << " \'" << g.first << "' :";
00224 NxsSetReader::WriteSetAsNexusValue(g.second, out);
00225 first = false;
00226 }
00227 out << ";\n";
00228 }
00229 }
00230
00231
00235 void NxsTransformationManager::SetDefaultTypeName(const std::string &n)
00236 {
00237 if (!(n.empty() || IsValidTypeName(n)))
00238 {
00239 NxsString e(n.c_str());
00240 e << " is not the name of a known type (and therefore is not a valid default type)";
00241 throw NxsException(e);
00242 }
00243 def_type = n;
00244 }
00245
00246
00247 bool NxsTransformationManager::IsEmpty() const
00248 {
00249 return (userTypeNames.empty()
00250 && dblWtSets.empty()
00251 && intWtSets.empty()
00252 && typeSets.empty()
00253 && (def_type.empty() || !NxsString::case_insensitive_equals(def_type.c_str(), "ORD")));
00254 }
00255
00259 double NxsTransformationManager::GetWeightForIndex(const ListOfDblWeights & wtset, unsigned index)
00260 {
00261 for (ListOfDblWeights::const_iterator wIt = wtset.begin(); wIt != wtset.end(); ++wIt)
00262 {
00263 if (wIt->second.count(index) > 0)
00264 return wIt->first;
00265 }
00266 return -1.0;
00267 }
00268
00272 int NxsTransformationManager::GetWeightForIndex(const ListOfIntWeights & wtset, unsigned index)
00273 {
00274 for (ListOfIntWeights::const_iterator wIt = wtset.begin(); wIt != wtset.end(); ++wIt)
00275 {
00276 if (wIt->second.count(index) > 0)
00277 return wIt->first;
00278 }
00279 return 1;
00280 }
00281
00285 bool NxsTransformationManager::IsIntType(const std::string & n) const
00286 {
00287 std::string capName(n.c_str());
00288 NxsString::to_upper(capName);
00289 if (standardTypeNames.count(capName) > 0)
00290 return true;
00291 if (intUserTypes.find(capName) != intUserTypes.end())
00292 return true;
00293 if (dblUserTypes.find(capName) != dblUserTypes.end())
00294 return false;
00295 NxsString errormsg = "Type name ";
00296 errormsg << n << " not found.";
00297 throw NxsNCLAPIException(errormsg);
00298 }
00299
00300
00304 bool NxsTransformationManager::IsValidTypeName(const std::string & n) const
00305 {
00306 std::string capName(n.c_str());
00307 NxsString::to_upper(capName);
00308 return (allTypeNames.count(capName) > 0);
00309 }
00310
00314 bool NxsTransformationManager::IsStandardType(const std::string & n) const
00315 {
00316 std::string capName(n.c_str());
00317 NxsString::to_upper(capName);
00318 return (standardTypeNames.count(capName) > 0);
00319 }
00320
00326 const NxsIntStepMatrix & NxsTransformationManager::GetIntType(const std::string & n) const
00327 {
00328 std::string capName(n.c_str());
00329 NxsString::to_upper(capName);
00330 if (IsStandardType(n))
00331 throw NxsNCLAPIException("Standard (predefined) types cannot be fetched using GetIntType.");
00332
00333 std::map<std::string, NxsIntStepMatrix>::const_iterator i = intUserTypes.find(capName);
00334 if (i != intUserTypes.end())
00335 return i->second;
00336 NxsString errormsg = "Type name ";
00337 errormsg << n << " not found.";
00338 throw NxsNCLAPIException(errormsg);
00339 }
00340
00346 const NxsRealStepMatrix & NxsTransformationManager::GetRealType(const std::string & n) const
00347 {
00348 std::string capName(n.c_str());
00349 NxsString::to_upper(capName);
00350 std::map<std::string, NxsRealStepMatrix>::const_iterator i = dblUserTypes.find(capName);
00351 if (i != dblUserTypes.end())
00352 return i->second;
00353 NxsString errormsg = "Type name ";
00354 errormsg << n << " not found.";
00355 throw NxsNCLAPIException(errormsg);
00356 }
00357
00358 const NxsIntStepMatrix::IntMatrix NxsTransformationManager::GetOrderedType(unsigned nStates)
00359 {
00360 NxsIntStepMatrix::IntVec v(nStates, 1);
00361 NxsIntStepMatrix::IntMatrix m(nStates, v);
00362 for (unsigned i = 0; i < nStates; ++i)
00363 m[i][i] = 0;
00364 return m;
00365 }
00366
00367 const NxsIntStepMatrix::IntMatrix NxsTransformationManager::GetUnorderedType(unsigned nStates)
00368 {
00369 NxsIntStepMatrix::IntVec v(nStates, 0);
00370 NxsIntStepMatrix::IntMatrix m(nStates, v);
00371 for (unsigned i = 0; i < nStates; ++i)
00372 {
00373 for (unsigned j = 0; j < nStates; ++j)
00374 {
00375 if (i > j)
00376 m[i][j] = j - i;
00377 else
00378 m[i][j] = i - j;
00379 }
00380 }
00381 return m;
00382 }
00383
00384
00389 bool NxsTransformationManager::AddIntType(const std::string &name, const NxsIntStepMatrix &s)
00390 {
00391 std::string capName(name.c_str());
00392 NxsString::to_upper(capName);
00393 if (standardTypeNames.count(capName) > 0)
00394 {
00395 NxsString errormsg(name.c_str());
00396 errormsg << " is a predefined type which cannot be redefined";
00397 throw NxsNCLAPIException(errormsg);
00398 }
00399 bool replacing = intUserTypes.find(capName) != intUserTypes.end();
00400 if (!replacing && dblUserTypes.find(capName) != dblUserTypes.end())
00401 {
00402 replacing = true;
00403 dblUserTypes.erase(capName);
00404 }
00405 intUserTypes.insert(pair<std::string, NxsIntStepMatrix>(capName, s));
00406 userTypeNames.insert(name);
00407 allTypeNames.insert(capName);
00408 return replacing;
00409 }
00410
00415 bool NxsTransformationManager::AddRealType(const std::string &name, const NxsRealStepMatrix &s)
00416 {
00417 std::string capName(name.c_str());
00418 NxsString::to_upper(capName);
00419 if (standardTypeNames.count(capName) > 0)
00420 {
00421 NxsString errormsg(name.c_str());
00422 errormsg << " is a predefined type which cannot be redefined";
00423 throw NxsNCLAPIException(errormsg);
00424 }
00425 bool replacing = dblUserTypes.find(capName) != dblUserTypes.end();
00426 if (!replacing && intUserTypes.find(capName) != intUserTypes.end())
00427 {
00428 replacing = true;
00429 intUserTypes.erase(capName);
00430 }
00431 dblUserTypes.insert(pair<std::string, NxsRealStepMatrix>(capName, s));
00432 userTypeNames.insert(capName);
00433 allTypeNames.insert(capName);
00434 return replacing;
00435 }
00436
00437 bool NxsTransformationManager::AddIntWeightSet(const std::string &name, const NxsTransformationManager::ListOfIntWeights &ws, bool isDefault)
00438 {
00439 std::string capName(name.c_str());
00440 NxsString::to_upper(capName);
00441 bool replacing = intWtSets.find(capName) != intWtSets.end();
00442 if (!replacing && dblWtSets.find(capName) != dblWtSets.end())
00443 {
00444 replacing = true;
00445 dblWtSets.erase(capName);
00446 }
00447 intWtSets[capName] = ws;
00448 if (isDefault)
00449 def_wtset = name;
00450 return replacing;
00451 }
00452
00453 bool NxsTransformationManager::AddRealWeightSet(const std::string &name, const NxsTransformationManager::ListOfDblWeights &ws, bool isDefault)
00454 {
00455 std::string capName(name.c_str());
00456 NxsString::to_upper(capName);
00457 bool replacing = dblWtSets.find(capName) != dblWtSets.end();
00458 if (!replacing && intWtSets.find(capName) != intWtSets.end())
00459 {
00460 replacing = true;
00461 intWtSets.erase(capName);
00462 }
00463 dblWtSets[capName] = ws;
00464 if (isDefault)
00465 {
00466 def_wtset = name;
00467 }
00468 return replacing;
00469 }
00470
00471 bool NxsTransformationManager::AddTypeSet(const std::string &name, const NxsPartition &ts, bool isDefault)
00472 {
00473 std::string capName(name.c_str());
00474 NxsString::to_upper(capName);
00475 bool replacing = typeSets.find(capName) != typeSets.end();
00476 typeSets[capName] = ts;
00477 if (isDefault)
00478 {
00479 def_typeset = name;
00480 }
00481 return replacing;
00482 }
00483
00484 std::set<std::string> NxsTransformationManager::GetWeightSetNames() const
00485 {
00486 std::set<std::string> s;
00487 std::map<std::string, ListOfDblWeights>::const_iterator dws = dblWtSets.begin();
00488 for (; dws != dblWtSets.end(); ++dws)
00489 s.insert(dws->first);
00490 std::map<std::string, ListOfIntWeights>::const_iterator iws = intWtSets.begin();
00491 for (; iws != intWtSets.end(); ++iws)
00492 s.insert(iws->first);
00493 return s;
00494 }
00495
00496 std::set<std::string> NxsTransformationManager::GetTypeSetNames() const
00497 {
00498 std::set<std::string> s;
00499 std::map<std::string, ListOfTypeNamesToSets>::const_iterator dws = typeSets.begin();
00500 for (; dws != typeSets.end(); ++dws)
00501 s.insert(dws->first);
00502 return s;
00503 }
00504
00505
00506 void NxsAssumptionsBlock::AddCharPartition(const std::string & name, const NxsPartition &p)
00507 {
00508 charPartitions[name] = p;
00509 }
00510 void NxsAssumptionsBlock::AddTaxPartition(const std::string & name, const NxsPartition &p)
00511 {
00512 taxPartitions[name] = p;
00513 }
00514
00515 void NxsAssumptionsBlock::AddTreePartition(const std::string & name, const NxsPartition &p)
00516 {
00517 treePartitions[name] = p;
00518 }
00519
00520 void NxsAssumptionsBlock::AddCodeSet(const std::string & name, const NxsPartition &p, bool asterisked)
00521 {
00522 codeSets[name] = p;
00523 if (asterisked)
00524 def_codeSet.assign(name.c_str());
00525 }
00526
00527 void NxsAssumptionsBlock::AddCodonPosSet(const std::string & name, const NxsPartition &p, bool asterisked)
00528 {
00529 codonPosSets[name] = p;
00530 if (asterisked)
00531 def_codonPosSet.assign(name.c_str());
00532 }
00533
00534
00535 void NxsAssumptionsBlock::WriteOptions(std::ostream & out) const
00536 {
00537 const std::string d = transfMgr.GetDefaultTypeName();
00538 if ((!d.empty() && !NxsString::case_insensitive_equals(d.c_str(), "ORD"))
00539 || gapsAsNewstate || polyTCountValue != POLY_T_COUNT_UNKNOWN)
00540 {
00541 out << " OPTIONS";
00542 if (!d.empty())
00543 out << " DefType = " << NxsString::GetEscaped(d);
00544 if (gapsAsNewstate)
00545 out << " GapMode = NewState";
00546 if (polyTCountValue == POLY_T_COUNT_MIN)
00547 out << " PolyTCount = MinSteps";
00548 else if (polyTCountValue == POLY_T_COUNT_MAX)
00549 out << " PolyTCount = MaxSteps";
00550 out << ";\n";
00551 }
00552 }
00553
00554 bool NxsAssumptionsBlock::HasAssumptionsBlockCommands() const
00555 {
00556 return (gapsAsNewstate
00557 || !transfMgr.IsEmpty()
00558 || !exsets.empty()
00559 || polyTCountValue != POLY_T_COUNT_UNKNOWN);
00560 }
00561 bool NxsAssumptionsBlock::HasSetsBlockCommands() const
00562 {
00563 return (!charsets.empty() || !taxsets.empty() || !treesets.empty()
00564 ||!charPartitions.empty() || !taxPartitions.empty() || !treePartitions.empty() );
00565 }
00566 bool NxsAssumptionsBlock::HasCodonsBlockCommands() const
00567 {
00568 return (!codeSets.empty() || !codonPosSets.empty() || !codesMgr.IsEmpty());
00569 }
00570
00571 bool NxsAssumptionsBlock::CanReadBlockType(const NxsToken & token)
00572 {
00573 if (token.Equals("ASSUMPTIONS"))
00574 {
00575 id = "ASSUMPTIONS";
00576 readAs = ASSUMPTIONS_BLOCK_READ;
00577 return true;
00578 }
00579 if (token.Equals("SETS"))
00580 {
00581 id = "SETS";
00582 readAs = SETS_BLOCK_READ;
00583 return true;
00584 }
00585 if (token.Equals("CODONS"))
00586 {
00587 id = "CODONS";
00588 readAs = CODONS_BLOCK_READ;
00589 return true;
00590 }
00591 return token.Equals(GetID());
00592 }
00593
00594
00595
00596 void NxsAssumptionsBlock::WriteAsNexus(std::ostream &out) const
00597 {
00598 NxsAssumptionsBlock *t = const_cast<NxsAssumptionsBlock *>(this);
00599 const std::string ft = title;
00600 t->title.clear();
00601 NameOfAssumpBlockAsRead treatAs = this->readAs;
00602 if (treatAs == UNREAD_OR_GENERATED_BLOCK)
00603 {
00604
00605
00606
00607 if (HasAssumptionsBlockCommands())
00608 treatAs = ASSUMPTIONS_BLOCK_READ;
00609 else if (HasCodonsBlockCommands())
00610 treatAs = CODONS_BLOCK_READ;
00611 else if (HasSetsBlockCommands())
00612 treatAs = SETS_BLOCK_READ;
00613 }
00614 try
00615 {
00616 if (HasSetsBlockCommands())
00617 {
00618 if (treatAs == SETS_BLOCK_READ && !IsAutoGeneratedTitle())
00619 t->title = ft;
00620 out << "BEGIN SETS;\n";
00621 WriteBasicBlockCommands(out);
00622 this->WriteTaxSet(out);
00623 this->WriteCharSet(out);
00624 this->WriteTreeSet(out);
00625 this->WriteTaxPartition(out);
00626 this->WriteCharPartition(out);
00627 this->WriteTreePartition(out);
00628 if (treatAs == SETS_BLOCK_READ)
00629 {
00630 WriteSkippedCommands(out);
00631 t->title.clear();
00632 }
00633 out << "END;\n";
00634 }
00635 if (HasCodonsBlockCommands())
00636 {
00637 if (treatAs == CODONS_BLOCK_READ && !IsAutoGeneratedTitle())
00638 t->title = ft;
00639 out << "BEGIN CODONS;\n";
00640 WriteBasicBlockCommands(out);
00641 this->codesMgr.WriteGeneticCode(out);
00642 this->WriteCodonPosSet(out);
00643 this->WriteCodeSet(out);
00644 if (treatAs == CODONS_BLOCK_READ)
00645 {
00646 WriteSkippedCommands(out);
00647 t->title.clear();
00648 }
00649 out << "END;\n";
00650 }
00651 if (HasAssumptionsBlockCommands())
00652 {
00653 if (treatAs == ASSUMPTIONS_BLOCK_READ && !IsAutoGeneratedTitle())
00654 t->title = ft;
00655 out << "BEGIN ASSUMPTIONS;\n";
00656 WriteBasicBlockCommands(out);
00657 this->WriteExSet(out);
00658 this->transfMgr.WriteUserType(out);
00659 this->transfMgr.WriteWtSet(out);
00660 this->transfMgr.WriteTypeSet(out);
00661 this->WriteOptions(out);
00662 if (treatAs == ASSUMPTIONS_BLOCK_READ)
00663 WriteSkippedCommands(out);
00664 out << "END;\n";
00665 }
00666 }
00667 catch (...)
00668 {
00669 t->title = ft;
00670 throw;
00671 }
00672 t->title = ft;
00673 }
00674
00675
00676 NxsCharactersBlockAPI * NxsAssumptionsBlock::GetCharBlockPtr(int *status)
00677 {
00678 if (status)
00679 *status = GetCharLinkStatus();
00680 return charBlockPtr;
00681 }
00682 NxsTaxaBlockAPI * NxsAssumptionsBlock::GetTaxaBlockPtr(int *status)
00683 {
00684 if (status)
00685 *status = GetTaxaLinkStatus();
00686 return taxa;
00687 }
00688 NxsTreesBlockAPI * NxsAssumptionsBlock::GetTreesBlockPtr(int *status)
00689 {
00690 if (status)
00691 *status = GetTreesLinkStatus();
00692 return treesBlockPtr;
00693 }
00694
00695 NxsAssumptionsBlockAPI *NxsAssumptionsBlock::CreateNewAssumptionsBlock(NxsToken &token)
00696 {
00697 NxsAssumptionsBlockAPI * aba = NULL;
00698 if (nexusReader)
00699 {
00700 NxsString n("ASSUMPTIONS");
00701 NxsBlock * block = nexusReader->CreateBlockFromFactories(n, token, NULL);
00702 aba = static_cast<NxsAssumptionsBlockAPI *>(block);
00703 }
00704 if (aba == NULL)
00705 {
00706 NxsAssumptionsBlock *ab = new NxsAssumptionsBlock(NULL);
00707 ab->SetImplementsLinkAPI(this->ImplementsLinkAPI());
00708 aba = ab;
00709 }
00710 aba->SetNexus(nexusReader);
00711 passedRefOfOwnedBlock = false;
00712 createdSubBlocks.push_back(aba);
00713 return aba;
00714 }
00715
00716 NxsAssumptionsBlockAPI *NxsAssumptionsBlock::GetAssumptionsBlockForCharBlock(NxsCharactersBlockAPI *cb, NxsBlockLinkStatus status, NxsToken &token)
00717 {
00718 int cbstatus;
00719 NxsCharactersBlockAPI * thisCB = GetCharBlockPtr(&cbstatus);
00720 if (thisCB == NULL)
00721 {
00722 SetCharBlockPtr(cb, status);
00723 return this;
00724 }
00725 else if (cb == thisCB)
00726 {
00727 int f = cbstatus & NxsBlock::BLOCK_LINK_UNUSED_MASK;
00728 if (f == status)
00729 return this;
00730 if (!(cbstatus & NxsBlock::BLOCK_LINK_USED))
00731 {
00732 if (cbstatus == BLOCK_LINK_UNINITIALIZED || cbstatus == BLOCK_LINK_UNKNOWN_STATUS)
00733 {
00734 SetCharLinkStatus(status);
00735 return this;
00736 }
00737 }
00738 else
00739 {
00740
00741 if ((f | status) == (BLOCK_LINK_FROM_LINK_CMD | BLOCK_LINK_TO_ONLY_CHOICE))
00742 {
00743 charLinkStatus |= (BLOCK_LINK_FROM_LINK_CMD | BLOCK_LINK_TO_ONLY_CHOICE);
00744 return this;
00745 }
00746 }
00747 }
00748 for (VecAssumpBlockPtr::iterator bIt = createdSubBlocks.begin(); bIt != createdSubBlocks.end(); ++bIt)
00749 {
00750 NxsAssumptionsBlockAPI * c = *bIt;
00751 if (c && cb == c->GetCharBlockPtr(&cbstatus) && (cbstatus & BLOCK_LINK_UNUSED_MASK) == status)
00752 return c;
00753 }
00754 NxsAssumptionsBlockAPI *effBlock = CreateNewAssumptionsBlock(token);
00755 effBlock->SetCharBlockPtr(cb, status);
00756 return effBlock;
00757 }
00758
00759 NxsAssumptionsBlockAPI *NxsAssumptionsBlock::GetAssumptionsBlockForTaxaBlock(NxsTaxaBlockAPI *cb, NxsBlockLinkStatus status, NxsToken &token)
00760 {
00761 int cbstatus;
00762 NxsTaxaBlockAPI * thisCB = GetTaxaBlockPtr(&cbstatus);
00763 if (thisCB == NULL)
00764 {
00765 SetTaxaBlockPtr(cb, status);
00766 return this;
00767 }
00768 else if (cb == GetTaxaBlockPtr(&cbstatus))
00769 {
00770 int f = cbstatus & NxsBlock::BLOCK_LINK_UNUSED_MASK;
00771 if (f == status)
00772 return this;
00773 if (!(cbstatus & NxsBlock::BLOCK_LINK_USED))
00774 {
00775 if (cbstatus == BLOCK_LINK_UNINITIALIZED || cbstatus == BLOCK_LINK_UNKNOWN_STATUS)
00776 {
00777 SetTaxaLinkStatus(status);
00778 return this;
00779 }
00780 }
00781 else
00782 {
00783
00784 if ((f | status) == (BLOCK_LINK_FROM_LINK_CMD | BLOCK_LINK_TO_ONLY_CHOICE))
00785 {
00786 taxaLinkStatus |= (BLOCK_LINK_FROM_LINK_CMD | BLOCK_LINK_TO_ONLY_CHOICE);
00787 return this;
00788 }
00789 }
00790 }
00791 for (VecAssumpBlockPtr::iterator bIt = createdSubBlocks.begin(); bIt != createdSubBlocks.end(); ++bIt)
00792 {
00793 NxsAssumptionsBlockAPI * c = *bIt;
00794 if (c && cb == c->GetTaxaBlockPtr(&cbstatus) && (cbstatus & BLOCK_LINK_UNUSED_MASK) == status)
00795 return c;
00796 }
00797 NxsAssumptionsBlockAPI *effBlock = CreateNewAssumptionsBlock(token);
00798 effBlock->SetTaxaBlockPtr(cb, status);
00799 return effBlock;
00800 }
00801 NxsAssumptionsBlockAPI *NxsAssumptionsBlock::GetAssumptionsBlockForTreesBlock(NxsTreesBlockAPI *cb, NxsBlockLinkStatus status, NxsToken &token)
00802 {
00803 int cbstatus;
00804 NxsTreesBlockAPI * thisCB = GetTreesBlockPtr(&cbstatus);
00805 if (thisCB == NULL)
00806 {
00807 SetTreesBlockPtr(cb, status);
00808 return this;
00809 }
00810 else if (cb == GetTreesBlockPtr(&cbstatus))
00811 {
00812 int f = cbstatus & NxsBlock::BLOCK_LINK_UNUSED_MASK;
00813 if (f == status)
00814 return this;
00815 if (!(cbstatus & NxsBlock::BLOCK_LINK_USED))
00816 {
00817 if (cbstatus == BLOCK_LINK_UNINITIALIZED || cbstatus == BLOCK_LINK_UNKNOWN_STATUS)
00818 {
00819 SetTreesLinkStatus(status);
00820 return this;
00821 }
00822 }
00823 else
00824 {
00825
00826 if ((f | status) == (BLOCK_LINK_FROM_LINK_CMD | BLOCK_LINK_TO_ONLY_CHOICE))
00827 {
00828 treesLinkStatus |= (BLOCK_LINK_FROM_LINK_CMD | BLOCK_LINK_TO_ONLY_CHOICE);
00829 return this;
00830 }
00831 }
00832 }
00833 for (VecAssumpBlockPtr::iterator bIt = createdSubBlocks.begin(); bIt != createdSubBlocks.end(); ++bIt)
00834 {
00835 NxsAssumptionsBlockAPI * c = *bIt;
00836 if (c && cb == c->GetTreesBlockPtr(&cbstatus) && (cbstatus & BLOCK_LINK_UNUSED_MASK) == status)
00837 return c;
00838 }
00839 NxsAssumptionsBlockAPI *effBlock = CreateNewAssumptionsBlock(token);
00840 effBlock->SetTreesBlockPtr(cb, status);
00841 return effBlock;
00842 }
00843
00844 NxsAssumptionsBlockAPI *NxsAssumptionsBlock::GetAssumptionsBlockForCharTitle(const char *charTitle, NxsToken &token, const char *cmd)
00845 {
00846 if (!nexusReader)
00847 NxsNCLAPIException("No NxsReader when reading Assumptions block.");
00848 if (charTitle == NULL)
00849 {
00850 int cbstatus;
00851 NxsCharactersBlockAPI * thisCB = GetCharBlockPtr(&cbstatus);
00852 int ust = cbstatus & NxsBlock::BLOCK_LINK_UNUSED_MASK;
00853 if (thisCB != NULL && ust != BLOCK_LINK_UNINITIALIZED && ust != BLOCK_LINK_UNKNOWN_STATUS)
00854 return this;
00855 }
00856 unsigned ncb = 0;
00857 NxsCharactersBlockAPI * cb = nexusReader->GetCharBlockByTitle(charTitle, &ncb);
00858 NxsAssumptionsBlockAPI *effectiveB = NULL;
00859 if (cb == NULL)
00860 {
00861 if (charBlockPtr)
00862 {
00863 const NxsString t=charBlockPtr->GetID();
00864 if (t.empty())
00865 {
00866 if (charTitle == NULL)
00867 effectiveB = this;
00868 }
00869 else
00870 {
00871 if (NxsString::case_insensitive_equals(charTitle, t.c_str()))
00872 effectiveB = this;
00873 }
00874 }
00875 if (effectiveB == NULL)
00876 {
00877 errormsg.clear();
00878 errormsg << "A CHARACTERS (or DATA) block ";
00879 if (charTitle)
00880 errormsg << "with the title " << NxsString::GetEscaped(charTitle);
00881 errormsg << " must precede an " << id << " block with a " << cmd << " command.";
00882 errormsg << "\n(If such a block exists, then this program may not be using an API for the NCL library that supports block linking).";
00883 throw NxsException(errormsg, token);
00884 }
00885 }
00886 else if (ncb > 1)
00887 {
00888 errormsg = "Multiple CHARACTERS blocks have been encountered, but a ";
00889 errormsg += cmd;
00890 errormsg += " command was found which does not specify which CHARACTERS block it uses. The most recent CHARACTERS block will be used.";
00891 if (nexusReader)
00892 nexusReader->NexusWarnToken(errormsg, NxsReader::AMBIGUOUS_CONTENT_WARNING, token);
00893 errormsg.clear();
00894 effectiveB = GetAssumptionsBlockForCharBlock(cb, NxsBlock::BLOCK_LINK_TO_MOST_RECENT, token);
00895 }
00896 else
00897 {
00898 NxsBlockLinkStatus statusRequested = (charTitle == NULL ? NxsBlock::BLOCK_LINK_TO_ONLY_CHOICE : NxsBlock::BLOCK_LINK_FROM_LINK_CMD);
00899 effectiveB = GetAssumptionsBlockForCharBlock(cb, statusRequested, token);
00900 }
00901 effectiveB->FlagCharBlockAsUsed();
00902 return effectiveB;
00903 }
00904
00905 NxsAssumptionsBlockAPI *NxsAssumptionsBlock::GetAssumptionsBlockForTaxaTitle(const char *taxTitle, NxsToken &token, const char *cmd)
00906 {
00907 if (!nexusReader)
00908 NxsNCLAPIException("No NxsReader when reading Assumptions block.");
00909 if (taxTitle == NULL)
00910 {
00911 int cbstatus;
00912 NxsTaxaBlockAPI * thisCB = GetTaxaBlockPtr(&cbstatus);
00913 int ust = cbstatus & NxsBlock::BLOCK_LINK_UNUSED_MASK;
00914 if (thisCB != NULL && ust != BLOCK_LINK_UNINITIALIZED && ust != BLOCK_LINK_UNKNOWN_STATUS)
00915 return this;
00916 }
00917 unsigned ncb = 0;
00918 NxsTaxaBlockAPI * cb = nexusReader->GetTaxaBlockByTitle(taxTitle, &ncb);
00919 NxsAssumptionsBlockAPI *effectiveB = NULL;
00920 if (cb == NULL)
00921 {
00922 if (taxa)
00923 {
00924 const NxsString t=taxa->GetID();
00925 if (t.empty())
00926 {
00927 if (taxTitle == NULL)
00928 effectiveB = this;
00929 }
00930 else
00931 {
00932 if (NxsString::case_insensitive_equals(taxTitle, t.c_str()))
00933 effectiveB = this;
00934 }
00935 }
00936 if (effectiveB == NULL)
00937 {
00938 errormsg.clear();
00939 errormsg << "A TAXA block ";
00940 if (taxTitle)
00941 errormsg << "with the title " << NxsString::GetEscaped(taxTitle);
00942 errormsg << " must precede an " << id << " block with a " << cmd << " command.";
00943 errormsg << "\n(If such a block exists, then this program may not be using an API for the NCL library that supports block linking).";
00944 throw NxsException(errormsg, token);
00945 }
00946 }
00947 else if (ncb > 1)
00948 {
00949 errormsg = "Multiple TAXA blocks have been encountered, but a ";
00950 errormsg += cmd;
00951 errormsg += " command was found which does not specify which TAXA block it uses. The most recent TAXA block will be used.";
00952 nexusReader->NexusWarnToken(errormsg, NxsReader::AMBIGUOUS_CONTENT_WARNING, token);
00953 errormsg.clear();
00954 effectiveB = GetAssumptionsBlockForTaxaBlock(cb, NxsBlock::BLOCK_LINK_TO_MOST_RECENT, token);
00955 }
00956 else
00957 {
00958 NxsBlockLinkStatus statusRequested = (taxTitle == NULL ? NxsBlock::BLOCK_LINK_TO_ONLY_CHOICE : NxsBlock::BLOCK_LINK_FROM_LINK_CMD);
00959 effectiveB = GetAssumptionsBlockForTaxaBlock(cb, statusRequested, token);
00960 }
00961 effectiveB->FlagTaxaBlockAsUsed();
00962 return effectiveB;
00963 }
00964
00965 NxsAssumptionsBlockAPI *NxsAssumptionsBlock::GetAssumptionsBlockForTreesTitle(const char *treesTitle, NxsToken &token, const char *cmd)
00966 {
00967 if (!nexusReader)
00968 NxsNCLAPIException("No NxsReader when reading Assumptions block.");
00969 if (treesTitle == NULL)
00970 {
00971 int cbstatus;
00972 NxsTreesBlockAPI * thisCB = GetTreesBlockPtr(&cbstatus);
00973 int ust = cbstatus & NxsBlock::BLOCK_LINK_UNUSED_MASK;
00974 if (thisCB != NULL && ust != BLOCK_LINK_UNINITIALIZED && ust != BLOCK_LINK_UNKNOWN_STATUS)
00975 return this;
00976 }
00977 unsigned ncb = 0;
00978 NxsTreesBlockAPI * cb = nexusReader->GetTreesBlockByTitle(treesTitle, &ncb);
00979 NxsAssumptionsBlockAPI *effectiveB = NULL;
00980 if (cb == NULL)
00981 {
00982 if (treesBlockPtr)
00983 {
00984 const NxsString t=treesBlockPtr->GetID();
00985 if (t.empty())
00986 {
00987 if (treesTitle == NULL)
00988 effectiveB = this;
00989 }
00990 else
00991 {
00992 if (NxsString::case_insensitive_equals(treesTitle, t.c_str()))
00993 effectiveB = this;
00994 }
00995 }
00996 if (effectiveB == NULL)
00997 {
00998 errormsg.clear();
00999 errormsg << "A TREES block";
01000 if (treesTitle)
01001 errormsg << "with the title " << NxsString::GetEscaped(treesTitle);
01002 errormsg << " must precede an " << id << " block with a " << cmd << " command.";
01003 errormsg << "\n(If such a block exists, then this program may not be using an API for the NCL library that supports block linking).";
01004 throw NxsException(errormsg, token);
01005 }
01006 }
01007 else if (ncb > 1)
01008 {
01009 errormsg = "Multiple TREES blocks have been encountered, but a ";
01010 errormsg += cmd;
01011 errormsg += " command was found which does not specify which TREES block it uses. The most recent TREES block will be used.";
01012 nexusReader->NexusWarnToken(errormsg, NxsReader::AMBIGUOUS_CONTENT_WARNING, token);
01013 errormsg.clear();
01014 effectiveB = GetAssumptionsBlockForTreesBlock(cb, NxsBlock::BLOCK_LINK_TO_MOST_RECENT, token);
01015 }
01016 else
01017 {
01018 NxsBlockLinkStatus statusRequested = (treesTitle == NULL ? NxsBlock::BLOCK_LINK_TO_ONLY_CHOICE : NxsBlock::BLOCK_LINK_FROM_LINK_CMD);
01019 effectiveB = GetAssumptionsBlockForTreesBlock(cb, statusRequested, token);
01020 }
01021 effectiveB->FlagTreesBlockAsUsed();
01022 return effectiveB;
01023 }
01024
01025 void NxsAssumptionsBlock::SetCharLinkStatus(NxsBlockLinkStatus s)
01026 {
01027 if (charLinkStatus & NxsBlock::BLOCK_LINK_USED)
01028 {
01029 throw NxsNCLAPIException("Resetting a used charLinkStatus");
01030 }
01031 charLinkStatus = s;
01032 }
01033
01034 void NxsAssumptionsBlock::SetTaxaLinkStatus(NxsBlockLinkStatus s)
01035 {
01036 if (taxaLinkStatus & NxsBlock::BLOCK_LINK_USED)
01037 {
01038 throw NxsNCLAPIException("Resetting a used taxaLinkStatus");
01039 }
01040 taxaLinkStatus = s;
01041 }
01042
01043 void NxsAssumptionsBlock::SetTreesLinkStatus(NxsBlockLinkStatus s)
01044 {
01045 if (treesLinkStatus & NxsBlock::BLOCK_LINK_USED)
01046 {
01047 throw NxsNCLAPIException("Resetting a used charLinkStatus");
01048 }
01049 treesLinkStatus = s;
01050 }
01051
01052 void NxsAssumptionsBlock::SetCharBlockPtr(NxsCharactersBlockAPI * c, NxsBlockLinkStatus s)
01053 {
01054 SetCharLinkStatus(s);
01055 charBlockPtr = c;
01056 }
01057
01058 void NxsAssumptionsBlock::SetTaxaBlockPtr(NxsTaxaBlockAPI *c, NxsBlockLinkStatus s)
01059 {
01060 SetTaxaLinkStatus(s);
01061 taxa = c;
01062 }
01063
01064 void NxsAssumptionsBlock::SetTreesBlockPtr(NxsTreesBlockAPI * c, NxsBlockLinkStatus s)
01065 {
01066 SetTreesLinkStatus(s);
01067 treesBlockPtr = c;
01068 }
01069
01073 NxsAssumptionsBlock::NxsAssumptionsBlock(
01074 NxsTaxaBlockAPI *t)
01075 :taxa(t),
01076 charBlockPtr(NULL),
01077 treesBlockPtr(NULL),
01078 charLinkStatus(NxsBlock::BLOCK_LINK_UNINITIALIZED),
01079 taxaLinkStatus(NxsBlock::BLOCK_LINK_UNINITIALIZED),
01080 treesLinkStatus(NxsBlock::BLOCK_LINK_UNINITIALIZED),
01081 passedRefOfOwnedBlock(false)
01082 {
01083 taxaLinkStatus = (t == NULL ? NxsBlock::BLOCK_LINK_UNINITIALIZED : NxsBlock::BLOCK_LINK_UNKNOWN_STATUS);
01084 id = "ASSUMPTIONS";
01085 Reset();
01086 }
01087
01091 NxsAssumptionsBlock::~NxsAssumptionsBlock()
01092 {
01093 }
01094
01100 void NxsAssumptionsBlock::ReplaceTaxaBlockPtr(
01101 NxsTaxaBlockAPI *tb)
01102 {
01103 NCL_ASSERT(tb != NULL);
01104 if (tb != taxa)
01105 SetTaxaBlockPtr(tb, NxsBlock::BLOCK_LINK_UNKNOWN_STATUS);
01106 }
01107
01111 int NxsAssumptionsBlock::GetNumCharSets() const
01112 {
01113 return (int)charsets.size();
01114 }
01115
01119 void NxsAssumptionsBlock::GetCharSetNames(
01120 NxsStringVector &names) const
01121 {
01122 names.erase(names.begin(), names.end());
01123 NxsUnsignedSetMap::const_iterator i;
01124 for (i = charsets.begin(); i != charsets.end(); i++)
01125 names.push_back((*i).first);
01126 }
01127
01131 const NxsUnsignedSet *NxsAssumptionsBlock::GetCharSet(
01132 NxsString n) const
01133 {
01134 NxsUnsignedSetMap::const_iterator it = charsets.find(n);
01135 if (it == charsets.end())
01136 return NULL;
01137 return &(it->second);
01138 }
01139
01143 int NxsAssumptionsBlock::GetNumCharPartitions()
01144 {
01145 return (int)charPartitions.size();
01146 }
01147
01151 void NxsAssumptionsBlock::GetCharPartitionNames(
01152 vector<std::string> &names)
01153 {
01154 names.erase(names.begin(), names.end());
01155 NxsPartitionsByName::const_iterator i;
01156 for (i = charPartitions.begin(); i != charPartitions.end(); i++)
01157 names.push_back((*i).first);
01158 }
01159
01163 const NxsPartition *NxsAssumptionsBlock::GetCharPartition(
01164 std::string nm) const
01165 {
01166 NxsPartitionsByName::const_iterator it = charPartitions.find(nm);
01167 if (it == charPartitions.end())
01168 return NULL;
01169 return &(it->second);
01170 }
01171
01175 int NxsAssumptionsBlock::GetNumTaxSets()
01176 {
01177 return (int)taxsets.size();
01178 }
01179
01183 void NxsAssumptionsBlock::GetTaxSetNames(
01184 NxsStringVector &names)
01185 {
01186 names.erase(names.begin(), names.end());
01187 NxsUnsignedSetMap::const_iterator i;
01188 for (i = taxsets.begin(); i != taxsets.end(); i++)
01189 names.push_back((*i).first);
01190 }
01191
01195 NxsUnsignedSet &NxsAssumptionsBlock::GetTaxSet(
01196 NxsString nm)
01197 {
01198 return taxsets[nm];
01199 }
01200
01201
01205 int NxsAssumptionsBlock::GetNumExSets()
01206 {
01207 return (int)exsets.size();
01208 }
01209
01213 void NxsAssumptionsBlock::GetExSetNames(
01214 NxsStringVector &names)
01215 {
01216 names.erase(names.begin(), names.end());
01217 NxsUnsignedSetMap::const_iterator i;
01218 for (i = exsets.begin(); i != exsets.end(); i++)
01219 names.push_back((*i).first);
01220 }
01221
01225 NxsUnsignedSet &NxsAssumptionsBlock::GetExSet(
01226 NxsString nm)
01227 {
01228 return exsets[nm];
01229 }
01230
01235 NxsString NxsAssumptionsBlock::GetDefExSetName()
01236 {
01237 return def_exset;
01238 }
01239
01245 void NxsAssumptionsBlock::ApplyExset(
01246 NxsString n)
01247 {
01248 NxsString nm(n.c_str());
01249 NCL_ASSERT(charBlockPtr != NULL);
01250 charBlockPtr->ApplyExset(exsets[nm]);
01251 }
01252
01253 NxsAssumptionsBlockAPI *NxsAssumptionsBlock::DealWithPossibleParensInCharDependentCmd(NxsToken &token, const char *cmd, const std::vector<std::string> *unsupported, bool * isVect)
01254 {
01255 token.GetNextToken();
01256 NxsString charblock_name;
01257 errormsg.clear();
01258 if (isVect)
01259 *isVect = false;
01260 if (token.Equals("("))
01261 {
01262 token.GetNextToken();
01263 while (!token.Equals(")"))
01264 {
01265 if (token.Equals("CHARACTERS"))
01266 {
01267 NxsString t;
01268 t << "after \"(Characters\" in a " << cmd << " command";
01269 DemandEquals(token, t.c_str());
01270 token.GetNextToken();
01271 charblock_name = token.GetToken();
01272 }
01273 else if (token.Equals("VECTOR"))
01274 {
01275 if (!isVect)
01276 GenerateNxsException(token, "VECTOR-style set definitions are not currently supported");
01277 else
01278 *isVect = true;
01279 }
01280 else if (token.Equals("NOTOKENS"))
01281 GenerateNxsException(token, "NOTOKENS-style set definitions are not currently supported");
01282 else if (token.Equals(";"))
01283 {
01284 NxsString s;
01285 s << "; encountered in " << cmd << " command before parentheses were closed";
01286 GenerateNxsException(token, s.c_str());
01287 }
01288 else if (!(token.Equals("STANDARD") || token.Equals("TOKENS")) && nexusReader)
01289 {
01290 bool found = false;
01291 if (unsupported)
01292 {
01293 for (std::vector<std::string>::const_iterator u = unsupported->begin(); u != unsupported->end(); ++u)
01294 {
01295 if (token.Equals(u->c_str()))
01296 {
01297 found = true;
01298 break;
01299 }
01300 }
01301 }
01302 if (found)
01303 {
01304 NxsString s;
01305 s << "The " << token.GetTokenReference()<< " as a " << cmd << " qualifier is not supported.";
01306 GenerateNxsException(token, s.c_str());
01307 }
01308 else
01309 {
01310 errormsg << "Skipping unknown " << cmd << " qualifier: " << token.GetTokenReference();
01311 nexusReader->NexusWarnToken(errormsg, NxsReader::SKIPPING_CONTENT_WARNING, token);
01312 errormsg.clear();
01313 }
01314 }
01315 token.GetNextToken();
01316 }
01317 token.GetNextToken();
01318 }
01319 const char *cbn = (charblock_name.empty() ? NULL : charblock_name.c_str());
01320 NxsString u;
01321 u << "in " << cmd << " definition";
01322 DemandIsAtEquals(token, u.c_str());
01323 return this->GetAssumptionsBlockForCharTitle(cbn, token, cmd);
01324 }
01325
01326
01330 void NxsAssumptionsBlock::HandleTypeSet(
01331 NxsToken &token)
01332 {
01333 errormsg.clear();
01334 bool asterisked = false;
01335 token.GetNextToken();
01336 if (token.Equals("*"))
01337 {
01338 asterisked = true;
01339 token.GetNextToken();
01340 }
01341 NxsString typeset_name = token.GetToken();
01342
01343 NxsAssumptionsBlockAPI * effectiveAssumpBlock = DealWithPossibleParensInCharDependentCmd(token, "TypeSet");
01344 token.GetNextToken();
01345 NCL_ASSERT(effectiveAssumpBlock);
01346 NxsPartition newPartition;
01347 NxsCharactersBlockAPI *cbp = effectiveAssumpBlock->GetCharBlockPtr();
01348 NCL_ASSERT(cbp);
01349 effectiveAssumpBlock->ReadPartitionDef(newPartition, *cbp, typeset_name, "Character", "TypeSet", token, false, false, false);
01350 NxsTransformationManager &ctm = cbp->GetNxsTransformationManagerRef();
01351 for (NxsPartition::const_iterator groupIt = newPartition.begin(); groupIt != newPartition.end(); ++groupIt)
01352 {
01353 if (!ctm.IsValidTypeName(groupIt->first))
01354 {
01355 errormsg << "The group name " << groupIt->first << " found in a TypeSet command does not correspond to a known type";
01356 throw NxsException(errormsg, token);
01357 }
01358 }
01359 NxsTransformationManager &tm = effectiveAssumpBlock->GetNxsTransformationManagerRef();
01360 ctm.AddTypeSet(typeset_name, newPartition, asterisked);
01361 tm.AddTypeSet(typeset_name, newPartition, asterisked);
01362 }
01363
01364
01365 void NxsAssumptionsBlock::HandleUserType(NxsToken& token)
01366 {
01367 token.GetNextToken();
01368 errormsg.clear();
01369 if (token.Equals("*"))
01370 {
01371 errormsg << "An * is ignored in a UserType command";
01372 if (nexusReader)
01373 nexusReader->NexusWarnToken(errormsg, NxsReader::SKIPPING_CONTENT_WARNING, token);
01374 token.GetNextToken();
01375 errormsg.clear();
01376 }
01377 NxsString user_type_name = token.GetToken();
01378
01379 token.GetNextToken();
01380 NxsString charblock_name;
01381 bool floatMat = false;
01382 bool cstreeform = false;
01383 if (token.Equals("("))
01384 {
01385 token.GetNextToken();
01386 while (!token.Equals(")"))
01387 {
01388 if (token.Equals("CHARACTERS"))
01389 {
01390 NxsString t;
01391 t << "after \"(Characters\" in a UserType command";
01392 DemandEquals(token, t.c_str());
01393 token.GetNextToken();
01394 charblock_name = token.GetToken();
01395 }
01396 else if (token.Equals("CSTREE"))
01397 cstreeform = true;
01398 else if (token.Equals("NOTOKENS"))
01399 GenerateNxsException(token, "NOTOKENS-style UserType are not supported");
01400 else if (token.Equals("REALMATRIX"))
01401 floatMat = true;
01402 else if (token.Equals(";"))
01403 {
01404 NxsString s;
01405 s << "; encountered in UserType command before parentheses were closed";
01406 GenerateNxsException(token, s.c_str());
01407 }
01408 else if (!(token.Equals("STEPMATRIX") || token.Equals("TOKENS")) && nexusReader)
01409 {
01410 errormsg << "Skipping unknown UserType qualifier: " << token.GetTokenReference();
01411 nexusReader->NexusWarnToken(errormsg, NxsReader::SKIPPING_CONTENT_WARNING, token);
01412 errormsg.clear();
01413 }
01414 token.GetNextToken();
01415 }
01416 token.GetNextToken();
01417 }
01418 if (token.Equals("STEPMATRIX") || token.Equals("REALMATRIX"))
01419 {
01420 errormsg << "UserType qualifier "<< token.GetTokenReference() << " should occur in parentheses ("<< token.GetTokenReference() <<") ";
01421 nexusReader->NexusWarnToken(errormsg, NxsReader::DEPRECATED_WARNING, token);
01422 errormsg.clear();
01423 token.GetNextToken();
01424 }
01425 DemandIsAtEquals(token, "in UserType definition");
01426
01427 const char *cbn = (charblock_name.empty() ? NULL : charblock_name.c_str());
01428 NxsAssumptionsBlockAPI * effectiveAssumpBlock = this->GetAssumptionsBlockForCharTitle(cbn, token, "UserType");
01429 NCL_ASSERT(effectiveAssumpBlock);
01430 NxsCharactersBlockAPI *cbp = effectiveAssumpBlock->GetCharBlockPtr();
01431 NCL_ASSERT(cbp);
01432
01433 NxsRealStepMatrix::DblMatrix dm;
01434 NxsIntStepMatrix::IntMatrix im;
01435 std::vector<std::string> symbolsOrder;
01436 const std::vector<const NxsDiscreteDatatypeMapper *> mappers = cbp->GetAllDatatypeMappers();
01437
01438 if (cstreeform)
01439 {
01440 bool success = false;
01441 ProcessedNxsCommand tokenVec;
01442 token.GetNextToken();
01443 token.ProcessAsCommand(&tokenVec);
01444
01445 for (std::vector<const NxsDiscreteDatatypeMapper *>::const_iterator mIt = mappers.begin(); !success && mIt != mappers.end(); ++mIt)
01446 {
01447 const NxsDiscreteDatatypeMapper * mapper = *mIt;
01448 std::string s = mapper->GetSymbolsWithGapChar();
01449 symbolsOrder.clear();
01450 std::map<std::string, unsigned> symMap;
01451 for (unsigned i = 0; i < s.length(); ++i)
01452 {
01453 std::string sym(1, s[i]);
01454 symbolsOrder.push_back(sym);
01455 symMap[sym] = i;
01456 }
01457 std::string newick;
01458 NxsFullTreeDescription treeDesc(newick, user_type_name, 0);
01459 BogusToIndMapper labelToIndMapper;
01460 try
01461 {
01462 NxsTreesBlock::ProcessTokenVecIntoTree(tokenVec, treeDesc, &labelToIndMapper, symMap, false, nexusReader, mapper->IsRespectCase());
01463 success = true;
01464 }
01465 catch (NxsException &x)
01466 {
01467 if (!labelToIndMapper.queried)
01468 throw x;
01469 }
01470 NxsSimpleTree cstree(treeDesc, 1, 1.0);
01471 if (treeDesc.SomeEdgesHaveLengths() && !treeDesc.EdgeLengthsAreAllIntegers())
01472 {
01473 floatMat = true;
01474 dm = cstree.GetDblPathDistances(false);
01475 if (dm.size() < symbolsOrder.size())
01476 symbolsOrder.resize(dm.size());
01477 else if (dm.size() > symbolsOrder.size())
01478 success = false;
01479 }
01480 else
01481 {
01482 im = cstree.GetIntPathDistances();
01483 if (im.size() < symbolsOrder.size())
01484 symbolsOrder.resize(im.size());
01485 else if (im.size() > symbolsOrder.size())
01486 success = false;
01487 }
01488
01489 }
01490 if (!success)
01491 {
01492 errormsg << "No datatype was found with all of the symbols the UserType CSTree";
01493 throw NxsException(errormsg, token);
01494 }
01495 }
01496 else
01497 {
01498
01499 token.GetNextToken();
01500 NxsString t = token.GetToken();
01501 long longNstates;
01502 if (!NxsString::to_long(t.c_str(), &longNstates) || longNstates < 2)
01503 {
01504 errormsg << "Expecting a number of states after the = in the UserType command (the number of states must be greater than one). Found " << t;
01505 throw NxsException(t, token);
01506 }
01507 const bool respectCase = cbp->IsRespectCase();
01508 unsigned nStates = (unsigned) longNstates;
01509 NxsRealStepMatrix::DblVec dv(nStates, DBL_MAX);
01510 NxsIntStepMatrix::IntVec iv(nStates, INT_MAX);
01511 dm.assign(nStates, dv);
01512 im.assign(nStates, iv);
01513 std::set<char> symbolsSet;
01514 for (unsigned i = 0; i < nStates;)
01515 {
01516 token.GetNextToken();
01517 if (token.Equals(";"))
01518 {
01519 errormsg << "; prematurely terminated the state declaration portion of a UserType stepmatrix.";
01520 throw NxsException(t, token);
01521 }
01522 NxsString tokStr = token.GetToken();
01523 if (!respectCase)
01524 tokStr.ToUpper();
01525 for (NxsString::const_iterator cIt = tokStr.begin(); cIt != tokStr.end(); ++cIt, ++i)
01526 {
01527 char s = *cIt;
01528 if (symbolsSet.count(s) > 0)
01529 {
01530 errormsg << "State names cannot be repeated in a UserType stepmatrix. " << s << " was encountered more than once.";
01531 throw NxsException(t, token);
01532 }
01533 bool found = false;
01534 for (std::vector<const NxsDiscreteDatatypeMapper *>::const_iterator mIt = mappers.begin(); mIt != mappers.end(); ++mIt)
01535 {
01536 const NxsDiscreteDatatypeMapper * mapper = *mIt;
01537 if (mapper->PositionInSymbolsOrGaps(s) != NXS_INVALID_STATE_CODE)
01538 {
01539 found = true;
01540 break;
01541 }
01542 }
01543 if (!found)
01544 {
01545 errormsg << "Unrecognized state " << s << "in UserType stepmatrix.";
01546 throw NxsException(t, token);
01547 }
01548 symbolsSet.insert(s);
01549 symbolsOrder.push_back(std::string(1,s));
01550 }
01551 }
01552
01553 double currDblWt;
01554 long currLongWt;
01555
01556 for (unsigned i = 0; i < nStates; ++i)
01557 {
01558 for (unsigned j = 0; j < nStates; ++j)
01559 {
01560 token.SetLabileFlagBit(NxsToken::hyphenNotPunctuation);
01561 token.GetNextToken();
01562 NxsString s = token.GetToken();
01563 if (i == j && (token.Equals(".") || token.Equals("-")))
01564 {
01565 im[i][i] = 0;
01566 dm[i][i] = 0.0;
01567 }
01568 else
01569 {
01570 bool v = NxsString::to_double(s.c_str(), &currDblWt);
01571 if (!v)
01572 {
01573 if (!token.Equals("I") && !token.Equals("INF"))
01574 {
01575 errormsg << "Expecting a number or i (for infinity) as an element of the UserType stepmatrix. Found " << s;
01576 throw NxsException(errormsg, token);
01577 }
01578 }
01579 else
01580 {
01581 dm[i][j] = currDblWt;
01582 if (!floatMat)
01583 {
01584 floatMat = !NxsString::to_long(s.c_str(), &currLongWt);
01585 if (!floatMat)
01586 im[i][j] = currLongWt;
01587 }
01588 }
01589 }
01590 }
01591 }
01592
01593 token.GetNextToken();
01594 if (!token.Equals(";"))
01595 {
01596 errormsg << "Expecting ; at the end of the UserType command. Found " << token.GetTokenReference();
01597 throw NxsException(t, token);
01598 }
01599 }
01600
01601 NxsTransformationManager &ctm = cbp->GetNxsTransformationManagerRef();
01602 NxsTransformationManager &tm = effectiveAssumpBlock->GetNxsTransformationManagerRef();
01603 if (floatMat)
01604 {
01605 const NxsRealStepMatrix nrsm(symbolsOrder, dm);
01606 ctm.AddRealType(user_type_name, nrsm);
01607 tm.AddRealType(user_type_name, nrsm);
01608 }
01609 else
01610 {
01611 const NxsIntStepMatrix nism(symbolsOrder, im);
01612 ctm.AddIntType(user_type_name, nism);
01613 tm.AddIntType(user_type_name, nism);
01614 }
01615 }
01616
01617
01618 NxsGeneticCodesManager::NxsGeneticCodesManager()
01619 {
01620 standardCodeNames.insert(std::string("UNIVERSAL"));
01621 standardCodeNames.insert(std::string("UNIVERSAL.EXT"));
01622 standardCodeNames.insert(std::string("MTDNA.DROS"));
01623 standardCodeNames.insert(std::string("MTDNA.DROS.EXT"));
01624 standardCodeNames.insert(std::string("MTDNA.MAM"));
01625 standardCodeNames.insert(std::string("MTDNA.MAM.EXT"));
01626 standardCodeNames.insert(std::string("MTDNA.YEAST"));
01627 }
01628
01629 bool NxsGeneticCodesManager::IsValidCodeName(const std::string &n) const
01630 {
01631 std::string capName(n.c_str());
01632 NxsString::to_upper(capName);
01633 return (standardCodeNames.count(capName) > 0) || (userDefinedCodeNames.count(capName) > 0);
01634 }
01638 void NxsAssumptionsBlock::HandleCodeSet(
01639 NxsToken &token)
01640 {
01641 bool asterisked = false;
01642 token.GetNextToken();
01643 if (token.Equals("*"))
01644 {
01645 asterisked = true;
01646 token.GetNextToken();
01647 }
01648 std::vector<std::string> unsupported;
01649 unsupported.push_back(std::string("TAXA"));
01650 unsupported.push_back(std::string("UNALIGNED"));
01651 NxsString codeset_name = token.GetToken();
01652
01653 NxsAssumptionsBlockAPI * effectiveAssumpBlock = DealWithPossibleParensInCharDependentCmd(token, "CodeSet", &unsupported);
01654 token.GetNextToken();
01655 NxsPartition newPartition;
01656 NxsCharactersBlockAPI *cbp = effectiveAssumpBlock->GetCharBlockPtr();
01657 NCL_ASSERT(cbp);
01658 effectiveAssumpBlock->ReadPartitionDef(newPartition, *cbp, codeset_name, "Character", "CodeSet", token, false, false, false);
01659 NxsGeneticCodesManager &gcm = effectiveAssumpBlock->GetNxsGeneticCodesManagerRef();
01660 for (NxsPartition::const_iterator groupIt = newPartition.begin(); groupIt != newPartition.end(); ++groupIt)
01661 {
01662 const std::string & s = groupIt->first;
01663 if (!gcm.IsValidCodeName(s))
01664 {
01665 errormsg << "The Genetic code name " << groupIt->first << " found in a CodeSet command does not correspond to a known code";
01666 throw NxsException(errormsg, token);
01667 }
01668 }
01669 effectiveAssumpBlock->AddCodeSet(codeset_name, newPartition, asterisked);
01670 }
01671
01675 void NxsAssumptionsBlock::HandleCodonPosSet(
01676 NxsToken &token)
01677 {
01678 bool asterisked = false;
01679 token.GetNextToken();
01680 if (token.Equals("*"))
01681 {
01682 asterisked = true;
01683 token.GetNextToken();
01684 }
01685 NxsString codonPosSetName = token.GetToken();
01686
01687 NxsAssumptionsBlockAPI * effectiveAssumpBlock = DealWithPossibleParensInCharDependentCmd(token, "CodonPosSet", NULL);
01688 token.GetNextToken();
01689 NxsPartition newPartition;
01690 NxsCharactersBlockAPI *cbp = effectiveAssumpBlock->GetCharBlockPtr();
01691 NCL_ASSERT(cbp);
01692 effectiveAssumpBlock->ReadPartitionDef(newPartition, *cbp, codonPosSetName, "Character", "CodonPosSet", token, false, false, false);
01693 for (NxsPartition::const_iterator groupIt = newPartition.begin(); groupIt != newPartition.end(); ++groupIt)
01694 {
01695 const std::string & s = groupIt->first;
01696 bool legal = false;
01697 if (s.length() == 1)
01698 {
01699 const char c = s[0];
01700 if (c == 'n' || c == 'N' || c == '1' || c == '2' || c == '3' || c == '?')
01701 legal = true;
01702 }
01703 if (!legal)
01704 {
01705 errormsg << "The Codon Position category name " << groupIt->first << " found in a CodonPosSet command is not legal. \"N\", \"1\", \"2\", or \"3\" were expected.";
01706 throw NxsException(errormsg, token);
01707 }
01708 }
01709 effectiveAssumpBlock->AddCodonPosSet(codonPosSetName, newPartition, asterisked);
01710 cbp->AddNewCodonPosPartition(codonPosSetName, newPartition, asterisked);
01711 }
01712
01713 class NxsSetVectorItemValidator
01714 {
01715 public:
01716 virtual ~NxsSetVectorItemValidator(){};
01717 virtual std::string convert(NxsToken &) = 0;
01718 };
01719
01720 class WtSetVectorItemValidator: public NxsSetVectorItemValidator
01721 {
01722 public:
01723 virtual ~WtSetVectorItemValidator(){};
01724 virtual std::string convert(NxsToken & token)
01725 {
01726 NxsString s = token.GetToken();
01727 const char * c = s.c_str();
01728 long currLongWt;
01729 double currDblWt;
01730 if (NxsString::to_long(c, &currLongWt) || NxsString::to_double(s.c_str(), &currDblWt))
01731 return std::string(c);
01732 NxsString errormsg;
01733 errormsg << "Expecting a number as a character weight. Found \"" << c << "\" instead.";
01734 throw NxsException(errormsg, token);
01735 }
01736
01737 };
01738
01742 void NxsAssumptionsBlock::HandleWeightSet(
01743 NxsToken &token)
01744 {
01745 bool asterisked = false;
01746 token.GetNextToken();
01747 if (token.Equals("*"))
01748 {
01749 asterisked = true;
01750 token.GetNextToken();
01751 }
01752 NxsString wtset_name = token.GetToken();
01753
01754 bool isVect;
01755 NxsAssumptionsBlockAPI * effectiveAssumpBlock = DealWithPossibleParensInCharDependentCmd(token, "WtSet", NULL, &isVect);
01756 token.SetLabileFlagBit(NxsToken::hyphenNotPunctuation);
01757 token.GetNextToken();
01758 NxsPartition newPartition;
01759 NxsCharactersBlockAPI *cbp = effectiveAssumpBlock->GetCharBlockPtr();
01760 NCL_ASSERT(cbp);
01761 if (isVect)
01762 {
01763 WtSetVectorItemValidator validator;
01764 effectiveAssumpBlock->ReadVectorPartitionDef(newPartition, *cbp, wtset_name, "Character", "WtSet", token, false, true, validator);
01765 }
01766 else
01767 effectiveAssumpBlock->ReadPartitionDef(newPartition, *cbp, wtset_name, "Character", "WtSet", token, false, false, false);
01768 bool floatWts = false;
01769 long currLongWt;
01770 double currDblWt;
01771 NxsTransformationManager &ctm = cbp->GetNxsTransformationManagerRef();
01772 NxsTransformationManager::ListOfIntWeights liw;
01773 NxsTransformationManager::ListOfDblWeights diw;
01774 for (NxsPartition::const_iterator groupIt = newPartition.begin(); groupIt != newPartition.end(); ++groupIt)
01775 {
01776 const std::string & s = groupIt->first;
01777 if (!floatWts)
01778 {
01779 floatWts = !NxsString::to_long(s.c_str(), &currLongWt);
01780 if (!floatWts)
01781 liw.push_back(NxsTransformationManager::IntWeightToIndexSet((int)currLongWt, groupIt->second));
01782 }
01783 bool v = NxsString::to_double(s.c_str(), &currDblWt);
01784 if (!v)
01785 {
01786 errormsg << "Invalid weight " << groupIt->first << " found in a WtSet command.";
01787 throw NxsException(errormsg, token);
01788 }
01789 diw.push_back(NxsTransformationManager::DblWeightToIndexSet(currDblWt, groupIt->second));
01790 }
01791 NxsTransformationManager &tm = effectiveAssumpBlock->GetNxsTransformationManagerRef();
01792 if (floatWts)
01793 {
01794 ctm.AddRealWeightSet(wtset_name, diw, asterisked);
01795 tm.AddRealWeightSet(wtset_name, diw, asterisked);
01796 }
01797 else
01798 {
01799 ctm.AddIntWeightSet(wtset_name, liw, asterisked);
01800 tm.AddIntWeightSet(wtset_name, liw, asterisked);
01801 }
01802 }
01803
01804
01808 void NxsAssumptionsBlock::HandleCharPartition(
01809 NxsToken &token)
01810 {
01811 bool asterisked = false;
01812 token.GetNextToken();
01813 if (token.Equals("*"))
01814 {
01815 asterisked = true;
01816 token.GetNextToken();
01817 }
01818 NxsString charpart_name = token.GetToken();
01819
01820 NxsAssumptionsBlockAPI * effectiveAssumpBlock = DealWithPossibleParensInCharDependentCmd(token, "CharPartition");
01821 token.GetNextToken();
01822
01823 NxsPartition newPartition;
01824 NxsCharactersBlockAPI *cbp = effectiveAssumpBlock->GetCharBlockPtr();
01825 NCL_ASSERT(cbp);
01826 effectiveAssumpBlock->ReadPartitionDef(newPartition, *cbp, charpart_name, "Character", "CharPartition", token, asterisked, false, true);
01827 effectiveAssumpBlock->AddCharPartition(charpart_name, newPartition);
01828 }
01829
01833 void NxsAssumptionsBlock::HandleCharSet(
01834 NxsToken &token)
01835 {
01836 bool asterisked = false;
01837 token.GetNextToken();
01838 if (token.Equals("*"))
01839 {
01840 asterisked = true;
01841 token.GetNextToken();
01842 }
01843 NxsString charset_name = token.GetToken();
01844
01845 NxsAssumptionsBlockAPI * effectiveAssumpBlock = DealWithPossibleParensInCharDependentCmd(token, "CharSet");
01846 token.GetNextToken();
01847 effectiveAssumpBlock->ReadCharsetDef(charset_name, token, asterisked);
01848 }
01849
01853 void NxsAssumptionsBlock::ReadCharsetDef(NxsString charset_name, NxsToken &token, bool asterisked)
01854 {
01855 NCL_ASSERT(charBlockPtr != NULL);
01856 NxsCharactersBlockAPI &charBlock = *charBlockPtr;
01857 NxsUnsignedSet s;
01858 NxsSetReader::ReadSetDefinition(token, charBlock, "Character", "CharSet", &s);
01859 charsets[charset_name] = s;
01860 if (asterisked && nexusReader != NULL)
01861 {
01862 nexusReader->NexusWarnToken("An * is ignored in a CHARSET command", NxsReader::SKIPPING_CONTENT_WARNING, token);
01863 errormsg.clear();
01864 }
01865 if (charBlock.AddNewIndexSet(charset_name, s) && nexusReader)
01866 {
01867 errormsg = "A CHARSET with the name ";
01868 errormsg += charset_name;
01869 errormsg += " has already been encountered. The later definition will preempt the earlier definition(s).";
01870 nexusReader->NexusWarnToken(errormsg, NxsReader::OVERWRITING_CONTENT_WARNING, token);
01871 errormsg.clear();
01872 }
01873 }
01874
01875
01879 void NxsAssumptionsBlock::HandleExSet(
01880 NxsToken &token)
01881 {
01882
01883 bool asterisked = false;
01884 token.GetNextToken();
01885 if (token.Equals("*"))
01886 {
01887 asterisked = true;
01888 token.GetNextToken();
01889 }
01890 NxsString exset_name = token.GetToken();
01891
01892 NxsAssumptionsBlockAPI * effectiveAssumpBlock = DealWithPossibleParensInCharDependentCmd(token, "ExSet");
01893 token.GetNextToken();
01894 effectiveAssumpBlock->ReadExsetDef(exset_name, token, asterisked);
01895 }
01896
01900 void NxsAssumptionsBlock::ReadExsetDef(NxsString charset_name, NxsToken &token, bool asterisked)
01901 {
01902 NCL_ASSERT(charBlockPtr != NULL);
01903 NxsCharactersBlockAPI &charBlock = *charBlockPtr;
01904 NxsUnsignedSet s;
01905 NxsSetReader::ReadSetDefinition(token, charBlock, "Character", "ExSet", &s);
01906 exsets[charset_name] = s;
01907 if (charBlock.AddNewExSet(charset_name, s) && nexusReader)
01908 {
01909 errormsg = "A ExSet with the name ";
01910 errormsg += charset_name;
01911 errormsg += " has already been encountered. The later definition will preempt the earlier definition(s).";
01912 nexusReader->NexusWarnToken(errormsg, NxsReader::OVERWRITING_CONTENT_WARNING, token);
01913 errormsg.clear();
01914 }
01915 if (asterisked)
01916 {
01917 def_exset = charset_name;
01918 ApplyExset(charset_name);
01919 }
01920 }
01921
01922
01926 void NxsAssumptionsBlock::HandleTaxPartition(
01927 NxsToken &token)
01928 {
01929 bool asterisked = false;
01930 token.GetNextToken();
01931 if (token.Equals("*"))
01932 {
01933 asterisked = true;
01934 token.GetNextToken();
01935 }
01936 NxsString taxpart_name = token.GetToken();
01937
01938
01939 NxsAssumptionsBlockAPI *effectiveAssumpBlock = NULL;
01940 token.GetNextToken();
01941 NxsString taxblock_name;
01942
01943 if (token.Equals("("))
01944 {
01945 token.GetNextToken();
01946 while (!token.Equals(")"))
01947 {
01948 if (token.Equals("TAXA"))
01949 {
01950 DemandEquals(token, "after \"(Taxa\" in a TaxPartition command");
01951 token.GetNextToken();
01952 taxblock_name = token.GetToken();
01953 }
01954 else if (token.Equals("VECTOR"))
01955 GenerateNxsException(token, "VECTOR-style set definitions are not currently supported");
01956 else if (token.Equals("NOTOKENS"))
01957 GenerateNxsException(token, "NOTOKENS-style set definitions are not currently supported");
01958 else if (token.Equals(";"))
01959 GenerateNxsException(token, "; encountered in TaxPartition command before parentheses were closed");
01960 else if (!(token.Equals("STANDARD") || token.Equals("TOKENS")) && nexusReader)
01961 {
01962 errormsg = "Skipping unknown TaxPartition qualifier: ";
01963 errormsg << token.GetTokenReference();
01964 nexusReader->NexusWarnToken(errormsg, NxsReader::SKIPPING_CONTENT_WARNING, token);
01965 errormsg.clear();
01966 }
01967 token.GetNextToken();
01968 }
01969 token.GetNextToken();
01970 }
01971 const char *cbn = (taxblock_name.empty() ? NULL : taxblock_name.c_str());
01972 effectiveAssumpBlock = this->GetAssumptionsBlockForTaxaTitle(cbn, token, "TaxPartition");
01973 DemandIsAtEquals(token, "in TaxPartition definition");
01974 token.GetNextToken();
01975 NxsPartition newPartition;
01976 NCL_ASSERT(taxa);
01977 effectiveAssumpBlock->ReadPartitionDef(newPartition, *taxa, taxpart_name, "Taxa", "TaxPartition", token, asterisked, false, true);
01978 effectiveAssumpBlock->AddTaxPartition(taxpart_name, newPartition);
01979 }
01983 void NxsAssumptionsBlock::HandleTreePartition(
01984 NxsToken &token)
01985 {
01986 bool asterisked = false;
01987 token.GetNextToken();
01988 if (token.Equals("*"))
01989 {
01990 asterisked = true;
01991 token.GetNextToken();
01992 }
01993 NxsString treepart_name = token.GetToken();
01994
01995 NxsAssumptionsBlockAPI *effectiveAssumpBlock = NULL;
01996 token.GetNextToken();
01997 NxsString treeblock_name;
01998
01999 if (token.Equals("("))
02000 {
02001 token.GetNextToken();
02002 while (!token.Equals(")"))
02003 {
02004 if (token.Equals("TREES"))
02005 {
02006 DemandEquals(token, "after \"(Trees\" in a TreePartition command");
02007 token.GetNextToken();
02008 treeblock_name = token.GetToken();
02009 }
02010 else if (token.Equals("VECTOR"))
02011 GenerateNxsException(token, "VECTOR-style set definitions are not currently supported");
02012 else if (token.Equals("NOTOKENS"))
02013 GenerateNxsException(token, "NOTOKENS-style set definitions are not currently supported");
02014 else if (token.Equals(";"))
02015 GenerateNxsException(token, "; encountered in TreePartition command before parentheses were closed");
02016 else if (!(token.Equals("STANDARD") || token.Equals("TOKENS")) && nexusReader)
02017 {
02018 errormsg = "Skipping unknown TreePartition qualifier: ";
02019 errormsg << token.GetTokenReference();
02020 nexusReader->NexusWarnToken(errormsg, NxsReader::SKIPPING_CONTENT_WARNING, token);
02021 errormsg.clear();
02022 }
02023 token.GetNextToken();
02024 }
02025 token.GetNextToken();
02026 }
02027 const char *cbn = (treeblock_name.empty() ? NULL : treeblock_name.c_str());
02028 effectiveAssumpBlock = this->GetAssumptionsBlockForTreesTitle(cbn, token, "TreePartition");
02029 DemandIsAtEquals(token, "in TreePartition definition");
02030 token.GetNextToken();
02031 NxsPartition newPartition;
02032 NCL_ASSERT(treesBlockPtr);
02033 effectiveAssumpBlock->ReadPartitionDef(newPartition, *treesBlockPtr, treepart_name, "Tree", "TreePartition", token, asterisked, false, true);
02034 effectiveAssumpBlock->AddTreePartition(treepart_name, newPartition);
02035 }
02036
02037 void NxsBlock::ReadPartitionDef(
02038 NxsPartition &np,
02039 NxsLabelToIndicesMapper <m,
02040 const std::string & partName,
02041 const char * ptype,
02042 const char * cmd,
02043 NxsToken & token,
02044 bool warnAsterisked,
02045 bool demandAllInds,
02046 bool storeAsPartition)
02047 {
02048 NxsUnsignedSet allInds;
02049 const unsigned total = ltm.GetMaxIndex() + 1;
02050 std::set<NxsString> prevGroupNames;
02051 errormsg.clear();
02052 for (;;)
02053 {
02054 if (token.Equals(";"))
02055 break;
02056 NxsString groupN = token.GetToken();
02057 NxsString capGroupN = groupN;
02058 capGroupN.ToUpper();
02059 if (prevGroupNames.count(capGroupN) > 0)
02060 {
02061 errormsg << "Illegal repitition of a subset name (" << groupN << ") in the " << cmd << " definition of " << partName;
02062 throw NxsException(errormsg, token);
02063 }
02064 token.GetNextToken();
02065 if (!token.Equals(":"))
02066 {
02067 errormsg << "Expecting a : after the subset name " << groupN << " in the " << cmd << " definition of " << partName << ". Found " << token.GetToken();
02068 throw NxsException(errormsg, token);
02069 }
02070 token.GetNextToken();
02071 NxsUnsignedSet s;
02072 NxsSetReader::ReadSetDefinition(token, ltm, ptype, cmd, &s, &allInds);
02073 allInds.insert(s.begin(), s.end());
02074 np.push_back(NxsPartitionGroup(groupN, s));
02075 if (token.Equals(";"))
02076 break;
02077 NCL_ASSERT(token.Equals(","));
02078
02079
02080
02081 token.SetLabileFlagBit(NxsToken::hyphenNotPunctuation);
02082 token.GetNextToken();
02083 }
02084 if (allInds.size() < total)
02085 {
02086 unsigned n = 0;
02087 for (;n < total; ++n)
02088 {
02089 if (allInds.count(n) == 0)
02090 break;
02091 }
02092 errormsg << partName << " is a not a valid "<< cmd <<". At least one " << ptype << " ("<< n+1 << ") is not included";
02093 if (demandAllInds)
02094 throw NxsException(errormsg, token);
02095 else if (nexusReader)
02096 {
02097 nexusReader->NexusWarnToken(errormsg, NxsReader::ILLEGAL_CONTENT_WARNING, token);
02098 errormsg.clear();
02099 }
02100 }
02101 if (warnAsterisked && nexusReader != NULL)
02102 {
02103 errormsg << "An * is ignored in a " << cmd << " command";
02104 nexusReader->NexusWarnToken(errormsg, NxsReader::SKIPPING_CONTENT_WARNING, token);
02105 errormsg.clear();
02106 }
02107 if (storeAsPartition && ltm.AddNewPartition(partName, np) && nexusReader)
02108 {
02109 errormsg << "A " << cmd << " with the name ";
02110 errormsg += partName;
02111 errormsg += " has already been encountered. The later definition will preempt the earlier definition(s).";
02112 nexusReader->NexusWarnToken(errormsg, NxsReader::OVERWRITING_CONTENT_WARNING, token);
02113 errormsg.clear();
02114 }
02115 }
02116
02117 unsigned NxsBlock::ReadVectorPartitionDef(NxsPartition &np, NxsLabelToIndicesMapper <m, const std::string & partName, const char * ptype, const char * cmd, NxsToken & token, bool warnAsterisked, bool demandAllInds, NxsSetVectorItemValidator & v)
02118 {
02119 NxsUnsignedSet allInds;
02120 const unsigned total = ltm.GetMaxIndex() + 1;
02121 std::map<std::string, NxsUnsignedSet> subsetMap;
02122 errormsg.clear();
02123 unsigned ind = 0;
02124 for (; ind < total; ++ind)
02125 {
02126 if (token.Equals(";"))
02127 break;
02128 const std::string key = v.convert(token);
02129 const std::string capKey = NxsString::get_upper(key);
02130 NxsUnsignedSet & s = subsetMap[key];
02131 s.insert(ind);
02132 token.GetNextToken();
02133 }
02134 if (ind < total)
02135 {
02136 errormsg << partName << " is a not a valid "<< cmd <<". Only " << ind + 1 << " entries for " << ptype << "(s) were included in the definition";
02137 if (demandAllInds)
02138 throw NxsException(errormsg, token);
02139 else if (nexusReader)
02140 {
02141 nexusReader->NexusWarnToken(errormsg, NxsReader::ILLEGAL_CONTENT_WARNING, token);
02142 errormsg.clear();
02143 }
02144 }
02145 if (warnAsterisked && nexusReader != NULL)
02146 {
02147 errormsg << "An * is ignored in a " << cmd << " command";
02148 nexusReader->NexusWarnToken(errormsg, NxsReader::SKIPPING_CONTENT_WARNING, token);
02149 errormsg.clear();
02150 }
02151 np.clear();
02152 for (std::map<std::string, NxsUnsignedSet>::const_iterator sIt = subsetMap.begin(); sIt != subsetMap.end(); ++sIt)
02153 {
02154 const std::string & k = sIt->first;
02155 const NxsUnsignedSet & valset = sIt->second;
02156 np.push_back(NxsPartitionGroup(k, valset));
02157 }
02158 if (ltm.AddNewPartition(partName, np) && nexusReader)
02159 {
02160 errormsg << "A " << cmd << " with the name ";
02161 errormsg += partName;
02162 errormsg += " has already been encountered. The later definition will preempt the earlier definition(s).";
02163 nexusReader->NexusWarnToken(errormsg, NxsReader::OVERWRITING_CONTENT_WARNING, token);
02164 errormsg.clear();
02165 }
02166 return ind;
02167 }
02168
02169 void NxsWriteSetCommand(const char *cmd, const NxsUnsignedSetMap & usetmap, std::ostream &out, const char * nameOfDef)
02170 {
02171 if (usetmap.empty())
02172 return;
02173 for (NxsUnsignedSetMap::const_iterator csIt = usetmap.begin(); csIt != usetmap.end(); ++csIt)
02174 {
02175 out << " " << cmd << " ";
02176 if (NxsString::case_insensitive_equals(csIt->first.c_str(), nameOfDef))
02177 out << "* ";
02178 out << NexusToken::EscapeString(csIt->first) << " =";
02179 NxsSetReader::WriteSetAsNexusValue(csIt->second, out);
02180 out << ";\n";
02181 }
02182 }
02183
02184 void NxsWritePartitionCommand(const char *cmd, const NxsPartitionsByName & usetmap, std::ostream &out, const char * nameOfDef)
02185 {
02186 if (usetmap.empty())
02187 return;
02188 for (NxsPartitionsByName::const_iterator csIt = usetmap.begin(); csIt != usetmap.end(); ++csIt)
02189 {
02190 out << " " << cmd << " ";
02191 if (NxsString::case_insensitive_equals(csIt->first.c_str(), nameOfDef))
02192 out << "* ";
02193 out << NexusToken::EscapeString(csIt->first) << " =";
02194 const NxsPartition & p = csIt->second;
02195 bool first = true;
02196 for (NxsPartition::const_iterator pIt = p.begin(); pIt != p.end(); ++pIt)
02197 {
02198 const NxsPartitionGroup & g = *pIt;
02199 if (!first)
02200 out << ',';
02201 out << ' ' << NxsString::GetEscaped(g.first) << " :";
02202 NxsSetReader::WriteSetAsNexusValue(g.second, out);
02203 first = false;
02204 }
02205 out << ";\n";
02206 }
02207 }
02208
02212 void NxsAssumptionsBlock::HandleTaxSet(
02213 NxsToken &token)
02214 {
02215 bool asterisked = false;
02216 token.GetNextToken();
02217 if (token.Equals("*"))
02218 {
02219 asterisked = true;
02220 token.GetNextToken();
02221 }
02222 NxsString taxset_name = token.GetToken();
02223
02224 token.GetNextToken();
02225 NxsAssumptionsBlockAPI *effectiveAssumpBlock = NULL;
02226 NxsString taxblock_name;
02227 if (token.Equals("("))
02228 {
02229 token.GetNextToken();
02230 while (!token.Equals(")"))
02231 {
02232 if (token.Equals("TAXA"))
02233 {
02234 DemandEquals(token, "after \"(Taxa\" in a TaxSet command");
02235 token.GetNextToken();
02236 taxblock_name = token.GetToken();
02237 }
02238 else if (token.Equals("VECTOR"))
02239 GenerateNxsException(token, "VECTOR-style set definitions are not currently supported");
02240 else if (token.Equals(";"))
02241 GenerateNxsException(token, "; encountered in TaxSet command before parentheses were closed");
02242 else if (!token.Equals("STANDARD") && nexusReader)
02243 {
02244 errormsg = "Skipping unknown TaxSet qualifier: ";
02245 errormsg << token.GetTokenReference();
02246 nexusReader->NexusWarnToken(errormsg, NxsReader::SKIPPING_CONTENT_WARNING, token);
02247 errormsg.clear();
02248 }
02249 token.GetNextToken();
02250 }
02251 token.GetNextToken();
02252 }
02253 const char *tbn = (taxblock_name.empty() ? NULL : taxblock_name.c_str());
02254 effectiveAssumpBlock = this->GetAssumptionsBlockForTaxaTitle(tbn, token, "TAXSET");
02255 DemandIsAtEquals(token, "in TAXSET definition");
02256 token.GetNextToken();
02257 effectiveAssumpBlock->ReadTaxsetDef(taxset_name, token, asterisked);
02258 }
02259
02263 void NxsAssumptionsBlock::ReadTaxsetDef(NxsString taxset_name, NxsToken &token, bool asterisked)
02264 {
02265 NCL_ASSERT(taxa != NULL);
02266 NxsTaxaBlockAPI &taxaBlock = *taxa;
02267 NxsUnsignedSet s;
02268 NxsSetReader::ReadSetDefinition(token, taxaBlock, "Taxon", "TaxSet", &s);
02269 taxsets[taxset_name] = s;
02270 if (asterisked && nexusReader != NULL)
02271 {
02272 nexusReader->NexusWarnToken("An * is ignored in a TaxSet command", NxsReader::SKIPPING_CONTENT_WARNING, token);
02273 errormsg.clear();
02274 }
02275 if (taxaBlock.AddNewIndexSet(taxset_name, s) && nexusReader)
02276 {
02277 errormsg = "A TaxSet with the name ";
02278 errormsg += taxset_name;
02279 errormsg += " has already been encountered. The later definition will preempt the earlier definition(s).";
02280 nexusReader->NexusWarnToken(errormsg, NxsReader::SKIPPING_CONTENT_WARNING, token);
02281 errormsg.clear();
02282 }
02283 }
02284
02288 void NxsAssumptionsBlock::HandleTreeSet(
02289 NxsToken &token)
02290 {
02291 bool asterisked = false;
02292 token.GetNextToken();
02293 if (token.Equals("*"))
02294 {
02295 asterisked = true;
02296 token.GetNextToken();
02297 }
02298 NxsString treeset_name = token.GetToken();
02299
02300 token.GetNextToken();
02301 NxsAssumptionsBlockAPI *effectiveAssumpBlock = NULL;
02302 NxsString treeblock_name;
02303 if (token.Equals("("))
02304 {
02305 token.GetNextToken();
02306 while (!token.Equals(")"))
02307 {
02308 if (token.Equals("TREES"))
02309 {
02310 DemandEquals(token, "after \"(Trees\" in a TreeSet command");
02311 token.GetNextToken();
02312 treeblock_name = token.GetToken();
02313 }
02314 else if (token.Equals("VECTOR"))
02315 GenerateNxsException(token, "VECTOR-style set definitions are not currently supported");
02316 else if (token.Equals(";"))
02317 GenerateNxsException(token, "; encountered in TreeSet command before parentheses were closed");
02318 else if (!token.Equals("STANDARD") && nexusReader)
02319 {
02320 errormsg = "Skipping unknown TreeSet qualifier: ";
02321 errormsg << token.GetTokenReference();
02322 nexusReader->NexusWarnToken(errormsg, NxsReader::SKIPPING_CONTENT_WARNING, token);
02323 errormsg.clear();
02324 }
02325 token.GetNextToken();
02326 }
02327 token.GetNextToken();
02328 }
02329 const char *tbn = (treeblock_name.empty() ? NULL : treeblock_name.c_str());
02330 effectiveAssumpBlock = this->GetAssumptionsBlockForTreesTitle(tbn, token, "TreeSet");
02331 DemandIsAtEquals(token, "in TreeSet definition");
02332 token.GetNextToken();
02333 effectiveAssumpBlock->ReadTreesetDef(treeset_name, token, asterisked);
02334 }
02335
02339 void NxsAssumptionsBlock::ReadTreesetDef(NxsString treeset_name, NxsToken &token, bool asterisked)
02340 {
02341 NCL_ASSERT(treesBlockPtr != NULL);
02342 NxsTreesBlockAPI &treesBlock = *treesBlockPtr;
02343 NxsUnsignedSet s;
02344 NxsSetReader::ReadSetDefinition(token, treesBlock, "Trees", "TreeSet", &s);
02345 treesets[treeset_name] = s;
02346 if (asterisked && nexusReader != NULL)
02347 {
02348 nexusReader->NexusWarnToken("An * is ignored in a TreeSet command", NxsReader::SKIPPING_CONTENT_WARNING, token);
02349 errormsg.clear();
02350 }
02351 if (treesBlock.AddNewIndexSet(treeset_name, s) && nexusReader)
02352 {
02353 errormsg = "A TreeSet with the name ";
02354 errormsg += treeset_name;
02355 errormsg += " has already been encountered. The later definition will preempt the earlier definition(s).";
02356 nexusReader->NexusWarnToken(errormsg, NxsReader::SKIPPING_CONTENT_WARNING, token);
02357 errormsg.clear();
02358 }
02359 }
02360
02366 void NxsAssumptionsBlock::Read(
02367 NxsToken &token)
02368 {
02369 isEmpty = false;
02370 isUserSupplied = true;
02371 NxsString n = "BEGIN ";
02372 n << id;
02373 DemandEndSemicolon(token, n.c_str());
02374
02375 for(;;)
02376 {
02377 token.GetNextToken();
02378 NxsBlock::NxsCommandResult res = HandleBasicBlockCommands(token);
02379 if (res == NxsBlock::NxsCommandResult(STOP_PARSING_BLOCK))
02380 return;
02381 if (res != NxsBlock::NxsCommandResult(HANDLED_COMMAND))
02382 {
02383 if (token.Equals("CHARPARTITION"))
02384 HandleCharPartition(token);
02385 else if (token.Equals("CHARSET"))
02386 HandleCharSet(token);
02387 else if (token.Equals("CODESET"))
02388 HandleCodeSet(token);
02389 else if (token.Equals("CODONPOSSET"))
02390 HandleCodonPosSet(token);
02391 else if (token.Equals("EXSET"))
02392 HandleExSet(token);
02393 else if (token.Equals("OPTIONS"))
02394 HandleOptions(token);
02395 else if (token.Equals("TAXSET"))
02396 HandleTaxSet(token);
02397 else if (token.Equals("TAXPARTITION"))
02398 HandleTaxPartition(token);
02399 else if (token.Equals("TREESET"))
02400 HandleTreeSet(token);
02401 else if (token.Equals("TREEPARTITION"))
02402 HandleTreePartition(token);
02403 else if (token.Equals("TYPESET"))
02404 HandleTypeSet(token);
02405 else if (token.Equals("USERTYPE"))
02406 HandleUserType(token);
02407 else if (token.Equals("WTSET"))
02408 HandleWeightSet(token);
02409 else
02410 SkipCommand(token);
02411
02412 }
02413 }
02414 }
02415 void NxsAssumptionsBlock::HandleOptions(NxsToken &token)
02416 {
02417 errormsg.clear();
02418 token.GetNextToken();
02419 std::map<std::string, std::string> kv = token.ProcessAsSimpleKeyValuePairs("OPTIONS");
02420 std::map<std::string, std::string>::const_iterator kvIt = kv.begin();
02421 for (; kvIt != kv.end(); ++kvIt)
02422 {
02423 if (NxsString::case_insensitive_equals(kvIt->first.c_str(), "DEFTYPE"))
02424 {
02425 NxsAssumptionsBlockAPI * effAssumpB = GetAssumptionsBlockForCharTitle(NULL, token, "OPTIONS");
02426 NCL_ASSERT(effAssumpB);
02427 NxsCharactersBlockAPI * cb = effAssumpB->GetCharBlockPtr();
02428 NCL_ASSERT(cb);
02429 NxsTransformationManager & tmRef = cb->GetNxsTransformationManagerRef();
02430 if (!tmRef.IsValidTypeName(kvIt->second.c_str()))
02431 {
02432 errormsg << kvIt->second << " is not a valid type name for OPTIONS DefType. Expceting one of:\n";
02433 const std::set<std::string> & tn = tmRef.GetTypeNames();
02434 for (std::set<std::string>::const_iterator tnIt = tn.begin(); tnIt != tn.end(); ++tnIt)
02435 errormsg << ' ' << NxsString::GetEscaped(*tnIt);
02436 throw NxsException(errormsg, token);
02437 }
02438 try
02439 {
02440 tmRef.SetDefaultTypeName(kvIt->second);
02441 NxsTransformationManager & etmRef = effAssumpB->GetNxsTransformationManagerRef();
02442 etmRef.SetDefaultTypeName(kvIt->second);
02443 }
02444 catch (const NxsException & x)
02445 {
02446 throw NxsException(x.msg, token);
02447 }
02448 }
02449 else if (NxsString::case_insensitive_equals(kvIt->first.c_str(), "POLYTCOUNT"))
02450 {
02451 if (NxsString::case_insensitive_equals(kvIt->second.c_str(), "MINSTEPS"))
02452 polyTCountValue = POLY_T_COUNT_MIN;
02453 else if (NxsString::case_insensitive_equals(kvIt->second.c_str(), "MAXSTEPS"))
02454 polyTCountValue = POLY_T_COUNT_MAX;
02455 else
02456 {
02457 errormsg << "Unknown value (" << kvIt->second << ") found for OPTIONS PolyTCount (expecting MINSTEPS or MAXSTEPS).";
02458 throw NxsException(errormsg, token);
02459 }
02460 }
02461 else if (NxsString::case_insensitive_equals(kvIt->first.c_str(), "GAPMODE"))
02462 {
02463 NxsAssumptionsBlockAPI * effAssumpB = GetAssumptionsBlockForCharTitle(NULL, token, "OPTIONS");
02464 NCL_ASSERT(effAssumpB);
02465 NxsCharactersBlockAPI * cb = effAssumpB->GetCharBlockPtr();
02466 NCL_ASSERT(cb);
02467 if (NxsString::case_insensitive_equals(kvIt->second.c_str(), "MISSING"))
02468 {
02469 effAssumpB->SetGapsAsNewstate(false);
02470 cb->SetGapModeSetting(NxsCharactersBlockAPI::GAP_MODE_MISSING);
02471 }
02472 else if (NxsString::case_insensitive_equals(kvIt->second.c_str(), "NEWSTATE"))
02473 {
02474 effAssumpB->SetGapsAsNewstate(true);
02475 cb->SetGapModeSetting(NxsCharactersBlockAPI::GAP_MODE_NEWSTATE);
02476 }
02477 else
02478 {
02479 errormsg << "Unknown value (" << kvIt->second << ") found for OPTIONS GapMode (expecting MISSING or NEWSTATE).";
02480 throw NxsException(errormsg, token);
02481 }
02482 }
02483 else if (nexusReader)
02484 {
02485 errormsg << "Skipping unknown subcommand (" << kvIt->first << ") in OPTIONS command of " << id << " Block";
02486 nexusReader->NexusWarnToken(errormsg, NxsReader::SKIPPING_CONTENT_WARNING, token);
02487 errormsg.clear();
02488 }
02489 }
02490 }
02491
02495 void NxsAssumptionsBlock::Reset()
02496 {
02497 if (!passedRefOfOwnedBlock)
02498 {
02499 VecAssumpBlockPtr::iterator bIt = createdSubBlocks.begin();
02500 for(; bIt != createdSubBlocks.end(); ++bIt)
02501 {
02502 if (*bIt)
02503 delete *bIt;
02504 }
02505 createdSubBlocks.clear();
02506 }
02507 passedRefOfOwnedBlock = false;
02508 NxsBlock::Reset();
02509 exsets.clear();
02510 taxsets.clear();
02511 charsets.clear();
02512 def_exset.clear();
02513 charPartitions.clear();
02514 taxPartitions.clear();
02515 treePartitions.clear();
02516 readAs = UNREAD_OR_GENERATED_BLOCK;
02517 charLinkStatus &= BLOCK_LINK_UNUSED_MASK;
02518 taxaLinkStatus &= BLOCK_LINK_UNUSED_MASK;
02519 treesLinkStatus &= BLOCK_LINK_UNUSED_MASK;
02520 if (charLinkStatus & NxsBlock::BLOCK_LINK_FROM_LINK_CMD)
02521 SetCharBlockPtr(NULL, NxsBlock::BLOCK_LINK_UNINITIALIZED);
02522 if (taxaLinkStatus & NxsBlock::BLOCK_LINK_FROM_LINK_CMD)
02523 SetTaxaBlockPtr(NULL, NxsBlock::BLOCK_LINK_UNINITIALIZED);
02524 if (treesLinkStatus & NxsBlock::BLOCK_LINK_FROM_LINK_CMD)
02525 SetTreesBlockPtr(NULL, NxsBlock::BLOCK_LINK_UNINITIALIZED);
02526 transfMgr.Reset();
02527 codesMgr.Reset();
02528 polyTCountValue = POLY_T_COUNT_UNKNOWN;
02529 gapsAsNewstate = false;
02530 codonPosSets.clear();
02531 def_codonPosSet.clear();
02532 codeSets.clear();
02533 def_codeSet.clear();
02534 }
02535
02540 void NxsAssumptionsBlock::Report(
02541 std::ostream &out) NCL_COULD_BE_CONST
02542 {
02543 out << endl;
02544 out << id << " block contains the following:" << endl;
02545
02546 if (charsets.empty())
02547 out << " No character sets were defined" << endl;
02548 else
02549 {
02550 NxsUnsignedSetMap::const_iterator charsets_iter = charsets.begin();
02551 if (charsets.size() == 1)
02552 {
02553 out << " 1 character set defined:" << endl;
02554 out << " " << (*charsets_iter).first << endl;
02555 }
02556 else
02557 {
02558 out << " " << (unsigned)charsets.size() << " character sets defined:" << endl;
02559 for (; charsets_iter != charsets.end(); charsets_iter++)
02560 {
02561 NxsString nm = (*charsets_iter).first;
02562 out << " " << nm;
02563 out << endl;
02564 }
02565 }
02566 }
02567
02568 if (taxsets.empty())
02569 out << " No taxon sets were defined" << endl;
02570 else
02571 {
02572 NxsUnsignedSetMap::const_iterator taxsets_iter = taxsets.begin();
02573 if (taxsets.size() == 1)
02574 {
02575 out << " 1 taxon set defined:" << endl;
02576 out << " " << (*taxsets_iter).first << endl;
02577 }
02578 else
02579 {
02580 out << " " << (unsigned)taxsets.size() << " taxon sets defined:" << endl;
02581 for (; taxsets_iter != taxsets.end(); taxsets_iter++)
02582 {
02583 NxsString nm = (*taxsets_iter).first;
02584 out << " " << nm;
02585 out << endl;
02586 }
02587 }
02588 }
02589
02590 if (exsets.empty())
02591 out << " No exclusion sets were defined" << endl;
02592 else
02593 {
02594 NxsUnsignedSetMap::const_iterator exsets_iter = exsets.begin();
02595 if (exsets.size() == 1)
02596 {
02597 out << " 1 exclusion set defined:" << endl;
02598 out << " " << (*exsets_iter).first << endl;
02599 }
02600 else
02601 {
02602 out << " " << (unsigned)exsets.size() << " exclusion sets defined:" << endl;
02603 for (; exsets_iter != exsets.end(); exsets_iter++)
02604 {
02605 NxsString nm = (*exsets_iter).first;
02606 out << " " << nm;
02607 if (NxsString::case_insensitive_equals(nm.c_str(), def_exset.c_str()))
02608 out << " (default)";
02609 out << endl;
02610 }
02611 }
02612 }
02613
02614 out << endl;
02615 }
02616
02623 void NxsAssumptionsBlock::SetCallback(
02624 NxsCharactersBlockAPI* p)
02625 {
02626 charBlockPtr = p;
02627 SetCharLinkStatus(NxsBlock::BLOCK_LINK_TO_MOST_RECENT);
02628 }
02629
02635 unsigned NxsAssumptionsBlock::TaxonLabelToNumber(
02636 NxsString s) const
02637 {
02638 NCL_ASSERT(taxa != NULL);
02639 int i;
02640 try
02641 {
02642 i = 1 + taxa->FindTaxon(s);
02643 }
02644 catch(NxsTaxaBlock::NxsX_NoSuchTaxon)
02645 {
02646 i = 0;
02647 }
02648
02649 return i;
02650 }
02651
02652
02653 void NxsAssumptionsBlock::HandleLinkCommand(NxsToken & token)
02654 {
02655 if (!nexusReader)
02656 NxsNCLAPIException("No NxsReader when reading Assumptions block.");
02657
02658 token.GetNextToken();
02659 const std::map<std::string, std::string> kv = token.ProcessAsSimpleKeyValuePairs("LINK");
02660 std::map<std::string, std::string>::const_iterator pairIt = kv.begin();
02661 for (;pairIt != kv.end(); ++pairIt)
02662 {
02663 NxsString key(pairIt->first.c_str());
02664 key.ToUpper();
02665 NxsString value(pairIt->second.c_str());
02666 if (key == "TAXA")
02667 {
02668 if (taxa && !taxa->GetID().EqualsCaseInsensitive(value))
02669 {
02670 if (GetTaxaLinkStatus() & NxsBlock::BLOCK_LINK_USED)
02671 {
02672 errormsg = "LINK to a Taxa block must occur before commands that use a taxa block";
02673 throw NxsException(errormsg, token);
02674 }
02675 SetTaxaBlockPtr(NULL, NxsBlock::BLOCK_LINK_UNINITIALIZED);
02676 }
02677 if (!taxa)
02678 {
02679 NxsTaxaBlockAPI * cb = nexusReader->GetTaxaBlockByTitle(value.c_str(), NULL);
02680 if (cb == NULL)
02681 {
02682 errormsg = "Unknown TAXA block (";
02683 errormsg += value;
02684 errormsg +=") referred to in the LINK command";
02685 throw NxsException(errormsg, token);
02686 }
02687 SetTaxaBlockPtr(cb, NxsBlock::BLOCK_LINK_FROM_LINK_CMD);
02688 }
02689 }
02690 else if (key == "CHARACTERS")
02691 {
02692 if (charBlockPtr && !charBlockPtr->GetID().EqualsCaseInsensitive(value))
02693 {
02694 if (GetCharLinkStatus() & NxsBlock::BLOCK_LINK_USED)
02695 {
02696 errormsg = "LINK to a CHARACTERS block must occur before commands that use a CHARACTERS block";
02697 throw NxsException(errormsg, token);
02698 }
02699 SetCharBlockPtr(NULL, NxsBlock::BLOCK_LINK_UNINITIALIZED);
02700 }
02701 if (!charBlockPtr)
02702 {
02703 NxsCharactersBlockAPI * cb = nexusReader->GetCharBlockByTitle(value.c_str(), NULL);
02704 if (cb == NULL)
02705 {
02706 errormsg = "Unknown CHARACTERS block (";
02707 errormsg += value;
02708 errormsg +=") referred to in the LINK command";
02709 throw NxsException(errormsg, token);
02710 }
02711 SetCharBlockPtr(cb, NxsBlock::BLOCK_LINK_FROM_LINK_CMD);
02712 }
02713 }
02714 else if (key == "TREES")
02715 {
02716 if (treesBlockPtr && !treesBlockPtr->GetID().EqualsCaseInsensitive(value))
02717 {
02718 if (GetTreesLinkStatus() & NxsBlock::BLOCK_LINK_USED)
02719 {
02720 errormsg = "LINK to a TREES block must occur before commands that use a TREES block";
02721 throw NxsException(errormsg, token);
02722 }
02723 SetTreesBlockPtr(NULL, NxsBlock::BLOCK_LINK_UNINITIALIZED);
02724 }
02725 if (!treesBlockPtr)
02726 {
02727 NxsTreesBlockAPI * cb = nexusReader->GetTreesBlockByTitle(value.c_str(), NULL);
02728 if (cb == NULL)
02729 {
02730 errormsg = "Unknown TREES block (";
02731 errormsg += value;
02732 errormsg +=") referred to in the LINK command";
02733 throw NxsException(errormsg, token);
02734 }
02735 SetTreesBlockPtr(cb, NxsBlock::BLOCK_LINK_FROM_LINK_CMD);
02736 }
02737 }
02738 else
02739 {
02740 errormsg = "Skipping unknown LINK subcommand: ";
02741 errormsg += pairIt->first.c_str();
02742 nexusReader->NexusWarnToken(errormsg, NxsReader::SKIPPING_CONTENT_WARNING, token);
02743 errormsg.clear();
02744 }
02745 }
02746 }
02747 void NxsAssumptionsBlock::WriteLinkCommand(std::ostream &out) const
02748 {
02749 if ( (taxa && !(taxa->GetTitle().empty()))
02750 || (treesBlockPtr && !(treesBlockPtr->GetTitle().empty()))
02751 || (charBlockPtr && !(charBlockPtr->GetTitle().empty())))
02752 {
02753 out << " LINK";
02754 if (taxa)
02755 out << " TAXA = " << NxsString::GetEscaped(taxa->GetTitle());
02756 if (charBlockPtr)
02757 out << " CHARACTERS = " << NxsString::GetEscaped(charBlockPtr->GetTitle());
02758 if (treesBlockPtr)
02759 out << " TREES = " << NxsString::GetEscaped(treesBlockPtr->GetTitle());
02760 out << ";\n";
02761 }
02762 }
02763
02764 VecBlockPtr NxsAssumptionsBlock::GetCreatedTaxaBlocks()
02765 {
02766 passedRefOfOwnedBlock = true;
02767 VecBlockPtr r;
02768 VecAssumpBlockPtr::iterator bIt = createdSubBlocks.begin();
02769 for(; bIt != createdSubBlocks.end(); ++bIt)
02770 r.push_back(*bIt);
02771 return r;
02772 }
02773
02774
02775 NxsAssumptionsBlock *NxsAssumptionsBlockFactory::GetBlockReaderForID(const std::string & idneeded, NxsReader *reader, NxsToken *)
02776 {
02777 if (reader == NULL || (idneeded != "ASSUMPTIONS" && idneeded != "CODONS" && idneeded != "SETS"))
02778 return NULL;
02779 NxsAssumptionsBlock * nb = new NxsAssumptionsBlock(NULL);
02780 nb->SetImplementsLinkAPI(true);
02781 return nb;
02782 }