Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
hd_geom_query.cc
Go to the documentation of this file.
1 
2 #include <stdlib.h>
3 #include <dlfcn.h>
4 #include <unistd.h>
5 
6 #include <iostream>
7 #include <fstream>
8 #include <string>
9 using namespace std;
10 
11 #include <TGeoManager.h>
12 #include <TGeoVolume.h>
13 #include <TGeoMaterial.h>
14 #include <TGeoMedium.h>
15 #include <TGeoPcon.h>
16 #include <TGeoPgon.h>
17 #include <TGeoMatrix.h>
18 
19 #include <DANA/DApplication.h>
20 
21 //#include <hddsroot.h>
22 
23 extern TGeoManager * hddsroot();
24 extern const char* md5geom(void);
25 
26 void Usage(void);
27 void ParseCommandLineArguments(int narg, char *argv[]);
28 
29 bool USE_XML = false;
30 bool SHOW_ANCESTORY=true;
31 bool SHOW_CCDB = true;
32 double X_LAB = 20.0;
33 double Y_LAB = 20.0;
34 double Z_LAB = 650.0;
35 int32_t RUN_NUMBER = 30000;
36 
37 static void *dlgeom_handle=NULL;
38 string HDDS_XML = "$HDDS_HOME/main_HDDS.xml";
39 
40 void init_runtime_xml(void);
41 void MakeSharedObjectFromXML(void);
42 TGeoManager* hddsroot_runtime(void);
43 const char* GetMD5Geom(void);
44 const char* md5geom_runtime(void);
45 const char* md5geom_xml(void);
46 
47 //------------------
48 // main
49 //------------------
50 int main(int narg, char *argv[])
51 {
52 
53  ParseCommandLineArguments(narg, argv);
54 
55  double pos[3];
56  pos[0] = X_LAB;
57  pos[1] = Y_LAB;
58  pos[2] = Z_LAB;
59 
60  if(!gGeoManager){
61  new TGeoManager();
62  cout<<"Created TGeoManager :"<<gGeoManager<<endl;
63  }
64 
65  TGeoManager *DRGeom = NULL;
66  if(USE_XML){
67  DRGeom = hddsroot_runtime();
68  }else{
69  DRGeom = hddsroot();
70  }
71  if(!DRGeom){
72  cerr<<"Can't get TGeoManager object!"<<endl;
73  return -2;
74  }
75 
76  TGeoNode *cnode = DRGeom->FindNode(X_LAB, Y_LAB, Z_LAB);
77  if(!cnode){
78  cerr<<"Can't get node object from TGeoManager!"<<endl;
79  return -2;
80  }
81 
82  TGeoVolume *vol = cnode->GetVolume();
83  if(!vol){
84  cerr<<"Can't get volume object from TGeoNode!"<<endl;
85  return -2;
86  }
87 
88  TGeoMaterial *mat = vol->GetMedium()->GetMaterial();
89  if(!mat){
90  cerr<<"Can't get material object from TGeoVolume!"<<endl;
91  return -3;
92  }
93 
94  DGeometry *geom = NULL;
95  if(SHOW_CCDB){
96  DApplication *dapp = new DApplication(narg, argv);
97  geom = dapp->GetDGeometry(RUN_NUMBER);
98  }
99 
100  cout<<endl;
101  cout<<"Ignore above ROOT errors they are \"normal\" ;)" << endl;
102  cout<<endl;
103 
104  double density=mat->GetDensity();
105  double RadLen=mat->GetRadLen();
106  double A=mat->GetA();
107  double Z=mat->GetZ();
108 
109  cout<<endl;
110  cout<<" Location: (X, Y, Z) = ("<<X_LAB<<", "<<Y_LAB<<", "<<Z_LAB<<")"<<endl;
111  cout<<"==============================================="<<endl;
112  cout<<" Volume: "<<vol->GetName()<<endl;
113  cout<<" material: "<<mat->GetName()<<endl;
114  cout<<" density: "<<density<<" g/cm^3"<<endl;
115  cout<<"rad. length: "<<RadLen<<" cm"<<endl;
116  cout<<" A: "<<A<<endl;
117  cout<<" Z: "<<Z<<endl;
118 
119  if(SHOW_ANCESTORY){
120 
121  gGeoManager->GetCurrentNavigator()->SetCurrentPoint(pos);
122  cout<<" ancestory: ";
123 
124  for(int i=0; i<1000; i++){
125  TGeoNode *node = gGeoManager->GetCurrentNavigator()->GetMother(i);
126  if(!node)break;
127  if(i>0) cout << " -> ";
128  cout << node->GetVolume()->GetName();
129  }
130  cout<<endl;
131  }
132 
133  // Optionally get info from material maps in CCDB and print
134  if(SHOW_CCDB){
135  DVector3 pos(X_LAB, Y_LAB, Z_LAB);
136  const DMaterialMap *map = geom->FindDMaterialMap(pos);
137  cout << endl;
138  if(!map){
139  cerr << "Unable to find material map in CCDB corresponding to this point" << endl;
140  }else{
141  const DMaterialMap::MaterialNode *node = map->FindNode(pos);
142 
143  // Some maps have numbers very close to, but not quite
144  // zero fro rmin. For purposes of display, call anything
145  // within 1 um of r=0 to be actually at r=0
146  double rmin = map->GetRmin();
147  if( fabs(rmin) < 1.0E-6) rmin = 0.0;
148 
149  cout << "Material map info from CCDB for run " << RUN_NUMBER << endl;
150  cout<<"==============================================="<<endl;
151  cout << " namepath: " << map->GetNamepath() << endl;
152  cout << "R range (cm): " << rmin << " - " << map->GetRmax() << endl;
153  cout << "Z range (cm): " << map->GetZmin() << " - " << map->GetZmax() << endl;
154  cout << " density: " << node->Density <<" g/cm^3"<< endl;
155  cout << " rad. length: " << node->RadLen <<" cm"<< endl;
156  cout << " A: " << node->A << endl;
157  cout << " Z: " << node->Z << endl;
158  }
159  }
160 
161  cout << endl;
162 
163  return 0;
164 }
165 
166 
167 //------------------
168 // init_runtime_xml
169 //------------------
171 {
172  cout<<endl;
173  cout<<"=============================================================="<<endl;
174  cout<<"Enabling dynamic geometry rendering"<<endl;
175  cout<<"- - - - - - - - - - - - - - - - - - -"<<endl;
176  cout<<endl;
177 
178  // Check if a shared object file already exists and
179  // if we can attach it. Do this by trying to get the
180  // md5 checksum from it. If we succeed, get the md5
181  // checksum for the XML so they can be compared
182  string fname = "./tmp_hddsroot.so";
183  string md5_shared = "";
184  string md5_xml = "";
185  void *handle = dlopen(fname.c_str(), RTLD_NOW | RTLD_GLOBAL);
186  if(handle){
187  const char* (*md5geom_ext)(void);
188  *(void **) (&md5geom_ext) = dlsym(handle, "md5geom_ext");
189  char *err = dlerror();
190  if(err == NULL){
191  md5_shared = (*md5geom_ext)();
192  md5_xml = md5geom_xml();
193  }
194  dlclose(handle);
195  }
196 
197  // Regenerate shared object if needed
198  if(md5_shared.length()>0){
199  cout<<"found existing shared object"<<endl;
200  cout<<" shared object checksum: "<<md5_shared<<endl;
201  cout<<" xml checksum: "<<md5_xml<<endl;
202  if(md5_shared != md5_xml){
203  cout<<"Checksums don't match. Shared object will be regenerated."<<endl;
205  }
206  }else{
208  }
209 
210  // Attach shared object
211  cout<<endl;
212  cout << "Attaching shared object ..." << endl;
213  handle = dlopen(fname.c_str(), RTLD_NOW | RTLD_GLOBAL);
214  if(!handle){
215  cerr<<"Unable to open \""<<fname<<"\"!"<<endl;
216  cerr<<dlerror()<<endl;
217  exit(-1);
218  }
219 
220  // Copy handle to global variable
221  dlgeom_handle = handle;
222 
223  // do not close shared object since it may contain needed routines
224  //dlclose(dlgeom_handle);
225 }
226 
227 //------------------
228 // MakeSharedObjectFromXML
229 //------------------
231 {
232  cout<<"Please make sure root-config is in your PATH and that"<<endl;
233  cout<<"the following environment variables are set:" <<endl;
234  cout<<" HDDS_HOME "<< endl;
235  cout<<" BMS_OSNAME "<< endl;
236 
237  // Open temporary file and add some includes so it will compile
238  ofstream ofs("tmp_hddsroot.cc");
239  ofs << "#include <TSystem.h>"<<endl;
240  ofs << "#include <TGeoManager.h>"<<endl;
241  ofs << "#include <TGeoVolume.h>"<<endl;
242  ofs << "#include <TGeoMaterial.h>"<<endl;
243  ofs << "#include <TGeoMedium.h>"<<endl;
244  ofs << "#include <TGeoPcon.h>"<<endl;
245  ofs << "#include <TGeoPgon.h>"<<endl;
246  ofs << "#include <TGeoMatrix.h>"<<endl;
247  ofs << "extern \"C\" {"<<endl;
248  ofs << "TGeoManager* hddsroot(void);"<<endl;
249  ofs.close();
250 
251  // Generate C++ code from XML
252  cout<<endl;
253  cout << "Generating C++ from XML source ...." << endl;
254  string cmd = "$HDDS_HOME/$BMS_OSNAME/bin/hdds-root_h " + HDDS_XML + " >> tmp_hddsroot.cc";
255  cout << cmd << endl;
256  int err = system(cmd.c_str());
257  if(err!=0){ cerr << "Error running \""<< cmd << "\"" << endl; exit(-1); }
258 
259  // Close off file with externally accessible md5geom wrapper
260  ofs.open("tmp_hddsroot.cc", ios_base::app);
261  ofs << "const char* md5geom_ext(void){return md5geom();}"<<endl;
262  ofs << "}"<<endl; // close off extern "C"
263  ofs.close();
264 
265  // Compile C++ into shared object
266  cout<<endl;
267  cout << "Compiling C++ into shared object ..." << endl;
268  cmd = "c++ -shared -fPIC -o tmp_hddsroot.so `root-config --cflags --libs` -lGeom tmp_hddsroot.cc";
269  cout << cmd << endl;
270  err = system(cmd.c_str());
271  if(err!=0){ cerr << "Error running \""<< cmd << "\"" << endl; exit(-1); }
272 
273  // Remove temporary C++ source file
274  unlink("./tmp_hddsroot.cc");
275 }
276 
277 //------------------
278 // hddsroot_runtime
279 //------------------
280 TGeoManager* hddsroot_runtime(void)
281 {
282  // This should only be called if the user specifies the
283  // "-xml" command line switch. Otherwise, the built-in
284  // geometry is used.
285 
286  // Create, compile and link shared object. That part is done
287  // in a separate routine so md5geom_runtime() can use it too.
289 
290  // Find hddsroot symbol inside shared object
291  cout<<endl;
292  cout << "Locating geometry ... " << endl;
293  TGeoManager* (*my_hddsroot)(void);
294  *(void **) (&my_hddsroot) = dlsym(dlgeom_handle, "hddsroot");
295  char *err = dlerror();
296  if(err != NULL){
297  cerr << err << endl;
298  exit(-1);
299  }
300 
301  // Execute my_hddsroot
302  cout<<endl;
303  cout << "Loading geometry ... " << endl;
304  TGeoManager *geo = (*my_hddsroot)();
305 
306  cout<<endl;
307  cout << "Geometry loaded successfully" << endl;
308  cout<<"=============================================================="<<endl;
309 
310  return geo;
311 }
312 
313 //------------------
314 // md5geom_runtime
315 //------------------
316 const char* md5geom_runtime(void)
317 {
318  // This will extract the MD5 checksum of the
319  // geometry from the dynamically linked shared
320  // object. It is called from the GetMD5Geom()
321  // routine below. Use that routine to get the
322  // checksum, not this one.
323 
324  // Create, compile and link shared object if needed.
326 
327  // Grab md5geom routine from shared object
328  const char* (*md5geom_ext)(void);
329  *(void **) (&md5geom_ext) = dlsym(dlgeom_handle, "md5geom_ext");
330  char *err = dlerror();
331  if(err != NULL){
332  cerr << err << endl;
333  exit(-1);
334  }
335 
336  // Execute my_md5geom_
337  return (*md5geom_ext)();
338 }
339 
340 //------------------
341 // md5geom_xml
342 //------------------
343 const char* md5geom_xml(void)
344 {
345  /// This will get the checksum from the XML directly by
346  /// running the hdds-md5 program and parsing the output.
347  static string md5_xml="";
348  string fname = "tmp_hddsroot.md5";
349  string cmd = "$HDDS_HOME/$BMS_OSNAME/bin/hdds-md5 " + HDDS_XML + " > " + fname;
350  int err = system(cmd.c_str());
351  if(err!=0){ cerr << "Error running \""<< cmd << "\"" << endl; exit(-1); }
352  ifstream ifs(fname.c_str());
353  if(ifs.is_open()){
354  string str;
355  while(ifs.good())ifs >> str;
356  if(str.length()>=32)md5_xml = str.substr(str.length()-32);
357  ifs.close();
358  }
359  unlink(fname.c_str());
360 
361  return md5_xml.c_str();
362 }
363 
364 
365 //------------------
366 // GetMD5Geom
367 //------------------
368 const char* GetMD5Geom(void)
369 {
370  // Get the MD5 checksum of the geometry that will be
371  // used for the simulation. This will retrieve the
372  // geometry checksum from either what has been statically
373  // linked in, or dynamically, whichever is being used.
374 
375  if(USE_XML){
376  // Grab version from shared object
377  return md5geom_runtime();
378  }else{
379  // Use compiled in version
380  return md5geom();
381  }
382 
383  return NULL;
384 }
385 
386 //------------------
387 // ParseCommandLineArguments
388 //------------------
389 void ParseCommandLineArguments(int narg, char *argv[])
390 {
391  vector<double> vals;
392  bool print_xml_md5_checksum = false;
393 
394  for(int i=1; i<narg; i++){
395 
396  if(argv[i][0]=='-'){
397  string arg(argv[i]);
398  string next = (i+1)<narg ? (const char*)argv[i+1]:"";
399  if(arg=="-h" || arg=="--help")Usage();
400 
401  if(arg=="-checksum" || arg=="--checksum")print_xml_md5_checksum = true;
402  if(arg.find("-xml")==0){
403  USE_XML = true;
404  if(arg.find("=")!=string::npos){
405  HDDS_XML = arg.substr(arg.find("=")+1);
406  }
407  }
408  if( arg=="-r" && next.length()>0 ){
409  RUN_NUMBER = atoi(next.c_str());
410  i++;
411  }
412  }else{
413  vals.push_back(atof(argv[i]));
414  }
415  }
416 
417  // If user specified printing the checksum then
418  // do that and quit
419  if(print_xml_md5_checksum){
420  string checksum = GetMD5Geom();
421  cout << "HDDS Geometry MD5 Checksum: " << checksum << endl;
422  exit(0);
423  }
424 
425  // Copy user-given coordinates to global variables
426  if(vals.size() != 3)Usage();
427  X_LAB = vals[0];
428  Y_LAB = vals[1];
429  Z_LAB = vals[2];
430 }
431 
432 //------------------
433 // Usage
434 //------------------
435 void Usage(void)
436 {
437  cout<<endl;
438  cout<<"Usage:"<<endl;
439  cout<<" hd_geom_query [options] X Y Z"<<endl;
440  cout<<endl;
441  cout<<"Print the material properties for the specified point in lab"<<endl;
442  cout<<" coordinates. Units of X,Y, and Z are cm."<<endl;
443  cout<<endl;
444  cout<<"By default, this uses the geometry in $HDDS/src/hddsroot.h"<<endl;
445  cout<<"that was used to link this executable. The -xml switch may be used"<<endl;
446  cout<<"to dynamically compile and link code generated from the XML at run"<<endl;
447  cout<<"time. If an equals sign \"=\" follows the -xml switch then the"<<endl;
448  cout<<"main_HDDS.xml file is taken from the remainder of that argument."<<endl;
449  cout<<endl;
450  cout<<"If the -xml switch is specified, then a file named \"tmp_hddsroot.so\""<<endl;
451  cout<<"is searched for in the current directory. If found, it is opened and"<<endl;
452  cout<<"the geometry checksum is read from it and compared to that of the XML"<<endl;
453  cout<<"specified (which may be the default of $HDDS_HOME/main_HDDS.xml)."<<endl;
454  cout<<"If the two match, then that shared object is used, bypassing the"<<endl;
455  cout<<"(expensive) compilation phase. If the file is not present, is unreadable,"<<endl;
456  cout<<"or the checksums don't match, then the shared object is automatically"<<endl;
457  cout<<"(re)generated."<<endl;
458  cout<<endl;
459  cout<<"Information from the CCDB hosted material map will also be printed."<<endl;
460  cout<<"This map is used by the track reconstruction software. It is derived"<<endl;
461  cout<<"from the same ROOT geometry classes used for the above. Keep in mind"<<endl;
462  cout<<"though that the CCDB material maps are maintained by a human regenerating"<<endl;
463  cout<<"the maps and committing them to CCDB. i.e. they are not updated automatically."<<endl;
464  cout<<"One can specify the run number used to index the CCDB via the -r run"<<endl;
465  cout<<"command line option. The location of the CCDB and variation are set by"<<endl;
466  cout<<"the standard environment variables."<<endl;
467  cout<<""<<endl;
468  cout<<endl;
469  cout<<" options:"<<endl;
470  cout<<" -h or --help Print this usage statement"<<endl;
471  cout<<" -xml[=main_HDDS.xml] Dynamically generate geometry"<<endl;
472  cout<<" -checksum Print the MD5 checksum of the "<<endl;
473  cout<<" geometry and exit"<<endl;
474  cout<<" -r run Set run number used for CCDB query"<<endl;
475  cout<<endl;
476  cout<<"If the -xml option is given and no file is specified,"<<endl;
477  cout<<"then a value of: "<<HDDS_XML<<endl;
478  cout<<"is used."<<endl;
479  cout<<endl;
480 
481  exit(0);
482 }
483 
484 
DApplication * dapp
const char * md5geom_runtime(void)
double GetZmin(void) const
Definition: DMaterialMap.h:57
char str[256]
TVector3 DVector3
Definition: DVector3.h:14
TGeoManager * hddsroot()
double rmin
void MakeSharedObjectFromXML(void)
const char * md5geom(void)
const char * GetMD5Geom(void)
void ParseCommandLineArguments(int &narg, char *argv[])
Definition: hd_dump.cc:124
DGeometry * GetDGeometry(unsigned int run_number)
string HDDS_XML
TGeoManager * hddsroot_runtime(void)
double X_LAB
double GetZmax(void) const
Definition: DMaterialMap.h:58
double Y_LAB
const char * md5geom_xml(void)
double Z_LAB
static unsigned int RUN_NUMBER
Definition: mc2coda.c:24
double GetRmin(void) const
Definition: DMaterialMap.h:55
static void * dlgeom_handle
const MaterialNode * FindNode(const DVector3 &pos) const
Definition: DMaterialMap.h:92
double GetRmax(void) const
Definition: DMaterialMap.h:56
bool SHOW_CCDB
string GetNamepath(void) const
Definition: DMaterialMap.h:54
void Usage(JApplication &app)
Definition: hd_ana.cc:33
bool SHOW_ANCESTORY
int main(int argc, char *argv[])
Definition: gendoc.cc:6
const DMaterialMap * FindDMaterialMap(DVector3 &pos) const
Definition: DGeometry.cc:363
void init_runtime_xml(void)
bool USE_XML