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
//*-- 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.
//
//
// Golden track using scin. Zafar Ahmed. August 19 2014
// Goldent track is moved to THcHallCSpectrometer::TrackCalc()
// if fSelUsingScin == 0 then golden track is calculated just
// like podd. i.e. it is the first track with minimum chi2/ndf
// with sorting ON
//
// if fSelUsingScin == 1 then golden track is calculetd just like
// engine/HTRACKING/h_select_best_track_using_scin.h. This method
// gives the best track with minimum value of chi2/ndf but with
// additional cuts on the tracks. These cuts are on dedx, beta
// and on energy.
//
//////////////////////////////////////////////////////////////////////////
#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 "THcShower.h"
#include <vector>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#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
delete [] fX2D; fX2D = NULL; // Ahmed
delete [] fY2D; fY2D = NULL; // Ahmed
delete [] f2XHits; f2XHits = NULL; // Ahmed
delete [] f2YHits; f2YHits = NULL; // Ahmed
}
//_____________________________________________________________________________
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<fMaxReconElements;i++) {
Stephen A. Wood
committed
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
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
fX2D = new Double_t [MAXHODHITS];
fY2D = new Double_t [MAXHODHITS];
f2XHits = new Int_t [16];
f2YHits = new Int_t [16];
// --------------- To get energy from THcShower ----------------------
const char* detector_name = "hod";
//THaApparatus* app = GetDetector();
THaDetector* det = GetDetector("hod");
// THaDetector* det = app->GetDetector( shower_detector_name );
if( !dynamic_cast<THcHodoscope*>(det) ) {
Error("THcHallCSpectrometer", "Cannot find hodoscope detector %s",
detector_name );
return fStatus = kInitError;
}
fHodo = static_cast<THcHodoscope*>(det); // fHodo is a membervariable
// fShower = static_cast<THcShower*>(det); // fShower is a membervariable
// --------------- To get energy from THcShower ----------------------
Stephen A. Wood
committed
// 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 },
{"thetacentral_offset", &fThetaCentralOffset, kDouble },
{"_oopcentral_offset", &fOopCentralOffset, kDouble },
{"pcentral_offset", &fPCentralOffset, kDouble },
{"pcentral", &fPCentral, kDouble },
{"theta_lab", &fTheta_lab, kDouble },
{"sel_using_scin", &fSelUsingScin, kInt, 0, 1},
{"sel_ndegreesmin", &fSelNDegreesMin, kDouble, 0, 1},
{"sel_dedx1min", &fSeldEdX1Min, kDouble, 0, 1},
{"sel_dedx1max", &fSeldEdX1Max, kDouble, 0, 1},
{"sel_betamin", &fSelBetaMin, kDouble, 0, 1},
{"sel_betamax", &fSelBetaMax, kDouble, 0, 1},
{"sel_etmin", &fSelEtMin, kDouble, 0, 1},
{"sel_etmax", &fSelEtMax, kDouble, 0, 1},
{"hodo_num_planes", &fNPlanes, kInt },
{"scin_2x_zpos", &fScin2XZpos, kDouble, 0, 1},
{"scin_2x_dzpos", &fScin2XdZpos, kDouble, 0, 1},
{"scin_2y_zpos", &fScin2YZpos, kDouble, 0, 1},
{"scin_2y_dzpos", &fScin2YdZpos, kDouble, 0, 1},
Stephen A. Wood
committed
{0}
};
gHcParms->LoadParmValues((DBRequest*)&list,prefix);
cout << " fPcentral = " << fPCentral << " " <<fPCentralOffset << endl;
cout << " fThate_lab = " << fTheta_lab << " " <<fThetaCentralOffset << endl;
fPCentral= fPCentral*(1.+fPCentralOffset/100.);
// Check that these offsets are in radians
fTheta_lab=fTheta_lab + fThetaCentralOffset*TMath::RadToDeg();
Double_t ph = 0.0+fPhiOffset*TMath::RadToDeg();
SetCentralAngles(fTheta_lab, ph, false);
Double_t off_x = 0.0, off_y = 0.0, off_z = 0.0;
fPointingOffset.SetXYZ( off_x, off_y, off_z );
Stephen A. Wood
committed
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();
Stephen A. Wood
committed
}
// 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();
Stephen A. Wood
committed
fNReconTerms = 0;
//cout << "Reading matrix elements" << endl;
Stephen A. Wood
committed
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?
}
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();
}
cout << "Read " << fNReconTerms << " matrix element terms" << endl;
Stephen A. Wood
committed
if(!good) {
Error(here, "Error processing reconstruction coefficient file %s",reconCoeffFilename.c_str());
Stephen A. Wood
committed
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.
Stephen A. Wood
committed
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
352
353
354
355
356
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));
// ------------------ Moving it to TrackCalc --------------------
/*
// 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;
*/
// ------------------ Moving it to TrackCalc --------------------
return 0;
}
//_____________________________________________________________________________
Int_t THcHallCSpectrometer::TrackCalc()
{
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
if ( fSelUsingScin == 0 ) {
if( GetTrSorting() )
fTracks->Sort();
// Find the "Golden Track".
// if( GetNTracks() > 0 ) {
if( fNtracks > 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;
}
if ( fSelUsingScin == 1 ){
if( fNtracks > 0 ) {
Double_t fY2Dmin, fX2Dmin, fZap, ft, fChi2PerDeg; //, fShowerEnergy;
Double_t fHitPos4, fHitPos3, fHitDist3, fHitDist4; //, fChi2Min;
Int_t i, j, itrack, ip, ihit; //, fGoodTimeIndex = -1;
fChi2Min = 10000000000.0; fGoodTrack = -1; fY2Dmin = 100.;
fX2Dmin = 100.; fZap = 0.;
for ( itrack = 0; itrack < fNtracks; itrack++ ){
THaTrack* goodTrack = static_cast<THaTrack*>( fTracks->At(itrack) );
if ( goodTrack->GetNDoF() > fSelNDegreesMin ){
fChi2PerDeg = goodTrack->GetChi2() / goodTrack->GetNDoF();
if( ( goodTrack->GetDedx() > fSeldEdX1Min ) &&
( goodTrack->GetDedx() < fSeldEdX1Max ) &&
( goodTrack->GetBeta() > fSelBetaMin ) &&
( goodTrack->GetBeta() < fSelBetaMax ) &&
( goodTrack->GetEnergy() > fSelEtMin ) &&
( goodTrack->GetEnergy() < fSelEtMax ) )
{
for ( j = 0; j < fHodo->GetNPaddles(2); j++ ){
for ( ip = 0; ip < fNPlanes; ip++ ){
for ( ihit = 0; ihit < fHodo->GetNScinHits(ip); ihit++ ){
fRawIndex ++;
// fGoodRawPad = fHodo->GetGoodRawPad(fRawIndex)-1;
fGoodRawPad = fHodo->GetGoodRawPad(fRawIndex);
if ( ip == 2 ){
f2XHits[fGoodRawPad] = 0;
}
if ( ip == 3 ){
f2YHits[fGoodRawPad] = 0;
}
fHitPos4 = goodTrack->GetY() + goodTrack->GetPhi() * ( fScin2YZpos + 0.5 * fScin2YdZpos );
fHitCnt4 = TMath::Nint( ( fHodo->GetPlaneCenter(3) - fHitPos4 ) / fHodo->GetPlaneSpacing(3) ) + 1;
fHitCnt4 = TMath::Max( TMath::Min(fHitCnt4, fHodo->GetNPaddles(3) ) , 1); // scin_2y_nr = 10
fHitDist4 = fHitPos4 - ( fHodo->GetPlaneCenter(3) - fHodo->GetPlaneSpacing(3) * ( fHitCnt4 - 1 ) );
//----------------------------------------------------------------
if ( fNtracks > 1 ){ // Plane 4
fZap = 0.;
ft = 0;
for ( i = 0; i < fHodo->GetNPaddles(3); i++ ){
if ( ft == 1 ) fZap = fY2D[itrack];
if ( ( ft == 2 ) && ( fY2D[itrack] < fZap ) ) fZap = fY2D[itrack];
if ( ( ft == 3 ) && ( fY2D[itrack] < fZap ) ) fZap = fY2D[itrack];
if ( ( ft == 4 ) && ( fY2D[itrack] < fZap ) ) fZap = fY2D[itrack];
if ( ( ft == 5 ) && ( fY2D[itrack] < fZap ) ) fZap = fY2D[itrack];
if ( ( ft == 6 ) && ( fY2D[itrack] < fZap ) ) fZap = fY2D[itrack];
} // condition for fHodScinHit[4][i]
} // loop over 10
fY2D[itrack] = fZap;
} // condition for track. Plane 4
if ( fNtracks == 1 ) fY2D[itrack] = 0.;
fHitPos3 = goodTrack->GetX() + goodTrack->GetTheta() * ( fScin2XZpos + 0.5 * fScin2XdZpos );
fHitCnt3 = TMath::Nint( ( fHitPos3 - fHodo->GetPlaneCenter(2) ) / fHodo->GetPlaneSpacing(2) ) + 1;
fHitCnt3 = TMath::Max( TMath::Min(fHitCnt3, fHodo->GetNPaddles(2) ) , 1); // scin_2x_nr = 16
fHitDist3 = fHitPos3 - ( fHodo->GetPlaneSpacing(2) * ( fHitCnt3 - 1 ) + fHodo->GetPlaneCenter(2) );
//----------------------------------------------------------------
for ( i = 0; i < fHodo->GetNPaddles(2); i++ ){
ft ++;
if ( ft == 1 ) fZap = fX2D[itrack];
if ( ( ft == 2 ) && ( fX2D[itrack] < fZap ) ) fZap = fX2D[itrack];
if ( ( ft == 3 ) && ( fX2D[itrack] < fZap ) ) fZap = fX2D[itrack];
if ( ( ft == 4 ) && ( fX2D[itrack] < fZap ) ) fZap = fX2D[itrack];
if ( ( ft == 5 ) && ( fX2D[itrack] < fZap ) ) fZap = fX2D[itrack];
if ( ( ft == 6 ) && ( fX2D[itrack] < fZap ) ) fZap = fX2D[itrack];
} // condition for fHodScinHit[4][i]
} // loop over 16
fX2D[itrack] = fZap;
} // condition for track. Plane 3
//----------------------------------------------------------------
if ( fNtracks == 1 )
fX2D[itrack] = 0.;
if ( fY2D[itrack] <= fY2Dmin ) {
if ( fY2D[itrack] < fY2Dmin ) {
fX2Dmin = 100.;
fChi2Min = 10000000000.;
} // fY2D min
if ( fX2D[itrack] <= fX2Dmin ){
if ( fX2D[itrack] < fX2Dmin ){
fChi2Min = 10000000000.0;
} // condition fX2D
if ( fChi2PerDeg < fChi2Min ){
fGoodTrack = itrack; // fGoodTrack = itrack
fY2Dmin = fY2D[itrack];
fX2Dmin = fX2D[itrack];
fChi2Min = fChi2PerDeg;
fGoldenTrack = static_cast<THaTrack*>( fTracks->At( fGoodTrack ) );
fTrkIfo = *fGoldenTrack;
fTrk = fGoldenTrack;
}
} // condition fX2D
} // condition fY2D
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
} // confition for fNFreeFP greater than fSelNDegreesMin
} // loop over tracks
if ( fGoodTrack == -1 ){
fChi2Min = 10000000000.0;
for (Int_t iitrack = 0; iitrack < fNtracks; iitrack++ ){
THaTrack* aTrack = dynamic_cast<THaTrack*>( fTracks->At(iitrack) );
if (!aTrack) return -1;
if ( aTrack->GetNDoF() > fSelNDegreesMin ){
fChi2PerDeg = aTrack->GetChi2() / aTrack->GetNDoF();
if ( fChi2PerDeg < fChi2Min ){
fGoodTrack = iitrack;
fChi2Min = fChi2PerDeg;
fGoldenTrack = static_cast<THaTrack*>( fTracks->At(fGoodTrack) );
fTrkIfo = *fGoldenTrack;
fTrk = fGoldenTrack;
}
}
} // loop over trakcs
} // Condition for fNtrack > 0
} else // condtion fSelUsingScin == 1
fGoldenTrack = NULL;
}
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).
return 0;
}
//_____________________________________________________________________________
Int_t THcHallCSpectrometer::ReadRunDatabase( const TDatime& date )
{
// Override THaSpectrometer with nop method. All needed kinamatics
// read in ReadDatabase.
return kOK;
}
//_____________________________________________________________________________
ClassImp(THcHallCSpectrometer)