/* * Copyright (C) 2008,2009,2010 Thorsten Liebig (Thorsten.Liebig@gmx.de) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include "ParameterObjects.h" #include #include #include "tinyxml.h" #include "CSFunctionParser.h" #include "CSUseful.h" bool ReadTerm(ParameterScalar &PS, TiXmlElement &elem, const char* attr, double val) { double dHelp; PS.SetValue(val); // set default value const char* chHelp=elem.Attribute(attr); if (chHelp==NULL) return false; PS.SetValue(chHelp); // set string value if found return true; } void WriteTerm(ParameterScalar &PS, TiXmlElement &elem, const char* attr, bool mode, bool scientific) { if (PS.GetMode() && mode) elem.SetAttribute(attr,PS.GetString().c_str()); else { if (PS.GetValue()==NAN) return; if (scientific) { char doubleVal[50]; sprintf(doubleVal,"%e",PS.GetValue()); elem.SetAttribute(attr,doubleVal); } else elem.SetDoubleAttribute(attr,PS.GetValue()); } } bool ReadVectorTerm(ParameterScalar PS[3], TiXmlElement &elem, std::string attr, double val, const char delimiter) { return ReadVectorTerm(PS, elem, attr.c_str(), val, delimiter); } bool ReadVectorTerm(ParameterScalar PS[3], TiXmlElement &elem, const char* attr, double val, const char delimiter) { //initialize with default value for (int n=0;n<3;++n) PS[n].SetValue(val); const char* values = elem.Attribute(attr); if (values==NULL) return false; std::vector val_list = SplitString2Vector(values, delimiter); if (val_list.size()>3) return false; for (int n=0;n<3;++n) PS[n].SetValue(val); for (int n=0;n<(int)val_list.size();++n) { std::string sHelp=val_list.at(n); bool ok; double val = String2Double(sHelp, ok); if (ok) PS[n].SetValue(val); else PS[n].SetValue(sHelp.c_str()); } return true; } void WriteVectorTerm(ParameterScalar PS[3], TiXmlElement &elem, std::string attr, bool mode, bool scientific, const char delimiter) { WriteVectorTerm(PS, elem, attr.c_str(), mode, scientific, delimiter); } void WriteVectorTerm(ParameterScalar PS[3], TiXmlElement &elem, const char* attr, bool mode, bool sci, const char delimiter) { std::stringstream ss; if (sci) ss << std::scientific; for (int i=0;i<3;++i) { if (PS[i].GetMode() && mode) ss << PS[i].GetString(); else if (PS[i].GetValue()==NAN) ss << "NAN" << std::endl; else ss << PS[i].GetValue(); if (i<2) ss << delimiter; } elem.SetAttribute(attr,ss.str().c_str()); } Parameter::Parameter() { bModified=true; dValue=0; Type=Const; bSweep=true; // Set=NULL; } Parameter::Parameter(const std::string Paraname, double val) { sName=Paraname; SetValue(val); Type=Const; bSweep=true; // Set=NULL; } Parameter::~Parameter() { // if (Set!=NULL) Set->RemoveParameter(this); } void Parameter::PrintSelf(FILE* /*out*/) { fprintf(stderr," Parameter: %s Value: %f Type %d\n\n",sName.c_str(),dValue,Type); } bool Parameter::Write2XML(TiXmlNode& root) { TiXmlElement *elem=NULL; if (Type==Const) { elem = new TiXmlElement("Parameter"); elem->SetAttribute("Type","Const"); } else elem = root.ToElement(); if (elem==NULL) return false; elem->SetAttribute("name",sName.c_str()); elem->SetAttribute("Sweep",bSweep); elem->SetDoubleAttribute("value",dValue); if (Type==Const) root.LinkEndChild(elem); return true; } bool Parameter::ReadFromXML(TiXmlNode &root) { TiXmlElement *elem = root.ToElement(); if (elem==NULL) return false; int iAtt=0; if (elem->QueryIntAttribute("Sweep",&iAtt)!=TIXML_SUCCESS) bSweep=true; else if (iAtt>0) bSweep=true; else bSweep=false; double val=0; if (elem->QueryDoubleAttribute("value",&val)!=TIXML_SUCCESS) return false; SetValue(val); const char* att=elem->Attribute("name"); if (att==NULL) sName=std::string(); else sName=std::string(att); return true; } Parameter* Parameter::GetParameterFromXML(TiXmlNode &/*root*/) { return NULL; } LinearParameter::LinearParameter() : Parameter() { Type=Linear; dMin=dMax=dStep=0; } LinearParameter::LinearParameter(const std::string Paraname, double val, double min, double max, double step) : Parameter(Paraname,val) { //sName=string(Paraname); if (maxType==Linear) { dMin=parameter->dMin; dMax=parameter->dMax; dStep=parameter->dStep; } else { Type=Linear; dMin=dMax=dStep=0; } SetValue(dValue); } void LinearParameter::SetValue(double val) { if (val>dMax) val=dMax; else if (valdMax) dValue=dValue-dStep; } bModified=true; } bool LinearParameter::IncreaseStep() { if (dValue+dStep>dMax) return false; SetValue(dValue+dStep); return true; } void LinearParameter::PrintSelf(FILE* /*out*/) { fprintf(stderr," Parameter: %s Value: %f\n from %f to %f; Stepsize: %f\n",sName.c_str(),dValue,dMin,dMax,dStep); } bool LinearParameter::Write2XML(TiXmlNode& root) { TiXmlElement para("Parameter"); para.SetAttribute("Type","Linear"); Parameter::Write2XML(para); para.SetDoubleAttribute("min",dMin); para.SetDoubleAttribute("max",dMax); para.SetDoubleAttribute("step",dStep); root.InsertEndChild(para); return true; } bool LinearParameter::ReadFromXML(TiXmlNode &root) { TiXmlElement *elem = root.ToElement(); if (elem==NULL) return false; if (elem->QueryDoubleAttribute("min",&dMin)!=TIXML_SUCCESS) return false; if (elem->QueryDoubleAttribute("max",&dMax)!=TIXML_SUCCESS) return false; if (elem->QueryDoubleAttribute("step",&dStep)!=TIXML_SUCCESS) return false; if (Parameter::ReadFromXML(root)==false) return false; // const char* att=elem->Attribute("name"); // if (att==NULL) return false; // sName=string(att); // if (elem->QueryDoubleAttribute("value",&dValue)!=TIXML_SUCCESS) return false; return true; } ParameterSet::ParameterSet(void) { bModified=true; } ParameterSet::~ParameterSet(void) { clear(); } size_t ParameterSet::LinkParameter(Parameter* newPara) { vParameter.push_back(newPara); // newPara->ParameterSet(this); return vParameter.size(); } size_t ParameterSet::DeleteParameter(size_t index) { if (index>=vParameter.size()) return vParameter.size(); std::vector::iterator pIter=vParameter.begin(); vParameter.erase(pIter+index); return vParameter.size(); } size_t ParameterSet::DeleteParameter(Parameter* para) { std::vector::iterator pIter=vParameter.begin(); while (pIter!=vParameter.end()) { if (*pIter==para) { vParameter.erase(pIter); return vParameter.size(); } ++pIter; } return vParameter.size(); } void ParameterSet::clear() { for (size_t i=0; iGetModified()==true) return true; return false; } void ParameterSet::SetModified(bool mod) { if (mod==true) { bModified=true; return; } bModified=false; for (size_t i=0; iSetModified(false); } double* ParameterSet::GetValueArray(double *array) { if (array==NULL) return array; for (size_t i=0; iGetValue(); } return array; } int ParameterSet::CountSweepSteps(int SweepMode) { int count=0; switch (SweepMode) { case 1: for (size_t i=0; iGetSweep()) { if (count==0) count=vParameter.at(i)->CountSteps(); else count*=vParameter.at(i)->CountSteps(); } return count; break; case 2: for (size_t i=0; iGetSweep()) count+=vParameter.at(i)->CountSteps(); return count; break; } return 0; } void ParameterSet::InitSweep() { for (size_t i=0; iGetSweep()) { vParameter.at(i)->Save(); vParameter.at(i)->InitSweep(); } SweepPara=0; } void ParameterSet::EndSweep() { for (size_t i=0; iGetSweep()) { vParameter.at(i)->Restore(); } } bool ParameterSet::NextSweepPos(int SweepMode) { switch (SweepMode) { case 1: { int level=vParameter.size()-1; while (level>=0) { if (vParameter.at(level)->GetSweep()) { if (vParameter.at(level)->IncreaseStep()) return true; else { vParameter.at(level)->InitSweep(); --level; } } else --level; } return false; break; } case 2: if ((unsigned int)SweepPara>=vParameter.size()) return false; if (vParameter.at(SweepPara)->GetSweep()) { if (vParameter.at(SweepPara)->IncreaseStep()) return true; else ++SweepPara; return NextSweepPos(SweepMode); } else { ++SweepPara; return NextSweepPos(SweepMode); } break; } return false; } const std::string ParameterSet::GetParameterString(const std::string spacer) { std::string ParameterString; for (size_t i=0; i0) ParameterString+=spacer; ParameterString+=vParameter.at(i)->GetName(); } return ParameterString; } const std::string ParameterSet::GetParameterValueString(const std::string spacer, bool ValuesOnly) { std::string ParameterValueString; for (size_t i=0; i0) ParameterValueString+=spacer; if (!ValuesOnly) { ParameterValueString+=vParameter.at(i)->GetName(); ParameterValueString+="="; } std::ostringstream os; os << vParameter.at(i)->GetValue(); ParameterValueString+=os.str(); } return ParameterValueString.c_str(); } void ParameterSet::PrintSelf(FILE* out) { fprintf(out," Parameter-Set Printout, Qty of Parameter: %d\n",(int)vParameter.size()); for (size_t i=0; iPrintSelf(out); } } bool ParameterSet::Write2XML(TiXmlNode& root) { TiXmlElement pSet("ParameterSet"); //pSet.SetAttribute("QtyParameter",(int)vParameter.size()); for (size_t i=0;iWrite2XML(pSet); root.InsertEndChild(pSet); return true; } bool ParameterSet::ReadFromXML(TiXmlNode &root) { TiXmlNode* paraNode = root.FirstChild("Parameter"); while (paraNode!=NULL) { TiXmlElement *elem = paraNode->ToElement(); if (elem!=NULL) { const char* att=elem->Attribute("Type"); if (att!=NULL) { Parameter* newPara=NULL; if (strcmp(att,"Const")==0) newPara = new Parameter(); else if (strcmp(att,"Linear")==0) newPara = new LinearParameter(); if (newPara!=NULL) { if (newPara->ReadFromXML(*elem)==true) this->InsertParameter(newPara); } } } paraNode=paraNode->NextSiblingElement("Parameter"); }; return true; } ParameterScalar::ParameterScalar() { clParaSet=NULL; bModified=true; ParameterMode=false; sValue.clear(); dValue=0; } ParameterScalar::ParameterScalar(ParameterSet* ParaSet, const std::string value) { SetParameterSet(ParaSet); SetValue(value); } ParameterScalar::ParameterScalar(ParameterSet* ParaSet, double value) { SetParameterSet(ParaSet); bModified=true; SetValue(value); } ParameterScalar::ParameterScalar(ParameterScalar* ps) { Copy(ps); } ParameterScalar::~ParameterScalar() { } void ParameterScalar::SetParameterSet(ParameterSet *paraSet) { clParaSet=paraSet; } int ParameterScalar::SetValue(const std::string value, bool Eval) { if (value.empty()) return -1; //check if string is only a plain double char *pEnd; double val = strtod(value.c_str(),&pEnd); if (*pEnd == 0) SetValue(val); ParameterMode=true; bModified=true; sValue=value; if (Eval) return Evaluate(); return 0; } void ParameterScalar::SetValue(double value) { ParameterMode=false; dValue=value; sValue.clear(); } double ParameterScalar::GetValue() const { return dValue; } const std::string ParameterScalar::GetValueString() const { if (ParameterMode) return sValue; std::stringstream numString; numString << dValue; return numString.str(); } int ParameterScalar::Evaluate() { if (ParameterMode==false) return 0; if (clParaSet!=NULL) bModified = bModified || clParaSet->GetModified(); if (bModified==false) return 0; CSFunctionParser fParse; dValue=0; if (clParaSet!=NULL) fParse.Parse(sValue,clParaSet->GetParameterString()); else fParse.Parse(sValue,""); if (fParse.GetParseErrorType()!=FunctionParser::FP_NO_ERROR) return fParse.GetParseErrorType()+100; bModified=false; if (clParaSet!=NULL) { double *vars = new double[clParaSet->GetQtyParameter()]; vars=clParaSet->GetValueArray(vars); dValue=fParse.Eval(vars); delete[] vars;vars=NULL; } else dValue=fParse.Eval(NULL); return fParse.EvalError(); } double ParameterScalar::GetEvaluated(double* ParaValues, int &EC) { if (ParameterMode==false) return dValue; CSFunctionParser fParse; fParse.Parse(sValue,clParaSet->GetParameterString()); if (fParse.GetParseErrorType()!=FunctionParser::FP_NO_ERROR) { EC = fParse.GetParseErrorType()+100; return 0; } double dvalue = fParse.Eval(ParaValues); EC = fParse.EvalError(); return dvalue; } void ParameterScalar::Copy(ParameterScalar* ps) { SetParameterSet(ps->clParaSet); bModified=ps->bModified; ParameterMode=ps->ParameterMode; sValue=std::string(ps->sValue); dValue=ps->dValue; } std::string PSErrorCode2Msg(int code) { std::string msg; PSErrorCode2Msg(code,&msg); return msg; } void PSErrorCode2Msg(int code, std::string *msg) { switch (code) { case -1: msg->append("Internal Error"); break; case 0: msg->append("No Error"); break; case 1: msg->append("Division by zero"); break; case 2: msg->append("sqrt error (sqrt of a negative value)"); break; case 3: msg->append("log error (logarithm of a negative value)"); break; case 4: msg->append("trigonometric error (asin or acos of illegal value)"); break; case 5: msg->append("Maximum recursion level reached"); break; case 100: msg->append("Syntax error (check Parameter)"); break; case 101: msg->append("Mismatched parenthesis"); break; case 102: msg->append("Missing \')\'"); break; case 103: msg->append("Empty parentheses"); break; case 104: msg->append("Syntax error: Operator expected"); break; case 105: msg->append("Not enough memory"); break; case 106: msg->append("An unexpected error occurred"); break; case 107: msg->append("Syntax error in parameters"); break; case 108: msg->append("Illegal number of parameters to function"); break; case 109: msg->append("Syntax error: Premature end of string"); break; case 110: msg->append("Syntax error: Expecting ( after function"); break; }; }