SimQieElectronics Class Reference

#include <SimQieElectronics.h>

Inheritance diagram for SimQieElectronics:
SimElectronics SimQiePerfectElectronics

List of all members.

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

Detailed Description

Id
SimQieElectronics.h,v 1.7 2006/03/08 23:22:57 tagg Exp

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.

n.tagg1@physics.ox.ac.uk

Definition at line 26 of file SimQieElectronics.h.


Constructor & Destructor Documentation

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]

Definition at line 31 of file SimQieElectronics.h.

00031 {};


Member Function Documentation

SimQieElectronics::ClassDef ( SimQieElectronics  ,
 
)

Reimplemented from SimElectronics.

Reimplemented in SimQiePerfectElectronics.

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]

Definition at line 154 of file SimQieElectronics.cxx.

00155 {
00156   // No dynode simulation...yet.
00157   return true;  
00158 }

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(), SimPmt::GetPixelSpotId(), PlexHandle::GetRawChannelId(), it, 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 QIE 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, 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 }


Member Data Documentation

Definition at line 52 of file SimQieElectronics.h.

Referenced by GenSimulatedADC(), and SetupTables().

Definition at line 48 of file SimQieElectronics.h.

Referenced by Reset().

Definition at line 54 of file SimQieElectronics.h.

Referenced by SetupTables().

Definition at line 53 of file SimQieElectronics.h.

Referenced by GenSimulatedADC(), and SetupTables().

Definition at line 51 of file SimQieElectronics.h.

Referenced by GenSimulatedADC(), and SetupTables().

Definition at line 61 of file SimQieElectronics.h.

Referenced by Config(), and GenSimulatedADC().

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 60 of file SimQieElectronics.h.

Referenced by Config(), GenSimulatedADC(), and Print().

Definition at line 63 of file SimQieElectronics.h.

Referenced by Config(), Print(), SimQiePerfectElectronics::Print(), and ReadoutPmt().


The documentation for this class was generated from the following files:

Generated on 24 Jul 2017 for loon by  doxygen 1.6.1