UNPKG

jsroot

Version:
174 lines (149 loc) 6.16 kB
import { isStr, clTF2, clTF3 } from '../core.mjs'; import * as jsroot_math from './math.mjs'; /** @summary Assign `evalPar` function for TF1 object * @private */ function proivdeEvalPar(obj, check_save) { obj.$math = jsroot_math; let _func = obj.fTitle, isformula = false, pprefix = '['; if (_func === 'gaus') _func = 'gaus(0)'; if (isStr(obj.fFormula?.fFormula)) { if (obj.fFormula.fFormula.indexOf('[](double*x,double*p)') === 0) { isformula = true; pprefix = 'p['; _func = obj.fFormula.fFormula.slice(21); } else { _func = obj.fFormula.fFormula; pprefix = '[p'; } if (obj.fFormula.fClingParameters && obj.fFormula.fParams) { obj.fFormula.fParams.forEach(pair => { const regex = new RegExp(`(\\[${pair.first}\\])`, 'g'), parvalue = obj.fFormula.fClingParameters[pair.second]; _func = _func.replace(regex, (parvalue < 0) ? `(${parvalue})` : parvalue); }); } } if (!_func) return !check_save || (obj.fSave?.length > 2); obj.formulas?.forEach(entry => { _func = _func.replaceAll(entry.fName, entry.fTitle); }); _func = _func.replace(/\b(TMath::SinH)\b/g, 'Math.sinh') .replace(/\b(TMath::CosH)\b/g, 'Math.cosh') .replace(/\b(TMath::TanH)\b/g, 'Math.tanh') .replace(/\b(TMath::ASinH)\b/g, 'Math.asinh') .replace(/\b(TMath::ACosH)\b/g, 'Math.acosh') .replace(/\b(TMath::ATanH)\b/g, 'Math.atanh') .replace(/\b(TMath::ASin)\b/g, 'Math.asin') .replace(/\b(TMath::ACos)\b/g, 'Math.acos') .replace(/\b(TMath::Atan)\b/g, 'Math.atan') .replace(/\b(TMath::ATan2)\b/g, 'Math.atan2') .replace(/\b(sin|SIN|TMath::Sin)\b/g, 'Math.sin') .replace(/\b(cos|COS|TMath::Cos)\b/g, 'Math.cos') .replace(/\b(tan|TAN|TMath::Tan)\b/g, 'Math.tan') .replace(/\b(exp|EXP|TMath::Exp)\b/g, 'Math.exp') .replace(/\b(log|LOG|TMath::Log)\b/g, 'Math.log') .replace(/\b(log10|LOG10|TMath::Log10)\b/g, 'Math.log10') .replace(/\b(pow|POW|TMath::Power)\b/g, 'Math.pow') .replace(/\b(pi|PI)\b/g, 'Math.PI') .replace(/\b(abs|ABS|TMath::Abs)\b/g, 'Math.abs') .replace(/\bsqrt\(/g, 'Math.sqrt(') .replace(/\bxygaus\(/g, 'this.$math.gausxy(this, x, y, ') .replace(/\bgaus\(/g, 'this.$math.gaus(this, x, ') .replace(/\bgausn\(/g, 'this.$math.gausn(this, x, ') .replace(/\bexpo\(/g, 'this.$math.expo(this, x, ') .replace(/\blandau\(/g, 'this.$math.landau(this, x, ') .replace(/\blandaun\(/g, 'this.$math.landaun(this, x, ') .replace(/\b(TMath::|ROOT::Math::)/g, 'this.$math.'); if (_func.match(/^pol[0-9]$/) && (parseInt(_func[3]) === obj.fNpar - 1)) { _func = '[0]'; for (let k = 1; k < obj.fNpar; ++k) _func += ` + [${k}] * ` + ((k === 1) ? 'x' : `Math.pow(x,${k})`); } if (_func.match(/^chebyshev[0-9]$/) && (parseInt(_func[9]) === obj.fNpar - 1)) { _func = `this.$math.ChebyshevN(${obj.fNpar - 1}, x, `; for (let k = 0; k < obj.fNpar; ++k) _func += (k === 0 ? '[' : ', ') + `[${k}]`; _func += '])'; } for (let i = 0; i < obj.fNpar; ++i) _func = _func.replaceAll(pprefix + i + ']', `(${obj.GetParValue(i)})`); for (let n = 2; n < 10; ++n) _func = _func.replaceAll(`x^${n}`, `Math.pow(x,${n})`); if (isformula) { _func = _func.replace(/x\[0\]/g, 'x'); if (obj._typename === clTF3) { _func = _func.replace(/x\[1\]/g, 'y'); _func = _func.replace(/x\[2\]/g, 'z'); obj.evalPar = new Function('x', 'y', 'z', _func).bind(obj); } else if (obj._typename === clTF2) { _func = _func.replace(/x\[1\]/g, 'y'); obj.evalPar = new Function('x', 'y', _func).bind(obj); } else obj.evalPar = new Function('x', _func).bind(obj); } else if (obj._typename === clTF3) obj.evalPar = new Function('x', 'y', 'z', 'return ' + _func).bind(obj); else if (obj._typename === clTF2) obj.evalPar = new Function('x', 'y', 'return ' + _func).bind(obj); else obj.evalPar = new Function('x', 'return ' + _func).bind(obj); return true; } /** @summary Get interpolation in saved buffer * @desc Several checks must be done before function can be used * @private */ function _getTF1Save(func, x) { const np = func.fSave.length - 3, xmin = func.fSave[np + 1], xmax = func.fSave[np + 2], dx = (xmax - xmin) / np; if (x < xmin) return func.fSave[0]; if (x > xmax) return func.fSave[np]; const bin = Math.min(np - 1, Math.floor((x - xmin) / dx)); let xlow = xmin + bin * dx, xup = xlow + dx, ylow = func.fSave[bin], yup = func.fSave[bin + 1]; if (!Number.isFinite(ylow) && (bin < np - 1)) { xlow += dx; xup += dx; ylow = yup; yup = func.fSave[bin + 2]; } else if (!Number.isFinite(yup) && (bin > 0)) { xup -= dx; xlow -= dx; yup = ylow; ylow = func.fSave[bin - 1]; } return ((xup * ylow - xlow * yup) + x * (yup - ylow)) / dx; } /** @summary Provide TF1 value * @desc First try evaluate, if not possible - check saved buffer * @private */ function getTF1Value(func, x, skip_eval = undefined) { if (!func) return 0; let iserr = false; if (!skip_eval && !func.evalPar) { try { if (!proivdeEvalPar(func)) iserr = true; } catch { iserr = true; } } if (func.evalPar && !iserr) { try { return func.evalPar(x); } catch { /* eslint-disable-next-line no-useless-assignment */ iserr = true; } } const np = func.fSave.length - 3; return (np < 2) || (func.fSave[np + 1] === func.fSave[np + 2]) ? 0 : _getTF1Save(func, x); } export { proivdeEvalPar, getTF1Value, _getTF1Save };