00001 #include <TMath.h>
00002 #include "MessageService/MsgService.h"
00003 #include "Digitization/DigiSignal.h"
00004 #include "SimVaTimedElectronics.h"
00005 #include "SimElecMaker.h"
00006 #include "Calibrator/Calibrator.h"
00007
00008
00009 SimElecMakerProxy<SimVaTimedElectronics> gSimVaTimedElec("SimVaTimedElectronics");
00010
00011 CVSID("$Id: SimVaTimedElectronics.cxx,v 1.10 2007/02/07 16:08:33 rodriges Exp $");
00012
00013 ClassImp(SimVaTimedElectronics)
00014
00015 SimVaTimedElectronics::SimVaTimedElectronics( VldContext context, TRandom* random )
00016 : SimVaElectronics( context, random ),
00017 fVaShapingTime(500.*Munits::ns)
00018 {
00019 }
00020
00021 void SimVaTimedElectronics::Config( Registry& config )
00022 {
00023
00024
00025
00026 config.Get("vaShapingTime",fVaShapingTime);
00027 SimVaElectronics::Config(config);
00028 }
00029
00030
00031 void SimVaTimedElectronics::ReadoutDetector( SimPmtList& pmtList )
00032 {
00033 PlexHandle plex(fContext);
00034
00035
00036 std::map<int,std::vector<double> > varcTrigTimes;
00037 std::map<int,std::vector<double> >::iterator it;
00038
00039
00040 std::map<int,vector<SimPmt*> > varcs;
00041 std::map<int,vector<SimPmt*> >::iterator varcItr;
00042
00043 SimPmtList::iterator PmtIt;
00044 for(PmtIt = pmtList.begin(); PmtIt!= pmtList.end(); PmtIt++) {
00045 SimPmt* pmt = PmtIt->second;
00046 if(pmt) {
00047 RawChannelId rcid = plex.GetRawChannelId(pmt->GetPixelSpotId(1));
00048 if ( (rcid.GetElecType()==ElecType::kVA) ) {
00049 if(DynodeTrigger(pmt->GetDynodeCharge())>0.) {
00050
00051 int crate = rcid.GetCrate();
00052 int varc = rcid.GetVarcId();
00053 int vmm = rcid.GetVmm();
00054 int index = crate*100 + varc*10;
00055 if(fVarcTriggerMode == SimVarcTriggerMode::k2of6) {
00056 index += vmm;
00057 }
00058 varcs[index].push_back(pmt);
00059 }
00060 }
00061 }
00062 }
00063
00064
00065 for(varcItr=varcs.begin();varcItr!=varcs.end();varcItr++) {
00066
00067 MSG("DetSim",Msg::kDebug) << "Reading out varc " << varcItr->first << endl;
00068 ReadoutVarc(varcItr->second);
00069 }
00070 }
00071
00072 void SimVaTimedElectronics::ReadoutVarc( std::vector<SimPmt*>& pmts )
00073 {
00078
00079
00080 if(fVarcTriggerMode != SimVarcTriggerMode::kNone) {
00081 if(pmts.size()<2) return;
00082 };
00083
00084
00085
00086
00087 std::vector<double> vDynodeTimes;
00088 for(UInt_t i=0; i<pmts.size(); i++) {
00089 if(pmts[i]==0) continue;
00090
00091
00092
00093
00094
00095 double lastHitTime = -1e9;
00096
00097 SimPmtBucketIterator bIt( *(pmts[i]) );
00098 for( ; !bIt.End(); bIt.Next() ) {
00099 Int_t bucket = bIt.BucketId();
00100 double bucketcharge = pmts[i]->GetDynodeCharge(bucket);
00101 if(DynodeTrigger(bucketcharge)) {
00102 double t = pmts[i]->GetDynodeTime(bucket);
00103 if((t-lastHitTime)>fVaChipDeadTime) {
00104 lastHitTime = t;
00105 vDynodeTimes.push_back(t);
00106 MSG("DetSim",Msg::kDebug) << "Dynode trigger at " << t << endl;
00107 }
00108 }
00109 }
00110 }
00111
00112
00113
00114
00115 std::sort(vDynodeTimes.begin(),vDynodeTimes.end());
00116
00117
00118 std::vector<double> vVarcTrigTimes;
00119
00120 if(fVarcTriggerMode != SimVarcTriggerMode::kNone) {
00121 for(UInt_t i=0; i<(vDynodeTimes.size() - 1); i++) {
00122 if((vDynodeTimes[i+1]-vDynodeTimes[i])<fVarcTriggerWindow) {
00123 vVarcTrigTimes.push_back(vDynodeTimes[i]);
00124 }
00125 }
00126 } else {
00127
00128 vVarcTrigTimes = vDynodeTimes;
00129 }
00130
00131
00132 for(UInt_t i=0; i<pmts.size(); i++) {
00133 if(pmts[i]==0) continue;
00134
00135
00136
00137
00138
00139 double lastHitTime = -1e9;
00140
00141 SimPmtBucketIterator bIt( *(pmts[i]) );
00142 for( ; !bIt.End(); bIt.Next() ) {
00143 Int_t bucket = bIt.BucketId();
00144 double bucketcharge = pmts[i]->GetDynodeCharge(bucket);
00145
00146
00147 if(DynodeTrigger(bucketcharge)) {
00148 double t = pmts[i]->GetDynodeTime(bucket);
00149
00150
00151 if((t-lastHitTime)>fVaChipDeadTime) {
00152
00153
00154
00155 bool fired = false;
00156 if(fVarcTriggerMode == SimVarcTriggerMode::kNone) {
00157 fired=true;
00158 }
00159 else {
00160 for(UInt_t j=0;j<vVarcTrigTimes.size();j++) {
00161 Double_t dt = t - vVarcTrigTimes[j];
00162
00163
00164
00165 if ( ( dt > -1e-12 ) && ( dt < fVarcTriggerWindow ) ) {
00166 fired = true;
00167 }
00168 }
00169 }
00170 if(fired) {
00171 MSG("DetSim",Msg::kDebug) << "Chip fired. " << t/Munits::ns << endl;
00172 lastHitTime = t;
00173 ReadoutPmt(pmts[i],t);
00174 }
00175 }
00176 }
00177 }
00178 }
00179
00180
00181 }
00182
00183
00184
00185 void SimVaTimedElectronics::ReadoutPmt( SimPmt* pmt,
00186 Double_t dynodeTrigTime)
00187 {
00188 MSG("DetSim",Msg::kDebug) << "SimVaTimedElectronics::ReadoutPmt "
00189 << pmt->GetTubeId().AsString()
00190 << " type " << pmt->GetType()
00191 << " at time " << dynodeTrigTime
00192 << endl;
00193
00194 PlexHandle plex(fContext);
00195
00196
00197 AddDigitsAfterFETrigger( pmt->GetTotalHitPixels(true) );
00198 AddAdcsAfterFETrigger( pmt->GetTotalCharge() * fVaGain );
00199
00200 for(int ipixel = 1; ipixel<= pmt->GetNumberOfPixels(); ipixel++) {
00201 RawChannelId rcid = plex.GetRawChannelId(pmt->GetPixelSpotId(ipixel));
00202
00203 int errorbits = 0;
00204
00205 if(!(rcid.IsNull())) {
00206
00207
00208
00209
00210
00211 DigiSignal* totalSignal = new DigiSignal();
00212 AddSignal(totalSignal);
00213
00214 std::vector<Float_t> spotpe(pmt->GetNumberOfSpots()+1,0);
00215
00216
00217 double qeff = 0;
00218 double qtot = 0;
00219 SimPmtBucketIterator it(*pmt);
00220 for( ; !it.End(); it.Next() ) {
00221 int bucketId = it.BucketId();
00222 SimPmtTimeBucket& pmttb = pmt->GetBucket(bucketId);
00223 SimPixelTimeBucket& pixtb = pmttb.GetPixelBucket(ipixel);
00224
00225
00226 for(int ispot=0;ispot<=pmt->GetNumberOfSpots();ispot++)
00227 spotpe[ispot]+=pixtb.GetPEXtalk(ispot);
00228
00229 double dt = pmt->BucketToStartTime(bucketId) - dynodeTrigTime;
00230
00231
00232 if(pmt->BucketToStopTime(bucketId) <= dynodeTrigTime) continue;
00233
00234
00235 if(dt > fVaChipDeadTime) break;
00236
00237
00238 DigiSignal* signal = pixtb.CreateSignal();
00239 totalSignal->Merge(*signal);
00240 delete signal;
00241
00242 double q = pixtb.GetCharge();
00243 double resp = 1.0;
00244 if(dt>0) {
00245
00246
00247 double t = dt+fVaShapingTime;
00248 resp = t*t*exp(-2*t/fVaShapingTime)/(fVaShapingTime*fVaShapingTime*exp(-2.0));
00249 }
00250 qeff += q*resp;
00251 qtot += q;
00252 }
00253
00254 MSG("DetSim",Msg::kDebug) << "Shaped readout of " << rcid.AsString()
00255 << " TrueQ = " << qtot/Munits::fC
00256 << " fC. Shaped Q = " << qeff/Munits::fC
00257 << endl;
00258
00259
00260 int bigspot = 1;
00261 for(int ispot=1;ispot<=pmt->GetNumberOfSpots();ispot++)
00262 if(spotpe[ispot] > spotpe[bigspot]) bigspot = ispot;
00263
00264 PlexPixelSpotId bestPsid = pmt->GetPixelSpotId(ipixel,bigspot);
00265
00266 int adc = GenSimulatedADC( qeff, rcid, bestPsid );
00267 int tdc = GenSimulatedTDC( dynodeTrigTime, rcid );
00268
00269 SimDigit d( pmt->GetPixelSpotId(ipixel),
00270 rcid,
00271 adc,
00272 tdc,
00273 totalSignal,
00274 errorbits
00275 );
00276 MSG("DetSim",Msg::kVerbose) << "ReadoutPmt: " << d.AsString() << std::endl;
00277
00278
00279 if(d.GetADC() > fVaSparsifyThresh) {
00280 AddDigit(d);
00281
00282
00283 AddDigitsAfterSpars(1);
00284 AddAdcsAfterSpars(d.GetADC());
00285 }
00286 }
00287 }
00288
00289 }
00290
00291
00292 void
00293 SimVaTimedElectronics::Print(Option_t* option) const
00294 {
00295 SimVaElectronics::Print(option);
00296 printf("Timing: fVaShapingTime %f ns\n",fVaShapingTime/Munits::ns);
00297 }