Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DRootGeom.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DRootGeom.h
4 // Created: Fri Feb 13 08:43:39 EST 2009
5 // Creator: zihlmann
6 //
7 
8 #include "DRootGeom.h"
9 #include "hddsroot.h"
10 
11 using namespace std;
12 
13 
14 //---------------------------------
15 // DRootGeom (Constructor)
16 //---------------------------------
17 DRootGeom::DRootGeom(JApplication *japp, unsigned int run_number)
18 {
19  pthread_mutexattr_init(&mutex_attr);
20  pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
21  pthread_mutex_init(&mutex, &mutex_attr);
22 
23  table_initialized = false;
24  DRGeom = NULL;
25 
26  jcalib = japp->GetJCalibration(run_number);
27  if(!jcalib){
28  _DBG_<<"Unable to get JCalibration object!"<<endl;
29  exit(-1);
30  }
31 
32  JParameterManager *jparms = japp->GetJParameterManager();
33  if(!jparms){
34  _DBG_<<"Unable to get JParameterManager object!"<<endl;
35  exit(-1);
36  }
37 
38 }
39 
40 //---------------------------------
41 // DRootGeom (Destructor)
42 //---------------------------------
44 {
45  if(DRGeom != NULL)
46  delete DRGeom;
47 }
48 
49 //---------------------------------
50 // ReadMap
51 //---------------------------------
52 int DRootGeom::ReadMap(string namepath, int32_t runnumber)
53 {
54  /// Read the magnetic field map in from the calibration database.
55  /// This will read in the map and figure out the number of grid
56  /// points in each direction (x,y, and z) and the range in each.
57  /// The gradiant of the field is calculated for all but the most
58  /// exterior points and saved to use in later calls to GetField(...).
59 
60  // Read in map from calibration database. This should really be
61  // built into a run-dependent geometry framework, but for now
62  // we do it this way.
63  if(!jcalib)return 0;
64 
65  cout<<"Reading Material map from "<<namepath<<" ..."<<endl;
66  vector< vector<float> > Mmap;
67  jcalib->Get(namepath, Mmap);
68  cout<<Mmap.size()<<" entries found (";
69  if(Mmap.size()<1){
70  cout<<")"<<endl;
71  return Mmap.size();
72  }
73 
74  // The map should be on a grid with equal spacing in r, and z.
75  // Here we want to determine the number of points in each of these
76  // dimensions and the range.
77  // The easiest way to do this is to use a map<float, int> to make a
78  // histogram of the entries by using the key to hold the extent
79  // so that the number of entries will be equal to the number of
80  // different values.
81  map<float, int> rvals;
82  map<float, int> zvals;
83  double rmin, zmin, rmax, zmax;
84  rmin = zmin = 1.0E6;
85  rmax = zmax = -1.0E6;
86  for(unsigned int i=0; i<Mmap.size(); i++){
87  vector<float> &a = Mmap[i];
88  float &r = a[0];
89  float &z = a[1];
90 
91  rvals[r] = 1;
92  zvals[z] = 1;
93  if(r<rmin)rmin=r;
94  if(z<zmin)zmin=z;
95  if(r>rmax)rmax=r;
96  if(z>zmax)zmax=z;
97  }
98  Nr = rvals.size();
99  Nz = zvals.size();
100  r0 = rmin;
101  z0 = zmin;
102  dr = (rmax-rmin)/(double)(Nr-1);
103  dz = (zmax-zmin)/(double)(Nz-1);
104  cout<<" Nr="<<Nr;
105  cout<<" Nz="<<Nz;
106  cout<<" ) at 0x"<<hex<<(unsigned long)this<<dec<<endl;
107 
108  // Create 2D array to hold table in class
109  MatTable = new VolMat*[Nr];
110  buff = new VolMat[Nr*Nz];
111  for(int ir=0; ir<Nr; ir++){
112  MatTable[ir]=&buff[ir*Nz];
113  }
114 
115  // Fill table
116  for(unsigned int i=0; i<Mmap.size(); i++){
117  vector<float> &a = Mmap[i];
118  float &r = a[0];
119  float &z = a[1];
120  int ir = (int)floor((r - r0)/dr);
121  int iz = (int)floor((z - z0)/dz);
122  if(ir<0 || ir>=Nr){_DBG_<<"ir out of range: ir="<<ir<<" Nr="<<Nr<<endl; continue;}
123  if(iz<0 || iz>=Nz){_DBG_<<"iz out of range: iz="<<iz<<" Nz="<<Nz<<endl; continue;}
124  VolMat &mat = MatTable[ir][iz];
125  mat.A = a[2];
126  mat.Z = a[3];
127  mat.Density = a[4];
128  mat.RadLen = a[5];
129  mat.rhoZ_overA = a[6];
130  mat.rhoZ_overA_logI = a[7];
131  }
132 
133 
134  return Mmap.size();
135 }
136 
137 //---------------------------------
138 // InitTable
139 //---------------------------------
141 {
142  pthread_mutex_lock(&mutex);
143 
144  if(table_initialized){
145  // Don't initialize table twice!
146  pthread_mutex_unlock(&mutex);
147  return;
148  }
149 
150  // Fill average materials table
151  cout<<"Filling material table"; cout.flush();
152  Nr = 125;
153  Nz = 750;
154  double rmin = 0.0;
155  double rmax = 125.0;
156  double zmin = -100.0;
157  double zmax = 650.0;
158  r0 = rmin;
159  z0 = zmin;
160  dr = (rmax-rmin)/(double)Nr;
161  dz = (zmax-zmin)/(double)Nz;
162  MatTable = new VolMat*[Nr];
163  buff = new VolMat[Nr*Nz];
164  for(int ir=0; ir<Nr; ir++){
165  double r = r0 + (double)ir*dr;
166  MatTable[ir]=&buff[ir*Nz];
167  for(int iz=0; iz<Nz; iz++){
168  double z = z0 + (double)iz*dz;
169 
170  // Loop over points in phi, r, and z and add up material
171  int n_r = 3;
172  int n_z = 2;
173  int n_phi = 20;
174  double d_r = dr/(double)n_r;
175  double d_z = dz/(double)n_z;
176  double d_phi = 2.0*M_PI/(double)n_phi;
177  VolMat avg_mat={0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
178 
179  for(int i_r=0; i_r<n_r; i_r++){
180  double my_r = r - dr/2.0 + (double)i_r*d_r;
181  for(int i_z=0; i_z<n_z; i_z++){
182  double my_z = z - dz/2.0 + (double)i_z*d_z;
183  for(int i_phi=0; i_phi<n_phi; i_phi++){
184  double my_phi = (double)i_phi*d_phi;
185 
186  DVector3 pos(my_r*cos(my_phi), my_r*sin(my_phi), my_z);
187  double A, Z, density, radlen,LnI;
188 
189  FindMatLL(pos, density, A, Z, radlen,LnI);
190 
191  double rhoZ_overA = density*Z/A;
192  double rhoZ_overA_logI = rhoZ_overA*LnI;
193 
194  avg_mat.A += A;
195  avg_mat.Z += Z;
196  avg_mat.Density += density;
197  avg_mat.RadLen += radlen;
198  avg_mat.rhoZ_overA += rhoZ_overA;
199  avg_mat.rhoZ_overA_logI += rhoZ_overA_logI;
200  }
201  }
202  }
203 
204  // Divide by number of points to get averages
205  avg_mat.A /= (double)(n_r*n_z*n_phi);
206  avg_mat.Z /= (double)(n_r*n_z*n_phi);
207  avg_mat.Density /= (double)(n_r*n_z*n_phi);
208  avg_mat.RadLen /= (double)(n_r*n_z*n_phi);
209  avg_mat.rhoZ_overA /= (double)(n_r*n_z*n_phi);
210  avg_mat.rhoZ_overA_logI /= (double)(n_r*n_z*n_phi);
211 
212  MatTable[ir][iz] = avg_mat;
213  }
214  cout<<"\r Filling Material table ... "<<100.0*(double)ir/(double)Nr<<"% ";cout.flush();
215  }
216  cout <<"Done"<<endl;
217 
218  table_initialized=true;
219  pthread_mutex_unlock(&mutex);
220 }
221 
222 //---------------------------------
223 // InitDRGeom
224 //---------------------------------
226 {
227  if(!gGeoManager){
228 
229 // If ROOT_MAJOR is not defined, then define it as the minimal
230 // needed to create a TGeoManager. Most folks should have at least
231 // 5.28 by now.
232 #ifndef ROOT_MAJOR
233 #define ROOT_MAJOR 5
234 #define ROOT_MINOR 28
235 #endif
236 
237 #if ROOT_MAJOR>=5 && ROOT_MINOR>=28
238  new TGeoManager();
239  cout<<"Created TGeoManager :"<<gGeoManager<<endl;
240 #else
241  cout<<"Skipping explicit TGeoManager creation due to ROOT ver. < 5.28"<<endl;
242 #endif
243  }
244  DRGeom = hddsroot();
245 }
246 
247 //---------------------------------
248 // FindNode
249 //---------------------------------
250 TGeoNode* DRootGeom::FindNode(double *x)
251 {
252  pthread_mutex_lock(&mutex);
253 
254  if(!DRGeom)InitDRGeom();
255 
256  TGeoNode *cnode = DRGeom->FindNode(x[0],x[1],x[2]);
257 
258  pthread_mutex_unlock(&mutex);
259 
260  return cnode;
261 
262 }
263 
264 //---------------------------------
265 // FindVolume
266 //---------------------------------
267 TGeoVolume* DRootGeom::FindVolume(double *x)
268 {
269 
270  pthread_mutex_lock(&mutex);
271  if(!DRGeom)InitDRGeom();
272  TGeoNode *cnode = DRGeom->FindNode(x[0],x[1],x[2]);
273  TGeoVolume *cvol = cnode->GetVolume();
274  pthread_mutex_unlock(&mutex);
275 
276  return cvol;
277 
278 }
279 
280 //---------------------------------
281 // FindMat
282 //---------------------------------
283 jerror_t DRootGeom::FindMat(DVector3 pos, double &density, double &A, double &Z, double &RadLen) const
284 {
285  return FindMatLL(pos, density, A, Z, RadLen);
286 }
287 
288 //---------------------------------
289 // FindMat
290 //---------------------------------
291 jerror_t DRootGeom::FindMat(DVector3 pos, double &rhoZ_overA, double &rhoZ_overA_logI, double &RadLen) const
292 {
293  return FindMatTable(pos, rhoZ_overA, rhoZ_overA_logI, RadLen);
294 }
295 
296 //---------------------------------
297 // FindMatTable
298 //---------------------------------
299 jerror_t DRootGeom::FindMatTable(DVector3 pos,double &density, double &A, double &Z, double &RadLen) const
300 {
301  if(!table_initialized)((DRootGeom*)this)->InitTable();
302 
303  // For now, this just finds the bin in the material map the given position is in
304  // (i.e. no interpolation )
305  double r = pos.Perp();
306  double z = pos.Z();
307  int ir = (int)floor((r-r0)/dr);
308  int iz = (int)floor((z-z0)/dz);
309  if(ir<0 || ir>=Nr || iz<0 || iz>=Nz){
310  A = Z = density = RadLen = 0.0;
311  return RESOURCE_UNAVAILABLE;
312  }
313 
314  const VolMat &mat = MatTable[ir][iz];
315  A = mat.A;
316  Z = mat.Z;
317  density = mat.Density;
318  RadLen = mat.RadLen;
319 
320  return NOERROR;
321 }
322 
323 
324 //---------------------------------
325 // FindMatTable
326 //---------------------------------
327 jerror_t DRootGeom::FindMatTable(DVector3 pos, double &rhoZ_overA, double &rhoZ_overA_logI, double &RadLen) const
328 {
329  if(!table_initialized)((DRootGeom*)this)->InitTable();
330 
331  // For now, this just finds the bin in the material map the given position is in
332  // (i.e. no interpolation )
333  double r = pos.Perp();
334  double z = pos.Z();
335  int ir = (int)floor((r-r0)/dr);
336  int iz = (int)floor((z-z0)/dz);
337  if(ir<0 || ir>=Nr || iz<0 || iz>=Nz){
338  rhoZ_overA = rhoZ_overA_logI = RadLen = 0.0;
339  return RESOURCE_UNAVAILABLE;
340  }
341 
342  const VolMat &mat = MatTable[ir][iz];
343  rhoZ_overA = mat.rhoZ_overA;
344  rhoZ_overA_logI = mat.rhoZ_overA_logI;
345  RadLen = mat.RadLen;
346 
347  return NOERROR;
348 }
349 
350 // Find material properties by material name
351 jerror_t DRootGeom::FindMat(const char* matname,double &rhoZ_overA,
352  double &rhoZ_overA_logI, double &RadLen) const{
353  pthread_mutex_lock(const_cast<pthread_mutex_t*>(&mutex));
354 
355  if(!DRGeom)((DRootGeom*)this)->InitDRGeom(); // cast away constness to ensure DRGeom is set
356 
357  TGeoMaterial *mat=DRGeom->GetMaterial(matname);
358  if (mat==NULL){
359  _DBG_<<"Missing material " << matname <<endl;
360  pthread_mutex_unlock(const_cast<pthread_mutex_t*>(&mutex));
361  return RESOURCE_UNAVAILABLE;
362  }
363  double A=mat->GetA();
364  double Z=mat->GetZ();
365  double density=mat->GetDensity();
366  rhoZ_overA=density*Z/A;
367  RadLen=mat->GetRadLen();
368 
369  // Get mean excitation energy. For a mixture this is calculated according
370  // to Leo 2nd ed p 29 eq 2.42
371  double LnI=0.;
372  if (mat->IsMixture()) {
373  const TGeoMixture * mixt = dynamic_cast <const TGeoMixture*> (mat);
374  for (int i=0;i<mixt->GetNelements();i++){
375  double w_i=mixt->GetWmixt()[i];
376  double Z_i=mixt->GetZmixt()[i];
377  // Mean excitation energy for the element; see Leo 2nd ed., p25
378  double I_i=7.0+12.0*Z_i; //eV
379  if (Z_i>=13) I_i=9.76*Z_i+58.8*pow(Z_i,-0.19);
380  I_i*=1e-9; // convert to GeV
381  LnI+=w_i*Z_i*log(I_i)/Z;
382  }
383  }
384  else{
385  // mean excitation energy for the element
386  double I=7.0+12.0*Z; //eV
387  if (Z>=13) I=9.76*Z+58.8*pow(Z,-0.19);
388  I*=1e-9; // Convert to GeV
389  LnI=log(I);
390  }
391  rhoZ_overA_logI=rhoZ_overA*LnI;
392 
393  pthread_mutex_unlock(const_cast<pthread_mutex_t*>(&mutex));
394 
395  return NOERROR;
396 }
397 
398 
399 //---------------------------------
400 // FindMatLL
401 //---------------------------------
402 jerror_t DRootGeom::FindMatLL(DVector3 pos, double &rhoZ_overA, double &rhoZ_overA_logI, double &RadLen) const
403 {
404  /// This is a wrapper for the other FindMatLL method that returns density, A, and Z.
405  /// It is here to make easy comparisons between the LL and table methods.
406 
407  double density, A, Z,LnI;
408  FindMatLL(pos, density, A, Z, RadLen,LnI);
409  rhoZ_overA = density*Z/A;
410  rhoZ_overA_logI = rhoZ_overA*LnI;
411 
412  return NOERROR;
413 }
414 
415 //---------------------------------
416 // FindMatLL
417 //---------------------------------
418 jerror_t DRootGeom::FindMatLL(DVector3 pos,double &density, double &A, double &Z,
419  double &RadLen) const{
420  density=RadLen=A=Z=0.;
421 
422  pthread_mutex_lock(const_cast<pthread_mutex_t*>(&mutex));
423 
424  if(!DRGeom)((DRootGeom*)this)->InitDRGeom(); // cast away constness to ensure DRGeom is set
425 
426  TGeoNode *cnode = DRGeom->FindNode(pos.X(),pos.Y(),pos.Z());
427  if (cnode==NULL){
428  _DBG_<<"Missing cnode at position (" <<pos.X()<<","<<pos.Y()<<","
429  <<pos.Z()<<")"<<endl;
430  pthread_mutex_unlock(const_cast<pthread_mutex_t*>(&mutex));
431  return RESOURCE_UNAVAILABLE;
432  }
433  TGeoVolume *cvol = cnode->GetVolume();
434  if (cvol==NULL){
435  _DBG_<<"Missing cvol" <<endl;
436  pthread_mutex_unlock(const_cast<pthread_mutex_t*>(&mutex));
437  return RESOURCE_UNAVAILABLE;
438  }
439  TGeoMaterial *cmat = cvol->GetMedium()->GetMaterial();
440 
441  density=cmat->GetDensity();
442  RadLen=cmat->GetRadLen();
443  A=cmat->GetA();
444  Z=cmat->GetZ();
445  if (A<1.){ // try to prevent division by zero problems
446  A=1.;
447  }
448  pthread_mutex_unlock(const_cast<pthread_mutex_t*>(&mutex));
449 
450  return NOERROR;
451 }
452 
453 //---------------------------------
454 // FindMatLL
455 //---------------------------------
456 jerror_t DRootGeom::FindMatLL(DVector3 pos,double &density, double &A, double &Z,
457  double &RadLen, double &LnI
458  ) const{
459  density=RadLen=A=Z=LnI=0.;
460 
461  pthread_mutex_lock(const_cast<pthread_mutex_t*>(&mutex));
462 
463  if(!DRGeom)((DRootGeom*)this)->InitDRGeom(); // cast away constness to ensure DRGeom is set
464 
465  TGeoNode *cnode = DRGeom->FindNode(pos.X(),pos.Y(),pos.Z());
466  if (cnode==NULL){
467  _DBG_<<"Missing cnode at position (" <<pos.X()<<","<<pos.Y()<<","
468  <<pos.Z()<<")"<<endl;
469  pthread_mutex_unlock(const_cast<pthread_mutex_t*>(&mutex));
470  return RESOURCE_UNAVAILABLE;
471  }
472  TGeoVolume *cvol = cnode->GetVolume();
473  if (cvol==NULL){
474  _DBG_<<"Missing cvol" <<endl;
475  pthread_mutex_unlock(const_cast<pthread_mutex_t*>(&mutex));
476  return RESOURCE_UNAVAILABLE;
477  }
478  TGeoMaterial *cmat = cvol->GetMedium()->GetMaterial();
479  density=cmat->GetDensity();
480  RadLen=cmat->GetRadLen();
481  A=cmat->GetA();
482  Z=cmat->GetZ();
483  if (A<1.){ // try to prevent division by zero problems
484  A=1.;
485  }
486 
487  // Get mean excitation energy. For a mixture this is calculated according
488  // to Leo 2nd ed p 29 eq 2.42
489  if (cmat->IsMixture()) {
490  const TGeoMixture * mixt = dynamic_cast <const TGeoMixture*> (cmat);
491  LnI=0.;
492  for (int i=0;i<mixt->GetNelements();i++){
493  double w_i=mixt->GetWmixt()[i];
494  double Z_i=mixt->GetZmixt()[i];
495  // Mean excitation energy for the element; see Leo 2nd ed., p25
496  double I_i=7.0+12.0*Z_i; //eV
497  if (Z_i>=13) I_i=9.76*Z_i+58.8*pow(Z_i,-0.19);
498  I_i*=1e-9; // convert to GeV
499  LnI+=w_i*Z_i*log(I_i)/Z;
500  }
501  }
502  else{
503  // mean excitation energy for the element
504  double I=7.0+12.0*Z; //eV
505  if (Z>=13) I=9.76*Z+58.8*pow(Z,-0.19);
506  I*=1e-9; // Convert to GeV
507  LnI=log(I);
508  }
509 
510  return NOERROR;
511 }
512 
513 
514 
515 //---------------------------------
516 // FindMat
517 //---------------------------------
518 struct VolMat DRootGeom::FindMat(double *x)
519 {
520 
521  pthread_mutex_lock(&mutex);
522  if(!DRGeom)InitDRGeom();
523  TGeoNode *cnode = DRGeom->FindNode(x[0],x[1],x[2]);
524  TGeoVolume *cvol = cnode->GetVolume();
525  TGeoMaterial *cmat = cvol->GetMedium()->GetMaterial();
526 
527  Current_Node = cnode;
528  Current_Volume = cvol;
529  Current_Material = cmat;
530  Mat_Index = cmat->GetIndex();
531 
532  Mat.A = cmat->GetA();
533  Mat.Z = cmat->GetZ();
534  Mat.Density = cmat->GetDensity();
535  Mat.RadLen = cmat->GetRadLen();
536 
537  pthread_mutex_unlock(&mutex);
538 
539  //cout<<x[0]<<" "<<x[1]<<" "<<x[2]<<endl;
540  //cout<<DRGeom->FindNode(x[0],x[1],x[2])->GetVolume()->GetName()<<endl;
541 
542  return Mat;
543 
544 }
545 
546 
struct VolMat FindMat(double *x)
Definition: DRootGeom.cc:518
double A
Definition: DRootGeom.h:28
double rmax
void InitTable(void)
Definition: DRootGeom.cc:140
TVector3 DVector3
Definition: DVector3.h:14
int n_z
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
virtual ~DRootGeom()
Definition: DRootGeom.cc:43
double zmax
TGeoManager * hddsroot()
int Nr
Definition: bfield2root.cc:25
double rmin
jerror_t FindMatLL(DVector3 pos, double &rhoZ_overA, double &rhoZ_overA_logI, double &RadLen) const
Definition: DRootGeom.cc:402
double rhoZ_overA_logI
Definition: DRootGeom.h:33
JApplication * japp
int Nz
Definition: bfield2root.cc:27
TGeoNode * FindNode(double *x)
Definition: DRootGeom.cc:250
DRootGeom(JApplication *japp, unsigned int run_number=1)
Definition: DRootGeom.cc:17
TEllipse * e
int n_r
double rhoZ_overA
Definition: DRootGeom.h:32
int ReadMap(string namepath, int32_t runnumber)
Definition: DRootGeom.cc:52
#define _DBG_
Definition: HDEVIO.h:12
jerror_t FindMatTable(DVector3 pos, double &rhoZ_overA, double &rhoZ_overA_logI, double &RadLen) const
Definition: DRootGeom.cc:327
double sin(double)
void InitDRGeom(void)
Definition: DRootGeom.cc:225
int n_phi
TGeoVolume * FindVolume(double *x)
Definition: DRootGeom.cc:267
double Density
Definition: DRootGeom.h:30
double RadLen
Definition: DRootGeom.h:31
double zmin
#define I(x, y, z)
double Z
Definition: DRootGeom.h:29