00001
00002
00003
00004 #include "tplate.h"
00005 #include "common.h"
00006 #include "func.h"
00007 #include "udf.h"
00008 #include "bfunc.h"
00009 #include "ast.h"
00010 #include "lexer.h"
00011 #include "cparser.h"
00012 #include "eparser.h"
00013 #include "guess.h"
00014
00015
00016 using namespace std;
00017
00018 string Tplate::as_formula() const
00019 {
00020 string r = name + "(";
00021 for (size_t i = 0; i != fargs.size(); ++i) {
00022 if (i != 0)
00023 r += ", ";
00024 r += fargs[i];
00025 if (!defvals[i].empty())
00026 r += "=" + defvals[i];
00027 }
00028 r += ") = " + rhs;
00029 return r;
00030 }
00031
00032 bool Tplate::is_coded() const
00033 {
00034 return create != create_CompoundFunction &&
00035 create != create_SplitFunction &&
00036 create != create_CustomFunction &&
00037 create != NULL;
00038 }
00039
00040 vector<string> Tplate::get_missing_default_values() const
00041 {
00042 vector<string> gkeys;
00043 if (peak_d)
00044 gkeys.insert(gkeys.end(), Guess::peak_traits.begin(),
00045 Guess::peak_traits.end());
00046 if (linear_d)
00047 gkeys.insert(gkeys.end(), Guess::linear_traits.begin(),
00048 Guess::linear_traits.end());
00049 ExpressionParser ep(NULL);
00050 vector<string> missing;
00051 for (size_t i = 0; i < fargs.size(); ++i) {
00052 string dv = defvals[i].empty() ? fargs[i] : defvals[i];
00053 ep.clear_vm();
00054 Lexer lex(dv.c_str());
00055 ep.parse_expr(lex, 0, &gkeys, &missing);
00056 }
00057 return missing;
00058 }
00059
00060 #define FACTORY_FUNC(NAME) \
00061 Function* create_##NAME(const Settings* settings, const std::string& name, \
00062 Tplate::Ptr tp, const std::vector<std::string>& vars) \
00063 { return new NAME(settings, name, tp, vars); }
00064
00065 FACTORY_FUNC(FuncConstant)
00066 FACTORY_FUNC(FuncLinear)
00067 FACTORY_FUNC(FuncQuadratic)
00068 FACTORY_FUNC(FuncCubic)
00069 FACTORY_FUNC(FuncPolynomial4)
00070 FACTORY_FUNC(FuncPolynomial5)
00071 FACTORY_FUNC(FuncPolynomial6)
00072 FACTORY_FUNC(FuncGaussian)
00073 FACTORY_FUNC(FuncSplitGaussian)
00074 FACTORY_FUNC(FuncLorentzian)
00075 FACTORY_FUNC(FuncPearson7)
00076 FACTORY_FUNC(FuncSplitPearson7)
00077 FACTORY_FUNC(FuncPseudoVoigt)
00078 FACTORY_FUNC(FuncVoigt)
00079 FACTORY_FUNC(FuncVoigtA)
00080 FACTORY_FUNC(FuncEMG)
00081 FACTORY_FUNC(FuncDoniachSunjic)
00082 FACTORY_FUNC(FuncPielaszekCube)
00083 FACTORY_FUNC(FuncLogNormal)
00084 FACTORY_FUNC(FuncSpline)
00085 FACTORY_FUNC(FuncPolyline)
00086
00087 FACTORY_FUNC(CustomFunction)
00088 FACTORY_FUNC(CompoundFunction)
00089 FACTORY_FUNC(SplitFunction)
00090
00091
00092 void TplateMgr::add(const char* name,
00093 const char* cs_fargs,
00094 const char* cs_dv,
00095 const char* rhs,
00096 bool linear_d, bool peak_d,
00097 Tplate::create_type create,
00098 Parser* parser)
00099 {
00100 Tplate* tp = new Tplate;
00101 tp->name = name;
00102 if (cs_fargs[0] != '\0') {
00103 tp->fargs = split_string(cs_fargs, ',');
00104 tp->defvals = split_string(cs_dv, ',');
00105 }
00106 tp->rhs = rhs;
00107 tp->linear_d = linear_d;
00108 tp->peak_d = peak_d;
00109 tp->create = create;
00110 assert(tp->fargs.size() == tp->defvals.size());
00111 tpvec_.push_back(Tplate::Ptr(tp));
00112
00113 if (parser) {
00114 Lexer lex(rhs);
00115 parser->parse_define_rhs(lex, tp);
00116 }
00117 }
00118
00119
00120 void TplateMgr::add_builtin_types(Parser* p)
00121 {
00122 tpvec_.reserve(32);
00123
00124
00125
00126 add("Constant", "a", "avgy",
00127 "a",
00128 true, false, &create_FuncConstant);
00129
00130 add("Linear", "a0,a1", "intercept,slope",
00131 "a0 + a1 * x",
00132 true, false, &create_FuncLinear);
00133
00134 add("Quadratic", "a0,a1,a2", "intercept,slope,0",
00135 "a0 + a1*x + a2*x^2",
00136 true, false, &create_FuncQuadratic);
00137
00138 add("Cubic", "a0,a1,a2,a3", "intercept,slope,0,0",
00139 "a0 + a1*x + a2*x^2 + a3*x^3",
00140 true, false, &create_FuncCubic);
00141
00142 add("Polynomial4", "a0,a1,a2,a3,a4", "intercept,slope,0,0,0",
00143 "a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4",
00144 true, false, &create_FuncPolynomial4);
00145
00146 add("Polynomial5", "a0,a1,a2,a3,a4,a5", "intercept,slope,0,0,0,0",
00147 "a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5",
00148 true, false, &create_FuncPolynomial5);
00149
00150 add("Polynomial6", "a0,a1,a2,a3,a4,a5,a6", "intercept,slope,0,0,0,0,0",
00151 "a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5 + a6*x^6",
00152 true, false, &create_FuncPolynomial6);
00153
00154 add("Gaussian", "height,center,hwhm", ",,",
00155 "height*exp(-ln(2)*((x-center)/hwhm)^2)",
00156 false, true, &create_FuncGaussian);
00157
00158 add("SplitGaussian", "height,center,hwhm1,hwhm2", ",,hwhm,hwhm",
00159 "x<center ? Gaussian(height,center,hwhm1) : Gaussian(height,center,hwhm2)",
00160 false, true, &create_FuncSplitGaussian);
00161
00162 add("Lorentzian", "height,center,hwhm", ",,",
00163 "height/(1+((x-center)/hwhm)^2)",
00164 false, true, &create_FuncLorentzian);
00165
00166 add("Pearson7", "height,center,hwhm,shape", ",,,2",
00167 "height/(1+((x-center)/hwhm)^2*(2^(1/shape)-1))^shape",
00168 false, true, &create_FuncPearson7);
00169
00170 add("SplitPearson7",
00171 "height,center,hwhm1,hwhm2,shape1,shape2", ",,hwhm,hwhm,2,2",
00172 "x < center ? Pearson7(height, center, hwhm1, shape1)"
00173 " : Pearson7(height, center, hwhm2, shape2)",
00174 false, true, &create_FuncSplitPearson7);
00175
00176 add("PseudoVoigt", "height,center,hwhm,shape", ",,,0.5",
00177 "height*((1-shape)*exp(-ln(2)*((x-center)/hwhm)^2)"
00178 "+shape/(1+((x-center)/hwhm)^2))",
00179 false, true, &create_FuncPseudoVoigt);
00180
00181 add("Voigt", "height,center,gwidth,shape", ",,hwhm*0.8,0.1",
00182 "convolution of Gaussian and Lorentzian #",
00183 false, true, &create_FuncVoigt);
00184
00185 add("VoigtA", "area,center,gwidth,shape", ",,hwhm*0.8,0.1",
00186 "convolution of Gaussian and Lorentzian #",
00187 false, true, &create_FuncVoigtA);
00188
00189 add("EMG", "a,b,c,d", "height,center,hwhm*0.8,hwhm*0.08",
00190 "a*c*(2*pi)^0.5/(2*d) * exp((b-x)/d + c^2/(2*d^2))"
00191 " * (abs(d)/d - erf((b-x)/(2^0.5*c) + c/(2^0.5*d)))",
00192 false, true, &create_FuncEMG);
00193
00194 add("DoniachSunjic", "h,a,f,e", "height,0.1,1,center",
00195 "h * cos(pi*a/2 + (1-a)*atan((x-e)/f)) / (f^2+(x-e)^2)^((1-a)/2)",
00196 false, true, &create_FuncDoniachSunjic);
00197
00198 add("PielaszekCube", "a,center,r,s", "height*0.016,,300,150",
00199 "...#",
00200 false, true, &create_FuncPielaszekCube);
00201
00202 add("LogNormal", "height,center,width,asym", ",,2*hwhm,0.1",
00203 "height*exp(-ln(2)*(ln(2.0*asym*(x-center)/width+1)/asym)^2)",
00204 false, true, &create_FuncLogNormal);
00205
00206 add("Spline", "", "",
00207 "cubic spline #",
00208 false, false, &create_FuncSpline);
00209
00210 add("Polyline", "", "",
00211 "linear interpolation #",
00212 false, false, &create_FuncPolyline);
00213
00214
00215
00216
00217 add("ExpDecay", "a,t", "0,1",
00218 "a*exp(-x/t)",
00219 false, false, &create_CustomFunction, p);
00220
00221 add("GaussianA", "area,center,hwhm", ",,",
00222 "Gaussian(area/hwhm/sqrt(pi/ln(2)), center, hwhm)",
00223 false, true, &create_CompoundFunction, p);
00224
00225 add("LogNormalA", "area,center,width,asym", ",,2*hwhm,0.1",
00226 "LogNormal(sqrt(ln(2)/pi)*(2*area/width)*exp(-asym^2/4/ln(2)), "
00227 "center, width, asym)",
00228 false, true, &create_CompoundFunction, p);
00229
00230 add("LorentzianA", "area,center,hwhm", ",,",
00231 "Lorentzian(area/hwhm/pi, center, hwhm)",
00232 false, true, &create_CompoundFunction, p);
00233 assert(tpvec_.back()->components[0].cargs.size() == 3);
00234 assert(tpvec_.back()->components[0].cargs[1].code().size() == 2);
00235
00236 add("Pearson7A", "area,center,hwhm,shape", ",,,2",
00237 "Pearson7(area/(hwhm*exp(lgamma(shape-0.5)-lgamma(shape))"
00238 "*sqrt(pi/(2^(1/shape)-1))), "
00239 "center, hwhm, shape)",
00240 false, true, &create_CompoundFunction, p);
00241
00242 add("PseudoVoigtA",
00243 "area,center,hwhm,shape",
00244 ",,,0.5",
00245 "GaussianA(area*(1-shape), center, hwhm)"
00246 " + LorentzianA(area*shape, center, hwhm)",
00247 false, true, &create_CompoundFunction, p);
00248
00249 add("SplitLorentzian", "height,center,hwhm1,hwhm2", ",,hwhm,hwhm",
00250 "x < center ? Lorentzian(height, center, hwhm1)"
00251 " : Lorentzian(height, center, hwhm2)",
00252 false, true, &create_SplitFunction, p);
00253
00254 add("SplitPseudoVoigt",
00255 "height,center,hwhm1,hwhm2,shape1,shape2", ",,hwhm,hwhm,0.5,0.5",
00256 "x < center ? PseudoVoigt(height, center, hwhm1, shape1)"
00257 " : PseudoVoigt(height, center, hwhm2, shape2)",
00258 false, true, &create_SplitFunction, p);
00259
00260 add("SplitVoigt",
00261 "height,center,hwhm1,hwhm2,shape1,shape2", ",,hwhm,hwhm,0.5,0.5",
00262 "x < center ? Voigt(height, center, hwhm1, shape1)"
00263 " : Voigt(height, center, hwhm2, shape2)",
00264 false, true, &create_SplitFunction, p);
00265 }
00266
00267 void TplateMgr::define(Tplate::Ptr tp)
00268 {
00269 if (get_tp(tp->name) != NULL)
00270 throw ExecuteError(tp->name
00271 + " is already defined. (undefine it first)");
00272 tpvec_.push_back(tp);
00273 }
00274
00275 void TplateMgr::undefine(string const &type)
00276 {
00277 vector<Tplate::Ptr>::iterator iter;
00278 for (iter = tpvec_.begin(); iter != tpvec_.end(); ++iter)
00279 if ((*iter)->name == type)
00280 break;
00281 if (iter == tpvec_.end())
00282 throw ExecuteError(type + " is not defined");
00283 if (iter->use_count() > 1)
00284 throw ExecuteError(type + " is currently used ("
00285 + S(iter->use_count() - 1) + ").");
00286 tpvec_.erase(iter);
00287 }
00288
00289 const Tplate* TplateMgr::get_tp(string const &type) const
00290 {
00291 v_foreach (Tplate::Ptr, i, tpvec_)
00292 if ((*i)->name == type)
00293 return i->get();
00294 return NULL;
00295 }
00296
00297 Tplate::Ptr TplateMgr::get_shared_tp(string const &type) const
00298 {
00299 v_foreach (Tplate::Ptr, i, tpvec_)
00300 if ((*i)->name == type)
00301 return *i;
00302 return Tplate::Ptr();
00303 }
00304
00305 vector<VMData*> reorder_args(Tplate::Ptr tp, const vector<string> &keys,
00306 const vector<VMData*> &values)
00307 {
00308 assert (keys.size() == values.size());
00309 int n = tp->fargs.size();
00310 vector<VMData*> vv(n, (VMData*) NULL);
00311 for (int i = 0; i < n; ++i) {
00312 int idx = index_of_element(keys, tp->fargs[i]);
00313 if (idx != -1)
00314 vv[i] = values[idx];
00315 }
00316 return vv;
00317 }
00318