11#include "TClonesArray.h"
12#include "TGeoManager.h"
15#include "FairLogger.h"
16#include "FairRunAna.h"
43 fNoiseCharge(nullptr),
56 for (
auto chanIt = fAnalogBuffer.begin(); chanIt != fAnalogBuffer.end();
58 for (
auto sigIt = (chanIt->second).begin(); sigIt != (chanIt->second).end();
70 return fThreshold + fDynRange / Double_t(fNofAdcChannels) *
71 ( Double_t(adcChannel) + 0.5 );
79 Double_t charge, Int_t index, Int_t entry,
83 assert( channel < fNofChannels );
86 LOG(debug3) << GetName() <<
": Receiving signal " << charge
87 <<
" in channel " << channel <<
" at time "
91 if ( fDeadChannels.count(channel) ) {
92 LOG(debug) << GetName() <<
": discarding signal in dead channel "
99 if ( fAnalogBuffer.find(channel) == fAnalogBuffer.end() ) {
102 fAnalogBuffer[channel].insert(signal);
103 LOG(debug4) << GetName() <<
": Activating channel " << channel;
110 Bool_t isMerged = kFALSE;
112 for (it = fAnalogBuffer[channel].begin();
113 it != fAnalogBuffer[channel].end(); it++) {
116 if ( TMath::Abs( (*it)->GetTime() - time ) < fDeadTime ) {
121 LOG(debug4) << GetName() <<
": channel " << channel
122 <<
", new signal at t = " << time
123 <<
" ns is merged with present signal at t = "
124 << (*it)->GetTime() <<
" ns";
125 (*it)->SetTime( TMath::Min( (*it)->GetTime(), time) );
126 (*it)->AddLink(charge, index, entry, file);
128 LOG(debug4) <<
" New signal: time " << (*it)->GetTime()
129 <<
", charge " << (*it)->GetCharge()
130 <<
", number of links " << (*it)->GetMatch().GetNofLinks();
138 if ( isMerged )
return;
144 fAnalogBuffer[channel].insert(signal);
145 LOG(debug4) << GetName() <<
": Adding signal at t = " << time
146 <<
" ns, charge " << charge <<
" in channel " << channel;
156 Double_t& timeLast) {
160 Double_t tFirst = -1.;
161 Double_t tLast = -1.;
162 Double_t tSignal = -1.;
165 for (
auto chanIt = fAnalogBuffer.begin();
166 chanIt != fAnalogBuffer.end(); chanIt++) {
169 for (
auto sigIt = (chanIt->second).begin();
170 sigIt != (chanIt->second).end(); sigIt++) {
172 tSignal = (*sigIt)->GetTime();
174 tFirst = tFirst < 0. ? tSignal : TMath::Min(tFirst, tSignal);
175 tLast = TMath::Max(tLast, tSignal);
181 nofSignals = nSignals;
192 if ( charge < fThreshold )
return -1;
193 Int_t adc = Int_t ( (charge - fThreshold) * Double_t(fNofAdcChannels)
195 return ( adc < fNofAdcChannels ? adc : fNofChannels - 1 );
202void BmnSsdModule::Digitize(UShort_t channel,
BmnSsdSignal* signal) {
205 assert ( channel < fNofChannels );
209 if ( charge < fThreshold )
return;
215 if ( charge > fDynRange ) adc = fNofAdcChannels - 1;
216 else adc = UShort_t( (charge - fThreshold) / fDynRange
217 * Double_t(fNofAdcChannels) );
220 Double_t deltaT = gRandom->Gaus(0., fTimeResolution);
221 Long64_t dTime = Long64_t(round(signal->
GetTime() + deltaT));
224 LOG(debug4) << GetName() <<
": charge " << signal->
GetCharge()
225 <<
", dyn. range " << fDynRange <<
", threshold "
226 << fThreshold <<
", # ADC channels "
228 LOG(debug3) << GetName() <<
": Sending message. Channel " << channel
229 <<
", time " << dTime <<
", adc " << adc;
237 LOG(fatal) << GetName() <<
": no digitiser task present!";
252 nHits += sensor->
FindHits(fClusters, hitArray, event, fDeadTime);
255 LOG(debug2) << GetName() <<
": Clusters " << fClusters.size()
270 Double_t nNoiseMean = fNoiseRate * fNofChannels * ( t2 - t1 );
273 Int_t nNoise = gRandom->Poisson(nNoiseMean);
276 for (Int_t iNoise = 0; iNoise < nNoise; iNoise++) {
279 Int_t channel = Int_t(gRandom->Uniform(Double_t(fNofChannels)));
280 Double_t time = gRandom->Uniform(t1, t2);
281 Double_t charge = fNoiseCharge->GetRandom();
285 AddSignal(channel, time, charge, -1, -1, -1);
299 Bool_t isValid = kTRUE;
300 if ( name.Length() != 16 ) isValid = kFALSE;
302 if ( ! name.BeginsWith(
"SSD") ) isValid = kFALSE;
303 if ( name[4] !=
'U' ) isValid = kFALSE;
304 if ( name[8] !=
'L' ) isValid = kFALSE;
305 if ( name[13] !=
'M' ) isValid = kFALSE;
308 LOG(fatal) <<
"GetAddressFromName: Not a valid module name "
313 Int_t unit = 10 * ( name[5] -
'0') + name[6] -
'0' - 1;
314 Int_t ladder = 10 * ( name[9] -
'0') + name[10] -
'0' - 1;
315 Int_t hLadder = ( name[11] ==
'U' ? 0 : 1);
316 Int_t
module = 10 * ( name[14] - '0') + name[15] - '0' - 1;
327 for (UShort_t channel = 0; channel < fNofChannels; channel++) {
328 multiset<BmnSsdSignal*, BmnSsdSignal::Before> mset;
329 fAnalogBuffer[channel] = mset;
338void BmnSsdModule::InitDaughters() {
341 assert( gGeoManager );
346 TGeoNode* moduleNode =
fNode->GetNode();
347 TString modulePath =
fNode->GetName();
349 for (Int_t iNode = 0; iNode < moduleNode->GetNdaughters(); iNode++) {
352 TString daughterName = moduleNode->GetDaughter(iNode)->GetName();
353 if ( daughterName.Contains(
"Sensor", TString::kIgnoreCase) ) {
356 TString daughterPath = modulePath +
"/" + daughterName;
357 TGeoPhysicalNode* sensorNode =
new TGeoPhysicalNode(daughterPath.Data());
391 Double_t timeLimit = readoutTime - 5. * fTimeResolution - fDeadTime;
394 map<UShort_t, sigset>::iterator chanIt;
395 for (chanIt = fAnalogBuffer.begin();
396 chanIt != fAnalogBuffer.end(); chanIt++) {
399 sigset::iterator sigIt = (chanIt->second).begin();
400 sigset::iterator oldIt = sigIt;
401 while ( sigIt != (chanIt->second).end() ) {
405 if ( readoutTime >= 0. && (*sigIt)->GetTime() > timeLimit )
break;
408 Digitize( chanIt->first, (*sigIt) );
417 (chanIt->second).erase(oldIt);
430 Int_t nAdc, Double_t timeResolution,
431 Double_t deadTime, Double_t noise,
432 Double_t zeroNoiseRate,
433 Double_t fracDeadChannels) {
436 assert( dynRange > 0. );
437 assert( threshold > 0. );
439 assert( timeResolution > 0. );
440 assert( deadTime >= 0. );
441 assert( noise >= 0. );
442 assert( zeroNoiseRate >= 0. );
443 assert( fracDeadChannels >= 0. && fracDeadChannels <= 1.);
449 if ( dType.BeginsWith(
"Dssd") ) {
454 fNofChannels = 2 * TMath::Max(nStripsF, nStripsB);
457 LOG(fatal) << GetName() <<
": No sensor connected!";
462 fDynRange = dynRange;
463 fThreshold = threshold;
464 fNofAdcChannels = nAdc;
465 fTimeResolution = timeResolution;
466 fDeadTime = deadTime;
468 fZeroNoiseRate = zeroNoiseRate;
471 fNoiseRate = 0.5 * fZeroNoiseRate
472 * TMath::Exp( -0.5 * fThreshold * fThreshold / (fNoise * fNoise) );
473 fNoiseCharge =
new TF1(
"Noise Charge",
"TMath::Gaus(x, [0], [1])",
474 threshold, 10. * noise);
475 fNoiseCharge->SetParameters(0., noise);
478 if ( fracDeadChannels > 0.) SetDeadChannels(fracDeadChannels);
491Int_t BmnSsdModule::SetDeadChannels(Double_t percentage) {
493 Double_t fraction = percentage;
496 if ( percentage < 0. ) {
497 LOG(WARNING) << GetName() <<
": illegal percentage of dead channels "
498 << percentage <<
", is set to 0.";
501 if ( percentage > 100. ) {
502 LOG(WARNING) << GetName() <<
": illegal percentage of dead channels "
503 << percentage <<
", is set to 100.";
508 fDeadChannels.clear();
511 UInt_t nOfDeadChannels = fraction * fNofChannels / 100;
516 if ( nOfDeadChannels < (fNofChannels / 2) ) {
517 while ( fDeadChannels.size() < nOfDeadChannels )
518 fDeadChannels.insert( Int_t( gRandom->Uniform(fNofChannels) ) );
525 for (Int_t channel = 0; channel < fNofChannels; channel++)
526 fDeadChannels.insert(channel);
527 while ( fDeadChannels.size() > nOfDeadChannels )
528 fDeadChannels.erase( Int_t ( gRandom->Uniform(fNofChannels) ) );
531 return fDeadChannels.size();
540 ss <<
"Module " << GetName() <<
": dynRange " << fDynRange
541 <<
"e, thresh. " << fThreshold <<
"e, nAdc " << fNofAdcChannels
542 <<
", time res. " << fTimeResolution <<
"ns, dead time "
543 << fDeadTime <<
"ns, noise " << fNoise <<
"e, zero noise rate "
544 << fZeroNoiseRate <<
"/ns, dead chan. " << fDeadChannels.size()
545 <<
" / " << fNofChannels;
Data class for SSD clusters.
Class characterising one event by a collection of links (indices) to data objects,...
Task class for simulating the detector response of the SSD.
void CreateDigi(Int_t address, UShort_t channel, Long64_t time, UShort_t adc, const BmnMatch &match)
Class representing an element of the SSD setup.
TGeoPhysicalNode * fNode
Pointer to geometry.
std::vector< BmnSsdElement * > fDaughters
Array of daughters.
Int_t GetNofDaughters() const
Int_t fAddress
Unique element address.
BmnSsdElement * GetDaughter(Int_t index) const
void SetMother(BmnSsdElement *mother)
Int_t ProcessAnalogBuffer(Double_t readoutTime)
void AddSignal(UShort_t channel, Double_t time, Double_t charge, Int_t index=0, Int_t entry=0, Int_t file=0)
std::string ToString() const
Int_t ChargeToAdc(Double_t charge)
static Int_t GetAddressFromName(TString name)
Get the address from the module name (static)
Int_t GenerateNoise(Double_t t1, Double_t t2)
Generate noise.
void SetParameters(Double_t dynRange, Double_t threshold, Int_t nAdc, Double_t timeResolution, Double_t deadTime, Double_t noise, Double_t zeroNoiseRate, Double_t fracDeadChannels=0.)
BmnSsdModule(UInt_t address=0, TGeoPhysicalNode *node=nullptr, BmnSsdElement *mother=nullptr)
Int_t FindHits(TClonesArray *hitArray, BmnEvent *event=NULL)
void BufferStatus(Int_t &nofSignals, Double_t &timeFirst, Double_t &timeLast)
Double_t AdcToCharge(UShort_t adcChannel)
Class describing double-sided silicon strip sensors.
virtual Int_t GetNofStrips(Int_t side) const =0
Number of strips on front and back side.
Class representing an instance of a sensor in the BMN-SSD.
virtual Int_t FindHits(std::vector< BmnSsdCluster * > &clusters, TClonesArray *hitArray, BmnEvent *event, Double_t dTime)=0
static BmnSsdSetup * Instance()
BmnSsdDigitize * GetDigitizer() const
BmnSsdSensor * AssignSensor(Int_t address, TGeoPhysicalNode *node=nullptr)
Data class for an analog signal in the SSD.
const BmnMatch & GetMatch() const
Double_t GetCharge() const
Int_t SetElementId(Int_t address, Int_t level, UInt_t newId)
Set the index of an element, leaving the other element levels untouched.
Int_t GetAddress(UInt_t unit=0, UInt_t ladder=0, UInt_t halfladder=0, UInt_t module=0, UInt_t sensor=0, UInt_t side=0, UInt_t version=kCurrentVersion)
Construct address.