-
Administrator authored
Apply code formatting to all source/header files and root macros.
Administrator authoredApply code formatting to all source/header files and root macros.
CbmTrdModuleRecT.cxx 29.70 KiB
#include "CbmTrdModuleRecT.h"
#include "CbmTrdCluster.h"
#include "CbmTrdDigi.h"
#include "CbmTrdFASP.h"
#include "CbmTrdHit.h"
#include "CbmTrdParModDigi.h"
#include <FairLogger.h>
#include <TGeoPhysicalNode.h>
#include <TClonesArray.h>
#include <TF1.h>
#include <TGraphErrors.h>
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
Double_t CbmTrdModuleRecT::fgDT[] = {4.181e-6, 1586, 24};
TGraphErrors* CbmTrdModuleRecT::fgEdep = NULL;
TGraphErrors* CbmTrdModuleRecT::fgT = NULL;
TF1* CbmTrdModuleRecT::fgPRF = NULL;
//_______________________________________________________________________________
CbmTrdModuleRecT::CbmTrdModuleRecT()
: CbmTrdModuleRec()
, fConfigMap(0)
, fT0(0)
, fBuffer()
, vs()
, vse()
, vt()
, vx()
, vxe() {}
//_______________________________________________________________________________
CbmTrdModuleRecT::CbmTrdModuleRecT(Int_t mod, Int_t ly, Int_t rot)
: CbmTrdModuleRec(mod, ly, rot)
, fConfigMap(0)
, fT0(0)
, fBuffer()
, vs()
, vse()
, vt()
, vx()
, vxe() {
//printf("AddModuleT @ %d\n", mod); Config(1,0);
SetNameTitle(Form("TrdRecT%d", mod),
"Reconstructor for triangular read-out.");
}
//_______________________________________________________________________________
CbmTrdModuleRecT::~CbmTrdModuleRecT() {}
//_______________________________________________________________________________
Bool_t CbmTrdModuleRecT::AddDigi(const CbmTrdDigi* d, Int_t id) {
/* Add digi to cluster fragments. At first clusters are ordered on pad rows and time.
* No channel ordering is assumed. The time condition for a digi to enter a cluster
* chunk is to have abs(dt)<5 wrt cluster t0
*/
if (CWRITE()) cout << "add @" << id << " " << d->ToString();
Int_t ch = d->GetAddressChannel(), col, row = GetPadRowCol(ch, col), dtime;
Double_t t, r = d->GetCharge(t, dtime);
Int_t tm = d->GetTimeDAQ() - fT0, terminator(0);
if (dtime < 0)
tm += dtime; // correct for the difference between tilt and rect
if (r < 1)
terminator = 1;
else if (t < 1)
terminator = -1;
if (CWRITE())
printf(
"row[%2d] col[%2d] tm[%2d] terminator[%d]\n", row, col, tm, terminator);
CbmTrdCluster* cl(NULL);
// get the link to saved clusters
std::map<Int_t, std::list<CbmTrdCluster*>>::iterator it = fBuffer.find(row);
// check for saved
if (it != fBuffer.end()) {
Bool_t kINSERT(kFALSE);
std::list<CbmTrdCluster*>::iterator itc = fBuffer[row].begin();
for (; itc != fBuffer[row].end(); itc++) {
if (CWRITE()) cout << (*itc)->ToString();
UShort_t tc = (*itc)->GetStartTime();
Int_t dt = tc - tm;
if (dt < -5)
continue;
else if (dt < 5) {
if (CWRITE()) printf("match time dt=%d\n", dt);
if ((*itc)->IsChannelInRange(ch) == 0) {
if (!(*itc)->AddDigi(id, ch, terminator, dt)) break;
kINSERT = kTRUE;
if (CWRITE()) cout << " => Cl (Ad) " << (*itc)->ToString();
break;
}
} else {
if (CWRITE()) printf("break for time dt=%d\n", dt);
break;
}
}
if (!kINSERT) {
if (itc != fBuffer[row].end() && itc != fBuffer[row].begin()) {
itc--;
fBuffer[row].insert(
itc, cl = new CbmTrdCluster(fModAddress, id, ch, row, tm));
if (CWRITE()) cout << " => Cl (I) " << cl->ToString();
} else {
fBuffer[row].push_back(
cl = new CbmTrdCluster(fModAddress, id, ch, row, tm));
if (CWRITE()) cout << " => Cl (Pb) " << cl->ToString();
}
cl->SetTrianglePads();
if (terminator < 0)
cl->SetProfileStart();
else if (terminator > 0)
cl->SetProfileStop();
}
} else {
fBuffer[row].push_back(cl =
new CbmTrdCluster(fModAddress, id, ch, row, tm));
cl->SetTrianglePads();
if (terminator < 0)
cl->SetProfileStart();
else if (terminator > 0)
cl->SetProfileStop();
if (CWRITE()) cout << " => Cl (Nw) " << cl->ToString();
}
return kTRUE;
}
//_______________________________________________________________________________
Int_t CbmTrdModuleRecT::GetOverThreshold() const {
Int_t nch(0);
for (std::map<Int_t, std::list<CbmTrdCluster*>>::const_iterator ir =
fBuffer.cbegin();
ir != fBuffer.cend();
ir++) {
for (std::list<CbmTrdCluster*>::const_iterator itc = (*ir).second.cbegin();
itc != (*ir).second.cend();
itc++)
nch += (*itc)->GetNCols();
}
return nch;
}
//_______________________________________________________________________________
Int_t CbmTrdModuleRecT::FindClusters() {
CbmTrdCluster* cl(NULL);
// get the link to saved clusters
Int_t ncl(0);
std::list<CbmTrdCluster*>::iterator itc0, itc1;
for (std::map<Int_t, std::list<CbmTrdCluster*>>::iterator ir =
fBuffer.begin();
ir != fBuffer.end();
ir++) {
itc0 = (*ir).second.begin();
while ((*ir).second.size() > 1
&& itc0 != (*ir).second.end()) { // try merge clusters
itc1 = itc0;
itc1++;
Bool_t kMERGE = kFALSE;
while (itc1 != (*ir).second.end()) {
if (CWRITE())
cout << " base cl[0] : " << (*itc0)->ToString()
<< " + cl[1] : " << (*itc1)->ToString();
if ((*itc0)->Merge((*itc1))) {
if (CWRITE()) cout << " SUM : " << (*itc0)->ToString();
kMERGE = kTRUE;
delete (*itc1);
itc1 = (*ir).second.erase(itc1);
if (itc1 == (*ir).second.end()) break;
} else
itc1++;
}
if (!kMERGE) itc0++;
}
for (itc0 = (*ir).second.begin(); itc0 != (*ir).second.end(); itc0++) {
cl = (*itc0);
cl = new ((*fClusters)[ncl++]) CbmTrdCluster(*cl);
cl->SetTrianglePads();
delete (*itc0);
}
}
fBuffer.clear();
//printf("fClusters[%p] nCl[%d]\n", (void*)fClusters, fClusters->GetEntriesFast());
//LOG(info) << GetName() << "::FindClusters : " << ncl;
return ncl;
}
//_______________________________________________________________________________
Bool_t CbmTrdModuleRecT::MakeHits() { return kTRUE; }
//_______________________________________________________________________________
Bool_t CbmTrdModuleRecT::Finalize() {
/* Steering routine for classifying hits and apply further analysis
* -> hit deconvolution (see Deconvolute)
* -> hit merging for row-cross (see RowCross)
*/
// Int_t nhits=fHits->GetEntriesFast();
// //if(CWRITE())
// LOG(info) << "\n"<<GetName()<<"::Finalize("<<nhits<<")";
// CbmTrdHit *hit(NULL), *hitp(NULL);
// for(Int_t ih(0); ih<nhits; ih++){
// hit = (CbmTrdHit*)((*fHits)[ih]);
// for(Int_t jh(ih+1); jh<nhits; jh++){
// hitp = (CbmTrdHit*)((*fHits)[jh]);
// //if(CWRITE())
// cout<<ih<<" "<<hit->ToString();
// cout<<"-> "<<jh<<" "<<hitp->ToString();
// }
// }
return kTRUE;
}
#include <TCanvas.h>
#include <TH1.h>
#define NANODE 9
//_______________________________________________________________________________
CbmTrdHit* CbmTrdModuleRecT::MakeHit(Int_t ic,
const CbmTrdCluster* cl,
std::vector<const CbmTrdDigi*>* digis) {
if (!fgEdep) { // first use initialization of PRF helppers
LOG(info) << GetName() << "::MakeHit: Init static helpers. ";
fgEdep = new TGraphErrors;
fgEdep->SetLineColor(kBlue);
fgEdep->SetLineWidth(2);
fgT = new TGraphErrors;
fgT->SetLineColor(kBlue);
fgT->SetLineWidth(2);
fgPRF = new TF1("prf", "[0]*exp(-0.5*((x-[1])/[2])**2)", -10, 10);
fgPRF->SetLineColor(kRed);
fgPRF->SetParNames("E", "x", "prf");
}
TH1* hf(NULL);
TCanvas* cvs(NULL);
if (CDRAW()) {
cvs = new TCanvas("c", "TRD Anode Hypothesis", 10, 600, 1000, 500);
cvs->Divide(2, 1, 1.e-5, 1.e-5);
TVirtualPad* vp = cvs->cd(1);
vp->SetLeftMargin(0.06904908);
vp->SetRightMargin(0.009969325);
vp->SetTopMargin(0.01402806);
vp = cvs->cd(2);
vp->SetLeftMargin(0.06904908);
vp->SetRightMargin(0.009969325);
vp->SetTopMargin(0.01402806);
hf = new TH1I("hf", ";x [pw];s [ADC chs]", 100, -3, 3);
hf->GetYaxis()->SetRangeUser(-50, 4500);
hf->Draw("p");
}
if (CWRITE()) cout << cl->ToString();
// check cluster integrity and do digi merging if needed
vector<Bool_t> vmask(digis->size(), 0); // masks in case of merged Digis
vector<CbmTrdDigi*> vdgM;
if (cl->GetNCols() != digis->size() && !MergeDigis(digis, &vdgM, &vmask)) {
cout << cl->ToString();
for (vector<const CbmTrdDigi*>::iterator i = digis->begin();
i != digis->end();
i++)
cout << (*i)->ToString();
return NULL;
}
// Read in all digis information()
ULong64_t t0 = fT0 + cl->GetStartTime(); // absolute hit time (prompt signal)
Int_t n0(0), ovf(0), cM;
if (!(n0 = LoadDigis(digis, &vdgM, &vmask, t0, cM))) {
cout << cl->ToString();
for (vector<const CbmTrdDigi*>::iterator i = digis->begin();
i != digis->end();
i++)
cout << (*i)->ToString();
return NULL;
}
if (n0 < 0) {
ovf = 1;
n0 *= -1;
}
// analyse digis topology; no of signal types, maximum, etc
Bool_t tM(kTRUE); // maximum type tilt=1; rect=0
Int_t nL(0); // signal index for the max signal
Int_t col, row = GetPadRowCol(cl->GetStartCh(), col);
Double_t max(0.), // maximum signal
LS(0.), // left side sum of signals
S(0.); // sum of signals
Int_t nr(0), nt(0);
for (Int_t is(1); is <= n0; is++) {
if (vxe[is] > 0) { // select tilted coupling
nt++;
S += vs[is];
if (vs[is] > max) {
max = vs[is];
tM = kTRUE;
nL = is;
LS += vs[is];
}
} else { // select rectangular coupling
nr++;
S += vs[is];
if (vs[is] > max) {
max = vs[is];
tM = kFALSE;
nL = is;
LS += vs[is];
}
}
}
col += cM;
S -= LS;
LS -= max;
// evaluate asymmetry
Int_t lr(0), // max signal left-right asymmetry wrt central pad
tr(0), // left-right innequality for symmetric clusters
nR(n0 + 1 - nL); // no of signals to the right of maximum
if (nL < nR)
lr = 1;
else if (nL > nR)
lr = -1;
if (!lr && (n0 % 2)) tr = (LS < S ? -1 : 1);
// compute x and y offset from center pad
Double_t dx(0.), dy(0.), edx(0.21650635),
edy(0.77942286); // fixed error parametrization
switch (n0) {
case 1:
if (nt) {
dx = -0.5;
dy = 0;
} // T
else {
dx = 0.5;
dy = 0;
} // R
break;
case 2:
if (cl->HasOpenStart() && cl->HasOpenStop()) {
dx = cM ? -1. : 0.;
dy = -0.5;
} // RT
else {
dx = 0.;
dy = 0.5;
} // TR
break;
case 3:
if (tM && lr) {
dx = cM ? -1. : 0.;
dy = GetYoffset(n0);
} // TRT asymm
else if (!tM && !lr) {
dx = 0.;
dy = GetYoffset(n0);
} // TRT symm
else if (tM && !lr) {
dx = GetXoffset(n0);
dy = 0.;
} // RTR symm
else if (!tM && lr) {
dx = GetXoffset(n0);
dy = cM ? 0.5 : -0.5;
} // RTR asymm
break;
default:
dx = GetXoffset(n0);
dy = GetYoffset(n0);
break;
}
if (dx < -0.5
&& cM > 0) { // shift graph representation to fit dx[pw] in [-0.5, 0.5]
dx += 1.;
col -= 1;
for (UInt_t idx(0); idx < vx.size(); idx++)
vx[idx] += 1;
}
if (dx > 0.5) { // dirty fix for compound clusters TODO
Int_t ishift = Int_t(dx - 0.5) + 1;
dx -= ishift;
col += ishift;
for (UInt_t idx(0); idx < vx.size(); idx++)
vx[idx] -= ishift;
}
dy = dx - dy; // only on natural scalling !
// go to cm scale
dx *= fDigiPar->GetPadSizeX(0);
dy *= fDigiPar->GetPadSizeY(0);
// apply systematic correction for x (MC derived)
Int_t typ = 0; // [0] center hit type
// [1] side hit type
if ((n0 == 5 && ((tM && !lr) || (!tM && lr))) || // TRTRT symm/asymm
n0 == 4 || (n0 == 3 && ((tM && !lr) || (!tM && lr != 0))))
typ = 1; // RTR symm/asymm
Double_t xcorr(0.);
Int_t nbins((NBINSCORRX - 1) >> 1), ii = nbins + TMath::Nint(dx / fgCorrXdx),
i0, i1;
if (ii < 0 || ii >= NBINSCORRX)
LOG(warn) << GetName() << "::MakeHit : Idx " << ii
<< " outside range for displacement " << dx << ".";
else {
if (dx < fgCorrXdx * ii) {
i0 = TMath::Max(0, ii - 1);
i1 = ii;
} else {
i0 = ii;
i1 = TMath::Min(NBINSCORRX - 1, ii + 1);
}
Double_t DDx = (fgCorrXval[typ][i1] - fgCorrXval[typ][i0]),
a = DDx / fgCorrXdx, b = fgCorrXval[typ][i0] - DDx * (i0 - nbins);
xcorr = 0.1 * (b + a * dx);
}
dx += xcorr;
dy += xcorr;
if (dx > 0.5 * fDigiPar->GetPadSizeX(0))
dx = 0.5 * fDigiPar->GetPadSizeX(0);
else if (dx < -0.5 * fDigiPar->GetPadSizeX(0))
dx = -0.5 * fDigiPar->GetPadSizeX(0);
if (dy > 0.5 * fDigiPar->GetPadSizeY(0)) { //
//printf("BEFORE dy[%+6.4f] dx[%+6.4f] {n[%d] max[%c] lr[%+d]}\n", dy, dx, n0, tM?'T':'R', lr);
dy -= fDigiPar->GetPadSizeY(0);
}
if (dy < -0.5 * fDigiPar->GetPadSizeY(0)) { //
//printf("(BEFORE) dy[%+6.4f] dx[%+6.4f] {n[%d] max[%c] lr[%+d]}\n", dy, dx, n0, tM?'T':'R', lr);
dy += fDigiPar->GetPadSizeY(0);
}
// process y offset
// apply systematic correction for y (MC derived)
Float_t fdy(1.), yoff(0.);
switch (n0) {
case 3:
fdy = fgCorrYval[0][0];
yoff = fgCorrYval[0][1];
if (tM && !lr)
dy -= tr * 0.5 * fDigiPar->GetPadSizeY(0);
else if (lr)
dy -= 0.5 * fDigiPar->GetPadSizeY(0);
;
break;
case 4:
fdy = fgCorrYval[1][0];
yoff = fgCorrYval[1][1];
if ((!tM && lr == 1) || (tM && lr == -1)) yoff *= -1;
break;
case 5:
case 7:
case 9:
case 11:
fdy = fgCorrYval[2][0];
yoff = fgCorrYval[2][1];
break;
case 6:
case 8:
case 10:
fdy = fgCorrYval[3][0];
yoff = fgCorrYval[3][1];
if ((!tM && lr == 1) || (tM && lr == -1)) yoff *= -1;
break;
}
dy *= fdy;
dy += yoff;
if (dy > 0.5 * fDigiPar->GetPadSizeY(0))
dy = 0.5 * fDigiPar->GetPadSizeY(0);
else if (dy < -0.5 * fDigiPar->GetPadSizeY(0))
dy = -0.5 * fDigiPar->GetPadSizeY(0);
// get anode wire offset
Int_t ia(0);
Float_t ya; // anode position in local pad coordinates
for (; ia <= NANODE; ia++) {
ya = -1.35 + ia * 0.3;
if (dy > ya + 0.15) continue;
break;
}
// Error parametrization X : parabolic model on cl size
Double_t parX[] = {0.713724, -0.318667, 0.0366036};
Int_t nex = TMath::Min(n0, 7);
edx = parX[0] + parX[1] * nex + parX[2] * nex * nex;
Double_t parY[] = {0.0886413, 0., 0.0435141};
edy = parY[0] + parY[2] * dy * dy;
if (CWRITE()) {
printf("row[%2d] col[%2d] sz[%d%c] M[%d%c] dx[mm]=%6.3f dy[mm]=%6.3f "
"t0[clk]=%llu OVF[%c]\n",
row,
col,
n0,
(lr ? (lr < 0 ? 'L' : 'R') : 'C'),
cM,
(tM ? 'T' : 'R'),
10 * dx,
10 * dy,
t0,
(ovf ? 'y' : 'n'));
for (UInt_t idx(0); idx < vs.size(); idx++) {
printf("%2d%cdt[%2d] s[ADC]=%6.1f+-%6.1f x[pw]=%5.2f+-%5.2f\n",
idx,
(UInt_t(nL) == idx ? '*' : ' '),
vt[idx],
vs[idx],
vse[idx],
vx[idx],
vxe[idx]);
}
}
// compute energy
for (UInt_t idx(0); idx < vs.size(); idx++) {
if (vxe[idx] > 0) {
fgEdep->SetPoint(idx, vx[idx] + dy / fDigiPar->GetPadSizeY(0), vs[idx]);
fgEdep->SetPointError(idx, vxe[idx], vse[idx]);
} else {
fgEdep->SetPoint(idx, vx[idx], vs[idx]);
fgEdep->SetPointError(idx, vxe[idx], vse[idx]);
}
}
Double_t xc = vx[n0 + 2];
for (Int_t ip(vs.size()); ip < fgEdep->GetN(); ip++) {
//fgEdep->RemovePoint(ip);
xc += 0.5;
fgEdep->SetPoint(ip, xc, 0);
fgEdep->SetPointError(ip, 0., 300);
}
if (CWRITE()) fgEdep->Print();
Double_t e(0.), chi(100), xlo(*vx.begin()), xhi(*vx.rbegin());
fgPRF->SetParameter(0, max);
fgPRF->FixParameter(1, dx / fDigiPar->GetPadSizeX(0));
fgPRF->SetParameter(2, 0.65);
fgPRF->SetParLimits(2, 0.45, 10.5);
fgEdep->Fit(fgPRF, "QBN", "goff", xlo - 0.5, xhi + 0.5);
if (!fgPRF->GetNDF()) return NULL;
chi = fgPRF->GetChisquare() / fgPRF->GetNDF();
e = fgPRF->Integral(xlo - 0.5, xhi + 0.5);
// apply MC correction
Float_t gain0 = 210.21387; //(XeCO2 @ 1900V)
// Float_t grel[3] = {1., 0.98547803, 0.93164071},
// goff[3][3] = {
// {0.05714, -0.09, -0.09},
// {0., -0.14742, -0.14742},
// {0., -0.29, -0.393}
// };
// Int_t ian=0;
// if(TMath::Abs(dy)<=0.3) ian=0;
// else if(TMath::Abs(dy)<=0.6) ian=1;
// else if(TMath::Abs(dy)<=0.9) ian=2;
// Int_t isize=0;
// if(n0<=3) isize=0;
// else if(n0<=4) isize=1;
// else isize=2;
Float_t gain = gain0; //*grel[ian];
e /= gain; // apply effective gain
//e+=goff[ian][isize]; // apply missing energy offset
TVector3 local_pad, local_pad_err;
Int_t srow, sector = fDigiPar->GetSectorRow(row, srow);
fDigiPar->GetPadPosition(sector, col, srow, local_pad, local_pad_err);
//printf("r[%2d] c[%2d] max[%d] lr[%d] n0[%d] cM[%d] nM[%d] dx[%7.4f] dy[%7.4f] loc[%6.2f %6.2f %6.2f] err[%6.2f %6.2f %6.2f] e[%f] chi[%f]\n", row, col, mtyp, lr, n0, cM, nM, dx, dy, local_pad[0], local_pad[1], local_pad[2], local_pad_err[0], local_pad_err[1], local_pad_err[2], e, chi);
Double_t local[3] = {local_pad[0] + dx, local_pad[1] + dy, local_pad[2]},
global[3], globalErr[3] = {edx, edy, 0.};
LocalToMaster(local, global);
// process time profile
for (Int_t idx(1); idx <= n0; idx++) {
Double_t dtFEE = fgDT[0] * (vs[idx] - fgDT[1]) * (vs[idx] - fgDT[1])
/ CbmTrdDigi::Clk(CbmTrdDigi::kFASP);
if (vxe[idx] > 0) vx[idx] += dy / fDigiPar->GetPadSizeY(0);
fgT->SetPoint(idx - 1, vx[idx], vt[idx] - dtFEE);
}
xc = vx[n0 + 2];
for (Int_t ip(n0); ip < fgT->GetN(); ip++) {
fgT->SetPoint(ip, xc, 0);
xc += 0.5;
}
Double_t time(-21.),
edt(26.33), // should be parametrized as function of da TODO
tdrift(100); // should depend on Ua
if (n0 > 1 && (fgT->Fit("pol1", "QC", "goff") == 0)) {
TF1* f = fgT->GetFunction("pol1");
time = f->GetParameter(0) - fgDT[2];
if (TMath::IsNaN(time)) time = -21;
//dtime += TMath::Abs(f->GetParameter(1)*(vx[n0+1] - vx[1]));
}
if (CDRAW()) {
Double_t rangex(vx[0] - 0.25), rangeX(vx[n0 + 2] + 0.25);
cvs->cd(1);
hf->Draw("p");
hf->GetXaxis()->SetRangeUser(rangex, rangeX);
hf->SetTitle(Form(
"%d[%d] row[%d] col[%2d] an[%+d] m[%+4.2f] s[%4.2f] E[%7.2f] chi2[%7.2f]",
ic,
Int_t(vs.size()),
row,
col,
ia,
fgPRF->GetParameter(1),
fgPRF->GetParameter(2),
e,
chi));
hf->GetXaxis()->SetRangeUser(rangex, rangeX);
hf->GetYaxis()->SetRangeUser(-100., 4500);
fgEdep->Draw("pl");
fgPRF->Draw("same");
cvs->cd(2);
hf = (TH1*) hf->DrawClone("p");
hf->GetXaxis()->SetRangeUser(rangex, rangeX);
hf->GetYaxis()->SetRangeUser(-10, 20);
//hf->SetTitle(Form("%d row[%d] col[%2d] an[%+d] m[%+4.2f] s[%4.2f] E[%7.2f] chi2[%7.2f]", ic, row, col, ia, fgPRF->GetParameter(1), fgPRF->GetParameter(2), fgPRF->Integral(xlo, xhi), fgPRF->GetChisquare()/fgPRF->GetNDF()));
// hf->GetXaxis()->SetRangeUser(xlo-0.25, xhi+0.25);
// //hf->GetYaxis()->SetRangeUser(0., 4500);
fgT->Draw("pl");
cvs->Modified();
cvs->Update();
cvs->SaveAs(Form("cl_%02d_A%d.gif", ic, ia));
}
Int_t nofHits = fHits->GetEntriesFast();
CbmTrdHit* hit = new ((*fHits)[nofHits])
CbmTrdHit(fModAddress,
global,
globalErr,
0., // sxy chi,
ic,
e, // energy
CbmTrdDigi::Clk(CbmTrdDigi::kFASP) * (t0 + time) - tdrift + 30.29,
edt);
hit->SetClassType();
hit->SetMaxType(tM);
if (ovf) hit->SetOverFlow();
if (CWRITE()) cout << hit->ToString();
return hit;
}
//_______________________________________________________________________________
Double_t CbmTrdModuleRecT::GetXoffset(Int_t n0) const {
Double_t dx(0.), R(0.);
for (Int_t ir(1); ir <= n0; ir++) {
if (vxe[ir] > 0) continue; // select rectangular coupling
R += vs[ir];
dx += vs[ir] * vx[ir];
}
if (TMath::Abs(R) > 0) return dx / R;
LOG(warn) << GetName() << "::GetDx : Unexpected null sum.";
return 0.;
}
//_______________________________________________________________________________
Double_t CbmTrdModuleRecT::GetYoffset(Int_t n0) const {
Double_t dy(0.), T(0.);
for (Int_t it(1); it <= n0; it++) {
if (vxe[it] > 0) { // select tilted coupling
T += vs[it];
dy += vs[it] * vx[it];
}
}
if (TMath::Abs(T) > 0) return dy / T;
LOG(warn) << GetName() << "::GetDy : Unexpected null sum.";
return 0.;
}
//_______________________________________________________________________________
Int_t CbmTrdModuleRecT::LoadDigis(vector<const CbmTrdDigi*>* digis,
vector<CbmTrdDigi*>* vdgM,
vector<Bool_t>* vmask,
ULong64_t& t0,
Int_t& cM) {
/* Load digis information in working vectors.
* The digis as provided by the digitizer are replaced by the merged one
* according to the vmask map. Digis are represented in the normal coordinate system of
* (pad width [pw], DAQ time [clk], signal [ADC chs]) with rectangular signals at integer
* positions.
*/
vs.clear();
vse.clear();
vx.clear();
vxe.clear();
vt.clear();
cM = 0; // relative position of maximum signal
Int_t n0(0), // number of measured signals
ovf(1), // over-flow flag for at least one of the digis
dt;
Char_t ddt, // signal time offset wrt prompt
dt0(0); // cluster time offset wrt arbitrary t0
Double_t r, re(100.), // rect signal
t, te(100.), // tilt signal
err, // final error parametrization for signal
xc(-0.5), // running signal-pad position
max(0.); // max signal
Int_t j(0), col0(-1), col1(0);
const CbmTrdDigi* dg(NULL);
vector<CbmTrdDigi*>::iterator idgM = vdgM->begin();
for (vector<const CbmTrdDigi*>::iterator i = digis->begin();
i != digis->end();
i++, j++) {
dg = (*i);
if ((*vmask)[j]) {
dg = (*idgM);
idgM++;
}
if (CWRITE()) cout << dg->ToString();
r = dg->GetCharge(t, dt);
if (t0 == 0)
t0 = dg->GetTimeDAQ(); // set arbitrary t0 to avoid double digis loop
if (col0 < 0) GetPadRowCol(dg->GetAddressChannel(), col0); // initialilze
ddt = dg->GetTimeDAQ() - t0;
if (ddt < dt0) dt0 = ddt;
// check column wise organization
GetPadRowCol(dg->GetAddressChannel(), col1);
if (col0 + j != col1) {
LOG(error) << GetName()
<< "::LoadDigis : digis in cluster not in increasing order !";
return 0;
}
// process tilt signal
if (t > 0) {
err = te;
if (t > 4094) {
ovf = -1;
err = 150.;
}
t -= CbmTrdFASP::GetBaselineCorr();
n0++;
if (t > max) {
max = t;
cM = j;
}
} else
err = 300.;
vt.push_back(ddt);
vs.push_back(t);
vse.push_back(err);
vx.push_back(xc);
vxe.push_back(0.035);
xc += 0.5;
// process rect signal
ddt += dt;
if (ddt < dt0) dt0 = ddt;
if (r > 0) {
err = re;
if (r > 4094) {
ovf = -1;
err = 150.;
}
r -= CbmTrdFASP::GetBaselineCorr();
n0++;
if (r > max) {
max = r;
cM = j;
}
} else
err = 300.;
vt.push_back(ddt);
vs.push_back(r);
vse.push_back(err);
vx.push_back(xc);
vxe.push_back(0.);
xc += 0.5;
}
// remove merged digis if they were created
if (idgM != vdgM->end())
LOG(warn) << GetName()
<< "::LoadDigis : not all merged digis have been consumed !";
for (idgM = vdgM->begin(); idgM != vdgM->end(); idgM++)
delete (*idgM);
// add front and back anchor points if needed
if (TMath::Abs(vs[0]) > 1.e-3) {
xc = vx[0];
ddt = vt[0];
vs.insert(vs.begin(), 0);
vse.insert(vse.begin(), 300);
vt.insert(vt.begin(), ddt);
vx.insert(vx.begin(), xc - 0.5);
vxe.insert(vxe.begin(), 0);
}
Int_t n(vs.size() - 1);
if (TMath::Abs(vs[n]) > 1.e-3) {
xc = vx[n] + 0.5;
ddt = vt[n];
vs.push_back(0);
vse.push_back(300);
vt.push_back(ddt);
vx.push_back(xc);
vxe.push_back(0.035);
}
// recenter time and space profile
t0 += dt0;
for (UInt_t idx(0); idx < vx.size(); idx++) {
vt[idx] -= dt0;
vx[idx] -= cM;
}
return ovf * n0;
}
//_______________________________________________________________________________
Bool_t CbmTrdModuleRecT::MergeDigis(vector<const CbmTrdDigi*>* digis,
vector<CbmTrdDigi*>* vdgM,
vector<Bool_t>* vmask) {
/* Merge digis in the cluster if their topology within it allows it although cuts in the
* digi merger procedure (CbmTrdFASP::WriteDigi()) were not fulfilled.
* Normally this are boundary signals with large time delays wrt neighbors
*/
CbmTrdDigi* dgM(NULL);
if (digis->size() < 2) { // sanity check ... just in case
LOG(warn) << GetName() << "::MergeDigis : Bad digi config for cluster :";
return kFALSE;
}
Double_t r, t;
Int_t colR, colT, dt, contor(0);
Bool_t kFOUND(0);
for (vector<const CbmTrdDigi*>::iterator idig = digis->begin(),
jdig = idig + 1;
jdig != digis->end();
idig++, jdig++, contor++) {
const CbmTrdDigi* dgT((*idig)); // tilt signal digi
const CbmTrdDigi* dgR((*jdig)); // rect signal digi
GetPadRowCol(dgR->GetAddressChannel(), colR);
GetPadRowCol(dgT->GetAddressChannel(), colT);
if (colR != colT) continue;
dgM = new CbmTrdDigi(*dgT);
r = dgR->GetCharge(t, dt);
dgT->GetCharge(t, dt);
dt = dgR->GetTimeDAQ() - dgT->GetTimeDAQ();
dgM->SetCharge(t, r, dt);
Int_t rtrg(dgR->GetTriggerType() & 2), ttrg(dgT->GetTriggerType() & 1);
dgM->SetTriggerType(rtrg | ttrg); //merge the triggers
if (CWRITE()) {
cout << "MERGE" << endl;
cout << dgT->ToString();
cout << dgR->ToString();
cout << "TO" << endl;
cout << dgM->ToString();
cout << "..." << endl;
}
kFOUND = 1;
vdgM->push_back(dgM);
(*vmask)[contor] = 1;
jdig = digis->erase(jdig);
if (jdig == digis->end()) break;
}
if (!kFOUND) {
LOG(warn) << GetName()
<< "::MergeDigis : Digi to pads matching failed for cluster :";
return kFALSE;
}
return kTRUE;
}
Float_t CbmTrdModuleRecT::fgCorrXdx = 0.005;
Float_t CbmTrdModuleRecT::fgCorrXval[2][NBINSCORRX] = {
{0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
0.000, 0.000, 0.000, -0.144, -0.091, -0.134, -0.185, -0.120, -0.115,
-0.125, -0.125, -0.124, -0.124, -0.122, -0.120, -0.119, -0.116, -0.114,
-0.113, -0.111, -0.109, -0.107, -0.105, -0.102, -0.100, -0.098, -0.097,
-0.093, -0.091, -0.089, -0.087, -0.084, -0.082, -0.079, -0.077, -0.074,
-0.072, -0.068, -0.065, -0.062, -0.059, -0.056, -0.053, -0.049, -0.046,
-0.043, -0.039, -0.036, -0.032, -0.029, -0.025, -0.022, -0.018, -0.015,
-0.011, -0.007, -0.003, 0.000, 0.003, 0.007, 0.011, 0.014, 0.018,
0.022, 0.025, 0.029, 0.032, 0.036, 0.039, 0.043, 0.046, 0.049,
0.053, 0.056, 0.059, 0.062, 0.065, 0.068, 0.071, 0.074, 0.077,
0.080, 0.082, 0.084, 0.087, 0.090, 0.091, 0.094, 0.096, 0.098,
0.100, 0.103, 0.104, 0.107, 0.108, 0.110, 0.113, 0.115, 0.116,
0.120, 0.121, 0.121, 0.123, 0.125, 0.124, 0.127, 0.140, 0.119,
0.114, 0.028, 0.049, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000},
{0.003, 0.013, 0.026, 0.039, 0.052, 0.065, 0.078, 0.091, 0.104,
0.118, 0.132, 0.145, 0.160, 0.174, 0.189, 0.203, 0.219, 0.234,
0.250, 0.267, 0.283, 0.301, 0.319, 0.338, 0.357, 0.375, 0.398,
0.419, 0.440, 0.464, 0.491, 0.514, 0.541, 0.569, 0.598, 0.623,
0.660, 0.696, 0.728, 0.763, 0.804, 0.847, 0.888, 0.930, 0.988,
1.015, 1.076, 1.128, 1.167, 1.228, 1.297, 1.374, 1.443, 1.511,
1.564, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
0.000, -1.992, -1.884, -1.765, -1.703, -1.609, -1.572, -1.493, -1.426,
-1.356, -1.309, -1.243, -1.202, -1.109, -1.069, -1.026, -0.970, -0.933,
-0.881, -0.844, -0.803, -0.767, -0.721, -0.691, -0.659, -0.629, -0.596,
-0.569, -0.541, -0.514, -0.490, -0.466, -0.441, -0.419, -0.397, -0.377,
-0.357, -0.337, -0.319, -0.301, -0.283, -0.267, -0.250, -0.234, -0.218,
-0.203, -0.189, -0.174, -0.160, -0.145, -0.131, -0.119, -0.104, -0.091,
-0.078, -0.064, -0.052, -0.039, -0.026, -0.013, -0.002}};
Float_t CbmTrdModuleRecT::fgCorrYval[NBINSCORRY][2] = {{2.421729, 0.},
{1.537359, 0.483472},
{1.1752, 0.},
{1.154183, -0.090229}};
ClassImp(CbmTrdModuleRecT)