-
Etienne Bechtel authoredEtienne Bechtel authored
CbmTrdModuleRecR.cxx 24.85 KiB
#include "CbmTrdModuleRecR.h"
#include "CbmTrdAddress.h"
#include "CbmTrdCluster.h"
#include "CbmTrdClusterFinder.h"
#include "CbmTrdDigi.h"
#include "CbmTrdHit.h"
#include "CbmTrdParModDigi.h"
#include "CbmTrdParSetDigi.h"
#include "TGeoMatrix.h"
#include <TCanvas.h>
#include <TClonesArray.h>
#include <TH2F.h>
#include <TImage.h>
#include <TVector3.h>
#include <iostream>
#include "CbmDigiManager.h"
#include <FairLogger.h>
using std::cout;
using std::deque;
using std::endl;
using std::get;
using std::list;
using std::make_pair;
using std::make_tuple;
using std::map;
using std::pair;
using std::tuple;
using std::vector;
//_______________________________________________________________________________
CbmTrdModuleRecR::CbmTrdModuleRecR()
: CbmTrdModuleRec(), fDigiCounter(0), fDigiMap(), fClusterMap() {
SetNameTitle("TrdModuleRecR", "Reconstructor for rectangular pad TRD module");
}
//_______________________________________________________________________________
CbmTrdModuleRecR::CbmTrdModuleRecR(Int_t mod, Int_t ly, Int_t rot)
: CbmTrdModuleRec(mod, ly, rot), fDigiCounter(0), fDigiMap(), fClusterMap() {
SetNameTitle(Form("TrdModuleRecR%02d", mod),
"Reconstructor for rectangular pad TRD module");
}
//_______________________________________________________________________________
CbmTrdModuleRecR::~CbmTrdModuleRecR() {}
//_______________________________________________________________________________
Bool_t CbmTrdModuleRecR::AddDigi(const CbmTrdDigi* digi, Int_t id) {
// fill the digimap
fDigiMap.push_back(make_tuple(id, false, digi));
fDigiCounter++;
return kTRUE;
}
//_______________________________________________________________________________
void CbmTrdModuleRecR::Clear(Option_t* opt) {
if (strcmp(opt, "cls") == 0) {
fDigiMap.erase(fDigiMap.begin(), fDigiMap.end());
fClusterMap.erase(fClusterMap.begin(), fClusterMap.end());
fDigiCounter = 0;
}
CbmTrdModuleRec::Clear(opt);
}
//_______________________________________________________________________________
Int_t CbmTrdModuleRecR::FindClusters() {
deque<tuple<Int_t, Bool_t, const CbmTrdDigi*>>::iterator
mainit; // subiterator for the deques in each module; searches for
// main-trigger to then add the neighbors
deque<tuple<Int_t, Bool_t, const CbmTrdDigi*>>::iterator FNit; // last
// iterator to
// find the FN
// digis which
// correspond
// to the main
// trigger or
// the
// adjacent
// main
// triggers
deque<tuple<Int_t, Bool_t, const CbmTrdDigi*>>::iterator start; // marker to
// erase
// already
// processed
// entries
// from the
// map to
// reduce the
// complexity
// of the
// algorithm
deque<tuple<Int_t, Bool_t, const CbmTrdDigi*>>::iterator stop; // marker to
// erase
// already
// processed
// entries
// from the
// map to
// reduce the
// complexity
// of the
// algorithm
// reset time information; used to erase processed digis from the map
Double_t time = 0;
Double_t lasttime = 0;
Double_t timediff = -1000;
Int_t Clustercount = 0;
Double_t interval = CbmTrdDigi::Clk(CbmTrdDigi::kSPADIC);
Bool_t print = false;
// iterator for the main trigger; searches for an unprocessed main triggered
// digi and then starts a subloop to directly construct the cluster
// while(!fDigiMap.empty()){
// std::cout<<fDigiMap.size()<<std::endl;
if (print) {
std::cout << fDigiMap.size() << std::endl;
for (mainit = fDigiMap.begin(); mainit != fDigiMap.end(); mainit++) {
const CbmTrdDigi* digi = (const CbmTrdDigi*) get<2>(*mainit);
Double_t ptime = digi->GetTime();
// Int_t digiAddress = digi->GetAddress();
Float_t Charge = digi->GetCharge();
// Int_t digiId = get<0>(*mainit);
Int_t channel = digi->GetAddressChannel();
Int_t ncols = fDigiPar->GetNofColumns();
Int_t triggerId = digi->GetTriggerType();
std::cout << " module: " << fModAddress << " time: " << ptime
<< " charge: " << Charge << " col: " << channel % ncols
<< " row: " << channel / ncols << " trigger: " << triggerId
<< " ncols: " << ncols << std::endl;
}
}
start = fDigiMap.begin();
for (mainit = fDigiMap.begin(); mainit != fDigiMap.end(); mainit++) {
// block to erase processed entries
const CbmTrdDigi* digi = (const CbmTrdDigi*) get<2>(*mainit);
if (!digi) continue;
time = digi->GetTime();
if (lasttime > 0) timediff = time - lasttime;
lasttime = time;
// if(timediff < -interval) start=mainit;
if (timediff > interval && lasttime > 0) { start = mainit; }
// if(timediff > interval) {start=mainit;stop=mainit;break;}
if (timediff > interval) {
fDigiMap.erase(fDigiMap.begin(), stop + 1);
start = mainit;
stop = mainit;
}
if (timediff < interval) stop = mainit;
Int_t triggerId = digi->GetTriggerType();
Bool_t marked = get<1>(*mainit);
if (triggerId != CbmTrdDigi::kSelf || marked) continue;
// variety of neccessary address information; uses the "combiId" for the
// comparison of digi positions
// Int_t digiAddress = digi->GetAddress();
Float_t Charge = digi->GetCharge();
Int_t digiId = get<0>(*mainit);
Int_t channel = digi->GetAddressChannel();
Int_t ncols = fDigiPar->GetNofColumns();
// some logic information which is used to process and find the clusters
Int_t lowcol = channel;
Int_t highcol = channel;
Int_t lowrow = channel;
Int_t highrow = channel;
// counter which is used to easily break clusters which are at the edge and
// therefore do not fullfill the classical look
Int_t dmain = 1;
// information buffer to handle neighbor rows and cluster over two rows; the
// identification of adjacent rows is done by comparing their center of
// gravity
Int_t counterrow = 1;
Int_t countertop = 0;
Int_t counterbot = 0;
Double_t buffertop[3] = {0, 0, 0};
Double_t bufferbot[3] = {0, 0, 0};
Double_t bufferrow[3] = {Charge, 0, 0};
// vector<Double_t> buffertop;
// vector<Double_t> bufferbot;
// vector<Double_t> bufferrow;
Double_t CoGtop = 0.;
Double_t CoGbot = 0.;
Double_t CoGrow = 0.;
tuple<const CbmTrdDigi*, const CbmTrdDigi*, const CbmTrdDigi*>
topdigi; // used to store the necassary digis for the CoG calculation
// without the need to revisit those digis
tuple<const CbmTrdDigi*, const CbmTrdDigi*, const CbmTrdDigi*> botdigi;
// //some logical flags to reject unnecessary steps
Bool_t finished =
false; // is turned true either if the implemented trigger
// logic is fullfilled or if there are no more
// adjacend pads due to edges,etc.
Bool_t sealtopcol =
false; // the "seal" bools register when the logical end
// of the cluster was found
Bool_t sealbotcol = false;
Bool_t sealtoprow = false;
Bool_t sealbotrow = false;
Bool_t rowchange = false; // flags that there is a possible two row cluster
Bool_t addtop = false; // adds the buffered information of the second row
Bool_t addbot = false;
// //deque which contains the actual cluster
deque<std::pair<Int_t, const CbmTrdDigi*>> cluster;
cluster.push_back(make_pair(digiId, digi));
if (print)
std::cout << " module: " << fModAddress << " time: " << time
<< " charge: " << Charge << " col: " << channel % ncols
<< " row: " << channel / ncols << " trigger: " << triggerId
<< " ncols: " << ncols << std::endl;
// std::cout<<" module: " << fModAddress<<" time: " << time<<"
// charge: " << Charge<<" col: " << channel % ncols<<" trigger: " <<
// triggerId<<" ncols: " << ncols<<std::endl;
get<1>(*mainit) = true;
// Bool_t mergerow=CbmTrdClusterFinder::HasRowMerger();
Bool_t mergerow = true;
// loop to find the other pads corresponding to the main trigger
while (!finished) {
dmain = 0;
// for (FNit=fDigiMap.begin() ; FNit != fDigiMap.end();FNit++) {
for (FNit = start; FNit != fDigiMap.end(); FNit++) {
// some information to serparate the time space and to skip processed
// digis
// continue;
const CbmTrdDigi* d = (const CbmTrdDigi*) get<2>(*FNit);
Double_t newtime = d->GetTime();
Double_t dt = newtime - time;
Bool_t filled = get<1>(*FNit);
if (filled) continue;
if (dt < -interval) continue;
if (dt > interval) break;
// position information of the possible neighbor digis
Double_t charge = d->GetCharge();
// digiAddress = d->GetAddress();
Int_t digiid = get<0>(*FNit);
Int_t ch = d->GetAddressChannel();
Int_t col = ch % ncols;
Int_t trigger = d->GetTriggerType();
if (mergerow) {
// multiple row processing
// first buffering
if (ch == channel - ncols && !rowchange
&& trigger == CbmTrdDigi::kSelf && !get<1>(*FNit)) {
rowchange = true;
bufferbot[0] = charge;
counterbot++;
get<0>(botdigi) = d;
}
if (ch == (channel - ncols) - 1 && rowchange && !get<1>(*FNit)) {
bufferbot[1] = charge;
counterbot++;
get<1>(botdigi) = d;
}
if (ch == (channel - ncols) + 1 && rowchange && !get<1>(*FNit)) {
bufferbot[2] = charge;
counterbot++;
get<2>(botdigi) = d;
}
if (ch == channel + ncols && !rowchange
&& trigger == CbmTrdDigi::kSelf && !get<1>(*FNit)) {
rowchange = true;
buffertop[0] = charge;
countertop++;
get<0>(topdigi) = d;
}
if (ch == (channel + ncols) - 1 && rowchange && !get<1>(*FNit)) {
buffertop[1] = charge;
countertop++;
get<1>(topdigi) = d;
}
if (ch == (channel + ncols) + 1 && rowchange && !get<1>(*FNit)) {
buffertop[2] = charge;
countertop++;
get<2>(topdigi) = d;
}
if (ch == channel - 1) {
bufferrow[1] = charge;
counterrow++;
get<1>(topdigi) = d;
}
if (ch == channel + 1) {
bufferrow[2] = charge;
counterrow++;
get<2>(topdigi) = d;
}
// then the calculation of the center of gravity with the
// identification of common CoGs
if (countertop == 3) {
CoGtop =
(buffertop[2] / buffertop[0]) - (buffertop[1] / buffertop[0]);
}
if (counterbot == 3) {
CoGbot =
(bufferbot[2] / bufferbot[0]) - (bufferbot[1] / bufferbot[0]);
}
if (counterrow == 3) {
CoGrow =
(bufferrow[2] / bufferrow[0]) - (bufferrow[1] / bufferrow[0]);
}
if (countertop == 3 && counterrow == 3 && !addtop
&& TMath::Abs((CoGtop - CoGrow)) < 0.25 * CoGrow) {
addtop = true;
}
if (counterbot == 3 && counterrow == 3 && !addbot
&& TMath::Abs((CoGbot - CoGrow)) < 0.25 * CoGrow) {
addbot = true;
}
}
// logical implementation of the trigger logic in the same row as the
// main trigger
if (ch == lowcol - 1 && trigger == CbmTrdDigi::kSelf
&& !get<1>(*FNit)) {
cluster.push_back(make_pair(digiid, d));
lowcol = ch;
dmain++;
get<1>(*FNit) = true;
if (print)
std::cout << " time: " << newtime << " charge: " << charge
<< " col: " << col << " row: " << ch / ncols
<< " trigger: " << trigger << std::endl;
}
if (ch == highcol + 1 && trigger == CbmTrdDigi::kSelf
&& !get<1>(*FNit)) {
cluster.push_back(make_pair(digiid, d));
highcol = ch;
dmain++;
get<1>(*FNit) = true;
if (print)
std::cout << " time: " << newtime << " charge: " << charge
<< " col: " << col << " row: " << ch / ncols
<< " trigger: " << trigger << std::endl;
}
if (ch == highcol + 1 && trigger == CbmTrdDigi::kNeighbor
&& !get<1>(*FNit) && !sealtopcol) {
cluster.push_back(make_pair(digiid, d));
sealtopcol = true;
dmain++;
get<1>(*FNit) = true;
if (print)
std::cout << " time: " << newtime << " charge: " << charge
<< " col: " << col << " row: " << ch / ncols
<< " trigger: " << trigger << std::endl;
}
if (ch == lowcol - 1 && trigger == CbmTrdDigi::kNeighbor
&& !get<1>(*FNit) && !sealbotcol) {
cluster.push_back(make_pair(digiid, d));
sealbotcol = true;
dmain++;
get<1>(*FNit) = true;
if (print)
std::cout << " time: " << newtime << " charge: " << charge
<< " col: " << col << " row: " << ch / ncols
<< " trigger: " << trigger << std::endl;
}
if (col == ncols) { sealtopcol = true; }
if (col == 0) { sealbotcol = true; }
if (mergerow) {
// adding of the neighboring row
if (ch == channel - ncols && addbot && !get<1>(*FNit)) {
cluster.push_back(make_pair(digiid, d));
lowrow = ch;
highrow = ch;
dmain++;
get<1>(*FNit) = true;
}
if (ch == channel + ncols && addtop && !get<1>(*FNit)) {
cluster.push_back(make_pair(digiid, d));
lowrow = ch;
highrow = ch;
dmain++;
get<1>(*FNit) = true;
}
if (rowchange && ch == lowrow - 1 && lowrow != channel
&& trigger == CbmTrdDigi::kSelf && !get<1>(*FNit)) {
cluster.push_back(make_pair(digiid, d));
lowrow = ch;
dmain++;
get<1>(*FNit) = true;
}
if (rowchange && ch == highrow + 1 && highrow != channel
&& trigger == CbmTrdDigi::kSelf && !get<1>(*FNit)) {
cluster.push_back(make_pair(digiid, d));
highrow = ch;
dmain++;
get<1>(*FNit) = true;
}
if (rowchange && ch == highrow + 1 && highrow != channel
&& trigger == CbmTrdDigi::kNeighbor && !get<1>(*FNit)
&& !sealtoprow) {
cluster.push_back(make_pair(digiid, d));
sealtoprow = true;
dmain++;
get<1>(*FNit) = true;
}
if (rowchange && ch == lowrow - 1 && lowrow != channel
&& trigger == CbmTrdDigi::kNeighbor && !get<1>(*FNit)
&& !sealbotrow) {
cluster.push_back(make_pair(digiid, d));
sealbotrow = true;
dmain++;
get<1>(*FNit) = true;
}
}
}
// some finish criteria
if (((sealbotcol && sealtopcol) && !rowchange) || dmain == 0)
finished = true;
if ((sealbotcol && sealtopcol && sealtoprow && sealbotrow) || dmain == 0)
finished = true;
// finished=true;
if (print) cout << dmain << endl;
} // end of cluster completion
if (print) cout << dmain << endl;
if (print) cout << endl;
// fClusterMap.push_back(cluster);
Clustercount++;
addClusters(cluster);
} // end of main trigger loop
// fDigiMap.erase(fDigiMap.begin(),fDigiMap.end());
// }
// Int_t checkcount=0;
// for (mainit=fDigiMap.begin() ; mainit != fDigiMap.end(); mainit++) {
// if(!get<1>(*mainit)) checkcount++;
// }
// std:cout<< checkcount<<" " << fDigiMap.size()<<std::endl;
return Clustercount;
}
//_____________________________________________________________________
void CbmTrdModuleRecR::addClusters(
deque<std::pair<Int_t, const CbmTrdDigi*>> cluster) {
// create vector for indice matching
vector<Int_t> digiIndices(cluster.size());
Int_t idigi = 0;
CbmDigiManager::Instance()->Init();
for (std::deque<std::pair<Int_t, const CbmTrdDigi*>>::iterator iDigi =
cluster.begin();
iDigi != cluster.end();
iDigi++) {
// add digi id to vector
digiIndices[idigi] = iDigi->first;
idigi++;
}
// add the clusters to the Array
// const CbmDigi* digi = static_cast<const
// CbmDigi*>(fDigis->At(digiIndices.front()));
Int_t size = fClusters->GetEntriesFast();
CbmTrdCluster* newcluster = new ((*fClusters)[size]) CbmTrdCluster();
// std::cout<<idigi<<std::endl;
newcluster->SetAddress(fModAddress);
newcluster->SetDigis(digiIndices);
newcluster->SetNCols(idigi);
// BuildChannelMap(cluster);
}
//_______________________________________________________________________________
Bool_t CbmTrdModuleRecR::MakeHits() { return kTRUE; }
//_______________________________________________________________________________
CbmTrdHit* CbmTrdModuleRecR::MakeHit(Int_t clusterId,
const CbmTrdCluster* /*cluster*/,
std::vector<const CbmTrdDigi*>* digis) {
TVector3 hit_posV;
TVector3 local_pad_posV;
TVector3 local_pad_dposV;
for (Int_t iDim = 0; iDim < 3; iDim++) {
hit_posV[iDim] = 0.0;
local_pad_posV[iDim] = 0.0;
local_pad_dposV[iDim] = 0.0;
}
Double_t xVar = 0;
Double_t yVar = 0;
Double_t totalCharge = 0;
// Double_t totalChargeTR = 0;
// Double_t momentum = 0.;
// Int_t moduleAddress = 0;
Double_t time = 0.;
Int_t errorclass = 0.;
Bool_t EB = false;
Bool_t EBP = false;
for (std::vector<const CbmTrdDigi*>::iterator id = digis->begin();
id != digis->end();
id++) {
const CbmTrdDigi* digi = (*id);
if (!digi) {
continue;
std::cout << " no digi " << std::endl;
}
Double_t digiCharge = digi->GetCharge();
errorclass = digi->GetErrorClass();
EB = digi->IsFlagged(0);
EBP = digi->IsFlagged(1);
// if (digiCharge <= 0) {std::cout<<" charge 0 " <<
// std::endl;continue;}
if (digiCharge <= 0.05) { continue; }
time += digi->GetTime();
// time += digi->GetTimeDAQ();
totalCharge += digi->GetCharge();
fDigiPar->GetPadPosition(
digi->GetAddressChannel(), true, local_pad_posV, local_pad_dposV);
Double_t xMin = local_pad_posV[0] - local_pad_dposV[0];
Double_t xMax = local_pad_posV[0] + local_pad_dposV[0];
xVar += (xMax * xMax + xMax * xMin + xMin * xMin) * digiCharge;
Double_t yMin = local_pad_posV[1] - local_pad_dposV[1];
Double_t yMax = local_pad_posV[1] + local_pad_dposV[1];
yVar += (yMax * yMax + yMax * yMin + yMin * yMin) * digiCharge;
for (Int_t iDim = 0; iDim < 3; iDim++) {
hit_posV[iDim] += local_pad_posV[iDim] * digiCharge;
}
}
time /= digis->size();
if (totalCharge <= 0) return NULL;
Double_t hit_pos[3];
for (Int_t iDim = 0; iDim < 3; iDim++) {
hit_posV[iDim] /= totalCharge;
hit_pos[iDim] = hit_posV[iDim];
}
if (EB) {
if (errorclass == 0)
xVar = 0.0258725;
else if (errorclass == 1)
xVar = 0.0267693;
else if (errorclass == 2)
xVar = 0.0344325;
else if (errorclass == 3)
xVar = 0.0260322;
else if (errorclass == 4)
xVar = 0.040115;
if (errorclass == 0)
yVar = 0.024549;
else if (errorclass == 1)
yVar = 0.025957;
else if (errorclass == 2)
yVar = 0.0250713;
else if (errorclass == 3)
yVar = 0.0302682;
else if (errorclass == 4)
yVar = 0.0291146;
} else {
if (EBP) time -= 46; // due to the event time of 0 in the EB
// mode and the ULong in the the digi time
// TODO: move variables to parameter file
if (errorclass == 0)
xVar = 0.0426313;
else if (errorclass == 1)
xVar = 0.0426206;
else if (errorclass == 2)
xVar = 0.0636962;
else if (errorclass == 3)
xVar = 0.038981;
else if (errorclass == 4)
xVar = 0.0723851;
if (errorclass == 0)
yVar = 0.0401438;
else if (errorclass == 1)
yVar = 0.0407502;
else if (errorclass == 2)
yVar = 0.0397242;
else if (errorclass == 3)
yVar = 0.0519485;
else if (errorclass == 4)
yVar = 0.0504586;
}
TVector3 cluster_pad_dposV(xVar, yVar, 0);
// --- If a TGeoNode is attached, transform into global coordinate system
Double_t global[3];
LocalToMaster(hit_pos, global);
if (!EB) { // preliminary correction for angle dependence in the position
// reconsutrction
global[0] = global[0] + (0.00214788 + global[0] * 0.000195394);
global[1] = global[1] + (0.00370566 + global[1] * 0.000213235);
}
fDigiPar->TransformHitError(cluster_pad_dposV);
// TODO: get momentum for more exact spacial error
if ((fDigiPar->GetOrientation() == 1) || (fDigiPar->GetOrientation() == 3)) {
cluster_pad_dposV[0] = sqrt(fDigiPar->GetPadSizeY(1));
} else {
cluster_pad_dposV[1] = sqrt(fDigiPar->GetPadSizeY(1));
}
Int_t nofHits = fHits->GetEntriesFast();
// return new ((*fHits)[nofHits]) CbmTrdHit(fModAddress, global,
// cluster_pad_dposV, 0, clusterId,0, 0,
// totalCharge/1e6,time,Double_t(CbmTrdDigi::Clk(CbmTrdDigi::kSPADIC)));
return new ((*fHits)[nofHits])
CbmTrdHit(fModAddress,
global,
cluster_pad_dposV,
0,
clusterId,
totalCharge / 1e6,
time,
Double_t(8.5)); // TODO: move to parameter file
}
Double_t CbmTrdModuleRecR::GetSpaceResolution(Double_t val) {
std::pair<Double_t, Double_t> res[12] = {make_pair(0.5, 0.4),
make_pair(1, 0.35),
make_pair(2, 0.3),
make_pair(2.5, 0.3),
make_pair(3.5, 0.28),
make_pair(4.5, 0.26),
make_pair(5.5, 0.26),
make_pair(6.5, 0.26),
make_pair(7.5, 0.26),
make_pair(8.5, 0.26),
make_pair(8.5, 0.26),
make_pair(9.5, 0.26)};
Double_t selval = 0.;
for (Int_t n = 0; n < 12; n++) {
if (val < res[0].first) selval = res[0].second;
if (n == 11) {
selval = res[11].second;
break;
}
if (val >= res[n].first && val <= res[n + 1].first) {
Double_t dx = res[n + 1].first - res[n].first;
Double_t dy = res[n + 1].second - res[n].second;
Double_t slope = dy / dx;
selval = (val - res[n].first) * slope + res[n].second;
break;
}
}
return selval;
}
ClassImp(CbmTrdModuleRecR)