Ignore:
Timestamp:
06/20/09 10:14:33 (15 years ago)
Author:
tbretz
Message:
*** empty log message ***
Location:
trunk/MagicSoft/Mars/msimcamera
Files:
3 edited

Legend:

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

    r9427 r9462  
    206206        return kERROR;
    207207    }
    208 
     208/*
    209209    for (UInt_t idx=0; idx<npix; idx++)
    210210    {
     
    212212        static_cast<APD*>(fAPDs.UncheckedAt(idx))->FillRandom(freq, fStat->GetTimeFirst());
    213213    }
     214*/
     215
     216    // This tries to initialize dead and relaxing cells properly. If
     217    // the APD has not been initialized before the chip is randomsly
     218    // filled, otherwise a time window of the default relaxing time
     219    // is simulated, so that the previous influence is less than a permille.
     220    for (UInt_t idx=0; idx<npix; idx++)
     221    {
     222        const Double_t freq = fRates ? (*fRates)[idx].GetPedestal() : fFreq;
     223        static_cast<APD*>(fAPDs.UncheckedAt(idx))->Init(freq);
     224    }
    214225
    215226    // Get number of photons
     
    223234
    224235        // Get arrival time of photon and idx
    225         const Double_t t = ph.GetTime();
     236        const Double_t t = ph.GetTime()-fStat->GetTimeFirst();
    226237        const Int_t  idx = ph.GetTag();
    227238        if (idx<0)
     
    239250        // Simulate hitting the APD (the signal height in effective
    240251        // "number of photons" is returned)
    241         const Double_t hits = static_cast<APD*>(fAPDs.UncheckedAt(idx))->HitRandomCell(t);
     252        const Double_t hits = static_cast<APD*>(fAPDs.UncheckedAt(idx))->HitRandomCellRelative(t);
    242253
    243254        // FIXME: Make a proper simulation of the excess noise!!!
     
    248259    }
    249260
     261    // Now we have to shift the evolved time of all APDs to the end of our
     262    // simulated time.
     263    for (UInt_t idx=0; idx<npix; idx++)
     264        static_cast<APD*>(fAPDs.UncheckedAt(idx))->IncreaseTime(fStat->GetTimeLast());
     265
    250266    return kTRUE;
    251267}
  • trunk/MagicSoft/Mars/msimcamera/MSimTrigger.cc

    r9318 r9462  
    4242//
    4343// With a second look-up table fCoincidenceMap the analog channels are
    44 // checked for coincidences. The coincidense must at least be of the length
     44// checked for coincidences. The coincidence must at least be of the length
    4545// defined by fCoincidenceTime. The earliest coincide is then stored as
    4646// trigger position.
     47//
     48// If a minimum multiplicity m is given, m signals above threshold
     49// in the coincidence patterns are enough to emit a trigger signal.
    4750//
    4851//
     
    97100    fEvtHeader(0), fElectronicNoise(0), fGain(0),
    98101    fDiscriminatorThreshold(-1), fDigitalSignalLength(8), fCoincidenceTime(0.5),
    99     fShiftBaseline(kTRUE), fUngainSignal(kTRUE)
     102    fShiftBaseline(kTRUE), fUngainSignal(kTRUE), fSimulateElectronics(kTRUE),
     103    fMinMultiplicity(-1)
    100104{
    101105    fName  = name  ? name  : "MSimTrigger";
     
    107111// Take two TObjArrays with a collection of digital signals.
    108112// Every signal from one array is compared with any from the other array.
    109 // For all signals whihc overlaps and which have an overlap time >gate
     113// For all signals which overlap and which have an overlap time >gate
    110114// a new digital signal is created storing start time and length of overlap.
    111115// They are collected in a newly allocated TObjArray. A pointer to this array
    112116// is returned.
    113117//
    114 // Th euser gains owenership of the object, ie.e., the user is responsible of
     118// The user gains owenership of the object, i.e., the user is responsible of
    115119// deleting the memory.
    116120//
    117 TObjArray *MSimTrigger::CalcCoincidence(const TObjArray &arr1, const TObjArray &arr2, Float_t gate) const
     121TObjArray *MSimTrigger::CalcCoincidence(const TObjArray &arr1, const TObjArray &arr2/*, Float_t gate*/) const
    118122{
    119123    TObjArray *res = new TObjArray;
     
    131135        {
    132136            MDigitalSignal *ttl = new MDigitalSignal(*ttl1, *ttl2);
    133 
     137            /*
    134138            if (ttl->GetLength()<=gate)
    135139            {
     
    137141                continue;
    138142            }
    139 
     143            */
    140144            res->Add(ttl);
    141145        }
     
    143147
    144148    res->SetOwner();
     149
     150    return res;
     151}
     152
     153class Edge : public TObject
     154{
     155private:
     156    Double_t fEdge;
     157    Int_t    fRising;
     158
     159public:
     160    Edge(Double_t t, Int_t rising) : fEdge(t), fRising(rising) { }
     161    Bool_t IsSortable() const { return kTRUE; }
     162    Int_t Compare(const TObject *o) const { const Edge *e = static_cast<const Edge*>(o); if (e->fEdge<fEdge) return 1; if (e->fEdge>fEdge) return -1; return 0; }
     163
     164    Int_t IsRising() const { return fRising; }
     165    Double_t GetEdge() const { return fEdge; }
     166};
     167
     168// --------------------------------------------------------------------------
     169//
     170// Calculate a multiplicity trigger on the given array(s). The idx-array
     171// conatins all channels which should be checked for coincidences
     172// and the ttls array conatins the arrays with the digital signals.
     173//
     174// For the windows in which more or euqal than threshold channels have
     175// a high signal a new MDigitalSignal is created.  newly allocated
     176// array with a collection of these trigger signals is returned.
     177//
     178TObjArray *MSimTrigger::CalcMinMultiplicity(const MArrayI &idx, const TObjArray &ttls, Int_t threshold) const
     179{
     180    // Create a new array for the rising and falling edges of the signals
     181    TObjArray times;
     182    times.SetOwner();
     183
     184    // Fill the array with edges from all digital signals of all our channels
     185    for (UInt_t k=0; k<idx.GetSize(); k++)
     186    {
     187        TObjArray *arr = static_cast<TObjArray*>(ttls[idx[k]]);
     188
     189        TIter Next(arr);
     190        MDigitalSignal *ttl = 0;
     191        while ((ttl=static_cast<MDigitalSignal*>(Next())))
     192        {
     193            times.Add(new Edge(ttl->GetStart(),  1));
     194            times.Add(new Edge(ttl->GetEnd(),   -1));
     195        }
     196    }
     197
     198    // Sort them in time
     199    times.Sort();
     200
     201    // Start with no channel active
     202    Int_t lvl = 0;
     203
     204    TObjArray *res = new TObjArray;
     205    res->SetOwner();
     206
     207    // First remove all edges which do not change the status
     208    // "below threshold" or "above threshold"
     209    for (int i=0; i<times.GetEntriesFast(); i++)
     210    {
     211        // Get i-th edge
     212        const Edge &e = *static_cast<Edge*>(times.UncheckedAt(i));
     213
     214        // Claculate what the number of active channels after the edge is
     215        const Int_t lvl1 = lvl + e.IsRising();
     216
     217        // Remove edge if number of active channels before and after the
     218        // edge lower is lower than the threshold or higher than
     219        // the threshold
     220        if (lvl+1<threshold || lvl-1>=threshold)
     221            delete times.RemoveAt(i);
     222
     223        // keep the (now) "previous" level
     224        lvl = lvl1<0 ? 0 : lvl1;
     225    }
     226
     227    // Remove the empty slots from the array
     228    times.Compress();
     229
     230    //
     231    for (int i=0; i<times.GetEntriesFast()-1; i++)
     232    {
     233        // get the current edge
     234        const Edge &e0 = *static_cast<Edge*>(times.UncheckedAt(i));
     235
     236        // go ahead if this is a falling edge
     237        if (e0.IsRising()!=1)
     238            continue;
     239
     240        // get the following edge (must be a falling edge now)
     241        const Edge &e1 = *static_cast<Edge*>(times.UncheckedAt(i+1));
     242
     243        // calculate the length of the digital signal
     244        const Double_t len = e1.GetEdge()-e0.GetEdge();
     245
     246        // Create a digital trigger signal
     247        MDigitalSignal *ds = new MDigitalSignal(e0.GetEdge(), len);
     248        //ds->SetIndex(lvl);
     249        res->Add(ds);
     250    }
    145251
    146252    return res;
     
    231337    }
    232338
    233     if (fElectronicNoise && !fRouteAC.IsEmpty() && !fRouteAC.IsDefault())
     339    if (fElectronicNoise && !fRouteAC.IsEmpty() && !fRouteAC.IsDefaultCol())
    234340    {
    235341        // FIXME: Apply to analog channels when summing
     
    238344    }
    239345
    240     if (fGain && !fRouteAC.IsEmpty() && !fRouteAC.IsDefault())
     346    if (fGain && !fRouteAC.IsEmpty() && !fRouteAC.IsDefaultCol())
    241347    {
    242348        // FIXME: Apply to analog channels when summing
     
    255361        *fLog << "Using " << fNameRouteAC << " for re-routing/summing of analog channels before discriminator." << endl;
    256362
    257     if (fCoincidenceMap.IsEmpty())
     363    if (fCoincidenceMap.IsEmpty() && fMinMultiplicity==0)
    258364        *fLog << "No coincidences of digital channels will be checked. Signal-above-threshold trigger applied." << endl;
    259365    else
    260         *fLog << "Using " << fNameCoincidenceMap << " to check for coincidences of the digital channels." << endl;
     366    {
     367        *fLog << "Using ";
     368        if (fCoincidenceMap.IsEmpty())
     369            *fLog << "the whole camera";
     370        else
     371            *fLog << "patterns from " << fNameCoincidenceMap;
     372        *fLog << " to check for ";
     373        if (fMinMultiplicity==0)
     374            *fLog << "coincidences of the digital channels." << endl;
     375        else
     376            *fLog << fMinMultiplicity << " multiplicity." << endl;
     377        }
    261378
    262379    *fLog << "Using discriminator threshold of " << fDiscriminatorThreshold << endl;
     
    265382}
    266383
     384/*
     385class MDigitalChannel : public TObjArray
     386{
     387private:
     388    TObjArray fArray;
     389
     390public:
     391    MDigitalSignal *GetSignal(UInt_t i) { return static_cast<MDigitalSignal*>(fArray[i]); }
     392
     393};
     394*/
     395
     396#include "MCamEvent.h"
     397class MTriggerSignal : public MParContainer, public MCamEvent
     398{
     399private:
     400    TObjArray fSignals;
     401
     402public:
     403    MTriggerSignal() { fSignals.SetOwner(); }
     404
     405    void Add(MDigitalSignal *signal) { fSignals.Add(signal); }
     406
     407    MDigitalSignal *GetSignal(UInt_t i) { return static_cast<MDigitalSignal*>(fSignals[i]); }
     408
     409    void Sort() { fSignals.Sort(); }
     410
     411    Int_t GetNumSignals() const { return fSignals.GetEntriesFast(); }
     412
     413    Float_t GetFirstTrigger() const
     414    {
     415        MDigitalSignal *sig = static_cast<MDigitalSignal*>(fSignals[0]);
     416        return sig ? sig->GetStart() : -1;
     417    }
     418    Bool_t GetPixelContent(Double_t&, Int_t, const MGeomCam&, Int_t) const
     419    {
     420        switch (1)
     421        {
     422        case 1: // yes/no
     423        case 2: // first time
     424        case 3: // length
     425        case 4: // n
     426            break;
     427        }
     428
     429        return kTRUE;
     430    }
     431    void DrawPixelContent(Int_t) const
     432    {
     433    }
     434};
     435
     436
     437void MSimTrigger::SetTrigger(Double_t pos)
     438{
     439    // FIXME: Jitter! (Own class?)
     440    fTrigger->SetVal(pos);
     441    fTrigger->SetReadyToSave();
     442
     443    // Trigger pattern to be set
     444    // FIXME: Make flexible
     445    const UInt_t pat = (UInt_t)~(MTriggerPattern::kTriggerLvl1 | (MTriggerPattern::kTriggerLvl1<<8));
     446
     447    // Flag this event as triggered by the lvl1 trigger (FIXME?)
     448    fEvtHeader->SetTriggerPattern(pos<0 ? 0 : pat);
     449    fEvtHeader->SetReadyToSave();
     450}
     451
    267452// --------------------------------------------------------------------------
    268453//
     
    270455{
    271456    // Invalidate trigger
    272     fTrigger->SetVal(-1);
     457    //fTrigger->SetVal(-1);
     458    // Calculate the minimum and maximum time for a valid trigger
     459    const Double_t freq    = fRunHeader->GetFreqSampling()/1000.;
     460    const Float_t  nsamp   = fRunHeader->GetNumSamplesHiGain();
     461    const Float_t  pulspos = fPulsePos->GetVal()/freq;
     462
     463    // Valid range in units of bins
     464    const Float_t min = fCamera->GetValidRangeMin()+pulspos;
     465    const Float_t max = fCamera->GetValidRangeMax()-(nsamp-pulspos);
     466
     467    if (!fSimulateElectronics)
     468    {
     469        SetTrigger(min);
     470        return kTRUE;
     471    }
    273472
    274473    // ================== Simulate channel bundling ====================
     
    297496            {
    298497                const UInt_t idx = row[j];
    299                 (*patches)[i].AddSignal((*fCamera)[idx]);
     498
     499                // FIXME: Shrinking the mapping table earlier (e.g.
     500                //        ReInit) would avoid a lot of if's
     501                if (idx<fCamera->GetNumChannels())
     502                    (*patches)[i].AddSignal((*fCamera)[idx]);
    300503            }
    301504        }
     
    329532    //        omitted in the loop
    330533    if (fCoincidenceMap.IsEmpty())
    331         fCoincidenceMap.SetDefault(npatch);
    332 
    333     // Calculate the minimum and maximum time for a valid trigger
    334     const Double_t freq    = fRunHeader->GetFreqSampling()/1000.;
    335     const Float_t  nsamp   = fRunHeader->GetNumSamplesHiGain();
    336     const Float_t  pulspos = fPulsePos->GetVal()/freq;
    337 
    338     // Valid range in units of bins
    339     const Float_t min = fCamera->GetValidRangeMin()+pulspos;
    340     const Float_t max = fCamera->GetValidRangeMax()-(nsamp-pulspos);
     534    {
     535        if (fMinMultiplicity>0)
     536            fCoincidenceMap.SetDefaultRow(npatch);
     537        else
     538            fCoincidenceMap.SetDefaultCol(npatch);
     539    }
    341540
    342541    // Create an array for the individual triggers
    343     TObjArray triggers;
    344     triggers.SetOwner();
     542    MTriggerSignal triggers;
    345543
    346544    Int_t cnt  = 0;
     
    352550        const MArrayI &idx = fCoincidenceMap.GetRow(j);
    353551
    354         // Start with a copy of the first coincidence channel
    355         TObjArray *arr = static_cast<TObjArray*>(ttls[idx[0]]->Clone());
    356         arr->SetOwner();
    357 
    358         // compare to all other channels in this coincidence patch, one by one
    359         for (UInt_t k=1; k<idx.GetSize() && arr->GetEntriesFast()>0; k++)
    360         {
    361             TObjArray *res = CalcCoincidence(*arr, *static_cast<TObjArray*>(ttls[idx[k]]),
    362                                              fCoincidenceTime);
    363 
    364             // Delete the original array and keep the new one
    365             delete arr;
    366             arr = res;
    367         }
     552        TObjArray *arr = 0;
     553
     554        if (fMinMultiplicity>0)
     555        {
     556            arr = CalcMinMultiplicity(idx, ttls, fMinMultiplicity);
     557        }
     558        else
     559        {
     560            arr = CalcMinMultiplicity(idx, ttls, idx.GetSize());
     561            /*
     562            // Start with a copy of the first coincidence channel
     563            arr = static_cast<TObjArray*>(ttls[idx[0]]->Clone());
     564            arr->SetOwner();
     565
     566            // compare to all other channels in this coincidence patch, one by one
     567            for (UInt_t k=1; k<idx.GetSize() && arr->GetEntriesFast()>0; k++)
     568            {
     569                TObjArray *res = CalcCoincidence(*arr, *static_cast<TObjArray*>(ttls[idx[k]]));//, fCoincidenceTime);
     570
     571                // Delete the original array and keep the new one
     572                delete arr;
     573                arr = res;
     574            }*/
     575        }
     576
     577        // Count the number of totally emitted coincidence signals
     578        cnt += arr->GetEntriesFast();
    368579
    369580        // Remove all signals which are not in the valid digitization range
    370581        // (This is not the digitization window, but the region in which
    371582        //  the analog channels contain usefull data)
     583        // and which are shorter than the defined coincidence gate.
    372584        TIter Next(arr);
    373585        MDigitalSignal *ttl = 0;
    374586        while ((ttl=static_cast<MDigitalSignal*>(Next())))
    375587        {
     588            if (ttl->GetLength()<fCoincidenceTime)
     589            {
     590                delete arr->Remove(ttl);
     591                continue;
     592            }
     593
    376594            if (ttl->GetStart()<min)
    377595            {
    378596                delete arr->Remove(ttl);
    379597                rmlo++;
     598                continue;
    380599            }
    381600            if (ttl->GetStart()>max)
     
    383602                delete arr->Remove(ttl);
    384603                rmhi++;
     604                continue;
    385605            }
     606
     607            // Set trigger channel index
     608            ttl->SetIndex(j);
    386609        }
    387610
     
    389612        arr->Compress();
    390613
    391         cnt += arr->GetEntriesFast();
    392 
    393614        // If we have at least one trigger keep the earliest one.
    394         // FIXME: The triggers should be ordered in time automatically: To be checked!
     615        // FIXME: The triggers might be ordered in time automatically:
     616        //        To be checked!
    395617        // FIXME: Simulate trigger dead-time!
    396618        if (arr->GetEntriesFast()>0)
    397             triggers.Add(arr->RemoveAt(0));
     619            triggers.Add(static_cast<MDigitalSignal*>(arr->RemoveAt(0)));
    398620
    399621        // delete the allocated space
    400622        delete arr;
    401     }
    402 
    403     // No trigger issued. Go on.
    404     if (triggers.GetEntriesFast()==0)
    405     {
    406         if (rmlo>0 || rmhi>0)
    407             *fLog << inf2 << rmlo << "/" << rmhi << " trigger out of valid range. No trigger raised." << endl;
    408         return kTRUE;
    409623    }
    410624
     
    414628    //         is omitted
    415629    triggers.Sort();
    416 
    417     // FIXME: Jitter! (Own class?)
    418     fTrigger->SetVal(static_cast<MDigitalSignal*>(triggers[0])->GetStart());
    419     fTrigger->SetReadyToSave();
    420 
    421     // Flag this event as triggered by the lvl1 trigger (FIXME?)
    422     fEvtHeader->SetTriggerPattern((UInt_t)~(MTriggerPattern::kTriggerLvl1 | (MTriggerPattern::kTriggerLvl1<<8)));
    423     fEvtHeader->SetReadyToSave();
    424 
    425     // inf2?
    426     *fLog << inf;
    427     *fLog << cnt << " triggers left in " << triggers.GetEntriesFast() << " patches (" << rmlo << "/" << rmhi << " trigger out of valid range), T=" << fTrigger->GetVal();
     630    // FIXME: Store triggers! (+ Reversed pixels?)
     631
     632    SetTrigger(triggers.GetFirstTrigger());
     633
     634    // No trigger issued. Go on.
     635    if (triggers.GetNumSignals()==0)
     636    {
     637        if (rmlo>0 || rmhi>0)
     638            *fLog << inf2 << GetNumExecutions() << ": " << rmlo << "/" << rmhi << " trigger out of valid range. No trigger raised." << endl;
     639        return kTRUE;
     640    }
     641
     642    // Number of patches which have triggered out of the total number of
     643    // Coincidence signals emitted. (If the total number is higher than
     644    // the number of triggers either some triggers had to be removed or
     645    // or a patch has emitted more than one trigger signal)
     646    // FIXME: inf2?
     647    *fLog << inf << GetNumExecutions() << ": ";
     648    *fLog << setw(3) << triggers.GetNumSignals() << " triggers left out of ";
     649    *fLog << setw(3) << cnt << " (" << rmlo << "/" << rmhi << " trigger out of valid range), T=" << fTrigger->GetVal();
    428650    *fLog << endl;
     651
     652    //# Trigger characteristics: gate length (ns), min. overlapping time (ns),
     653    //# amplitude and FWHM of (gaussian) single phe response for trigger:
     654    //trigger_prop 3.0 0.25 1.0 2.0
    429655
    430656    return kTRUE;
     
    438664// DigitalSignalLength:     8
    439665// CoincidenceTime:         0.5
     666// SimulateElectronics:     Yes
    440667//
    441668Int_t MSimTrigger::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
     
    472699    }
    473700
     701    if (IsEnvDefined(env, prefix, "SimulateElectronics", print))
     702    {
     703        rc = kTRUE;
     704        fSimulateElectronics = GetEnvValue(env, prefix, "SimulateElectronics", fSimulateElectronics);
     705    }
     706
     707    if (IsEnvDefined(env, prefix, "MinMultiplicity", print))
     708    {
     709        rc = kTRUE;
     710        fMinMultiplicity = GetEnvValue(env, prefix, "MinMultiplicity", fMinMultiplicity);
     711    }
     712
    474713    return rc;
    475714}
  • trunk/MagicSoft/Mars/msimcamera/MSimTrigger.h

    r9318 r9462  
    4040    Bool_t  fShiftBaseline;             // Shift the baseline back to 0 for the threshold (needs ElectronicNoise [MPedestalCam])
    4141    Bool_t  fUngainSignal;              // "Remove" the gain from the signal (needs Gain [MPedestalCam])
     42    Bool_t  fSimulateElectronics;       // If the electronics is not simulated the trigger is set artificially to the first photon arrived
     43
     44    Int_t   fMinMultiplicity;           // N out of M
    4245
    4346    // MSimTrigger
    44     TObjArray *CalcCoincidence(const TObjArray &arr1, const TObjArray &arr2, Float_t gate=0) const;
     47    TObjArray *CalcCoincidence(const TObjArray &arr1, const TObjArray &arr2/*, Float_t gate=0*/) const;
     48    TObjArray *CalcMinMultiplicity(const MArrayI &idx, const TObjArray &ttls, Int_t threshold) const;
     49    TObjArray *CalcCoincidences(const MArrayI &idx, const TObjArray &ttls) const;
     50    void SetTrigger(Double_t pos);
    4551
    4652    // MTask
Note: See TracChangeset for help on using the changeset viewer.