Skip to content

Commit 93fed86

Browse files
authored
Add BPM module (#527)
Adding THcBPM to analyze BPM data. This detector module is to analyzer the BPM signals sent to a readout board (e.g. FADC250). It is largely based on THaBPM class but using the Hall C style decoding and hit processing. To include the analysis in replay, one will need to update the crate - Update crate and detector maps accordingly. It assumes channels 1-4 to be X+, X-, Y+, Y- - Have a parameter file: (e.g. make PARAM/GEN/gbpm.param and include calibration parameters such as rotation matrix, offset values) - Add the module to THcRasteredBeam apparatus in a replay script
1 parent f570302 commit 93fed86

File tree

2 files changed

+402
-0
lines changed

2 files changed

+402
-0
lines changed

src/THcBPM.cxx

Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
// THcBPM: BPM class for Hall C
2+
// Based on THaBPM but using Hall C style hit list in decoding
3+
4+
#include "THcBPM.h"
5+
#include "THaEvData.h"
6+
#include "THaApparatus.h"
7+
#include "THaCutList.h"
8+
9+
#include "THcDetectorMap.h"
10+
#include "THcRawAdcHit.h"
11+
#include "THcRasterRawHit.h"
12+
#include "THcSignalHit.h"
13+
14+
#include "THcParmList.h"
15+
#include "THcGlobals.h"
16+
17+
static const Int_t NCHAN = 4; // number of channels
18+
19+
using namespace std;
20+
21+
//______________________________________________________________
22+
THcBPM::THcBPM( const char* name, const char* description, THaApparatus* a)
23+
: THaBeamDet(name, description, a),
24+
fRawSignal(NCHAN), fPedestals(NCHAN), fCorSignal(NCHAN), fRotPos(NCHAN/2),
25+
fRot2HCSPos(NCHAN/2,NCHAN/2), fCalibRot(0)
26+
{
27+
fNhits = 0;
28+
fAnalyzePedestals = 0;
29+
fNPedestalEvents = 0;
30+
fADCMode = 0; // default: kDBPed
31+
frAdcPulseIntRaw = new TClonesArray("THcSignalHit", NCHAN);
32+
frAdcPulseInt = new TClonesArray("THcSignalHit", NCHAN);
33+
34+
}
35+
36+
//______________________________________________________________
37+
THcBPM::~THcBPM()
38+
{
39+
delete frAdcPulseIntRaw; frAdcPulseIntRaw = nullptr;
40+
delete frAdcPulseInt; frAdcPulseInt = nullptr;
41+
42+
delete [] fPed; fPed = nullptr;
43+
delete [] fPedSum; fPedSum = nullptr;
44+
delete [] fPedLimit; fPedLimit = nullptr;
45+
delete [] fPedCount; fPedCount = nullptr;
46+
}
47+
48+
//______________________________________________________________
49+
THaAnalysisObject::EStatus THcBPM::Init( const TDatime& date )
50+
{
51+
// cout << "THcBPM::Init" << endl;
52+
53+
char EngineDID[] = "xBPM";
54+
EngineDID[0] = toupper(GetApparatus()->GetName()[0]);
55+
56+
if( gHcDetectorMap->FillMap(fDetMap, EngineDID) < 0 ) {
57+
static const char* const here = "Init()";
58+
Error( Here(here), "Error filling detectormap for %s.", EngineDID);
59+
60+
return kInitError;
61+
}
62+
63+
InitHitList(fDetMap,"THcRasterRawHit",fDetMap->GetTotNumChan()+1);
64+
65+
EStatus status;
66+
if( (status = THaBeamDet::Init( date )) )
67+
return fStatus=status;
68+
69+
return fStatus = kOK;
70+
71+
}
72+
73+
//______________________________________________________________
74+
Int_t THcBPM::ReadDatabase( const TDatime& date )
75+
{
76+
77+
// cout << "THcBPM::ReadDatabase" << endl;
78+
79+
// Hall C style LoadDB
80+
char prefix[2];
81+
prefix[0] = 'g';
82+
prefix[1] = '\0';
83+
84+
// default values
85+
fMinPed = 0;
86+
87+
fOrigin.SetXYZ(0.0, 0.0, 0.0);
88+
89+
InitializePedestals();
90+
91+
Double_t pedestals[NCHAN], rotations[NCHAN];
92+
Double_t offsets[2]; // offset x, y
93+
94+
memset( pedestals, 0, sizeof(pedestals) );
95+
memset( rotations, 0, sizeof(rotations) );
96+
memset( offsets , 0, sizeof( offsets ) );
97+
DBRequest list[] = {
98+
{Form("%s_calib_rot",GetName()), &fCalibRot},
99+
{Form("%s_pedestals",GetName()), pedestals, kDouble, NCHAN, 1}, // optional
100+
{Form("%s_rotmatrix",GetName()), rotations, kDouble, NCHAN, 1},
101+
{Form("%s_offsets",GetName()), offsets, kDouble, 2, 1},
102+
{Form("%s_mode",GetName()), &fADCMode, kInt, 0, 1},
103+
{Form("%s_ped_limit",GetName()), fPedLimit, kInt, NCHAN, 1},
104+
{Form("%s_min_ped",GetName()), &fMinPed, kInt, 0, 1},
105+
{nullptr}
106+
};
107+
108+
gHcParms->LoadParmValues((DBRequest*)&list, prefix);
109+
110+
fOffset.SetXYZ(offsets[0], offsets[1], 0);
111+
fPedestals.SetElements( pedestals );
112+
113+
fRot2HCSPos(0,0) = rotations[0];
114+
fRot2HCSPos(0,1) = rotations[1];
115+
fRot2HCSPos(1,0) = rotations[2];
116+
fRot2HCSPos(1,1) = rotations[3];
117+
118+
return kOK;
119+
}
120+
121+
//______________________________________________________________
122+
Int_t THcBPM::DefineVariables( EMode mode )
123+
{
124+
125+
RVarDef vars[] = {
126+
{"rawcur.1", "Current in antenna 1", "GetRawSignal0()"},
127+
{"rawcur.2", "Current in antenna 2", "GetRawSignal1()"},
128+
{"rawcur.3", "Current in antenna 3", "GetRawSignal2()"},
129+
{"rawcur.4", "Current in antenna 4", "GetRawSignal3()"},
130+
{"x", "reconstructed x position", "fPosition.fX"},
131+
{"y", "reconstructed y position", "fPosition.fY"},
132+
{"z", "reconstructed z position", "fPosition.fZ"},
133+
{"xl", "local x position in bpm system", "GetRotPosX()"},
134+
{"yl", "local y position in bpm system", "GetRotPosY()"},
135+
{ nullptr }
136+
};
137+
138+
return DefineVarsFromList( vars, mode );
139+
}
140+
141+
//______________________________________________________________
142+
void THcBPM::Clear( Option_t* opt )
143+
{
144+
145+
THaBeamDet::Clear(opt);
146+
fPosition.SetXYZ(0.,0.,-10000.);
147+
fDirection.SetXYZ(0.,0.,1.);
148+
for( UInt_t k=0; k<NCHAN; ++k ) {
149+
fRawSignal(k)=-1;
150+
fCorSignal(k)=-1;
151+
}
152+
153+
fRotPos(0) = fRotPos(1) = 0.0;
154+
155+
fNhits = 0;
156+
frAdcPulseIntRaw->Clear();
157+
frAdcPulseInt->Clear();
158+
159+
}
160+
161+
//______________________________________________________________
162+
Int_t THcBPM::Decode( const THaEvData& evdata )
163+
{
164+
// cout << "THcBPM::Decode" << endl;
165+
166+
fNhits = DecodeToHitList(evdata);
167+
168+
if(gHaCuts->Result("Pedestal_event")) {
169+
AccumulatePedestals(fRawHitList);
170+
fAnalyzePedestals = 1; // Analyze pedestals first normal events
171+
fNPedestalEvents++;
172+
return(0);
173+
}
174+
175+
if(fAnalyzePedestals) {
176+
CalculatePedestals();
177+
fAnalyzePedestals = 0; // Don't analyze pedestals next event
178+
}
179+
180+
Int_t ihit = 0;
181+
UInt_t nrAdcHits = 0;
182+
while(ihit < fNhits) {
183+
THcRasterRawHit* hit = (THcRasterRawHit*)fRawHitList->At(ihit);
184+
THcRawAdcHit& rawAdcHit = hit->GetRawAdcHitPos();
185+
Int_t nsig = hit->fCounter;
186+
187+
Double_t adcTopC = rawAdcHit.GetAdcTopC();
188+
189+
// pulse data
190+
for(UInt_t thit = 0; thit < rawAdcHit.GetNPulses(); thit++) {
191+
((THcSignalHit*) frAdcPulseIntRaw->ConstructedAt(nrAdcHits))->Set(nsig, rawAdcHit.GetPulseIntRaw(thit));
192+
((THcSignalHit*) frAdcPulseInt->ConstructedAt(nrAdcHits))->Set(nsig, rawAdcHit.GetPulseInt(thit)/adcTopC); // convert back from pC to ADC
193+
++nrAdcHits;
194+
}
195+
196+
// or using simple integral of sample data
197+
if (rawAdcHit.GetNPulses()==0 && rawAdcHit.GetNSamples()>0 ) {
198+
Int_t NSA = rawAdcHit.GetF250_NSA();
199+
UInt_t LS = 0;
200+
UInt_t HS = NSA;
201+
Int_t rawdata = rawAdcHit.GetIntegral(LS,HS);
202+
203+
UInt_t SampPed = rawAdcHit.GetSampPedRaw();
204+
// NSA+1: because we call GetIntegral for [0, NSA]; NSA+1 samples
205+
Double_t PeakPedestalRatio = 1.0 * (NSA+1)/rawAdcHit.GetF250_NPedestalSamples();
206+
Double_t data = (rawdata - SampPed * PeakPedestalRatio);
207+
208+
((THcSignalHit*) frAdcPulseIntRaw->ConstructedAt(nrAdcHits))->Set(nsig, rawdata);
209+
((THcSignalHit*) frAdcPulseInt->ConstructedAt(nrAdcHits))->Set(nsig, data);
210+
++nrAdcHits;
211+
}
212+
ihit++;
213+
}// loop over hits
214+
215+
// subtract pedestal and fill vectors
216+
for(Int_t ielem = 0; ielem < frAdcPulseIntRaw->GetEntries(); ielem++) {
217+
Int_t pad_num = ((THcSignalHit*) frAdcPulseIntRaw->ConstructedAt(ielem))->GetPaddleNumber() - 1;
218+
Double_t pulseIntRaw = ((THcSignalHit*) frAdcPulseIntRaw->ConstructedAt(ielem))->GetData();
219+
Double_t pulseInt = ((THcSignalHit*) frAdcPulseInt->ConstructedAt(ielem))->GetData();
220+
221+
// We expect N paddle = NCHAN = 4
222+
if( pad_num > NCHAN-1 ) {
223+
Warning(Here("Decode"), "Number of fired channels out of range. Should be <= 4. Ignore the channel.");
224+
continue;
225+
}
226+
227+
fRawSignal(pad_num) = pulseIntRaw;
228+
229+
// Subtract pedestals
230+
if(fADCMode == kDynamicPed){
231+
// Use event by event ped subtraction
232+
fCorSignal(pad_num) = pulseInt;
233+
} else if (fADCMode == kDBPed ) {
234+
// Use ped values from DB file (default)
235+
fCorSignal(pad_num) = fRawSignal(pad_num) - fPedestals(pad_num);
236+
} else {
237+
// kCalculatePed
238+
fCorSignal(pad_num) = fRawSignal(pad_num) - fPed[pad_num];
239+
}
240+
}
241+
242+
return fNhits;
243+
}
244+
245+
//______________________________________________________________
246+
Int_t THcBPM::Process( )
247+
{
248+
// Calculate position and directions
249+
// (x, y)_lab = Cij * (x, y)_bpm + (offset_x, offset_y)
250+
251+
// First calculate position in bpm coord system
252+
// assume 0:x+ 1:x- 2:y+ 3:y-
253+
for(Int_t k = 0; k < NCHAN; k += 2) {
254+
Double_t ap = fCorSignal(k);
255+
Double_t am = fCorSignal(k+1);
256+
257+
fRotPos(k / 2) = 0.0;
258+
if( ap + am != 0.0 )
259+
fRotPos(k / 2) = fCalibRot * (ap - am) / (ap + am);
260+
}
261+
262+
// transform it into the HCS
263+
TVectorD temp(fRotPos);
264+
temp *= fRot2HCSPos;
265+
fPosition.SetXYZ( temp(0) + fOrigin(0) + fOffset(0),
266+
temp(1) + fOrigin(1) + fOffset(1),
267+
fOrigin(2) );
268+
269+
return 0;
270+
}
271+
272+
//______________________________________________________________
273+
void THcBPM::InitializePedestals()
274+
{
275+
276+
fNPedestalEvents = 0;
277+
fPed = new Int_t [NCHAN];
278+
fPedSum = new Int_t [NCHAN];
279+
fPedCount = new Int_t [NCHAN];
280+
fPedLimit = new Int_t [NCHAN];
281+
for(Int_t i = 0; i < NCHAN; i++) {
282+
fPed[i] = 0;
283+
fPedSum[i] = 0;
284+
fPedCount[i] = 0;
285+
fPedLimit[i] = 1000;
286+
}
287+
288+
}
289+
290+
//______________________________________________________________
291+
void THcBPM::AccumulatePedestals( TClonesArray* rawhits )
292+
{
293+
294+
UInt_t nhits = rawhits->GetLast() + 1;
295+
296+
for(UInt_t ihit = 0; ihit < nhits; ihit++) {
297+
THcRasterRawHit* hit = (THcRasterRawHit*)fRawHitList->At(ihit);
298+
299+
Int_t ielem = hit->fCounter -1;
300+
Int_t rawadc = hit->GetRawAdcHitPos().GetPulseIntRaw();
301+
302+
if(rawadc <= fPedLimit[ielem]) {
303+
fPedSum[ielem] += rawadc;
304+
fPedCount[ielem]++;
305+
306+
//fMinPed is hard-coded value, 500
307+
if(fPedCount[ielem] == fMinPed/5) {
308+
fPedLimit[ielem] = 100 + fPedSum[ielem]/fPedCount[ielem];
309+
}
310+
}
311+
}//loop over hits
312+
313+
}
314+
315+
//______________________________________________________________
316+
void THcBPM::CalculatePedestals()
317+
{
318+
// Calculate pedestal mean
319+
for(Int_t i = 0; i < NCHAN; i++) {
320+
fPed[i] = (Double_t)fPedSum[i]/TMath::Max(1, fPedCount[i]);
321+
}
322+
323+
}
324+
325+
ClassImp(THcBPM)

0 commit comments

Comments
 (0)