mEmcClusterizerv0.C

Go to the documentation of this file.
00001 #include "mEmcClusterizerv0.h"
00002 
00003 #include <cstdio>
00004 #include <cmath>
00005 #include <cstdlib>
00006 #include <iostream>
00007 #include <cassert>
00008 #include <memory>
00009 
00010 #include "PHNode.h"
00011 #include "PHCompositeNode.h"
00012 #include "PHIODataNode.h"
00013 #include "PHNodeIterator.h"
00014 #include "PHTable.hh"
00015 
00016 #include "PHCompositeNode.h"
00017 
00018 #include "EmcIndexer.h"
00019 #include "EmcCluster.h"
00020 #include "EmcScSectorRec.h"
00021 #include "EmcGlSectorRec.h"
00022 
00023 #include "mEmcGeometryModule.h"
00024 
00025 #include "VtxOut.h"
00026 
00027 #include "emcTowerContainer.h"
00028 #include "emcTowerContent.h"
00029 #include "EmcIndexer.h"
00030 
00031 #include "emcClusterContainer.h"
00032 #include "emcClusterContent.h"
00033 
00034 using namespace std;
00035 
00036 typedef PHIODataNode<PHTable> TableNode_t;
00037 
00038 namespace {
00039 
00040   //_________________________________________________________________________
00041   void  computeCorrectedDispersion(float ycg, float zcg,
00042                                    float dispy, float dispz, 
00043                                    float yModSize, float zModSize,
00044                                    float& corrdispy, float& corrdispz)
00045   {
00046     float zpos = zcg/zModSize;
00047     float ypos = ycg/yModSize;
00048     
00049     corrdispy = dispy/(yModSize*yModSize);
00050     corrdispz = dispz/(zModSize*zModSize);
00051 
00052     float zposmod = zpos - floor(zpos);
00053     float yposmod = ypos - floor(ypos);
00054     corrdispz -= ( zposmod - zposmod*zposmod);
00055     corrdispy -= ( yposmod - yposmod*yposmod);
00056   }
00057 
00058 }
00059 
00060 //_____________________________________________________________________________
00061 mEmcClusterizerv0::mEmcClusterizerv0(mEmcGeometryModule* geom) :
00062   fClusters(0)
00063 {
00064   name = "mEmcClusterizerv0";
00065   int arm, sector;
00066   int nx, ny;
00067   float txsz, tysz;
00068   PHMatrix emcrm;
00069   PHVector emctr;
00070   float towerThresh = 0.003;
00071   float peakThresh = 0.08;
00072   float eClMin = 0.02;
00073   EmcSectorRec* SectorRec;
00074   SecGeom* SecGeometry;
00075 
00076   for (int is = 0; is < MAX_SECTORS_PROCESS; is++)
00077     {
00078       if ( is < 6 ) 
00079         {
00080           SectorRec = new EmcScSectorRec;
00081           fScSector.push_back(SectorRec);
00082         }
00083       else
00084         {
00085           SectorRec = new EmcGlSectorRec;
00086           fGlSector.push_back(SectorRec);
00087         }
00088 
00089       // Parmeters for Shower reconstruction
00090       SectorRec->SetTowerThreshold(towerThresh);
00091       SectorRec->SetPeakThreshold(peakThresh);
00092       SectorRec->SetChi2Limit(2);
00093 
00094       if (is <= 3)
00095         {
00096           arm = 0;
00097           sector = is;
00098         }
00099       else
00100         {
00101           arm = 1;
00102           sector = 7 - is;
00103         }
00104 
00105       geom->GetSectorDim(is, nx, ny);
00106       geom->GetTowerSize(is, txsz, tysz);
00107       geom->GetMatrixVector(is, emcrm, emctr);
00108 
00109       SecGeometry = new SecGeom;
00110       fSectorGeometries.push_back(SecGeometry);
00111       SecGeometry->nx = nx;
00112       SecGeometry->ny = ny;
00113       SecGeometry->Tower_xSize = txsz;
00114       SecGeometry->Tower_ySize = tysz;
00115 
00116       SectorRec->SetGeometry(*SecGeometry, &emcrm, &emctr);      
00117     }
00118 
00119   SetMinClusterEnergy(eClMin);
00120 
00121   for (int is = 0; is < MAX_SECTORS_PROCESS; is++)
00122     {
00123       if (is < 6)
00124         {
00125           SectorRec = fScSector[is];
00126         }
00127       else
00128         {
00129           SectorRec = fGlSector[is-6];
00130         }
00131       TowerThresh[is] = SectorRec->GetTowerThreshold();
00132       Nx[is] = SectorRec->GetNx();
00133     }
00134   fHVect = new EmcModule[HVECTSIZE];
00135 }
00136 
00137 //_____________________________________________________________________________
00138 mEmcClusterizerv0::~mEmcClusterizerv0()
00139 {
00140   for ( size_t i = 0; i < fScSector.size(); ++i ) 
00141     {
00142       delete fScSector[i];
00143     }
00144   for ( size_t i = 0; i < fGlSector.size(); ++i ) 
00145     {
00146       delete fGlSector[i];
00147     }
00148   for ( size_t i = 0; i < fSectorGeometries.size(); ++i ) 
00149     {
00150       delete fSectorGeometries[i];
00151     }
00152 
00153   delete[] fHVect;
00154 }
00155 
00156 //_____________________________________________________________________________
00157 void 
00158 mEmcClusterizerv0::SetTowerThreshold(float Thresh)
00159 {
00160   for (int is = 0; is < MAX_SECTORS_PROCESS; is++)
00161     {
00162       if (is < 6)
00163         {
00164           fScSector[is]->SetTowerThreshold(Thresh);
00165         }
00166       else
00167         {
00168           fGlSector[is - 6]->SetTowerThreshold(Thresh);
00169         }
00170     }
00171 }
00172 
00173 //_____________________________________________________________________________
00174 void
00175 mEmcClusterizerv0::SetTowerThreshold(int is, float Thresh)
00176 {
00177   if (is < 0 || is >= MAX_SECTORS_PROCESS)
00178     {
00179       cout << PHWHERE << "Wrong sector index:" << is << endl;
00180       return;
00181     }
00182   if (is < 6)
00183     {
00184       fScSector[is]->SetTowerThreshold(Thresh);
00185     }
00186   else
00187     {
00188       fGlSector[is - 6]->SetTowerThreshold(Thresh);
00189     }
00190 }
00191 
00192 //_____________________________________________________________________________
00193 void
00194 mEmcClusterizerv0::SetTowerThresholdPbSc(float Thresh)
00195 {
00196   for (int is = 0; is < 6; is++)
00197     {
00198       fScSector[is]->SetTowerThreshold(Thresh);
00199     }
00200 }
00201 
00202 //_____________________________________________________________________________
00203 void mEmcClusterizerv0::SetTowerThresholdPbGl(float Thresh)
00204 {
00205   for (int is = 0; is < 2; is++)
00206     {
00207       fGlSector[is]->SetTowerThreshold(Thresh);
00208     }
00209 }
00210 
00211 //_____________________________________________________________________________
00212 void 
00213 mEmcClusterizerv0::SetPeakThreshold(float Thresh)
00214 {
00215   for (int is = 0; is < MAX_SECTORS_PROCESS; is++)
00216     {
00217       if (is < 6)
00218         {
00219           fScSector[is]->SetPeakThreshold(Thresh);
00220         }
00221       else
00222         {
00223           fGlSector[is - 6]->SetPeakThreshold(Thresh);
00224         }
00225     }
00226 }
00227 
00228 //_____________________________________________________________________________
00229 void
00230 mEmcClusterizerv0::SetPeakThreshold(int is, float Thresh)
00231 {
00232   if (is < 0 || is >= MAX_SECTORS_PROCESS)
00233     {
00234       cout << PHWHERE << "Wrong sector index:" << is << endl;
00235       return;
00236     }
00237   if (is < 6)
00238     {
00239       fScSector[is]->SetPeakThreshold(Thresh);
00240     }
00241   else
00242     {
00243       fGlSector[is - 6]->SetPeakThreshold(Thresh);
00244     }
00245 }
00246 
00247 //_____________________________________________________________________________
00248 void
00249 mEmcClusterizerv0::fillHitList(const emcTowerContainer& towers)
00250 {
00251   for (int is = 0; is < MAX_SECTORS_PROCESS; is++)
00252     {
00253       // Clean up hits list
00254       HitList[is].erase(HitList[is].begin(), HitList[is].end());
00255 
00256       EmcSectorRec* SectorRec;
00257 
00258       if ( is < 6 ) 
00259         {
00260           SectorRec = fScSector[is];
00261         }
00262       else
00263         {
00264           SectorRec = fGlSector[is-6];
00265         }
00266 
00267       // Update the towerthreshold and nx values.
00268       TowerThresh[is] = SectorRec->GetTowerThreshold();
00269       Nx[is] = SectorRec->GetNx();
00270     }
00271 
00272   for ( size_t i = 0; i < towers.size(); ++i ) 
00273     {
00274       const emcTowerContent* t = towers.getTower(i);
00275       int towerID = t->TowerID();
00276       int iarm,isector,iy,iz;
00277       EmcIndexer::TowerLocation(towerID,iarm,isector,iy,iz);
00278 
00279       if ( iarm == 1 )
00280         {
00281           isector = 7 - isector;
00282         }
00283   
00284       float de = t->Energy();
00285 
00286       // skip too low energy towers
00287       if ( de<= TowerThresh[isector] ) continue;
00288 
00289       float adc=0.0;
00290       float tac=0.0;
00291 
00292       if ( t->hasDC() ) 
00293         {
00294           adc = t->ADC();
00295           tac = t->TDC();
00296         }
00297 
00298       EmcModule vhit(iy * Nx[isector] + iz,
00299                      0,
00300                      de,
00301                      t->ToF(),
00302                      t->ErrorNeighbours(),
00303                      t->WarnNeighbours(),
00304                      adc,
00305                      tac);
00306       
00307       HitList[isector].push_back(vhit);
00308     }
00309 }
00310 
00311 //_____________________________________________________________________________
00312 void
00313 mEmcClusterizerv0::fillPeakArea(EmcPeakarea& pp, EmcCluster& cluster,
00314                                 int arm, int sector)
00315 {
00316   EmcModule hmax = pp.GetMaxTower();
00317   int ndead = pp.GetNDead();
00318   float qual = ndead ? 1.0 : -ndead;
00319 
00320 //   float rmax = (hmax.amp > 0) ? 
00321 //     hmax.amp / cluster.GetTowerEnergy(hmax.ich) : 0;
00322   
00323 //  EmcModule himp = pp.GetImpactTower();
00324 
00325 //   float rimp = (himp.amp > 0) ? 
00326 //     himp.amp / cluster.GetTowerEnergy(himp.ich) : 0;
00327 
00328   float e,ecorr,ecore,ecorecorr;
00329   float xcg,ycg,xcgm,ycgm;
00330   float xc,yc,xgl,ygl,zgl;
00331   float xx,xy,yy;
00332   float chi2;
00333   float de,dx,dy,dz;
00334 
00335   pp.GetChar(&e, &ecorr, &ecore, &ecorecorr,
00336               &xcg, &ycg, &xcgm, &ycgm,
00337               &xc, &yc, &xgl, &ygl, &zgl,
00338               &xx, &xy, &yy, &chi2, &de, &dx, &dy, &dz);
00339 
00340   float e9 = pp.GetE9(hmax.ich);
00341   //  float re9 = (e9 > 0) ? e9 / cluster.GetE9(hmax.ich) : 0.0;
00342 
00343   int nh = pp.GetNofHits();
00344   assert(nh<=HVECTSIZE);
00345   pp.GetHits(fHVect, nh);
00346 
00347   float e_max_cl = cluster.GetTowerEnergy(hmax.ich);
00348   
00349   // Principal axis dispersion (eigenvalues).
00350   float padisp[2];
00351   float pahelp = (xx + yy) * (xx + yy) - 4.0 * (xx * yy - xy * xy);
00352   pahelp = sqrt(abs(pahelp));
00353   padisp[0] = (xx + yy + pahelp) / 2.0;
00354   padisp[1] = (xx + yy - pahelp) / 2.0;
00355   
00356   float vx = fVertex[0]-xgl;
00357   float vy = fVertex[1]-ygl;
00358   float vz = fVertex[2]-zgl;
00359   
00360   float lactual = sqrt( vx*vx + vy*vy + vz*vz );
00361   float lnominal = sqrt(xgl * xgl + ygl * ygl + zgl * zgl);
00362   float dd = lactual - lnominal;
00363   
00364   //                  if ( is < 6 )
00365   //                  // This is needed because simulated times for the
00366   //                  // PbGl do not have their flashtime subtracted
00367   //                  if (runno <re1000)
00368   //                    {
00369   //                      dd = sqrt((Vertex[0] - xgl) * (Vertex[0] - xgl) +
00370   //                                (Vertex[1] - ygl) * (Vertex[1] - ygl) +
00371   //                                (Vertex[2] - zgl) * (Vertex[2] - zgl));
00372   //                    }
00373 
00374   float etof, etofmin, etofmax;
00375   float tof, tofcorr, dtof, tofmin, tofmax, tofmincorr, tofmaxcorr;
00376   float tofdisp=0;
00377 
00378   ToF_Process(fHVect, nh,
00379               dd, hmax,
00380               &tof, &etof, &tofcorr, &dtof,
00381               &tofmin, &etofmin, &tofmincorr,
00382               &tofmax, &etofmax, &tofmaxcorr,
00383               tofdisp);               
00384   
00385   size_t id = fClusters->size();
00386 
00387   emcClusterContent* clus = 
00388     fClusters->addCluster(id);
00389   
00390   clus->set_multiplicity(nh);
00391 
00392   clus->set_id(id);
00393   clus->set_arm(arm);
00394   clus->set_sector(sector);
00395   
00396   int is = EmcIndexer::sectorOfflineToOnline(arm,sector);
00397 
00398   if (is < 6)
00399     {
00400       clus->set_type(1); // PbSc
00401     } 
00402   else
00403     {
00404       clus->set_type(2); // PbGl
00405     }
00406   //                  clus->set_method(nPeakArea, 2);
00407   clus->set_xyz(xgl,ygl,zgl);
00408   clus->set_dxyz(dx,dy,dz);
00409   clus->set_e(e);
00410   clus->set_e9(e9);
00411 
00412   if (is<6)
00413     {
00414       clus->set_ecore(ecorecorr);
00415     }
00416   else
00417     {
00418       clus->set_ecore(ecorr);
00419     }
00420   clus->set_ecent(e_max_cl);
00421   clus->set_chi2(chi2);
00422   clus->set_tof(tof);
00423   clus->set_tofcorr(tofcorr);
00424   clus->set_tofdisp(tofdisp);
00425   //                  clus->set_dtof(nPeakArea, dtof);
00426   clus->set_quality(qual);
00427   clus->set_pid(0);
00428   clus->set_prob_photon(pp.GetCL());
00429   //                  clus->set_prob_neuhad(nPeakArea, 0);
00430   float phi = ( xgl == 0.0 && ygl == 0.0 ? 0.0 : atan2(ygl,xgl) );
00431   float theta = ( xgl == 0.0 && ygl == 0.0 && zgl == 0.0 ? 0.0 : 
00432                   atan2(sqrt(xgl*xgl+ygl*ygl),zgl) );
00433 
00434   clus->set_theta(theta);
00435   clus->set_phi(phi);
00436   int iy = hmax.ich / Nx[is];
00437   int iz = hmax.ich - iy * Nx[is];
00438   clus->set_ipos(iy,iz);
00439   clus->set_tofmin(tofmin);
00440   clus->set_etofmin(etofmin);
00441   clus->set_tofcorrmin(tofmincorr);
00442   clus->set_tofmax(tofmax);
00443   clus->set_etofmax(etofmax);
00444   clus->set_tofcorrmax(tofmaxcorr);
00445   //                  clus->set_tofmean(0);
00446   float dispy = yy;
00447   float dispz = xx;
00448   clus->set_disp(dispy,dispz);
00449   clus->set_padisp(padisp[1],padisp[0]);
00450 
00451   if ( clus->has_yz_cg() )
00452     {
00453       clus->set_yz_cg(ycg,xcg);
00454       
00455       float corrdispy=-9999;
00456       float corrdispz=-9999;
00457 
00458       float zModSize = fSectorGeometries[is]->Tower_xSize;
00459       float yModSize = fSectorGeometries[is]->Tower_ySize;
00460 
00461       computeCorrectedDispersion(ycg,xcg,
00462                                  dispy,dispz,
00463                                  yModSize,zModSize,
00464                                  corrdispy,corrdispz);
00465 
00466       clus->set_corrdisp(corrdispy,corrdispz);
00467     }
00468 
00469   float esum = 0;
00470   for (int ih = 0; ih < nh; ++ih)
00471     {
00472       if (fHVect[ih].amp <= 0)
00473         {
00474           clus->set_towerid(ih,-1);
00475           clus->set_partesum(ih,0);
00476           
00477         }
00478       else
00479         {
00480           int ich = fHVect[ih].ich;
00481           int iy = ich / Nx[is];
00482           int iz = ich - iy * Nx[is];
00483           int swkey = iz + iy * 100 + 10000 * sector 
00484             + 100000 * arm;
00485           int towerid = EmcIndexer::TowerID(swkey);
00486           clus->set_towerid(ih, towerid);
00487           esum += fHVect[ih].amp;
00488           clus->set_partesum(ih, esum);
00489         }
00490     }
00491   
00492   clus->set_maps(hmax.deadmap,hmax.warnmap);
00493 
00494   if ( clus->has_rawtdc() )
00495     {
00496       clus->set_rawtdc(hmax.tac);
00497     }
00498 }
00499 
00500 //_____________________________________________________________________________
00501 PHBoolean
00502 mEmcClusterizerv0::event(PHCompositeNode *root)
00503 {
00504   PHNodeIterator it(root);
00505 
00506   // OK. Te be able to work, we need some objects :
00507   // input : VtxOut and emcTowerContainer
00508   // output : emcClusterContainer
00509   //
00510   PHIODataNode<PHObject>* emcTowerContainerNode = 
00511     (PHIODataNode<PHObject>*)it.findFirst("PHIODataNode","emcTowerContainer");
00512   if ( !emcTowerContainerNode ) 
00513     {
00514       cerr << __FILE__ << ":" << __LINE__ << " cannot find emcTowerContainer "
00515            << "node." << endl;
00516       return false;
00517     }
00518   emcTowerContainer* towers = 
00519     static_cast<emcTowerContainer*>(emcTowerContainerNode->getData());
00520   if (!towers)
00521     {
00522       cerr << __FILE__ << ":" << __LINE__ << " cannot find emcTowerContainer "
00523            << "object." << endl;
00524       return false;
00525     }
00526 
00527   if ( !towers->isValid() ) return false;
00528 
00529   PHIODataNode<PHObject>* emcClusterContainerNode =
00530     (PHIODataNode<PHObject>*)it.findFirst("PHIODataNode",
00531                                           "emcClusterContainer");
00532   if ( !emcClusterContainerNode ) 
00533     {
00534       cerr << __FILE__ << ":" << __LINE__ 
00535            << " cannot find emcClusterContainer node." << endl;
00536       return false;
00537     }
00538 
00539   fClusters = 
00540     static_cast<emcClusterContainer*>(emcClusterContainerNode->getData());
00541   if (!fClusters)
00542     {
00543       cerr << __FILE__ << ":" << __LINE__ 
00544            << " cannot find emcClusterContainer object." << endl;
00545       return false;
00546     }
00547   else
00548     {
00549       fClusters->Reset();
00550     }
00551 
00552   PHIODataNode<PHObject>* vtxoutnode =
00553     (PHIODataNode<PHObject>*)it.findFirst("PHIODataNode", "VtxOut");
00554   
00555   VtxOut* vtxout = 0;
00556 
00557   if ( vtxoutnode )
00558     {
00559       vtxout = static_cast<VtxOut*>(vtxoutnode->getData());
00560     }
00561 
00562   fVertex.resize(3,0);
00563 
00564   if ( !vtxoutnode || !vtxout )
00565     {
00566       cout << PHWHERE << " No information (vtxout) about vertex. Assuming "
00567            << "(0,0,0)" << endl;
00568 
00569       for ( int i = 0; i < 3; ++i )
00570         {
00571           fVertex[i] = 0.0;
00572         }
00573     }
00574   else
00575     {
00576       PHPoint vertex = vtxout->get_Vertex();
00577       fVertex[0] = vertex.getX();
00578       fVertex[1] = vertex.getY();
00579       fVertex[2] = vertex.getZ();
00580     }
00581 
00582   if (!(fabs(fVertex[0]) < 10.0 &&
00583         fabs(fVertex[1]) < 10.0 &&
00584         fabs(fVertex[2]) < 100.0))
00585     {
00586       // Reset vertex to 0 and do clustering in case of nonvalid/bad vertex
00587       for ( int i = 0; i < 3; ++i )
00588         {
00589           fVertex[i] = 0.0;
00590         }
00591       //      cout << PHWHERE << "No clustering done, bad Vertex=("
00592       //           << fVertex[0] << ", "
00593       //           << fVertex[1] << ", "
00594       //           << fVertex[2] << ")"
00595       //           << endl;
00596       //      return false;
00597     }
00598 
00599   // Fine. We get everything we need. Let's continue.
00600 
00601   // Fill the internal hit list from towers read from the node tree.
00602   fillHitList(*towers);
00603 
00604   EmcPeakarea pPList[MAX_NUMBER_OF_PEAKS];
00605   EmcModule peaks[MAX_NUMBER_OF_PEAKS];
00606 
00607   //==========> Start looping over sectors <========== 
00608   for ( int is = 0; is < MAX_SECTORS_PROCESS; ++is )
00609     {
00610       EmcSectorRec* SectorRec = (is < 6) ? fScSector[is] : fGlSector[is - 6];
00611       int arm, sector;
00612 
00613       if (is <= 3)
00614         {
00615           arm = 0;
00616           sector = is;
00617         }
00618       else
00619         {
00620           arm = 1;
00621           sector = 7 - is;
00622         }
00623 
00624       float MinClusterEnergy = (is < 6) ? fMinClusterEnergySc : 
00625         fMinClusterEnergyGl;
00626 
00627       SectorRec->SetVertex(&fVertex[0]);
00628       SectorRec->SetModules(&HitList[is]);
00629       int nCl = SectorRec->FindClusters();
00630       vector<EmcCluster>* ClusterList = SectorRec->GetClusters();
00631 
00632       if (nCl < 0)
00633         {
00634           cerr << " ?????? " << name << ": Increase parameter MaxLen !!!"
00635                << endl;
00636           return false;
00637         }
00638 
00639       // Fill cluster table
00640       // Start looping on clusters
00641 
00642       vector<EmcCluster>::iterator pc;
00643 
00644       for ( pc = ClusterList->begin(); pc != ClusterList->end(); ++pc )
00645         {
00646           int npk = (*pc).GetPeaks(pPList, peaks);
00647           EmcPeakarea* pp = pPList;
00648           assert(pp!=0);
00649 
00650           for ( int ip = 0; ip < npk; ++ip )
00651             { 
00652               if (pp->GetTotalEnergy() > MinClusterEnergy) 
00653                 {
00654                   fillPeakArea(*pp,(*pc), arm, sector);
00655                 }
00656               pp++;
00657             } // end of loop over peakareas of cluster (*pc)
00658         } // end loop over clusters of sector is
00659     } // end of loop over sectors
00660 
00661   return true;
00662 }
00663 
00664 void
00665 mEmcClusterizerv0::ToF_Process(EmcModule* phit, size_t nhits,
00666                                float dist, EmcModule& hmax,
00667                                float* ptof, float* petof, float* ptofcorr,
00668                                float* pdtof,
00669                                float* ptofmin, float* petofmin, 
00670                                float* ptofmincorr,
00671                                float* ptofmax, float* petofmax, 
00672                                float* ptofmaxcorr,
00673                                float& tofdisp)
00674 {
00675   float tof, tofcorr, etof, tflash;
00676   float tofmin, tofmincorr, etofmin, tofmax, tofmaxcorr, etofmax;
00677   EmcModule* ph;
00678 
00679   tof = hmax.tof;
00680   etof = hmax.amp;
00681 
00682   tofmax = 0;
00683   tofmin = 999;
00684   etofmax = 0;
00685   etofmin = 0;
00686   ph = phit;
00687 
00688   float tofsum=0;
00689   float tofsum2=0;
00690   int nsum = 0;
00691 
00692   for ( size_t i = 0; i < nhits; i++)
00693     {
00694       if (ph->amp > 0)
00695         {
00696           if (ph->tof > tofmax)
00697             {
00698               tofmax = ph->tof;
00699               etofmax = ph->amp;
00700             }
00701           if (ph->tof < tofmin)
00702             {
00703               tofmin = ph->tof;
00704               etofmin = ph->amp;
00705             }
00706           tofsum += ph->tof;
00707           tofsum2 += ph->tof * ph->tof;
00708           ++nsum;
00709         }
00710       ph++;
00711     }
00712 
00713   if ( nsum > 1 )
00714     {
00715       float tofmean = tofsum/nsum;
00716       tofdisp = sqrt((tofsum2 - nsum*tofmean*tofmean)/(nsum-1));
00717     }
00718   else
00719     {
00720       tofdisp = 0;
00721     }
00722 
00723   tflash = dist / 30.0;
00724 
00725   tof = tof - tflash;
00726   tofmin = tofmin - tflash;
00727   tofmax = tofmax - tflash;
00728 
00729   tofcorr = tof;
00730   tofmincorr = tofmin;
00731   tofmaxcorr = tofmax;
00732 
00733   *ptof = tof;
00734   *petof = etof;
00735   *ptofcorr = tofcorr;
00736   *pdtof = 0;
00737   *ptofmax = tofmax;
00738   *petofmax = etofmax;
00739   *ptofmaxcorr = tofmaxcorr;
00740   *ptofmin = tofmin;
00741   *petofmin = etofmin;
00742   *ptofmincorr = tofmincorr;
00743 }