GEMC  1.8
Geant4 Monte-Carlo Framework
detector_io_mysql.cc
Go to the documentation of this file.
1 // %%%%%%%%%%
2 // Qt headers
3 // %%%%%%%%%%
4 #include <QtSql>
5 
6 
7 // %%%%%%%%%%%%%
8 // gemc headers
9 // %%%%%%%%%%%%%
10 #include "usage.h"
11 #include "detector.h"
12 #include "MSensitiveDetector.h"
13 #include "run_conditions.h"
14 #include "string_utilities.h"
15 
16 
17 // %%%%%%%%%%%
18 // C++ headers
19 // %%%%%%%%%%%
20 #include <sstream>
21 using namespace std;
22 
23 
24 
25 map<string, detector> read_detector(gemc_opts gemcOpt, run_conditions RunConditions)
26 {
27  string database = gemcOpt.args["DATABASE"].args;
28  string dbtable = gemcOpt.args["GT"].args;
29  string dbhost = gemcOpt.args["DBHOST"].args;
30 
31  string dbUser = gemcOpt.args["DBUSER"].args;
32  string dbPswd = gemcOpt.args["DBPSWD"].args;
33 
34  string hd_msg = gemcOpt.args["LOG_MSG"].args + " MySQL: >> ";
35  double GEO_VERBOSITY = gemcOpt.args["GEO_VERBOSITY"].arg;
36  string catch_v = gemcOpt.args["CATCH"].args;
37  string hall_field = gemcOpt.args["HALL_FIELD"].args;
38 
39  // StderrLog errlog;
40  map<string, detector> CLAS;
41  detector Detector;
42  stringstream vars;
43  string var;
44 
45  G4Colour thisCol;
46  vector<identifier> identity; // vector of identifiers
47  identifier iden;
48 
49 
50  cout << endl << hd_msg << " Connecting to database \"" << database << "\" as \""
51  << dbUser << "\". " << endl;
52 
53 
54  QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
55  db.setHostName(dbhost.c_str());
56  db.setDatabaseName(database.c_str());
57  db.setUserName( dbUser.c_str() );
58  db.setPassword( dbPswd.c_str() );
59  bool ok = db.open();
60 
61  if(!ok)
62  {
63  cout << hd_msg << " Cannot connect to database " << database << ". Exiting." << endl;
64  exit(-1);
65  }
66 
67  else
68  {
69  // if no tables in the gcard or gcard is not specified, using standard full clas12 geometry instead
70  if(RunConditions.gTab_Vec.size() == 0 && dbtable == "no")
71  {
72  RunConditions.gTab_Vec.push_back("BST");
73  RunConditions.gTab_Vec.push_back("CTOF");
74  RunConditions.gTab_Vec.push_back("HTCC");
75  RunConditions.gTab_Vec.push_back("SECTOR");
76  RunConditions.gTab_Vec.push_back("FTOF");
77  RunConditions.gTab_Vec.push_back("EC");
78  RunConditions.gTab_Vec.push_back("DC12");
79  RunConditions.gTab_Vec.push_back("solenoid");
80  RunConditions.gTab_Vec.push_back("torus");
81  }
82  if(RunConditions.gTab_Vec.size() == 0 && dbtable != "no")
83  RunConditions.gTab_Vec.push_back(dbtable);
84 
85  for(unsigned int sql_t=0; sql_t< RunConditions.gTab_Vec.size(); sql_t++)
86  {
87  if(GEO_VERBOSITY > 3) cout << hd_msg << " Importing table: " << RunConditions.gTab_Vec[sql_t] << endl;;
88  QSqlQuery q;
89  string dbexecute = "select name, mother, description, pos, rot, col, type,";
90  dbexecute += "dimensions, material, magfield, ncopy, pmany, exist, ";
91  dbexecute += "visible, style, sensitivity, hitType, identity from " + RunConditions.gTab_Vec[sql_t];
92 
93  // will exit if table cannot be accessed.
94  bool SUCCESS = q.exec(dbexecute.c_str());
95  if(!SUCCESS)
96  {
97  cout << hd_msg << " Failed to access DB for table: " << RunConditions.gTab_Vec[sql_t] << ". Maybe the table doesn't exist? Exiting." << endl;
98  exit(0);
99  }
100 
101  while (q.next())
102  {
103  // %%%%%%%%%%%%%%%%%
104  // Reading variables
105  // %%%%%%%%%%%%%%%%%
106 
107  // 0,1,2: Id, Mother, Description
108  Detector.name = TrimSpaces(gemc_tostring(q.value(0).toString()));
109  Detector.mother = TrimSpaces(gemc_tostring(q.value(1).toString()));
110  Detector.description = gemc_tostring(q.value(2).toString());
111 
112  // 3: Position Vector
113  Detector.pos = G4ThreeVector(0, 0, 0);
114 
115  G4ThreeVector nompos(0, 0, 0);
116  G4ThreeVector shiftp(0, 0, 0);
117  G4ThreeVector more_rot(0, 0, 0);
118 
119  vars << gemc_tostring(q.value(3).toString());
120  vars >> var; nompos.setX(get_number(var));
121  vars >> var; nompos.setY(get_number(var));
122  vars >> var; nompos.setZ(get_number(var));
123  vars.clear();
124  // Adding gcard displacement for this detector if necessary
125  if(RunConditions.gDet_Map.find(Detector.name) != RunConditions.gDet_Map.end())
126  {
127  shiftp = RunConditions.gDet_Map[Detector.name].get_position();
128  if(GEO_VERBOSITY > 3 || Detector.name.find(catch_v))
129  cout << hd_msg << " Detector " << Detector.name << " is displaced by: " << shiftp/cm << " cm" << endl;
130 
131  }
132  Detector.pos = nompos + shiftp;
133 
134 
135  // 4: Rotation Vector
136  Detector.rot = G4RotationMatrix(G4ThreeVector(1, 0, 0),
137  G4ThreeVector(0, 1, 0),
138  G4ThreeVector(0, 0, 1));
139 
140  vars << gemc_tostring(q.value(4).toString());
141  vars >> var;
142  if(var != "ordered:")
143  {
144  Detector.rot.rotateX(get_number(var));
145  vars >> var; Detector.rot.rotateY(get_number(var));
146  vars >> var; Detector.rot.rotateZ(get_number(var));
147  }
148  else
149  {
150  string order;
151  vars >> order;
152  if(order == "xzy")
153  {
154  vars >> var; Detector.rot.rotateX(get_number(var));
155  vars >> var; Detector.rot.rotateZ(get_number(var));
156  vars >> var; Detector.rot.rotateY(get_number(var));
157  }
158  else if(order == "yxz")
159  {
160  vars >> var; Detector.rot.rotateY(get_number(var));
161  vars >> var; Detector.rot.rotateX(get_number(var));
162  vars >> var; Detector.rot.rotateZ(get_number(var));
163  }
164  else if(order == "yzx")
165  {
166  vars >> var; Detector.rot.rotateY(get_number(var));
167  vars >> var; Detector.rot.rotateZ(get_number(var));
168  vars >> var; Detector.rot.rotateX(get_number(var));
169  }
170  else if(order == "zxy")
171  {
172  vars >> var; Detector.rot.rotateZ(get_number(var));
173  vars >> var; Detector.rot.rotateX(get_number(var));
174  vars >> var; Detector.rot.rotateY(get_number(var));
175  }
176  else if(order == "zyx")
177  {
178  vars >> var; Detector.rot.rotateZ(get_number(var));
179  vars >> var; Detector.rot.rotateY(get_number(var));
180  vars >> var; Detector.rot.rotateX(get_number(var));
181  }
182  else
183  {
184  cout << hd_msg << " Ordered rotation <" << order << "> for " << Detector.name << " is wrong, it's none of the following:"
185  << " xzy, yxz, yzx, zxy or zyx. Exiting." << endl;
186  exit(0);
187  }
188  }
189  // Adding gcard rotation for this detector if necessary
190  if(RunConditions.gDet_Map.find(Detector.name) != RunConditions.gDet_Map.end())
191  {
192  more_rot = RunConditions.gDet_Map[Detector.name].get_vrotation();
193  if(GEO_VERBOSITY > 3 || Detector.name.find(catch_v))
194  cout << hd_msg << " Detector " << Detector.name << " is rotated by: " << more_rot/deg << " deg" << endl;
195 
196  Detector.rot.rotateX(more_rot.x());
197  Detector.rot.rotateY(more_rot.y());
198  Detector.rot.rotateZ(more_rot.z());
199  }
200 
201 
202  vars.clear();
203 
204  // 5: Color, opacity
205  var = TrimSpaces(gemc_tostring(q.value(5).toString()));
206  if(var.size() != 6 && var.size() != 7)
207  {
208  cout << hd_msg << " Color for " << Detector.name << "<" << var << "> has wrong size: " << var.size()
209  << ". It should be 6 or 7 hexadecimal numbers." << endl;
210  exit(9);
211  }
212  thisCol = G4Colour(strtol(var.substr(0, 2).c_str(), NULL, 16)/255.0,
213  strtol(var.substr(2, 2).c_str(), NULL, 16)/255.0,
214  strtol(var.substr(4, 2).c_str(), NULL, 16)/255.0,
215  1.0 - atof(var.substr(6, 1).c_str())/5.0); // Transparency 0 to 5 where 5=max transparency (default is 0 if nothing is specified)
216 
217 
218  // 6: Solid Type
219  Detector.type = TrimSpaces(gemc_tostring(q.value(6).toString()));
220 
221  // 7: Dimensions
222  vars << gemc_tostring(q.value(7).toString());
223  while(!vars.eof())
224  {
225  vars >> var;
226  Detector.dimensions.push_back(get_number(var));
227  }
228  vars.clear();
229 
230  // 8: Material
231  Detector.material = TrimSpaces(gemc_tostring(q.value(8).toString()));
232 
233  // 9: Magnetic Field
234  Detector.magfield = TrimSpaces(gemc_tostring(q.value(9).toString()));
235 
236  // 10: copy number
237  Detector.ncopy = q.value(10).toInt();
238 
239  // 11: pMany
240  Detector.pMany = q.value(11).toInt();
241 
242  // 12: Activation flag
243  Detector.exist = q.value(12).toInt();
244  // Checking if existance is set in the gcard
245  if(RunConditions.gDet_Map.find(Detector.name) != RunConditions.gDet_Map.end())
246  {
247  Detector.exist = RunConditions.gDet_Map[Detector.name].get_existance();
248  if(GEO_VERBOSITY > 3 || Detector.name.find(catch_v))
249  cout << hd_msg << " Detector " << Detector.name << " has existance set to: " << Detector.exist << endl;
250 
251  }
252 
253 
254  // 13: Visibility
255  Detector.visible = q.value(13).toInt();
256 
257  // 14: Style
258  Detector.style = q.value(14).toInt();
259 
260  // 15: sensitivity
261  Detector.sensitivity = gemc_tostring(q.value(15).toString());
262 
263  if(Detector.sensitivity != "no")
264  {
265 
266  // 16: hitType
267  Detector.hitType = gemc_tostring(q.value(16).toString());
268 
269  // 17: identity
270  vars << gemc_tostring(q.value(17).toString());
271  while(!vars.eof())
272  {
273  vars >> iden.name >> iden.rule >> iden.id;
274  if(iden.rule.find("ncopy") != string::npos) iden.id = Detector.ncopy;
275  identity.push_back(iden);
276  }
277  vars.clear();
278 
279  Detector.identity = identity;
280  identity.clear();
281 
282  }
283 
284  // %%%%%%%%%%%%%%%%%
285  // End of variables
286  // %%%%%%%%%%%%%%%%%
287 
288  // Setting the Visual Atributes
289  Detector.VAtts = G4VisAttributes(thisCol);
290  if(Detector.visible) Detector.style ? Detector.VAtts.SetForceSolid(true) : Detector.VAtts.SetForceWireframe(true);
291  Detector.visible ? Detector.VAtts.SetVisibility(true) : Detector.VAtts.SetVisibility(false);
292 
293  // need to check that it doesn't exists already before putting it in the map.
294 
295  CLAS[Detector.name] = Detector;
296  Detector.dimensions.clear();
297  Detector.identity.clear();
298  }
299  }
300  }
301  db.close();
302  // need to create empty db before removing the connection
303  db = QSqlDatabase();
304  db.removeDatabase("qt_sql_default_connection");
305 
306  // adding mother volume here:
307  string hall_mat = gemcOpt.args["HALL_MATERIAL"].args;
308  detector queen;
309  queen.name = "root";
310  queen.mother = "akasha";
311  queen.description = "mother of us all";
312  queen.pos = G4ThreeVector(0, 0, 0);
313  queen.rot = G4RotationMatrix(G4ThreeVector(1, 0, 0),
314  G4ThreeVector(0, 1, 0),
315  G4ThreeVector(0, 0, 1));
316  queen.type = "Box";
317  queen.dimensions.push_back(120*m);
318  queen.dimensions.push_back(120*m);
319  queen.dimensions.push_back(120*m);
320  queen.material = hall_mat;
321  queen.magfield = hall_field;
322  queen.exist = 1;
323  queen.visible = 0;
324  queen.ncopy = 0;
325  queen.scanned = 1;
326  CLAS["root"] = queen;
327 
328 
329 
330 
331 
332  cout << endl;
333 
334  string field = gemcOpt.args["NO_FIELD"].args;
335  // Transmitting the magnetic field properties to the whole genealogy if they are set to "no"
336  for( map<string, detector>::iterator it = CLAS.begin() ; it!=CLAS.end() && field != "all" ; it++)
337  {
338  // if this is tagged for no field, continue
339  if(it->first == field)
340  continue;
341 
342  if(it->second.magfield == "no")
343  {
344  // looking up the whole genealogy, until the first field is found
345  string mother = it->second.mother;
346  string firstAncestorFieldFound = "no";
347  while(mother != "akasha" && firstAncestorFieldFound == "no")
348  {
349  if(CLAS[mother].magfield != "no")
350  {
351  firstAncestorFieldFound = CLAS[mother].magfield;
352  it->second.magfield = CLAS[mother].magfield;
353  }
354  // moving up in genealogy
355  mother = CLAS[mother].mother;
356  }
357  }
358 
359  if(GEO_VERBOSITY > 3 || it->first.find(catch_v) != string::npos) cout << hd_msg << " " << it->second ;
360 
361  }
362 
363 
364  return CLAS;
365 }
366 
367 
368 SDId get_SDId(string SD, gemc_opts gemcOpt)
369 {
370  string hd_msg = gemcOpt.args["LOG_MSG"].args + " MySQL: >> ";
371  string database = gemcOpt.args["BANK_DATABASE"].args;
372  string dbhost = gemcOpt.args["DBHOST"].args;
373 
374  string dbUser = gemcOpt.args["DBUSER"].args;
375  string dbPswd = gemcOpt.args["DBPSWD"].args;
376 
377  double HIT_VERBOSITY = gemcOpt.args["HIT_VERBOSITY"].arg;
378 
379  stringstream vars;
380  string var;
381 
382  SDId SDID;
383  QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
384  db.setHostName(dbhost.c_str());
385  db.setDatabaseName(database.c_str());
386  db.setUserName( dbUser.c_str() );
387  db.setPassword( dbPswd.c_str() );
388  bool ok = db.open();
389 
390  if(!ok)
391  {
392  cout << hd_msg << " Database not connected. Exiting." << endl;
393  exit(-1);
394  }
395 
396  else
397  {
398  if(HIT_VERBOSITY>1) cout << hd_msg << " Loading definitions table for <" << SD << ">..." ;
399  QSqlQuery q;
400  string command = "select id, identifiers, minEnergy, TimeWindow, ProdThreshold, MaxStep from SDId where name = \"" + SD + "\"" ;
401  q.exec(command.c_str());
402 
403  while (q.next())
404  {
405  // %%%%%%%%%%%%%%%%%
406  // Reading variables
407  // %%%%%%%%%%%%%%%%%
408  // 0: Bank ID
409  SDID.id = q.value(0).toInt();
410 
411  // 1: Identifier Maxs
412  vars << gemc_tostring(q.value(1).toString());
413  vars >> var;
414  while(!vars.eof())
415  {
416  SDID.IDnames.push_back(var);
417  vars >> var;
418  }
419  vars.clear();
420 
421  // 2: Minimum Energy Cut for processing the hit
422  SDID.minEnergy = get_number(gemc_tostring(q.value(2).toString()));
423 
424  // 3: Minimum Energy Cut for processing the hit
425  SDID.TimeWindow = get_number(gemc_tostring(q.value(3).toString()));
426 
427  // 4: Production Threshold in the detector
428  SDID.ProdThreshold = get_number(gemc_tostring(q.value(4).toString()));
429 
430  // 5: Maximum Acceptable Step in the detector
431  SDID.MaxStep = get_number(gemc_tostring(q.value(5).toString()));
432 
433  if(HIT_VERBOSITY>3)
434  {
435  cout << "found: bank " << SD << ", id=" << SDID.id << "." << endl << endl ;
436  for(unsigned int i=0; i<SDID.IDnames.size(); i++)
437  {
438  cout << " element name: " << SDID.IDnames[i] << endl;
439  }
440  cout << endl << hd_msg << " Minimum Energy Cut for processing the <" << SD << "> hit: " << SDID.minEnergy/MeV << " MeV." << endl ;
441  cout << hd_msg << " Time Window for <" << SD << ">: " << SDID.TimeWindow/ns << " ns." << endl ;
442  cout << hd_msg << " Production Threshold for <" << SD << ">: " << SDID.ProdThreshold/mm << " mm." << endl ;
443  cout << hd_msg << " Maximum Acceptable Step for <" << SD << ">: " << SDID.MaxStep/mm << " mm." << endl ;
444  cout << endl;
445  }
446 
447  }
448  }
449  db.close();
450 
451  // need to create empty db before removing the connection
452  db = QSqlDatabase();
453  db.removeDatabase("qt_sql_default_connection");
454  return SDID;
455 }
456 
457 
458 
459 
460 
461 
462 
463 
464 
465 
SDId get_SDId(string SD, gemc_opts gemcOpt)
Connects to DB and retrieve SDId.
map< string, detector > read_detector(gemc_opts gemcOpt, run_conditions RunConditions)
Reads detector map from database.
vector< string > gTab_Vec
Vector of SQL tables names.
int id
Sensitive Detector identifier. This is also the bank ID.
string sensitivity
Defines the Sensitive Detector. possible choices: "no" "hits collection name".
Definition: detector.h:75
string mother
Mother Volume name.
Definition: detector.h:54
double ProdThreshold
Production Threshold in the detector.
STL namespace.
G4ThreeVector pos
Position relative to the mother volume, as G4ThreeVector.
Definition: detector.h:57
double TimeWindow
If two steps happens withing the same TimeWindow, they belong to the same Hit.
string gemc_tostring(QString input)
int id
manually assing ID. 0 if "ncopy" (will be set at hit processing time)
Definition: identifier.h:31
string name
Name of the detector.
Definition: identifier.h:28
G4VisAttributes VAtts
Visual Attributes: color, transparency, style (wireframe, solid), visibility.
Definition: detector.h:60
vector< string > IDnames
Identifier names as they should be in identifier.
bool pMany
Needed by geant4 at G4PVPlacement time.
Definition: detector.h:69
int ncopy
copy number
Definition: detector.h:68
map< string, gcard_detector > gDet_Map
Map of gcard_detector. Map Key = detector name.
string name
Name of the volume. Since this is the key of the STL map, it has to be unique.
Definition: detector.h:53
string material
Volume Material name.
Definition: detector.h:65
double minEnergy
Minimum energy of the hit to be recorded in the output stream.
int visible
visibility of the detector: 0=invisible 1=visible
Definition: detector.h:72
int style
Visual style: 0=wireframe 1=solid.
Definition: detector.h:73
double MaxStep
Maximum Acceptable Step in the detector.
string hitType
Hit Process routine name. A Hit Process MPHBaseClass derived class must exists with this name...
Definition: detector.h:76
vector< identifier > identity
Vector of identifiers. Example: superlayer manual 1 type manual 2 segment manual 3 strip manual 4...
Definition: detector.h:77
string magfield
Magnetic Field. The string "no" means that the field is inherited from the mother volume...
Definition: detector.h:66
map< string, opts > args
Options map.
Definition: usage.h:68
G4RotationMatrix rot
Rotation Matrix, defined by rotations along x,y,z axis relative to the mother volume.
Definition: detector.h:58
int exist
detector ON/OFF switch
Definition: detector.h:71
string type
solid type. This follows the GEANT4 definitions
Definition: detector.h:62
vector< double > dimensions
vector of dimensions. Size, units depends on solid type
Definition: detector.h:63
string TrimSpaces(string in)
Removes leading and trailing spaces.
double get_number(string)
Returns dimension from string, i.e. 100*cm.
int scanned
for use during construction
Definition: detector.h:79
string rule
"manual" or "ncopy"
Definition: identifier.h:30
string description
Volume Description for documentation.
Definition: detector.h:55