UMN CDMS Wiki archive
start › cdms › k100 › run_summary › run_76 › write_efficiency

Write Efficiency

The DAQ system can not quite keep up with the trigger rate typically - some triggered events are lost. We can look at random traces to calculate the true event rate for a category of pulses strong enough that they should trigger the DAQ, then find the rate that we see triggered events of that category; the ratio of the two rates is the write efficiency. True rates can be derived from observed rates by dividing by the efficiency.

NaI-triggered data

For NaI-triggered data we want to look at pulses in zip4 pA - that's the channel that records triggers from the NaI array.

Example

Load some NaI-triggered data:

// load NaI series into one chain
gStyle->SetOptStat(0)
gStyle->SetOptFit(1)
TString datapath ="/data/chocula/fritts/data/k100proc/midasrq/byseries/"
TString ser[] = {"07220916_2059","07220916_2200","07220917_1039","07220917_1225","07220917_2125","07220917_2155"}
//TString lab[] = {"0V","-4V","-21V","-65V","-84V","-84V"}
int nser = 6
TChain *e
TChain *z
e = new TChain("rqDir/eventTree")
z = new TChain("rqDir/zip1")
z4 = new TChain("rqDir/zip4")
// load odd-numbered series only, those are the NaI-triggered series
for(int s=0;s<nser;s++)if(s%2==1)e->Add(Form("%s/%s/umn*root",datapath.Data(),ser[s].Data()));
for(int s=0;s<nser;s++)if(s%2==1)z->Add(Form("%s/%s/umn*root",datapath.Data(),ser[s].Data()));
for(int s=0;s<nser;s++)if(s%2==1)z4->Add(Form("%s/%s/umn*root",datapath.Data(),ser[s].Data()));
z->AddFriend(e)
z->AddFriend(z4)
//z->SetLineColor(kRed)
TCut crand = "EventCategory"

We can use walk algorithm quantities to look for NaI triggers in random traces:

z->Draw("zip4.PAWKmax:zip4.PAWKr50",crand)

Most random events are in the narrow band at the bottom - just flat traces. The band at the top is TTL pulses from the NaI array. The horizontal axis is the 50% start time of the pulse according to the walk algorithm. This algorithm doesn't work properly if the pulse is too early or too late. So we choose a time window where the algorithm works properly.

float nrand
nrand=z->GetEntries(crand) 
float nrandhit
nrandhit=z->GetEntries(crand+"zip4.PAWKmax>0.6e-6&&zip4.PAWKr50>0.00035&&zip4.PAWKr50<0.003")
// note: my criterion for a hit is based on PTWK quantities
// in the trace window 0.00035 to 0.003 seconds (for PTWKr50) the walk algorithm seems to work properly 
float twindow = 0.003-0.00035
float rate_rand
rate_rand = log(nrand/(nrand-nrandhit))/twindow
// 11.8466 Hz

The code above calculates the trigger rate in randoms. We count the number of randoms and the number of randoms that have a “hit” (a pulse) according to our criteria. The proper way to get the rate for a Poisson process is shown in the second-to-last line. The rate we see in this data is 11.85 Hz.

Note - we can also calculate the uncertainty in this rate - I will add that later.

Now we get the rate of pulses seen in the triggered data:

float timesec = 102291-89791+87895-55573+49158-3690
float ntrig
ntrig = z->GetEntries(!crand+"zip4.PAWKmax>0.6e-6")
float rate_trig
rate_trig = ntrig/timesec 
// 10.2368 Hz

It is indeed somewhat less than the true rate. We now calculate the write efficiency:

float effic_write
effic_write = rate_trig/rate_rand
//
cout<<"// "<<rate_rand<<"\t"<<rate_trig<<"\t"<<effic_write<<endl
// 11.8466      10.2368 0.86411

We get a write efficiency of 86.4%.

Addendum to example

The example above did not show how to calculated “timesec”, the number of seconds in the active part of the run. It's easier to do that for a single series rather than the multiple series above, so here we'll start over and load only a single series.

// load one NaI series 
TString datapath ="/data/chocula/fritts/data/k100proc/midasrq/byseries/"
TString ser = "07220916_2200"
TChain *e
TChain *z
e = new TChain("rqDir/eventTree")
z = new TChain("rqDir/zip1")
z4 = new TChain("rqDir/zip4")
e->Add(Form("%s/%s/umn*root",datapath.Data(),ser.Data()));
z->Add(Form("%s/%s/umn*root",datapath.Data(),ser.Data()));
z4->Add(Form("%s/%s/umn*root",datapath.Data(),ser.Data()));
z->AddFriend(e)
z->AddFriend(z4)
TCut crand = "EventCategory"

Now calculate the live time. This is the period of time during the series in which the DAQ is set to trigger on data. Every series starts with 1000 randoms, so we look at the 1001th event and the final event. For each event the EventTime is shown - that's the Unix Time of the event in seconds, so we just subtract the two and take that as the live time.

// calculate live time for single series
int nentries = z->GetEntries()
z->GetEntry(nentries-1)
double timesec = z->GetLeaf("EventTime")->GetValue()
z->GetEntry(1000) // this is the first event after the initial 1000 randoms. So this is when the "live" part of the run begins.
timesec -= z->GetLeaf("EventTime")->GetValue()
cout<<timesec<<endl
// The result for this series is timesec = 45468. That's the time in seconds, equal to about 12.6 hours