GEMC  2.3
Geant4 Monte-Carlo Framework
detector_tree.cc
Go to the documentation of this file.
1 // Qt headers
2 #include <QActionGroup>
3 #include <QColorDialog>
4 #include <QMenu>
5 
6 // gemc headers
7 #include "detector_tree.h"
10 #include "options.h"
11 #include "string_utilities.h"
12 #include "detector_editor.h"
13 
14 // C++ headers
15 #include <sys/stat.h>
16 #include <vector>
17 #include <string>
18 
19 detector_tree::detector_tree(QWidget *parent, goptions Opts, G4RunManager* RM, map<string, detector> *Map,
20  map<string, G4Material*> MMap) : QWidget(parent)
21 {
22  gemcOpt = Opts;
23  runManager = RM;
24  UImanager = G4UImanager::GetUIpointer();
25  Hall_Map = Map;
26  MMats = MMap;
27  createActions();
28 
29  // Layout:
30  //
31  // + +-------------------+ +
32  // | | | | |
33  // | | Tree | infos | |
34  // | | | | |
35  // | +-------------------+ |
36  // | | | | |
37  // | | | | |
38  // | | | | |
39  // | | | | |
40  // | +-------------------+ |
41  // | | | | |
42  // | | | | |
43  // | | | | |
44  // | +-------------------+ |
45 
46 
47 
48 
49  // Detector Tree
50  treeWidget = new QTreeWidget();
51  treeWidget->setColumnCount(1);
52  QStringList headers;
53  headers << tr("Volumes") ;
54  treeWidget->setHeaderLabels(headers);
55 
56  // in case the geometry changes need to reload the tree
57  // in case it doesn't, no need to load the tree
58  tree_map = read_geometry(treeWidget);
59  treeWidget->setContextMenuPolicy( Qt::ActionsContextMenu );
60  treeWidget-> addAction( Switch_visibility );
61  treeWidget-> addAction( Switch_visibility_daughters );
62  treeWidget-> addAction( Switch_wiresolid );
63  treeWidget-> addAction( Switch_color );
64  treeWidget-> addAction( Write_GDML_File );
65  treeWidget-> addAction( Write_WRL_File );
66  connect(treeWidget, SIGNAL(itemSelectionChanged ()), this, SLOT(show_detector()));
67 
68  // detector infos
69  dTab = new descriptionTab();
70 
71 
72  QSplitter *splitter = new QSplitter(Qt::Horizontal);
73 
74  QWidget *leftWidget = new QWidget(splitter);
75  leftWidget->setMinimumWidth(300);
76  QVBoxLayout *leftLayout = new QVBoxLayout(leftWidget);
77  leftLayout->addWidget(treeWidget);
78 
79 
80  // writing single volumes in GDML or WRL
81  QHBoxLayout *writeSingleVolumeButtons = new QHBoxLayout();
82 
83  writeToGDML = new QPushButton(tr("detector to gdml"));
84  writeToGDML->setEnabled(false);
85  writeToGDML->setToolTip("Creates a gdml file for the highlighted detector");
86  writeToGDML->setIcon(style()->standardIcon(QStyle::SP_DialogSaveButton));
87  connect ( writeToGDML , SIGNAL(clicked()), this, SLOT( set_gdml_name() ));
88  writeSingleVolumeButtons->addWidget(writeToGDML);
89 
90  writeToWRL = new QPushButton(tr("detector to wrl"));
91  writeToWRL->setEnabled(false);
92  writeToWRL->setToolTip("Creates a gdml file for the highlighted detector");
93  writeToWRL->setIcon(style()->standardIcon(QStyle::SP_DialogSaveButton));
94  connect ( writeToWRL , SIGNAL(clicked()), this, SLOT( set_wrl_name() ));
95  writeSingleVolumeButtons->addWidget(writeToWRL);
96 
97 
98  // writing all volumes in GDML or WRL
99  QHBoxLayout *writeAllVolumeButtons = new QHBoxLayout();
100 
101  QPushButton *writeToGDMLA = new QPushButton(tr("all to gdml"));
102  writeToGDMLA->setToolTip("Creates a gdml file for all detectors");
103  writeToGDMLA->setIcon(style()->standardIcon(QStyle::SP_DialogSaveButton));
104  connect ( writeToGDMLA , SIGNAL(clicked()), this, SLOT( set_gdml_nameAll() ));
105  writeAllVolumeButtons->addWidget(writeToGDMLA);
106 
107  QPushButton *writeToWRLA = new QPushButton(tr("all to wrl"));
108  writeToWRLA->setToolTip("Creates a wrl file for all detectors");
109  writeToWRLA->setIcon(style()->standardIcon(QStyle::SP_DialogSaveButton));
110  connect ( writeToWRLA , SIGNAL(clicked()), this, SLOT( set_wrl_nameAll() ));
111  writeAllVolumeButtons->addWidget(writeToWRLA);
112 
113  // inspect detectors will open a new window
114  showDetInNewWindow= new QPushButton(tr("inspect detector"));
115  showDetInNewWindow->setEnabled(false);
116  showDetInNewWindow->setToolTip("Creates a gdml file for all detectors");
117  showDetInNewWindow->setIcon(style()->standardIcon(QStyle::SP_ComputerIcon));
118  connect ( showDetInNewWindow , SIGNAL(clicked()), this, SLOT( inspectDetector() ) );
119 
120 
121  // adding all together on the left layout
122  leftLayout->addLayout(writeSingleVolumeButtons);
123  leftLayout->addLayout(writeAllVolumeButtons);
124  leftLayout->addWidget(showDetInNewWindow);
125 
126 
127  QWidget *rightWidget = new QWidget(splitter);
128  QVBoxLayout *rightLayout = new QVBoxLayout(rightWidget);
129  rightLayout->addWidget(dTab);
130 
131 
132  // all layouts
133  QVBoxLayout *mainLayout = new QVBoxLayout;
134  mainLayout->addWidget(splitter);
135  setLayout(mainLayout);
136 
137 }
138 
140 {
141  string hd_msg = gemcOpt.optMap["LOG_MSG"].args ;
142  double VERB = gemcOpt.optMap["GEO_VERBOSITY"].arg ;
143  if(VERB>2)
144  cout << hd_msg << " Detector Widget Tree Deleted." << endl;
145 
146  delete Switch_visibility;
147  delete Switch_wiresolid;
148  delete treeWidget;
149 }
150 
151 map<string, tree_item> detector_tree::read_geometry(QTreeWidget *motherWidget)
152 {
153  string hd_msg = gemcOpt.optMap["LOG_MSG"].args + " Detector Tree >> " ;
154  double VERB = gemcOpt.optMap["GEO_VERBOSITY"].arg ;
155 
156  map<string, tree_item> tree_map;
157  tree_item item;
158 
159 
160  if(VERB > 2)
161  {
162  cout << endl;
163  cout << hd_msg << " Building Detector Widget Tree from Geometry STL Map..." << endl << endl;
164  cout << hd_msg << " Experimenta Hall has " << Hall_Map->size() << " components." << endl << endl;
165  }
166 
167 
168  // fills the volumes tree map
169  // initialize the Hall_Map member QTreeWidgetItem pointer and built variable to zero
170  for(map<string, detector>::iterator i = Hall_Map->begin(); i != Hall_Map->end(); i++)
171  {
172  item.volume = i->second.name;
173  item.mother = i->second.mother;
174  item.treeItem = NULL;
175  item.scanned = 0;
176  item.sensitive = 0;
177  if(i->second.sensitivity != "no")
178  item.sensitive = 1;
179 
180  item.exist = i->second.exist;
181  item.visible = i->second.visible;
182  item.wiresolid = i->second.style;
183 
184  if(i->second.name != "root" && i->second.GetPhysical())
185  {
186  tree_map.insert(map<string, tree_item>::value_type(i->second.name, item));
187  if(VERB > 3) cout << hd_msg << " Mapping Detector " << i->first << endl;
188  }
189  }
190 
191  if(VERB > 3) cout << endl << endl;
192 
193  ActiveGrad = QLinearGradient(QPointF(1, 100), QPointF(180, 70));
194  ActiveGrad.setColorAt(0, QColor( 80, 80, 255));
195  ActiveGrad.setColorAt(1, QColor(245, 245, 245));
196 
197  SensitiveGrad = QLinearGradient(QPointF(1, 100), QPointF(180, 20));
198  SensitiveGrad.setColorAt(0, QColor(255, 80, 80));
199  SensitiveGrad.setColorAt(1, QColor(245, 245, 245));
200 
201  NonActiveGrad = QLinearGradient(QPointF(1, 100), QPointF(10, 30));
202  NonActiveGrad.setColorAt(0, QColor(255, 20, 20));
203  NonActiveGrad.setColorAt(1, QColor(245, 245, 245));
204 
205  NonVisibleGrad = QLinearGradient(QPointF(1, 100), QPointF(60, 30));
206  NonVisibleGrad.setColorAt(0, QColor(5, 5, 5));
207  NonVisibleGrad.setColorAt(1, QColor(240, 240, 240));
208 
209  ActiveBrush = QBrush(ActiveGrad);
210  SensitiveBrush = QBrush(SensitiveGrad);
211  NonActiveBrush = QBrush (NonActiveGrad);
212  NonVisibleBrush = QBrush (NonVisibleGrad);
213 
214 
215  // now build the actual QTreeWidgetItem
216  // if a kid has no mom, its mom will be built first
217  vector<string> relatives;
218  string mom, kid;
219  if(VERB > 2) cout << endl << hd_msg << " Reordering Tree Elements..." << endl << endl;
220  for(map<string, tree_item>::iterator i = tree_map.begin(); i != tree_map.end(); i++)
221  {
222  if(i->first != "" && i->first != "root") relatives.push_back(i->second.volume);
223 
224  while(relatives.size() > 0 && relatives.size() < 100)
225  {
226  mom = tree_map[relatives.back()].mother;
227  kid = tree_map[relatives.back()].volume;
228 
229 
230  if(VERB > 3)
231  {
232  for(unsigned int i=0; i<relatives.size()-1; i++) cout << "\t";
233  cout << hd_msg << " Checking " << kid << ", child of " << mom
234  << ", for a living ancestor. This Geneaology Depth is " << relatives.size() << "." << endl;
235  }
236 
237  // Mom is <root>. Can build the kid.
238  if(tree_map[kid].scanned == 0 && mom.find("root", 0) != string::npos)
239  {
240  if(VERB > 3)
241  {
242  for(unsigned int i=0; i<relatives.size()-1; i++) cout << "\t";
243  cout << hd_msg << " Found: " << relatives.back()
244  << " has <root> as mom and it's not built yet. Building " << kid << "..." << endl;
245  }
246  tree_map[kid].treeItem = new QTreeWidgetItem(motherWidget);
247  tree_map[kid].treeItem->setText(0, kid.c_str());
248  tree_map[kid].scanned = 1;
249 
250  }
251 
252  // Mom (not root) is built, kid not built yet. Build the kid.
253  if(tree_map[kid].scanned == 0 && tree_map[mom].scanned == 1)
254  {
255  if(VERB > 3)
256  {
257  for(unsigned int i=0; i<relatives.size()-1; i++) cout << "\t";
258  cout << hd_msg << " Found: " << kid
259  << " is not built yet but its mommie " << mom << " is. Building " << kid << "..." << endl;
260  }
261 
262  tree_map[kid].treeItem = new QTreeWidgetItem(tree_map[mom].treeItem);
263  tree_map[kid].treeItem->setText(0, kid.c_str());
264  tree_map[kid].scanned = 1;
265  }
266 
267  // if the kid still doesn't exists it means its mom doesn't exist. Need to go up one level.
268  if(tree_map[kid].scanned == 0) relatives.push_back(mom);
269 
270  // the kid has been built. Can go down one step in geneaology
271  if(tree_map[kid].scanned == 1 && relatives.size())
272  {
273  if(VERB > 3)
274  cout << hd_msg << " " << kid << " is built." << endl << endl;
275 
276  if(tree_map[kid].exist == 1) tree_map[kid].treeItem->setBackground(0, ActiveBrush );
277  if(tree_map[kid].exist == 0) tree_map[kid].treeItem->setBackground(0, NonActiveBrush );
278  if(tree_map[kid].visible == 1) tree_map[kid].treeItem->setBackground(0, ActiveBrush );
279  if(tree_map[kid].sensitive == 1) tree_map[kid].treeItem->setBackground(0, SensitiveBrush );
280  if(tree_map[kid].visible == 0) tree_map[kid].treeItem->setBackground(0, NonVisibleBrush );
281  relatives.pop_back();
282  }
283  }
284  }
285 
286  return tree_map;
287 }
288 
289 
290 void detector_tree::switch_visibility()
291 {
292  QTreeWidgetItem *CurrentItem = treeWidget->currentItem();
293  string name = qs_tostring(CurrentItem->text(0));
294  tree_map[name].visible == 1 ? tree_map[name].visible = 0 : tree_map[name].visible = 1;
295  tree_map[name].visible == 1 ? CurrentItem->setBackground(0, ActiveBrush ) : CurrentItem->setBackground(0, NonVisibleBrush);
296  char command[100];
297  sprintf(command, "/vis/geometry/set/visibility %s 0 %d", name.c_str(), tree_map[name].visible);
298  UImanager->ApplyCommand(command);
299 }
300 
301 void detector_tree::switch_visibility_daughters()
302 {
303  string name = qs_tostring(treeWidget->currentItem()->text(0));
304  int vis = 0;
305  for(map<string, tree_item>::iterator it = tree_map.begin(); it != tree_map.end(); it++)
306  if(it->second.mother == name)
307  {
308  it->second.visible == 1 ? it->second.visible = 0 : it->second.visible = 1;
309  it->second.visible == 1 ? it->second.treeItem->setBackground(0, ActiveBrush )
310  : it->second.treeItem->setBackground(0, NonVisibleBrush);
311  vis = it->second.visible;
312  }
313 
314  char command[100];
315  sprintf(command, "/vis/geometry/set/daughtersInvisible %s 0 %d", name.c_str(), !vis);
316  UImanager->ApplyCommand(command);
317 }
318 
319 void detector_tree::inspectDetector()
320 {
321  string name = qs_tostring(treeWidget->currentItem()->text(0));
322 
323  char command[100];
324  sprintf(command,"/vis/viewer/set/lineSegmentsPerCircle 100 ");
325  UImanager->ApplyCommand(command);
326  sprintf(command, "/vis/open OGL");
327  UImanager->ApplyCommand(command);
328  sprintf(command, "/vis/specify %s", name.c_str());
329  UImanager->ApplyCommand(command);
330  sprintf(command, "/vis/viewer/set/background .85 .95 .98 1");
331  UImanager->ApplyCommand(command);
332 }
333 
334 
335 
336 
337 
338 void detector_tree::switch_wiresolid()
339 {
340  string name = qs_tostring(treeWidget->currentItem()->text(0));
341  tree_map[name].wiresolid == 1 ? tree_map[name].wiresolid = 0 : tree_map[name].wiresolid = 1;
342 
343  char command[100];
344  if( tree_map[name].wiresolid == 1) sprintf(command, "/vis/geometry/set/forceSolid %s 0 1", name.c_str());
345  if( tree_map[name].wiresolid == 0) sprintf(command, "/vis/geometry/set/forceWireframe %s 0 1", name.c_str());
346  UImanager->ApplyCommand(command);
347 }
348 
349 
350 void detector_tree::switch_color()
351 {
352  int r, g, b;
353  string name = qs_tostring(treeWidget->currentItem()->text(0));
354  QColor color = QColorDialog::getColor(Qt::green, this);
355  color.getRgb(&r, &g, &b);
356  char command[100];
357  sprintf(command, "/vis/geometry/set/colour %s 0 %3.2f %3.2f %3.2f", name.c_str(), r/255.0, g/255.0, b/255.0);
358  UImanager->ApplyCommand(command);
359 }
360 
361 
362 
363 // maybe add a apply button to apply the changes?
364 void detector_tree::show_detector()
365 {
366  QTreeWidgetItem *CurrentItem = treeWidget->currentItem();
367  string name = qs_tostring(CurrentItem->text(0));
368 
369  detector detect = (*Hall_Map)[name];
370  dTab->update_detector(&detect);
371 
372  writeToGDML->setEnabled(true);
373  writeToWRL->setEnabled(true);
374  showDetInNewWindow->setEnabled(true);
375 
376 
377  // have to overload "=" to make this happen
378 // if((*Hall_Map)[name] != detect)
379 // cout << hd_msg << " Old detector: " << (*Hall_Map)[name];
380  (*Hall_Map)[name] = detect;
381 // cout << hd_msg << " New detector: " << (*Hall_Map)[name];
382 
383  // need mother to remove it
384  // string mother = (*Hall_Map)[name].mother;
385  // //(*Hall_Map)[name].create_solid(gemcOpt, Hall_Map);
386  // //(*Hall_Map)[name].create_logical_volume(MMats, gemcOpt);
387  // //(*Hall_Map)[mother].RemoveDaughter( (*Hall_Map)[name].GetPhysical());
388  // //(*Hall_Map)[name].create_physical_volumes(gemcOpt, (*Hall_Map)[mother].GetLogical());
389  (*Hall_Map)[name].SetTranslation(detect.pos);
390  //
393  //
394  // char command[100];
395  // sprintf(command, "/vis/geometry/set/visibility root 0 0");
397  // UImanager->ApplyCommand(command);
398 
399 }
400 
401 
402 void detector_tree::set_gdml_name()
403 {
404  write_gdml_file(qs_tostring(treeWidget->currentItem()->text(0)));
405 }
406 
407 void detector_tree::set_gdml_nameAll()
408 {
409  write_gdml_file("root");
410 }
411 
412 void detector_tree::set_wrl_name()
413 {
414  write_wrl_file(qs_tostring(treeWidget->currentItem()->text(0)));
415 }
416 
417 void detector_tree::set_wrl_nameAll()
418 {
419  write_wrl_file("root");
420 }
421 
422 
423 
424 void detector_tree::write_gdml_file(string name)
425 {
426  string fileout = name + ".gdml";
427 
428  detector detect = (*Hall_Map)[name];
429 
430  struct stat stFileInfo;
431  if(stat(fileout.c_str(),&stFileInfo)==0) // Check if file exists already.
432  {
433  if(remove(fileout.c_str())){ // Remove file, otherwise parser throws trap.
434  cout << "ERROR -- Could not remove file " << fileout << " cannot write new one.\n";
435  return;
436  }
437  }
438 
439  G4GDMLParser parser;
440  parser.Write(fileout.c_str(),detect.GetPhysical(),false);
441 }
442 
443 
444 
445 void detector_tree::write_wrl_file(string name)
446 {
447  char command[100];
448 
449  if(name != "root")
450  {
451  sprintf(command, "/vis/specify %s", name.c_str());
452  UImanager->ApplyCommand(command);
453  }
454 
455  sprintf(command, "/vis/open VRML2FILE");
456  UImanager->ApplyCommand(command);
457 
458  sprintf(command, "/vis/viewer/flush");
459  UImanager->ApplyCommand(command);
460 }
461 
462 
463 
464 void detector_tree::change_placement()
465 {
466  cout << " YAY! " << endl;
467 }
468 
469 
470 void detector_tree::createActions()
471 {
472  // Toggle visibility
473  Switch_visibility = new QAction(tr("&Switch Visibility"), this);
474  Switch_visibility->setShortcut(tr("Ctrl+V"));
475  Switch_visibility->setStatusTip(tr("Switch Visibility"));
476  connect(Switch_visibility, SIGNAL(triggered()), this, SLOT(switch_visibility()));
477 
478  // Toggle daughters' visibility
479  Switch_visibility_daughters = new QAction(tr("&Switch Visibility of Daughters"), this);
480  Switch_visibility_daughters->setShortcut(tr("Ctrl+D"));
481  Switch_visibility_daughters->setStatusTip(tr("Switch Visibility for the daughters"));
482  connect(Switch_visibility_daughters, SIGNAL(triggered()), this, SLOT(switch_visibility_daughters()));
483 
484  // Toggle wireframe/solid
485  Switch_wiresolid = new QAction(tr("&Switch Wireframe / Solid"), this);
486  Switch_wiresolid->setShortcut(tr("Ctrl+W"));
487  Switch_wiresolid->setStatusTip(tr("Switch Wireframe / Solid"));
488  connect(Switch_wiresolid, SIGNAL(triggered()), this, SLOT(switch_wiresolid()));
489 
490  // Pick Volume Color
491  Switch_color = new QAction(tr("&Pick Volume Color"), this);
492  Switch_color->setShortcut(tr("Ctrl+L"));
493  Switch_color->setStatusTip(tr("Pick Volume Color"));
494  connect(Switch_color, SIGNAL(triggered()), this, SLOT(switch_color()));
495 
496  // Write GDML File
497  Write_GDML_File = new QAction(tr("Write GDML File"), this);
498  Write_GDML_File->setShortcut(tr("Ctrl+G"));
499  Write_GDML_File->setStatusTip(tr("Write file name.gdml to current directory"));
500  connect(Write_GDML_File, SIGNAL(triggered()), this, SLOT(set_gdml_name()));
501 
502  // Write WRL File
503  Write_WRL_File = new QAction(tr("Write WRL File"), this);
504  Write_WRL_File->setShortcut(tr("Ctrl+R"));
505  Write_WRL_File->setStatusTip(tr("Write file g4_#.wrl to current directory"));
506  connect(Write_WRL_File, SIGNAL(triggered()), this, SLOT(set_wrl_name()));
507 
508 }
509 
510 
511 
map< string, tree_item > read_geometry(QTreeWidget *motherWidget)
string volume
Definition: detector_tree.h:35
void update_detector(detector *Det)
change tab according to detector
QPushButton * writeToWRL
Definition: detector_tree.h:76
QBrush NonActiveBrush
Definition: detector_tree.h:71
QLinearGradient NonActiveGrad
Definition: detector_tree.h:66
QPushButton * writeToGDML
Definition: detector_tree.h:76
goptions gemcOpt
Definition: detector_tree.h:57
descriptionTab * dTab
Definition: detector_tree.h:74
QTreeWidgetItem * treeItem
Definition: detector_tree.h:37
map< string, tree_item > tree_map
Definition: detector_tree.h:60
QBrush ActiveBrush
Definition: detector_tree.h:69
QBrush SensitiveBrush
Definition: detector_tree.h:70
QBrush NonVisibleBrush
Definition: detector_tree.h:72
map< string, G4Material * > MMats
Definition: detector_tree.h:62
QLinearGradient NonVisibleGrad
Definition: detector_tree.h:67
map< string, aopt > optMap
Options map.
Definition: options.h:75
QPushButton * showDetInNewWindow
Definition: detector_tree.h:76
string qs_tostring(QString input)
map< string, detector > * Hall_Map
Definition: detector_tree.h:58
G4VPhysicalVolume * GetPhysical()
Returns Physical Volume pointer.
Definition: detector.h:114
QLinearGradient SensitiveGrad
Definition: detector_tree.h:65
string mother
Definition: detector_tree.h:36
QLinearGradient ActiveGrad
Definition: detector_tree.h:64