source: trunk/source/persistency/ascii/src/G4tgrUtils.cc @ 1347

Last change on this file since 1347 was 1347, checked in by garnier, 14 years ago

geant4 tag 9.4

File size: 20.2 KB
Line 
1//
2// ********************************************************************
3// * License and Disclaimer                                           *
4// *                                                                  *
5// * The  Geant4 software  is  copyright of the Copyright Holders  of *
6// * the Geant4 Collaboration.  It is provided  under  the terms  and *
7// * conditions of the Geant4 Software License,  included in the file *
8// * LICENSE and available at  http://cern.ch/geant4/license .  These *
9// * include a list of copyright holders.                             *
10// *                                                                  *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work  make  any representation or  warranty, express or implied, *
14// * regarding  this  software system or assume any liability for its *
15// * use.  Please see the license in the file  LICENSE  and URL above *
16// * for the full disclaimer and the limitation of liability.         *
17// *                                                                  *
18// * This  code  implementation is the result of  the  scientific and *
19// * technical work of the GEANT4 collaboration.                      *
20// * By using,  copying,  modifying or  distributing the software (or *
21// * any work based  on the software)  you  agree  to acknowledge its *
22// * use  in  resulting  scientific  publications,  and indicate your *
23// * acceptance of all terms of the Geant4 Software license.          *
24// ********************************************************************
25//
26//
27//
28// class G4tgrUtils
29
30// History:
31// - Created.                                 P.Arce, CIEMAT (November 2007)
32// -------------------------------------------------------------------------
33
34#include "geomdefs.hh"
35
36#include <iomanip>
37#include <set>
38
39#include "G4tgrUtils.hh"
40#include "G4tgrParameterMgr.hh"
41#include "G4tgrMessenger.hh"
42#include "G4UnitsTable.hh"
43#include "G4GeometryTolerance.hh"
44#include "G4UIcommand.hh"
45
46
47G4tgrEvaluator* G4tgrUtils::theEvaluator = new G4tgrEvaluator;
48
49
50//-------------------------------------------------------------
51G4tgrUtils::G4tgrUtils()
52{
53}
54
55
56//-------------------------------------------------------------
57G4tgrUtils::~G4tgrUtils()
58{
59}
60
61
62//-------------------------------------------------------------
63G4bool G4tgrUtils::IsSeparator( const char ch)
64{
65  char nonCharacters[7] = {"()+-*/"};
66  for( size_t ii = 0; ii < 6; ii++ )
67  {
68    if( ch == nonCharacters[ii] )
69    {
70      return true;
71    }
72  }
73  return false;
74}
75
76
77//-------------------------------------------------------------
78G4bool G4tgrUtils::IsNumber( const G4String& str)
79{
80  G4int isnum = true;
81  G4int numE = 0;
82  for(size_t ii=0; ii<str.length(); ii++)
83  {
84    if(!isdigit(str[ii]) && (str[ii]!='.') && (str[ii]!='-') && (str[ii]!='+'))
85    {
86      //--- check for E(xponential)
87      if(str[ii] == 'E' || str[ii] == 'e' )
88      {
89        if( ii == 0 )  { return 0; }
90        if(numE != 0 || ii == str.length()-1)
91        {
92          isnum = false;
93          break;
94        }
95        numE++;
96      }
97      else
98      {
99        isnum = false; 
100        break;
101      }
102    }
103  }
104  return isnum;
105}
106
107
108//-------------------------------------------------------------
109G4bool G4tgrUtils::IsInteger( const G4double val, const G4double precision )
110{
111  if( G4int(val) / val - 1 > precision )
112  { 
113    return 0;
114  }
115  else
116  { 
117    return 1;
118  }
119}
120
121
122//-------------------------------------------------------------
123void G4tgrUtils::Dump3v( const G4ThreeVector& vec, const char* msg) 
124{
125  G4cout << msg << std::setprecision(8)
126         << vec << std::setprecision(6) << G4endl;
127}
128
129
130//-------------------------------------------------------------
131void G4tgrUtils::Dumprm( const G4RotationMatrix& rm, const char* msg)
132{
133  G4cout << msg << G4endl
134       << " xx=" << rm.xx() << " yx=" << rm.yx() << " zx=" << rm.zx() << G4endl
135       << " xy=" << rm.xy() << " yy=" << rm.yy() << " zy=" << rm.zy() << G4endl
136       << " xz=" << rm.xz() << " yz=" << rm.yz() << " zz=" << rm.zz() << G4endl;
137}
138
139
140//-------------------------------------------------------------
141void G4tgrUtils::DumpVS( const std::vector<G4String>& wl,
142                         const char* msg, std::ostream& outs ) 
143{
144  outs << msg << G4endl;
145  std::vector<G4String>::const_iterator ite;
146  for( ite = wl.begin(); ite != wl.end(); ite++ )
147  {
148    outs << *ite << " ";
149  }
150  outs << G4endl;
151}
152
153
154//-------------------------------------------------------------
155void G4tgrUtils::DumpVS( const std::vector<G4String>& wl , const char* msg) 
156{
157  DumpVS( wl, msg, G4cout);
158}
159
160
161//-------------------------------------------------------------
162G4String G4tgrUtils::SubColon( const G4String& str ) 
163{
164  if( str.find(':') != 0 )
165  {
166    G4String ErrMessage = "Trying to subtract leading colon from a word\n"
167                        + G4String("that has no leading colon: ") + str;
168    G4Exception("G4tgrUtils::SubColon()", "ParseError",
169                FatalException, ErrMessage);
170  }
171  G4String strt = str.substr(1,str.size()-1);
172  return strt;
173}
174
175
176//-------------------------------------------------------------
177G4String G4tgrUtils::GetString( const G4String& str ) 
178{
179  //----------- first check if it is parameter
180  const char* cstr = str.c_str();
181  if( cstr[0] == '$' )
182  {
183#ifdef G4VERBOSE
184    if( G4tgrMessenger::GetVerboseLevel() >= 3 )
185    {
186      G4cout << " G4tgrUtils::GetString() - Substitute parameter: "
187             << G4tgrParameterMgr::GetInstance()
188                ->FindParameter( str.substr(1,str.size())) << G4endl;
189    }
190#endif
191    return G4tgrParameterMgr::GetInstance()
192           ->FindParameter( str.substr(1,str.size()) );
193  }
194  else
195  {
196    return str;
197  }
198}
199
200
201//-------------------------------------------------------------
202G4double G4tgrUtils::GetDouble( const G4String& str, G4double unitval ) 
203{
204#ifdef G4VERBOSE
205  if( G4tgrMessenger::GetVerboseLevel() >= 3 )
206  {
207    G4cout << "G4tgrUtils::GetDouble() - Processing: "
208           << str << " default unit " << unitval << G4endl;
209  }
210#endif
211  if( str == "DBL_MAX" ) {
212    return DBL_MAX;
213  }else if( str == "DBL_MIN" ) {
214    return DBL_MIN;
215  }else if( str == "FLT_MAX" ) {
216    return FLT_MAX;
217  }else if( str == "FLT_MIN" ) {
218    return FLT_MIN;
219  }else if( str == "INT_MAX" ) {
220    return INT_MAX;
221  }else if( str == "INT_MIN" ) {
222    return INT_MIN;
223  }
224  //----- Look for arithmetic symbols, (, )
225  const char* cstr = str.c_str();
226  std::set<G4int> separators;
227  separators.insert(-1);
228  G4int strlen = G4int(str.length());
229  for(G4int ii=0; ii<strlen; ii++)
230  {
231    char cs = cstr[ii];
232    if( cs == '*' || cs == '/' || cs == '(' || cs == ')' )
233    {     
234      separators.insert(ii);
235    }
236    else if( cs == '+' || cs == '-' )
237    {
238      // Check if it is not an exponential
239      //
240      if( (ii < 2)
241       || ( (cstr[ii-1] != 'E') && (cstr[ii-1] != 'e') )
242       || !IsNumber(cstr[ii-2]) )
243      { 
244        separators.insert(ii);
245      } 
246    } 
247  }
248  separators.insert(strlen);
249  std::string strnew; // build a new word with Parameters
250                      // and units substituted by values
251  //----- Process words, defined as characters between two separators
252  G4int nUnits = 0;
253  std::set<G4int>::const_iterator site, site2;
254  site = separators.begin();
255  site2 = site; site2++;
256  for( ; site2 != separators.end(); site++,site2++)
257  {
258#ifdef G4VERBOSE
259    if( G4tgrMessenger::GetVerboseLevel() >= 3 )
260    {
261      G4cout << "   Loop to find word between " << *site
262             << " " << *site2 << G4endl;
263    }
264#endif
265
266    if( *site != -1 )  { strnew += str.substr(*site,1); }
267
268    G4int wlen = (*site2)-(*site)-1;   //do not count contiguous separators
269    std::string word;
270    if(wlen != 0)
271    {
272      word = str.substr((*site)+1,(*site2)-(*site)-1);
273    }
274    else
275    {
276      //--- Check combination of separators
277      //--- Check number of parentheses
278      continue;
279    }
280     
281#ifdef G4VERBOSE
282    if( G4tgrMessenger::GetVerboseLevel() >= 3 )
283    {
284      G4cout << "   Processing word: " << word << G4endl;
285    }
286#endif
287    //----------- first check if it is parameter
288    const char* cword = word.c_str();
289    if( cword[0] == '$' )
290    {
291      G4String parstr = G4tgrParameterMgr::GetInstance()
292                      ->FindParameter( word.substr(1,word.size()));
293      if( parstr.substr(0,1) == "-" )
294      {
295        strnew += "(";
296      }
297      strnew += parstr;
298      if( parstr.substr(0,1) == "-" )
299      {
300        strnew += ")";
301      }
302#ifdef G4VERBOSE
303      if( G4tgrMessenger::GetVerboseLevel() >= 3 )
304      {
305        G4cout << " G4tgrutils::GetDouble() - Param found: "
306               << word << " in string " << str
307               << " , substituted by " << parstr << G4endl;
308      }
309#endif
310    }
311    else
312    {
313      //----- Get if it is a number
314      if( IsNumber(word) )
315      {
316        //--- left separator cannot be ')'
317        if( (*site != -1) && (cstr[*site] == ')') )
318        {
319          G4String ErrMessage = "There cannot be a ')' before a number: "
320                              + word + " in string: " + str;
321          G4Exception("G4tgrUtils::GetDouble()", "ParseError",
322                      FatalException, ErrMessage);
323        }
324        //--- right separator cannot be '('
325        if( (*site2 != strlen) && (cstr[*site2] == '(') )
326        {
327          G4String ErrMessage = "There cannot be a '(' after a number: "
328                              + word + " in string: " + str;
329          G4Exception("G4tgrUtils::GetDouble()", "ParseError",
330                      FatalException, ErrMessage);
331        }
332        strnew += word;
333       
334        //------ If it is an string, check if it is a unit
335      }
336      else
337      {
338        //--- First character cannot be a digit
339        if( isdigit(word[0]) )
340        {
341          G4String ErrMessage = "String words cannot start with a digit: "
342                              + word + " in string: " + str;
343          G4Exception("G4tgrUtils::GetDouble()", "ParseError",
344                      FatalException, ErrMessage );
345        }
346       
347        //----- Check if it is a function
348        G4bool bWordOK = false;     
349        if( G4tgrUtils::IsFunction( word ) )
350        {
351          //--- It must be followed by '('
352          if( (*site2 == strlen) || (cstr[*site2] != '(') )
353          {
354            G4String ErrMessage = "There must be a '(' after a function: "
355                                + word + " in string: " + str;
356            G4Exception("G4tgrUtils::GetDouble()", "ParseError",
357                        FatalException, ErrMessage );
358          }
359          strnew += word;
360          bWordOK = true;     
361        //----- Check if it is a unit     
362        }
363        else if( !G4tgrUtils::IsNumber( word ) )
364        {
365          //--- It must be preceded by a *
366          if( (*site == -1)
367           || ( (cstr[*site] != '*') && (cstr[*site] != '/') ) )
368          {
369            G4String ErrMess = "There must be a '*' before a unit definition: "
370                               + word + " in string " + str;
371            G4Exception("G4tgrUtils::GetDouble()", "ParseError",
372                        FatalException, ErrMess );
373          }
374          //--- check that it is indeed a CLHEP unit
375          if( G4UnitDefinition::GetValueOf(word) != 0. )
376          {
377            bWordOK = true;     
378            nUnits++;
379            if( nUnits > 1 )
380            {
381              // G4String ErrMess = "There cannot be two unit definitions: "
382              //                  + word + " in string " + str;
383              // G4Exception("G4tgrUtils::GetDouble()", "ParseError",
384              //             FatalException, ErrMess );
385            }
386            strnew += G4UIcommand::ConvertToString( G4UnitDefinition::GetValueOf(word) );
387          }
388        }
389        if( !bWordOK )
390        {
391          G4String ErrMess = "String word is not a parameter, nor a unit\n";
392                           + G4String("definition nor a function: ") + word
393                           + G4String(" in string: ") + str;
394          G4Exception("G4tgrUtils::GetDouble()", "ParseError",
395                      FatalException, ErrMess );
396        }
397      }
398    }
399  }
400
401  G4double val = theEvaluator->evaluate( strnew.c_str() );
402  if (theEvaluator->status() != HepTool::Evaluator::OK)
403  {
404    theEvaluator->print_error(theEvaluator->status());
405    G4String ErrMessage = "Evaluator error: " + strnew;
406    G4Exception("G4tgrUtils::GetDouble()", "ParseError",
407                FatalException, ErrMessage );
408  }
409 
410  if( nUnits == 0 )  { val *= unitval; }
411
412#ifdef G4VERBOSE
413  if( G4tgrMessenger::GetVerboseLevel() >= 3 )
414  {
415    G4cout << " G4tgrUtils::GetDouble() - RESULT= " << val << G4endl
416           << "   from string: " << str << " converted to: " << strnew
417           << " with unit val: " << unitval << G4endl;
418  }
419#endif
420
421  return val;
422}
423
424
425//-------------------------------------------------------------
426G4int G4tgrUtils::GetInt( const G4String& str ) 
427{
428  //----- Convert it to a number (it can be a parameter)
429  G4double val = GetDouble(str);
430
431  //----- Check it is an integer
432  if( !IsInteger(val) )
433  {
434    G4String ErrMessage = G4String("Trying to get the integer from a number")
435                        + G4String(" which is not an integer ") + str;
436    G4Exception("G4tgrUtils::GetInt()", "ParseError",
437                FatalException, ErrMessage );
438  }
439  return G4int( val );
440}
441
442
443//-------------------------------------------------------------
444G4bool G4tgrUtils::GetBool( const G4String& str ) 
445{
446  G4bool val = false;
447 
448  //----------- first check that it is a not number
449  if( (str == "ON") || (str == "TRUE")  )
450  {
451    val = true;
452  }
453  else if( (str == "OFF") || (str == "FALSE") )
454  {
455    val = false;
456  }
457  else
458  {
459    G4String ErrMessage = G4String("Trying to get a float from a string")
460                        + G4String(" which is not 'ON'/'OFF'/'TRUE'/'FALSE' ")
461                        + str;
462    G4Exception("G4tgrUtils::GetBool()", "ParseError",
463                FatalException, ErrMessage );
464  }
465
466  return val;
467}
468
469
470//-------------------------------------------------------------
471void G4tgrUtils::CheckWLsize( const std::vector<G4String>& wl,
472                              unsigned int nWcheck, WLSIZEtype st,
473                              const G4String& methodName )
474{
475
476  G4String outStr = methodName + G4String(".  Line read with number of words ");
477  unsigned int wlsize = wl.size();
478
479  G4bool isOK = CheckListSize( wlsize, nWcheck, st, outStr );
480
481  if( !isOK )
482  { 
483    G4String chartmp = G4UIcommand::ConvertToString( G4int(nWcheck) );
484    outStr += chartmp + G4String(" words");
485    DumpVS( wl, outStr.c_str() );
486    G4String ErrMessage = " NUMBER OF WORDS: "
487                        + G4UIcommand::ConvertToString(G4int(wlsize));
488    G4Exception("G4tgrUtils::CheckWLsize()", "ParseError",
489                FatalException, ErrMessage);
490  }
491}
492
493//-------------------------------------------------------------
494G4bool G4tgrUtils::CheckListSize( unsigned int nWreal, unsigned int nWcheck,
495                                  WLSIZEtype st, G4String& outStr )
496{
497  G4bool isOK = true;
498  switch (st)
499  {
500  case WLSIZE_EQ:
501    if( nWreal != nWcheck )
502    {
503      isOK = false;
504      outStr += G4String("not equal than ");
505    }
506    break;
507  case WLSIZE_NE:
508    if( nWreal == nWcheck )
509    {
510      isOK = false;
511      outStr += G4String("equal than ");
512    }
513    break;
514  case WLSIZE_LE:
515    if( nWreal > nWcheck )
516    {
517      isOK = false;
518      outStr += G4String("greater than ");
519    }
520    break;
521  case WLSIZE_LT:
522    if( nWreal >= nWcheck )
523    {
524      isOK = false;
525      outStr += G4String("greater or equal than ");
526    }
527    break;
528  case WLSIZE_GE:
529    if( nWreal < nWcheck )
530    {
531      isOK = false;
532      outStr += G4String("less than ");
533    }
534    break;
535  case WLSIZE_GT:
536    if( nWreal <= nWcheck )
537    {
538      isOK = false;
539      outStr += G4String("less or equal than ");
540    }
541    break;
542  default:
543    G4cerr << " ERROR!! - G4tgrUtils::CheckListSize()" << G4endl
544           << "           Type of WLSIZE type not found " << st << G4endl;
545    break;
546  }
547
548  return isOK;
549}
550
551
552//-------------------------------------------------------------
553G4bool G4tgrUtils::IsFunction( const G4String& word ) 
554{
555  if(    word == "sin"
556      || word == "cos"
557      || word == "tan"
558      || word == "asin"
559      || word == "acos"
560      || word == "atan"
561      || word == "atan2"
562      || word == "sinh"
563      || word == "cosh"
564      || word == "tanh"
565      || word == "asinh"
566      || word == "acosh"
567      || word == "atanh"
568      || word == "sqrt"
569      || word == "exp"
570      || word == "log"
571      || word == "log10" 
572      || word == "pow"  )
573  { 
574    return true;
575  }
576  else
577  { 
578    return false;
579  }
580}
581
582
583//-------------------------------------------------------------
584G4RotationMatrix G4tgrUtils::GetRotationFromDirection( G4ThreeVector dir )
585{
586  G4RotationMatrix rotation;
587
588  if( std::fabs(dir.mag()-1.) > G4GeometryTolerance::GetInstance()
589                              ->GetSurfaceTolerance() )
590  {
591    G4String WarMessage = "Direction cosines have been normalized to one.\n"
592                        + G4String("They were normalized to ")
593                        + G4UIcommand::ConvertToString(dir.mag());
594    G4Exception("G4tgrUtils::GetRotationFromDirection()", "WrongArgument",
595                JustWarning, WarMessage);
596    dir /= dir.mag();
597  } 
598  G4double angx = -std::asin(dir.y());
599
600  // There are always two solutions angx, angy and PI-angx,
601  // PI+angy, choose first
602  //
603  G4double angy;
604  if( dir.y() == 1. )
605  {
606    angy = 0.;
607  }
608  else if( dir.y() == 0. )
609  {
610    angy = 0.;
611  }
612  else
613  {
614    angy = std::asin( dir.x()/std::sqrt(1-dir.y()*dir.y()) );
615  }
616 
617  // choose between  angy and PI-angy
618  if( dir.z() * std::cos(angx)*std::cos(angy) < 0 )
619  {
620    angy = CLHEP::pi - angy;
621  }
622  rotation.rotateX( angx );
623  rotation.rotateY( angy );
624
625  return rotation;
626} 
627
628
629//-------------------------------------------------------------
630G4bool G4tgrUtils::AreWordsEquivalent( const G4String& word1,
631                                       const G4String& word2 )
632{
633  G4bool bEqual = true;
634  std::vector< std::pair<G4int,G4int> > stringPairs;
635    // start of substring, number of characters
636
637  //--- Get string limits between asterisks in word1
638
639  size_t cStart = 0;
640  for( ;; )
641  {
642    size_t cAster = word1.find("*",cStart);
643    if( cAster != std::string::npos )
644    {
645      if( cAster == cStart )
646      {
647        if( cAster != 0 )
648        {
649          G4Exception("G4tgrUtils::AreWordsEquivalent()",
650                      "A word has two asterisks together, please correct it",
651                      FatalException,("Offending word is: " + word1).c_str() );
652        }
653        else
654        {
655          // word1 == *
656          if(word1.size() == 1 )  { return true; }
657        }
658      }     
659      if( cAster!= cStart )
660      {
661        stringPairs.push_back( std::pair<G4int,G4int>(cStart, cAster-cStart) );
662      }
663      cStart = cAster+1;
664    }
665    else
666    {
667      if( cStart == 0 )
668      {
669        //--- If there is no asterisk check if they are the same
670        return word1 == word2;
671      }
672      break;
673    }
674  }
675 
676  //---- Add characters after last asterisk as string pair
677  if( cStart <= word1.length() )
678  {
679    if( word1.length() != cStart )
680    {
681      stringPairs.push_back( std::pair<G4int,G4int>(cStart,
682                                                    word1.length()-cStart) );
683    }
684  }
685
686  //--- If there are not asterisk, simple comparison
687  if( stringPairs.size() == 0 )
688  {
689    if( word1 == word2 )
690    {
691      return true;
692    }
693    else
694    {
695      return false;
696    }
697  }
698 
699  //--- Find substrings in word2, in same order as in word1
700  cStart = 0;
701  for( size_t ii = 0; ii < stringPairs.size(); ii++ )
702  {
703    std::pair<G4int,G4int> spair = stringPairs[ii];
704    size_t sFound = word2.find(word1.substr(spair.first, spair.second),cStart);
705    if( sFound  == std::string::npos )
706    {
707      bEqual = false;
708      break;
709    }
710    else
711    {
712      //---- If there is no asterisk before first character,
713      //     the fisrt string pair found has to start at the first character
714      if( spair.first == 0 && sFound != 0 )
715      {
716        bEqual = false;
717        break;
718        //---- If there is no asterisk after last character,
719        //     the last string pair found has to end at the last character
720      }
721      else if( (spair.first+spair.second-1 == G4int(word1.length()))
722            && (G4int(sFound)+spair.second-1 != G4int(word2.length())) )
723      {
724        bEqual = false;
725        break;
726      }
727      cStart += spair.second;
728    } 
729  }
730
731  return bEqual;
732}
Note: See TracBrowser for help on using the repository browser.