Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

PisaBBC.C

Go to the documentation of this file.
00001 #include "PisaBBC.h"
00002 
00003 #include <algorithm>
00004 #include <cassert>
00005 #include <iostream>
00006 #include <iomanip>
00007 #include <iterator>
00008 #include <vector>
00009 
00010 #include "PHCompositeNode.h"
00011 #include "PHIODataNode.h"
00012 #include "PHObjectVectorTCA.h"
00013 #include "phool.h"
00014 #include "PisaBBCHitv1.h"
00015 #include "PisaHelper.h"
00016 #include "PisaPhnxPar.h"
00017 
00018 #include "TGeoManager.h"
00019 #include "TGeoMedium.h"
00020 #include "TGeoVolume.h"
00021 #include "TLorentzVector.h"
00022 #include "TVirtualMC.h"
00023 #include "TMCProcess.h"
00024 #include "TArrayI.h"
00025 
00026 namespace 
00027 {
00028   double max(double a, double b, double c)
00029   {
00030     return std::max(a,std::max(b,c));
00031   }
00032 
00033   double max(double a, double b, double c, double d)
00034   {
00035     return std::max(a,max(b,c,d));
00036   }
00037  
00038   double min(double a, double b, double c)
00039   {
00040     return std::min(a,std::min(b,c));
00041   }
00042 
00043   double min(double a, double b, double c, double d)
00044   {
00045     return std::min(a,min(b,c,d));
00046   }
00047 
00048   std::string status()
00049   {
00050     std::string rv;
00051 
00052     if ( gMC->IsTrackInside() )
00053       {
00054         rv += " INSIDE";
00055       }
00056     if ( gMC->IsTrackEntering() )
00057       {
00058         rv += " ENTERING"; 
00059       }
00060     if ( gMC->IsTrackExiting() )
00061       {
00062         rv += " EXITING";
00063       }
00064     if ( gMC->IsTrackOut() )
00065       {
00066         rv += " OUTSIDE";
00067       }
00068     if ( gMC->IsTrackAlive() )
00069       {
00070         rv += " ALIVE";
00071       }
00072     if ( gMC->IsTrackDisappeared() )
00073       {
00074         rv += " DISAPPEARED";
00075       }
00076     if ( gMC->IsTrackStop() )
00077       {
00078         rv += " STOP";
00079       }
00080     if ( gMC->IsNewTrack() )
00081       {
00082         rv += " NEWTRACK";
00083       }
00084 
00085     TArrayI array;
00086     int n = gMC->StepProcesses(array);
00087 
00088     for ( int i = 0; i < n; ++i )
00089       {
00090         rv += "+";
00091         rv += TMCProcessName[array[i]];
00092       }
00093     return rv;
00094   }
00095 }
00096 
00097 //_____________________________________________________________________________
00098 PisaBBC::PisaBBC(bool enabled)
00099   : PisaDetector()
00100 {
00101   enable(enabled);
00102 }
00103 
00104 //_____________________________________________________________________________
00105 PisaBBC::~PisaBBC()
00106 {
00107 }
00108 
00109 //_____________________________________________________________________________
00110 void
00111 PisaBBC::beginEvent(PHCompositeNode* topNode)
00112 {
00113   PisaBBCHitVector* hits = 
00114     PisaHelper::getClass<PisaBBCHitVector>(topNode, "BBCHits","DST");
00115 
00116   if (!hits)
00117     {
00118       fHits = new PHObjectVectorTCA<PisaBBCHit,PisaBBCHitv1>;
00119       PHIODataNode<PisaBBCHitVector>* node =
00120         new PHIODataNode<PisaBBCHitVector>(fHits,"BBCHits","PHObject");
00121       PisaHelper::getPisaNode(topNode,"DST")->addNode(node);
00122     }
00123   else
00124     {
00125       fHits = hits;
00126     }
00127   
00128 }
00129 
00130 //_____________________________________________________________________________
00131 void
00132 PisaBBC::createGeometry(PHCompositeNode* topNode)
00133 {
00134 
00135   // This routine defines the geometry for the Beam-Beam
00136   // Counter. Structure of BBC is place in the mother volume "HALL".
00137   //
00138   //     HALL --- BBCM ---                         ! BBC mother volume
00139   //                     /-- BBCE                  ! Electron absorber
00140   //                     /-- BBCF                  ! Front panel
00141   //                     /-- BBCS                  ! Structure tube
00142   //                     /-- BBCB                  ! Back panel
00143   //                     /-- BBCC                  ! Thin barrel cover
00144   //                     /-- BBCD --               ! Detector volume
00145   //                               /-- BBCA        ! Attachment plate
00146   //                               /-- BBCQ        ! Quartz block
00147   //                               /-- BBCP        ! PMT
00148   //                               /-- BBCR        ! Breeder module
00149   //                               /-- BBCH        ! Metal shield 
00150   //
00151 
00152   const int MAXPMT = 100; // Maximum # of PMTs to be installed.
00153   const int MAXREM =  10; // Maximum # of PMTs to be removed.
00154 
00155   PisaPhnxPar* parameters = 
00156     PisaHelper::getClass<PisaPhnxPar>(topNode, "PHNXPAR");
00157   assert(parameters != 0);
00158 
00159   const PisaPhnxSubPar* bbc_par = parameters->get("bbc_par");
00160   assert(bbc_par != 0);
00161 
00162   TGeoManager* gm = PisaHelper::getGeoManager();
00163 
00164   double BBBCOVER[3];  // BarrelCover with Rmin, Rmax, thick 
00165   double BBDETECT[10]; // Detector element for PGON
00166   double BBMOTHER[3];  // BBC Mother Volume with Rmin, Rmax, thick
00167   double BBSHIELD[10]; // Metal shield PGON
00168 
00169   // Construct needed parameters from the phnxpar parameters.
00170 
00171   BBDETECT[0] = bbc_par->getDouble("BBQUARTZ",0);
00172   BBDETECT[1] = bbc_par->getDouble("BBQUARTZ",1);
00173   BBDETECT[2] = bbc_par->getDouble("BBQUARTZ",2);
00174   BBDETECT[3] = bbc_par->getDouble("BBQUARTZ",3);
00175   BBDETECT[4] = 
00176     + bbc_par->getDouble("BBATTACH",4) 
00177     + bbc_par->getDouble("BBQUARTZ",4) 
00178     - bbc_par->getDouble("BBPMTSIZ",2) 
00179     - bbc_par->getDouble("BBBREEDE",2);
00180   BBDETECT[5] = bbc_par->getDouble("BBQUARTZ",5);
00181   BBDETECT[6] = max(bbc_par->getDouble("BBATTACH",6),
00182                     bbc_par->getDouble("BBQUARTZ",6),
00183                     bbc_par->getDouble("BBPMTSIZ",1));
00184   BBDETECT[7] = 
00185     + bbc_par->getDouble("BBATTACH",7) 
00186     + bbc_par->getDouble("BBQUARTZ",7) 
00187     + bbc_par->getDouble("BBPMTSIZ",2)  
00188     + bbc_par->getDouble("BBBREEDE",2);
00189   BBDETECT[8] = bbc_par->getDouble("BBQUARTZ",8);
00190   BBDETECT[9] = max(bbc_par->getDouble("BBATTACH",9),
00191                     bbc_par->getDouble("BBQUARTZ",9),
00192                     bbc_par->getDouble("BBPMTSIZ",1));
00193 
00194   BBBCOVER[0] = max(bbc_par->getDouble("BBABSORB",1),
00195                     bbc_par->getDouble("BBFRONTB",1),
00196                     bbc_par->getDouble("BBSTRUCT",1),
00197                     bbc_par->getDouble("BBBACKBD",1));
00198   BBBCOVER[1] = BBBCOVER[0] + bbc_par->getDouble("BBCOVERT");
00199   BBBCOVER[2] = bbc_par->getDouble("BBSTRUCT",2);
00200    
00201   BBMOTHER[0] = min(bbc_par->getDouble("BBABSORB",0),
00202                     bbc_par->getDouble("BBFRONTB",0),
00203                     bbc_par->getDouble("BBSTRUCT",0),
00204                     bbc_par->getDouble("BBBACKBD",0));
00205   BBMOTHER[1] = BBBCOVER[1];
00206   BBMOTHER[2] = bbc_par->getDouble("BBSTRUCT",2);
00207 
00208   BBSHIELD[0] = bbc_par->getDouble("BBQUARTZ",0);
00209   BBSHIELD[1] = bbc_par->getDouble("BBQUARTZ",1);
00210   BBSHIELD[2] = bbc_par->getDouble("BBQUARTZ",2);
00211   BBSHIELD[3] = bbc_par->getDouble("BBQUARTZ",3);
00212   BBSHIELD[4] = 
00213     + bbc_par->getDouble("BBQUARTZ",4)
00214     - bbc_par->getDouble("BBPMTSIZ",2)
00215     - bbc_par->getDouble("BBBREEDE",2);
00216   BBSHIELD[5] = max(bbc_par->getDouble("BBATTACH",6),
00217                     bbc_par->getDouble("BBQUARTZ",6),
00218                     bbc_par->getDouble("BBPMTSIZ",1))
00219     - bbc_par->getDouble("BBSHITHI");
00220                     
00221   BBSHIELD[6] = max(bbc_par->getDouble("BBATTACH",6),
00222                     bbc_par->getDouble("BBQUARTZ",6),
00223                     bbc_par->getDouble("BBPMTSIZ",1));
00224   BBSHIELD[7] =
00225     + bbc_par->getDouble("BBQUARTZ",7)
00226     + bbc_par->getDouble("BBPMTSIZ",2)
00227     + bbc_par->getDouble("BBBREEDE",2); 
00228   BBSHIELD[8] =  max(bbc_par->getDouble("BBATTACH",9),
00229                      bbc_par->getDouble("BBQUARTZ",9),
00230                      bbc_par->getDouble("BBPMTSIZ",1))
00231     - bbc_par->getDouble("BBSHITHI");
00232   BBSHIELD[9] = max(bbc_par->getDouble("BBATTACH",9),
00233                      bbc_par->getDouble("BBQUARTZ",9),
00234                      bbc_par->getDouble("BBPMTSIZ",1));
00235 
00236   double YSTP = bbc_par->getDouble("BBQUARTZ",6) 
00237     + bbc_par->getDouble("BBSPACIN")*0.5;
00238   double XSTP = YSTP*sqrt(3.0);
00239  
00240   int MROW = static_cast<int>(floor(bbc_par->getDouble("BBFRONTB",1)/YSTP))+1;
00241   int MCOL = static_cast<int>(floor(bbc_par->getDouble("BBFRONTB",1)/XSTP))+1;
00242 
00243   double RMAX = bbc_par->getDouble("BBFRONTB",1)
00244     - BBDETECT[6]*2.0/sqrt(3.0);
00245   double RMIN = bbc_par->getDouble("BBFRONTB",0)
00246     + BBDETECT[6]*2.0/sqrt(3.0);
00247 
00248   double RRMA = RMAX*RMAX;
00249   double RRMI = RMIN*RMIN;
00250 
00251   if ( bbc_par->getInt("BBNUMREM") > MAXREM )
00252     {
00253       std::cerr << PHWHERE << "BBC: Number of detector to be removed"
00254                 << " exceeded MAXREM=" << MAXREM
00255                 << std::endl;
00256       exit(1);
00257     }
00258 
00259   if ( YSTP <= BBDETECT[6] ) 
00260     {
00261       std::cerr << PHWHERE << "BBC : Spacing conflict" << std::endl;
00262       exit(1);
00263     }
00264 
00265   // Create a BBC mother volume, BBCM
00266 
00267   TGeoVolume* bbcm = gm->Volume("BBCM","TUBE",
00268                                 bbc_par->getInt("BBMEDMOT"),BBMOTHER,3);
00269 
00270   // Place the mother volume BBCM in the HALL volume
00271   // BBZPOSIT gives the z position of a quartz radiator front face.
00272 
00273   TGeoVolume* hall = gm->GetVolume("HALL");
00274   assert(hall != 0);
00275 
00276   double zpos = 
00277     bbc_par->getDouble("BBZPOSIT",0) 
00278     + BBMOTHER[2]
00279     - 2.0*bbc_par->getDouble("BBABSORB",2)
00280     - 2.0*bbc_par->getDouble("BBFRONTB",2)
00281     - ( bbc_par->getDouble("BBATTACH",7)
00282         - bbc_par->getDouble("BBABSORB",2));
00283 
00284   hall->AddNode(bbcm,1,new TGeoTranslation(0.0,0.0,zpos));
00285 
00286   zpos = bbc_par->getDouble("BBZPOSIT",1) 
00287     - BBMOTHER[2]
00288     + 2.0*bbc_par->getDouble("BBABSORB",2)
00289     + 2.0*bbc_par->getDouble("BBFRONTB",2)
00290     + ( bbc_par->getDouble("BBATTACH",7)
00291         - bbc_par->getDouble("BBABSORB",2));
00292 
00293   TGeoTranslation t1(0.0,0.0,zpos);
00294   TGeoRotation r1;
00295 
00296   r1.SetAngles(90.,0.,90.,90.,180.,0.); // mirror symmetry
00297 
00298   TGeoCombiTrans* tr1 = new TGeoCombiTrans(t1,r1);
00299 
00300   hall->AddNode(bbcm,2,tr1);
00301 
00302   // Create BBCE, BBCF, BBCS, BBCB, BBCC, BBCD volumes
00303   // and place them into BBCM.
00304 
00305   TGeoVolume* bbce = gm->MakeTube("BBCE",
00306                                   gm->GetMedium(bbc_par->getInt("BBMEDABS")),
00307                                   bbc_par->getDouble("BBABSORB",0),
00308                                   bbc_par->getDouble("BBABSORB",1),
00309                                   bbc_par->getDouble("BBABSORB",2));
00310   bbcm->AddNode(bbce,1,
00311                 new TGeoTranslation(0.0,0.0,-BBMOTHER[2]+
00312                                     bbc_par->getDouble("BBABSORB",2)));
00313 
00314   TGeoVolume* bbcf = gm->MakeTube("BBCF",
00315                                   gm->GetMedium(bbc_par->getInt("BBMEDFRO")),
00316                                   bbc_par->getDouble("BBFRONTB",0),
00317                                   bbc_par->getDouble("BBFRONTB",1),
00318                                   bbc_par->getDouble("BBFRONTB",2));
00319   bbcm->AddNode(bbcf,1,
00320                 new TGeoTranslation(0.0,0.0,-BBMOTHER[2]+
00321                                     2.0*bbc_par->getDouble("BBABSORB",2)+
00322                                     bbc_par->getDouble("BBFRONTB",2)));
00323 
00324   TGeoVolume* bbcs = gm->MakeTube("BBCS",
00325                                   gm->GetMedium(bbc_par->getInt("BBMEDSTR")),
00326                                   bbc_par->getDouble("BBSTRUCT",0),
00327                                   bbc_par->getDouble("BBSTRUCT",1),
00328                                   bbc_par->getDouble("BBSTRUCT",2));  
00329   bbcm->AddNode(bbcs,1);
00330 
00331   TGeoVolume* bbcb = gm->MakeTube("BBCB",
00332                                   gm->GetMedium(bbc_par->getInt("BBMEDBAC")),
00333                                   bbc_par->getDouble("BBBACKBD",0),
00334                                   bbc_par->getDouble("BBBACKBD",1),
00335                                   bbc_par->getDouble("BBBACKBD",2)); 
00336 
00337   bbcm->AddNode(bbcb,1,
00338                 new TGeoTranslation(0.0,0.0,BBMOTHER[2]-
00339                                     bbc_par->getDouble("BBBACKBD",2)));
00340 
00341 
00342   TGeoVolume* bbcc = gm->Volume("BBCC","TUBE",bbc_par->getInt("BBMEDCOV"),
00343                                 BBBCOVER,3);
00344 
00345   bbcm->AddNode(bbcc,1);
00346 
00347   // Now the envelops of the detectors (vacuum)
00348   
00349   TGeoVolume* bbcd = gm->Volume("BBCD","PGON",bbc_par->getInt("BBMEDCOV"),
00350                                 BBDETECT,10);
00351   
00352   //  bbcm->AddNode(bbcd,1);
00353 
00354   zpos = -BBMOTHER[2] 
00355     + 2.0*bbc_par->getDouble("BBFRONTB",2)
00356     + 2.0*bbc_par->getDouble("BBABSORB",2)
00357     + ( BBDETECT[7]-BBDETECT[4] ) * 0.5;
00358 
00359   int NROW = MROW;
00360   int NCOL = MCOL;
00361   int NDET = 0;
00362 
00363   // Find detector element location inside the BBC boundaries.
00364 
00365   double XYPS[2][MAXPMT];
00366   bool LXYP[MAXPMT];
00367 
00368   while ( NROW >= -MROW ) // Start from top left and go right
00369     {
00370       int LROW = abs(NROW/2*2-NROW); // 0 for even, 1 for odd
00371       double YPOS = NROW*YSTP;
00372       NCOL = MCOL;
00373       while ( NCOL >= -MCOL )
00374         {
00375           int LCOL = abs(NCOL/2*2-NCOL); // 0 for even, 1 for odd
00376           if ( LROW == LCOL ) // since elements are staggered
00377             {
00378               double XPOS = NCOL*XSTP;
00379               double RRAD = XPOS*XPOS+YPOS*YPOS;
00380               if ( (RRAD<=RRMA) && (RRAD>=RRMI) ) // in range ?
00381                 {
00382                   if ( NDET < MAXPMT )
00383                     {
00384                       XYPS[0][NDET] = XPOS;
00385                       XYPS[1][NDET] = YPOS;
00386                       LXYP[NDET] = true;
00387                     }
00388                   else
00389                     {
00390                       std::cerr << PHWHERE << "BBC : max # of PMT exceeded"
00391                                 << std::endl;
00392                       exit(1);
00393                     }
00394                   ++NDET;
00395                 } // in range
00396             } // even-odd
00397           --NCOL;
00398         } // column loop
00399       --NROW;
00400     } // row loop
00401 
00402   double RREM=0.0;
00403 
00404   for ( int IP1 = 0; IP1 < bbc_par->getInt("BBNUMREM"); ++IP1 )
00405     {
00406       int RD = 1;
00407       double XX = XYPS[0][NDET] - bbc_par->getDouble("BBPOSREM",IP1*2);
00408       double YY = XYPS[1][NDET] - bbc_par->getDouble("BBPOSREM",IP1*2+1);
00409       RREM = XX*XX + YY*YY;
00410       for ( int IP2 = 1; IP2 < NDET; ++IP2 )
00411         {
00412           double XX = XYPS[0][IP2] - bbc_par->getDouble("BBPOSREM",IP1*2);
00413           double YY = XYPS[1][IP2] - bbc_par->getDouble("BBPOSREM",IP1*2+1);
00414           double RR = XX*XX + YY*YY;
00415           if ( RR <= RREM )
00416             {
00417               RD = IP2;
00418               RREM = RR;
00419             }
00420         }
00421       LXYP[RD] = false;
00422     }
00423 
00424   for ( int IP1 = 0; IP1 < NDET; ++IP1 )
00425     {
00426       if ( LXYP[IP1] )
00427         {
00428           bbcm->AddNode(bbcd,IP1+1,
00429                         new TGeoTranslation(XYPS[0][IP1],XYPS[1][IP1],zpos));
00430         }
00431     }
00432 
00433   // Now fills the detector empty envelops with usefull stuff =
00434   // attachment, quartz, PMT, breeder and metal shield.
00435 
00436   double BBATTACH[10];
00437   for ( size_t i = 0; i < 10; ++i )
00438     {
00439       BBATTACH[i] = bbc_par->getDouble("BBATTACH",i);
00440     }
00441 
00442   TGeoVolume* bbca = gm->Volume("BBCA","PGON",bbc_par->getInt("BBMEDATT"),
00443                                 BBATTACH,10);
00444 
00445   zpos = -(BBDETECT[7]-BBDETECT[4])*0.5
00446     + (BBATTACH[7]-BBATTACH[4])*0.5;
00447 
00448   bbcd->AddNode(bbca,1,new TGeoTranslation(0.0,0.0,zpos));
00449 
00450   double BBQUARTZ[10];
00451   for ( size_t i = 0; i < 10; ++i )
00452     {
00453       BBQUARTZ[i] = bbc_par->getDouble("BBQUARTZ",i);
00454     }
00455 
00456   TGeoVolume* bbcq = gm->Volume("BBCQ","PGON",bbc_par->getInt("BBMEDQUA"),
00457                                 BBQUARTZ,10);
00458 
00459   zpos = -(BBDETECT[7]-BBDETECT[4])*0.5
00460     + (BBQUARTZ[7]-BBQUARTZ[4])*0.5
00461     + (BBATTACH[7]-BBATTACH[4]);
00462 
00463   bbcd->AddNode(bbcq,1,new TGeoTranslation(0.0,0.0,zpos));
00464 
00465   TGeoVolume* bbcp = gm->MakeTube("BBCP",
00466                                   gm->GetMedium(bbc_par->getInt("BBMEDPMT")),
00467                                   bbc_par->getDouble("BBPMTSIZ",0),
00468                                   bbc_par->getDouble("BBPMTSIZ",1),
00469                                   bbc_par->getDouble("BBPMTSIZ",2));
00470 
00471   zpos = -(BBDETECT[7]-BBDETECT[4])*0.5
00472     + (BBQUARTZ[7]-BBQUARTZ[4])
00473     + (BBATTACH[7]-BBATTACH[4])
00474     + bbc_par->getDouble("BBPMTSIZ",2);
00475 
00476   bbcd->AddNode(bbcp,1,new TGeoTranslation(0.0,0.0,zpos));
00477  
00478   TGeoVolume* bbcr = gm->MakeTube("BBCR",
00479                                   gm->GetMedium(bbc_par->getInt("BBMEDBRE")),
00480                                   bbc_par->getDouble("BBBREEDE",0),
00481                                   bbc_par->getDouble("BBBREEDE",1),
00482                                   bbc_par->getDouble("BBBREEDE",2));
00483   
00484   zpos = -(BBDETECT[7]-BBDETECT[4])*0.5
00485     + (BBQUARTZ[7]-BBQUARTZ[4])
00486     + (BBATTACH[7]-BBATTACH[4])
00487     + bbc_par->getDouble("BBPMTSIZ",2)*2.0
00488     + bbc_par->getDouble("BBBREEDE",2);
00489 
00490   bbcd->AddNode(bbcr,1,new TGeoTranslation(0.0,0.0,zpos));
00491 
00492   TGeoVolume* bbch = gm->Volume("BBCH","PGON",bbc_par->getInt("BBMEDSHI"),
00493                                 BBSHIELD,10);
00494 
00495   zpos = -(BBDETECT[7]-BBDETECT[4])*0.5
00496     + (BBATTACH[7]-BBATTACH[4])
00497     + (BBSHIELD[7]-BBSHIELD[4])*0.5;
00498 
00499   bbcd->AddNode(bbch,1,new TGeoTranslation(0.0,0.0,zpos));  
00500 }
00501 
00502 //_____________________________________________________________________________
00503 void
00504 PisaBBC::createMaterials(PHCompositeNode*)
00505 {
00506   TGeoManager* gm = PisaHelper::getGeoManager();
00507 
00508   int nmat = 16;   // vacuum
00509 
00510   gm->Material("Vacuum",0.0,0.0,0.0,nmat,0.0,0.0);  
00511 
00512   nmat = 9; // aluminium
00513 
00514   gm->Material("Aluminium",26.980,13.000,2.700,nmat);
00515 
00516   nmat = 46; // iron
00517 
00518   gm->Material("Low Mag Iron",55.85,26.0,7.87,nmat,1.76,17.1);
00519 
00520   nmat = 201;
00521 
00522   double aquartz[] = { 28.09 ,    16.0 };
00523   double zquartz[] = { 14.00 ,     8.0 };
00524   double wquartz[] = {  0.467,   0.532 };
00525 
00526   double dens = 2.64;
00527 
00528   gm->Mixture("Quartz-BBQ",aquartz,zquartz,dens,2,wquartz,nmat);
00529 
00530   nmat = 202; // why a second material identical to the first one ?
00531 
00532   gm->Mixture("Quartz-PMT",aquartz,zquartz,dens,2,wquartz,nmat);
00533 
00534   nmat = 802;
00535 
00536   // Plastic (lucite) for cover plates (C5H8O2)
00537   double ap[] = { 12.0,  1.0, 16.0 };
00538   double zp[] = {  6.0,  1.0,  8.0 };
00539   double wp[] = {  0.6, 0.08, 0.32 };
00540   double dp = 1.18;
00541 
00542   gm->Mixture("Plastic",ap,zp,dp,3,wp,nmat);
00543 
00544   // Tracking media # 32 - Vacuum + magnetic field
00545   int isvol = 0;   // not sensitive
00546   int ifield = 1;  // magnetic field
00547   double fieldm = 5.0;  // max field
00548   double tmaxfd = 5.0;    // maximum angle due to field (one step) in degrees
00549   double dmaxms = 0.2;    // max disp. due to mulsct. in one step (cm)
00550   double deemax =  0.2;   // max fractional energy loss in one step
00551   double epsil =   0.1;  // tracking precision (cm)
00552   double stmin =   5.00;  // min step due to e loss or mulsct. (cm)
00553 
00554   gm->Medium("Air + Field",32,nmat,isvol,ifield,fieldm,tmaxfd,dmaxms,deemax,epsil,stmin);
00555 
00556   // Tracking media # 26 
00557 
00558   nmat = 9 ; // aluminium
00559   isvol = 0   ; // insensitive
00560   ifield = 1  ; // magnetic field
00561   fieldm = 5.0  ; // max field
00562   tmaxfd = 1.0   ; // maximum angle due to field (one step) in degrees
00563   dmaxms = 0.2   ; // max disp. due to mulsct. in one step (cm)
00564   deemax = 0.5   ; // max fractional energy loss in one step
00565   epsil = 0.01 ; // tracking precision (cm)
00566   stmin = 0.01 ; // min step due to e loss or mulsct. (cm)
00567   
00568   gm->Medium("Aluminum Frame",26,nmat,isvol,ifield,fieldm,tmaxfd,dmaxms,deemax,epsil,stmin);
00569 
00570   // Tracking medium #201 -- Quartz for BBQ (sensitive detector)
00571   nmat = 201;
00572   isvol = 1; // sensitive
00573   ifield = 1;
00574   fieldm = 20.0;
00575   tmaxfd = 45.0;
00576   dmaxms = 0.2;
00577   deemax = 0.1;
00578   epsil = 0.01;
00579   stmin = 0.1;
00580   
00581   gm->Medium("Quartz-BBQ",201,nmat,isvol,ifield,fieldm,tmaxfd,dmaxms,deemax,epsil,stmin);
00582 
00583   nmat = 202;
00584 
00585   gm->Medium("Quartz-PMT",202,nmat,isvol,ifield,fieldm,tmaxfd,dmaxms,deemax,epsil,stmin);
00586 
00587   nmat = 802;
00588   gm->Medium("Plastic",802,nmat,0,0,0.,10.,1.,0.1,0.01,0.05);
00589 
00590   // Tracking media # 46 - Mu Magnet Yoke (Iron)
00591   nmat = 46   ; // iron (low threshold)
00592   isvol = 0   ; // not sensitive
00593   ifield = 0  ; // no magnetic field
00594   fieldm = 0.0  ; // max field
00595   tmaxfd = 0.3    ; // maximum angle due to field (one step) in degrees
00596   dmaxms = 2.0   ; // max disp. due to mulsct. in one step (cm)
00597   deemax = 0.2   ; // max fractional energy loss in one step
00598   epsil = 0.1  ; // tracking precision (cm)
00599   stmin = 0.1 ; // min step due to e loss or mulsct. (cm)
00600   gm->Medium("MU non-mag-low",46,nmat,isvol,ifield,fieldm,tmaxfd,dmaxms,deemax,epsil,stmin);
00601 
00602 }
00603 
00604 //_____________________________________________________________________________
00605 void
00606 PisaBBC::finishEvent(PHCompositeNode*)
00607 {
00608   std::cout << PHWHERE << " : nhits=" << fHits->size() << std::endl;
00609   
00610 }
00611 
00612 //_____________________________________________________________________________
00613 void
00614 PisaBBC::stepManager()
00615 {
00616   static unsigned int nevt = 0;
00617 
00618   ++nevt;
00619 
00620   if ( gMC->GetMedium() != 5 )
00621     { 
00622       // This should of course be done by the PisaServer...
00623       // using e.g. a map tracking media -> PisaDetector
00624       // to know at each step which stepManager to call...
00625       return;
00626     }
00627 
00628   if ( gMC->TrackCharge() == 0.0 )
00629     {
00630       // Do not deal with e.g. photons.
00631       return;
00632     }
00633 
00634   int copy;
00635   int volid = gMC->CurrentVolID(copy);
00636   
00637   int track = gMC->GetStack()->GetCurrentTrackNumber();
00638   int pid = gMC->TrackPid();
00639   
00640   std::cout << " Track # " << std::setw(4) << track
00641             << " " << gMC->ParticleName(pid)
00642             << " VolID=" << volid << "(copy=" << copy << ") "
00643             << " VolName=" << gMC->CurrentVolName()
00644             << " Medium=" << gMC->GetMedium()
00645             << status()
00646             << " Length=" << gMC->TrackLength()
00647             << std::endl;
00648 
00649 
00650   if ( gMC->IsTrackEntering() )
00651     {
00652       //      PisaBBCHit* last = fHits->back();
00653   //     int id = 0;
00654 //       if (!last)
00655 //      {
00656 //        id = last->id()+1;
00657 //      }
00658       PisaBBCHit* hit = fHits->add(fHits->size());
00659       //      hit->id(id);
00660       hit->track(gMC->GetStack()->GetCurrentTrackNumber());
00661       hit->pid(gMC->TrackPid());
00662       TLorentzVector pos;
00663       TLorentzVector mom;
00664       gMC->TrackPosition(pos);
00665       gMC->TrackMomentum(mom);
00666       hit->position(pos.X(),pos.Y(),pos.Z());
00667       hit->momentum(mom.X(),mom.Y(),mom.Z());
00668       hit->del(0.0);
00669       hit->tof(gMC->TrackTime()*1e9);
00670       hit->len(0.0);
00671       std::cout << PHWHERE << nevt << " Created hit " << (*hit) << std::endl;
00672     }
00673 
00674   if ( gMC->IsTrackInside() )
00675     {
00676       PisaBBCHit* last = fHits->back();
00677       assert(last!=0);
00678       assert(last->track()==gMC->GetStack()->GetCurrentTrackNumber());
00679       assert(last->pid()==gMC->TrackPid());
00680       last->del(last->del()+gMC->Edep());
00681       std::cout << PHWHERE << nevt << " Updating hit " << std::endl;
00682       std::cout << (*last) << std::endl;
00683     }
00684 
00685   if ( !gMC->IsTrackAlive() || gMC->IsTrackExiting() || gMC->IsTrackOut() )
00686     {
00687       PisaBBCHit* last = fHits->back();
00688       assert(last!=0);
00689       assert(last->track()==gMC->GetStack()->GetCurrentTrackNumber());
00690       assert(last->pid()==gMC->TrackPid());
00691       last->len(gMC->TrackLength()-last->len());
00692       std::cout << PHWHERE << nevt << " Really closing hit" << (*last) << std::endl;
00693     }
00694 
00695  //  if ( gMC->IsTrackEntering() )
00696 //     {
00697 //       TLorentzVector track;
00698 //       gMC->TrackPosition(track);
00699 //       TLorentzVector mom;
00700 //       gMC->TrackMomentum(mom);
00701 //       hit->position(track.X(),track.Y(),track.Z());
00702 //       hit->momentum(mom.X(),mom.Y(),mom.Z());
00703 //       hit->len(gMC->TrackLength());
00704 //       hit->del(0.0);
00705 //       hit->tof(gMC->TrackTime()*1E9);
00706 //       hit->etot(gMC->Etot());
00707 //       hit->track(gMC->GetStack()->GetCurrentTrackNumber());
00708 //       hit->pid(gMC->TrackPid());
00709 //       std::cout << "VolID=" << volid << "(copy=" << copy << ") "
00710 //              << " VolName=" << gMC->CurrentVolName()
00711 //              << " Medium=" << gMC->GetMedium()
00712 //              << " IsExiting=" << gMC->IsTrackExiting()
00713 //              << " IsInside=" << gMC->IsTrackInside()
00714 //              << " IsAlive=" << gMC->IsTrackAlive()
00715 //              << " IsStop=" << gMC->IsTrackStop()
00716 //              << " IsDisappeared=" << gMC->IsTrackDisappeared()
00717 //              << std::endl;
00718 //       hit->identify();
00719 //     }
00720 
00721 //   if ( gMC->IsTrackInside() )
00722 //     {
00723 //       std::cout << "Length=" 
00724 //              << gMC->TrackLength()
00725 //              << " VolID=" << volid << "(copy=" << copy << ") "
00726 //              << " VolName=" << gMC->CurrentVolName()
00727 //              << " Medium=" << gMC->GetMedium()
00728 //              << " IsExiting=" << gMC->IsTrackExiting()
00729 //              << " IsInside=" << gMC->IsTrackInside()
00730 //              << " IsAlive=" << gMC->IsTrackAlive()
00731 //              << " IsStop=" << gMC->IsTrackStop()
00732 //              << " IsDisappeared=" << gMC->IsTrackDisappeared()
00733 //              << std::endl;
00734       
00735 //     }
00736 }