Ignore:
Timestamp:
01/07/11 15:48:35 (14 years ago)
Author:
tbretz
Message:
Added afterpulse treatment to MAvalanchePhotoDiode and MSimAPD
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Mars/msimcamera/MSimAPD.cc

    r9518 r10093  
    3737//
    3838// Remark:
    39 //   - The photons MUST be sorted increasing in time.
    4039//   - The photon rate used to initialize the APD must match the one used
    4140//     to "fill" the random photons. (FIXME: This should be stored somewhere)
     
    152151    //   * Make the arguments a data member of MSimAPD
    153152
    154     Int_t   ncells    = 0;
    155     Float_t crosstalk = 0;
    156     Float_t deadtime  = 0;
    157     Float_t recovery  = 0;
     153    Int_t   ncells     = 0;
     154    Float_t crosstalk  = 0;
     155    Float_t deadtime   = 0;
     156    Float_t recovery   = 0;
     157    Float_t afterprob1 = 0;
     158    Float_t afterprob2 = 0;
    158159
    159160    switch (fType)
    160161    {
    161162    case 1:
    162         ncells    = 30;
    163         crosstalk = 0.2;
    164         deadtime  = 3;
    165         recovery  = 8.75*4;
     163        ncells     = 30;
     164        crosstalk  = 0.2;
     165        deadtime   = 3;
     166        recovery   = 8.75*4;
     167        afterprob1 = 0;
     168        afterprob2 = 0;
    166169        break;
    167170
    168171    case 2:
    169         ncells    = 60;
    170         crosstalk = 0.2;
    171         deadtime  = 3;
    172         recovery  = 8.75;
     172        ncells     = 60;
     173        crosstalk  = 0.2;
     174        deadtime   = 3;
     175        recovery   = 8.75;
     176        afterprob1 = 0;
     177        afterprob2 = 0;
    173178        break;
    174179
    175180    case 3:
    176         ncells    = 60;
    177         crosstalk = 0.15;
    178         deadtime  = 3;
    179         recovery  = 8.75;
     181        ncells     = 60;
     182        crosstalk  = 0.15;
     183        deadtime   = 3;
     184        recovery   = 8.75;
     185        afterprob1 = 0;
     186        afterprob2 = 0;
     187        break;
     188
     189    case 4:
     190        ncells     = 60;
     191        crosstalk  = 0.15;
     192        deadtime   = 3;
     193        recovery   = 8.75;
     194        afterprob1 = 0.14;
     195        afterprob2 = 0.11;
    180196        break;
    181197
     
    186202
    187203    for (UInt_t i=0; i<fGeom->GetNumPixels(); i++)
    188         fAPDs.Add(new APD(ncells, crosstalk, deadtime, recovery));
     204    {
     205        APD *apd = new APD(ncells, crosstalk, deadtime, recovery);
     206        apd->SetAfterpulseProb(afterprob1, afterprob2);
     207
     208        fAPDs.Add(apd);
     209    }
    189210
    190211    return kTRUE;
     
    198219Int_t MSimAPD::Process()
    199220{
    200     //const Double_t rate = 40e9;
    201     // FIXME: Where do we get this number from??
    202     // const Double_t rate = 0.04;
    203 
    204221    // Make all APDs look neutral for the first hit by a photon according to the
    205222    // average hit rate
     
    213230        return kERROR;
    214231    }
    215 /*
    216     for (UInt_t idx=0; idx<npix; idx++)
    217     {
    218         const Double_t freq = fRates ? (*fRates)[idx].GetPedestal() : fFreq;
    219         static_cast<APD*>(fAPDs.UncheckedAt(idx))->FillRandom(freq, fStat->GetTimeFirst());
    220     }
    221 */
     232
     233    // To ensure that the photons are always sorted when calling
     234    // HitRandomCellRelative the array is sorted here. If it is sorted
     235    // already nothing will be done since the status is stored.
     236    // FIXME: Check that this is true and check that it is really necessary
     237    fEvt->Sort();
    222238
    223239    // This tries to initialize dead and relaxing cells properly. If
     
    228244    {
    229245        const Double_t freq = fRates ? (*fRates)[idx].GetPedestal() : fFreq;
     246
     247        // Init creates an empty G-APD, i.e. without external pulses
     248        // but the correct history for afterpulses and relaxation.
     249        // If it was already initialized once it evolves the G-APD
     250        // for a time until the effect of relaxation and afterpulses
     251        // is below 0.1%. The also creates the possible afterpulses
     252        // of the future and deletes later afterpulses from the list.
     253        // After the the time stamp fTime is set to 0.
    230254        static_cast<APD*>(fAPDs.UncheckedAt(idx))->Init(freq);
    231255    }
     
    240264        MPhotonData &ph = (*fEvt)[i];
    241265
    242         // Get arrival time of photon and idx
     266        // Get arrival time of photon wrt to left edge of window and its index
    243267        const Double_t t = ph.GetTime()-fStat->GetTimeFirst();
    244268        const Int_t  idx = ph.GetTag();
     
    255279            return kERROR;
    256280        }
    257         // Simulate hitting the APD (the signal height in effective
    258         // "number of photons" is returned)
     281
     282        // Simulate hitting the APD at a time t after T0 (APD::fTime).
     283        // Crosstalk is taken into account and the resulting signal height
     284        // in effective "number of photons" is returned. Afterpulses until
     285        // this time "hit" the G-APD and newly created afterpulses
     286        // are stored in the list of afterpulses
    259287        const Double_t hits = static_cast<APD*>(fAPDs.UncheckedAt(idx))->HitRandomCellRelative(t);
    260 
    261         // FIXME: Make a proper simulation of the excess noise!!!
    262         //const Double_t signal = gRandom->Gaus(hits, 0.2*TMath::Sqrt(hits));
    263288
    264289        // Set the weight to the input
     
    269294    // simulated time.
    270295    for (UInt_t idx=0; idx<npix; idx++)
    271         static_cast<APD*>(fAPDs.UncheckedAt(idx))->IncreaseTime(fStat->GetTimeLast());
     296    {
     297        APD *a = static_cast<APD*>(fAPDs.UncheckedAt(idx));
     298
     299        const Double_t end = fStat->GetTimeLast()-fStat->GetTimeFirst();
     300
     301        // This moves T0 (APD::fTime) at the right edge of our time-
     302        // window. For the next event this means that afterpulses of past
     303        // noise and afterpulses will be available already.
     304        // FIXME: Note, that this might mean that a cosmics-pulse
     305        //        might increase the noise above the normal level.
     306        a->IncreaseTime(end);
     307
     308        // Get the afterpulses and add them to the signal
     309        TIter Next(&a->GetListOfAfterpulses());
     310        Afterpulse *ap = 0;
     311        while ((ap=static_cast<Afterpulse*>(Next())))
     312        {
     313            // Skip afterpulses later than that which have been
     314            // already produced
     315            if (ap->GetTime()>=end)
     316                continue;
     317
     318            // Add a new photon
     319            // FIXME: SLOW!
     320            MPhotonData &ph = fEvt->Add();
     321
     322            // Set source to Artificial (noise), the amplitude produced by the
     323            // afterpulse (includes crosstalk), its arrival time
     324            // and its amplitude, as well as the index of the channel it
     325            // corresponds to.
     326            ph.SetPrimary(MMcEvtBasic::kArtificial);
     327            ph.SetWeight(ap->GetAmplitude());
     328            ph.SetTime(ap->GetTime()+fStat->GetTimeFirst());
     329            ph.SetTag(idx);
     330        }
     331
     332        // It seems to make sense to delete the previous afterpulses now
     333        // but this is not necessary. We have to loop over them in any
     334        // case. So we omit the additional loop for deletion but instead
     335        // do the deletion in the next loop at the end of Init()
     336        // If needed this could be used to keep the total memory
     337        // consumption slighly lower.
     338    }
     339
     340    // Now the newly added afterpulses have to be sorted into the array correctly
     341    fEvt->Sort();
    272342
    273343    return kTRUE;
Note: See TracChangeset for help on using the changeset viewer.