forked from KFTrack/KinKal
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathScintHit.hh
More file actions
132 lines (123 loc) · 6.03 KB
/
Copy pathScintHit.hh
File metadata and controls
132 lines (123 loc) · 6.03 KB
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#ifndef KinKal_ScintHit_hh
#define KinKal_ScintHit_hh
//
// simple hit subclass representing a time measurement using scintillator light from a crystal or plastic scintillator
//
#include "KinKal/Detector/ResidualHit.hh"
#include "KinKal/Trajectory/SensorLine.hh"
#include "KinKal/Trajectory/PiecewiseClosestApproach.hh"
#include <stdexcept>
namespace KinKal {
template <class KTRAJ> class ScintHit : public ResidualHit<KTRAJ> {
public:
using PTRAJ = ParticleTrajectory<KTRAJ>;
using PCA = PiecewiseClosestApproach<KTRAJ,SensorLine>;
using CA = ClosestApproach<KTRAJ,SensorLine>;
using RESIDHIT = ResidualHit<KTRAJ>;
using HIT = Hit<KTRAJ>;
using KTRAJPTR = std::shared_ptr<KTRAJ>;
// copy constructor
ScintHit(ScintHit<KTRAJ> const& rhs):
ResidualHit<KTRAJ>(rhs),
saxis_(rhs.sensorAxis()),
tvar_(rhs.timeVariance()),
wvar_(rhs.widthVariance()),
tpca_(
rhs.closestApproach().particleTraj(),
saxis_,
rhs.closestApproach().hint(),
rhs.closestApproach().precision()
),
rresid_(rhs.refResidual()){
/**/
};
// clone op for reinstantiation
std::shared_ptr< Hit<KTRAJ> > clone(CloneContext& context) const override{
auto rv = std::make_shared< ScintHit<KTRAJ> >(*this);
auto ca = rv->closestApproach();
auto trajectory = std::make_shared<KTRAJ>(ca.particleTraj());
ca.setTrajectory(trajectory);
rv->setClosestApproach(ca);
return rv;
};
// ResidualHit interface implementation
unsigned nResid() const override { return 1; } // 1 time residual
Residual const& refResidual(unsigned ires=0) const override;
double time() const override { return tpca_.particleToca(); }
void updateReference(PTRAJ const& ptraj) override;
KTRAJPTR const& refTrajPtr() const override { return tpca_.particleTrajPtr(); }
void updateState(MetaIterConfig const& config,bool first) override;
void print(std::ostream& ost=std::cout,int detail=0) const override;
// scintHit explicit interface
ScintHit(PCA const& pca, double tvar, double wvar);
virtual ~ScintHit(){}
// the line encapsulates both the measurement value (through t0), and the light propagation model (through the velocity)
auto const& sensorAxis() const { return saxis_; }
auto const& closestApproach() const { return tpca_; }
double timeVariance() const { return tvar_; }
double widthVariance() const { return wvar_; }
auto precision() const { return tpca_.precision(); }
private:
SensorLine saxis_; // symmetry axis of this sensor
double tvar_; // variance in the time measurement: assumed independent of propagation distance/time
double wvar_; // variance in transverse position of the sensor/measurement in mm. Assumes cylindrical error, could be more general
CA tpca_; // reference time and position of closest approach to the axis
Residual rresid_; // residual WRT most recent reference parameters
// modifiers to support cloning
void setClosestApproach(const CA& ca){ tpca_ = ca; }
};
template <class KTRAJ> ScintHit<KTRAJ>::ScintHit(PCA const& pca, double tvar, double wvar) :
saxis_(pca.sensorTraj()), tvar_(tvar), wvar_(wvar),
tpca_(pca.localTraj(),saxis_,pca.precision(),pca.tpData(),pca.dDdP(),pca.dTdP())
{}
template <class KTRAJ> Residual const& ScintHit<KTRAJ>::refResidual(unsigned ires) const {
if(ires !=0)throw std::invalid_argument("Invalid residual");
return rresid_;
}
template <class KTRAJ> void ScintHit<KTRAJ>::updateReference(PTRAJ const& ptraj) {
// use previous hint, or initialize from the sensor time
CAHint tphint = tpca_.usable() ? tpca_.hint() : CAHint(saxis_.measurementTime(), saxis_.measurementTime());
PCA pca(ptraj,saxis_,tphint,precision());
tpca_ = pca.localClosestApproach();
if(!tpca_.usable())throw std::runtime_error("ScintHit TPOCA failure");
}
template <class KTRAJ> void ScintHit<KTRAJ>::updateState(MetaIterConfig const& config,bool first) {
// check that TPCA position is consistent with the physical sensor. This can be off if the CA algorithm finds the wrong helix branch
// early in the fit when t0 has very large errors.
// If it is unphysical try to adjust it back using a better hint.
auto ppos = tpca_.particlePoca().Vect();
auto const& sstart = saxis_.start();
auto const& send = saxis_.end();
// tolerance should come from the config. Should also test relative to the error. FIXME
double tol = saxis_.length()*1.0;
double sdist = (ppos - saxis_.middle()).Dot(saxis_.direction());
if( (ppos-sstart).Dot(saxis_.direction()) < -tol || (ppos-send).Dot(saxis_.direction()) > tol) {
// adjust hint to the middle and try agian
double sspeed = tpca_.particleTraj().velocity(tpca_.particleToca()).Dot(saxis_.direction());
auto tphint = tpca_.hint();
tphint.particleToca_ -= sdist/sspeed;
tpca_ = CA(tpca_.particleTrajPtr(),saxis_,tphint,precision());
// should check if this is still unphysical and disable the hit if so FIXME
sdist = (tpca_.particlePoca().Vect() - saxis_.middle()).Dot(saxis_.direction());
}
// residual is just delta-T at CA.
// the variance includes the measurement variance and the tranvserse size (which couples to the relative direction)
// Might want to do more updating (set activity) based on DOCA in future: TODO
double dd2 = tpca_.dirDot()*tpca_.dirDot();
double totvar = tvar_ + wvar_*dd2/(saxis_.speed(sdist)*saxis_.speed(sdist)*(1.0-dd2));
rresid_ = Residual(tpca_.deltaT(),totvar,0.0,tpca_.dTdP());
this->updateWeight(config);
}
template<class KTRAJ> void ScintHit<KTRAJ>::print(std::ostream& ost, int detail) const {
if(this->active())
ost<<"Active ";
else
ost<<"Inactive ";
ost << " ScintHit tvar " << tvar_ << " wvar " << wvar_ << std::endl;
if(detail > 0){
ost << "Line ";
saxis_.print(ost,detail);
}
}
}
#endif