er  dev
ERTelescopeTrackFinder.cxx
1 /********************************************************************************
2  * Copyright (C) Joint Institute for Nuclear Research *
3  * *
4  * This software is distributed under the terms of the *
5  * GNU Lesser General Public Licence version 3 (LGPL) version 3, *
6  * copied verbatim in the file "LICENSE" *
7  ********************************************************************************/
8 
9 #include "ERTelescopeTrackFinder.h"
10 
11 #include <cassert>
12 
13 #include "TVector3.h"
14 #include "TMath.h"
15 
16 #include "FairRootManager.h"
17 #include "FairRuntimeDb.h"
18 #include "FairLogger.h"
19 #include "FairLink.h"
20 
21 #include "ERBeamDetTrack.h"
22 #include "ERRunAna.h"
23 #include "ERDigi.h"
24 
25 //--------------------------------------------------------------------------------------------------
27  : ERTask("ER telescope track finding scheme")
28 {
29  fAvailibleRunManagers.push_back("ERRunAna");
30  fQTelescopeSetup = ERTelescopeSetup::Instance();
31 }
32 //--------------------------------------------------------------------------------------------------
34  : ERTask("ER telescope track finding scheme ", verbose)
35 {
36  fAvailibleRunManagers.push_back("ERRunAna");
37  fQTelescopeSetup = ERTelescopeSetup::Instance();
38 }
39 //--------------------------------------------------------------------------------------------------
40 void ERTelescopeTrackFinder::SetHitStation(TString subassemblyName, TString componentId) {
41  TString xStripArrayName = componentId;
42  TString yStripArrayName = componentId;
43  fSiHitStationsPair[subassemblyName].emplace(
44  std::make_pair(componentId, std::pair<TString, TString>(xStripArrayName.Append("_X"),
45  yStripArrayName.Append("_Y"))));
46 }
47 //--------------------------------------------------------------------------------------------------
48 void ERTelescopeTrackFinder::SetHitStation(TString subassemblyName, TString componentIdX,
49  TString componentIdY)
50 {
51  fSiHitStationsPair[subassemblyName].emplace(
52  std::make_pair(componentIdX + componentIdY, std::pair<TString, TString>(componentIdX, componentIdY)));
53 }
54 //--------------------------------------------------------------------------------------------------
55 void ERTelescopeTrackFinder::
56 SetTrackPositionCorrection(const TString& station_name, ERChannel channel, float strip_fraction) {
57  if (strip_fraction < -0.5 || strip_fraction > 0.5) {
58  LOG(FATAL) << "Correction of track position in strip should be in range [-0.5, 0.5]"
59  << FairLogger::endl;
60  }
61  track_position_corrections_[station_name][channel] = strip_fraction;
62 }
63 //--------------------------------------------------------------------------------------------------
64 void ERTelescopeTrackFinder::SetStripEdepRange(Double_t edepMin, Double_t edepMax) {
65  fSiDigiEdepMin = edepMin;
66  fSiDigiEdepMax = edepMax;
67 }
68 //--------------------------------------------------------------------------------------------------
69 void ERTelescopeTrackFinder::SetInteractionPosition(double x, double y, double z) {
70  interaction_position_is_set_ = true;
71  interaction_x_ = x;
72  interaction_y_ = y;
73  interaction_z_ = z;
74 }
75 //--------------------------------------------------------------------------------------------------
76 TVector3 ERTelescopeTrackFinder::
77 GetGlobalTrackPositionByStrip(const TString& branch_name, const ERChannel channel) const {
78  // Local position of strip center
79  auto local_position = fQTelescopeSetup->GetStripLocalPosition(branch_name, channel);
80  const auto strip_width = fQTelescopeSetup->GetStripWidth(branch_name, channel);
81  // Apply user coorections
82  for (const auto& station_to_channels : track_position_corrections_) {
83  const auto station_name = station_to_channels.first;
84  if (!branch_name.Contains(station_name))
85  continue;
86  const auto channel_to_position_correction = station_to_channels.second;
87  const auto channel_and_correction = channel_to_position_correction.find(channel);
88  if (channel_and_correction == channel_to_position_correction.end())
89  continue;
90  const auto correction = channel_and_correction->second;
91  const auto current_position = local_position[0];
92  local_position[0] = current_position + strip_width * correction;
93  LOG(DEBUG) << "[ERQTelescopeTrackFinder] Local position of strip " << channel << " of "
94  << station_name << " corrected from " << current_position << " to "
95  << local_position[0] << FairLogger::endl;
96  }
97  return fQTelescopeSetup->ToGlobalCoordinateSystem(branch_name, local_position);
98 }
99 //--------------------------------------------------------------------------------------------------
101  if (ERTask::Init() != kSUCCESS)
102  return kFATAL;
103 
104  FairRootManager* ioman = FairRootManager::Instance();
105  if ( ! ioman ) Fatal("Init", "No FairRootManager");
106  TList* allbrNames = ioman->GetBranchNameList();
107  TIter nextBranch(allbrNames);
108  TObjString* bName;
109  std::vector<TString> pointBranches;
110  while (bName = (TObjString*)nextBranch()) {
111  TString bFullName = bName->GetString();
112  if (bFullName.Contains("Digi") && bFullName.Contains("Telescope")) {
113  Int_t bPrefixNameLength = bFullName.First('_');
114  TString brName(bFullName(bPrefixNameLength + 1, bFullName.Length()));
115  fQTelescopeDigi[brName] = (TClonesArray*) ioman->GetObject(bFullName);
116  }
117  }
118  // Register output track branches only for stations that are setted by interface SetStation(){
119  for (const auto itSubassemblies : fSiHitStationsPair) {
120  for (const auto itComponent : itSubassemblies.second) {
121  fQTelescopeTrack[itComponent.first] = new TClonesArray("ERTelescopeTrack",
122  consts::approx_telescope_track_number);
123  ioman->Register("TelescopeTrack_" + itComponent.first, "Telescope",
124  fQTelescopeTrack[itComponent.first], kTRUE);
125  }
126  }
127 
128  fBeamDetTrack = (TClonesArray*) ioman->GetObject("BeamDetTrack");
129  if (!interaction_position_is_set_) {
130  if (!fBeamDetTrack) {
131  LOG(DEBUG) << "ERTelescopeTrackFinder: target point not initialized by user "
132  << "(by means of SetTargetPoint()) and there is no ERBeamDetTrack branch"
133  <<FairLogger::endl;
134  return kFATAL;
135  }
136  }
137 
138  fQTelescopeSetup->ERTelescopeSetup::ReadGeoParamsFromParContainer();
139 
140  //@TODO check setup and digi branch names
141 
142  return kSUCCESS;
143 }
144 //--------------------------------------------------------------------------------------------------
145 void ERTelescopeTrackFinder::Exec(Option_t* opt) {
146  LOG(DEBUG) << "[ERTelescopeTrackFinder]------------Started--------------------------------------"
147  << FairLogger::endl;
148  Reset();
149  if (!interaction_position_is_set_) {
150  ERBeamDetTrack* trackFromMWPC = (ERBeamDetTrack*)fBeamDetTrack->At(0);
151  if (!trackFromMWPC) {
152  //fRun->MarkFill(kFALSE);
153  return ;
154  }
155  interaction_x_ = trackFromMWPC->GetTargetX();
156  interaction_y_ = trackFromMWPC->GetTargetY();
157  interaction_z_ = trackFromMWPC->GetTargetZ();
158  }
159  for (const auto& itSubassemblies : fSiHitStationsPair) {
160  for (const auto& itComponent : itSubassemblies.second) {
161  // pairs of X and Y strips that have difference between edep less than fEdepDiffXY
162  std::vector<std::pair<Int_t, Int_t>> hitTelescopePoint;
163  // strips with edep in correct interval (fSiDigiEdepMin, fSiDigiEdepMax)
164  std::vector<Int_t> correctStripsX;
165  // strips with edep in correct interval (fSiDigiEdepMin, fSiDigiEdepMax)
166  std::vector<Int_t> correctStripsY;
167  const TString xDigiBranchName = itComponent.second.first;
168  const TString yDigiBranchName = itComponent.second.second;
169  if (fQTelescopeSetup->GetStationType(xDigiBranchName) != fQTelescopeSetup->GetStationType(yDigiBranchName)) {
170  LOG(FATAL) << "Do not mix R and Q telescopes for track finding" << FairLogger::endl;
171  }
172  const TClonesArray* xDigi = fQTelescopeDigi[xDigiBranchName];
173  const TClonesArray* yDigi = fQTelescopeDigi[yDigiBranchName];
174  if ( !xDigi || !yDigi) {
175  continue;
176  }
177  if (xDigi->GetEntriesFast() == 0 || yDigi->GetEntriesFast()==0) {
178  continue;
179  }
180  for (Int_t iXDigi = 0; iXDigi < xDigi->GetEntriesFast(); iXDigi++) {
181  const Double_t xStripEdep = ((ERDigi*)xDigi->At(iXDigi))->Edep();
182  if (xStripEdep > fSiDigiEdepMin && xStripEdep < fSiDigiEdepMax) {
183  correctStripsX.push_back(iXDigi);
184  }
185  }
186  for (Int_t iYDigi = 0; iYDigi < yDigi->GetEntriesFast(); iYDigi++) {
187  const Double_t yStripEdep = ((ERDigi*)yDigi->At(iYDigi))->Edep();
188  if (yStripEdep > fSiDigiEdepMin && yStripEdep < fSiDigiEdepMax) {
189  correctStripsY.push_back(iYDigi);
190  }
191  }
192  for (const auto itCorrectStripsX : correctStripsX) {
193  const Double_t xStripEdep = ((ERDigi*)xDigi->At(itCorrectStripsX))->Edep();
194  for (const auto itCorrectStripsY : correctStripsY) {
195  const Double_t yStripEdep = ((ERDigi*)yDigi->At(itCorrectStripsY))->Edep();
196  if (TMath::Abs(xStripEdep - yStripEdep) < fEdepDiffXY) {
197  hitTelescopePoint.push_back(std::pair<Int_t, Int_t>(itCorrectStripsX, itCorrectStripsY));
198  }
199  }
200  }
201  LOG(DEBUG) << "[ERTelescopeTrackFinder] Strips array pair " << itComponent.second.first << " "
202  << itComponent.second.second << FairLogger::endl;
203  LOG(DEBUG) << "[ERTelescopeTrackFinder] Hits count on pair " << hitTelescopePoint.size() << FairLogger::endl;
204  for (const auto& itHitPoint : hitTelescopePoint) {
205  const auto xChannelIndex = itHitPoint.first;
206  const auto yChannelIndex = itHitPoint.second;
207  const auto* xStrip = dynamic_cast<ERDigi*>(xDigi->At(xChannelIndex));
208  const auto* yStrip = dynamic_cast<ERDigi*>(yDigi->At(yChannelIndex));
209  if (!xStrip || !yStrip)
210  continue;
211  const auto xChannel = xStrip->Channel();
212  const auto yChannel = yStrip->Channel();
213  if (fQTelescopeSetup->GetStationType(xDigiBranchName) == ERTelescopeSetup::StationType::QStation) {
214  CreateTrackInQTelescope(xChannelIndex, yChannelIndex, xChannel, yChannel,
215  xStrip->Edep(), yStrip->Edep(), xDigiBranchName, yDigiBranchName,
216  itComponent.first);
217  } else {
218  CreateTrackInRTelescope(xChannelIndex, yChannelIndex, xChannel, yChannel,
219  xStrip->Edep(), yStrip->Edep(), xDigiBranchName, yDigiBranchName,
220  itComponent.first);
221  }
222  }
223  }
224  }
225  LOG(DEBUG) << "[ERTelescopeTrackFinder]------------Finished--------------------------------------"
226  << FairLogger::endl;
227 }
228 //--------------------------------------------------------------------------------------------------
229 void ERTelescopeTrackFinder::CreateTrackInQTelescope(
230  const Int_t xChannelIndex, const Int_t yChannelIndex, const Int_t xChannel, const Int_t yChannel,
231  const Double_t xEdep, const Double_t yEdep, const TString& xDigiBranchName, const TString& yDigiBranchName,
232  const TString& trackBranchName) {
233  LOG(DEBUG) << "[ERTelescopeTrackFinder] Branch names X:" << xDigiBranchName
234  << " Y: " << yDigiBranchName << FairLogger::endl;
235  LOG(DEBUG) << "[ERTelescopeTrackFinder] Strips pair numbers " << xChannel << " "
236  << yChannel << FairLogger::endl;
237  // Calc unknown coordinated using condition: target, hit on first station(closest) and
238  // hit on second station lie on line :
239  // {x2, y2, z2} = {interaction_x_, interaction_y_, interaction_z_} + k * ({x1, y1, z1} - {interaction_x_, interaction_y_, interaction_z_}).
240  const bool xStationIsClosest = fQTelescopeSetup->GetStripGlobalZ(xDigiBranchName, xChannel)
241  < fQTelescopeSetup->GetStripGlobalZ(yDigiBranchName, yChannel);
242  // We know all about z coordinate, so
243  const double z1 = xStationIsClosest
244  ? fQTelescopeSetup->GetStripGlobalZ(xDigiBranchName, xChannel)
245  : fQTelescopeSetup->GetStripGlobalZ(yDigiBranchName, yChannel);
246  const double z2 = xStationIsClosest
247  ? fQTelescopeSetup->GetStripGlobalZ(yDigiBranchName, yChannel)
248  : fQTelescopeSetup->GetStripGlobalZ(xDigiBranchName, xChannel);
249  assert(z1 != interaction_z_);
250  const double k = (z2 - interaction_z_) / (z1 - interaction_z_);
251  double x1 = 0., x2 = 0., y1 = 0., y2 = 0.;
252  if (xStationIsClosest) { // find y1, x2 from equation
253  x1 = GetGlobalTrackPositionByStrip(xDigiBranchName, xChannel)[0];
254  y2 = GetGlobalTrackPositionByStrip(yDigiBranchName, yChannel)[1];
255  LOG(DEBUG) << "[ERTelescopeTrackFinder] Coordinates from strips. x1 = " << x1
256  << " y2 = " << y2 << " z1 = " << z1 << " z2 = " << z2 << FairLogger::endl;
257  y1 = (-1./k)*((1. - k)*interaction_y_ - y2);
258  x2 = (1. - k)*interaction_x_ + k*x1;
259  } else { // find x1, y2 from equation
260  x2 = GetGlobalTrackPositionByStrip(xDigiBranchName, xChannel)[0];
261  y1 = GetGlobalTrackPositionByStrip(yDigiBranchName, yChannel)[1];
262  LOG(DEBUG) << "[ERTelescopeTrackFinder] Coordinates from strips. x2 = " << x2
263  << " y1 = " << y1 << " z1 = " << z1 << " z2 = " << z2 << FairLogger::endl;
264  x1 = (-1./k)*((1. - k)*interaction_x_ - x2);
265  y2 = (1. - k)*interaction_y_ + k*y1;
266  }
267  const auto& xStationVertex = xStationIsClosest ? TVector3(x1, y1, z1) : TVector3(x2, y2, z2);
268  const auto& yStationVertex = xStationIsClosest ? TVector3(x2, y2, z2) : TVector3(x1, y1, z1);
269  const auto& xStationLocalVertex = fQTelescopeSetup->ToStationCoordinateSystem(xDigiBranchName, xStationVertex);
270  const auto& yStationLocalVertex = fQTelescopeSetup->ToStationCoordinateSystem(yDigiBranchName, yStationVertex);
271  LOG(DEBUG) << "[ERTelescopeTrackFinder] X Station Vertex (" << xStationVertex.x() << " " << xStationVertex.y()
272  << " " << xStationVertex.z() << ")" << FairLogger::endl;
273  LOG(DEBUG) << "[ERTelescopeTrackFinder] Y Station Vertex (" << yStationVertex.x() << " " << yStationVertex.y()
274  << " " << yStationVertex.z() << ")" << FairLogger::endl;
275  LOG(DEBUG) << "[ERTelescopeTrackFinder] X Station Vertex in station CS (" << xStationLocalVertex.x() << " " << xStationLocalVertex.y()
276  << " " << xStationLocalVertex.z() << ")" << FairLogger::endl;
277  LOG(DEBUG) << "[ERTelescopeTrackFinder] Y Station Vertex in station CS (" << yStationLocalVertex.x() << " " << yStationLocalVertex.y()
278  << " " << yStationLocalVertex.z() << ")" << FairLogger::endl;
279  auto* track = AddTrack(TVector3(interaction_x_, interaction_y_, interaction_z_), xStationVertex, yStationVertex,
280  xStationLocalVertex, yStationLocalVertex, xChannel, yChannel, xEdep, yEdep,
281  trackBranchName);
282  //track->AddLink(FairLink(xDigiBranchName, xChannelIndex));
283  //track->AddLink(FairLink(yDigiBranchName, yChannelIndex));
284 }
285 //--------------------------------------------------------------------------------------------------
286 void ERTelescopeTrackFinder::CreateTrackInRTelescope(
287  const Int_t phiChannelIndex, const Int_t rChannelIndex, const Int_t phiChannel, const Int_t rChannel,
288  const Double_t phiEdep, const Double_t rEdep, const TString& phiDigiBranchName, const TString& rDigiBranchName,
289  const TString& trackBranchName) {
290  LOG(DEBUG) << "[ERTelescopeTrackFinder] Branch names phi:" << phiDigiBranchName
291  << " R: " << rDigiBranchName << FairLogger::endl;
292  LOG(DEBUG) << "[ERTelescopeTrackFinder] phi channel = " << phiChannel << " r channel = "
293  << rChannel << FairLogger::endl;
294  // Calc unknown coordinated using condition: target, hit on first station(closest) and
295  // hit on second station lie on line :
296  // {x2, y2, z2} = {interaction_x_, interaction_y_, interaction_z_} + k * ({x1, y1, z1} - {interaction_x_, interaction_y_, interaction_z_}).
297  // x = x_station + r * cos(phi); y = y_station + r * sin(phi)
298  // Lets 1 - phi station(we know phi1), 2 - r station (we know r2)
299  // r2 cos(phi2) = interaction_x_ - x_station2 + k(x_station1 + r1 cos(phi1) - interaction_x_)
300  // r2 sin(phi2) = interaction_y_ - y_station2 + k(y_station1 + r1 sin(phi1) - interaction_x_)
301  // k = (z2 - interaction_z_) / (z1 - interaction_z_)
302  // ----
303  // r1: r2^2 = (interaction_x_ - x_station2 + k(x_station1 + r1 cos(phi1) - interaction_x_))^2
304  // + (interaction_y_ - y_station2 + k(y_station1 + r1 sin(phi1) - interaction_y_))^2
305  // A = interaction_x_ - x_station2 + k(x_station1 - interaction_x_)
306  // B = k cos(phi1)
307  // C = interaction_y_ - y_station2 + k(y_station1 - interaction_y_)
308  // D = k sin(phi1)
309  // r2^2 = (A + Br1)^2 + (C + Dr1)^2
310  // r1 = -/+(sqrt(D^2(r2^2 - A^2)+2ABCD +B^2(r2^2 - C^2)) +- AB +/- CD) / (B^2 +D^2)
311  // r1 = -/+(sqrt(D^2(r2^2 - A^2)+2ABCD +B^2(r2^2 - C^2)) +- AB +/- CD) / k^2
312  const TVector3 station1 = fQTelescopeSetup->GetStationTranslation(phiDigiBranchName);
313  const TVector3 station2 = fQTelescopeSetup->GetStationTranslation(rDigiBranchName);
314  const TVector3 target(interaction_x_, interaction_y_, interaction_z_);
315  const Double_t phi1 = fQTelescopeSetup->GetStripPhi(phiDigiBranchName, phiChannel);
316  const Double_t r2 = fQTelescopeSetup->GetStripR(rDigiBranchName, rChannel);
317  const Double_t k = (station2.Z() - interaction_z_) / (station1.Z() - interaction_z_);
318  const Double_t A = interaction_x_ - station2.X() + k * (station1.X() - interaction_x_);
319  const Double_t B = k * TMath::Cos(phi1*TMath::RadToDeg());
320  const Double_t C = interaction_y_ - station2.Y() + k * (station1.Y() - interaction_y_);
321  const Double_t D = k * TMath::Sin(phi1*TMath::RadToDeg());
322  const Double_t r1 = (TMath::Sqrt(D*D*(r2*r2 - A*A) + 2*A*B*C*D +B*B*(r2*r2 - C*C)) - A*B - C*D) / (k*k);
323  const TVector3 local_vertex1(r1 * TMath::Cos(phi1*TMath::DegToRad()), r1 * TMath::Sin(phi1*TMath::DegToRad()), 0.);
324  const TVector3 global_vertex1 = station1 + local_vertex1;
325  const TVector3 global_vertex2 = target + k * (global_vertex1 - target);
326  const TVector3 local_vertex2 = global_vertex2 - station2;
327  const Double_t phi2 = TMath::ACos(local_vertex2.X() / r2) * TMath::RadToDeg();
328  LOG(DEBUG) << "[ERTelescopeTrackFinder] phi station: phi = " << phi1 << " r = " << r1 << FairLogger::endl;
329  LOG(DEBUG) << "[ERTelescopeTrackFinder] r station: phi = " << phi2 << " r = " << r2 << FairLogger::endl;
330  LOG(DEBUG) << "[ERTelescopeTrackFinder] phi station: local vertex = (" << local_vertex1.x() << " " << local_vertex1.y()
331  << " " << local_vertex1.z() << ")" << FairLogger::endl;
332  LOG(DEBUG) << "[ERTelescopeTrackFinder] r station: local vertex = (" << local_vertex2.x() << " " << local_vertex2.y()
333  << " " << local_vertex2.z() << ")" << FairLogger::endl;
334  LOG(DEBUG) << "[ERTelescopeTrackFinder] phi station: global vertex = (" << global_vertex1.x() << " " << global_vertex1.y()
335  << " " << global_vertex1.z() << ")" << FairLogger::endl;
336  LOG(DEBUG) << "[ERTelescopeTrackFinder] r station: global vertex = (" << global_vertex2.x() << " " << global_vertex2.y()
337  << " " << global_vertex2.z() << ")" << FairLogger::endl;
338  auto* track = AddTrack(TVector3(interaction_x_, interaction_y_, interaction_z_), global_vertex1, global_vertex2,
339  local_vertex1, local_vertex2, phiChannel, rChannel, phiEdep, rEdep,
340  trackBranchName);
341  //track->AddLink(FairLink(phiDigiBranchName, phiChannelIndex));
342  //track->AddLink(FairLink(rDigiBranchName, rChannelIndex));
343 }
344 //--------------------------------------------------------------------------------------------------
346  for (const auto itTrackBranches : fQTelescopeTrack) {
347  if (itTrackBranches.second) {
348  itTrackBranches.second->Delete();
349  }
350  }
351 }
352 //--------------------------------------------------------------------------------------------------
354  const TVector3& targetVertex, const TVector3& xStationVertex, const TVector3& yStationVertex,
355  const TVector3& xStationLocalVertex, const TVector3& yStationLocalVertex,
356  const Int_t xChannel, const Int_t yChannel, const Double_t xEdep, const Double_t yEdep,
357  const TString& digiBranchName) {
358  return new((*fQTelescopeTrack[digiBranchName]) [fQTelescopeTrack[digiBranchName]->GetEntriesFast()])
359  ERTelescopeTrack(targetVertex, xStationVertex, yStationVertex, xStationLocalVertex,
360  yStationLocalVertex, xChannel, yChannel, xEdep, yEdep);
361 }
362 //--------------------------------------------------------------------------------------------------
363 ClassImp(ERTelescopeTrackFinder)
Definition: ERDigi.h:15
virtual void Reset()
Resets all output data.
ERTelescopeTrackFinder()
Default constructor.
virtual InitStatus Init()
Defines all input and output object colletions participates in track finding.
ERTelescopeSetup * fQTelescopeSetup
access to ERTelescopeSetup class instance
ERTelescopeTrack * AddTrack(const TVector3 &targetVertex, const TVector3 &xStationVertex, const TVector3 &yStationVertex, const TVector3 &xStationLocalVertex, const TVector3 &yStationLocalVertex, Int_t xChannel, Int_t yChannel, Double_t xEdep, Double_t yEdep, const TString &digiBranchName)
Adds a ERTelescopeTrack to the output Collection.
virtual InitStatus Init()
Definition: ERTask.cxx:31
std::vector< TString > fAvailibleRunManagers
Run managers that are availible for this task.
Definition: ERTask.h:64
Base abstract class for all tasks in er.
Definition: ERTask.h:27
virtual void Exec(Option_t *opt)
Defines the transformation actions for all input data (Digi) to output data (Track) for each event...