CbmTrdModuleSimR.cxx 87.41 KiB
/* Copyright (C) 2018-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Etienne Bechtel, Florian Uhlig [committer] */
// Includes from TRD
#include "CbmTrdModuleSimR.h"
#include "CbmTrdAddress.h"
#include "CbmTrdDigi.h"
#include "CbmTrdDigitizer.h"
#include "CbmTrdParModAsic.h"
#include "CbmTrdParModDigi.h"
#include "CbmTrdParSpadic.h"
#include "CbmTrdPoint.h"
#include "CbmTrdRadiator.h"
// Includes from CbmRoot
//#include "CbmDaqBuffer.h"
#include "CbmMatch.h"
// Includes from FairRoot
#include <Logger.h>
// Includes from Root
#include <TClonesArray.h>
#include <TGeoManager.h>
#include <TMath.h>
#include <TRandom3.h>
#include <TStopwatch.h>
#include <TVector3.h>
// Includes from C++
#include "CbmTrdRawToDigiR.h"
#include <fstream>
#include <iomanip>
#include <iostream>
#include <cmath>
//_________________________________________________________________________________
CbmTrdModuleSimR::CbmTrdModuleSimR(Int_t mod, Int_t ly, Int_t rot)
: CbmTrdModuleSim(mod, ly, rot)
, fSigma_noise_keV(0.2)
, fMinimumChargeTH(.5e-06)
, fCurrentTime(-1.)
, fAddress(-1.)
, fLastEventTime(-1)
, fEventTime(-1)
, fLastTime(-1)
, fCollectTime(2048)
, //in pulsed mode
fnClusterConst(0)
, fnScanRowConst(0)
,
fPulseSwitch(true)
, fPrintPulse(false)
, //only for debugging
fTimeShift(true)
, //for pulsed mode
fAddCrosstalk(true)
, //for pulsed mode
fClipping(true)
, //for pulsed mode
fepoints(0)
, fAdcNoise(2)
, fDistributionMode(4)
, fCrosstalkLevel(0.01)
,
nofElectrons(0)
, nofLatticeHits(0)
, nofPointsAboveThreshold(0)
,
fAnalogBuffer()
, fPulseBuffer()
, fMultiBuffer()
, fTimeBuffer()
, fShiftQA()
, fLinkQA()
, fMCQA()
, fMCBuffer()
{
FairRootManager* ioman = FairRootManager::Instance();
fTimeSlice = (CbmTimeSlice*) ioman->GetObject("TimeSlice.");
if (!fPulseSwitch && CbmTrdDigitizer::IsTimeBased()) fCollectTime = 200;
SetNameTitle(Form("TrdSimR%d", mod), "Simulator for rectangular read-out.");
/// Save old global file and folder pointer to avoid messing with FairRoot
TFile* oldFile = gFile;
TDirectory* oldDir = gDirectory;
TString dir = getenv("VMCWORKDIR");
TString filename = dir + "/parameters/trd/FeatureExtractionLookup.root";
TFile* f = new TFile(filename, "OPEN");
LOG_IF(fatal, !f->IsOpen()) << "parameter file " << filename << " does not exist!";
fDriftTime = f->Get<TH2D>("Drift");
LOG_IF(fatal, !fDriftTime) << "No histogram Drift founfd in file " << filename;
fDriftTime->SetDirectory(0);
f->Close();
/// Restore old global file and folder pointer to avoid messing with FairRoot
gFile = oldFile;
gDirectory = oldDir;
oldFile = nullptr;
delete oldFile;
if (fPulseSwitch) {
SetSpadicResponse(fCalibration, fTau);
SetPulsePars(fRecoMode);
}
}
//_______________________________________________________________________________
void CbmTrdModuleSimR::AddDigi(Int_t address, Double_t charge, Double_t /*chargeTR*/, Double_t time, Int_t trigger)
{
Double_t weighting = charge;
if (CbmTrdDigitizer::UseWeightedDist()) {
TVector3 padPos, padPosErr;
fDigiPar->GetPadPosition(address, padPos, padPosErr);
Double_t distance = sqrt(pow(fXYZ[0] - padPos[0], 2) + pow(fXYZ[1] - padPos[1], 2));
weighting = 1. / distance;
}
// std::map<Int_t, std::pair<CbmTrdDigi*, CbmMatch*> >::iterator it = fDigiMap.find(address);
// std::map<Int_t, std::pair<CbmTrdDigi*, CbmMatch*> >::iterator it;
Int_t col = CbmTrdAddress::GetColumnId(address);
Int_t row = CbmTrdAddress::GetRowId(address);
Int_t sec = CbmTrdAddress::GetSectorId(address);
Int_t ncols = fDigiPar->GetNofColumns();
Int_t channel(0);
for (Int_t isec(0); isec < sec; isec++)
channel += ncols * fDigiPar->GetNofRowsInSector(isec);
channel += ncols * row + col;
std::map<Int_t, std::pair<CbmTrdDigi*, CbmMatch*>>::iterator it = fDigiMap.find(address);
if (it == fDigiMap.end()) { // Pixel not yet in map -> Add new pixel
CbmMatch* digiMatch = new CbmMatch();
digiMatch->AddLink(CbmLink(weighting, fPointId, fEventId, fInputId));
AddNoise(charge);
CbmTrdDigi::eTriggerType triggertype = CbmTrdDigi::eTriggerType::kNTrg;
if (trigger == 1) triggertype = CbmTrdDigi::eTriggerType::kSelf;
if (trigger == 2) triggertype = CbmTrdDigi::eTriggerType::kNeighbor;
CbmTrdDigi* digi = new CbmTrdDigi(channel, fModAddress, charge * 1e6, ULong64_t(time), triggertype, 0);
digi->SetFlag(0, true);
if (fDigiPar->GetPadSizeY(sec) == 1.5) digi->SetErrorClass(1);
if (fDigiPar->GetPadSizeY(sec) == 4.) digi->SetErrorClass(2);
if (fDigiPar->GetPadSizeY(sec) == 6.75) digi->SetErrorClass(3);
if (fDigiPar->GetPadSizeY(sec) == 12.) digi->SetErrorClass(4);
fDigiMap[address] = std::make_pair(digi, digiMatch);
it = fDigiMap.find(address);
// it->second.first->SetAddressModule(fModAddress);//module); <- now handled in the digi contructor
}
else {
it->second.first->AddCharge(charge * 1e6);
it->second.second->AddLink(CbmLink(weighting, fPointId, fEventId, fInputId));
}
}
//_______________________________________________________________________________
void CbmTrdModuleSimR::ProcessBuffer(Int_t address)
{
std::vector<std::pair<CbmTrdDigi*, CbmMatch*>> analog = fAnalogBuffer[address];
std::vector<std::pair<CbmTrdDigi*, CbmMatch*>>::iterator it;
CbmTrdDigi* digi = analog.begin()->first;
CbmMatch* digiMatch = new CbmMatch();
//printf("CbmTrdModuleSimR::ProcessBuffer(%10d)=%3d\n", address, digi->GetAddressChannel());
// Int_t trigger = 0;
Float_t digicharge = 0;
// Float_t digiTRcharge=0;
for (it = analog.begin(); it != analog.end(); it++) {
digicharge += it->first->GetCharge();
digiMatch->AddLink(it->second->GetLink(0));
//printf(" add charge[%f] trigger[%d]\n", it->first->GetCharge(), it->first->GetTriggerType());
}
digi->SetCharge(digicharge);
digi->SetTriggerType(fAnalogBuffer[address][0].first->GetTriggerType());
// std::cout<<digicharge<<std::endl;
// if(analog.size()>1) for (it=analog.begin()+1 ; it != analog.end(); it++) if(it->first) delete it->first;
fDigiMap[address] = std::make_pair(digi, digiMatch);
fAnalogBuffer.erase(address);
}
//_______________________________________________________________________________
void CbmTrdModuleSimR::ProcessPulseBuffer(Int_t address, Bool_t FNcall, Bool_t MultiCall = false, Bool_t down = true,
Bool_t up = true)
{
std::map<Int_t, std::pair<std::vector<Double_t>, CbmMatch*>>::iterator iBuff = fPulseBuffer.find(address);
std::map<Int_t, Double_t>::iterator tBuff = fTimeBuffer.find(address);
if (iBuff == fPulseBuffer.end() || tBuff == fTimeBuffer.end()) return;
Int_t trigger = CheckTrigger(fPulseBuffer[address].first);
if (fPulseBuffer[address].first.size() < 32) { return; }
if (trigger == 0 && !FNcall) { return; }
if (trigger == 1 && FNcall) { FNcall = false; }
Int_t col = CbmTrdAddress::GetColumnId(address);
Int_t row = CbmTrdAddress::GetRowId(address);
Int_t sec = CbmTrdAddress::GetSectorId(address);
Int_t ncols = fDigiPar->GetNofColumns();
Int_t channel(0);
for (Int_t isec(0); isec < sec; isec++)
channel += ncols * fDigiPar->GetNofRowsInSector(isec);
channel += ncols * row + col;
CbmMatch* digiMatch = new CbmMatch();
std::vector<Int_t> temp;
for (size_t i = 0; i < fPulseBuffer[address].first.size(); i++) {
Int_t noise = AddNoiseADC();
Int_t cross = AddCrosstalk(address, i, sec, row, col, ncols);
fPulseBuffer[address].first[i] = fPulseBuffer[address].first[i] + noise + cross;
if (fPulseBuffer[address].first[i] <= fClipLevel && fPulseBuffer[address].first[i] >= -12.)
temp.push_back((Int_t) fPulseBuffer[address].first[i]);
if (fPulseBuffer[address].first[i] > fClipLevel) temp.push_back(fClipLevel - 1);
if (fPulseBuffer[address].first[i] < -12.) temp.push_back(-12.);
if (fDebug) fQA->Fill("Pulse", i, fPulseBuffer[address].first[i]);
if (fDebug) fQA->CreateHist("Pulse self", 32, -0.5, 31.5, 512, -12., 500.);
if (fDebug) fQA->CreateHist("Pulse FN", 32, -0.5, 31.5, 512, -12., 500.);
if (fDebug && trigger == 1) fQA->Fill("Pulse self", i, fPulseBuffer[address].first[i]);
if (fDebug && trigger == 0) fQA->Fill("Pulse FN", i, fPulseBuffer[address].first[i]);
}
Float_t shift = fMessageConverter->GetTimeShift(temp);
Float_t corr = fMinDrift; //correction of average sampling to clock difference and systematic average drift time
if (!CbmTrdDigitizer::IsTimeBased()) corr = CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC);
//correction for EB case is done later, due to the event time 0 and the unsigned data member for the time in the digi
if (fTimeSlice) {
if (fTimeBuffer[address] + corr - shift < fTimeSlice->GetStartTime()) {
delete digiMatch;
delete fPulseBuffer[address].second;
fPulseBuffer.erase(address);
fTimeBuffer.erase(address);
return;
}
}
CbmTrdDigi* digi = nullptr;
if (fTimeBuffer[address] + corr - shift > 0.)
digi = fMessageConverter->MakeDigi(temp, channel, fModAddress, fTimeBuffer[address] + corr - shift, true);
else
digi = fMessageConverter->MakeDigi(temp, channel, fModAddress, fTimeBuffer[address] + corr, true);
if (fDigiPar->GetPadSizeY(sec) == 1.5) digi->SetErrorClass(1);
if (fDigiPar->GetPadSizeY(sec) == 4.) digi->SetErrorClass(2);
if (fDigiPar->GetPadSizeY(sec) == 6.75) digi->SetErrorClass(3);
if (fDigiPar->GetPadSizeY(sec) == 12.) digi->SetErrorClass(4);
if (!CbmTrdDigitizer::IsTimeBased()) digi->SetFlag(1, true);
Int_t shiftcut = fShiftQA[address] * 10;
Float_t timeshift = shiftcut / 10.0;
if (temp[fMinBin] == fClipLevel - 1 && temp[fMaxBin] == fClipLevel - 1) digi->SetCharge(35.);
std::vector<CbmLink> links = fPulseBuffer[address].second->GetLinks();
Int_t Links = 0.;
for (UInt_t iLinks = 0; iLinks < links.size(); iLinks++) {
digiMatch->AddLink(links[iLinks]);
Links++;
}
if (fDebug) {
fQA->CreateHist("MC", 200, 0., 50.);
fQA->Fill("MC", fMCQA[address]);
fQA->CreateHist("rec shift", 63, -0.5, 62.5);
fQA->Fill("rec shift", shift);
fQA->CreateHist("T res", 70, -35, 35);
fQA->Fill("T res", shift - timeshift);
fQA->CreateHist("Time", 100, -50, 50);
fQA->Fill("Time", digi->GetTime() - fLinkQA[address][0]["Time"]);
fQA->CreateProfile("MAX ADC", 63, -0.5, 62.5, 512, -12., 500.);
fQA->FillProfile("MAX ADC", timeshift, temp[fMaxBin], fMCQA[address]);
fQA->CreateProfile("ASYM MAP", 512, -12., 500., 512, -12., 500.);
fQA->FillProfile("ASYM MAP", temp[fMinBin], temp[fMaxBin], timeshift);
if (trigger == 1 && MultiCall && digi->GetCharge() > 0.) fQA->Fill("Multi Quote", 1);
else
fQA->Fill("Multi Quote", 0);
if (trigger == 1 && !MultiCall) {
fQA->CreateHist("E self", 200, 0., 50.0);
fQA->Fill("E self", digi->GetCharge());
fQA->CreateHist("E res", 400., -1., 1.);
fQA->Fill("E res", digi->GetCharge() - fMCQA[address]);
fQA->CreateHist("E res rel", 400., -1., 1.);
fQA->Fill("E res rel", (digi->GetCharge() - fMCQA[address]) / fMCQA[address]);
fQA->CreateHist("Charge Max", 200, 0., 50.0, 512, -12., 500.);
fQA->Fill("Charge Max", fMessageConverter->GetCharge(temp, timeshift), temp[fMaxBin]);
fQA->CreateHist("Links Res Self", 400., -1., 1., 5, -0.5, 4.5);
fQA->Fill("Links Res Self", (digi->GetCharge() - fMCQA[address]) / fMCQA[address], digiMatch->GetNofLinks());
if (Links == 1) {
fQA->CreateProfile("1 Link Prof", 32, 0., 32.);
for (size_t i = 0; i < fPulseBuffer[address].first.size(); i++) {
fQA->FillProfile("1 Link Prof", i, temp[i]);
}
}
if (fLinkQA[address].size() == 2 && fLinkQA[address][1]["Event"] != fLinkQA[address][0]["Event"]) {
fQA->CreateHist("Links QA time", 400., -1., 1., 500, 0., 2000.);
fQA->Fill("Links QA time", (digi->GetCharge() - fMCQA[address]) / fMCQA[address],
fLinkQA[address][1]["Time"] - fLinkQA[address][0]["Time"]);
fQA->CreateProfile("2 Link Prof", 32, 0., 32., 100, 0., 2000.);
for (size_t i = 0; i < fPulseBuffer[address].first.size(); i++) {
fQA->FillProfile("2 Link Prof", i, fLinkQA[address][1]["Time"] - fLinkQA[address][0]["Time"], temp[i]);
}
}
if (Links == 2 && links[0].GetEntry() == links[1].GetEntry()) {
fQA->CreateHist("In Event Res", 400., -1., 1.);
fQA->Fill("In Event Res", (digi->GetCharge() - fMCQA[address]) / fMCQA[address]);
}
if (Links == 2 && links[0].GetEntry() != links[1].GetEntry()) {
fQA->CreateHist("Inter Event Res", 400., -1., 1.);
fQA->Fill("Inter Event Res", (digi->GetCharge() - fMCQA[address]) / fMCQA[address]);
}
}
else {
fQA->CreateHist("E FN", 200, 0., 10.0);
fQA->Fill("E FN", digi->GetCharge());
fQA->CreateHist("E FN max", 512, -12., 500.);
fQA->Fill("E FN max", temp[fMaxBin]);
fQA->CreateHist("E FN MC max", 512, -12., 500., 200, 0., 50.);
fQA->Fill("E FN MC max", temp[fMaxBin], fMCQA[address]);
fQA->CreateHist("E FN res", 400., -1., 1.);
fQA->Fill("E FN res", digi->GetCharge() - fMCQA[address]);
fQA->CreateHist("E FN rel", 400., -1., 1.);
fQA->Fill("E FN rel", (digi->GetCharge() - fMCQA[address]) / fMCQA[address]);
fQA->CreateHist("Links Res FN", 400., -1., 1., 5, -0.5, 4.5);
fQA->Fill("Links Res FN", digi->GetCharge() - fMCQA[address], digiMatch->GetNofLinks());
fQA->CreateProfile("1 Link Prof FN", 32, 0., 32.);
for (size_t i = 0; i < fPulseBuffer[address].first.size(); i++) {
fQA->FillProfile("1 Link Prof FN", i, temp[i]);
}
if (fLinkQA[address].size() == 2 && fLinkQA[address][1]["Event"] != fLinkQA[address][0]["Event"]) {
fQA->CreateHist("Links QA time FN", 400., -1., 1., 500, 0., 2000.);
fQA->Fill("Links QA time FN", (digi->GetCharge() - fMCQA[address]) / fMCQA[address],
fLinkQA[address][1]["Time"] - fLinkQA[address][0]["Time"]);
fQA->CreateProfile("2 Link Prof FN", 32, 0., 32., 100, 0., 2000.);
for (size_t i = 0; i < fPulseBuffer[address].first.size(); i++) {
fQA->FillProfile("2 Link Prof FN", i, fLinkQA[address][1]["Time"] - fLinkQA[address][0]["Time"], temp[i]);
}
}
}
fShiftQA.erase(address);
fMCQA.erase(address);
fLinkQA.erase(address);
}
// digi->SetAddressModule(fModAddress); Not required anymore, now handled in the digi c'tor
if (trigger == 1) { digi->SetTriggerType(CbmTrdDigi::eTriggerType::kSelf); }
if (trigger == 0 && FNcall) { digi->SetTriggerType(CbmTrdDigi::eTriggerType::kNeighbor); }
if (trigger == 1 && MultiCall) { digi->SetTriggerType(CbmTrdDigi::eTriggerType::kMulti); }
//digi->SetMatch(digiMatch);
if (fDebug) {
fQA->CreateHist("Links", 10, -0.5, 9.5);
fQA->Fill("Links", digiMatch->GetNofLinks());
}
if (!FNcall && fPrintPulse)
std::cout << "main call charge: " << digi->GetCharge() << " col : " << col
<< " lay : " << CbmTrdAddress::GetLayerId(address) << " trigger: " << trigger
<< " time: " << digi->GetTime() << std::endl;
if (FNcall && fPrintPulse)
std::cout << "FN call charge: " << digi->GetCharge() << " col : " << col
<< " lay : " << CbmTrdAddress::GetLayerId(address) << " trigger: " << trigger
<< " time: " << digi->GetTime() << std::endl;
// if(!FNcall && MultiCall) std::cout<<"main call charge: "<<digi->GetCharge()<<" col : " << col<<" lay : " << CbmTrdAddress::GetLayerId(address)<<" trigger: " << trigger<<" time: " << digi->GetTime()<<std::endl;
// if(FNcall && MultiCall) std::cout<<"FN call charge: "<<digi->GetCharge()<<" col : " << col<<" lay : " << CbmTrdAddress::GetLayerId(address)<< " trigger: " << trigger<<" time: " << digi->GetTime()<<std::endl;
fDigiMap[address] = std::make_pair(digi, digiMatch);
fPulseBuffer.erase(address);
if (!FNcall && !MultiCall && trigger == 1) {
if (down) {
Int_t FNaddress = 0;
if (col >= 1)
FNaddress = CbmTrdAddress::GetAddress(CbmTrdAddress::GetLayerId(address),
CbmTrdAddress::GetModuleId(fModAddress), sec, row, col - 1);
Double_t timediff = TMath::Abs(fTimeBuffer[address] - fTimeBuffer[FNaddress]);
if (FNaddress != 0 && timediff < CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC))
ProcessPulseBuffer(FNaddress, true, false, true, false);
}
if (up) {
Int_t FNaddress = 0;
if (col < (ncols - 1))
FNaddress = CbmTrdAddress::GetAddress(CbmTrdAddress::GetLayerId(address), CbmTrdAddress::GetModuleId(address),
sec, row, col + 1);
Double_t timediff = TMath::Abs(fTimeBuffer[address] - fTimeBuffer[FNaddress]);
if (FNaddress != 0 && timediff < CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC))
ProcessPulseBuffer(FNaddress, true, false, false, true);
}
}
if (!FNcall && MultiCall && trigger == 1) {
if (down) {
Int_t FNaddress = 0;
if (col >= 1)
FNaddress = CbmTrdAddress::GetAddress(CbmTrdAddress::GetLayerId(address),
CbmTrdAddress::GetModuleId(fModAddress), sec, row, col - 1);
// Double_t timediff = TMath::Abs(fTimeBuffer[address]-fTimeBuffer[FNaddress]);
if (FNaddress != 0) ProcessPulseBuffer(FNaddress, true, true, true, false);
}
if (up) {
Int_t FNaddress = 0;
if (col < (ncols - 1))
FNaddress = CbmTrdAddress::GetAddress(CbmTrdAddress::GetLayerId(address), CbmTrdAddress::GetModuleId(address),
sec, row, col + 1);
// Double_t timediff = TMath::Abs(fTimeBuffer[address]-fTimeBuffer[FNaddress]);
if (FNaddress != 0) ProcessPulseBuffer(FNaddress, true, true, false, true);
}
}
fTimeBuffer.erase(address);
}
//_______________________________________________________________________________
void CbmTrdModuleSimR::AddDigitoBuffer(Int_t address, Double_t charge, Double_t /*chargeTR*/, Double_t time,
Int_t trigger)
{
Double_t weighting = charge;
if (CbmTrdDigitizer::UseWeightedDist()) {
TVector3 padPos, padPosErr;
fDigiPar->GetPadPosition(address, padPos, padPosErr);
Double_t distance = sqrt(pow(fXYZ[0] - padPos[0], 2) + pow(fXYZ[1] - padPos[1], 2));
weighting = 1. / distance;
}
//compare times of the buffer content with the actual time and process the buffer if collecttime is over
Bool_t eventtime = false;
if (time > 0.000) eventtime = true;
if (eventtime) CheckTime(address);
AddNoise(charge);
//fill digis in the buffer
CbmMatch* digiMatch = new CbmMatch();
digiMatch->AddLink(CbmLink(weighting, fPointId, fEventId, fInputId));
Int_t col = CbmTrdAddress::GetColumnId(address);
Int_t row = CbmTrdAddress::GetRowId(address);
Int_t sec = CbmTrdAddress::GetSectorId(address);
Int_t ncols = fDigiPar->GetNofColumns();
Int_t channel(0);
for (Int_t isec(0); isec < sec; isec++)
channel += ncols * fDigiPar->GetNofRowsInSector(isec);
channel += ncols * row + col;
auto triggertype = CbmTrdDigi::eTriggerType::kNTrg;
if (trigger == 1) triggertype = CbmTrdDigi::eTriggerType::kSelf;
if (trigger == 2) triggertype = CbmTrdDigi::eTriggerType::kNeighbor;
// std::cout<<charge*1e6<<" "<<fTimeBuffer[address]/CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC)<<std::endl;
CbmTrdDigi* digi =
new CbmTrdDigi(channel, fModAddress, charge * 1e6,
ULong64_t(time / CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC)), triggertype, 0);
//digi->SetMatch(digiMatch);
// printf("CbmTrdModuleSimR::AddDigitoBuffer(%10d)=%3d [%d] col[%3d] row[%d] sec[%d]\n", address, channel, fModAddress, col, row, sec);
fAnalogBuffer[address].push_back(std::make_pair(digi, digiMatch));
fTimeBuffer[address] = fCurrentTime;
if (!eventtime) ProcessBuffer(address);
}
//_______________________________________________________________________________
void CbmTrdModuleSimR::AddDigitoPulseBuffer(Int_t address, Double_t reldrift, Double_t charge, Double_t /*chargeTR*/,
Double_t time, Int_t /*trigger*/, Int_t /*epoints*/, Int_t /*ipoint*/)
{
Double_t weighting = charge * fepoints;
if (CbmTrdDigitizer::UseWeightedDist()) {
TVector3 padPos, padPosErr;
fDigiPar->GetPadPosition(address, padPos, padPosErr);
Double_t distance = sqrt(pow(fXYZ[0] - padPos[0], 2) + pow(fXYZ[1] - padPos[1], 2));
weighting = 1. / distance;
}
// if(!CbmTrdDigitizer::IsTimeBased() && fPointId-fLastPoint!=0) {CheckBuffer(true);CleanUp(true);}
if (CbmTrdDigitizer::IsTimeBased() && reldrift == 0.) {
Bool_t gotMulti = CheckMulti(address, fPulseBuffer[address].first);
fMultiBuffer.erase(address);
if (gotMulti) fMCBuffer[address].clear();
}
if (CbmTrdDigitizer::IsTimeBased() && reldrift == 0.) CheckTime(address);
fMultiBuffer[address] = std::make_pair(fMultiBuffer[address].first + charge, 0.);
if (fMCBuffer[address].size() > 0) {
fMCBuffer[address][0].push_back(fPointId);
fMCBuffer[address][1].push_back(fEventId);
fMCBuffer[address][2].push_back(fInputId);
}
else
for (auto ini = 0; ini < 3; ini++) {
std::vector<Int_t> v;
fMCBuffer[address].push_back(v);
}
std::vector<Double_t> pulse;
if (fTimeBuffer[address] > 0) {
pulse = fPulseBuffer[address].first;
if (pulse.size() < 32) return;
AddToPulse(address, charge, reldrift, pulse);
Bool_t found = false;
for (Int_t links = 0; links < fPulseBuffer[address].second->GetNofLinks(); links++)
if (fPulseBuffer[address].second->GetLink(links).GetIndex() == fPointId) found = true;
if (!found) {
fPulseBuffer[address].second->AddLink(CbmLink(weighting, fPointId, fEventId, fInputId));
if (fDebug) {
std::map<TString, Int_t> LinkQA;
LinkQA["Event"] = fEventId;
LinkQA["Point"] = fPointId;
LinkQA["Time"] = fEventTime;
LinkQA["Charge"] = charge * 1e6 * fepoints;
LinkQA["PosX"] = fQAPosition[0];
LinkQA["PosY"] = fQAPosition[1];
fLinkQA[address].push_back(LinkQA);
}
}
}
else {
fMCBuffer[address].clear();
pulse = MakePulse(charge, pulse, address);
fPulseBuffer[address].first = pulse;
CbmMatch* digiMatch = new CbmMatch();
digiMatch->AddLink(CbmLink(weighting, fPointId, fEventId, fInputId));
if (fDebug) {
std::vector<std::map<TString, Int_t>> vecLink;
std::map<TString, Int_t> LinkQA;
LinkQA["Event"] = fEventId;
LinkQA["Point"] = fPointId;
LinkQA["Time"] = fEventTime;
LinkQA["Charge"] = charge * 1e6 * fepoints;
LinkQA["PosX"] = fQAPosition[0];
LinkQA["PosY"] = fQAPosition[1];
vecLink.push_back(LinkQA);
fLinkQA[address] = vecLink;
}
fPulseBuffer[address].second = digiMatch;
fTimeBuffer[address] = time;
}
// if(!CbmTrdDigitizer::IsTimeBased() && finish) {CheckBuffer(true);CleanUp(true);}
}
std::vector<Double_t> CbmTrdModuleSimR::MakePulse(Double_t charge, std::vector<Double_t> pulse, Int_t address)
{
Double_t sample[32];
for (Int_t i = 0; i < 32; i++)
sample[i] = 0;
// Double_t timeshift = gRandom->Uniform(0.,CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
Double_t timeshift =
((Int_t)(fCurrentTime * 10) % (Int_t)(CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC) * 10)) / 10.0;
if (fDebug) fQA->Fill("Shift", timeshift);
// Int_t shift=timeshift;
//fShiftQA[address]=shift;
fShiftQA[address] = timeshift;
for (Int_t i = 0; i < 32; i++) {
if (i < fPresamples) {
sample[i] = 0.;
continue;
}
if (fTimeShift)
sample[i] = fCalibration * charge * 1e6
* CalcResponse((i - fPresamples) * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC) + timeshift);
if (!fTimeShift)
sample[i] = fCalibration * charge * 1e6
* CalcResponse((i - fPresamples) * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
if (sample[i] > fClipLevel && fClipping) sample[i] = fClipLevel - 1; //clipping
}
for (Int_t i = 0; i < 32; i++) {
pulse.push_back(sample[i]);
}
AddCorrelatedNoise(pulse);
// if(fDebug && CheckTrigger(pulse) == 1) fMCQA[address]=charge*1e6;
if (fDebug) fMCQA[address] = charge * 1e6;
return pulse;
}
void CbmTrdModuleSimR::AddToPulse(Int_t address, Double_t charge, Double_t reldrift, std::vector<Double_t> pulse)
{
Int_t comptrigger = CheckTrigger(pulse);
std::vector<Double_t> temppulse;
for (Int_t i = 0; i < 32; i++)
temppulse.push_back(pulse[i]);
Double_t dt = fCurrentTime - fTimeBuffer[address];
Int_t startbin = (dt + reldrift) / CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC);
Double_t timeshift =
((Int_t)((dt + reldrift) * 10) % (Int_t)(CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC) * 10)) / 10.0;
if (startbin > 31 || dt < 0.) return;
if (fDebug) fMCQA[address] += charge * 1e6;
for (Int_t i = 0; i < 32; i++) {
if (i < fPresamples + startbin) {
pulse[i] = temppulse[i];
continue;
}
Int_t addtime = i - startbin - fPresamples;
pulse[i] += fCalibration * charge * 1e6
* CalcResponse(addtime * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC) + timeshift);
if (pulse[i] > fClipLevel && fClipping) pulse[i] = fClipLevel - 1; //clipping
}
// std::vector<Int_t> newpulse;
// for(Int_t i=0;i<32;i++){
// if(i < fPresamples) continue;
// if(fTimeShift){
// Int_t sample = fCalibration*charge*1e6*CalcResponse((i-fPresamples)*CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC)+timeshift);
// if(sample > fClipLevel && fClipping) sample=fClipLevel-1; //clipping
// newpulse.push_back(sample);
// }
// if(!fTimeShift){
// Int_t sample = fCalibration*charge*1e6*CalcResponse((i-fPresamples)*CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
// if(sample > fClipLevel && fClipping) sample=fClipLevel-1; //clipping
// newpulse.push_back(sample);
// }
// }
Int_t trigger = CheckTrigger(pulse);
if (comptrigger == 0 && trigger == 1) {
for (Int_t i = 0; i < 32; i++) {
if (i < fPresamples && startbin >= fPresamples) {
pulse[i] = temppulse[i + startbin - fPresamples];
continue;
}
if (i < fPresamples && startbin < fPresamples) {
pulse[i] = temppulse[i + startbin];
continue;
}
Int_t addtime = i - fPresamples;
Int_t shift = startbin + i;
if (fTimeShift) {
if (shift < 32)
pulse[i] = temppulse[shift]
+ fCalibration * charge * 1e6
* CalcResponse(addtime * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC) + timeshift);
else
pulse[i] = fCalibration * charge * 1e6
* CalcResponse(addtime * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC) + timeshift);
if (pulse[i] > fClipLevel && fClipping) pulse[i] = fClipLevel - 1; //clipping
}
if (!fTimeShift) {
if (shift < 32)
pulse[i] = temppulse[shift]
+ fCalibration * charge * 1e6
* CalcResponse(addtime * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
else
pulse[i] =
fCalibration * charge * 1e6 * CalcResponse(addtime * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
if (pulse[i] > fClipLevel && fClipping) pulse[i] = fClipLevel - 1; //clipping
}
}
fTimeBuffer[address] = fCurrentTime;
}
if (trigger == 2) { fMultiBuffer[address].second = fCurrentTime; }
fPulseBuffer[address].first = pulse;
}
Bool_t CbmTrdModuleSimR::CheckMulti(Int_t address, std::vector<Double_t> pulse)
{
Bool_t processed = false;
Int_t trigger = CheckTrigger(pulse);
if (trigger == 2) {
processed = true;
Int_t maincol = CbmTrdAddress::GetColumnId(address);
Int_t row = CbmTrdAddress::GetRowId(address);
Int_t sec = CbmTrdAddress::GetSectorId(address);
Int_t shift = GetMultiBin(pulse);
Int_t ncols = fDigiPar->GetNofColumns();
// Double_t timeshift = gRandom->Uniform(0.,CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
Double_t timeshift =
((Int_t)(fMultiBuffer[address].second * 10) % (Int_t)(CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC) * 10))
/ 10.0;
std::vector<Double_t> temppulse;
std::map<Int_t, std::vector<Double_t>> templow;
std::map<Int_t, std::vector<Double_t>> temphigh;
temppulse = pulse;
for (Int_t i = 0; i < 32; i++) {
if (fDebug) fQA->CreateHist("Multi self", 32, -0.5, 31.5, 512, -12., 500.);
if (fDebug) fQA->Fill("Multi self", i, pulse[i]);
if (i >= shift) pulse[i] = 0.;
}
fPulseBuffer[address].first = pulse;
// std::cout<<"multi time: " << fTimeBuffer[address]<<" col: "<<maincol<<std::endl;
// Double_t dt=TMath::Abs(fMultiBuffer[address].second - fTimeBuffer[address]);
Int_t col = maincol;
Int_t FNaddress = 0;
Double_t FNshift = 0;
std::vector<Double_t> FNpulse = fPulseBuffer[address].first;
if (col >= 1)
FNaddress = CbmTrdAddress::GetAddress(CbmTrdAddress::GetLayerId(address), CbmTrdAddress::GetModuleId(fModAddress),
sec, row, col - 1);
Int_t FNtrigger = 1;
while (FNtrigger == 1 && FNaddress != 0) {
if (col >= 1)
FNaddress = CbmTrdAddress::GetAddress(CbmTrdAddress::GetLayerId(address),
CbmTrdAddress::GetModuleId(fModAddress), sec, row, col - 1);
else
break;
col--;
FNpulse = fPulseBuffer[FNaddress].first;
templow[FNaddress] = FNpulse;
FNshift =
(fTimeBuffer[address] - fTimeBuffer[FNaddress]) / CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC) + shift;
for (Int_t i = 0; i < 32; i++) {
if (i >= FNshift) FNpulse[i] = 0.;
}
FNtrigger = CheckTrigger(FNpulse);
fPulseBuffer[FNaddress].first = FNpulse;
if (col == 0) break;
// std::cout<<"col: "<<col<<" "<< fTimeBuffer[FNaddress]<<" FNaddress: " << FNaddress<<" FNtrigger: "<< FNtrigger<<" samples: " << fPulseBuffer[FNaddress].first.size()<<" time: " << fTimeBuffer[FNaddress]<<std::endl;
}
col = maincol;
FNaddress = 0;
if (col < (ncols - 1))
FNaddress = CbmTrdAddress::GetAddress(CbmTrdAddress::GetLayerId(address), CbmTrdAddress::GetModuleId(fModAddress),
sec, row, col + 1);
FNtrigger = 1;
while (FNtrigger == 1 && FNaddress != 0) {
if (col < (ncols - 1))
FNaddress = CbmTrdAddress::GetAddress(CbmTrdAddress::GetLayerId(address),
CbmTrdAddress::GetModuleId(fModAddress), sec, row, col + 1);
else
break;
col++;
FNpulse = fPulseBuffer[FNaddress].first;
temphigh[FNaddress] = FNpulse;
FNshift =
(fTimeBuffer[address] - fTimeBuffer[FNaddress]) / CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC) + shift;
for (Int_t i = 0; i < 32; i++) {
if (i >= FNshift) FNpulse[i] = 0.;
}
FNtrigger = CheckTrigger(FNpulse);
fPulseBuffer[FNaddress].first = FNpulse;
if (col == ncols - 1) break;
}
ProcessPulseBuffer(address, false, true, true, true);
for (Int_t i = 0; i < 32; i++) {
if (i < fPresamples) {
pulse[i] = temppulse[shift + i - fPresamples];
continue;
}
if (shift + i - fPresamples < 32) {
if (fTimeShift)
pulse[i] =
temppulse[shift + i - fPresamples]
+ fCalibration * fMultiBuffer[address].first * 1e6
* CalcResponse((i - fPresamples) * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC) + timeshift);
if (!fTimeShift)
pulse[i] = temppulse[shift + i - fPresamples]
+ fCalibration * fMultiBuffer[address].first * 1e6
* CalcResponse((i - fPresamples) * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
}
else {
if (fTimeShift)
pulse[i] =
fCalibration * fMultiBuffer[address].first * 1e6
* CalcResponse((i - fPresamples) * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC) + timeshift);
if (!fTimeShift)
pulse[i] = fCalibration * fMultiBuffer[address].first * 1e6
* CalcResponse((i - fPresamples) * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
}
// if(shift+i < 32){
// if(fTimeShift) pulse[i]=temppulse[shift+i]+fCalibration*fMultiBuffer[address].first*1e6*CalcResponse(i*CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC)+timeshift);
// if(!fTimeShift) pulse[i]=temppulse[shift+i]+fCalibration*fMultiBuffer[address].first*1e6*CalcResponse(i*CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
// }
// else{
// if(fTimeShift) pulse[i]=fCalibration*fMultiBuffer[address].first*1e6*CalcResponse(i*CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC)+timeshift);
// if(!fTimeShift) pulse[i]=fCalibration*fMultiBuffer[address].first*1e6*CalcResponse(i*CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
// }
}
for (Int_t i = 0; i < 32; i++) {
if (fDebug) fQA->CreateHist("Multi self after", 32, -0.5, 31.5, 512, -12., 500.);
if (fDebug) fQA->Fill("Multi self after", i, pulse[i]);
}
fTimeBuffer[address] = fMultiBuffer[address].second;
fPulseBuffer[address].first = pulse;
if (col < ncols - 1)
FNaddress = CbmTrdAddress::GetAddress(CbmTrdAddress::GetLayerId(address), CbmTrdAddress::GetModuleId(fModAddress),
sec, row, col + 1);
FNtrigger = 1;
while (FNtrigger == 1 && FNaddress != 0) {
if (col < (ncols - 1))
FNaddress = CbmTrdAddress::GetAddress(CbmTrdAddress::GetLayerId(address),
CbmTrdAddress::GetModuleId(fModAddress), sec, row, col + 1);
else
break;
col++;
FNpulse = fPulseBuffer[FNaddress].first;
for (Int_t i = 0; i < 32; i++) {
if (i < fPresamples && temphigh[FNaddress].size() > 0.) {
pulse[i] = temphigh[FNaddress][shift + i - fPresamples];
continue;
}
if (fTimeShift) {
if ((size_t) shift + i - fPresamples < temphigh[FNaddress].size())
FNpulse[i] =
temphigh[FNaddress][shift + i - fPresamples]
+ fCalibration * fMultiBuffer[FNaddress].first * 1e6
* CalcResponse((i - fPresamples) * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC) + timeshift);
else
FNpulse[i] =
fCalibration * fMultiBuffer[FNaddress].first * 1e6
* CalcResponse((i - fPresamples) * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC) + timeshift);
if (FNpulse[i] > fClipLevel && fClipping) FNpulse[i] = fClipLevel - 1; //clipping
}
if (!fTimeShift) {
if ((size_t) shift + i - fPresamples < temphigh[FNaddress].size())
FNpulse[i] = temphigh[FNaddress][shift + i - fPresamples]
+ fCalibration * fMultiBuffer[FNaddress].first * 1e6
* CalcResponse((i - fPresamples) * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
else
FNpulse[i] = fCalibration * fMultiBuffer[FNaddress].first * 1e6
* CalcResponse((i - fPresamples) * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
if (FNpulse[i] > fClipLevel && fClipping) FNpulse[i] = fClipLevel - 1; //clipping
}
// if(fTimeShift){
// if(shift+i<32 && temphigh[FNaddress].size()>0) FNpulse[i]=temphigh[FNaddress][shift+i]+fCalibration*fMultiBuffer[FNaddress].first*1e6*CalcResponse(i*CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC)+timeshift);
// else FNpulse[i]=fCalibration*fMultiBuffer[FNaddress].first*1e6*CalcResponse(i*CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC)+timeshift);
// if(FNpulse[i] > fClipLevel && fClipping) FNpulse[i]=fClipLevel-1; //clipping
// }
// if(!fTimeShift){
// if(shift+i<32 && temphigh[FNaddress].size()>0) FNpulse[i]=temphigh[FNaddress][shift+i]+fCalibration*fMultiBuffer[FNaddress].first*1e6*CalcResponse(i*CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
// else FNpulse[i]=fCalibration*fMultiBuffer[FNaddress].first*1e6*CalcResponse(i*CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
// if(FNpulse[i] > fClipLevel && fClipping) FNpulse[i]=fClipLevel-1; //clipping
// }
}
fPulseBuffer[FNaddress].first = FNpulse;
CbmMatch* FNdigiMatch = new CbmMatch();
if (!fMCBuffer[FNaddress].empty())
for (UInt_t links = 0; links < fMCBuffer[FNaddress][0].size(); links++)
FNdigiMatch->AddLink(CbmLink(fMultiBuffer[FNaddress].first, fMCBuffer[FNaddress][0][links],
fMCBuffer[FNaddress][1][links], fMCBuffer[FNaddress][2][links]));
fPulseBuffer[FNaddress].second = FNdigiMatch;
if (fDebug) {
std::vector<std::map<TString, Int_t>> vecLink;
std::map<TString, Int_t> LinkQA;
LinkQA["Event"] = fEventId;
LinkQA["Point"] = fPointId;
LinkQA["Time"] = fEventTime;
LinkQA["Charge"] = fMultiBuffer[FNaddress].first * 1e6 * fepoints;
vecLink.push_back(LinkQA);
fLinkQA[FNaddress] = vecLink;
}
FNtrigger = CheckTrigger(FNpulse);
fTimeBuffer[FNaddress] = fMultiBuffer[address].second;
fMultiBuffer.erase(FNaddress);
if (col == ncols - 1) break;
}
if (col >= 1)
FNaddress = CbmTrdAddress::GetAddress(CbmTrdAddress::GetLayerId(address), CbmTrdAddress::GetModuleId(fModAddress),
sec, row, col - 1);
FNtrigger = 1;
while (FNtrigger == 1 && FNaddress != 0) {
if (col >= 1)
FNaddress = CbmTrdAddress::GetAddress(CbmTrdAddress::GetLayerId(address),
CbmTrdAddress::GetModuleId(fModAddress), sec, row, col - 1);
else
break;
col--;
FNpulse = fPulseBuffer[FNaddress].first;
for (Int_t i = 0; i < 32; i++) {
if (i < fPresamples && templow[FNaddress].size() > 0.) {
pulse[i] = templow[FNaddress][shift + i - fPresamples];
continue;
}
if (fTimeShift) {
if ((size_t) shift + i - fPresamples < templow[FNaddress].size())
FNpulse[i] =
templow[FNaddress][shift + i - fPresamples]
+ fCalibration * fMultiBuffer[FNaddress].first * 1e6
* CalcResponse((i - fPresamples) * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC) + timeshift);
else
FNpulse[i] =
fCalibration * fMultiBuffer[FNaddress].first * 1e6
* CalcResponse((i - fPresamples) * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC) + timeshift);
if (FNpulse[i] > fClipLevel && fClipping) FNpulse[i] = fClipLevel - 1; //clipping
}
if (!fTimeShift) {
if ((size_t) shift + i - fPresamples < templow[FNaddress].size())
FNpulse[i] = templow[FNaddress][shift + i - fPresamples]
+ fCalibration * fMultiBuffer[FNaddress].first * 1e6
* CalcResponse((i - fPresamples) * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
else
FNpulse[i] = fCalibration * fMultiBuffer[FNaddress].first * 1e6
* CalcResponse((i - fPresamples) * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
if (FNpulse[i] > fClipLevel && fClipping) FNpulse[i] = fClipLevel - 1; //clipping
}
}
fPulseBuffer[FNaddress].first = FNpulse;
CbmMatch* FNdigiMatch = new CbmMatch();
if (!fMCBuffer[FNaddress].empty())
for (UInt_t links = 0; links < fMCBuffer[FNaddress][0].size(); links++)
FNdigiMatch->AddLink(CbmLink(fMultiBuffer[FNaddress].first, fMCBuffer[FNaddress][0][links],
fMCBuffer[FNaddress][1][links], fMCBuffer[FNaddress][2][links]));
fPulseBuffer[FNaddress].second = FNdigiMatch;
if (fDebug) {
std::vector<std::map<TString, Int_t>> vecLink;
std::map<TString, Int_t> LinkQA;
LinkQA["Event"] = fEventId;
LinkQA["Point"] = fPointId;
LinkQA["Time"] = fEventTime;
LinkQA["Charge"] = fMultiBuffer[FNaddress].first * 1e6 * fepoints;
vecLink.push_back(LinkQA);
fLinkQA[FNaddress] = vecLink;
}
FNtrigger = CheckTrigger(FNpulse);
fTimeBuffer[FNaddress] = fMultiBuffer[address].second;
fMultiBuffer.erase(FNaddress);
if (col == 0) break;
}
CbmMatch* digiMatch = new CbmMatch();
if (!fMCBuffer[address].empty())
for (UInt_t links = 0; links < fMCBuffer[address][0].size(); links++)
digiMatch->AddLink(CbmLink(fMultiBuffer[address].first, fMCBuffer[address][0][links],
fMCBuffer[address][1][links], fMCBuffer[address][2][links]));
fPulseBuffer[address].second = digiMatch;
if (fDebug) {
std::vector<std::map<TString, Int_t>> vecLink;
std::map<TString, Int_t> LinkQA;
LinkQA["Event"] = fEventId;
LinkQA["Point"] = fPointId;
LinkQA["Time"] = fEventTime;
LinkQA["Charge"] = fMultiBuffer[address].first * 1e6 * fepoints;
vecLink.push_back(LinkQA);
fLinkQA[address] = vecLink;
}
}
return processed;
}
Int_t CbmTrdModuleSimR::CheckTrigger(std::vector<Double_t> pulse)
{
Int_t slope = 0;
Bool_t trigger = false;
Bool_t falling = false;
Bool_t multihit = false;
for (size_t i = 0; i < pulse.size(); i++) {
if (i < pulse.size() - 1) slope = pulse[i + 1] - pulse[i];
if (slope >= fTriggerSlope && !trigger) trigger = true;
if (slope < 0 && trigger) falling = true;
if (slope >= fTriggerSlope && trigger && falling && (Int_t) i > fMaxBin) multihit = true;
}
if (!trigger && !multihit) return 0;
if (trigger && !multihit) return 1;
if (trigger && multihit) return 2;
return 0;
}
Int_t CbmTrdModuleSimR::GetMultiBin(std::vector<Double_t> pulse)
{
Int_t slope = 0;
Int_t startbin = 0;
Bool_t trigger = false;
Bool_t falling = false;
for (size_t i = 0; i < pulse.size(); i++) {
if (i < 31) slope = pulse[i + 1] - pulse[i];
if (slope >= fTriggerSlope && !trigger) trigger = true;
if (slope < 0 && trigger) falling = true;
if (slope >= fTriggerSlope && trigger && falling && (Int_t) i > fMaxBin) startbin = i;
}
return startbin;
}
//_______________________________________________________________________________
Double_t CbmTrdModuleSimR::CalcPRF(Double_t x, Double_t W, Double_t h)
{
Float_t K3 = 0.525;
Double_t SqrtK3 = sqrt(K3);
return std::fabs(-1. / (2. * atan(SqrtK3))
* (atan(SqrtK3 * tanh(TMath::Pi() * (-2. + SqrtK3) * (W + 2. * x) / (8. * h)))
+ atan(SqrtK3 * tanh(TMath::Pi() * (-2. + SqrtK3) * (W - 2. * x) / (8. * h)))));
}
//_______________________________________________________________________________
Double_t CbmTrdModuleSimR::CalcResponse(Double_t t)
{
if (fShapingOrder == 1) return (t / fTau) * TMath::Exp(-(t / fTau));
else
return (t / fTau) * (t / fTau) * TMath::Exp(-(t / fTau));
}
//_______________________________________________________________________________
Bool_t CbmTrdModuleSimR::DistributeCharge(Double_t pointin[3], Double_t pointout[3], Double_t delta[3], Double_t pos[3],
Int_t ipoints)
{
if (fDistributionMode == 1) {
for (Int_t i = 0; i < 3; i++) {
pos[i] = pointin[i] + (0.01) * delta[i] + 0.95 * delta[i] / fepoints * ipoints;
}
}
if (fDistributionMode == 5) {
for (Int_t i = 0; i < 3; i++) {
pos[i] = pointin[i] + 0.5 * delta[i];
}
}
//in development
if (fDistributionMode == 2) {
Double_t lastpos[3] = {pointin[0], pointin[1], pointin[2]};
Double_t dist_gas = TMath::Sqrt(delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2]);
if (ipoints > 0)
for (Int_t i = 0; i < 3; i++)
lastpos[i] = pos[i];
Double_t roll = gRandom->Integer(100);
Double_t s = (GetStep(dist_gas, roll) / dist_gas) / 2;
if (TMath::Abs(lastpos[0] + s * delta[0]) > fDigiPar->GetSizeX()
|| TMath::Abs(lastpos[1] + s * delta[1]) > fDigiPar->GetSizeY() || (lastpos[2] + s * delta[2]) >= pointout[2]) {
for (Int_t i = 0; i < 3; i++) {
pos[i] = lastpos[i];
}
return true;
}
for (Int_t i = 0; i < 3; i++)
pos[i] = lastpos[i] + s * delta[i];
return true;
}
if (fDistributionMode == 3) {
for (Int_t i = 0; i < 3; i++) {
pos[i] = pointin[i] + (0.5 + ipoints) * delta[i];
}
}
return true;
}
//_______________________________________________________________________________
Bool_t CbmTrdModuleSimR::MakeDigi(CbmTrdPoint* point, Double_t time, Bool_t TR)
{
// if(!CbmTrdDigitizer::IsTimeBased()) fPulseSwitch = false;
if (fPulseSwitch && !fMessageConverter->GetSetter()) {
if (fDebug) fQA->CreateHist("Pulse", 32, -0.5, 31.5, 512, -12., 500.);
if (fDebug) fQA->CreateHist("Shift", 63, -0.5, 62.5);
if (fDebug) fQA->CreateHist("Multi Quote", 4, -0.5, 3.5);
// if(fDebug) fMessageConverter->SetDebug(true);
if (fDebug) fMessageConverter->SetQA(fQA);
std::vector<Int_t> recomask;
for (Int_t i = frecostart; i <= frecostop; i++)
recomask.push_back(i);
fMessageConverter->SetRecoMask(recomask);
fMessageConverter->SetCalibration(fCalibration);
fMessageConverter->SetShapingOrder(fShapingOrder);
fMessageConverter->SetTau(fTau);
fMessageConverter->SetPresamples(fPresamples);
fMessageConverter->SetMaxBin(fMaxBin);
fMessageConverter->SetMinBin(fMinBin);
//fMessageConverter->SetLookup(1);
TString dir = getenv("VMCWORKDIR");
TString filename = dir + "/parameters/trd/FeatureExtractionLookup.root";
// if(fDistributionMode == 1 && fepoints == 3) filename= dir + "/parameters/trd/Feature_mode1_3points.root";
// if(fDistributionMode == 1 && fepoints == 5) filename= dir + "/parameters/trd/Feature_mode1_5points.root";
// if(fDistributionMode == 4) filename= dir + "/parameters/trd/Feature_mode4.root";
fMessageConverter->SetReadFile(filename.Data());
fMessageConverter->Init();
fMessageConverter->SetSetter(true);
}
// calculate current physical time
fCurrentTime = time + point->GetTime(); //+ AddDrifttime(gRandom->Integer(240))*1000; //convert to ns;
fEventTime = time;
const Double_t nClusterPerCm = 1.0;
Double_t point_in[3] = {point->GetXIn(), point->GetYIn(), point->GetZIn()};
Double_t point_out[3] = {point->GetXOut(), point->GetYOut(), point->GetZOut()};
Double_t local_point_out[3]; // exit point coordinates in local module cs
Double_t local_point_in[3]; // entrace point coordinates in local module cs
gGeoManager->cd(GetPath());
gGeoManager->MasterToLocal(point_in, local_point_in);
gGeoManager->MasterToLocal(point_out, local_point_out);
SetPositionMC(local_point_out);
for (Int_t i = 0; i < 3; i++)
fQAPosition[i] = point_in[i];
for (Int_t i = 0; i < 3; i++)
fQAPos_out[i] = point_out[i];
//fCurrentTime -= 1e9 * (point_in[2] / 100)
// / 2.99e8; // subtract time of flight to the detector layer
// General processing on the MC point
Double_t ELoss(0.), ELossTR(0.), ELossdEdX(point->GetEnergyLoss());
if (fRadiator && TR) {
nofElectrons++;
if (
fRadiator->LatticeHit(
point)) { // electron has passed lattice grid (or frame material) befor reaching the gas volume -> TR-photons have been absorbed by the lattice grid
nofLatticeHits++;
}
else if (point_out[2] >= point_in[2]) { //electron has passed the radiator
TVector3 mom;
point->Momentum(mom);
ELossTR = fRadiator->GetTR(mom);
}
}
ELoss = ELossTR + ELossdEdX;
if (fDebug) fQA->CreateHist("E MC", 200, 0., 50.0);
if (fDebug) fQA->Fill("E MC", ELoss * 1e6);
if (ELoss > fMinimumChargeTH) nofPointsAboveThreshold++;
Double_t cluster_pos[3]; // cluster position in local module coordinate system
Double_t cluster_delta
[3]; // vector pointing in MC-track direction with length of one path slice within chamber volume to creat n cluster
Double_t trackLength = 0;
for (Int_t i = 0; i < 3; i++) {
cluster_delta[i] = (local_point_out[i] - local_point_in[i]);
trackLength += cluster_delta[i] * cluster_delta[i];
}
trackLength = TMath::Sqrt(trackLength);
Int_t nCluster =
trackLength / nClusterPerCm + 0.9; // Track length threshold of minimum 0.1cm track length in gas volume
if (fnClusterConst > 0) {
nCluster = fnClusterConst; // Set number of cluster to constant value
}
if (nCluster < 1) { return kFALSE; }
nCluster = 1;
for (Int_t i = 0; i < 3; i++) {
cluster_delta[i] /= Double_t(nCluster);
}
Double_t clusterELoss = ELoss / Double_t(nCluster);
Double_t clusterELossTR = ELossTR / Double_t(nCluster);
//to change the number of ionization points in the gas
Int_t epoints = fepoints;
if (fDistributionMode == 3) { epoints = nCluster; }
if (fDistributionMode == 5) { epoints = 1; }
//in development
std::vector<Double_t> vec;
std::pair<Int_t, std::vector<Double_t>> steps = std::make_pair(0, vec);
if (fDistributionMode == 4) {
Double_t dist_gas = TMath::Sqrt(cluster_delta[0] * cluster_delta[0] + cluster_delta[1] * cluster_delta[1]
+ cluster_delta[2] * cluster_delta[2]);
steps = (GetTotalSteps(local_point_in, local_point_out, dist_gas));
epoints = steps.first;
fepoints = steps.first;
if (fDebug) fQA->CreateHist("Ionization", 63, -0.5, 62.5);
if (fDebug) fQA->Fill("Ionization", steps.first);
if (fDebug) fQA->CreateHist("Dist Ionization", 63, -0.5, 62.5, 20, 0., 2.);
if (fDebug) fQA->Fill("Dist Ionization", steps.first, dist_gas);
}
if (epoints != 1) {
clusterELoss = ELoss / epoints;
clusterELossTR = ELossTR / epoints;
}
if (!fPulseSwitch) {
for (Int_t ipoints = 0; ipoints < epoints; ipoints++) {
Bool_t dist = DistributeCharge(local_point_in, local_point_out, cluster_delta, cluster_pos, ipoints);
if (!dist) break;
if (fDistributionMode == 4)
for (Int_t i = 0; i < 3; i++)
cluster_pos[i] = steps.second[i + ipoints * 3];
if (fDigiPar->GetSizeX() < std::fabs(cluster_pos[0]) || fDigiPar->GetSizeY() < std::fabs(cluster_pos[1])) {
printf("-> nC %i/%i x: %7.3f y: %7.3f \n", ipoints, nCluster - 1, cluster_pos[0], cluster_pos[1]);
for (Int_t i = 0; i < 3; i++)
printf(" (%i) | in: %7.3f + delta: %7.3f * cluster: %i/%i = "
"cluster_pos: %7.3f out: %7.3f g_in:%f g_out:%f\n",
i, local_point_in[i], cluster_delta[i], ipoints, (Int_t) nCluster, cluster_pos[i], local_point_out[i],
point_in[i], point_out[i]);
}
if (CbmTrdDigitizer::AddNoise()) {
Int_t noiserate = gRandom->Uniform(0, 3); //still in development
Double_t simtime = fCurrentTime;
for (Int_t ndigi = 0; ndigi < noiserate; ndigi++) {
NoiseTime(time);
// ScanPadPlane(cluster_pos, gRandom->Gaus(0, fSigma_noise_keV * 1.E-6), 0,epoints,ipoints);
}
fCurrentTime = simtime;
}
ScanPadPlane(cluster_pos, 0., clusterELoss, clusterELossTR, epoints, ipoints);
}
}
Double_t driftcomp = 10000;
Int_t start = -1;
Double_t Ionizations[epoints][3];
if (fPulseSwitch) {
for (Int_t ipoints = 0; ipoints < epoints; ipoints++) {
Bool_t dist = DistributeCharge(local_point_in, local_point_out, cluster_delta, cluster_pos, ipoints);
if (!dist) break;
if (fDistributionMode == 4)
for (Int_t i = 0; i < 3; i++)
cluster_pos[i] = steps.second[i + ipoints * 3];
for (Int_t i = 0; i < 3; i++)
Ionizations[ipoints][i] = cluster_pos[i];
if (fDigiPar->GetSizeX() < std::fabs(cluster_pos[0]) || fDigiPar->GetSizeY() < std::fabs(cluster_pos[1])) {
printf("-> nC %i/%i x: %7.3f y: %7.3f \n", ipoints, nCluster - 1, cluster_pos[0], cluster_pos[1]);
for (Int_t i = 0; i < 3; i++)
printf(" (%i) | in: %7.3f + delta: %7.3f * cluster: %i/%i = "
"cluster_pos: %7.3f out: %7.3f g_in:%f g_out:%f\n",
i, local_point_in[i], cluster_delta[i], ipoints, (Int_t) nCluster, cluster_pos[i], local_point_out[i],
point_in[i], point_out[i]);
}
fDigiPar->ProjectPositionToNextAnodeWire(cluster_pos);
Int_t relz = 239 - (cluster_pos[2] - local_point_in[2]) / 0.005;
if (relz > 239 || relz < 0) relz = 239;
Double_t Drift_x =
TMath::Abs(double(int(cluster_pos[0] * 1000000) % int(fDigiPar->GetAnodeWireSpacing() * 100)) / 100);
// std::cout<<" pos: " << Drift_x<< " " << int(cluster_pos[0]*100000)<< " " << int(fDigiPar->GetAnodeWireSpacing()*100)<<" " << (int(cluster_pos[0]*100000) % int(fDigiPar->GetAnodeWireSpacing()*100))<<std::endl;
if (TMath::Abs(AddDrifttime(Drift_x, cluster_pos[2])) < driftcomp
&& TMath::Abs(AddDrifttime(Drift_x, cluster_pos[2])) > 0.) {
driftcomp = TMath::Abs(AddDrifttime(Drift_x, cluster_pos[2]));
start = ipoints;
}
}
if (start == -1) return false;
for (Int_t i = 0; i < 3; i++)
cluster_pos[i] = Ionizations[start][i];
Int_t relz = 239 - (cluster_pos[2] - local_point_in[2]) / 0.005;
if (relz > 239 || relz < 0) relz = 239;
Double_t Drift_x =
TMath::Abs(double(int(cluster_pos[0] * 1000000) % int(fDigiPar->GetAnodeWireSpacing() * 100)) / 100);
Double_t reldrift = TMath::Abs(AddDrifttime(Drift_x, cluster_pos[2]) - driftcomp) * 1000;
fDriftStart = driftcomp * 1000;
fCurrentTime += fDriftStart;
if (reldrift < 250.) ScanPadPlane(cluster_pos, 0., clusterELoss, clusterELossTR, epoints, start);
if (fPrintPulse) std::cout << std::endl;
for (Int_t ipoints = 0; ipoints < epoints; ipoints++) {
if (ipoints == start) continue;
for (Int_t i = 0; i < 3; i++)
cluster_pos[i] = Ionizations[ipoints][i];
relz = 239 - (cluster_pos[2] - local_point_in[2]) / 0.005;
if (relz > 239 || relz < 0) relz = 239;
Drift_x = TMath::Abs(double(int(cluster_pos[0] * 1000000) % int(fDigiPar->GetAnodeWireSpacing() * 100)) / 100);
reldrift = TMath::Abs(AddDrifttime(Drift_x, cluster_pos[2]) - driftcomp) * 1000;
if (reldrift < 250.) ScanPadPlane(cluster_pos, reldrift, clusterELoss, clusterELossTR, epoints, ipoints);
if (fPrintPulse) std::cout << std::endl;
}
}
fLastEventTime = time;
fLastPoint = fPointId;
fLastEvent = fEventId;
fLastTime = fCurrentTime;
return true;
}
//_______________________________________________________________________________
void CbmTrdModuleSimR::ScanPadPlane(const Double_t* local_point, Double_t reldrift, Double_t clusterELoss,
Double_t clusterELossTR, Int_t epoints, Int_t ipoint)
{
Int_t sectorId(-1), columnId(-1), rowId(-1);
fDigiPar->GetPadInfo(local_point, sectorId, columnId, rowId);
if (sectorId < 0 && columnId < 0 && rowId < 0) { return; }
else {
for (Int_t i = 0; i < sectorId; i++) {
rowId += fDigiPar->GetNofRowsInSector(i); // local -> global row
}
// for (Int_t i = 0; i < 3; i++) fQAPosition[i]=local_point[i];
Double_t displacement_x(0), displacement_y(0); //mm
Double_t h = fDigiPar->GetAnodeWireToPadPlaneDistance();
Double_t W(fDigiPar->GetPadSizeX(sectorId)), H(fDigiPar->GetPadSizeY(sectorId));
fDigiPar->TransformToLocalPad(local_point, displacement_x, displacement_y);
Int_t maxRow(6);
if (fnScanRowConst > 0) maxRow = fnScanRowConst;
Int_t startRow(rowId - maxRow / 2);
Int_t secRow(-1), targCol(-1), targRow(-1), targSec(-1), address(-1), fnRow(fDigiPar->GetNofRows()),
fnCol(fDigiPar->GetNofColumns());
for (Int_t iRow = startRow; iRow <= rowId + maxRow / 2; iRow++) {
Int_t iCol = columnId;
if (((iCol >= 0) && (iCol <= fnCol - 1)) && ((iRow >= 0) && (iRow <= fnRow - 1))) { // real adress
targSec = fDigiPar->GetSector(iRow, secRow);
address = CbmTrdAddress::GetAddress(fLayerId, CbmTrdAddress::GetModuleId(fModAddress), targSec, secRow, iCol);
}
else {
targRow = iRow;
targCol = iCol;
if (iCol < 0) { targCol = 0; }
else if (iCol > fnCol - 1) {
targCol = fnCol - 1;
}
if (iRow < 0) { targRow = 0; }
else if (iRow > fnRow - 1) {
targRow = fnRow - 1;
}
targSec = fDigiPar->GetSector(targRow, secRow);
address =
CbmTrdAddress::GetAddress(fLayerId, CbmTrdAddress::GetModuleId(fModAddress), targSec, secRow, targCol);
}
Bool_t print = false;
//distribute the mc charge fraction over the channels wit the PRF
Float_t chargeFraction = 0;
Float_t ch = 0;
Float_t tr = 0;
// std::cout<<" prf half: " << CalcPRF(0 * W , W, h)<<std::endl;
// std::cout<<" prf half -1 : " << CalcPRF(-1 * W , W, h)<<std::endl;
// std::cout<<" prf half +1: " << CalcPRF(1 * W , W, h)<<std::endl;
chargeFraction =
CalcPRF((iCol - columnId) * W - displacement_x, W, h) * CalcPRF((iRow - rowId) * H - displacement_y, H, h);
ch = chargeFraction * clusterELoss;
tr = chargeFraction * clusterELossTR;
Bool_t lowerend = false;
Bool_t upperend = false;
Int_t collow = 1;
Int_t colhigh = 1;
if (fDebug) fQA->CreateHist("E self MC", 200, 0., 50.0);
if (fDebug) fQA->CreateHist("E FN MC", 200, 0., 10.0);
if (ch >= (fMinimumChargeTH / epoints)) {
if (!CbmTrdDigitizer::IsTimeBased() && !fPulseSwitch && !print)
AddDigi(address, ch, tr, fCurrentTime, Int_t(1));
if (!CbmTrdDigitizer::IsTimeBased() && !fPulseSwitch && print) {
AddDigi(address, ch, tr, fCurrentTime, Int_t(1));
std::cout << " time: " << fCurrentTime << " col: " << iCol << " row: " << iRow - rowId
<< " secrow: " << secRow << " charge: " << ch * 1e6 << " 1 " << std::endl;
}
if (CbmTrdDigitizer::IsTimeBased() && !fPulseSwitch) AddDigitoBuffer(address, ch, tr, fCurrentTime, Int_t(1));
if (fPulseSwitch) {
if (fDebug) fQA->Fill("E self MC", ch * epoints * 1e6);
AddDigitoPulseBuffer(address, reldrift, ch, tr, fCurrentTime, Int_t(1), epoints, ipoint);
}
if (fPulseSwitch && print) {
AddDigitoPulseBuffer(address, reldrift, ch, tr, fCurrentTime, Int_t(1), epoints, ipoint);
std::cout << " time: " << fCurrentTime << " col: " << iCol << " row: " << iRow - rowId
<< " secrow: " << secRow << " charge: " << ch * 1e6 << " 1 " << std::endl;
}
while (!lowerend) {
if ((((iCol - collow) >= 0) && ((iCol - collow) <= fnCol - 1))
&& ((iRow >= 0) && (iRow <= fnRow - 1))) { // real adress
targSec = fDigiPar->GetSector(iRow, secRow);
address = CbmTrdAddress::GetAddress(fLayerId, CbmTrdAddress::GetModuleId(fModAddress), targSec, secRow,
iCol - collow);
}
else {
break;
}
chargeFraction = CalcPRF(((iCol - collow) - columnId) * W - displacement_x, W, h)
* CalcPRF((iRow - rowId) * H - displacement_y, H, h);
ch = chargeFraction * clusterELoss;
tr = chargeFraction * clusterELossTR;
if (ch >= (fMinimumChargeTH / epoints) && !CbmTrdDigitizer::IsTimeBased() && !fPulseSwitch && !print) {
AddDigi(address, ch, tr, fCurrentTime, Int_t(1));
collow++;
}
if (ch < (fMinimumChargeTH / epoints) && !CbmTrdDigitizer::IsTimeBased() && !fPulseSwitch && !print) {
AddDigi(address, ch, tr, fCurrentTime, Int_t(2));
lowerend = true;
}
if (ch >= (fMinimumChargeTH / epoints) && !CbmTrdDigitizer::IsTimeBased() && !fPulseSwitch && print) {
std::cout << " time: " << fCurrentTime << " col: " << iCol - collow << " row: " << iRow - rowId
<< " secrow: " << secRow << " charge: " << ch * 1e6 << " 1 " << std::endl;
AddDigi(address, ch, tr, fCurrentTime, Int_t(1));
collow++;
}
if (ch < (fMinimumChargeTH / epoints) && !CbmTrdDigitizer::IsTimeBased() && !fPulseSwitch && print) {
std::cout << " time: " << fCurrentTime << " col: " << iCol - collow << " row: " << iRow - rowId
<< " secrow: " << secRow << " charge: " << ch * 1e6 << " 0 " << std::endl;
AddDigi(address, ch, tr, fCurrentTime, Int_t(2));
lowerend = true;
}
if (ch >= (fMinimumChargeTH / epoints) && CbmTrdDigitizer::IsTimeBased() && !fPulseSwitch) {
AddDigitoBuffer(address, ch, tr, fCurrentTime, Int_t(1));
collow++;
}
if (ch < (fMinimumChargeTH / epoints) && CbmTrdDigitizer::IsTimeBased() && !fPulseSwitch) {
AddDigitoBuffer(address, ch, tr, fCurrentTime, Int_t(2));
lowerend = true;
}
if (ch >= (fMinimumChargeTH / epoints) && fPulseSwitch && !print) {
if (fDebug) fQA->Fill("E self MC", ch * epoints * 1e6);
AddDigitoPulseBuffer(address, reldrift, ch, tr, fCurrentTime, Int_t(1), epoints, ipoint);
collow++;
}
if (ch < (fMinimumChargeTH / epoints) && fPulseSwitch && !print) {
if (fDebug) fQA->Fill("E FN MC", ch * epoints * 1e6);
AddDigitoPulseBuffer(address, reldrift, ch, tr, fCurrentTime, Int_t(2), epoints, ipoint);
lowerend = true;
}
if (ch >= (fMinimumChargeTH / epoints) && fPulseSwitch && print) {
std::cout << " time: " << fCurrentTime << " col: " << iCol - collow << " row: " << iRow - rowId
<< " secrow: " << secRow << " charge: " << ch * 1e6 << " 1 " << std::endl;
AddDigitoPulseBuffer(address, reldrift, ch, tr, fCurrentTime, Int_t(1), epoints, ipoint);
collow++;
}
if (ch < (fMinimumChargeTH / epoints) && fPulseSwitch && print) {
std::cout << " time: " << fCurrentTime << " col: " << iCol - collow << " row: " << iRow - rowId
<< " secrow: " << secRow << " charge: " << ch * 1e6 << " 0 " << std::endl;
AddDigitoPulseBuffer(address, reldrift, ch, tr, fCurrentTime, Int_t(2), epoints, ipoint);
lowerend = true;
}
}
while (!upperend) {
if ((((iCol + colhigh) >= 0) && ((iCol + colhigh) <= fnCol - 1))
&& ((iRow >= 0) && (iRow <= fnRow - 1))) { // real adress
targSec = fDigiPar->GetSector(iRow, secRow);
address = CbmTrdAddress::GetAddress(fLayerId, CbmTrdAddress::GetModuleId(fModAddress), targSec, secRow,
iCol + colhigh);
}
else {
break;
}
chargeFraction = CalcPRF(((iCol + colhigh) - columnId) * W - displacement_x, W, h)
* CalcPRF((iRow - rowId) * H - displacement_y, H, h);
ch = chargeFraction * clusterELoss;
tr = chargeFraction * clusterELossTR;
if (ch >= (fMinimumChargeTH / epoints) && !CbmTrdDigitizer::IsTimeBased() && !fPulseSwitch && !print) {
AddDigi(address, ch, tr, fCurrentTime, Int_t(1));
colhigh++;
}
if (ch < (fMinimumChargeTH / epoints) && !CbmTrdDigitizer::IsTimeBased() && !fPulseSwitch && !print) {
AddDigi(address, ch, tr, fCurrentTime, Int_t(2));
upperend = true;
}
if (ch >= (fMinimumChargeTH / epoints) && !CbmTrdDigitizer::IsTimeBased() && !fPulseSwitch && print) {
std::cout << " time: " << fCurrentTime << " col: " << iCol + colhigh << " row: " << iRow - rowId
<< " secrow: " << secRow << " charge: " << ch * 1e6 << " 1 " << std::endl;
AddDigi(address, ch, tr, fCurrentTime, Int_t(1));
colhigh++;
}
if (ch < (fMinimumChargeTH / epoints) && !CbmTrdDigitizer::IsTimeBased() && !fPulseSwitch && print) {
std::cout << " time: " << fCurrentTime << " col: " << iCol + colhigh << " row: " << iRow - rowId
<< " secrow: " << secRow << " charge: " << ch * 1e6 << " 0 " << std::endl;
AddDigi(address, ch, tr, fCurrentTime, Int_t(2));
upperend = true;
}
if (ch >= (fMinimumChargeTH / epoints) && CbmTrdDigitizer::IsTimeBased() && !fPulseSwitch) {
AddDigitoBuffer(address, ch, tr, fCurrentTime, Int_t(1));
colhigh++;
}
if (ch < (fMinimumChargeTH / epoints) && CbmTrdDigitizer::IsTimeBased() && !fPulseSwitch) {
AddDigitoBuffer(address, ch, tr, fCurrentTime, Int_t(2));
upperend = true;
}
if (ch >= (fMinimumChargeTH / epoints) && fPulseSwitch && !print) {
if (fDebug) fQA->Fill("E self MC", ch * epoints * 1e6);
AddDigitoPulseBuffer(address, reldrift, ch, tr, fCurrentTime, Int_t(1), epoints, ipoint);
colhigh++;
}
if (ch < (fMinimumChargeTH / epoints) && fPulseSwitch && !print) {
if (fDebug) fQA->Fill("E FN MC", ch * epoints * 1e6);
if (ipoint == epoints - 1 && epoints > 1)
AddDigitoPulseBuffer(address, reldrift, ch, tr, fCurrentTime, Int_t(2), epoints, ipoint);
if (ipoint != epoints - 1 && epoints > 1)
AddDigitoPulseBuffer(address, reldrift, ch, tr, fCurrentTime, Int_t(2), epoints, ipoint);
if (epoints == 1) AddDigitoPulseBuffer(address, reldrift, ch, tr, fCurrentTime, Int_t(2), epoints, ipoint);
upperend = true;
}
if (ch >= (fMinimumChargeTH / epoints) && fPulseSwitch && print) {
std::cout << " time: " << fCurrentTime << " col: " << iCol + colhigh << " row: " << iRow - rowId
<< " secrow: " << secRow << " charge: " << ch * 1e6 << " 1 " << std::endl;
AddDigitoPulseBuffer(address, reldrift, ch, tr, fCurrentTime, Int_t(1), epoints, ipoint);
colhigh++;
}
if (ch < (fMinimumChargeTH / epoints) && fPulseSwitch && print) {
std::cout << " time: " << fCurrentTime << " col: " << iCol + colhigh << " row: " << iRow - rowId
<< " secrow: " << secRow << " charge: " << ch * 1e6 << " 0 " << std::endl;
if (ipoint == epoints - 1 && epoints > 1)
AddDigitoPulseBuffer(address, reldrift, ch, tr, fCurrentTime, Int_t(2), epoints, ipoint);
if (ipoint != epoints - 1 && epoints > 1)
AddDigitoPulseBuffer(address, reldrift, ch, tr, fCurrentTime, Int_t(2), epoints, ipoint);
if (epoints == 1) AddDigitoPulseBuffer(address, reldrift, ch, tr, fCurrentTime, Int_t(2), epoints, ipoint);
upperend = true;
}
}
if (print) std::cout << std::endl;
} //if charge > trigger
} //for rows
}
}
//_______________________________________________________________________________
void CbmTrdModuleSimR::SetAsicPar(CbmTrdParModAsic* /*p*/)
{
/** Build local set of ASICs and perform initialization. Need a proper fDigiPar already defined.
*/
if (!fDigiPar) {
LOG(warn) << GetName() << "::SetAsicPar : No Digi params for module " << fModAddress
<< ". Try calling first CbmTrdModSim::SetDigiPar.";
return;
}
if (fAsicPar) {
LOG(warn) << GetName() << "::SetAsicPar : The list for module " << fModAddress << " already initialized.";
return;
}
fAsicPar = new CbmTrdParModAsic();
CbmTrdParSpadic* asic(NULL);
Int_t iFebGroup = 0; // 1; 2; // normal, super, ultimate
Int_t gRow[3] = {2, 2, 2}; // re-ordering on the feb -> same mapping for normal and super
Int_t gCol[3] = {16, 8, 4}; // re-ordering on the feb -> same mapping for normal and super
Double_t xAsic = 0; // x position of Asic
Double_t yAsic = 0; // y position of Asic
Int_t rowId(0), isecId(0), irowId(0), iAsic(0);
for (Int_t s = 0; s < fDigiPar->GetNofSectors(); s++) {
for (Int_t r = 0; r < fDigiPar->GetNofRowsInSector(s); r++) {
for (Int_t c = 0; c < fDigiPar->GetNofColumnsInSector(s); c++) {
// ultimate density 6 rows, 5 pads
// super density 4 rows, 8 pads
// normal density 2 rows, 16 pads
if ((rowId % gRow[iFebGroup]) == 0) {
if ((c % gCol[iFebGroup]) == 0) {
xAsic = c + gCol[iFebGroup] / 2.;
yAsic = r + gRow[iFebGroup] / 2.;
Double_t local_point[3];
Double_t padsizex = fDigiPar->GetPadSizeX(s);
Double_t padsizey = fDigiPar->GetPadSizeY(s);
// calculate position in sector coordinate system
// with the origin in the lower left corner (looking upstream)
local_point[0] = ((Int_t)(xAsic + 0.5) * padsizex);
local_point[1] = ((Int_t)(yAsic + 0.5) * padsizey);
// calculate position in module coordinate system
// with the origin in the lower left corner (looking upstream)
local_point[0] += fDigiPar->GetSectorBeginX(s);
local_point[1] += fDigiPar->GetSectorBeginY(s);
// local_point[i] must be >= 0 at this point Double_t local_point[3];
Double_t fDx(GetDx()), fDy(GetDy());
asic = new CbmTrdParSpadic(iAsic, iFebGroup, local_point[0] - fDx, local_point[1] - fDy);
fAsicPar->SetAsicPar(asic);
if (local_point[0] > 2 * fDx) {
LOG(error) << "CbmTrdModuleSimR::SetAsicPar: asic position x=" << local_point[0]
<< " is out of bounds [0," << 2 * fDx << "]!";
fDigiPar->Print("all");
}
if (local_point[1] > 2 * fDy) {
LOG(error) << "CbmTrdModuleSimR::SetAsicPar: asic position y=" << local_point[1]
<< " is out of bounds [0," << 2 * fDy << "]!";
fDigiPar->Print("all");
}
for (Int_t ir = rowId; ir < rowId + gRow[iFebGroup]; ir++) {
for (Int_t ic = c; ic < c + gCol[iFebGroup]; ic++) {
if (ir >= fDigiPar->GetNofRows())
LOG(error) << "CbmTrdModuleSimR::SetAsicPar: ir " << ir << " is out of bounds!";
if (ic >= fDigiPar->GetNofColumns())
LOG(error) << "CbmTrdModuleSimR::SetAsicPar: ic " << ic << " is out of bounds!";
isecId = fDigiPar->GetSector((Int_t) ir, irowId);
asic->SetChannelAddress(
CbmTrdAddress::GetAddress(fLayerId, CbmTrdAddress::GetModuleId(fModAddress), isecId, irowId, ic));
//s, ir, ic));//new
if (false)
printf(" M:%10i(%4i) s: %i irowId: %4i ic: "
"%4i r: %4i c: %4i address:%10i\n",
fModAddress, CbmTrdAddress::GetModuleId(fModAddress), isecId, irowId, ic, r, c,
CbmTrdAddress::GetAddress(fLayerId, fModAddress, isecId, irowId, ic));
}
}
iAsic++; // next Asic
}
}
}
rowId++;
}
}
// Self Test
for (Int_t s = 0; s < fDigiPar->GetNofSectors(); s++) {
const Int_t nRow = fDigiPar->GetNofRowsInSector(s);
const Int_t nCol = fDigiPar->GetNofColumnsInSector(s);
for (Int_t r = 0; r < nRow; r++) {
for (Int_t c = 0; c < nCol; c++) {
Int_t channelAddress = CbmTrdAddress::GetAddress(fLayerId, CbmTrdAddress::GetModuleId(fModAddress), s, r, c);
if (fAsicPar->GetAsicAddress(channelAddress) == -1)
LOG(error) << "CbmTrdModuleSimR::SetAsicPar: Channel address:" << channelAddress
<< " is not or multible initialized in module " << fModAddress
<< "(ID:" << CbmTrdAddress::GetModuleId(fModAddress) << ")"
<< "(s:" << s << ", r:" << r << ", c:" << c << ")";
}
}
}
}
//_______________________________________________________________________________
void CbmTrdModuleSimR::SetNoiseLevel(Double_t sigma_keV) { fSigma_noise_keV = sigma_keV; }
//_______________________________________________________________________________
void CbmTrdModuleSimR::SetDistributionPoints(Int_t points) { fepoints = points; }
//_______________________________________________________________________________
void CbmTrdModuleSimR::SetSpadicResponse(Double_t calibration, Double_t tau)
{
fCalibration = calibration;
fTau = tau;
Double_t sum = 0;
for (auto i = frecostart; i <= frecostop; i++)
sum += fCalibration * CalcResponse(i * CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC));
fEReco = sum;
}
//_______________________________________________________________________________
void CbmTrdModuleSimR::SetPulsePars(Int_t mode)
{
if (mode == 1) {
frecostart = 2;
frecostop = 8;
}
if (mode == 2) {
frecostart = 2;
frecostop = 6;
}
}
//_______________________________________________________________________________
void CbmTrdModuleSimR::SetPulseMode(Bool_t pulsed = true) { fPulseSwitch = pulsed; }
//_______________________________________________________________________________
void CbmTrdModuleSimR::SetPadPlaneScanArea(Int_t row)
{
if (row % 2 == 0) row += 1;
fnScanRowConst = row;
}
//_______________________________________________________________________________
Double_t CbmTrdModuleSimR::AddNoise(Double_t charge)
{
if (fSigma_noise_keV > 0.0 && CbmTrdDigitizer::AddNoise() && !fPulseSwitch) {
Double_t noise = gRandom->Gaus(0,
fSigma_noise_keV * 1e-6); // keV->GeV // add only once per digi and event noise !!!
charge += noise; // resulting charge can be < 0 -> possible problems with position reconstruction
return charge;
}
else
return 0.;
}
//_______________________________________________________________________________
Int_t CbmTrdModuleSimR::AddNoiseADC()
{
if (CbmTrdDigitizer::AddNoise() && fPulseSwitch) {
if (fAdcNoise == 0) return 0.;
Int_t noise = gRandom->Gaus(0, fAdcNoise);
return noise;
// return 0;
}
else
return 0.;
}
std::vector<Double_t> CbmTrdModuleSimR::AddCorrelatedNoise(std::vector<Double_t> pulse)
{
//dummy for now
return pulse;
// for(size_t i=0;i<pulse.size();i++){
// pulse[i] += TMath::Sin(i)*5;
// }
// return pulse;
}
//_______________________________________________________________________________
Int_t CbmTrdModuleSimR::AddCrosstalk(Double_t address, Int_t i, Int_t sec, Int_t row, Int_t col, Int_t ncols)
{
Double_t cross = 0.;
if (fAddCrosstalk && fPulseSwitch) {
Int_t FNaddress = 0;
if (col >= 1)
FNaddress = CbmTrdAddress::GetAddress(CbmTrdAddress::GetLayerId(address), CbmTrdAddress::GetModuleId(fModAddress),
sec, row, col - 1);
if (fPulseBuffer[FNaddress].first.size() >= (size_t) i + 1)
cross += fPulseBuffer[FNaddress].first[i] * fCrosstalkLevel;
FNaddress = 0;
if (col < (ncols - 1))
FNaddress = CbmTrdAddress::GetAddress(CbmTrdAddress::GetLayerId(address), CbmTrdAddress::GetModuleId(address),
sec, row, col + 1);
if (fPulseBuffer[FNaddress].first.size() >= (size_t) i + 1)
cross += fPulseBuffer[FNaddress].first[i] * fCrosstalkLevel;
}
return cross;
}
//_______________________________________________________________________________
void CbmTrdModuleSimR::CheckBuffer(Bool_t EB = false)
{
std::map<Int_t, Double_t>::iterator timeit;
std::vector<Int_t> toBeErased;
Bool_t done = false;
while (!done) {
done = true;
for (timeit = fTimeBuffer.begin(); timeit != fTimeBuffer.end(); timeit++) {
Int_t add = timeit->first;
if (fCurrentTime < fTimeBuffer[add]) continue;
Double_t dt = fCurrentTime - fTimeBuffer[add];
if ((dt < fCollectTime || dt == fCurrentTime) && !EB) continue;
// if(!fPulseSwitch) {ProcessBuffer(add);fTimeBuffer.erase(add);}
if (!fPulseSwitch) {
ProcessBuffer(add);
toBeErased.push_back(add);
}
if (fPulseSwitch) {
std::vector<Double_t> pulse;
pulse = fPulseBuffer[add].first;
if (CheckTrigger(pulse) == 1 && EB) {
ProcessPulseBuffer(add, false, false, true, true);
break;
}
if (CheckTrigger(pulse) == 1 && !EB) {
ProcessPulseBuffer(add, false, false, true, true);
done = false;
break;
}
if (fPrintPulse) std::cout << std::endl;
}
}
}
for (auto& address : toBeErased) {
fTimeBuffer.erase(address);
}
}
//_______________________________________________________________________________
Int_t CbmTrdModuleSimR::FlushBuffer(ULong64_t time)
{
Bool_t closeTS(kFALSE);
if (fTimeSlice && (time - fTimeSlice->GetEndTime()) > -1000.) closeTS = true;
// if(!CbmTrdDigitizer::IsTimeBased()) return 0;
//process channels before timeslice ending and release memory
// if(closeTS && CbmTrdDigitizer::IsTimeBased()){
if (closeTS || time == 0) {
std::map<Int_t, Double_t>::iterator timeit;
Bool_t done = false;
while (!done) {
done = true;
for (timeit = fTimeBuffer.begin(); timeit != fTimeBuffer.end(); timeit++) {
Int_t add = timeit->first;
if (!fPulseSwitch) { ProcessBuffer(add); }
if (fPulseSwitch) {
std::vector<Double_t> pulse;
pulse = fPulseBuffer[add].first;
if (CheckTrigger(pulse) == 1) {
ProcessPulseBuffer(add, false, false, true, true);
done = false;
break;
}
if (fPrintPulse) std::cout << std::endl;
}
}
}
std::map<Int_t, std::pair<std::vector<Double_t>, CbmMatch*>>::iterator itBuffer;
for (itBuffer = fPulseBuffer.begin(); itBuffer != fPulseBuffer.end(); itBuffer++) {
if (fPulseBuffer[itBuffer->first].second) delete fPulseBuffer[itBuffer->first].second;
}
fPulseBuffer.clear();
fTimeBuffer.clear();
fMultiBuffer.clear();
fMCBuffer.clear();
}
return 0;
}
//_______________________________________________________________________________
void CbmTrdModuleSimR::CleanUp(Bool_t EB = false)
{
std::map<Int_t, Double_t>::iterator timeit;
// clean up
std::vector<Int_t> erase_list;
if (fPulseSwitch) {
for (timeit = fTimeBuffer.begin(); timeit != fTimeBuffer.end(); timeit++) {
Int_t add = timeit->first;
Double_t dt = fCurrentTime - fTimeBuffer[add];
if (fTimeSlice) {
if (fTimeBuffer[add] < fTimeSlice->GetStartTime()) {
erase_list.push_back(add);
continue;
}
}
if ((dt < fCollectTime || dt == fCurrentTime) && !EB) continue;
erase_list.push_back(add);
}
}
// //release memory for all non-triggered channels after signal collection time
for (UInt_t i = 0; i < erase_list.size(); i++) {
if (fPulseBuffer[erase_list[i]].second) delete fPulseBuffer[erase_list[i]].second;
fPulseBuffer.erase(erase_list[i]);
fTimeBuffer.erase(erase_list[i]);
fMultiBuffer.erase(erase_list[i]);
fMCBuffer.erase(erase_list[i]);
}
}
//_______________________________________________________________________________
void CbmTrdModuleSimR::CheckTime(Int_t address)
{
//compare last entry in the actual channel with the current time
std::map<Int_t, Double_t>::iterator timeit;
Double_t dt = fCurrentTime - fTimeBuffer[address];
// std::cout<<" dt: " << dt<<std::endl;
Bool_t go = false;
if (fCurrentTime > fTimeBuffer[address] && dt > 0.0000000) {
if (dt > fCollectTime && dt != fCurrentTime && !fPulseSwitch) {
ProcessBuffer(address);
fTimeBuffer.erase(address);
go = true;
}
// if(dt>fCollectTime && dt!=fCurrentTime && fPulseSwitch) {ProcessPulseBuffer(address,false,false);std::cout<<" ------ " <<std::endl;go=true;}
if (dt > fCollectTime && dt != fCurrentTime && fPulseSwitch) {
//ProcessPulseBuffer(address,false,false,true,true);
go = true;
if (fPrintPulse) std::cout << std::endl;
}
}
if (go && fPulseSwitch) {
CheckBuffer(false);
CleanUp(false);
}
if (go && !fPulseSwitch) CheckBuffer();
}
//_______________________________________________________________________________
void CbmTrdModuleSimR::NoiseTime(ULong64_t eventTime) { fCurrentTime = gRandom->Uniform(fLastEventTime, eventTime); }
//_______________________________________________________________________________
Double_t CbmTrdModuleSimR::AddDrifttime(Double_t x, Double_t z)
{
if (fDebug) fQA->CreateHist("All drift", 300, 0., 300.);
if (fDebug) fQA->Fill("All drift", fDriftTime->GetBinContent(fDriftTime->FindBin(x, z)) * 1000);
return fDriftTime->GetBinContent(fDriftTime->FindBin(x, z));
}
//_______________________________________________________________________________
Double_t CbmTrdModuleSimR::AddDrifttime(Int_t x)
{
Double_t drifttime[241] = {
0.11829, 0.11689, 0.11549, 0.11409, 0.11268, 0.11128, 0.10988, 0.10847, 0.10707, 0.10567, 0.10427,
0.10287, 0.10146, 0.10006, 0.09866, 0.09726, 0.095859, 0.094459, 0.09306, 0.091661, 0.090262, 0.088865,
0.087467, 0.086072, 0.084677, 0.083283, 0.08189, 0.080499, 0.07911, 0.077722, 0.076337, 0.074954, 0.073574,
0.072197, 0.070824, 0.069455, 0.06809, 0.066731, 0.065379, 0.064035, 0.0627, 0.061376, 0.060063, 0.058764,
0.05748, 0.056214, 0.054967, 0.053743, 0.052544, 0.051374, 0.05024, 0.049149, 0.048106, 0.047119, 0.046195,
0.045345, 0.044583, 0.043925, 0.043403, 0.043043, 0.042872, 0.042932, 0.043291, 0.044029, 0.045101, 0.04658,
0.048452, 0.050507, 0.052293, 0.053458, 0.054021, 0.053378, 0.052139, 0.53458, 0.050477, 0.048788, 0.047383,
0.046341, 0.045631, 0.045178, 0.045022, 0.045112, 0.045395, 0.045833, 0.046402, 0.047084, 0.047865, 0.048726,
0.049651, 0.050629, 0.051654, 0.052718, 0.053816, 0.054944, 0.056098, 0.057274, 0.058469, 0.059682, 0.060909,
0.062149, 0.0634, 0.064661, 0.06593, 0.067207, 0.06849, 0.069778, 0.07107, 0.072367, 0.073666, 0.074968,
0.076272, 0.077577, 0.078883, 0.080189, 0.081495, 0.082801, 0.084104, 0.085407, 0.086707, 0.088004, 0.089297,
0.090585, 0.091867, 0.093142, 0.094408, 0.095664, 0.096907, 0.098134, 0.099336, 0.10051, 0.10164, 0.10273,
0.10375, 0.10468, 0.10548, 0.10611, 0.10649, 0.10655, 0.10608, 0.10566, 0.1072, 0.10799, 0.10875,
0.11103, 0.11491, 0.11819, 0.12051, 0.12211, 0.12339, 0.12449, 0.12556, 0.12663, 0.12771, 0.12881,
0.12995, 0.13111, 0.13229, 0.13348, 0.13468, 0.13589, 0.13711, 0.13834, 0.13957, 0.1408, 0.14204,
0.14328, 0.14452, 0.14576, 0.14701, 0.14825, 0.1495, 0.15075, 0.152, 0.15325, 0.1545, 0.15576,
0.15701, 0.15826, 0.15952, 0.16077, 0.16203, 0.16328, 0.16454, 0.16579, 0.16705, 0.1683, 0.16956,
0.17082, 0.17207, 0.17333, 0.17458, 0.17584, 0.1771, 0.17835, 0.17961, 0.18087, 0.18212, 0.18338,
0.18464, 0.18589, 0.18715, 0.18841, 0.18966, 0.19092, 0.19218, 0.19343, 0.19469, 0.19595, 0.19721,
0.19846, 0.19972, 0.20098, 0.20223, 0.20349, 0.20475, 0.20601, 0.20726, 0.20852, 0.20978, 0.21103,
0.21229, 0.21355, 0.2148, 0.21606, 0.21732, 0.21857, 0.21983, 0.22109, 0.22234, 0.2236, 0.22486,
0.22612, 0.22737, 0.22863, 0.22989, 0.23114, 0.2324, 0.23366, 0.23491, 0.23617, 0.2363};
// Int_t xindex=0;
return drifttime[Int_t(x)];
}
//_______________________________________________________________________________
Double_t CbmTrdModuleSimR::GetStep(Double_t dist, Int_t roll)
{
Double_t prob = 0.;
Int_t steps = 1000;
Double_t CalcGamma = 0.;
std::pair<Double_t, Double_t> bethe[12] = {
std::make_pair(1.5, 1.5), std::make_pair(2, 1.1), std::make_pair(3, 1.025), std::make_pair(4, 1),
std::make_pair(10, 1.1), std::make_pair(20, 1.2), std::make_pair(100, 1.5), std::make_pair(200, 1.6),
std::make_pair(300, 1.65), std::make_pair(400, 1.675), std::make_pair(500, 1.7), std::make_pair(1000, 1.725)};
for (Int_t n = 0; n < 12; n++) {
if (fGamma < bethe[0].first) {
CalcGamma = bethe[0].second;
break;
}
if (n == 11) {
CalcGamma = bethe[11].second;
break;
}
if (fGamma >= bethe[n].first && fGamma <= bethe[n + 1].first) {
Double_t dx = bethe[n + 1].first - bethe[n].first;
Double_t dy = bethe[n + 1].second - bethe[n].second;
Double_t slope = dy / dx;
CalcGamma = (fGamma - bethe[n].first) * slope + bethe[n].second;
break;
}
}
Double_t s = 0;
Double_t D = 1 / (20.5 * CalcGamma);
for (Int_t i = 1; i < steps; i++) {
s = (dist / steps) * i;
prob = (1 - TMath::Exp(-s / D)) * 100;
if (prob >= roll) return s;
}
return s;
}
std::pair<Int_t, std::vector<Double_t>> CbmTrdModuleSimR::GetTotalSteps(Double_t In[3], Double_t Out[3], Double_t dist)
{
Double_t prob = 0.;
Int_t steps = 1000;
Double_t CalcGamma = 0.;
Double_t roll = gRandom->Integer(100);
std::pair<Double_t, Double_t> bethe[12] = {
std::make_pair(1.5, 1.5), std::make_pair(2, 1.1), std::make_pair(3, 1.025), std::make_pair(4, 1),
std::make_pair(10, 1.1), std::make_pair(20, 1.2), std::make_pair(100, 1.5), std::make_pair(200, 1.6),
std::make_pair(300, 1.65), std::make_pair(400, 1.675), std::make_pair(500, 1.7), std::make_pair(1000, 1.725)};
for (Int_t n = 0; n < 12; n++) {
if (fGamma < bethe[0].first) {
CalcGamma = bethe[0].second;
break;
}
if (n == 11) {
CalcGamma = bethe[11].second;
break;
}
if (fGamma >= bethe[n].first && fGamma <= bethe[n + 1].first) {
Double_t dx = bethe[n + 1].first - bethe[n].first;
Double_t dy = bethe[n + 1].second - bethe[n].second;
Double_t slope = dy / dx;
CalcGamma = (fGamma - bethe[n].first) * slope + bethe[n].second;
break;
}
}
Double_t pos[3] = {In[0], In[1], In[2]};
Double_t lastpos[3] = {In[0], In[1], In[2]};
Int_t pointcount = 0;
std::vector<Double_t> posvec;
Double_t D = 1 / (20.5 * CalcGamma);
Double_t delta[3];
Double_t s = 0;
for (Int_t i = 0; i < 3; i++)
delta[i] = (Out[i] - In[i]);
roll = gRandom->Integer(100);
for (Int_t i = 1; i < steps; i++) {
s = (dist / steps) * i;
prob = (1 - TMath::Exp(-s / D)) * 100;
if (prob >= roll) {
Double_t move = 2 * (s / dist);
for (Int_t n = 0; n < 3; n++)
pos[n] = lastpos[n] + move * delta[n];
for (Int_t n = 0; n < 3; n++)
lastpos[n] = pos[n];
// Double_t r = TMath::Sqrt((In[0]-pos[0])*(In[0]-pos[0])+(In[1]-pos[1])*(In[1]-pos[1]));
if (TMath::Abs(pos[0]) < fDigiPar->GetSizeX() && TMath::Abs(pos[1]) < fDigiPar->GetSizeY() && (pos[2]) < Out[2]) {
posvec.push_back(pos[0]);
posvec.push_back(pos[1]);
posvec.push_back(pos[2]);
pointcount++;
i = 1;
roll = gRandom->Integer(100);
continue;
}
}
if (TMath::Abs(pos[0]) < fDigiPar->GetSizeX() && TMath::Abs(pos[1]) < fDigiPar->GetSizeY() && (pos[2]) < Out[2]) {
continue;
}
break;
}
return std::make_pair(pointcount, posvec);
}
ClassImp(CbmTrdModuleSimR)