00001
00008 #include "WekaSource.h"
00009
00010 using namespace std;
00011 using namespace Marsyas;
00012
00013 WekaSource::WekaSource(mrs_string name):MarSystem("WekaSource",name)
00014 {
00015 addControls();
00016 validationModeEnum_ = None;
00017 currentIndex_ = 0;
00018 }
00019
00020 WekaSource::~WekaSource()
00021 {
00022 data_.Clear();
00023 useTestSetData_.Clear();
00024 }
00025
00026 WekaSource::WekaSource(const WekaSource& a) : MarSystem(a) {
00027 validationModeEnum_ = None;
00028 currentIndex_ = 0;
00029 ctrl_regression_ = getctrl("mrs_bool/regression");
00030 }
00031
00032 MarSystem *WekaSource::clone() const
00033 {
00034 return new WekaSource(*this);
00035 }
00036
00037 void
00038 WekaSource::addControls()
00039 {
00040 addctrl("mrs_string/filename", "");
00041 setctrlState("mrs_string/filename", true);
00042
00043
00044
00045
00046 addctrl("mrs_string/attributesToInclude", "");
00047 setctrlState("mrs_string/attributesToInclude", true);
00048
00049
00050
00051 addctrl("mrs_string/classNames", "");
00052
00053
00054 addctrl("mrs_natural/nClasses", 0);
00055 addctrl("mrs_bool/regression", false, ctrl_regression_);
00056
00057
00058
00059 addctrl("mrs_string/mode", "train");
00060
00061
00062 setctrl("mrs_natural/onSamples", 1 );
00063
00064
00065 addctrl("mrs_natural/nAttributes", 0);
00066 addctrl("mrs_string/attributeNames", "");
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 addctrl("mrs_string/validationMode", "");
00078 addctrl("mrs_bool/done", false);
00079
00080 addctrl("mrs_natural/nInstances", 0);
00081
00082
00083
00084
00085 addctrl("mrs_string/currentFilename", "");
00086 addctrl("mrs_real/currentSrate", 22050.0);
00087
00088
00089 addctrl("mrs_realvec/instanceIndexes", realvec());
00090
00091 addctrl("mrs_bool/normMaxMin", false);
00092
00093 }
00094
00095 void
00096 WekaSource::myUpdate(MarControlPtr sender)
00097 {
00098 (void) sender;
00099 MRSDIAG("WekaSource.cpp - WekaSource:myUpdate");
00100
00101
00102
00103
00104
00105 if (filename_ != getctrl("mrs_string/filename")->to<mrs_string>())
00106 {
00107
00108
00109 this->updControl("mrs_bool/done", false);
00110 filename_ = getctrl("mrs_string/filename")->to<mrs_string>();
00111 attributesToInclude_ = getctrl("mrs_string/attributesToInclude")->to<mrs_string>();
00112
00113 mrs_bool normMaxMin = getctrl("mrs_bool/normMaxMin")->to<mrs_bool>();
00114
00115 loadFile(filename_, attributesToInclude_, data_);
00116 if (normMaxMin)
00117 {
00118 data_.NormMaxMin();
00119 }
00120
00121
00122
00123 mrs_string names;
00124 bool first = true;
00125 for(vector<mrs_string>::const_iterator citer = classesFound_.begin(); citer!= classesFound_.end(); citer++)
00126 {
00127 if(!first)
00128 names += ",";
00129
00130 names += (*citer);
00131 first = false;
00132 }
00133 setctrl("mrs_string/classNames", names);
00134 setctrl("mrs_natural/nClasses", (mrs_natural)classesFound_.size());
00135
00136 names = "";
00137 first = true;
00138 mrs_natural index = 0;
00139 for(vector<mrs_string>::const_iterator citer = attributesFound_.begin(); citer!= attributesFound_.end(); citer++,index++)
00140 {
00141 if(attributesIncluded_[index])
00142 {
00143 if(!first)
00144 names += ",";
00145
00146 names += (*citer);
00147 first = false;
00148 }
00149 }
00150 MRSASSERT(index == (mrs_natural)attributesIncluded_.size());
00151
00152 setctrl("mrs_string/attributeNames", names);
00153 ctrl_onObsNames_->setValue(names);
00154 setctrl("mrs_natural/onSamples", 1);
00155 setctrl("mrs_natural/nAttributes", (mrs_natural)attributesFound_.size());
00156 setctrl("mrs_natural/onObservations", (mrs_natural)attributesFound_.size()+1);
00157 setctrl("mrs_natural/nInstances", (mrs_natural)data_.getRows());
00158
00159 mrs_string mode = getctrl("mrs_string/validationMode")->to<mrs_string>();
00160 validationMode_ = mode;
00161
00162 if (validationMode_ == "")
00163 {
00164 validationModeEnum_ = None;
00165 currentIndex_ = 0;
00166 return;
00167 }
00168
00169 if (validationMode_ == "OutputInstancePair")
00170 {
00171 validationModeEnum_ = OutputInstancePair;
00172 MarControlAccessor acc(getctrl("mrs_realvec/instanceIndexes"));
00173 realvec& instIdxs = acc.to<mrs_realvec>();
00174 instIdxs.create(0.0, 1, 2);
00175 setctrl("mrs_natural/onSamples", 2);
00176 return;
00177 }
00178
00179
00180 char *cp = strtok((char *)mode.c_str(), ",");
00181 MRSASSERT(cp!=NULL);
00182 if(strcmp(cp ,"kFold")==0)
00183 {
00184 data_.Shuffle();
00185
00186
00187 cp = (char *)strtok(NULL, ",");
00188 MRSASSERT(cp!=NULL);
00189
00190 validationModeEnum_ = kFoldStratified;
00191 if(strcmp(cp,"NS")==0)
00192 validationModeEnum_ = kFoldNonStratified;
00193 else if(strcmp(cp,"S")==0)
00194 validationModeEnum_ = kFoldStratified;
00195 else
00196 {
00197 MRSASSERT(0);
00198 (void)42;
00199 }
00200
00201 cp = (char *)strtok(NULL, ",");
00202 MRSASSERT(cp!=NULL);
00203
00204 foldCount_ = ::atol(cp);
00205 MRSASSERT(foldCount_>=2&&foldCount_<=10);
00206
00207 if( validationModeEnum_ != kFoldStratified)
00208 {
00209 cout << "=== Non-Stratified cross-validation (" << foldCount_ << " folds) ===" << endl;
00210
00211 foldData_.SetupkFoldSections(data_, foldCount_);
00212 }
00213 else
00214 {
00215 cout << "=== Stratified cross-validation (" << foldCount_ << " folds) ===" << endl;
00216 foldClassData_.clear();
00217 foldClassData_.resize(classesFound_.size());
00218
00219
00220 for(mrs_natural ii=0; ii<(mrs_natural)classesFound_.size(); ++ii)
00221 {
00222 WekaFoldData data;
00223 data.setFold(true);
00224 data.SetupkFoldSections(data_, foldCount_, ii);
00225 foldClassData_[ii] = data;
00226 }
00227 foldClassDataIndex_ = 0;
00228 }
00229
00230 }
00231 else if(strcmp(cp ,"UseTestSet")==0)
00232 {
00233 validationModeEnum_ = UseTestSet;
00234
00235 cp = (char *)strtok(NULL, ",");
00236 MRSASSERT(cp!=NULL);
00237 useTestSetFilename_ = cp;
00238 loadFile(cp, attributesToInclude_, useTestSetData_);
00239 MRSASSERT(data_.getCols()==useTestSetData_.getCols());
00240 currentIndex_ = 0;
00241
00242 cout << "=== Evaluation on test set === (" << useTestSetFilename_.c_str() << ") ===" << endl;
00243
00244 }
00245 else if(strcmp(cp ,"PercentageSplit")==0)
00246 {
00247 data_.Shuffle();
00248 data_.Dump("shuffle.txt", classesFound_);
00249 validationModeEnum_ = PercentageSplit;
00250
00251 cp = (char *)strtok(NULL, ",");
00252 MRSASSERT(cp!=NULL);
00253 percentageSplit_ = ::atoi(cp);
00254 cout << "=== Evaluation on percentage split " << percentageSplit_ << "% ===" << endl;
00255 MRSASSERT(percentageSplit_>0&&percentageSplit_<100);
00256
00257 percentageIndex_ = ((mrs_natural)data_.size() * percentageSplit_) / 100;
00258
00259 percentageIndex_--;
00260
00261 if(percentageIndex_ < 1) percentageIndex_ = 1;
00262 currentIndex_ = 0;
00263
00264 }
00265
00266 }
00267
00268 }
00269
00270 void WekaSource::myProcess(realvec& in,realvec &out)
00271 {
00272 (void) in;
00273
00274 if(getctrl("mrs_bool/done")->to<mrs_bool>()) return;
00275 bool trainMode = (strcmp(getctrl("mrs_string/mode")->to<mrs_string>().c_str(), "train") == 0);
00276 switch(validationModeEnum_)
00277 {
00278 case kFoldNonStratified:
00279 handleFoldingNonStratifiedValidation(trainMode, out);
00280 break;
00281 case kFoldStratified:
00282 handleFoldingStratifiedValidation(trainMode, out);
00283 break;
00284 case UseTestSet:
00285 handleUseTestSet(trainMode, out);
00286 break;
00287 case PercentageSplit:
00288 handlePercentageSplit(trainMode, out);
00289 break;
00290 case OutputInstancePair:
00291 handleInstancePair(out);
00292 break;
00293 default:
00294 handleDefault(trainMode, out);
00295 }
00296 }
00297
00298
00299 void
00300 WekaSource::handleDefault(bool trainMode, realvec &out)
00301 {
00302
00303 (void) trainMode;
00304
00305 vector<mrs_real> *row = NULL;
00306 mrs_string fname = data_.GetFilename(currentIndex_);
00307 row = data_.at(currentIndex_++);
00308 if(currentIndex_ >= (mrs_natural)data_.size())
00309 {
00310 this->updControl("mrs_bool/done", true);
00311 }
00312 for(mrs_natural ii=0; ii<(mrs_natural)row->size(); ++ii)
00313 {
00314 out(ii, 0) = row->at(ii);
00315 this->updControl("mrs_string/currentFilename", fname);
00316 }
00317 }
00318
00319 void
00320 WekaSource::handleInstancePair(realvec& out)
00321 {
00322 const realvec& instIdxs = getctrl("mrs_realvec/instanceIndexes")->to<mrs_realvec>();
00323
00324 mrs_natural i = (mrs_natural)instIdxs(0);
00325 mrs_natural j = (mrs_natural)instIdxs(1);
00326
00327 if(i >= (mrs_natural)data_.size() || j >= (mrs_natural)data_.size())
00328 {
00329
00330 MRSWARN("WekaSource::handlePair - out of bound file indexes!");
00331 return;
00332 }
00333
00334 vector<mrs_real> *rowi = NULL;
00335 vector<mrs_real> *rowj = NULL;
00336
00337 mrs_string fnamei = data_.GetFilename(i);
00338 mrs_string fnamej = data_.GetFilename(j);
00339
00340 rowi = data_.at(i);
00341 rowj = data_.at(j);
00342
00343 for(mrs_natural ii=0; ii<(mrs_natural)rowi->size(); ++ii)
00344 {
00345 out(ii, 0) = rowi->at(ii);
00346 out(ii, 1) = rowj->at(ii);
00347 }
00348 this->updControl("mrs_string/currentFilename", fnamei+"_"+fnamej);
00349
00350 }
00351
00352 void WekaSource::handlePercentageSplit(bool trainMode, realvec &out)
00353 {
00354 vector<mrs_real> *row = NULL;
00355 if(trainMode)
00356 {
00357 MRSASSERT(currentIndex_<percentageIndex_);
00358 row = data_.at(currentIndex_++);
00359
00360
00361 if(currentIndex_>=percentageIndex_)
00362 {
00363 this->updControl("mrs_string/mode", "predict");
00364 }
00365 }
00366 else
00367 {
00368 row = data_.at(currentIndex_++);
00369 if(currentIndex_ >= (mrs_natural)data_.size())
00370 {
00371 this->updControl("mrs_bool/done", true);
00372 }
00373 }
00374
00375 for(mrs_natural ii=0; ii<(mrs_natural)row->size(); ++ii)
00376 {
00377 out(ii, 0) = row->at(ii);
00378 }
00379 }
00380
00381 void WekaSource::handleUseTestSet(bool trainMode, realvec &out)
00382 {
00383 vector<mrs_real> *row = NULL;
00384 if(trainMode)
00385 {
00386 row = data_.at(currentIndex_++);
00387
00388 if(currentIndex_ >= (mrs_natural)data_.size())
00389 {
00390 this->updControl("mrs_string/mode", "predict");
00391 currentIndex_ = 0;
00392 }
00393 }
00394 else
00395 {
00396 row = useTestSetData_.at(currentIndex_++);
00397
00398 if(currentIndex_ >= (mrs_natural)useTestSetData_.size())
00399 {
00400 this->updControl("mrs_bool/done", true);
00401 currentIndex_ = 0;
00402 }
00403 }
00404 MRSASSERT((mrs_natural)row->size() == out.getCols());
00405 for(mrs_natural ii=0; ii<(mrs_natural)row->size(); ++ii)
00406 {
00407 out(ii, 0 ) = row->at(ii);
00408 }
00409 }
00410
00411 void WekaSource::handleFoldingStratifiedValidation(bool trainMode, realvec &out)
00412 {
00413 WekaFoldData::nextMode currentMode = trainMode ? WekaFoldData::Training : WekaFoldData::Predict;
00414
00415 WekaFoldData::nextMode next;
00416
00417 vector<mrs_real> *row = foldClassData_[foldClassDataIndex_].Next(next);
00418
00419
00420
00421 switch(currentMode)
00422 {
00423 case WekaFoldData::Training:
00424 {
00425 if(next == WekaFoldData::Predict)
00426 {
00427 foldClassDataIndex_++;
00428 if(foldClassDataIndex_ >= (mrs_natural)foldClassData_.size())
00429 {
00430 foldClassDataIndex_ = 0;
00431 this->updControl("mrs_string/mode", "predict");
00432 }
00433 }
00434 }break;
00435 case WekaFoldData::Predict:
00436 {
00437 if(next == WekaFoldData::None)
00438 {
00439 foldClassDataIndex_++;
00440 if(foldClassDataIndex_ >= (mrs_natural)foldClassData_.size())
00441 {
00442 foldClassDataIndex_ = 0;
00443 this->updControl("mrs_bool/done", true);
00444 }
00445 }
00446 else if(next == WekaFoldData::Training)
00447 {
00448 foldClassDataIndex_++;
00449 if(foldClassDataIndex_ >= (mrs_natural)foldClassData_.size())
00450 {
00451 foldClassDataIndex_ = 0;
00452 this->updControl("mrs_string/mode", "train");
00453 }
00454 }
00455 }break;
00456
00457 default:
00458 (void) 42;
00459 }
00460
00461
00462 MRSASSERT((mrs_natural)row->size() == out.getRows());
00463 for(mrs_natural ii=0; ii<(mrs_natural)row->size(); ++ii)
00464 {
00465 out(ii, 0) = row->at(ii);
00466 }
00467
00468 }
00469
00470 void WekaSource::handleFoldingNonStratifiedValidation(bool trainMode, realvec &out)
00471 {
00472
00473
00474
00475 WekaFoldData::nextMode next;
00476
00477
00478 vector<mrs_real> *row = foldData_.Next(next);
00479
00480 if(next == WekaFoldData::None)
00481 this->updControl("mrs_bool/done", true);
00482
00483 else if(next == WekaFoldData::Training)
00484 this->updControl("mrs_string/mode", "train");
00485
00486 else if(next == WekaFoldData::Predict)
00487 this->updControl("mrs_string/mode", "predict");
00488
00489 MRSASSERT((mrs_natural) row->size() == out.getRows());
00490
00491 for(mrs_natural ii=0; ii<(mrs_natural)row->size(); ++ii)
00492 {
00493 out(ii, 0) = row->at(ii);
00494 }
00495 }
00496
00497 void WekaSource::loadFile(const std::string& filename, const std::string& attributesToExtract, WekaData& data)
00498 {
00499
00500
00501
00502 ifstream *mis = new ifstream;
00503
00504 mis->open(filename.c_str());
00505
00506
00507 MRSASSERT( mis->is_open() );
00508
00509 data_.Clear();
00510
00511 parseHeader(*mis, filename, attributesToExtract);
00512
00513 parseData(*mis, filename, data);
00514 mis->close();
00515 delete mis;
00516
00517 }
00518
00519 void WekaSource::parseHeader(ifstream& mis, const mrs_string& filename, const std::string& attributesToExtract)
00520 {
00521
00522
00523
00524
00525
00526 char str[1024];
00527
00528 while (mis.peek() == '%')
00529 {
00530 mis.getline(str, 1023);
00531 }
00532
00533
00534 mrs_string token1,token2,token3;
00535 mrs_string whitespace = " \t\v\f\r\n";
00536 mrs_string::size_type startpos;
00537
00538
00539 mis >> token1;
00540 getline(mis, token2);
00541
00542
00543 startpos = token2.find_first_not_of(whitespace);
00544 if (startpos != mrs_string::npos)
00545 {
00546 token2 = token2.substr(startpos);
00547 }
00548
00549 if ((token1 != "@relation")&&(token1 != "@RELATION"))
00550 {
00551 MRSERR("Badly formatted .arff file: file must begin with @relation.");
00552 return;
00553 }
00554 if (token2.find("\t") != mrs_string::npos)
00555 {
00556 MRSERR("Badly formatted .arff file: Relation name cannot contain tab characters.");
00557 return;
00558 }
00559 if (token2.find_first_of(whitespace) != mrs_string::npos)
00560 {
00561 MRSERR("Badly formatted .arff file: Marsyas cannot handle relation names with whitespace.");
00562 return;
00563 }
00564 relation_ = token2;
00565
00566 attributesFound_.clear();
00567 attributesIncluded_.clear();
00568 classesFound_.clear();
00569 attributesIncludedList_.clear();
00570
00571
00572
00573 while( mis >> token1 && (token1 == "@attribute" || (token1 == "@ATTRIBUTE")))
00574 {
00575 mis >> token2;
00576 getline(mis, token3);
00577
00578
00579 startpos = token3.find_first_not_of(" \t");
00580 if (mrs_string::npos != startpos)
00581 token3 = token3.substr(startpos);
00582
00583 if ((token3 == "real") || (token3 == "REAL"))
00584 {
00585 attributesFound_.push_back(token2);
00586 attributesIncluded_.push_back(true);
00587 }
00588 else if (token3[0] == '{')
00589 {
00590 mrs_string token = token3.substr( 1, token3.length()-2 );
00591
00592 std::stringstream tokenStream(token);
00593 std::string cell;
00594 while(std::getline(tokenStream,cell,','))
00595 {
00596 classesFound_.push_back(cell);
00597 }
00598 }
00599 else
00600 {
00601 attributesFound_.push_back(token2);
00602 attributesIncluded_.push_back(false);
00603 MRSWARN("Incompatible datatype " + token3 + " found in file '" + filename + "'. " +
00604 "attribute " + token2 + "will be ignored!");
00605 }
00606 }
00607
00608 if ((token1 != "@data") && (token1 != "@DATA")) {
00609 MRSERR("Badly formatted .arff file: Finished parsing attributes but did not find @data section.");
00610 }
00611
00612
00613
00614
00615
00616 for(vector<mrs_string>::const_iterator citer = attributesFound_.begin(); citer!= attributesFound_.end(); citer++)
00617 {
00618 }
00619
00620 if (classesFound_.size() == 0) {
00621 ctrl_regression_->setValue(true);
00622
00623 attributesFound_.pop_back();
00624 attributesIncluded_.pop_back();
00625 }
00626
00627 parseAttributesToInclude(attributesToInclude_);
00628 }
00629
00630 void WekaSource::parseData(ifstream& mis, const mrs_string& filename, WekaData& data)
00631 {
00632
00633 (void) filename;
00634 mrs_string currentFname;
00635
00636 MRSASSERT(!mis.eof());
00637
00638 data.Create(attributesIncludedList_.size()+1);
00639
00640 char str[1024];
00641
00642 while (mis.peek() == '%')
00643 {
00644 mis.getline(str, 1023);
00645 }
00646
00647
00648 mrs_string token;
00649
00650
00651 while (token == "")
00652 getline(mis, token);
00653
00654 mrs_natural lineCount = 0;
00655 while(!mis.eof())
00656 {
00657 char *cp = (char *)token.c_str();
00658 if (cp[0] != '%')
00659 {
00660 cp = strtok(cp, ",");
00661
00662 vector<mrs_real> *lineBuffer = new vector<mrs_real>(attributesIncludedList_.size()+1);
00663
00664 mrs_natural index = 0;
00665 for(mrs_natural ii=0; ii < (mrs_natural)attributesFound_.size(); ++ii)
00666 {
00667 MRSASSERT( cp!=NULL );
00668 if(attributesIncluded_[ii])
00669 {
00670 lineBuffer->at(index++) = ::atof( cp );
00671 }
00672 cp = strtok(NULL, ",");
00673 }
00674 MRSASSERT(index == (mrs_natural)lineBuffer->size()-1);
00675
00676 if (ctrl_regression_->isTrue()) {
00677
00678 lineBuffer->at(index) = ::atof( cp );
00679 } else {
00680
00681 MRSASSERT( cp!=NULL );
00682
00683 mrs_natural classIndex = findClass(cp);
00684 MRSASSERT(classIndex>=0);
00685 lineBuffer->at(index) = (mrs_real)classIndex;
00686 }
00687
00688 data.Append(lineBuffer);
00689 data.AppendFilename(currentFname);
00690 lineCount++;
00691
00692
00693
00694 }
00695 else
00696 {
00697
00698
00699 if (strncmp(token.c_str(),"% filename",10) == 0) {
00700 currentFname = token.substr(11);
00701 }
00702
00703 if (strncmp(token.c_str(),"% srate",7) == 0) {
00704 mrs_real currentSrate = atof(token.substr(8).c_str());
00705 this->updControl("mrs_real/currentSrate", currentSrate);
00706 }
00707 }
00708 getline(mis,token);
00709 }
00710
00711
00712
00713 }
00714
00715
00716
00717 mrs_natural WekaSource::findClass(const char *className) const
00718 {
00719 MRSASSERT(className!=NULL);
00720 mrs_natural index = 0;
00721 for(vector<mrs_string>::const_iterator citer = classesFound_.begin(); citer!= classesFound_.end(); citer++,index++)
00722 {
00723 if(*citer == className)
00724 return index;
00725 }
00726 return -1;
00727 }
00728
00729
00730
00731 mrs_natural WekaSource::findAttribute(const char *attribute) const
00732 {
00733 MRSASSERT(attribute!=NULL);
00734
00735 mrs_natural index = 0;
00736 for(vector<mrs_string>::const_iterator citer = attributesFound_.begin(); citer!= attributesFound_.end(); citer++,index++)
00737 {
00738 if(*citer == attribute)
00739 return index;
00740 }
00741 return -1;
00742 }
00743
00744
00745
00746
00747
00748 mrs_natural WekaSource::parseAttribute(const char *attribute) const
00749 {
00750 MRSASSERT(attribute!=NULL);
00751
00752
00753
00754 mrs_natural ret = findAttribute(attribute);
00755 if(ret >= 0) return ret;
00756
00757
00758 for(mrs_natural ii=0; attribute[ii]!='\0'; ++ii)
00759 if(!isdigit(attribute[ii]))
00760 return -1;
00761
00762
00763 return ::atoi(attribute);
00764 }
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775 void WekaSource::parseAttributesToInclude(const std::string& attributesToInclude)
00776 {
00777
00778 (void) attributesToInclude;
00779
00780
00781 attributesIncluded_.resize(attributesFound_.size());
00782
00783
00784
00785 if(attributesToInclude_.size()==0)
00786 {
00787
00788 attributesIncludedList_.assign(attributesFound_.begin(), attributesFound_.end());
00789 for(mrs_natural ii=0; ii<(mrs_natural)attributesIncluded_.size(); ++ii)
00790 {
00791 attributesIncluded_[ii] = true;
00792
00793 }
00794
00795 return;
00796 }
00797
00798
00799 for(mrs_natural ii=0; ii<(mrs_natural)attributesIncluded_.size(); ++ii)
00800 attributesIncluded_[ii] = false;
00801
00802
00803 mrs_string str = attributesToInclude_;
00804 char *cp = strtok((char *)str.c_str(), ",");
00805
00806
00807 while(cp)
00808 {
00809
00810 char *mp = strstr(cp,"-");
00811 if(mp)
00812 {
00813
00814 *mp++ = '\0';
00815
00816
00817 mrs_natural left = parseAttribute(cp);
00818 MRSASSERT(left>=0&&left<(mrs_natural)attributesFound_.size());
00819
00820
00821 mrs_natural right = parseAttribute(mp);
00822 MRSASSERT(right>=0&&right<(mrs_natural)attributesFound_.size());
00823
00824
00825 MRSASSERT(right>=left);
00826
00827
00828 for(mrs_natural ii=left; ii<=right; ++ii)
00829 attributesIncluded_[ii] = true;
00830 }
00831
00832 else
00833 {
00834 mrs_natural index = parseAttribute(cp);
00835 MRSASSERT(index>=0&&index<(mrs_natural)attributesFound_.size());
00836 attributesIncluded_[index] = true;
00837 }
00838
00839
00840 cp = strtok(NULL, ",");
00841 }
00842
00843
00844
00845 attributesIncludedList_.clear();
00846 for(mrs_natural ii=0; ii<(mrs_natural)attributesIncluded_.size(); ++ii)
00847 {
00848 if(attributesIncluded_[ii])
00849 attributesIncludedList_.push_back(attributesFound_[ii]);
00850 }
00851 }