REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestSystemOfUnits.cxx
1 /*************************************************************************
2  * This file is part of the REST software framework. *
3  * *
4  * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) *
5  * For more information see http://gifna.unizar.es/trex *
6  * *
7  * REST is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * REST is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have a copy of the GNU General Public License along with *
18  * REST in $REST_PATH/LICENSE. *
19  * If not, see http://www.gnu.org/licenses/. *
20  * For the list of contributors see $REST_PATH/CREDITS. *
21  *************************************************************************/
22 
23 #include <iostream>
24 #include <limits>
25 
26 #include "TRestStringHelper.h"
27 
28 using namespace std;
29 
30 namespace REST_Units {
31 struct UnitsStruct {
32  UnitsStruct() {
33  name = "";
34  type = -1;
35  scale = 1;
36  }
37  UnitsStruct(string _name, int _type, double _scale) {
38  name = _name;
39  type = _type;
40  scale = _scale;
41  }
42 
43  string name = "";
44  int type = -1;
45  double scale = 1;
46 
47  bool operator>(const UnitsStruct& compare) const { return name > compare.name; }
48 
49  bool operator<(const UnitsStruct& compare) const { return name < compare.name; }
50 
51  bool operator==(const UnitsStruct& compare) const { return name == compare.name; }
52 };
53 
54 map<string, pair<int, double>> __ListOfRESTUnits; // name, {type, scale}
55 } // namespace REST_Units
56 #define REST_UnitsAdd_Caller
57 
58 #include "TRestSystemOfUnits.h"
59 
82 namespace REST_Units {
83 
93 bool IsUnit(string unitsStr) { return !TRestSystemOfUnits(unitsStr).IsZombie(); }
94 
98 bool IsBasicUnit(string unitsStr) { return (__ListOfRESTUnits.count(unitsStr) == 1); }
99 
104 double GetScaleToStandardUnit(string unitsdef) { return 1 * TRestSystemOfUnits(unitsdef); }
105 
110 string GetStandardUnitDefinition(string unitsdef) { return units(unitsdef).ToStandardDefinition(); }
111 
122 string FindRESTUnitsInString(string s) {
123  size_t l = RemoveUnitsFromString(s).length();
124  string unitDef = s.substr(l, -1);
125 
126  if (IsUnit(unitDef)) {
127  return unitDef;
128  }
129  return "";
130 }
131 
143 string RemoveUnitsFromString(string s) {
144  string valstr1 = s.substr(0, s.find_first_not_of("1234567890(),.-eE/: "));
145 
146  if (valstr1.size() == 0) {
147  return "";
148  }
149 
150  // if e turns out to be the last character, we shall also strip it
151  if (valstr1[valstr1.size() - 1] == 'e' || valstr1[valstr1.size() - 1] == 'E') {
152  return valstr1.substr(0, valstr1.size() - 1);
153  }
154 
155  return valstr1;
156 }
157 
163 Double_t GetDblValueInString(string in) {
164  string units = FindRESTUnitsInString(in);
165  double val = StringToDouble(RemoveUnitsFromString(in));
166  return ConvertValueToRESTUnits(val, units);
167 }
168 
174 Double_t GetValueInRESTUnits(string in) { return GetDblValueInString(in); }
175 
181 Double_t GetDblValueInRESTUnits(string in) { return GetDblValueInString(in); }
182 
188 TVector2 Get2DVectorValueInString(string in) {
189  string unit = FindRESTUnitsInString(in);
190  TVector2 value = StringTo2DVector(RemoveUnitsFromString(in));
191  Double_t valueX = REST_Units::ConvertValueToRESTUnits(value.X(), unit);
192  Double_t valueY = REST_Units::ConvertValueToRESTUnits(value.Y(), unit);
193  return TVector2(valueX, valueY);
194 }
195 
201 TVector2 Get2DVectorInRESTUnits(string in) { return Get2DVectorValueInString(in); }
202 
208 TVector3 Get3DVectorValueInString(string in) {
209  string unit = FindRESTUnitsInString(in);
210  TVector3 value = StringTo3DVector(RemoveUnitsFromString(in));
211  Double_t valueX = REST_Units::ConvertValueToRESTUnits(value.X(), unit);
212  Double_t valueY = REST_Units::ConvertValueToRESTUnits(value.Y(), unit);
213  Double_t valueZ = REST_Units::ConvertValueToRESTUnits(value.Z(), unit);
214  return TVector3(valueX, valueY, valueZ);
215 }
216 
222 TVector3 Get3DVectorInRESTUnits(string in) { return Get3DVectorValueInString(in); }
223 
239 Double_t ConvertValueToRESTUnits(Double_t value, string unitsStr) {
240  return value / TRestSystemOfUnits((string)unitsStr);
241 }
242 
246 Double_t ConvertRESTUnitsValueToCustomUnits(Double_t value, string unitsStr) {
247  return value * TRestSystemOfUnits((string)unitsStr);
248 }
249 
255 double _AddUnit(string name, int type, double scale) {
256  __ListOfRESTUnits[name] = {type, scale};
257  return scale;
258 }
259 
280 TRestSystemOfUnits::TRestSystemOfUnits(string unitsStr) {
281  unitsStr = Trim(unitsStr);
282 
283  // We skip for the moment parameters/fields that contain elements {,,,}.
284  if (unitsStr.find("{") != string::npos || unitsStr.find("}") != string::npos) {
285  fZombie = true;
286  return;
287  }
288 
289  if (unitsStr == "") {
290  fZombie = true;
291  return;
292  }
293  fScaleCombined = 1;
294 
295  for (size_t pos = 0; pos >= 0 && pos < unitsStr.size();) {
296  if (isalpha(unitsStr[pos])) {
297  size_t pos1 = pos;
298  while (pos < unitsStr.size() && isalpha(unitsStr[pos])) {
299  pos++;
300  }
301  size_t pos2 = pos;
302  string singleunit = unitsStr.substr(pos1, pos2 - pos1);
303 
304  if (IsBasicUnit(singleunit)) {
305  int orderprefix = 1;
306  if (pos1 > 0) {
307  if (unitsStr[pos1 - 1] == '/') {
308  orderprefix = -1;
309  } else if (unitsStr[pos1 - 1] == '-' || unitsStr[pos1 - 1] == '*') {
310  } else {
311  RESTWarning << "illegal unit combiner \"" << unitsStr[pos1 - 1] << "\"" << RESTendl;
312  }
313  }
314 
315  double ordernum = 1;
316  if (pos2 < unitsStr.size() - 1) {
317  if (unitsStr[pos2] == '^') {
318  int pos3 = unitsStr.find_first_not_of("-0123456789.", pos2 + 1);
319  string orderstr = unitsStr.substr(pos2 + 1, pos3 - pos2 - 1);
320  ordernum = StringToDouble(orderstr);
321  pos = pos3;
322  }
323  }
324 
325  int _type = GetUnitType(singleunit);
326  double _scale = GetUnitScale(singleunit);
327  double _order = ordernum * orderprefix;
328 
329  fComponents.push_back(_type);
330  fComponentOrder.push_back(_order);
331 
332  fScaleCombined *= pow(_scale, _order);
333  } else {
334  fZombie = true;
335  return;
336  // warning << "not a unit \"" << singleunit << "\"" << endl;
337  }
338 
339  } else {
340  if (pos == unitsStr.size() - 1) {
341  RESTWarning << "Last character inside \"" << unitsStr << "\" \"" << unitsStr[pos]
342  << "\" unrecognized in unit definition!" << RESTendl;
343 
344  std::string lastChar = unitsStr.substr(pos, 1);
345 
346  if (isANumber(lastChar)) {
347  std::string tmpStr = unitsStr;
348  tmpStr.insert(pos, "^");
349  RESTWarning << "Perhaps you meant: " << tmpStr << RESTendl;
350  }
351  }
352 
353  pos++;
354  }
355  }
356  if (fComponents.size() == 0) {
357  fZombie = true;
358  } else {
359  fZombie = false;
360  }
361 }
362 
363 int TRestSystemOfUnits::GetUnitType(string singleUnit) {
364  if (IsBasicUnit(singleUnit)) {
365  return __ListOfRESTUnits[singleUnit].first;
366  }
367  return -1;
368 }
369 
370 double TRestSystemOfUnits::GetUnitScale(string singleUnit) {
371  if (IsBasicUnit(singleUnit)) {
372  return __ListOfRESTUnits[singleUnit].second;
373  }
374  return 1;
375 }
376 
377 string TRestSystemOfUnits::ToStandardDefinition() {
378  string result = "";
379  for (unsigned int i = 0; i < fComponents.size(); i++) {
380  if (fComponentOrder[i] < 0) {
381  result += "/";
382  } else if (i > 0) {
383  result += "-";
384  }
385 
386  for (auto iter : __ListOfRESTUnits) {
387  if (iter.second.first == fComponents[i] && iter.second.second == 1) {
388  result += iter.first;
389  }
390  }
391 
392  if (abs(fComponentOrder[i]) != 1) {
393  result += "^" + ToString(abs(fComponentOrder[i]));
394  }
395  }
396 
397  return result;
398 }
399 
400 } // namespace REST_Units
bool IsZombie() const
Whether this unit is zombie(invalid)
Double_t StringToDouble(std::string in)
Gets a double from a string.
TVector2 StringTo2DVector(std::string in)
Gets a 2D-vector from a string.
std::string Trim(std::string s, const char *t=" \t\n\r\f\v")
Removes all white spaces found at the beginning and the end of the string (https://stackoverflow....
Int_t isANumber(std::string in)
Returns 1 only if a valid number is found in the string in. If not it returns 0.
TVector3 StringTo3DVector(std::string in)
Gets a 3D-vector from a string. Format should be : (X,Y,Z).
This namespace defines the unit conversion for different units which are understood by REST.
bool IsBasicUnit(std::string in)
Checks if the string is a REST basic unit.
Double_t GetValueInRESTUnits(std::string in)
It scales a physics measurement with its units into a REST default units value.
TVector3 Get3DVectorInRESTUnits(std::string in)
It scales a physics measurement with its units into a REST default units value.
Double_t GetDblValueInString(std::string in)
It scales a physics measurement with its units into a REST default units value.
double GetScaleToStandardUnit(std::string unitsdef)
Get the scale to REST standard unit. scale (unitsdef) = 1 (standard unit)
Double_t ConvertRESTUnitsValueToCustomUnits(Double_t value, std::string unitsStr)
Convert value with REST units into the given custom units.
std::string FindRESTUnitsInString(std::string InString)
Find and return the units definition in a string.
Double_t GetDblValueInRESTUnits(std::string in)
It scales a physics measurement with its units into a REST default units value.
std::string GetStandardUnitDefinition(std::string unitsdef)
Get standard form of this unit definition.
bool IsUnit(std::string in)
Checks if the string is a REST supported unit.
TVector2 Get2DVectorInRESTUnits(std::string in)
It scales a physics measurement with its units into a REST default units value.
Double_t ConvertValueToRESTUnits(Double_t value, std::string unitsStr)
Convert value into REST units.
TVector3 Get3DVectorValueInString(std::string in)
It scales a physics measurement with its units into a REST default units value.
TVector2 Get2DVectorValueInString(std::string in)
It scales a physics measurement with its units into a REST default units value.
std::string RemoveUnitsFromString(std::string s)
It should remove all units found inside the input string.
double _AddUnit(std::string name, int type, double scale)
Add a unit with given name, type and scale.