Newer
Older
///////////////////////////////////////////////////////////////////////////////
// //
// THcAerogel //
// //
// Class for an Aerogel detector consisting of pairs of PMT's //
// attached to a diffuser box //
// Will have a fixed number of pairs, but need to later make this //
// configurable. //T
// //
///////////////////////////////////////////////////////////////////////////////
#include "THcAerogel.h"
#include "TClonesArray.h"
#include "THcSignalHit.h"
#include "THaEvData.h"
#include "THaDetMap.h"
#include "THcDetectorMap.h"
#include "THcGlobals.h"
#include "THaCutList.h"
#include "THcParmList.h"
#include "VarDef.h"
#include "VarType.h"
#include "THaTrack.h"
#include "TClonesArray.h"
#include "TMath.h"
#include "THaTrackProj.h"
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
//_____________________________________________________________________________
THcAerogel::THcAerogel( const char* name, const char* description,
THaApparatus* apparatus ) :
THaNonTrackingDetector(name,description,apparatus)
{
// Normal constructor with name and description
fPosTDCHits = new TClonesArray("THcSignalHit",16);
fNegTDCHits = new TClonesArray("THcSignalHit",16);
fPosADCHits = new TClonesArray("THcSignalHit",16);
fNegADCHits = new TClonesArray("THcSignalHit",16);
// fTrackProj = new TClonesArray( "THaTrackProj", 5 );
}
//_____________________________________________________________________________
THcAerogel::THcAerogel( ) :
THaNonTrackingDetector()
{
// Constructor
}
//_____________________________________________________________________________
THaAnalysisObject::EStatus THcAerogel::Init( const TDatime& date )
{
static const char* const here = "Init()";
cout << "THcAerogel::Init " << GetName() << endl;
// Should probably put this in ReadDatabase as we will know the
// maximum number of hits after setting up the detector map
THcHitList::InitHitList(fDetMap, "THcAerogelHit", 100);
EStatus status;
if( (status = THaNonTrackingDetector::Init( date )) )
return fStatus=status;
// Will need to determine which apparatus it belongs to and use the
// appropriate detector ID in the FillMap call
if( gHcDetectorMap->FillMap(fDetMap, "HAERO") < 0 ) {
Error( Here(here), "Error filling detectormap for %s.",
return kInitError;
}
return fStatus = kOK;
}
//_____________________________________________________________________________
Int_t THcAerogel::ReadDatabase( const TDatime& date )
{
// This function is called by THaDetectorBase::Init() once at the beginning
// of the analysis.
char prefix[2];
// Pull values from THcParmList instead
prefix[0]=tolower(GetApparatus()->GetName()[0]);
prefix[1]='\0';
fNelem = 8;// Number of tube pairs // The ENGINE style parameter files don't define
// this. Probably need an additional parameter file
// that contains these fixed parameters.
fPosGain = new Double_t[fNelem];
fNegGain = new Double_t[fNelem];
fPosPedLimit = new Int_t[fNelem];
fNegPedLimit = new Int_t[fNelem];
fPosPedMean = new Double_t[fNelem];
fNegPedMean = new Double_t[fNelem];
DBRequest list[]={
{"aero_pos_gain", fPosGain, kDouble},
{"aero_neg_gain", fPosGain, kDouble},
{"aero_pos_ped_limit", fPosPedLimit, kInt},
{"aero_neg_ped_limit", fNegPedLimit, kInt},
{"aero_pos_ped_mean", fPosPedMean, kDouble},
{"aero_neg_ped_mean", fNegPedMean, kDouble},
{0}
};
gHcParms->LoadParmValues((DBRequest*)&list,prefix);
fIsInit = true;
// Create arrays to hold pedestal results
InitializePedestals();
return kOK;
}
//_____________________________________________________________________________
Int_t THcAerogel::DefineVariables( EMode mode )
{
// Initialize global variables for histogramming and tree
cout << "THcAerogel::DefineVariables called " << GetName() << endl;
if( mode == kDefine && fIsSetup ) return kOK;
fIsSetup = ( mode == kDefine );
// Register variables in global list
// Do we need to put the number of pos/neg TDC/ADC hits into the variables?
// No. They show up in tree as Ndata.H.aero.postdchits for example
RVarDef vars[] = {
{"postdchits", "List of Positive TDC hits",
"fPosTDCHits.THcSignalHit.GetPaddleNumber()"},
{"negtdchits", "List of Negative TDC hits",
"fNegTDCHits.THcSignalHit.GetPaddleNumber()"},
{"posadchits", "List of Positive ADC hits",
"fPosADCHits.THcSignalHit.GetPaddleNumber()"},
{"negadchits", "List of Negative ADC hits",
"fNegADCHits.THcSignalHit.GetPaddleNumber()"},
{"pos_npe","PEs Positive Tube","fPosNpe"},
{"neg_npe","PEs PE Negative Tube","fNegNpe"},
{"pos_npe_sum", "Total Positive Tube PEs", "fPosNpeSum"},
{"neg_npe_sum", "Total Negative Tube PEs", "fNegNpeSum"},
{"npe_sum", "Total PEs", ""},
{"ntdc_pos_hits", "Number of Positive Tube Hits", "fNTDCPosHits"},
{"ntdc_neg_hits", "Number of Negative Tube Hits", "fNTDCNegHits"},
{"ngood_hits", "Total number of good hits", "fNGoodHits"},
{ 0 }
};
return DefineVarsFromList( vars, mode );
}
//_____________________________________________________________________________
inline
void THcAerogel::Clear(Option_t* opt)
{
fPosTDCHits->Clear();
fNegTDCHits->Clear();
fPosADCHits->Clear();
fNegADCHits->Clear();
// Clear Aerogel variables from h_aero.f
fNhits = 0; // Don't really need to do this. (Be sure this called before Decode)
fPosNpeSum = 0.0;
fNegNpeSum = 0.0;
fNpeSum = 0.0;
fNGoodHits = 0;
fNADCPosHits = 0;
fNADCNegHits = 0;
fNTDCPosHits = 0;
fNTDCNegHits = 0;
for(Int_t itube = 0;itube < fNelem;itube++) {
fPosNpe[itube] = 0.0;
fNegNpe[itube] = 0.0;
}
}
//_____________________________________________________________________________
Int_t THcAerogel::Decode( const THaEvData& evdata )
{
// Get the Hall C style hitlist (fRawHitList) for this event
fNhits = THcHitList::DecodeToHitList(evdata);
if(gHaCuts->Result("Pedestal_event")) {
AccumulatePedestals(fRawHitList);
fAnalyzePedestals = 1; // Analyze pedestals first normal events
return(0);
}
if(fAnalyzePedestals) {
CalculatePedestals();
fAnalyzePedestals = 0; // Don't analyze pedestals next event
Int_t nPosTDCHits=0;
Int_t nNegTDCHits=0;
Int_t nPosADCHits=0;
Int_t nNegADCHits=0;
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
THcAerogelHit* hit = (THcAerogelHit *) fRawHitList->At(ihit);
// TDC positive hit
if(hit->fTDC_pos > 0) {
THcSignalHit *sighit = (THcSignalHit*) fPosTDCHits->ConstructedAt(nPosTDCHits++);
sighit->Set(hit->fCounter, hit->fTDC_pos);
}
// TDC negative hit
if(hit->fTDC_neg > 0) {
THcSignalHit *sighit = (THcSignalHit*) fNegTDCHits->ConstructedAt(nNegTDCHits++);
sighit->Set(hit->fCounter, hit->fTDC_neg);
}
// ADC positive hit
if(hit->fADC_pos > 0) {
THcSignalHit *sighit = (THcSignalHit*) fPosADCHits->ConstructedAt(nPosADCHits++);
sighit->Set(hit->fCounter, hit->fADC_pos);
}
// ADC negative hit
if(hit->fADC_neg > 0) {
THcSignalHit *sighit = (THcSignalHit*) fNegADCHits->ConstructedAt(nNegADCHits++);
sighit->Set(hit->fCounter, hit->fADC_neg);
}
ihit++;
}
return ihit;
}
//_____________________________________________________________________________
Int_t THcAerogel::ApplyCorrections( void )
{
return(0);
}
//_____________________________________________________________________________
Int_t THcAerogel::CoarseProcess( TClonesArray& ) //tracks
{
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
for(Int_t ihit=0; ihit < fNhits; ihit++) {
THcAerogelHit* hit = (THcAerogelHit *) fRawHitList->At(ihit);
// Pedestal subtraction and gain adjustment
// An ADC value of less than zero occurs when that particular
// channel has been sparsified away and has not been read.
// The NPE for that tube will be assigned zero by this code.
// An ADC value of greater than 8192 occurs when the ADC overflows on
// an input that is too large. Tubes with this characteristic will
// be assigned NPE = 100.0.
Int_t npmt = hit->fCounter - 1;
if(hit->fADC_pos < 8000) {
fPosNpe[npmt] = fPosGain[npmt]*(hit->fADC_pos - fPosPedMean[npmt]);
} else {
fPosNpe[npmt] = 100.0;
}
if(hit->fADC_neg < 8000) {
fNegNpe[npmt] = fNegGain[npmt]*(hit->fADC_neg - fNegPedMean[npmt]);
} else {
fNegNpe[npmt] = 100.0;
}
fPosNpeSum += fPosNpe[npmt];
fNegNpeSum += fNegNpe[npmt];
// Sum positive and negative hits to fill tot_good_hits
if(fPosNpe[npmt] > 0.3) {
fNADCPosHits++;
fNGoodHits++;
}
if(fNegNpe[npmt] > 0.3) {
fNADCNegHits++;
fNGoodHits++;
}
if(hit->fTDC_pos > 0 && hit->fTDC_pos < 8000) {
fNTDCPosHits++;
}
if(hit->fTDC_neg > 0 && hit->fTDC_neg < 8000) {
fNTDCNegHits++;
}
// Fill raw adc variables with actual tubve values
// mainly for diagnostic purposes
}
if(fPosNpeSum > 0.5 || fNegNpeSum > 0.5) {
fNpeSum = fPosNpeSum + fNegNpeSum;
} else {
fNpeSum = 0.0;
}
// If total hits are 0, then give a noticable ridiculous NPE
if(fNhits < 1) {
fNpeSum = 0.0;
}
// The following code is in the fortran. It probably doesn't work
// right because the arrays are not cleared first and the aero_ep,
// aero_en, ... lines make no sense.
//* Next, fill the rawadc variables with the actual tube values
//* mainly for diagnostic purposes.
//
// do ihit=1,haero_tot_hits
//
// npmt=haero_pair_num(ihit)
//
// haero_rawadc_pos(npmt)=haero_adc_pos(ihit)
// aero_ep(npmt)=haero_rawadc_pos(ihit)
//
// haero_rawadc_neg(npmt)=haero_adc_neg(ihit)
// aero_en(npmt)=haero_rawadc_neg(ihit)
//
// haero_rawtdc_neg(npmt)=haero_tdc_neg(ihit)
// aero_tn(npmt)= haero_tdc_neg(ihit)
//
// haero_rawtdc_pos(npmt)=haero_tdc_pos(ihit)
// aero_tp(npmt)= haero_tdc_pos(ihit)
//
// enddo
ApplyCorrections();
return 0;
}
//_____________________________________________________________________________
Int_t THcAerogel::FineProcess( TClonesArray& tracks )
{
return 0;
}
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
//_____________________________________________________________________________
void THcAerogel::InitializePedestals( )
{
fNPedestalEvents = 0;
fMinPeds = 500; // In engine, this is set in parameter file
fPosPedSum = new Int_t [fNelem];
fPosPedSum2 = new Int_t [fNelem];
fPosPedLimit = new Int_t [fNelem];
fPosPedCount = new Int_t [fNelem];
fNegPedSum = new Int_t [fNelem];
fNegPedSum2 = new Int_t [fNelem];
fNegPedLimit = new Int_t [fNelem];
fNegPedCount = new Int_t [fNelem];
fPosPed = new Double_t [fNelem];
fNegPed = new Double_t [fNelem];
fPosThresh = new Double_t [fNelem];
fNegThresh = new Double_t [fNelem];
for(Int_t i=0;i<fNelem;i++) {
fPosPedSum[i] = 0;
fPosPedSum2[i] = 0;
fPosPedLimit[i] = 1000; // In engine, this are set in parameter file
fPosPedCount[i] = 0;
fNegPedSum[i] = 0;
fNegPedSum2[i] = 0;
fNegPedLimit[i] = 1000; // In engine, this are set in parameter file
fNegPedCount[i] = 0;
}
fPosNpe = new Double_t [fNelem];
fNegNpe = new Double_t [fNelem];
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
}
//_____________________________________________________________________________
void THcAerogel::AccumulatePedestals(TClonesArray* rawhits)
{
// Extract data from the hit list, accumulating into arrays for
// calculating pedestals
Int_t nrawhits = rawhits->GetLast()+1;
Int_t ihit = 0;
while(ihit < nrawhits) {
THcAerogelHit* hit = (THcAerogelHit *) rawhits->At(ihit);
Int_t element = hit->fCounter - 1;
Int_t adcpos = hit->fADC_pos;
Int_t adcneg = hit->fADC_pos;
if(adcpos <= fPosPedLimit[element]) {
fPosPedSum[element] += adcpos;
fPosPedSum2[element] += adcpos*adcpos;
fPosPedCount[element]++;
if(fPosPedCount[element] == fMinPeds/5) {
fPosPedLimit[element] = 100 + fPosPedSum[element]/fPosPedCount[element];
}
}
if(adcneg <= fNegPedLimit[element]) {
fNegPedSum[element] += adcneg;
fNegPedSum2[element] += adcneg*adcneg;
fNegPedCount[element]++;
if(fNegPedCount[element] == fMinPeds/5) {
fNegPedLimit[element] = 100 + fNegPedSum[element]/fNegPedCount[element];
}
}
ihit++;
}
fNPedestalEvents++;
return;
}
//_____________________________________________________________________________
void THcAerogel::CalculatePedestals( )
{
// Use the accumulated pedestal data to calculate pedestals
// Later add check to see if pedestals have drifted ("Danger Will Robinson!")
// cout << "Plane: " << fPlaneNum << endl;
for(Int_t i=0; i<fNelem;i++) {
// Positive tubes
fPosPed[i] = ((Double_t) fPosPedSum[i]) / TMath::Max(1, fPosPedCount[i]);
fPosThresh[i] = fPosPed[i] + 15;
// Negative tubes
fNegPed[i] = ((Double_t) fNegPedSum[i]) / TMath::Max(1, fNegPedCount[i]);
fNegThresh[i] = fNegPed[i] + 15;
// cout << i+1 << " " << fPosPed[i] << " " << fNegPed[i] << endl;
// Just a copy for now, but allow the possibility that fXXXPedMean is set
// in a parameter file and only overwritten if there is a sufficient number of
// pedestal events. (So that pedestals are sensible even if the pedestal events were
// not acquired.)
if(fMinPeds > 0) {
if(fPosPedCount[i] > fMinPeds) {
fPosPedMean[i] = fPosPed[i];
}
if(fNegPedCount[i] > fMinPeds) {
fNegPedMean[i] = fNegPed[i];
}
}
}
// cout << " " << endl;
}
void THcAerogel::Print( const Option_t* opt) const {
THaNonTrackingDetector::Print(opt);
// Print out the pedestals
cout << endl;
cout << "Aerogel Pedestals" << endl;
cout << "No. Neg Pos" << endl;
for(Int_t i=0; i<fNelem; i++){
cout << " " << i << " " << fNegPed[i] << " " << fPosPed[i] << endl;
}
cout << endl;
}
ClassImp(THcAerogel)
////////////////////////////////////////////////////////////////////////////////