// $Id$ // // File: DBCALShower_factory_SIMPLE.cc // Created: Tue Mar 20 14:44:12 EDT 2007 // Creator: davidl (on Darwin swire-b241.jlab.org 8.9.0 powerpc) // #include using namespace std; #include #include #include "DBCALShower_factory_SIMPLE.h" bool pshowerSort_C(const DBCALShower_factory_SIMPLE::pshower_t &hit1, const DBCALShower_factory_SIMPLE::pshower_t &hit2) { return hit1.E > hit2.E; } //------------------ // DBCALShower_factory_SIMPLE (Constructor) //------------------ DBCALShower_factory_SIMPLE::DBCALShower_factory_SIMPLE() { UP_DOWN_COINCIDENCE_WINDOW = 50.0; // in ns ENERGY_SCALE_FACTOR = 1.0; // scale factor for converting energy to GeV (1.1 is empirical) SIGNAL_VELOCITY = 16.75; // in cm/ns ATTENUATION_LENGTH = 300.0; // in cm Z_CENTER = 17.0+0.5+390.0/2.0; // in cm (0.5 is empirical) MIN_CLUSTER_SPACING = 50.0; // in cm MIN_SHOWER_ENERGY = 0.001; // in GeV DEBUG_HISTS = true; gPARMS->SetDefaultParameter("BCAL:UP_DOWN_COINCIDENCE_WINDOW", UP_DOWN_COINCIDENCE_WINDOW); gPARMS->SetDefaultParameter("BCAL:ENERGY_SCALE_FACTOR", ENERGY_SCALE_FACTOR); gPARMS->SetDefaultParameter("BCAL:SIGNAL_VELOCITY", SIGNAL_VELOCITY); gPARMS->SetDefaultParameter("BCAL:ATTENUATION_LENGTH", ATTENUATION_LENGTH); gPARMS->SetDefaultParameter("BCAL:Z_CENTER", Z_CENTER); gPARMS->SetDefaultParameter("BCAL:MIN_CLUSTER_SPACING", MIN_CLUSTER_SPACING); gPARMS->SetDefaultParameter("BCAL:MIN_SHOWER_ENERGY", MIN_SHOWER_ENERGY); gPARMS->SetDefaultParameter("BCAL:DEBUG_HISTS", DEBUG_HISTS); hit_element_dist=NULL; } //------------------ // brun //------------------ jerror_t DBCALShower_factory_SIMPLE::brun(JEventLoop *eventLoop, int runnumber) { DApplication* dapp = dynamic_cast(eventLoop->GetJApplication()); if(DEBUG_HISTS){ dapp->Lock(); // Histograms may already exist. (Another thread may have created them) // Try and get pointers to the existing ones. hit_element_dist = (TH1F*)gROOT->FindObject("hit_element_dist"); hit_element_dist_z = (TH1F*)gROOT->FindObject("hit_element_dist_z"); hit_element_dist_phi = (TH1F*)gROOT->FindObject("hit_element_dist_phi"); hit_element_dist_r = (TH1F*)gROOT->FindObject("hit_element_dist_r"); x_vs_y_vs_z = (TH3F*)gROOT->FindObject("x_vs_y_vs_z"); r_shower = (TH1F*)gROOT->FindObject("r_shower"); phi_shower = (TH1F*)gROOT->FindObject("phi_shower"); z_shower = (TH1F*)gROOT->FindObject("z_shower"); E_shower = (TH1F*)gROOT->FindObject("E_shower"); r_element = (TH1F*)gROOT->FindObject("r_element"); phi_element = (TH1F*)gROOT->FindObject("phi_element"); z_element = (TH1F*)gROOT->FindObject("z_element"); E_element = (TH1F*)gROOT->FindObject("E_element"); E_upstream_vs_downstream = (TH2F*)gROOT->FindObject("E_upstream_vs_downstream"); E_clustersum = (TH1F*)gROOT->FindObject("E_clustersum"); E_elementsum = (TH1F*)gROOT->FindObject("E_elementsum"); if(!hit_element_dist)hit_element_dist = new TH1F("hit_element_dist","Distance between hit elements(cm)",300, 0.0, 300.0); if(!hit_element_dist_z)hit_element_dist_z = new TH1F("hit_element_dist_z","Distance in z between hit elements(cm)",300, -150.0, 150.0); if(!hit_element_dist_phi)hit_element_dist_phi = new TH1F("hit_element_dist_phi","Distance in phi between hit elements(degrees)",300, -180.0, 180.0); if(!hit_element_dist_r)hit_element_dist_r = new TH1F("hit_element_dist_r","Distance in r between hit elements(cm)",400, -100.0, 100.0); if(!x_vs_y_vs_z)x_vs_y_vs_z = new TH3F("x_vs_y_vs_z","X,Y,Z distribution of shower centers",100, -100.0, 100.0, 100, -100.0, 100.0, 100, -50.0, 550.0); if(!r_shower)r_shower = new TH1F("r_shower","radial distribution of shower centers",500, 0.0, 100.0); if(!phi_shower)phi_shower = new TH1F("phi_shower","#phi distribution of shower centers",360, 0.0, 360.0); if(!z_shower)z_shower = new TH1F("z_shower","z distribution of shower centers",700, -50.0, 650.0); if(!E_shower)E_shower = new TH1F("E_shower","Energy of shower (GeV)",1000, 0.0, 8.0); if(!r_element)r_element = new TH1F("r_element","radial distribution of element centers",500, 0.0, 100.0); if(!phi_element)phi_element = new TH1F("phi_element","#phi distribution of element centers",360, 0.0, 360.0); if(!z_element)z_element = new TH1F("z_element","z distribution of element centers",700, -50.0, 650.0); if(!E_element)E_element = new TH1F("E_element","Energy of element (GeV)",1000, 0.0, 2.0); if(!E_upstream_vs_downstream)E_upstream_vs_downstream = new TH2F("E_upstream_vs_downstream","Amplitude of upstream readout vs. downsteam readout for single elements",100, 0.0, 1.0, 100, 0.0, 1.0); if(!E_clustersum)E_clustersum = new TH1F("E_clustersum","Energy sum of all clusters (GeV)",1000, 0.0, 8.0); if(!E_elementsum)E_elementsum = new TH1F("E_elementsum","Energy sum of all elements (GeV)",1000, 0.0, 8.0); dapp->Unlock(); } return NOERROR; } //------------------ // evnt //------------------ jerror_t DBCALShower_factory_SIMPLE::evnt(JEventLoop *loop, int eventnumber) { // Get individual hits vector bcalhits; loop->Get(bcalhits); // Sort hits into upstream and downstream hits vector upstream_bcalhits; vector downstream_bcalhits; for(unsigned int i=0; iend == DBCALGeometry::kUpstream){upstream_bcalhits.push_back(hit); continue;} if(hit->end == DBCALGeometry::kDownstream){downstream_bcalhits.push_back(hit); continue;} _DBG_<<"Heyyy! How'd I get here?!?"< up_used(upstream_bcalhits.size(), false); vector down_used(downstream_bcalhits.size(), false); vector pshowers; for(unsigned int i=0; imodule != down->module)continue; if(up->layer != down->layer)continue; if(up->sector != down->sector)continue; // Check timing double tdiff = up->t - down->t; if(fabs(tdiff)>UP_DOWN_COINCIDENCE_WINDOW)continue; up_used[i] = true; down_used[j] = true; // Looks like a match! Add to list of coincidences pshower_t pshower; pshower.upstream_hit = up; pshower.downstream_hit = down; pshower.E = sqrt(up->E * down->E)*ENERGY_SCALE_FACTOR; pshower.t = (up->t + down->t)/2.0; pshower.z = Z_CENTER + SIGNAL_VELOCITY*(up->t - down->t)/2.0; ModuleLayerSectorToPhiR(up->module, up->layer, up->sector, pshower.phi, pshower.R); pshower.used = false; pshowers.push_back(pshower); if(DEBUG_HISTS){ r_element->Fill(pshower.R); phi_element->Fill(pshower.phi*180.0/M_PI); z_element->Fill(pshower.z); E_element->Fill(pshower.E); E_upstream_vs_downstream->Fill(down->E, up->E); } } } // Some hits are not used because a matching hit on the other end // was not found. This can represent a signifacnt amount of energy // in the cluster. Here, we loop over the hits and turn any un-used // single end hits into pshowers. Note that for now, we assume // knowledge of the attenutation length, signal propagation velocity, // and time offset. All of these should be known to some degree for // real data. for(unsigned int i=0; it; pshower.z = Z_CENTER + SIGNAL_VELOCITY*up->t; pshower.E = up->E*ENERGY_SCALE_FACTOR*exp(-(pshower.z-Z_CENTER)/ATTENUATION_LENGTH); ModuleLayerSectorToPhiR(up->module, up->layer, up->sector, pshower.phi, pshower.R); pshower.used = false; pshowers.push_back(pshower); } for(unsigned int i=0; it; pshower.z = Z_CENTER + SIGNAL_VELOCITY*down->t; pshower.E = down->E*ENERGY_SCALE_FACTOR*exp(-(pshower.z-Z_CENTER)/ATTENUATION_LENGTH); ModuleLayerSectorToPhiR(down->module, down->layer, down->sector, pshower.phi, pshower.R); pshower.used = false; pshowers.push_back(pshower); } // Sort pshowers by energy sort(pshowers.begin(), pshowers.end(), pshowerSort_C); // Sort pshowers into clusters. In this simple algorithm, the // largest energy pshower is assumed to be near a cluster center. // All pshowers within a certain distance of this are added to // the cluster and marked as used. The cycle starts again with // the largest energy, un-used pshower and continues until all // pshowers have been made into clusters for(unsigned int i=0; i cluster; cluster.clear(); cluster.push_back(&pshowers[i]); for(unsigned int j=i+1; jFill(dist); hit_element_dist_z->Fill(z1-z2); hit_element_dist_phi->Fill((phi1-phi2)*57.3); hit_element_dist_r->Fill(R1-R2); } if(dist>MIN_CLUSTER_SPACING)continue; pshowers[j].used = true; cluster.push_back(&pshowers[j]); } if(cluster.size()==0)break; // Loop over pshowers in this cluster and calculate logarithmically weighted means double x=0.0, y=0.0, z=0.0; double norm=0.0; double tmin = 1.0E6; double Etot = 0.0; for(unsigned int j=0; jE*1000.0); //double logE = pshower->E; norm += logE; x += pshower->R*cos(pshower->phi)*logE; y += pshower->R*sin(pshower->phi)*logE; z += pshower->z*logE; if(pshower->tt; Etot += pshower->E; } if(EtotE = Etot; shower->x = x; shower->y = y; shower->z = z; shower->t = tmin; _data.push_back(shower); if(DEBUG_HISTS){ r_shower->Fill(sqrt(x*x + y*y)); double phi = atan2(y,x)*180.0/M_PI; if(phi<0.0)phi+=360.0; phi_shower->Fill(phi); z_shower->Fill(z); x_vs_y_vs_z->Fill(x,y,z); E_shower->Fill(Etot); } } // A few more debugging histos if(DEBUG_HISTS){ // Total energy in all clusters(showers) double Etot = 0.0; for(unsigned int i=0; i<_data.size(); i++)Etot+=_data[i]->E; E_clustersum->Fill(Etot); // Total energy in all pshowers Etot = 0.0; for(unsigned int i=0; iFill(Etot); } return NOERROR; } //------------------ // FindZFromSingleHit //------------------ double DBCALShower_factory_SIMPLE::FindZFromSingleHit(const DBCALHit *hit) { double phi, R, z; ModuleLayerSectorToPhiR(hit->module, hit->layer, hit->sector, phi, R); double t = hit->end == DBCALGeometry::kUpstream ? -hit->t:hit->t; double zvertex = 65.0; double z0 = Z_CENTER - zvertex; _DBG_<<"z0="<9){ _DBG_<<"Layer out of range: "<4){ _DBG_<<"Sector out of range: "<3){ _DBG_<<"Sector out of range: "<x); printcol("%5.2f", s->y); printcol("%5.2f", s->z); printcol("%5.3f", s->t); printcol("%5.3f", s->E); printrow(); } return _table; }