14 #include <TGeoManager.h>
15 #include <TVirtualMC.h>
16 #include <TParticle.h>
17 #include <TClonesArray.h>
21 #include <FairRootManager.h>
22 #include <FairMCApplication.h>
23 #include <FairPrimaryGenerator.h>
24 #include <FairMCEventHeader.h>
34 double n_phase(
const double & lambda_um,
const double* sellmeier_coefficients)
36 double lambda_um_sq = lambda_um*lambda_um;
37 return sqrt( sellmeier_coefficients[0]/(1.0-(sellmeier_coefficients[3]/lambda_um_sq))
38 + sellmeier_coefficients[1]/(1.0-(sellmeier_coefficients[4]/lambda_um_sq))
39 + sellmeier_coefficients[2]/(1.0-(sellmeier_coefficients[5]/lambda_um_sq))
49 PndDisc::PndDisc() : FairDetector(), clarr_sensor_hits(NULL), clarr_particle_tracks(NULL),
50 nextid_clarr_sensor_hits(0), nextid_clarr_particle_tracks(0),
51 ev_header(NULL), design_id(0), wl_min_nm(385.0), wl_max_nm(430.0)
58 : FairDetector(name, active, det_id), store_photon_tracks(kFALSE),
59 clarr_sensor_hits(NULL), clarr_particle_tracks(NULL),
60 nextid_clarr_sensor_hits(0), nextid_clarr_particle_tracks(0),
61 ev_header(NULL), design_id(0), wl_min_nm(385.0), wl_max_nm(430.0)
105 TString fname = GetGeometryFileName();
106 if(!fname.EndsWith(
".root"))
108 LOG(ERROR) <<
"Geometry format not supported.";
112 if(!fname.CompareTo(
"DIRC_GEO_LIF1.root"))
114 LOG(WARNING) <<
"Wrong filename: (%s). DiscDIRC_Detector is expecting geo file DIRC_GEO_LRD.root." << fname.Data();
130 ConstructRootGeometry();
139 LOG(INFO) <<
"DiscDIRC_Detector::ConstructOpGeometry()";
145 gMC->DefineOpSurface(
"DiscDIRC_focel_mirror_surf", kGlisur, kDielectric_metal, kPolished, 0.0);
147 Double_t e_photon[] = {1.0e-09, 7.0e-09};
150 gMC->SetMaterialProperty(
"DiscDIRC_focel_mirror_surf",
"REFLECTIVITY", 2, e_photon, r_coeff);
151 gMC->SetMaterialProperty(
"DiscDIRC_focel_mirror_surf",
"EFFICIENCY", 2, e_photon, efficiency);
154 gMC->DefineOpSurface(
"DiscDIRC_filter_a_surf", kGlisur, kDielectric_dielectric, kPolished, 0.0);
158 Double_t e_photon_a[] = {1.0e-09, band_a_min, band_a_min+1E-11, band_a_max, band_a_max+1E-11, 7.0e-09};
159 Double_t transmittance[] = {1E-10, 1E-10, 1., 1., 1E-10, 1E-10};
160 gMC->SetMaterialProperty(
"DiscDIRC_filter_a_surf",
"TRANSMITTANCE", 6, e_photon_a, transmittance);
167 gMC->SetBorderSurface(
"rad_interface_0_1",
"DiscDIRC_Radiator",0,
"DiscDIRC_Radiator",1,
"DiscDIRC_focel_mirror_surf");
168 gMC->SetBorderSurface(
"rad_interface_1_0",
"DiscDIRC_Radiator",1,
"DiscDIRC_Radiator",0,
"DiscDIRC_focel_mirror_surf");
170 gMC->SetBorderSurface(
"rad_interface_1_2",
"DiscDIRC_Radiator",1,
"DiscDIRC_Radiator",2,
"DiscDIRC_focel_mirror_surf");
171 gMC->SetBorderSurface(
"rad_interface_2_1",
"DiscDIRC_Radiator",2,
"DiscDIRC_Radiator",1,
"DiscDIRC_focel_mirror_surf");
173 gMC->SetBorderSurface(
"rad_interface_2_3",
"DiscDIRC_Radiator",2,
"DiscDIRC_Radiator",3,
"DiscDIRC_focel_mirror_surf");
174 gMC->SetBorderSurface(
"rad_interface_3_2",
"DiscDIRC_Radiator",3,
"DiscDIRC_Radiator",2,
"DiscDIRC_focel_mirror_surf");
176 gMC->SetBorderSurface(
"rad_interface_3_0",
"DiscDIRC_Radiator",3,
"DiscDIRC_Radiator",0,
"DiscDIRC_focel_mirror_surf");
177 gMC->SetBorderSurface(
"rad_interface_0_3",
"DiscDIRC_Radiator",0,
"DiscDIRC_Radiator",3,
"DiscDIRC_focel_mirror_surf");
179 gMC->SetBorderSurface(
"rad_hole_interface_0",
"DiscDIRC_Radiator",0,
"DiscDIRC_hole",0,
"DiscDIRC_focel_mirror_surf");
180 gMC->SetBorderSurface(
"rad_hole_interface_1",
"DiscDIRC_Radiator",1,
"DiscDIRC_hole",0,
"DiscDIRC_focel_mirror_surf");
181 gMC->SetBorderSurface(
"rad_hole_interface_2",
"DiscDIRC_Radiator",2,
"DiscDIRC_hole",0,
"DiscDIRC_focel_mirror_surf");
182 gMC->SetBorderSurface(
"rad_hole_interface_3",
"DiscDIRC_Radiator",3,
"DiscDIRC_hole",0,
"DiscDIRC_focel_mirror_surf");
185 for(i=0; i<4*n_fel; i++)
188 sprintf(str_name,
"DiscDIRC_focel_a_window_a_%d", i);
189 gMC->SetBorderSurface(str_name,
"DiscDIRC_sensor_window", i,
"DiscDIRC_focel_a", i,
"DiscDIRC_filter_a_surf");
190 sprintf(str_name,
"DiscDIRC_focel_a_window_b_%d", i);
191 gMC->SetBorderSurface(str_name,
"DiscDIRC_focel_a", i,
"DiscDIRC_sensor_window", i,
"DiscDIRC_filter_a_surf");
193 sprintf(str_name,
"DiscDIRC_focel_b_window_a_%d", i);
194 gMC->SetBorderSurface(str_name,
"DiscDIRC_sensor_window", i,
"DiscDIRC_focel_b", i,
"DiscDIRC_filter_a_surf");
195 sprintf(str_name,
"DiscDIRC_focel_b_window_b_%d", i);
196 gMC->SetBorderSurface(str_name,
"DiscDIRC_focel_b", i,
"DiscDIRC_sensor_window", i,
"DiscDIRC_filter_a_surf");
198 sprintf(str_name,
"DiscDIRC_focel_c_window_a_%d", i);
199 gMC->SetBorderSurface(str_name,
"DiscDIRC_sensor_window", i,
"DiscDIRC_focel_c", i,
"DiscDIRC_filter_a_surf");
200 sprintf(str_name,
"DiscDIRC_focel_c_window_b_%d", i);
201 gMC->SetBorderSurface(str_name,
"DiscDIRC_focel_c", i,
"DiscDIRC_sensor_window", i,
"DiscDIRC_filter_a_surf");
204 sprintf(str_name,
"DiscDIRC_focel_a_mirror_a_%d", i);
205 gMC->SetBorderSurface(str_name,
"DiscDIRC_focel_mirror_a", i,
"DiscDIRC_focel_a", i,
"DiscDIRC_focel_mirror_surf");
206 sprintf(str_name,
"DiscDIRC_focel_a_mirror_b_%d", i);
207 gMC->SetBorderSurface(str_name,
"DiscDIRC_focel_a", i,
"DiscDIRC_focel_mirror_a", i,
"DiscDIRC_focel_mirror_surf");
209 sprintf(str_name,
"DiscDIRC_focel_b_mirror_a_%d", i);
210 gMC->SetBorderSurface(str_name,
"DiscDIRC_focel_mirror_b", i,
"DiscDIRC_focel_b", i,
"DiscDIRC_focel_mirror_surf");
211 sprintf(str_name,
"DiscDIRC_focel_b_mirror_b_%d", i);
212 gMC->SetBorderSurface(str_name,
"DiscDIRC_focel_b", i,
"DiscDIRC_focel_mirror_b", i,
"DiscDIRC_focel_mirror_surf");
214 sprintf(str_name,
"DiscDIRC_focel_c_mirror_a_%d", i);
215 gMC->SetBorderSurface(str_name,
"DiscDIRC_focel_mirror_c", i,
"DiscDIRC_focel_c", i,
"DiscDIRC_focel_mirror_surf");
216 sprintf(str_name,
"DiscDIRC_focel_c_mirror_b_%d", i);
217 gMC->SetBorderSurface(str_name,
"DiscDIRC_focel_c", i,
"DiscDIRC_focel_mirror_c", i,
"DiscDIRC_focel_mirror_surf");
222 Double_t sellmeier_coeff[6] = {0.473115591, 0.631038719, 0.906404498,
223 0.012995717, 0.0041280992, 98.7685322 };
225 const int n_entries = 800 - 200;
227 Double_t rayleigh_length[n_entries];
229 for(i=0, lambda_um = 0.8; i<n_entries; lambda_um-=0.001, i++)
231 photon_momenta[
i] = 1.239841939*1E-6/lambda_um;
232 Double_t rindex = n_phase(lambda_um, sellmeier_coeff);
233 rayleigh_length[
i] = 1E6/(45962092085.3903 * pow(rindex, 8.)/pow(lambda_um*1000.0, 4.)) *10.0;
236 gMC->SetMaterialProperty( gMC->MediumId(
"FusedSilica"),
"RAYLEIGH", n_entries, photon_momenta, rayleigh_length );
237 gMC->SetMaterialProperty( gMC->MediumId(
"FusedSilicaB"),
"RAYLEIGH", n_entries, photon_momenta, rayleigh_length );
250 #ifdef DISC_DIRC_VERBOSE
251 fLogger->GetLogger()->Info(MESSAGE_ORIGIN,
252 "tracknumber %d", gMC->GetStack()->GetCurrentTrackNumber() );
260 #ifdef DISC_DIRC_VERBOSE
261 fLogger->GetLogger()->Info(MESSAGE_ORIGIN,
262 "tracknumber %d", gMC->GetStack()->GetCurrentTrackNumber() );
270 static TVector3 pos_in, mom_in;
271 static Double_t integrated_energy_deposit;
273 const Int_t pid_optical_photon = 50000050;
275 static const Int_t sensor_volume_id = gMC->VolId(
"DiscDIRC_sensor_pmt");
276 static const Int_t radiator_volume_id = gMC->VolId(
"DiscDIRC_Radiator");
277 static const Int_t prism_a_volume_id = gMC->VolId(
"DiscDIRC_prism_a");
278 static const Int_t prism_b_volume_id = gMC->VolId(
"DiscDIRC_prism_b");
279 static const Int_t prism_c_volume_id = gMC->VolId(
"DiscDIRC_prism_c");
284 static Bool_t entered_inside = kFALSE;
285 static Int_t entered_track_id = -1;
286 static Int_t continued_track = -1;
288 TParticle *
track = gMC->GetStack()->GetCurrentTrack();
291 static Int_t current_track;
292 if(gMC->IsTrackEntering())
294 current_track = gMC->GetStack()->GetCurrentTrackNumber();
298 if(current_track!=gMC->GetStack()->GetCurrentTrackNumber())
300 LOG(WARNING) <<
"LOGIC ERROR: ProcessHits called with track (%d) that has not entered the volume!" << gMC->GetStack()->GetCurrentTrackNumber();
305 Int_t volume_id, copy_no;
306 volume_id = gMC->CurrentVolID(copy_no);
308 if(gMC->TrackPid() == pid_optical_photon)
314 gMC->TrackPosition(pos);
315 gMC->TrackMomentum(mom);
317 Double_t mom_mag = mom.Vect().Mag();
319 if(volume_id == radiator_volume_id)
324 double internal_reflection_angle =
TMath::Pi()/2.0 - mom.Vect().Theta();
328 else if(volume_id == prism_a_volume_id ||
329 volume_id == prism_b_volume_id ||
330 volume_id == prism_c_volume_id)
332 std::map<int, std::pair<TLorentzVector,TLorentzVector> >::iterator it =
photons_entering_optics.find(current_track);
334 TLorentzVector pos_local, mom_local;
335 TString vol_path(gMC->CurrentVolPath());
337 TGeoHMatrix * transform =
gGeoManager->GetCurrentMatrix();
340 pos.Vect().GetXYZ(p1);
341 transform->MasterToLocal(p1, p2);
342 pos_local.SetXYZT(p2[0], p2[1], p2[2], 0.0);
344 mom.Vect().GetXYZ(p1);
345 transform->MasterToLocalVect(p1, p2);
346 mom_local.SetXYZT(p2[0], p2[1], p2[2], 0.0);
347 photons_entering_optics.insert(std::pair<
int, std::pair<TLorentzVector,TLorentzVector> >(current_track, std::pair<TLorentzVector,TLorentzVector>(pos_local, mom_local)));
351 if( (mom_mag<1.239841939*1.e-06/
wl_max_nm) || (mom_mag>1.239841939*1.e-06/
wl_min_nm) )
355 if(gMC->IsTrackEntering() && volume_id==sensor_volume_id)
357 TString vol_path(gMC->CurrentVolPath());
359 TGeoHMatrix * transform =
gGeoManager->GetCurrentMatrix();
363 pos.Vect().GetXYZ(p1);
364 transform->MasterToLocal(p1, p2);
365 pos.SetXYZT(p2[0], p2[1], p2[2], 0.0);
367 mom.Vect().GetXYZ(p1);
368 transform->MasterToLocalVect(p1, p2);
369 mom.SetXYZT(p2[0], p2[1], p2[2], 0.0);
372 if(fVerboseLevel > 0)
374 "track->T(): "<<track->T()<<
"\tgMC->TrackTime(): "<<gMC->TrackTime()<<
"\tev_header->GetT(): "
382 LOG(WARNING) <<
"No registered total internal reflection angle for photon track id "<<current_track<<
"\n";
389 Int_t volume_uid =
gGeoManager->GetUID(gMC->VolName(volume_id));
391 std::cout <<
"Sensor number: " << copy_no <<
", volume id: " << volume_uid <<
", photon position: x = " << pos[0] <<
" y = " << pos[1] <<
" z = " << pos[2] << std::endl;
396 gMC->GetStack()->GetCurrentTrackNumber(),
402 gMC->TrackTime()*1E9,
409 std::map<int, std::pair<TLorentzVector,TLorentzVector> >::iterator it_optics =
photons_entering_optics.find(current_track);
411 LOG(WARNING) <<
"No registered optics entrance data for photon track id "<<current_track<<
"\n";
426 gMC->TrackPosition(pos);
427 gMC->TrackMomentum(mom);
429 if(gMC->IsTrackEntering() || (!gMC->IsTrackEntering() && entered_track_id<0))
431 if(entered_track_id >= 0)
432 LOG(FATAL) <<
"Track entering but processing of preceding track was not finished !!!";
434 entered_track_id = gMC->GetStack()->GetCurrentTrackNumber();
435 if(entered_track_id<0)
436 LOG(FATAL) <<
"Track entering has neg id !!!";
438 std::map<int, std::pair<int, double> >::iterator it =
last_track_occurence.find(entered_track_id);
440 continued_track = -1;
443 if( volume_id == pt->
volume_id || copy_no == pt->GetDetectorID() || gMC->TrackTime() == it->second.second ) {
444 continued_track = it->second.first;
447 if(fVerboseLevel > 0) LOG(INFO) << Form(
"Continued: Track id %d, (vol %d, cpn %d, z=%f, T=%g, pdg %d)", entered_track_id, volume_id, copy_no, pos.Z(), gMC->TrackTime(), gMC->TrackPid());
451 if(continued_track < 0)
455 integrated_energy_deposit = 0.0;
456 entered_inside = gMC->IsNewTrack();
457 if(fVerboseLevel > 0) LOG(INFO) << Form(
"Entered: Track id %d, (vol %d, cpn %d, z=%f, T=%g, pdg %d)", entered_track_id, volume_id, copy_no, pos.Z(), gMC->TrackTime() ,gMC->TrackPid());
461 if(entered_track_id >= 0) {
462 if(entered_track_id != gMC->GetStack()->GetCurrentTrackNumber() )
463 LOG(FATAL) <<
"Track id changed !!! Need a stack !!!";
464 integrated_energy_deposit += gMC->Edep();
465 if(fVerboseLevel > 0) LOG(INFO) <<
"Add eloss for: Track id " << entered_track_id;
470 if(gMC->IsTrackExiting() || gMC->IsTrackStop() || gMC->IsTrackDisappeared() || !gMC->IsTrackAlive())
473 if(entered_track_id != gMC->GetStack()->GetCurrentTrackNumber() )
474 LOG(FATAL) <<
"Track exiting without having entered (entered id = "<< entered_track_id<<
")";
476 if(fVerboseLevel > 0) LOG(INFO) << Form(
"Exiting: Track id %d (vol %d, cpn %d, Inside = %d, stop = %d, alive = %d, z=%f, T=%g)", entered_track_id, volume_id, copy_no, gMC->IsTrackInside(), gMC->IsTrackStop(), gMC->IsTrackAlive(), pos.Z(), gMC->TrackTime());
478 if(gMC->IsTrackStop() || !gMC->IsTrackInside() || gMC->IsTrackDisappeared() || !gMC->IsTrackAlive())
481 std::map<int, std::pair<int, double> >::iterator it =
last_track_occurence.find(entered_track_id);
488 it->second.second = gMC->TrackTime();
490 if(continued_track >= 0)
495 pt->SetTime(gMC->TrackTime()*1E9);
496 pt->SetLength(gMC->TrackLength());
497 pt->SetEnergyLoss(integrated_energy_deposit);
498 pt->
is_primary = gMC->GetStack()->GetCurrentTrack()->IsPrimary();
502 Int_t volume_uid =
gGeoManager->GetUID(gMC->VolName(volume_id));
512 gMC->TrackTime()*1E9,
514 integrated_energy_deposit,
519 gMC->GetStack()->GetCurrentTrack()->IsPrimary()
525 entered_track_id = -1;
529 LOG(INFO) << Form(
"Veto: Track id %d (Inside = %d)", entered_track_id, gMC->IsTrackInside());
541 ev_header = FairMCApplication::Instance()->GetGenerator()->GetEvent();
554 for(
int i=0;
i<n_entries;
i++)
567 FairRootManager::Instance()->Register(
"DiscSensorMCPoint",
"DiscPoint",
clarr_sensor_hits, serialized);
568 FairRootManager::Instance()->Register(
"DiscParticleMCPoint",
"DiscPoint",
clarr_particle_tracks, serialized);
584 default:
return NULL;
FairMCEventHeader * ev_header
virtual void Initialize()
Initialize will be called after the Geometry is created.
std::map< int, double > internal_reflection_angle_of_photons
TClonesArray * clarr_sensor_hits
virtual void BeginEvent()
friend F32vec4 sqrt(const F32vec4 &a)
TClonesArray * clarr_particle_tracks
optical photon tracks
virtual void Reset()
Interface implementation - reset the 'containers'.
virtual bool CheckIfSensitive(std::string name)
Interface implementation - Check if a given volume name belongs to a sensitive volume.
TGeoManager * gGeoManager
virtual void ConstructGeometry()
std::set< std::string > names_of_sensitive_volumes
virtual void Register()
Interface implementation - Register the data collections in FairRootManager.
TString pt(TString pts, TString exts="px py pz")
std::map< int, std::pair< int, double > > last_track_occurence
TVector3 photon_entering_pos
TVector3 photon_entering_momentum
std::map< int, std::pair< TLorentzVector, TLorentzVector > > photons_entering_optics
virtual Bool_t ProcessHits(FairVolume *v=0)
virtual TClonesArray * GetCollection(Int_t iColl) const
Interface implementation - Get a data collection by index.
int nextid_clarr_particle_tracks
int nextid_clarr_sensor_hits
tracks of other particles
Bool_t store_photon_tracks
Int_t volume_id
FairMCPoint forces the implementation.
void StorePhotonTracks(Bool_t bval)
Enable/Disable the storage of photon track information.
virtual void EndOfEvent()
Interface implementation - EndofEvent.
virtual void ConstructOpGeometry()
void SetFilterInterval(Double_t const &wl_min_nm_, Double_t const &wl_max_nm_)
Set the wavelength range of the bandpass filters.