#include <SimQieElectronics.h>
Inheritance diagram for SimQieElectronics:

Public Member Functions | |
| SimQieElectronics (VldContext context, TRandom *random=NULL) | |
| virtual | ~SimQieElectronics (void) |
| virtual void | Reset (const VldContext &newContext) |
| virtual void | ReadoutDetector (SimPmtList &fPmtList) |
| virtual void | Print (Option_t *option="") const |
| virtual void | Config (Registry &config) |
| virtual void | ReadoutPmt (SimPmt *pmt) |
| virtual Bool_t | DynodeTrigger (SimPmt *pmt) |
| virtual int | GenSimulatedADC (RawChannelId rcid, PlexPixelSpotId psid, double inCharge, int tdc) |
| void | SetupTables (void) |
| ClassDef (SimQieElectronics, 1) | |
Public Attributes | |
| SimQieClock | fClock |
| Double_t | fFlipPoint [9] |
| Double_t | fAdcDacSlope [8] |
| Double_t | fFlipLowAdc [8] |
| Double_t | fFlipHighAdc [8] |
| Int_t | fQieDoLookup |
| Double_t | fQieDacCharge |
| Double_t | fQieDacPerRangeZeroAdc |
| Double_t | fQiePedestalWidthAdc |
| Double_t | fQieAdcRms |
| Int_t | fQiePedestalDac |
| Int_t | fQieSparsifyThresh |
| Int_t | fDoLookupNonlinearity |
SimQIEElectronics
Simple implimentation of the QIEfront-end.
Assumes all channels identical. Assumes fast extraction mode. Assumes CNTRST happens at PPS, which is false.
Assumes real ND, not CalDet: no dynode trigger, no CalDet timing (a 0.01% timing correction), neither of which should be important.
Definition at line 26 of file SimQieElectronics.h.
| SimQieElectronics::SimQieElectronics | ( | VldContext | context, | |
| TRandom * | random = NULL | |||
| ) |
Definition at line 16 of file SimQieElectronics.cxx.
00017 : SimElectronics( context, random ), 00018 fClock(context), 00019 fQieDoLookup(1), 00020 fQieDacCharge(1.4*Munits::fC), 00021 fQieDacPerRangeZeroAdc(1.92), 00022 fQiePedestalWidthAdc(1.5), 00023 fQieAdcRms(0), 00024 fQiePedestalDac(50), 00025 fQieSparsifyThresh(70), 00026 fDoLookupNonlinearity(0) 00027 { 00028 SetupTables(); 00029 }
| virtual SimQieElectronics::~SimQieElectronics | ( | void | ) | [inline, virtual] |
| SimQieElectronics::ClassDef | ( | SimQieElectronics | , | |
| 1 | ||||
| ) |
| void SimQieElectronics::Config | ( | Registry & | config | ) | [virtual] |
Reimplemented from SimElectronics.
Definition at line 314 of file SimQieElectronics.cxx.
References fDoLookupNonlinearity, fQieAdcRms, fQieDacCharge, fQieDacPerRangeZeroAdc, fQieDoLookup, fQiePedestalDac, fQiePedestalWidthAdc, fQieSparsifyThresh, Registry::Get(), Msg::kWarning, MSG, and SetupTables().
00315 { 00316 // Modify the configuration. 00317 // 00318 // Use this method to set static members with the class configuration. 00319 config.Get("qieDoLookup",fQieDoLookup); 00320 config.Get("qieDacCharge",fQieDacCharge); 00321 config.Get("qieDacPerRangeZeroAdc",fQieDacPerRangeZeroAdc); 00322 config.Get("qiePedestalWidthAdc",fQiePedestalWidthAdc); 00323 config.Get("qieAdcRms",fQieAdcRms); 00324 config.Get("qiePedestalDac",fQiePedestalDac); 00325 config.Get("qieSparsifyThresh",fQieSparsifyThresh); 00326 config.Get("doLookupNonlinearity",fDoLookupNonlinearity); 00327 00328 if(fQieSparsifyThresh<fQiePedestalDac) 00329 MSG("DetSim",Msg::kWarning) << "WARNING: The QIE sparsification threshold " << std::endl 00330 << " is less than the digital offset!" << std::endl 00331 << " This turns off all sparsification!" << std::endl; 00332 00333 00334 SetupTables(); 00335 }
| Bool_t SimQieElectronics::DynodeTrigger | ( | SimPmt * | pmt | ) | [virtual] |
| int SimQieElectronics::GenSimulatedADC | ( | RawChannelId | rcid, | |
| PlexPixelSpotId | psid, | |||
| double | inCharge, | |||
| int | tdc | |||
| ) | [virtual] |
Reimplemented in SimQiePerfectElectronics.
Definition at line 209 of file SimQieElectronics.cxx.
References Calibrator::DecalLinearity(), fAdcDacSlope, Munits::fC, SimElectronics::fContext, fDoLookupNonlinearity, fFlipLowAdc, fFlipPoint, fQieAdcRms, fQieDacCharge, fQieDacPerRangeZeroAdc, fQieDoLookup, fQiePedestalDac, fQiePedestalWidthAdc, SimElectronics::fRandom, PlexHandle::GetStripEndId(), Calibrator::Instance(), PlexStripEndId::IsValid(), Msg::kVerbose, and MSG.
Referenced by ReadoutPmt().
00213 { 00214 // 00215 // This routine converts from a charge in fC to a 00216 // QIE digitized charge. Note that 'ADC' is an overloaded term here, 00217 // since these aren't ADC counts but rather lookup table values. 00218 // The units are actually DAC counts, which are 1.4 fC/ DAC. 00219 // 00220 00221 // Convert to DAC charge units. These are the units of charge 00222 // used by the sharge injection system. 00223 double true_dacs = inCharge / fQieDacCharge; 00224 00225 // Do nonlinearity curve. 00226 if (fDoLookupNonlinearity) { 00227 PlexHandle plex(fContext); 00228 PlexStripEndId seid = plex.GetStripEndId(psid); 00229 if(seid.IsValid()) 00230 true_dacs = Calibrator::Instance().DecalLinearity(true_dacs, seid); 00231 } 00232 00233 // Add some smear, by the pedestal RMS in DAC counts. 00234 double dacs = fRandom->Gaus(true_dacs, 00235 fQiePedestalWidthAdc * fQieDacPerRangeZeroAdc); 00236 00237 // Figure out what range you're in. 00238 // Find the range and pos within range. 00239 int range = 0; 00240 if (dacs < fFlipPoint[1]) range = 0; 00241 else if(dacs < fFlipPoint[2]) range = 1; 00242 else if(dacs < fFlipPoint[3]) range = 2; 00243 else if(dacs < fFlipPoint[4]) range = 3; 00244 else if(dacs < fFlipPoint[5]) range = 4; 00245 else if(dacs < fFlipPoint[6]) range = 5; 00246 else if(dacs < fFlipPoint[7]) range = 6; 00247 else range = 7; 00248 00249 00250 // Now find the ADC value. 00251 double adc = fFlipLowAdc[range] + fAdcDacSlope[range]*(dacs - fFlipPoint[range]); 00252 00253 // Smear by a constant resolution function. 00254 // i.e. if all values are wrong by 1.2 ADC counts rms, this does it. 00255 // This is set to zero by default because it is difficult to seperate 00256 // the charge injector error from the ADC conversion error. 00257 if(fQieAdcRms>0) 00258 adc = fRandom->Gaus(adc,fQieAdcRms); 00259 00260 // Make it an integer again. 00261 // Rounding is probably the most appropriate, given that we have correctly 00262 // calibrated the pedestals and whatnot. 00263 00264 if(adc>255) adc=255.; 00265 if(adc<0) adc=0.; 00266 double iadc = TMath::Nint(adc); 00267 00268 if(fQieDoLookup==0) { 00269 // We have turned off the lookup table, so we need to simply pack the output 00270 // word: 00271 int adc8bits = (int)iadc; 00272 int capid = tdc%4; // CapID rotates 0123 with the clock 00273 int dataword = (adc8bits & 0xFF) | (range << 8) | (capid << 11); 00274 return dataword; 00275 } 00276 00277 // Go back through the lookup table. 00278 double outdac = (iadc-fFlipLowAdc[range]) / fAdcDacSlope[range] + fFlipPoint[range]; 00279 00280 // Add the digital offset 00281 outdac += fQiePedestalDac; 00282 00283 // Round to a final value. 00284 // FIXME: Dave simply truncates this number in the lookup table, so I will too. 00285 // This may change. 00286 int final_dac = (int) ( floor(outdac) ); 00287 00288 if(final_dac < 0) final_dac = 0; // The floor of the lookup table. 00289 00290 if(final_dac > 0xffff) final_dac = 0xffff; // Final check to ensure it packs into a 16 bit word. 00291 MSG("DetSim",Msg::kVerbose) 00292 << "QIE: " << inCharge/Munits::fC << "fC -> " 00293 << " True DACs " << true_dacs 00294 << " Range: " << range 00295 << " ADC: " << adc 00296 << " -> DAC: " << final_dac << endl; 00297 return final_dac; 00298 }
| void SimQieElectronics::Print | ( | Option_t * | option = "" |
) | const [virtual] |
Reimplemented from SimElectronics.
Reimplemented in SimQiePerfectElectronics.
Definition at line 302 of file SimQieElectronics.cxx.
References Munits::fC, fDoLookupNonlinearity, fQieDacCharge, fQieDacPerRangeZeroAdc, fQieDoLookup, fQiePedestalDac, fQiePedestalWidthAdc, and fQieSparsifyThresh.
00303 { 00304 printf("SimQieElectronics: qieDoLookup %s\n",(fQieDoLookup)?("true"):("false")); 00305 printf(" qieDacCharge %.2f fC\n", fQieDacCharge/Munits::fC); 00306 printf(" qieDacPerRangeZeroAdc %.2f DACs\n",fQieDacPerRangeZeroAdc); 00307 printf(" qiePedestalWidthAdc %.2f Range-zero ADCs\n",fQiePedestalWidthAdc); 00308 printf(" qiePedestalDac %d DAC\n",fQiePedestalDac); 00309 printf(" qieSparsifyThresh %d DAC\n",fQieSparsifyThresh); 00310 printf(" doLookupNonlinearity %s \n",fDoLookupNonlinearity?("on"):("off") ); 00311 }
| void SimQieElectronics::ReadoutDetector | ( | SimPmtList & | fPmtList | ) | [virtual] |
Reimplemented from SimElectronics.
Definition at line 38 of file SimQieElectronics.cxx.
References SimElectronics::fContext, RawChannelId::GetElecType(), PlexHandle::GetRawChannelId(), ElecType::kQIE, and ReadoutPmt().
00039 { 00040 PlexHandle plex(fContext); 00041 SimPmtList::iterator it; 00042 for(it = pmtList.begin(); it!= pmtList.end(); it++) { 00043 SimPmt* pmt = it->second; 00044 if(pmt) { 00045 RawChannelId rcid = plex.GetRawChannelId(pmt->GetPixelSpotId(1)); 00046 // Make sure the PMT reads out to VA electronics: 00047 if ( (rcid.GetElecType()==ElecType::kQIE) ) { 00048 ReadoutPmt( pmt ); 00049 } 00050 } 00051 } 00052 00053 }
| void SimQieElectronics::ReadoutPmt | ( | SimPmt * | pmt | ) | [virtual] |
Definition at line 55 of file SimQieElectronics.cxx.
References SimElectronics::AddAdcsAfterFETrigger(), SimElectronics::AddAdcsAfterSpars(), SimElectronics::AddDigit(), SimElectronics::AddDigitsAfterFETrigger(), SimElectronics::AddDigitsAfterSpars(), SimElectronics::AddSignal(), SimDigit::AsString(), PlexPixelSpotId::AsString(), SimPmtBucketIterator::Bucket(), SimPmtBucketIterator::BucketId(), SimPixelTimeBucket::CreateSignal(), SimPmtBucketIterator::End(), Munits::fC, SimElectronics::fContext, fQieDacCharge, fQieSparsifyThresh, GenSimulatedADC(), SimDigit::GetADC(), SimPixelTimeBucket::GetCharge(), RawChannelId::GetEncoded(), SimPmt::GetNumberOfPixels(), SimPmtTimeBucket::GetPixelBucket(), SimPmt::GetPixelSpotId(), PlexHandle::GetRawChannelId(), SimPmt::GetTotalCharge(), SimPmt::GetTotalHitPixels(), SimPmt::GetTubeId(), SimPmt::GetType(), RawChannelId::IsNull(), Msg::kDebug, Msg::kError, Msg::kVerbose, DigiSignal::Merge(), MSG, SimPmtBucketIterator::Next(), and SimPmt::Print().
Referenced by ReadoutDetector().
00056 { 00057 // Reads out a single PMT. 00058 // Adds all readout to the list of SimDigits. 00059 00060 // This vaugely simulates the real ND, 00061 // which reads out all buckets from a channel before 00062 // moving to the next one. This is only incorrect in that 00063 // this uses pixel order instead of master/minder address order. 00064 // Shouldn't matter. 00065 00066 // Also, this assumes a fast extraction mode, such that no 00067 // hits are out of the readout window. For resonant extraction 00068 // or cosmics, you need to look for a dynode trigger, find latch the 00069 // dynode trigger time, and put a validity window around the dynode 00070 // trigger QIE tick. It's irrelevant for neutrino physics (at the moment) 00071 // so I'm ignoring it. --N 00072 00073 // This does NOT correctly deal with multiplexing! Must fix! 00074 00075 MSG("DetSim",Msg::kDebug) << "SimQieElectronics::ReadoutPmt " 00076 << pmt->GetTubeId().AsString() 00077 << " type " << pmt->GetType() 00078 << endl; 00079 00080 PlexHandle plex(fContext); 00081 00082 // No trigger, so add up all hits 00083 AddDigitsAfterFETrigger( pmt->GetTotalHitPixels(true) ); 00084 AddAdcsAfterFETrigger( pmt->GetTotalCharge() * fQieDacCharge ); 00085 00086 // Build a list of channels we can read out. 00087 std::map<UInt_t,std::vector<UInt_t> > channels; 00088 std::map<UInt_t,std::vector<UInt_t> >::iterator chItr; 00089 00090 for(int pixel = 1; pixel<= pmt->GetNumberOfPixels(); pixel++) { 00091 PlexPixelSpotId psid = pmt->GetPixelSpotId(pixel); 00092 RawChannelId rcid = plex.GetRawChannelId(psid); 00093 channels[rcid.GetEncoded()].push_back(pixel); 00094 } 00095 00096 // Loop through buckets. 00097 SimPmtBucketIterator bIt( *pmt ); 00098 for( ; !bIt.End(); bIt.Next() ) { 00099 00100 Int_t bucketID = bIt.BucketId(); 00101 SimPmtTimeBucket& bucket = bIt.Bucket(); 00102 00103 for( chItr = channels.begin(); chItr != channels.end(); chItr++) { 00104 Float_t totalCharge = 0; 00105 DigiSignal* totalSignal = new DigiSignal(); 00106 AddSignal(totalSignal); 00107 RawChannelId rcid(chItr->first); 00108 PlexPixelSpotId psid; 00109 00110 for(UInt_t ipix = 0; ipix < chItr->second.size(); ipix++) { 00111 Int_t pixel = chItr->second[ipix]; 00112 psid = pmt->GetPixelSpotId(pixel); 00113 SimPixelTimeBucket& pixBucket = bucket.GetPixelBucket(pixel); 00114 00115 DigiSignal* signal = pixBucket.CreateSignal(); 00116 Float_t charge = pixBucket.GetCharge(); 00117 00118 totalSignal->Merge(*signal); 00119 totalCharge+=charge; 00120 00121 delete signal; 00122 } 00123 00124 // Protect against invalid channels on tubes that have some valid pixels. 00125 if(!(rcid.IsNull())) { 00126 if((totalCharge<-1000*Munits::fC)||(totalCharge>1e6*Munits::fC)) { 00127 MSG("DetSim",Msg::kError) << "Abnormal charge " << totalCharge/Munits::fC 00128 << " fC in pmt " << pmt->GetTubeId().AsString() << endl; 00129 pmt->Print(); 00130 } 00131 SimDigit d( psid, // Pixel, or one of them 00132 rcid, // raw channel 00133 GenSimulatedADC( rcid, psid, totalCharge, bucketID ), // ADC 00134 bucketID, // The TDC _is_ the bucket ID. 00135 totalSignal, // Truth 00136 0 // Error bits. 00137 ); 00138 MSG("DetSim",Msg::kVerbose) << "SimQieElectronics::ReadoutPmt: " << d.AsString() << std::endl; 00139 00140 // Sparsify and record. 00141 if(d.GetADC() > fQieSparsifyThresh) { 00142 AddDigit(d); 00143 00144 // Stats: 00145 AddDigitsAfterSpars(1); 00146 AddAdcsAfterSpars(d.GetADC()); 00147 } 00148 } 00149 } 00150 } 00151 }
| void SimQieElectronics::Reset | ( | const VldContext & | newContext | ) | [virtual] |
Reimplemented from SimElectronics.
Definition at line 31 of file SimQieElectronics.cxx.
References fClock, SimElectronics::Reset(), and SimQieClock::Reset().
00032 { 00033 fClock.Reset(newContext); 00034 SimElectronics::Reset(newContext); 00035 }
| void SimQieElectronics::SetupTables | ( | void | ) |
Definition at line 162 of file SimQieElectronics.cxx.
References fAdcDacSlope, fFlipHighAdc, fFlipLowAdc, fFlipPoint, and fQieDacPerRangeZeroAdc.
Referenced by Config().
00163 { 00164 // These are the slopes (ADC/DAC) of each range. 00165 fAdcDacSlope[0] = 1./fQieDacPerRangeZeroAdc; // By definition. 00166 // Each higher range has double the gain of the last one. 00167 // These values could be improved still; I believe they are just approximate. 00168 fAdcDacSlope[1] = fAdcDacSlope[0]*0.5; 00169 fAdcDacSlope[2] = fAdcDacSlope[1]*0.5; 00170 fAdcDacSlope[3] = fAdcDacSlope[2]*0.5; 00171 fAdcDacSlope[4] = fAdcDacSlope[3]*0.5; 00172 fAdcDacSlope[5] = fAdcDacSlope[4]*0.5; 00173 fAdcDacSlope[6] = fAdcDacSlope[5]*0.5; 00174 fAdcDacSlope[7] = fAdcDacSlope[6]*0.5; 00175 00176 // These values are taken from a plot from Charlie Nelson. See 00177 // MENUswitchpoints.pdf in the doc directory. 00178 // These need not be terribly accurate, since they very from channel-to-channel 00179 // by 4 or 6 counts RMS. 00180 fFlipLowAdc[0] = 0; // Min 00181 fFlipLowAdc[1] = 23.7; 00182 fFlipLowAdc[2] = 25.6; 00183 fFlipLowAdc[3] = 26.5; 00184 fFlipLowAdc[4] = 27.1; 00185 fFlipLowAdc[5] = 27.0; 00186 fFlipLowAdc[6] = 27.2; 00187 fFlipLowAdc[7] = 29; 00188 00189 fFlipHighAdc[0] = 185; 00190 fFlipHighAdc[1] = 190; 00191 fFlipHighAdc[2] = 196; 00192 fFlipHighAdc[3] = 199; 00193 fFlipHighAdc[4] = 192; 00194 fFlipHighAdc[5] = 200; 00195 fFlipHighAdc[6] = 177; 00196 fFlipHighAdc[7] = 255; // Max 00197 00198 // This is the point, in DAC counts, where the range flips. 00199 // i.e. fFlipPoint[1] is the charge where the QIE flips from range 0 to 1 00200 // This is determined entirely from the above tables. 00201 fFlipPoint[0] = 0; 00202 for(int i=1;i<9;i++) 00203 fFlipPoint[i] = fFlipPoint[i-1] + (fFlipHighAdc[i-1]-fFlipLowAdc[i-1])/fAdcDacSlope[i-1]; 00204 }
| Double_t SimQieElectronics::fAdcDacSlope[8] |
Definition at line 52 of file SimQieElectronics.h.
Referenced by GenSimulatedADC(), and SetupTables().
Definition at line 64 of file SimQieElectronics.h.
Referenced by Config(), SimQiePerfectElectronics::GenSimulatedADC(), GenSimulatedADC(), and Print().
| Double_t SimQieElectronics::fFlipHighAdc[8] |
| Double_t SimQieElectronics::fFlipLowAdc[8] |
Definition at line 53 of file SimQieElectronics.h.
Referenced by GenSimulatedADC(), and SetupTables().
| Double_t SimQieElectronics::fFlipPoint[9] |
Definition at line 51 of file SimQieElectronics.h.
Referenced by GenSimulatedADC(), and SetupTables().
| Double_t SimQieElectronics::fQieAdcRms |
| Double_t SimQieElectronics::fQieDacCharge |
Definition at line 58 of file SimQieElectronics.h.
Referenced by Config(), SimQiePerfectElectronics::GenSimulatedADC(), GenSimulatedADC(), SimQiePerfectElectronics::Print(), Print(), and ReadoutPmt().
Definition at line 59 of file SimQieElectronics.h.
Referenced by Config(), GenSimulatedADC(), Print(), and SetupTables().
Definition at line 57 of file SimQieElectronics.h.
Referenced by Config(), GenSimulatedADC(), and Print().
Definition at line 62 of file SimQieElectronics.h.
Referenced by Config(), SimQiePerfectElectronics::GenSimulatedADC(), GenSimulatedADC(), SimQiePerfectElectronics::Print(), and Print().
Definition at line 60 of file SimQieElectronics.h.
Referenced by Config(), GenSimulatedADC(), and Print().
Definition at line 63 of file SimQieElectronics.h.
Referenced by Config(), SimQiePerfectElectronics::Print(), Print(), and ReadoutPmt().
1.4.7