Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//*-- Author : Stephen Wood 20-Apr-2012
//////////////////////////////////////////////////////////////////////////
//
// THcHallCSpectrometer
//
// A standard Hall C spectrometer.
// Contains no standard detectors,
// May add hodoscope
//
// The usual name of this object is either "H", "S", or "P"
// for HMS, SOS, or suPerHMS respectively
//
// Defines the functions FindVertices() and TrackCalc(), which are common
// to both the LeftHRS and the RightHRS.
//
// Special configurations of the HRS (e.g. more detectors, different
// detectors) can be supported in on e of three ways:
//
// 1. Use the AddDetector() method to include a new detector
// in this apparatus. The detector will be decoded properly,
// and its variables will be available for cuts and histograms.
// Its processing methods will also be called by the generic Reconstruct()
// algorithm implemented in THaSpectrometer::Reconstruct() and should
// be correctly handled if the detector class follows the standard
// interface design.
//
// 2. Write a derived class that creates the detector in the
// constructor. Write a new Reconstruct() method or extend the existing
// one if necessary.
//
// 3. Write a new class inheriting from THaSpectrometer, using this
// class as an example. This is appropriate if your HRS
// configuration has fewer or different detectors than the
// standard HRS. (It might not be sensible to provide a RemoveDetector()
// method since Reconstruct() relies on the presence of the
// standard detectors to some extent.)
//
// For timing calculations, S1 is treated as the scintillator at the
// 'reference distance', corresponding to the pathlength correction
// matrix.
//
//////////////////////////////////////////////////////////////////////////
#include "THcHallCSpectrometer.h"
#include "THaTrackingDetector.h"
Stephen A. Wood
committed
#include "THcGlobals.h"
#include "THcParmList.h"
#include "THaTrack.h"
#include "THaTrackProj.h"
#include "THaTriggerTime.h"
#include "TMath.h"
#include "TList.h"
#include <iostream>
Stephen A. Wood
committed
#include <fstream>
using namespace std;
//_____________________________________________________________________________
THcHallCSpectrometer::THcHallCSpectrometer( const char* name, const char* description ) :
THaSpectrometer( name, description )
{
// Constructor. Defines the standard detectors for the HRS.
// AddDetector( new THaTriggerTime("trg","Trigger-based time offset"));
//sc_ref = static_cast<THaScintillator*>(GetDetector("s1"));
SetTrSorting(kTRUE);
}
//_____________________________________________________________________________
THcHallCSpectrometer::~THcHallCSpectrometer()
{
// Destructor
}
//_____________________________________________________________________________
Bool_t THcHallCSpectrometer::SetTrSorting( Bool_t set )
{
if( set )
fProperties |= kSortTracks;
else
fProperties &= ~kSortTracks;
return set;
}
//_____________________________________________________________________________
Bool_t THcHallCSpectrometer::GetTrSorting() const
{
return ((fProperties & kSortTracks) != 0);
}
//_____________________________________________________________________________
Stephen A. Wood
committed
void THcHallCSpectrometer::InitializeReconstruction()
{
fNReconTerms = 0;
for(Int_t i=0;i<fNReconTerms;i++) {
for(Int_t j=0;j<4;j++) {
fReconCoeff[i][j] = 0.0;
}
for(Int_t j=0;j<5;j++) {
fReconExponents[i][j] = 0;
}
}
fAngSlope_x = 0.0;
fAngSlope_y = 0.0;
fAngOffset_x = 0.0;
fAngOffset_y = 0.0;
fDetOffset_x = 0.0;
fDetOffset_y = 0.0;
fZTrueFocus = 0.0;
}
//_____________________________________________________________________________
Int_t THcHallCSpectrometer::ReadDatabase( const TDatime& date )
Stephen A. Wood
committed
static const char* const here = "THcHallCSpectrometer::ReadDatabase";
#ifdef WITH_DEBUG
Stephen A. Wood
committed
cout << "In THcHallCSpectrometer::ReadDatabase()" << endl;
Stephen A. Wood
committed
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
// Get the matrix element filename from the variable store
// Read in the matrix
InitializeReconstruction();
char prefix[2];
cout << " GetName() " << GetName() << endl;
prefix[0]=tolower(GetName()[0]);
prefix[1]='\0';
string reconCoeffFilename;
DBRequest list[]={
{"_recon_coeff_filename",&reconCoeffFilename,kString},
{"theta_offset",&fThetaOffset,kDouble},
{"phi_offset",&fPhiOffset,kDouble},
{"delta_offset",&fDeltaOffset,kDouble},
{"pcentral",&fPCentral,kDouble},
{0}
};
gHcParms->LoadParmValues((DBRequest*)&list,prefix);
ifstream ifile;
ifile.open(reconCoeffFilename.c_str());
if(!ifile.is_open()) {
Error(here, "error opening reconstruction coefficient file %s",reconCoeffFilename.c_str());
return kInitError; // Is this the right return code?
}
string line="!";
int good=1;
while(good && line[0]=='!') {
good = getline(ifile,line).good();
cout << line << endl;
}
// Read in focal plane rotation coefficients
// Probably not used, so for now, just paste in fortran code as a comment
while(good && line.compare(0,4," ---")!=0) {
// if(line(1:13).eq.'h_ang_slope_x')read(line,1201,err=94)h_ang_slope_x
// if(line(1:13).eq.'h_ang_slope_y')read(line,1201,err=94)h_ang_slope_y
// if(line(1:14).eq.'h_ang_offset_x')read(line,1201,err=94)h_ang_offset_x
// if(line(1:14).eq.'h_ang_offset_y')read(line,1201,err=94)h_ang_offset_y
// if(line(1:14).eq.'h_det_offset_x')read(line,1201,err=94)h_det_offset_x
// if(line(1:14).eq.'h_det_offset_y')read(line,1201,err=94)h_det_offset_y
// if(line(1:14).eq.'h_z_true_focus')read(line,1201,err=94)h_z_true_focus
good = getline(ifile,line).good();
}
// Read in reconstruction coefficients and exponents
line=" ";
good = getline(ifile,line).good();
cout << line << endl;
fNReconTerms = 0;
cout << "Reading matrix elements" << endl;
while(good && line.compare(0,4," ---")!=0) {
if(fNReconTerms >= fMaxReconElements) {
Error(here, "too much data in reconstruction coefficient file %s",reconCoeffFilename.c_str());
return kInitError; // Is this the right return code?
}
#if 0
Double_t x,y,z,t;
Int_t a,b,c,d,e;
sscanf(line.c_str()," %le %le %le %le %1d%1d%1d%1d%1d",&x,&y,&z,&t,
&a,&b,&c,&d,&e);
cout << x << " " << y << " " << z << " " << t << " "
<< a << b << c << d << endl;
#endif
sscanf(line.c_str()," %le %le %le %le %1d%1d%1d%1d%1d"
,&fReconCoeff[fNReconTerms][0],&fReconCoeff[fNReconTerms][1]
,&fReconCoeff[fNReconTerms][2],&fReconCoeff[fNReconTerms][3]
,&fReconExponents[fNReconTerms][0]
,&fReconExponents[fNReconTerms][1]
,&fReconExponents[fNReconTerms][2]
,&fReconExponents[fNReconTerms][3]
,&fReconExponents[fNReconTerms][4]);
// Parse line into fReconCoeff[fNReconTerms][0 - 3] and
// fReconExponents[fNReconTerms][0 - 5]
fNReconTerms++;
good = getline(ifile,line).good();
}
#if 0
cout << fNReconTerms << " Reconstruction terms" << endl;
for (Int_t i=0;i<fNReconTerms;i++) {
cout << fReconCoeff[i][0] << " " << fReconCoeff[i][1] << " "
<< fReconCoeff[i][2] << " " << fReconCoeff[i][3] << " "
<< fReconExponents[i][0] << fReconExponents[i][1]
<< fReconExponents[i][2] << fReconExponents[i][3]
<< fReconExponents[i][4] << endl;
}
Stephen A. Wood
committed
215
216
217
218
219
220
221
222
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
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
if(!good) {
Error(here, "error processing reconstruction coefficient file %s",reconCoeffFilename.c_str());
return kInitError; // Is this the right return code?
}
return kOK;
}
//_____________________________________________________________________________
Int_t THcHallCSpectrometer::FindVertices( TClonesArray& tracks )
{
// Reconstruct target coordinates for all tracks found in the focal plane.
// In Hall A, this is passed off to the tracking detectors.
// In Hall C, we do the target traceback here since the traceback should
// not depend on which tracking detectors are used.
for (Int_t it=0;it<tracks.GetLast()+1;it++) {
THaTrack* track = static_cast<THaTrack*>( tracks[it] );
Double_t hut[5];
Double_t hut_rot[5];
hut[0] = track->GetX()/100.0 + fZTrueFocus*track->GetTheta() + fDetOffset_x;//m
hut[1] = track->GetTheta() + fAngOffset_x;//radians
hut[2] = track->GetY()/100.0 + fZTrueFocus*track->GetPhi() + fDetOffset_y;//m
hut[3] = track->GetPhi() + fAngOffset_y;//radians
Double_t gbeam_y = 0.0;// This will be the y position from the fast raster
hut[4] = -gbeam_y/100.0;
// Retrieve the focal plane coordnates
// Do the transpormation
// Stuff results into track
hut_rot[0] = hut[0];
hut_rot[1] = hut[1] + hut[0]*fAngSlope_x;
hut_rot[2] = hut[2];
hut_rot[3] = hut[3] + hut[2]*fAngSlope_y;
hut_rot[4] = hut[4];
// Compute COSY sums
Double_t sum[4];
for(Int_t k=0;k<4;k++) {
sum[k] = 0.0;
}
for(Int_t iterm=0;iterm<fNReconTerms;iterm++) {
Double_t term=1.0;
for(Int_t j=0;j<5;j++) {
if(fReconExponents[iterm][j]!=0) {
term *= pow(hut_rot[j],fReconExponents[iterm][j]);
}
}
for(Int_t k=0;k<4;k++) {
sum[k] += term*fReconCoeff[iterm][k];
}
}
// Transfer results to track
// No beam raster yet
//; In transport coordinates phi = hyptar = dy/dz and theta = hxptar = dx/dz
//; but for unknown reasons the yp offset is named htheta_offset
//; and the xp offset is named hphi_offset
track->SetTarget(0.0, sum[1]*100.0, sum[0]+fPhiOffset, sum[2]+fThetaOffset);
track->SetDp(sum[3]*100.0+fDeltaOffset); // Percent. (Don't think podd cares if it is % or fraction)
// There is an hpcentral_offset that needs to be applied somewhere.
// (happly_offs)
track->SetMomentum(fPCentral*(1+track->GetDp()/100.0));
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
}
// If enabled, sort the tracks by chi2/ndof
if( GetTrSorting() )
fTracks->Sort();
// Find the "Golden Track".
if( GetNTracks() > 0 ) {
// Select first track in the array. If there is more than one track
// and track sorting is enabled, then this is the best fit track
// (smallest chi2/ndof). Otherwise, it is the track with the best
// geometrical match (smallest residuals) between the U/V clusters
// in the upper and lower VDCs (old behavior).
//
// Chi2/dof is a well-defined quantity, and the track selected in this
// way is immediately physically meaningful. The geometrical match
// criterion is mathematically less well defined and not usually used
// in track reconstruction. Hence, chi2 sortiing is preferable, albeit
// obviously slower.
fGoldenTrack = static_cast<THaTrack*>( fTracks->At(0) );
fTrkIfo = *fGoldenTrack;
fTrk = fGoldenTrack;
} else
fGoldenTrack = NULL;
return 0;
}
//_____________________________________________________________________________
Int_t THcHallCSpectrometer::TrackCalc()
{
// Additioal track calculations. At present, we only calculate beta here.
return TrackTimes( fTracks );
}
//_____________________________________________________________________________
Int_t THcHallCSpectrometer::TrackTimes( TClonesArray* Tracks ) {
// Do the actual track-timing (beta) calculation.
// Use multiple scintillators to average together and get "best" time at S1.
//
// To be useful, a meaningful timing resolution should be assigned
// to each Scintillator object (part of the database).
Stephen A. Wood
committed
#if 0
if ( !Tracks ) return -1;
Stephen A. Wood
committed
THaTrack *track=0;
Int_t ntrack = GetNTracks();
Stephen A. Wood
committed
THaTrack *track=0;
// linear regression to: t = t0 + pathl/(beta*c)
// where t0 is the time of the track at the reference plane (sc_ref).
// t0 and beta are solved for.
//
Stephen A. Wood
committed
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
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
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
for ( Int_t i=0; i < ntrack; i++ ) {
track = static_cast<THaTrack*>(Tracks->At(i));
THaTrackProj* tr_ref = static_cast<THaTrackProj*>
(sc_ref->GetTrackHits()->At(i));
Double_t pathlref = tr_ref->GetPathLen();
Double_t wgt_sum=0.,wx2=0.,wx=0.,wxy=0.,wy=0.;
Int_t ncnt=0;
// linear regression to get beta and time at ref.
TIter nextSc( fNonTrackingDetectors );
THaNonTrackingDetector *det;
while ( ( det = static_cast<THaNonTrackingDetector*>(nextSc()) ) ) {
THaScintillator *sc = dynamic_cast<THaScintillator*>(det);
if ( !sc ) continue;
const THaTrackProj *trh = static_cast<THaTrackProj*>(sc->GetTrackHits()->At(i));
Int_t pad = trh->GetChannel();
if (pad<0) continue;
Double_t pathl = (trh->GetPathLen()-pathlref);
Double_t time = (sc->GetTimes())[pad];
Double_t wgt = (sc->GetTuncer())[pad];
if (pathl>.5*kBig || time>.5*kBig) continue;
if (wgt>0) wgt = 1./(wgt*wgt);
else continue;
wgt_sum += wgt;
wx2 += wgt*pathl*pathl;
wx += wgt*pathl;
wxy += wgt*pathl*time;
wy += wgt*time;
ncnt++;
}
Double_t beta = kBig;
Double_t dbeta = kBig;
Double_t time = kBig;
Double_t dt = kBig;
Double_t delta = wgt_sum*wx2-wx*wx;
if (delta != 0.) {
time = (wx2*wy-wx*wxy)/delta;
dt = TMath::Sqrt(wx2/delta);
Double_t invbeta = (wgt_sum*wxy-wx*wy)/delta;
if (invbeta != 0.) {
#if ROOT_VERSION_CODE >= ROOT_VERSION(3,4,0)
Double_t c = TMath::C();
#else
Double_t c = 2.99792458e8;
#endif
beta = 1./(c*invbeta);
dbeta = TMath::Sqrt(wgt_sum/delta)/(c*invbeta*invbeta);
}
}
track->SetBeta(beta);
track->SetdBeta(dbeta);
track->SetTime(time);
track->SetdTime(dt);
}
#endif
return 0;
}
//_____________________________________________________________________________
ClassImp(THcHallCSpectrometer)