@@ -63,80 +63,15 @@ namespace rapidxml
6363 template <class Ch > class xml_document ;
6464}// namespace rapidxml
6565
66- // Three expression evaluators have been tried; all have benefits and drawbacks.
67- // CLHEP/Evaluator: only added 21 kb to final binary size, but slowest option
68- // exprtk.hpp: added 5.3 Mb to final binary size, but 30x faster than CLHEP
69- // muparserx: adds 430 kb to binary size, and about 10x faster than CLHEP
70- //
71- // Since muparserx is what TerminalWidget uses, it was decided on 20180408 to
72- // only use muparserx.
73-
74- // 100000 evaluations of:
75- // exp(-343.6330974237 + 269.1023287277*log(x) + -83.8077567526*log(x)^2
76- // + 12.9980559362*log(x)^3 + -1.0068649823*log(x)^4 + 0.0311640084*log(x)^5)
77- // muparser x took: cpu=0.143294s, wall=0.14341s (1.4 us/eval)
78- // evaluator x took: cpu=1.10172s, wall=1.10209s (11 us/eval)
66+ /* * TODO:
67+ - Add a "fixed" geometry option - then distances in like shielding/source display are not shown/used
68+ - Add a "setback" option
69+ */
70+
7971
8072// Forward declarations
81- namespace mup
82- {
83- class Value ;
84- class ParserX ;
85- }
73+ struct FormulaWrapper ;
8674
87- struct FormulaWrapper
88- {
89- /* * Constructor that takes an equation as a string, and creates a callable
90- object to evaluate that equation.
91-
92- \param fcnstr The function to use. Ex: "exp(-1.2 + 3*lox(x) + ...)"
93- \param isMeV Only used to determine which energy value to use to test if the
94- function is valid or not; If isMeV is true, uses 0.1, else 100.
95- */
96- FormulaWrapper ( const std::string &fcnstr, const bool isMev );
97- ~FormulaWrapper ();
98-
99- float efficiency ( const float x );
100- double operator ()( const float x );
101-
102- /* * Finds the variable the user most likely intended to be the energy variable
103- for detector response functions, by looking for arguments inside
104- paranthesis.
105- Returned answer is always lower case. Spaces, tabs, and newlines are all
106- removed from input string before searching.
107- Returns "x" if it doesnt find any other candidates.
108-
109- e.x., assert(find_variable_name("exp(2.0*log(x) - 1.1*log(x)^2)") == "x");
110- assert(find_variable_name("exp(2.0*log(E) - 1.1*log(E)^2)") == "e");
111- assert(find_variable_name("3.2*exp(energy)") == "energy");
112- assert(find_variable_name("") == "x");
113- assert(find_variable_name("1-energy") == "x"); //no (...), so defaults to "x"
114- */
115- static std::string find_variable_name ( std::string eqn );
116-
117- std::mutex m_mutex;
118- std::string m_fcnstr;
119- std::string m_var_name;
120-
121- std::unique_ptr<mup::ParserX> m_parser;
122- std::unique_ptr<mup::Value> m_value;
123- };// struct FormulaWrapper
124-
125-
126- /*
127- //ToDo: Add table to database to track which DRF to use for a given detector
128- // model, or serial number,
129- struct DrfToUsePreference
130- {
131- Wt::Dbo::ptr<InterSpecUser> user;
132- long int / <DetectorPeakResponse> //Dbo::weak_ptr<DetectorPeakResponse>
133- enum MatchType{ MatchByDetectorModel, MatchBySerialNumber };
134- MatchType match_type;
135- string detector_dentifier;
136-
137- //could add info such as detector name, or whatever
138- }
139- */
14075
14176class DetectorPeakResponse
14277{
@@ -163,8 +98,6 @@ class DetectorPeakResponse
16398 std::cout << det.intrinsicEfficiency(700.0f) << std::endl; //0.219004
16499 std::cout << det.intrinsicEfficiency(800.0f) << std::endl; //0.197117
165100 */
166-
167-
168101
169102public:
170103 enum ResolutionFnctForm
@@ -317,6 +250,16 @@ class DetectorPeakResponse
317250 const float lowerEnergy,
318251 const float upperEnergy );
319252
253+ /* * Makes a callable funtion from the provided mathematical formula
254+
255+ @param fcn Mathematical formula to evaluate. Example: "exp( 1.2 + 3.2*ln(x) + -2.1*ln(x)^2 )"
256+ @param isMeV Whether units are in MeV, or keV
257+
258+ Throws exception if formula is invalid.
259+ */
260+ static std::function<float (float )> makeEfficiencyFunctionFromFormula ( const std::string &formula,
261+ const bool isMeV );
262+
320263 // fromGadrasDefinition(...): accepts the Efficiency.csv and Detector.dat
321264 // files from GADRAS to define the detector.
322265 // Note that just the Detector.dat file contains enough info to define the
@@ -819,10 +762,11 @@ class DetectorPeakResponse
819762 if ( (a.setsValue () || a.isSchema ()) && m_efficiencyFormula.size () )
820763 {
821764 const bool isMeV = (m_efficiencyEnergyUnits > 10 .0f );
765+
822766 try
823767 {
824- std::shared_ptr<FormulaWrapper> expression = std::make_shared<FormulaWrapper>(m_efficiencyFormula,isMeV);
825- m_efficiencyFcn = [expression]( float a) -> float { return expression-> efficiency (a); } ;
768+ m_efficiencyFcn
769+ = DetectorPeakResponse::makeEfficiencyFunctionFromFormula ( m_efficiencyFormula, isMeV) ;
826770 }catch ( std::exception & )
827771 {
828772 // In principle this shouldnt happen - in practice it might
0 commit comments