diff --git a/UpstreamTagger/UpstreamTagger.cxx b/UpstreamTagger/UpstreamTagger.cxx index a5100d1f80..d26112b35c 100644 --- a/UpstreamTagger/UpstreamTagger.cxx +++ b/UpstreamTagger/UpstreamTagger.cxx @@ -36,7 +36,6 @@ #include "TParticle.h" #include "TVector3.h" #include "TVirtualMC.h" -#include "UpstreamTaggerHit.h" #include "UpstreamTaggerPoint.h" using ROOT::TSeq; using ShipUnit::cm; @@ -44,6 +43,36 @@ using ShipUnit::m; using std::cout; using std::endl; +constexpr uint64_t hash(std::string_view str) { + uint64_t hash = 0; + for (char c : str) { + hash = (hash * 131) + c; + } + return hash; +} + +constexpr uint64_t operator"" _hash(const char* str, size_t len) { + return hash(std::string_view(str, len)); +} + + +constexpr const int detPieces(std::string_view pieceName) noexcept{ + switch(hash(pieceName)){ + case "Upstream_Tagger_Plastic"_hash: + return 0; + case "ubt_gas_UBT1_y2_layer"_hash: + return 1; + case "ubt_gas_UBT1_v_layer"_hash: + return 2; + case "ubt_gas_UBT1_u_layer"_hash: + return 3; + case "ubt_gas_UBT1_y1_layer"_hash: + return 4; + default: + return 10; + } +} + UpstreamTagger::UpstreamTagger() : FairDetector("UpstreamTagger", kTRUE, kUpstreamTagger), fTrackID(-1), @@ -53,34 +82,41 @@ UpstreamTagger::UpstreamTagger() fTime(-1.), fLength(-1.), fELoss(-1), - // det_zPos(0), - - // - UpstreamTagger_fulldet(0), - scoringPlaneUBText(0), - // fUpstreamTaggerPoints(nullptr) {} -UpstreamTagger::UpstreamTagger(const char* name, Bool_t active) - : FairDetector(name, active, kUpstreamTagger), - fTrackID(-1), - fVolumeID(-1), - fPos(), - fMom(), - fTime(-1.), - fLength(-1.), - fELoss(-1), - // - det_zPos(0), +//UpstreamTagger::UpstreamTagger(const char* name, Bool_t active) +UpstreamTagger::UpstreamTagger(std::string medium) + : FairDetector("UpstreamTagger", kTRUE, kUpstreamTagger), + fMedium(medium), + fTrackID(-1), + fVolumeID(-1), + fPos(), + fMom(), + fTime(-1.), + fLength(-1.), + fELoss(-1), + det_zPos(0), + fUpstreamTaggerPoints(nullptr) {} - // - UpstreamTagger_fulldet(0), - scoringPlaneUBText(0), // Initialize new scoring plane to nullptr - // - fUpstreamTaggerPoints(nullptr) {} +UpstreamTagger::UpstreamTagger(const char* name, Bool_t active) + : FairDetector(name, active, kUpstreamTagger), + fTrackID(-1), + fVolumeID(-1), + fPos(), + fMom(), + fTime(-1.), + fLength(-1.), + fELoss(-1), + det_zPos(0), + fUpstreamTaggerPoints(nullptr) {} + + +void UpstreamTagger::Initialize() +{ + FairDetector::Initialize(); +} -void UpstreamTagger::Initialize() { FairDetector::Initialize(); } UpstreamTagger::~UpstreamTagger() { if (fUpstreamTaggerPoints) { @@ -109,7 +145,9 @@ Int_t UpstreamTagger::InitMedium(const char* name) { return 0; } -Bool_t UpstreamTagger::ProcessHits(FairVolume* vol) { + +Bool_t UpstreamTagger::ProcessHits(FairVolume* vol) +{ /** This method is called from the MC stepping */ // Set parameters at entrance of volume. Reset ELoss. if (gMC->IsTrackEntering()) { @@ -119,21 +157,21 @@ Bool_t UpstreamTagger::ProcessHits(FairVolume* vol) { gMC->TrackPosition(fPos); gMC->TrackMomentum(fMom); } - // Sum energy loss for all steps in the active volume fELoss += gMC->Edep(); // Create vetoPoint at exit of active volume - if (gMC->IsTrackExiting() || gMC->IsTrackStop() || - gMC->IsTrackDisappeared()) { - if (fELoss == 0.) { - return kFALSE; - } - - fTrackID = gMC->GetStack()->GetCurrentTrackNumber(); + if ( gMC->IsTrackExiting() || + gMC->IsTrackStop() || + gMC->IsTrackDisappeared() ) { + if (fELoss == 0. ) { return kFALSE; } + fTrackID = gMC->GetStack()->GetCurrentTrackNumber(); Int_t uniqueId; gMC->CurrentVolID(uniqueId); + const char* volName = gMC->CurrentVolName(); + std::cout<<"volume id: "< 1000000) // Solid scintillator case { Int_t vcpy; @@ -151,7 +189,7 @@ Bool_t UpstreamTagger::ProcessHits(FairVolume* vol) { Double_t ymean = (fPos.Y() + Pos.Y()) / 2.; Double_t zmean = (fPos.Z() + Pos.Z()) / 2.; - AddHit(fTrackID, uniqueId, TVector3(xmean, ymean, zmean), + AddHit(fTrackID, uniqueId, subDetID, TVector3(xmean, ymean, zmean), TVector3(fMom.Px(), fMom.Py(), fMom.Pz()), fTime, fLength, fELoss, pdgCode, TVector3(Pos.X(), Pos.Y(), Pos.Z()), TVector3(Mom.Px(), Mom.Py(), Mom.Pz())); @@ -172,7 +210,6 @@ void UpstreamTagger::Register() { this collection will not be written to the file, it will exist only during the simulation. */ - fUpstreamTaggerPoints = new std::vector(); FairRootManager::Instance()->RegisterAny("UpstreamTaggerPoint", fUpstreamTaggerPoints, kTRUE); @@ -196,44 +233,258 @@ void UpstreamTagger::UpdatePointTrackIndices( void UpstreamTagger::Reset() { fUpstreamTaggerPoints->clear(); } -void UpstreamTagger::ConstructGeometry() { - TGeoVolume* top = gGeoManager->GetTopVolume(); +void UpstreamTagger::SetzPositions(Double_t z1) +{ + f_T1_z = z1; //! z-position of tracking station 1 +} - ////////////////////////////////////////////////////// +void UpstreamTagger::SetApertureArea(Double_t width, Double_t height, Double_t length) +{ + f_aperture_width = width; //! Aperture width (x) + f_aperture_height = height; //! Aperture height (y) + f_station_length = length; +} - /////////////////////////////////////////////////////// +void UpstreamTagger::SetStrawDiameter(Double_t outer_straw_diameter, Double_t wall_thickness) +{ + f_outer_straw_diameter = outer_straw_diameter; //! Outer straw diameter + f_inner_straw_diameter = + outer_straw_diameter - 2 * wall_thickness; //! Inner straw diameter +} - /////////////////////////////////////////////////////// +void UpstreamTagger::SetStrawPitch(Double_t straw_pitch, Double_t layer_offset) +{ + f_straw_pitch = straw_pitch; //! Distance (y) between straws in a layer + f_offset_layer = layer_offset; //! Offset (y) of straws between layers +} - InitMedium("vacuum"); - TGeoMedium* Vacuum_box = gGeoManager->GetMedium("vacuum"); - /////////////////////////////////////////////////////////////////// +void UpstreamTagger::SetDeltazLayer(Double_t delta_z_layer) +{ + f_delta_z_layer = delta_z_layer; //! Distance (z) between layers +} - // Adding UBT Extension - if (!Vacuum_box) { - Fatal("ConstructGeometry", "Medium 'vacuum' not found."); - } +void UpstreamTagger::SetStereoAngle(Double_t stereo_angle) +{ + f_view_angle = stereo_angle; //! Stereo view angle +} - UpstreamTagger_fulldet = - gGeoManager->MakeBox("Upstream_Tagger", Vacuum_box, xbox_fulldet / 2.0, - ybox_fulldet / 2.0, zbox_fulldet / 2.0); - UpstreamTagger_fulldet->SetLineColor(kGreen); +void UpstreamTagger::SetWireThickness(Double_t wire_thickness) +{ + f_wire_thickness = wire_thickness; //! Sense wire thickness +} - top->AddNode(UpstreamTagger_fulldet, 1, - new TGeoTranslation(0.0, 0.0, det_zPos)); - AddSensitiveVolume(UpstreamTagger_fulldet); - cout << " Z Position (Upstream Tagger1) " << det_zPos << endl; - ////////////////////////////////////////////////////////////////// +void UpstreamTagger::SetDeltazView(Double_t delta_z_view) +{ + f_delta_z_view = delta_z_view; //! Distance (z) between stereo views +} + +void UpstreamTagger::SetFrameMaterial(TString frame_material) +{ + f_frame_material = frame_material; //! Structure frame material +} - return; +void UpstreamTagger::ConstructGeometry() +{ + + /** If you are using the standard ASCII input for the geometry + just copy this and use it for your detector, otherwise you can + implement here you own way of constructing the geometry. */ + + std::cout<<"Making a geometry"<GetTopVolume(); + InitMedium("air"); + TGeoMedium *air = gGeoManager->GetMedium("air"); + InitMedium("mylar"); + TGeoMedium *mylar = gGeoManager->GetMedium("mylar"); + InitMedium("STTmix8020_1bar"); + TGeoMedium *sttmix8020_1bar = gGeoManager->GetMedium("STTmix8020_1bar"); + InitMedium("tungsten"); + TGeoMedium *tungsten = gGeoManager->GetMedium("tungsten"); + InitMedium(f_frame_material); + TGeoMedium *FrameMatPtr = gGeoManager->GetMedium(f_frame_material); + InitMedium(fMedium.c_str()); + TGeoMedium* med = gGeoManager->GetMedium(fMedium.c_str()); + + gGeoManager->SetVisLevel(4); + gGeoManager->SetTopVisible(); + + Double_t eps = 0.0001; // Epsilon to avoid overlapping volumes + Double_t straw_length = f_aperture_width;// + 2. * eps; // Straw (half) length + Double_t frame_width = 9.; // Width of frame metal + Double_t floor_offset = 14.; // Offset due to floor space limitation + Double_t rmin, rmax, T_station_z; + Double_t max_stereo_growth = TMath::Tan(TMath::Abs(f_view_angle) * TMath::Pi() / 180.0) * straw_length; + + // Arguments of boxes are half-lengths + TGeoBBox* detbox1 = new TGeoBBox( + "ubt_detbox1", + (straw_length + frame_width), + (f_aperture_height + 4*max_stereo_growth + frame_width - floor_offset / 2.), + f_station_length); + TGeoBBox* detbox2 = new TGeoBBox( + "ubt_detbox2", + (straw_length + eps), + (f_aperture_height + 4*max_stereo_growth - floor_offset / 2. + eps), + f_station_length + eps); + + TGeoTranslation* move_up = new TGeoTranslation("ubt_move_up", 0, floor_offset / 2., 0); + move_up->RegisterYourself(); + + // Composite shape to create frame + TGeoCompositeShape* detcomp1 = new TGeoCompositeShape("ubt_detcomp1", "ubt_detbox1:ubt_move_up - ubt_detbox2"); + + // Volume: straw - Third argument is half-length of tube + TGeoTube *straw_tube = new TGeoTube("ubt_straw", f_inner_straw_diameter / 2., f_outer_straw_diameter / 2., straw_length); + TGeoVolume *straw = new TGeoVolume("ubt_straw", straw_tube, mylar); + straw->SetLineColor(4); + // Volume: gas - Only the gas is sensitive +// TGeoTube *gas_tube = new TGeoTube("ubt_gas", f_wire_thickness / 2. + eps, f_inner_straw_diameter / 2. - eps, straw_length - 2. * eps); +// TGeoVolume *gas = new TGeoVolume("ubt_gas", gas_tube, sttmix8020_1bar); +// gas->SetLineColor(5); +// AddSensitiveVolume(gas); + // Volume: wire + TGeoTube *wire_tube = new TGeoTube("ubt_wire", 0., f_wire_thickness / 2., straw_length - 4. * eps); + TGeoVolume *wire = new TGeoVolume("ubt_wire", wire_tube, tungsten); + wire->SetLineColor(6); + + // Station box to contain all components + TGeoBBox* statbox = new TGeoBBox("ubt_statbox", straw_length + frame_width, f_aperture_height + frame_width + 4*max_stereo_growth - floor_offset / 2., f_station_length); + f_frame_material.ToLower(); + + for (Int_t statnb = 1; statnb < 2; statnb++) { + // Tracking station loop + TString nmstation = "UBT"; + std::stringstream ss; + ss << statnb; + nmstation = nmstation + ss.str(); + switch (statnb) { + case 1: + T_station_z = f_T1_z; + break; + default: + T_station_z = f_T1_z; + } + + TGeoVolume* vol = new TGeoVolume(nmstation, statbox, med); + // z-translate the station to its (absolute) position + top->AddNode(vol, statnb, new TGeoTranslation(0, floor_offset / 2., T_station_z)); + + TGeoVolume* statframe = new TGeoVolume(nmstation + "_frame", detcomp1, FrameMatPtr); + vol->AddNode(statframe, statnb * 1e6, new TGeoTranslation(0, -floor_offset / 2., 0)); + statframe->SetLineColor(kOrange); + // Loop over the 4 stereo layers + for (Int_t vnb = 0; vnb < 4; vnb++) { + // View loop + TString nmview; + Double_t angle; + Double_t stereo_growth; + Double_t stereo_pitch; + Double_t offset_layer; + Int_t straws_per_layer; + + switch (vnb) { + case 0: + angle = 0.; + nmview = nmstation + "_y1"; + break; + case 1: + angle = f_view_angle; + nmview = nmstation + "_u"; + break; + case 2: + angle = -f_view_angle; + nmview = nmstation + "_v"; + break; + case 3: + angle = 0.; + nmview = nmstation + "_y2"; + break; + default: + angle = 0.; + nmview = nmstation + "_y1"; + } + + // Adjustments in the stereo views + // stereo_growth: extension of stereo views beyond aperture + // stereo_pitch: straw pitch in stereo views + // offset_layer: layer offset in stereo views + // straws_per_layer: number of straws in one layer with stereo extension + // If angle == 0., all numbers return the case of non-stereo views. + stereo_growth = TMath::Tan(TMath::Abs(angle) * TMath::Pi() / 180.0) * straw_length; + stereo_pitch = f_straw_pitch / TMath::Cos(TMath::Abs(angle) * TMath::Pi() / 180.0); + offset_layer = f_offset_layer / TMath::Cos(TMath::Abs(angle) * TMath::Pi() / 180.0); + straws_per_layer = std::floor(2 * (f_aperture_height + stereo_growth) / stereo_pitch); + + // Two sets of straws per layer + for (Int_t lnb = 0; lnb < 2; lnb++) { + // Layer loop + TString nmlayer = nmview + "_layer"; + TString gasname = "ubt_gas_"+nmlayer; + + // Volume: gas - Only the gas is sensitive + TGeoTube *gas_tube = new TGeoTube(gasname, f_wire_thickness / 2. + eps, f_inner_straw_diameter / 2. - eps, straw_length - 2. * eps); + TGeoVolume *gas = new TGeoVolume(gasname, gas_tube, sttmix8020_1bar); + gas->SetLineColor(5); + AddSensitiveVolume(gas); + nmlayer += lnb; + + TGeoBBox* layer = new TGeoBBox( + "layer box", straw_length + eps / 4, f_aperture_height + stereo_growth * 2 + offset_layer + eps / 4, f_outer_straw_diameter / 2. + eps / 4); + TGeoVolume* layerbox = new TGeoVolume(nmlayer, layer, med); + + // The layer box sits in the viewframe. + // Hence, z-translate the layer w.r.t. the view + vol->AddNode(layerbox, statnb * 1e6 + vnb * 1e5 + lnb * 1e4, new TGeoTranslation(0, -floor_offset / 2., (vnb - 3. / 2.) * f_delta_z_view + (lnb - 1. / 2.) * f_delta_z_layer)); + + TGeoRotation r6s; + TGeoTranslation t6s; + // Loop over the straws + for (Int_t snb = 1; snb <= straws_per_layer; snb++) { + // y-translate the straw to its position + t6s.SetTranslation(0, f_aperture_height + stereo_growth - (snb - 1. / 2.) * stereo_pitch + lnb * offset_layer, 0); + // Rotate the straw with stereo angle + r6s.SetAngles(90 + angle, 90, 0); + TGeoCombiTrans c6s(t6s, r6s); + TGeoHMatrix* h6s = new TGeoHMatrix(c6s); + layerbox->AddNode(straw, statnb * 1e6 + vnb * 1e5 + lnb * 1e4 + 1e3 + snb, h6s); + layerbox->AddNode(gas, statnb * 1e6 + vnb * 1e5 + lnb * 1e4 + 2e3 + snb, h6s); + layerbox->AddNode(wire, statnb * 1e6 + vnb * 1e5 + lnb * 1e4 + 3e3 + snb, h6s); + } + + if (lnb == 1) { + // Add one more straw at the bottom of the second layer to cover aperture entirely + t6s.SetTranslation(0, f_aperture_height + stereo_growth - (straws_per_layer - 1. / 2.) * stereo_pitch - lnb * offset_layer, 0); + r6s.SetAngles(90 + angle, 90, 0); + TGeoCombiTrans c6s(t6s, r6s); + TGeoHMatrix* h6s = new TGeoHMatrix(c6s); + layerbox->AddNode(straw, statnb * 1e6 + vnb * 1e5 + lnb * 1e4 + 1e3 + straws_per_layer + 1, h6s); + layerbox->AddNode(gas, statnb * 1e6 + vnb * 1e5 + lnb * 1e4 + 2e3 + straws_per_layer + 1, h6s); + layerbox->AddNode(wire, statnb * 1e6 + vnb * 1e5 + lnb * 1e4 + 3e3 + straws_per_layer + 1, h6s); + } + // End of layer loop + } + // End of view loop + } + // A layer of plastic scintillator detector + InitMedium("polyvinyltoluene"); + TGeoMedium *Vacuum_box =gGeoManager->GetMedium("polyvinyltoluene"); + UpstreamTagger_plastic = gGeoManager->MakeBox("Upstream_Tagger_Plastic", Vacuum_box, straw_length, f_aperture_width, 1); + UpstreamTagger_plastic->SetLineColor(kGreen); + vol->AddNode(UpstreamTagger_plastic, 1, new TGeoTranslation(0.0, 0.0, -30)); + AddSensitiveVolume(UpstreamTagger_plastic); + std::cout<<"geometry constructed"<emplace_back(trackID, detID, pos, mom, time, length, + fUpstreamTaggerPoints->emplace_back(trackID, detID, subDetID, pos, mom, time, length, eLoss, pdgCode, Lpos, Lmom); return &(fUpstreamTaggerPoints->back()); } diff --git a/UpstreamTagger/UpstreamTagger.h b/UpstreamTagger/UpstreamTagger.h index 6b5e5832d7..b655e22815 100644 --- a/UpstreamTagger/UpstreamTagger.h +++ b/UpstreamTagger/UpstreamTagger.h @@ -49,13 +49,18 @@ class UpstreamTagger : public FairDetector, public ISTLPointContainer { * kFALSE for inactive detectors */ UpstreamTagger(const char* Name, Bool_t Active); - + UpstreamTagger& operator=(const UpstreamTagger&); /** default constructor */ UpstreamTagger(); + /** Name : Detector Name + * Active: kTRUE for active detectors (ProcessHits() will be called) + * kFALSE for inactive detectors + */ +// UpstreamTagger(const char* Name, Bool_t Active); + UpstreamTagger(std::string medium); /** destructor */ virtual ~UpstreamTagger(); - /** Initialization of the detector is done here */ virtual void Initialize(); @@ -78,19 +83,25 @@ class UpstreamTagger : public FairDetector, public ISTLPointContainer { /** Sets detector position and sizes */ void SetZposition(Double_t z) { det_zPos = z; } - void SetBoxDimensions(Double_t x, Double_t y, Double_t z) { - xbox_fulldet = x; - ybox_fulldet = y; - zbox_fulldet = z; - } + void SetzPositions(Double_t z1); + void SetApertureArea(Double_t width, Double_t height, Double_t length); + void SetStrawDiameter(Double_t outer_straw_diameter, Double_t wall_thickness); + void SetStrawPitch(Double_t straw_pitch, Double_t layer_offset); + void SetDeltazLayer(Double_t delta_z_layer); + void SetStereoAngle(Double_t stereo_angle); + void SetWireThickness(Double_t wire_thickness); + void SetFrameMaterial(TString frame_material); + void SetDeltazView(Double_t delta_z_view); + static std::tuple StrawDecode(Int_t detID); + static void StrawEndPoints(Int_t detID, TVector3& top, TVector3& bot); /** Create the detector geometry */ void ConstructGeometry(); /** This method is an example of how to add your own point * of type TimeRpcPoint to the clones array */ - UpstreamTaggerPoint* AddHit(Int_t trackID, Int_t detID, TVector3 pos, + UpstreamTaggerPoint* AddHit(Int_t trackID, Int_t detID, Int_t subDetID, TVector3 pos, TVector3 mom, Double_t time, Double_t length, Double_t eLoss, Int_t pdgCode, TVector3 Lpos, TVector3 Lmom); @@ -117,24 +128,36 @@ class UpstreamTagger : public FairDetector, public ISTLPointContainer { /** Detector parameters.*/ - Double_t det_zPos; //! z-position of detector (set via SetZposition) - // Detector box dimensions (set via SetBoxDimensions, defaults provided below) - Double_t xbox_fulldet = 4.4 * m; //! X dimension (default: 4.4 m) - Double_t ybox_fulldet = 6.4 * m; //! Y dimension (default: 6.4 m) - Double_t zbox_fulldet = - 16.0 * cm; //! Z dimension/thickness (default: 16 cm) + Double_t f_aperture_width; + Double_t f_aperture_height; + Double_t f_station_length; + Double_t f_straw_pitch; + Double_t f_view_angle; + Double_t f_offset_layer; + Double_t f_inner_straw_diameter; + Double_t f_outer_straw_diameter; + Double_t f_wire_thickness; + Double_t f_T1_z; + Double_t f_delta_z_view; + Double_t f_delta_z_layer; + TString f_frame_material; + std::string fMedium; + /** Detector parameters.*/ + + Double_t det_zPos; //! z-position of detector (set via SetZposition) private: - TGeoVolume* UpstreamTagger_fulldet; // Timing_detector_1 object - TGeoVolume* scoringPlaneUBText; // new scoring plane /** container for data points */ std::vector* fUpstreamTaggerPoints; - UpstreamTagger(const UpstreamTagger&); - UpstreamTagger& operator=(const UpstreamTagger&); Int_t InitMedium(const char* name); - ClassDef(UpstreamTagger, 1) + TGeoVolume* UpstreamTagger_plastic; + + /** container for data points */ + TClonesArray* fUpstreamTaggerPointCollection; + + ClassDef(UpstreamTagger,1) }; #endif // UPSTREAMTAGGER_UPSTREAMTAGGER_H_ diff --git a/UpstreamTagger/UpstreamTaggerHit.cxx b/UpstreamTagger/UpstreamTaggerHit.cxx index 01d788fbf4..09a9e564c1 100644 --- a/UpstreamTagger/UpstreamTaggerHit.cxx +++ b/UpstreamTagger/UpstreamTaggerHit.cxx @@ -29,6 +29,8 @@ UpstreamTaggerHit::UpstreamTaggerHit(UpstreamTaggerPoint* p, Double_t t0, // Smear time with Gaussian resolution fTime = gRandom->Gaus(p->GetTime() + t0, time_res); + + fSubDetID = p->GetLayerID(); } // ----- Destructor ------------------------- diff --git a/UpstreamTagger/UpstreamTaggerHit.h b/UpstreamTagger/UpstreamTaggerHit.h index f9bce7a2d6..258f697785 100644 --- a/UpstreamTagger/UpstreamTaggerHit.h +++ b/UpstreamTagger/UpstreamTaggerHit.h @@ -56,6 +56,7 @@ class UpstreamTaggerHit : public ShipHit { Double_t fY; ///< Smeared y position (cm) Double_t fZ; ///< Smeared z position (cm) Double_t fTime; ///< Smeared time (ns) + Int_t fSubDetID; ///< Which layer of the UBT is this ClassDef(UpstreamTaggerHit, 2); }; diff --git a/UpstreamTagger/UpstreamTaggerPoint.cxx b/UpstreamTagger/UpstreamTaggerPoint.cxx index d413f6dd2b..de2caff7d4 100644 --- a/UpstreamTagger/UpstreamTaggerPoint.cxx +++ b/UpstreamTagger/UpstreamTaggerPoint.cxx @@ -14,12 +14,14 @@ UpstreamTaggerPoint::UpstreamTaggerPoint() : FairMCPoint() {} // ----- Standard constructor ------------------------------------------ UpstreamTaggerPoint::UpstreamTaggerPoint(Int_t trackID, Int_t detID, + Int_t subDetID, TVector3 pos, TVector3 mom, Double_t tof, Double_t length, Double_t eLoss, Int_t pdgcode, TVector3 Lpos, TVector3 Lmom) : FairMCPoint(trackID, detID, pos, mom, tof, length, eLoss), fPdgCode(pdgcode), + fSubDetID(subDetID), fLpos{Lpos.X(), Lpos.Y(), Lpos.Z()}, fLmom{Lmom.X(), Lmom.Y(), Lmom.Z()} {} // ------------------------------------------------------------------------- diff --git a/UpstreamTagger/UpstreamTaggerPoint.h b/UpstreamTagger/UpstreamTaggerPoint.h index c6ff1f3a75..39367b78d6 100644 --- a/UpstreamTagger/UpstreamTaggerPoint.h +++ b/UpstreamTagger/UpstreamTaggerPoint.h @@ -27,7 +27,7 @@ class UpstreamTaggerPoint : public FairMCPoint { *@param length Track length since creation [cm] *@param eLoss Energy deposit [GeV] **/ - UpstreamTaggerPoint(Int_t trackID, Int_t detID, TVector3 pos, TVector3 mom, + UpstreamTaggerPoint(Int_t trackID, Int_t detID, Int_t subDetID, TVector3 pos, TVector3 mom, Double_t tof, Double_t length, Double_t eLoss, Int_t pdgCode, TVector3 Lpos, TVector3 Lmom); @@ -44,9 +44,12 @@ class UpstreamTaggerPoint : public FairMCPoint { Int_t PdgCode() const { return fPdgCode; } TVector3 LastPoint() const { return TVector3(fLpos[0], fLpos[1], fLpos[2]); } TVector3 LastMom() const { return TVector3(fLmom[0], fLmom[1], fLmom[2]); } + Int_t GetLayerID() const { return fSubDetID; }; + private: Int_t fPdgCode; + Int_t fSubDetID; std::array fLpos, fLmom; ClassDef(UpstreamTaggerPoint, 3) diff --git a/geometry/ubt_config.yaml b/geometry/ubt_config.yaml new file mode 100644 index 0000000000..e6e8d2d3cb --- /dev/null +++ b/geometry/ubt_config.yaml @@ -0,0 +1,14 @@ +# Geometry configuration of UBT (veto) in FairShip + +UBT: + width: 150 # Aperture width (x) in cm (half length) + height: 150 # Aperture height (y) in cm (half length) + wire_thickness: 0.003 # Sense wire thickness in cm + wall_thickness: 0.0036 # Straw wall thickness in cm + outer_straw_diameter: 2 # in cm + straw_pitch: 2 # Distance (y) between straws in a layer in cm + y_layer_offset: 1 # Offset (y) of straws between layers in cm + delta_z_layer: 1.732 # Distance (z) between layers in cm + delta_z_view: 12 # Distance (z) between stereo views in cm + view_angle: 4.57 # Stereo angle in degree + station_length: 40 # (z) in cm (half length) diff --git a/python/ShipGeo.py b/python/ShipGeo.py new file mode 100644 index 0000000000..21dc4eb766 --- /dev/null +++ b/python/ShipGeo.py @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: LGPL-3.0-or-later +# SPDX-FileCopyrightText: Copyright CERN for the benefit of the SHiP Collaboration + +import shipunit as u +import ROOT +fDesign = 2 +class ShipGeo(): + def __init__(self,z=0): + self.z = z + +def zPositions(): + main = sys.modules['__main__'] + if hasattr(main,'ShipGeo'): + for x in ShipGeo: + if hasattr(eval('ShipGeo.'+x),'z'): print(x,'z=',eval('ShipGeo.'+x+'.z')) + +#vetoStation = ShipGeo(-2390.*u.cm) +TrackStation1 = ShipGeo(1510.*u.cm) +TrackStation2 = ShipGeo(1710.*u.cm) +TrackStation3 = ShipGeo(2150.*u.cm) +TrackStation4 = ShipGeo(2370.*u.cm) + +UBTStation1 = ShipGeo(2390.*u.cm) +UBTStation2 = ShipGeo(2395.*u.cm) +UBTStation3 = ShipGeo(2400.*u.cm) +UBTStation4 = ShipGeo(2405.*u.cm) + + +z = TrackStation2.z + 0.5 * (TrackStation3.z - TrackStation2.z) +Bfield = ShipGeo(z) +Bfield.max = 1.5*u.kilogauss # was 1.15 in EOI + +# target absorber muon shield setup +decayVolume = ShipGeo(0*u.cm) +decayVolume.length = 50*u.m + +muShield = ShipGeo(0*u.cm) +muShield.dZ1 = 2.5*u.m +muShield.dZ2 = 3.5*u.m +muShield.dZ3 = 3.0*u.m +muShield.dZ4 = 3.0*u.m +muShield.dZ5 = 2.5*u.m +muShield.dZ6 = 2.5*u.m +muShield.LE = 5*u.m +# for passive design, fDesign==1 +if fDesign == 1: muShield.length = 70*u.m +# for active design, fDesign==2 +if fDesign == 2: muShield.length = 2*(muShield.dZ1+muShield.dZ2+muShield.dZ3+muShield.dZ4+muShield.dZ5+muShield.dZ6) + muShield.LE # leave some space for nu-tau detector +muShield.z = -decayVolume.length/2.-muShield.length/2. + +hadronAbsorber = ShipGeo(0*u.cm) +hadronAbsorber.length= 3.0*u.m +hadronAbsorber.z = muShield.z - muShield.length/2. - hadronAbsorber.length/2. + +target = ShipGeo(0*u.cm) +target.length = 50*u.cm +target.z = hadronAbsorber.z - hadronAbsorber.length/2. - target.length/2. + +# interaction point, start of target +target.z0 = target.z - target.length/2. + +# straws of tracking stations +straw = ShipGeo(0*u.cm) +straw.length = 250.*u.cm +straw.resol = 0.01*u.cm +straw.pitch = 1.*u.cm +straw.stereoAngle = 5./180.*ROOT.TMath.Pi() diff --git a/python/geometry_config.py b/python/geometry_config.py index 9b375a11a9..1bee6de57a 100644 --- a/python/geometry_config.py +++ b/python/geometry_config.py @@ -424,6 +424,8 @@ def create_config( c.Chamber1 = AttrDict(z=z4 - 4666.0 * u.cm - magnetIncrease - extraVesselLength) c.Chamber6 = AttrDict(z=z4 + 30.0 * u.cm + windowBulge / 2.0) + c.UBTStation1 = AttrDict(z = c.decayVolume.z0 - 50*u.cm) + c.Bfield = AttrDict() c.Bfield.z = c.z c.Bfield.max = 0 # 1.4361*u.kilogauss # was 1.15 in EOI @@ -537,7 +539,7 @@ def create_config( c.UpstreamTagger = AttrDict() c.UpstreamTagger.BoxX = 4.4 * u.m # X dimension (width) c.UpstreamTagger.BoxY = 6.4 * u.m # Y dimension (height) - c.UpstreamTagger.BoxZ = 16.0 * u.cm # Z dimension (thickness) + c.UpstreamTagger.BoxZ = 2.0 * u.cm # Z dimension (thickness) c.UpstreamTagger.Z_Position = ( -25.400 * u.m + c.decayVolume.z ) # Relative position of UBT to decay vessel centre diff --git a/python/shipDet_conf.py b/python/shipDet_conf.py index c79a7534b7..6fbdaee834 100644 --- a/python/shipDet_conf.py +++ b/python/shipDet_conf.py @@ -260,6 +260,49 @@ def configure_strawtubes(yaml_file, ship_geo): detectorList.append(strawtubes) +def configure_upstreamTagger(yaml_file, ship_geo): + with open(yaml_file) as file: + config = yaml.safe_load(file) + + ship_geo.ubt_geo = AttrDict(config['UBT']) + + # Straw tubes in decay vessel if vacuum, otherwise outside in air + ship_geo.ubt_geo.medium = "vacuums" if ship_geo.DecayVolumeMedium == "vacuums" else "air" + + ship_geo.ubt_geo.frame_material = "DIRCcarbonFiber" + + ubt = ROOT.UpstreamTagger(ship_geo.ubt_geo.medium) + ubt.SetzPositions( + ship_geo.UBTStation1.z, + ) + ubt.SetApertureArea( + ship_geo.ubt_geo.width, + ship_geo.ubt_geo.height, + ship_geo.ubt_geo.station_length + ) + ubt.SetStrawDiameter( + ship_geo.ubt_geo.outer_straw_diameter, + ship_geo.ubt_geo.wall_thickness, + ) + ubt.SetStrawPitch( + ship_geo.ubt_geo.straw_pitch, + ship_geo.ubt_geo.y_layer_offset, + ) + ubt.SetDeltazLayer(ship_geo.ubt_geo.delta_z_layer) + ubt.SetStereoAngle(ship_geo.ubt_geo.view_angle) + ubt.SetWireThickness(ship_geo.ubt_geo.wire_thickness) + ubt.SetDeltazView(ship_geo.ubt_geo.delta_z_view) + ubt.SetFrameMaterial(ship_geo.ubt_geo.frame_material) + + + #For digitization +# strawtubes.SetStrawResolution( +# ship_geo.strawtubesDigi.v_drift, +# ship_geo.strawtubesDigi.sigma_spatial, +# ) + + detectorList.append(ubt) + def configure(run, ship_geo): # ---- for backward compatibility ---- @@ -428,14 +471,10 @@ def configure(run, ship_geo): SplitCal.SetStripSize(x.StripHalfWidth, x.StripHalfLength) detectorList.append(SplitCal) - upstreamTagger = ROOT.UpstreamTagger("UpstreamTagger", ROOT.kTRUE) - upstreamTagger.SetZposition(ship_geo.UpstreamTagger.Z_Position) - upstreamTagger.SetBoxDimensions( - ship_geo.UpstreamTagger.BoxX, - ship_geo.UpstreamTagger.BoxY, - ship_geo.UpstreamTagger.BoxZ + configure_upstreamTagger( + os.path.join(os.environ["FAIRSHIP"], "geometry", "ubt_config.yaml"), + ship_geo, ) - detectorList.append(upstreamTagger) timeDet = ROOT.TimeDet("TimeDet", ROOT.kTRUE) timeDet.SetZposition(ship_geo.TimeDet.z) diff --git a/tests/test_rntuple_io.cxx b/tests/test_rntuple_io.cxx index 82852c8b17..aa580161d7 100644 --- a/tests/test_rntuple_io.cxx +++ b/tests/test_rntuple_io.cxx @@ -349,9 +349,9 @@ int main(int argc, char** argv) { TVector3 mom(0.1, 0.2, 0.3); TVector3 lpos(1.1, 2.1, 3.1); TVector3 lmom(0.11, 0.21, 0.31); - objects.emplace_back(1, 1001, pos, mom, 123.45, 234.56, 0.001, 2212, lpos, + objects.emplace_back(1, 1001, 1, pos, mom, 123.45, 234.56, 0.001, 2212, lpos, lmom); - objects.emplace_back(2, 2002, pos, mom, 345.67, 456.78, 0.002, 211, lpos, + objects.emplace_back(2, 2002, 1, pos, mom, 345.67, 456.78, 0.002, 211, lpos, lmom); total++; if (test_rntuple_io("UpstreamTaggerPoint", objects)) passed++;