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
28using namespace std;
29
30namespace REST_Units {
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
54map<string, pair<int, double>> __ListOfRESTUnits; // name, {type, scale}
55} // namespace REST_Units
56#define REST_UnitsAdd_Caller
57
58#include "TRestSystemOfUnits.h"
59
82namespace REST_Units {
83
93bool IsUnit(string unitsStr) { return !TRestSystemOfUnits(unitsStr).IsZombie(); }
94
98bool IsBasicUnit(string unitsStr) { return (__ListOfRESTUnits.count(unitsStr) == 1); }
99
104double GetScaleToStandardUnit(string unitsdef) { return 1 * TRestSystemOfUnits(unitsdef); }
105
110string GetStandardUnitDefinition(string unitsdef) { return units(unitsdef).ToStandardDefinition(); }
111
122string 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
143string 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
163Double_t GetDblValueInString(string in) {
164 string units = FindRESTUnitsInString(in);
165 double val = StringToDouble(RemoveUnitsFromString(in));
166 return ConvertValueToRESTUnits(val, units);
167}
168
174Double_t GetValueInRESTUnits(string in) { return GetDblValueInString(in); }
175
181Double_t GetDblValueInRESTUnits(string in) { return GetDblValueInString(in); }
182
188TVector2 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
201TVector2 Get2DVectorInRESTUnits(string in) { return Get2DVectorValueInString(in); }
202
208TVector3 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
222TVector3 Get3DVectorInRESTUnits(string in) { return Get3DVectorValueInString(in); }
223
239Double_t ConvertValueToRESTUnits(Double_t value, string unitsStr) {
240 return value / TRestSystemOfUnits((string)unitsStr);
241}
242
246Double_t ConvertRESTUnitsValueToCustomUnits(Double_t value, string unitsStr) {
247 return value * TRestSystemOfUnits((string)unitsStr);
248}
249
255double _AddUnit(string name, int type, double scale) {
256 __ListOfRESTUnits[name] = {type, scale};
257 return scale;
258}
259
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
363int TRestSystemOfUnits::GetUnitType(string singleUnit) {
364 if (IsBasicUnit(singleUnit)) {
365 return __ListOfRESTUnits[singleUnit].first;
366 }
367 return -1;
368}
369
370double TRestSystemOfUnits::GetUnitScale(string singleUnit) {
371 if (IsBasicUnit(singleUnit)) {
372 return __ListOfRESTUnits[singleUnit].second;
373 }
374 return 1;
375}
376
377string 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
double GetUnitScale(std::string singleUnit)
Get the scale of the unit to convert to the REST standard units.
TRestSystemOfUnits(std::string unitsStr)
Constructor from a unit std::string.
bool IsZombie() const
Whether this unit is zombie(invalid)
int GetUnitType(std::string singleUnit)
Get the type of the units.
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.