00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <climits>
00021 #include "ncl/nxsunalignedblock.h"
00022
00023 #include "ncl/nxsreader.h"
00024 using namespace std;
00025
00026
00027
00034 NxsUnalignedBlock::NxsUnalignedBlock(
00035 NxsTaxaBlockAPI * tb)
00036 : NxsBlock(),
00037 NxsTaxaBlockSurrogate(tb, NULL)
00038 {
00039 id = "UNALIGNED";
00040 Reset();
00041 }
00042
00047 NxsUnalignedBlock::~NxsUnalignedBlock()
00048 {
00049 Reset();
00050 }
00051
00056 void NxsUnalignedBlock::Reset()
00057 {
00058 NxsBlock::Reset();
00059 ResetSurrogate();
00060 nTaxWithData = 0;
00061 newtaxa = false;
00062 respectingCase = false;
00063 labels = true;
00064 originalDatatype = datatype = NxsCharactersBlock::standard;
00065 missing = '?';
00066 ResetSymbols();
00067 nChar = 0;
00068 uMatrix.clear();
00069 }
00070
00071
00072 void NxsUnalignedBlock::ResetDatatypeMapper()
00073 {
00074 mapper = NxsDiscreteDatatypeMapper(datatype, symbols, missing, '\0', matchchar, respectingCase, equates);
00075 datatype = mapper.GetDatatype();
00076 }
00081 void NxsUnalignedBlock::ResetSymbols()
00082 {
00083 switch(datatype)
00084 {
00085 case NxsCharactersBlock::nucleotide:
00086 case NxsCharactersBlock::dna:
00087 symbols = "ACGT";
00088 break;
00089
00090 case NxsCharactersBlock::rna:
00091 symbols = "ACGU";
00092 break;
00093
00094 case NxsCharactersBlock::protein:
00095 symbols = "ACDEFGHIKLMNPQRSTVWY*";
00096 break;
00097
00098 default:
00099 symbols = "01";
00100 }
00101
00102 equates.clear();
00103 this->equates = NxsCharactersBlock::GetDefaultEquates(datatype);
00104 ResetDatatypeMapper();
00105 }
00111 void NxsUnalignedBlock::DebugShowMatrix(
00112 std::ostream & out,
00113 const char * marginText) NCL_COULD_BE_CONST
00114 {
00115 if (!taxa)
00116 return;
00117 unsigned width = taxa->GetMaxTaxonLabelLength();
00118 const unsigned ntt = GetNTaxTotal();
00119 NCL_ASSERT(uMatrix.size() >= ntt);
00120 for (unsigned i = 0; i < ntt; i++)
00121 {
00122 const NxsDiscreteStateRow * row = GetDiscreteMatrixRow(i);
00123 if (row && !(row->empty()))
00124 {
00125 if (marginText != NULL)
00126 out << marginText;
00127 const NxsString currTaxonLabel = taxa->GetTaxonLabel(i);
00128 out << currTaxonLabel;
00129 unsigned currTaxonLabelLen = (unsigned)currTaxonLabel.size();
00130 unsigned diff = width - currTaxonLabelLen;
00131 std::string spacer(diff+5, ' ');
00132 out << spacer;
00133 mapper.WriteStateCodeRowAsNexus(out, *row);
00134 }
00135 }
00136 }
00137
00141 std::string NxsUnalignedBlock::FormatState(
00142 NxsDiscreteDatum d)
00143 const
00144 {
00145 if (d.taxInd >= GetNTaxTotal())
00146 throw NxsNCLAPIException("Taxon out of range in NxsUnalignedBlock::FormatState");
00147 const NxsDiscreteStateRow & row = uMatrix[d.taxInd];
00148 if (d.charInd >= row.size())
00149 return std::string(1, missing);
00150 return mapper.StateCodeToNexusString(row[d.charInd]);
00151 }
00152
00157 bool NxsUnalignedBlock::IsInSymbols(
00158 char ch)
00159 {
00160 char char_in_question = (respectingCase ? ch : (char)toupper(ch));
00161 for (std::string::const_iterator sIt = symbols.begin(); sIt != symbols.end(); ++sIt)
00162 {
00163 const char char_in_symbols = (respectingCase ? *sIt : (char)toupper(*sIt));
00164 if (char_in_symbols == char_in_question)
00165 return true;
00166 }
00167 return false;
00168 }
00169
00174 void NxsUnalignedBlock::HandleDimensions(
00175 NxsToken & token)
00176 {
00177 unsigned ntaxRead = 0;
00178 for (;;)
00179 {
00180 token.GetNextToken();
00181 if (token.Equals("NEWTAXA"))
00182 newtaxa = true;
00183 else if (token.Equals("NTAX"))
00184 {
00185 DemandEquals(token, "after NTAX in DIMENSIONS command");
00186 ntaxRead = DemandPositiveInt(token, "NTAX");
00187 }
00188 else if (token.Equals(";"))
00189 break;
00190 }
00191 if (newtaxa)
00192 {
00193 if (ntaxRead == 0)
00194 {
00195 errormsg = "DIMENSIONS command must have an NTAX subcommand when the NEWTAXA option is in effect.";
00196 throw NxsException(errormsg, token);
00197 }
00198 AssureTaxaBlock(createImpliedBlock, token, "Dimensions");
00199 if (!createImpliedBlock)
00200 {
00201 taxa->Reset();
00202 if (nexusReader)
00203 nexusReader->RemoveBlockFromUsedBlockList(taxa);
00204 }
00205 taxa->SetNtax(ntaxRead);
00206 nTaxWithData = ntaxRead;
00207 }
00208 else
00209 {
00210 AssureTaxaBlock(false, token, "Dimensions");
00211 const unsigned ntaxinblock = taxa->GetNTax();
00212 if (ntaxinblock == 0)
00213 {
00214 errormsg = "A TAXA block must be read before character data, or the DIMENSIONS command must use the NEWTAXA.";
00215 throw NxsException(errormsg, token);
00216 }
00217 if (ntaxinblock < ntaxRead)
00218 {
00219 errormsg = "NTAX in UNALIGNED block must be less than or equal to NTAX in TAXA block\nNote: one circumstance that can cause this error is \nforgetting to specify NTAX in DIMENSIONS command when \na TAXA block has not been provided";
00220 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00221 }
00222 nTaxWithData = (ntaxRead == 0 ? ntaxinblock : ntaxRead);
00223 }
00224 }
00225
00233 void NxsUnalignedBlock::HandleEndblock(
00234 NxsToken & token)
00235 {
00236 DemandEndSemicolon(token, "END or ENDBLOCK");
00237 }
00238
00243 void NxsUnalignedBlock::HandleFormat(
00244 NxsToken & token)
00245 {
00246 bool standardDataTypeAssumed = false;
00247 bool ignoreCaseAssumed = false;
00248
00249 for (;;)
00250 {
00251 token.GetNextToken();
00252
00253 if (token.Equals("DATATYPE"))
00254 {
00255 DemandEquals(token, "after keyword DATATYPE");
00256
00257 token.GetNextToken();
00258
00259 if (token.Equals("STANDARD"))
00260 datatype = NxsCharactersBlock::standard;
00261 else if (token.Equals("DNA"))
00262 datatype = NxsCharactersBlock::dna;
00263 else if (token.Equals("RNA"))
00264 datatype = NxsCharactersBlock::rna;
00265 else if (token.Equals("NUCLEOTIDE"))
00266 datatype = NxsCharactersBlock::nucleotide;
00267 else if (token.Equals("PROTEIN"))
00268 datatype = NxsCharactersBlock::protein;
00269 else
00270 {
00271 errormsg = token.GetToken();
00272 errormsg += " is not a valid DATATYPE within a ";
00273 errormsg += id;
00274 errormsg += " block";
00275 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00276 }
00277 if (standardDataTypeAssumed && datatype != NxsCharactersBlock::standard)
00278 {
00279 errormsg = "DATATYPE must be specified first in FORMAT command";
00280 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00281 }
00282 originalDatatype = datatype;
00283 ResetSymbols();
00284 }
00285 else if (token.Equals("RESPECTCASE"))
00286 {
00287 if (ignoreCaseAssumed)
00288 {
00289 errormsg = "RESPECTCASE must be specified before MISSING and SYMBOLS in FORMAT command";
00290 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00291 }
00292 standardDataTypeAssumed = true;
00293 respectingCase = true;
00294 }
00295 else if (token.Equals("MISSING"))
00296 {
00297 DemandEquals(token, "after keyword MISSING");
00298
00299 token.GetNextToken();
00300
00301 if (token.GetTokenLength() != 1)
00302 {
00303 errormsg = "MISSING symbol should be a single character, but ";
00304 errormsg += token.GetToken();
00305 errormsg += " was specified";
00306 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00307 }
00308 else if (token.IsPunctuationToken() && !token.IsPlusMinusToken())
00309 {
00310 errormsg = "MISSING symbol specified cannot be a punctuation token (";
00311 errormsg += token.GetToken();
00312 errormsg += " was specified)";
00313 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00314 }
00315 else if (token.IsWhitespaceToken())
00316 {
00317 errormsg = "MISSING symbol specified cannot be a whitespace character (";
00318 errormsg += token.GetToken();
00319 errormsg += " was specified)";
00320 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00321 }
00322
00323 missing = token.GetToken()[0];
00324
00325 ignoreCaseAssumed = true;
00326 standardDataTypeAssumed = true;
00327 }
00328 else if (token.Equals("SYMBOLS") || token.Equals("SYMBOL"))
00329 {
00330 NxsDiscreteStateCell numDefStates;
00331 unsigned maxNewStates;
00332 switch(datatype)
00333 {
00334 case NxsCharactersBlock::dna:
00335 case NxsCharactersBlock::rna:
00336 case NxsCharactersBlock::nucleotide:
00337 numDefStates = 4;
00338 maxNewStates = NCL_MAX_STATES-4;
00339 break;
00340 case NxsCharactersBlock::protein:
00341 numDefStates = 21;
00342 maxNewStates = NCL_MAX_STATES-21;
00343 break;
00344 default:
00345 numDefStates = 0;
00346 symbols[0] = '\0';
00347 maxNewStates = NCL_MAX_STATES;
00348 }
00349 DemandEquals(token, "after keyword SYMBOLS");
00350
00351
00352 token.SetLabileFlagBit(NxsToken::doubleQuotedToken);
00353 token.GetNextToken();
00354
00355 token.StripWhitespace();
00356 unsigned numNewSymbols = token.GetTokenLength();
00357
00358 if (numNewSymbols > maxNewStates)
00359 {
00360 errormsg = "SYMBOLS defines ";
00361 errormsg += numNewSymbols;
00362 errormsg += " new states but only ";
00363 errormsg += maxNewStates;
00364 errormsg += " new states allowed for this DATATYPE";
00365 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00366 }
00367
00368 NxsString to = token.GetToken();
00369 unsigned tlen = (unsigned)to.size();
00370 NxsString processedS;
00371
00372
00373 for (unsigned i = 0; i < tlen; i++)
00374 {
00375 if (IsInSymbols(to[i]))
00376 {
00377 errormsg = "The character ";
00378 errormsg << to[i] << " defined in SYMBOLS is predefined for this DATATYPE and shoud not occur in a SYMBOLS subcommand of a FORMAT command.";
00379 if (nexusReader)
00380 {
00381 nexusReader->NexusWarnToken(errormsg, NxsReader::SKIPPING_CONTENT_WARNING, token);
00382 errormsg.clear();
00383 }
00384 }
00385 else
00386 processedS += to[i];
00387 }
00388
00389
00390
00391 symbols.append(processedS);
00392
00393 ignoreCaseAssumed = true;
00394 standardDataTypeAssumed = true;
00395 }
00396
00397 else if (token.Equals("EQUATE"))
00398 {
00399 DemandEquals(token, "after keyword EQUATE");
00400
00401
00402 token.GetNextToken();
00403
00404 if (!token.Equals("\""))
00405 {
00406 errormsg = "Expecting '\"' after keyword EQUATE but found ";
00407 errormsg += token.GetToken();
00408 errormsg += " instead";
00409 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00410 }
00411
00412
00413 for (;;)
00414 {
00415 token.GetNextToken();
00416 if (token.Equals("\""))
00417 break;
00418
00419
00420
00421 if (token.GetTokenLength() != 1)
00422 {
00423 errormsg = "Expecting single-character EQUATE symbol but found ";
00424 errormsg += token.GetToken();
00425 errormsg += " instead";
00426 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00427 }
00428
00429
00430 NxsString t = token.GetToken();
00431 const char ch = t[0];
00432 bool badEquateSymbol = false;
00433
00434
00435 if (ch == '^')
00436 badEquateSymbol = true;
00437
00438
00439 if (token.IsPunctuationToken() && !token.IsPlusMinusToken())
00440 badEquateSymbol = true;
00441
00442
00443 if (ch == missing)
00444 badEquateSymbol = true;
00445
00446
00447 if (IsInSymbols(ch))
00448 badEquateSymbol = true;
00449
00450 if (badEquateSymbol)
00451 {
00452 errormsg = "EQUATE symbol specified (";
00453 errormsg += token.GetToken();
00454 errormsg += ") is not valid; must not be same as missing, \nmatchchar, gap, state symbols, or any of the following: ()[]{}/\\,;:=*'\"`<>^";
00455 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00456 }
00457
00458 NxsString k = token.GetToken();
00459
00460 DemandEquals(token, "in EQUATE definition");
00461
00462
00463 token.SetLabileFlagBit(NxsToken::parentheticalToken);
00464 token.SetLabileFlagBit(NxsToken::curlyBracketedToken);
00465 token.GetNextToken();
00466 NxsString v = token.GetToken();
00467
00468
00469 equates[ch] = v;
00470 }
00471
00472 standardDataTypeAssumed = true;
00473 }
00474 else if (token.Equals("LABELS"))
00475 {
00476 labels = true;
00477 standardDataTypeAssumed = true;
00478 }
00479 else if (token.Equals("NOLABELS"))
00480 {
00481 labels = false;
00482 standardDataTypeAssumed = true;
00483 }
00484 else if (token.Equals(";"))
00485 {
00486 break;
00487 }
00488 }
00489 ResetDatatypeMapper();
00490 }
00491
00496 bool NxsUnalignedBlock::HandleNextState(
00497 NxsToken & token,
00498 unsigned taxNum,
00499 unsigned charNum,
00500 NxsDiscreteStateRow & row, const NxsString &nameStr)
00501 {
00502 token.SetLabileFlagBit(NxsToken::parentheticalToken);
00503 token.SetLabileFlagBit(NxsToken::curlyBracketedToken);
00504 token.SetLabileFlagBit(NxsToken::singleCharacterToken);
00505
00506 token.GetNextToken();
00507
00508 if (token.Equals(",") || token.Equals(";"))
00509 return false;
00510 const NxsString stateAsNexus = token.GetToken();
00511 const NxsDiscreteStateCell stateCode = mapper.EncodeNexusStateString(stateAsNexus, token, taxNum, charNum, NULL, nameStr);
00512 if (charNum < row.size())
00513 row[charNum] = stateCode;
00514 else
00515 {
00516 while (charNum < row.size())
00517 row.push_back(NXS_INVALID_STATE_CODE);
00518 row.push_back(stateCode);
00519 }
00520 return true;
00521 }
00522
00527 void NxsUnalignedBlock::HandleMatrix(
00528 NxsToken & token)
00529 {
00530 if (taxa == NULL)
00531 {
00532 AssureTaxaBlock(false, token, "Matrix");
00533 unsigned ntax = taxa->GetNTax();
00534 if (ntax == 0)
00535 {
00536 errormsg = "Must precede ";
00537 errormsg += id;
00538 errormsg += " block with a TAXA block or specify NEWTAXA and NTAX in the DIMENSIONS command";
00539 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00540 }
00541 }
00542 const unsigned ntax = taxa->GetNTax();
00543 uMatrix.clear();
00544 uMatrix.resize(ntax);
00545 unsigned indOfTaxInMemory = 0;
00546 std::vector<unsigned> toInMem(nTaxWithData, UINT_MAX);
00547 const unsigned ntlabels = taxa->GetNumTaxonLabels();
00548 errormsg.clear();
00549 bool taxaBlockNeedsLabels = (ntlabels == 0);
00550 if (!taxaBlockNeedsLabels && ntlabels < nTaxWithData)
00551 {
00552 errormsg << "Not enough taxlabels are known to read characters for " << nTaxWithData << " taxa in the Matrix command.";
00553 throw NxsException(errormsg, token);
00554 }
00555 for (unsigned indOfTaxInCommand = 0; indOfTaxInCommand < nTaxWithData; indOfTaxInCommand++)
00556 {
00557 NxsString nameStr;
00558 if (labels)
00559 {
00560 token.GetNextToken();
00561 nameStr = token.GetToken();
00562 if (taxaBlockNeedsLabels)
00563 {
00564 if (taxa->IsAlreadyDefined(nameStr))
00565 {
00566 errormsg << "Data for this taxon (" << nameStr << ") has already been saved";
00567 throw NxsException(errormsg, token);
00568 }
00569 indOfTaxInMemory = taxa->AddTaxonLabel(nameStr);
00570 }
00571 else
00572 {
00573 unsigned numOfTaxInMemory = taxa->TaxLabelToNumber(nameStr);
00574 if (numOfTaxInMemory == 0)
00575 {
00576 if (token.Equals(";"))
00577 errormsg << "Unexpected ;";
00578 else
00579 errormsg << "Could not find taxon named " << nameStr << " among stored taxon labels";
00580 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00581 }
00582 indOfTaxInMemory = numOfTaxInMemory - 1;
00583 }
00584 }
00585 else
00586 {
00587 indOfTaxInMemory = indOfTaxInCommand;
00588 nameStr << 1+indOfTaxInMemory;
00589 }
00590 if (toInMem[indOfTaxInCommand] != UINT_MAX)
00591 {
00592 errormsg << "Characters for taxon " << indOfTaxInCommand << " (" << taxa->GetTaxonLabel(indOfTaxInMemory) << ") have already been stored";
00593 throw NxsException(errormsg, token);
00594 }
00595 toInMem[indOfTaxInCommand] = indOfTaxInMemory;
00596 NxsDiscreteStateRow * new_row = &uMatrix[indOfTaxInMemory];
00597 unsigned charInd = 0;
00598 while (HandleNextState(token, indOfTaxInMemory, charInd, *new_row, nameStr))
00599 charInd++;
00600 }
00601 }
00602
00603
00609 void NxsUnalignedBlock::Read(
00610 NxsToken & token)
00611 {
00612 isEmpty = false;
00613 isUserSupplied = true;
00614
00615
00616 token.GetNextToken();
00617 if (!token.Equals(";"))
00618 {
00619 errormsg = "Expecting ';' after ";
00620 errormsg += id;
00621 errormsg += " block name, but found ";
00622 errormsg += token.GetToken();
00623 errormsg += " instead";
00624 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00625 }
00626 nTaxWithData = 0;
00627
00628 for (;;)
00629 {
00630 token.GetNextToken();
00631 NxsBlock::NxsCommandResult res = HandleBasicBlockCommands(token);
00632 if (res == NxsBlock::NxsCommandResult(STOP_PARSING_BLOCK))
00633 return;
00634 if (res != NxsBlock::NxsCommandResult(HANDLED_COMMAND))
00635 {
00636 if (token.Equals("DIMENSIONS"))
00637 HandleDimensions(token);
00638 else if (token.Equals("FORMAT"))
00639 HandleFormat(token);
00640 else if (token.Equals("TAXLABELS"))
00641 HandleTaxLabels(token);
00642 else if (token.Equals("MATRIX"))
00643 HandleMatrix(token);
00644 else
00645 SkipCommand(token);
00646 }
00647 }
00648 }
00649
00654 void NxsUnalignedBlock::Report(
00655 std::ostream & out) NCL_COULD_BE_CONST
00656 {
00657 out << '\n' << id << " block contains ";
00658 if (nTaxWithData == 0)
00659 out << "no taxa";
00660 else if (nTaxWithData == 1)
00661 out << "one taxon";
00662 else
00663 out << nTaxWithData << " taxa";
00664
00665 out << "\n Data type is \"" << this->GetDatatypeName() << "\"" << endl;
00666
00667 if (respectingCase)
00668 out << " Respecting case" << endl;
00669 else
00670 out << " Ignoring case" << endl;
00671
00672 if (labels)
00673 out << " Taxon labels were provided on left side of matrix" << endl;
00674 else
00675 out << " No taxon labels were provided on left side of matrix" << endl;
00676
00677 out << " Missing data symbol is '" << missing << '\'' << endl;
00678 out << " Valid symbols are: " << symbols << endl;
00679
00680 int numEquateMacros = (int)equates.size();
00681 if (numEquateMacros > 0)
00682 {
00683 out << " Equate macros in effect:" << endl;
00684 std::map<char, NxsString>::const_iterator i = equates.begin();
00685 for (; i != equates.end(); ++i)
00686 {
00687 out << " " << (*i).first << " = " << (*i).second << endl;
00688 }
00689 }
00690 else
00691 out << " No equate macros have been defined" << endl;
00692
00693 out << " Data matrix:" << endl;
00694 DebugShowMatrix(out, " ");
00695 }
00696
00700 void NxsUnalignedBlock::WriteAsNexus(
00701 std::ostream & out)
00702 const
00703 {
00704 out << "BEGIN UNALIGNED;\n";
00705 WriteBasicBlockCommands(out);
00706 if (this->taxa && taxa->GetNumTaxonLabels() > this->nTaxWithData)
00707 out << " DIMENSIONS NTax=" << this->nTaxWithData << ";\n";
00708
00709 this->WriteFormatCommand(out);
00710 this->WriteMatrixCommand(out);
00711 WriteSkippedCommands(out);
00712 out << "END;\n";
00713 }
00714
00718 void NxsUnalignedBlock::WriteMatrixCommand(
00719 std::ostream & out)
00720 const
00721 {
00722 NCL_ASSERT(taxa);
00723 const unsigned ntax = taxa->GetNTax();
00724 unsigned width = taxa->GetMaxTaxonLabelLength();
00725 out << "Matrix";
00726
00727
00728 bool first = true;
00729 for (unsigned i = 0; i < ntax; ++i)
00730 {
00731 if (!uMatrix[i].empty())
00732 {
00733 if (first)
00734 out << "\n";
00735 else
00736 out << ",\n";
00737 first = false;
00738 NxsString nm = taxa->GetTaxonLabel(i);
00739 std::string s = nm.c_str();
00740 const std::string currTaxonLabel = NxsString::GetEscaped(taxa->GetTaxonLabel(i));
00741 out << currTaxonLabel;
00742
00743
00744 unsigned currTaxonLabelLen = (unsigned)currTaxonLabel.size();
00745 unsigned diff = width - currTaxonLabelLen;
00746 for (unsigned k = 0; k < diff + 5; k++)
00747 out << ' ';
00748
00749 WriteStatesForMatrixRow(out, i);
00750 }
00751 }
00752 out << "\n;\n";
00753 }
00754
00755 void NxsUnalignedBlock::WriteStatesForMatrixRow(
00756 std::ostream &out,
00757 unsigned currTaxonIndex) const
00758 {
00759 const NxsDiscreteStateRow & row = uMatrix[currTaxonIndex];
00760 for (NxsDiscreteStateRow::const_iterator rIt = row.begin(); rIt != row.end(); ++rIt)
00761 mapper.WriteStateCodeAsNexusString(out, *rIt);
00762 }
00763
00764
00768 void NxsUnalignedBlock::WriteFormatCommand(std::ostream &out) const
00769 {
00770 mapper.WriteStartOfFormatCommand(out);
00771 if (this->respectingCase)
00772 out << " RespectCase";
00773
00774 out << ";\n";
00775 }
00776
00777 NxsUnalignedBlock *NxsUnalignedBlockFactory::GetBlockReaderForID(const std::string & idneeded, NxsReader *reader, NxsToken *)
00778 {
00779 if (reader == NULL || idneeded != "UNALIGNED")
00780 return NULL;
00781 NxsUnalignedBlock * nb = new NxsUnalignedBlock(NULL);
00782 nb->SetCreateImpliedBlock(true);
00783 nb->SetImplementsLinkAPI(true);
00784 return nb;
00785 }
00786
00800 NxsDiscreteStateRow NxsUnalignedBlock::GetInternalRepresentation(
00801 unsigned taxInd,
00802 unsigned charInd)
00803 {
00804 if (taxInd >= uMatrix.size())
00805 throw NxsUnalignedBlock::NxsX_NoDataForTaxon(taxInd);
00806 NxsDiscreteStateRow & row = uMatrix[taxInd];
00807 if (charInd >= (unsigned)row.size())
00808 return NxsDiscreteStateRow();
00809 return mapper.GetStateVectorForCode(row[charInd]);
00810 }
00811
00820 unsigned NxsUnalignedBlock::NumCharsForTaxon(
00821 unsigned taxInd)
00822 {
00823 if (taxInd >= uMatrix.size())
00824 throw NxsUnalignedBlock::NxsX_NoDataForTaxon(taxInd);
00825 return (unsigned)uMatrix[taxInd].size();
00826 }
00827
00828
00837 unsigned NxsUnalignedBlock::GetNumStates(
00838 unsigned taxInd,
00839 unsigned charInd)
00840 {
00841 if (taxInd >= uMatrix.size())
00842 throw NxsUnalignedBlock::NxsX_NoDataForTaxon(taxInd);
00843 NxsDiscreteStateRow & row = uMatrix[taxInd];
00844 if (charInd >= (unsigned)row.size())
00845 return UINT_MAX;
00846 return mapper.GetNumStatesInStateCode(row[charInd]);
00847 }
00848
00857 bool NxsUnalignedBlock::IsMissingState(
00858 unsigned taxInd,
00859 unsigned charInd)
00860 {
00861 if (taxInd >= uMatrix.size())
00862 throw NxsNCLAPIException("Taxon index out of range of NxsUnalignedBlock::IsMissingState");
00863 NxsDiscreteStateRow & row = uMatrix[taxInd];
00864 if (charInd >= (unsigned)row.size())
00865 throw NxsNCLAPIException("Character index out of range of NxsUnalignedBlock::IsMissingState");
00866 return mapper.GetNumStates() == (unsigned) row[charInd];
00867 }
00868
00878 bool NxsUnalignedBlock::IsPolymorphic(
00879 unsigned taxInd,
00880 unsigned charInd)
00881 {
00882 if (taxInd >= uMatrix.size())
00883 throw NxsNCLAPIException("Taxon index out of range of NxsUnalignedBlock::IsMissingState");
00884 NxsDiscreteStateRow & row = uMatrix[taxInd];
00885 if (charInd >= (unsigned)row.size())
00886 throw NxsNCLAPIException("Character index out of range of NxsUnalignedBlock::IsMissingState");
00887 return mapper.IsPolymorphic(row[charInd]);
00888 }
00889
00890