9#include <reconstruction/modules/VXDDedxPID/VXDDedxPIDModule.h>
10#include <reconstruction/modules/VXDDedxPID/HelixHelper.h>
12#include <framework/gearbox/Const.h>
14#include <vxd/geometry/GeoCache.h>
16#include <genfit/MaterialEffects.h>
18#include <Math/VectorUtil.h>
36 setDescription(
"Extract dE/dx and corresponding log-likelihood from fitted tracks and hits in the SVD and PXD.");
40 "Use individual hits (true) or truncated mean (false) to determine likelihoods",
false);
42 "For MC only: if true, only save data for primary particles (as determined by MC truth)",
false);
43 addParam(
"usePXD",
m_usePXD,
"Use PXDClusters for dE/dx calculation",
false);
46 "Use a faster helix parametrisation, with corrections as soon as the approximation is more than ... cm off.",
double(4.0));
57 if (not
m_PXDDedxPDFs) B2FATAL(
"No PXD dE/dx PDF's available");
59 if (not ok) B2FATAL(
"Binning or ranges of PXD dE/dx PDF's differ");
62 if (not
m_SVDDedxPDFs) B2FATAL(
"No SVD Dedx PDF's available");
64 if (not ok) B2FATAL(
"Binning or ranges of SVD dE/dx PDF's differ");
104 if (!genfit::MaterialEffects::getInstance()->isInitialized()) {
105 B2FATAL(
"Need to have SetupGenfitExtrapolationModule in path before this one.");
131 for (
const auto& track :
m_tracks) {
134 std::shared_ptr<VXDDedxTrack> dedxTrack = std::make_shared<VXDDedxTrack>();
142 B2WARNING(
"No related fit for track ...");
146 if (numMCParticles != 0) {
158 dedxTrack->m_motherPDG = mother ? mother->
getPDG() : 0;
160 const ROOT::Math::XYZVector trueMomentum = mcpart->
getMomentum();
161 dedxTrack->m_pTrue = trueMomentum.R();
166 const ROOT::Math::XYZVector& trackPos = fitResult->
getPosition();
167 const ROOT::Math::XYZVector& trackMom = fitResult->
getMomentum();
168 dedxTrack->m_p = trackMom.R();
169 dedxTrack->m_cosTheta = cos(trackMom.Theta());
175 B2WARNING(
"No related track for this fit...");
183 B2ERROR(
"GFTrack is pruned, please run VXDDedxPID only on unpruned tracks! Skipping this track.");
190 const HelixHelper helixAtOrigin(trackPos, trackMom, dedxTrack->m_charge);
193 const std::vector<PXDCluster*>& pxdClusters = recoTrack->
getPXDHitList();
194 saveSiHits(dedxTrack.get(), helixAtOrigin, pxdClusters);
198 const std::vector<SVDCluster*>& svdClusters = recoTrack->
getSVDHitList();
199 saveSiHits(dedxTrack.get(), helixAtOrigin, svdClusters);
202 if (dedxTrack->dedx.empty()) {
203 B2DEBUG(50,
"Found track with no hits, ignoring.");
208 const int numDedx = dedxTrack->dedx.size();
209 dedxTrack->m_nHits = numDedx;
211 dedxTrack->m_nHitsUsed = numDedx - 2;
214 dedxTrack->clearLogLikelihoods();
216 if (
m_usePXD) dedxTrack->addLogLikelihoods(
m_PXDDedxPDFs->getPDFs(truncated), Dedx::c_PXD, truncated);
217 if (
m_useSVD) dedxTrack->addLogLikelihoods(
m_SVDDedxPDFs->getPDFs(truncated), Dedx::c_SVD, truncated);
220 if (dedxTrack->areLogLikelihoodsAvailable()) {
222 track.addRelationTo(likelihoodObj);
227 track.addRelationTo(newVXDDedxTrack);
235 B2DEBUG(50,
"VXDDedxPIDModule exiting after processing " <<
m_trackID <<
236 " tracks in " <<
m_eventID + 1 <<
" events.");
242 const std::vector<double>& dedx)
const
245 std::vector<double> sortedDedx = dedx;
246 std::sort(sortedDedx.begin(), sortedDedx.end());
248 double truncatedMeanTmp = 0.0;
249 double meanTmp = 0.0;
250 double sumOfSquares = 0.0;
251 const int numDedx = sortedDedx.size();
254 for (
int i = 0; i < numDedx; i++) {
255 meanTmp += sortedDedx[i];
261 for (
int i = 0; i < numDedx - 2; i++) {
262 truncatedMeanTmp += sortedDedx[i];
263 sumOfSquares += sortedDedx[i] * sortedDedx[i];
265 if (numDedx - 2 != 0) {
266 truncatedMeanTmp /= numDedx - 2;
270 truncatedMean = truncatedMeanTmp;
272 if (numDedx - 2 > 1) {
273 truncatedMeanErr =
sqrt(sumOfSquares /
double(numDedx - 2) - truncatedMeanTmp * truncatedMeanTmp) / double((numDedx - 2) - 1);
275 truncatedMeanErr = 0;
284 const ROOT::Math::XYZVector localPos(hit->getU(), hit->getV(), 0.0);
285 const ROOT::Math::XYZVector& globalPos = sensor.pointToGlobal(localPos);
288 const ROOT::Math::XYZVector& sensorNormal = sensor.vectorToGlobal(ROOT::Math::XYZVector(0.0, 0.0, 1.0));
289 const double angle = ROOT::Math::VectorUtil::Angle(sensorNormal, localMomentum);
292 return TMath::Min(sensor.getWidth(), sensor.getThickness() / fabs(cos(angle)));
301 ROOT::Math::XYZVector a, b;
302 if (hit->isUCluster()) {
303 const double u = hit->getPosition();
304 a = sensor.pointToGlobal(ROOT::Math::XYZVector(sensor.getBackwardWidth() / sensor.getWidth(0) * u, -0.5 * sensor.getLength(), 0.0));
305 b = sensor.pointToGlobal(ROOT::Math::XYZVector(sensor.getForwardWidth() / sensor.getWidth(0) * u, +0.5 * sensor.getLength(), 0.0));
307 const double v = hit->getPosition();
308 a = sensor.pointToGlobal(ROOT::Math::XYZVector(-0.5 * sensor.getWidth(v), v, 0.0));
309 b = sensor.pointToGlobal(ROOT::Math::XYZVector(+0.5 * sensor.getWidth(v), v, 0.0));
311 const double pathLength = helix->
pathLengthToLine(ROOT::Math::XYZVector(a), ROOT::Math::XYZVector(b));
312 const ROOT::Math::XYZVector& localMomentum = helix->
momentum(pathLength);
314 const ROOT::Math::XYZVector& sensorNormal = sensor.vectorToGlobal(ROOT::Math::XYZVector(0.0, 0.0, 1.0));
315 const double angle = ROOT::Math::VectorUtil::Angle(sensorNormal, localMomentum);
317 return TMath::Min(sensor.getWidth(), sensor.getThickness() / fabs(cos(angle)));
322 const std::vector<HitClass*>& hits)
const
324 const int numHits = hits.size();
334 assert(currentDetector == 0 or currentDetector == 1);
336 std::vector<double> siliconDedx;
337 siliconDedx.reserve(numHits);
340 for (
int i = 0; i < numHits; i++) {
341 const HitClass* hit = hits[i];
343 B2ERROR(
"Added hit is a null pointer!");
346 const VxdID& currentSensor = hit->getSensorID();
348 assert(layer >= -6 && layer < 0);
353 const double charge = hit->getCharge();
354 const double dedx = charge / totalDistance;
356 B2WARNING(
"dE/dx is " << dedx <<
" in layer " << layer);
357 }
else if (i == 0 or prevSensor != currentSensor) {
358 prevSensor = currentSensor;
360 siliconDedx.push_back(dedx);
361 track->m_dedxAvg[currentDetector] += dedx;
362 track->addDedx(layer, totalDistance, dedx);
365 track->addHit(currentSensor, layer, charge, totalDistance, dedx);
370 track->m_dedxAvgTruncated[currentDetector],
371 track->m_dedxAvgTruncatedErr[currentDetector],
static const ChargedStable pion
charged pion particle
Helper class representing a helical track.
double pathLengthToPoint(const ROOT::Math::XYZVector &p) const
returns the path length (along the helix) to the helix point closest to p.
ROOT::Math::XYZVector momentum(double s=0) const
momentum of the particle, at the helix point corresponding to a flown path length s (from poca).
double pathLengthToLine(const ROOT::Math::XYZVector &a, const ROOT::Math::XYZVector &b) const
returns the path length (along the helix) to the helix point closest to the line going through points...
A Class to store the Monte Carlo particle information.
@ c_PrimaryParticle
bit 0: Particle is primary particle.
bool hasStatus(unsigned short int bitmask) const
Return if specific status bit is set.
int m_pdg
PDG-Code of the particle.
int getPDG() const
Return PDG code of particle.
ROOT::Math::XYZVector getMomentum() const
Return momentum.
void setDescription(const std::string &description)
Sets the description of the module.
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
The PXD Cluster class This class stores all information about reconstructed PXD clusters The position...
This is the Reconstruction Event-Data Model Track.
std::vector< Belle2::RecoTrack::UsedPXDHit * > getPXDHitList() const
Return an unsorted list of pxd hits.
std::vector< Belle2::RecoTrack::UsedSVDHit * > getSVDHitList() const
Return an unsorted list of svd hits.
bool hasTrackFitStatus(const genfit::AbsTrackRep *representation=nullptr) const
Check, if there is a fit status for the given representation or for the cardinal one.
const genfit::FitStatus * getTrackFitStatus(const genfit::AbsTrackRep *representation=nullptr) const
Return the track fit status for the given representation or for the cardinal one. You are not allowed...
The SVD Cluster class This class stores all information about reconstructed SVD clusters.
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
bool isOptional(const std::string &name="")
Tell the DataStore about an optional input.
int getEntries() const
Get the number of objects in the array.
Values of the result of a track fit with a given particle hypothesis.
short getChargeSign() const
Return track charge (1 or -1).
ROOT::Math::XYZVector getMomentum() const
Getter for vector of momentum at closest approach of track in r/phi projection.
ROOT::Math::XYZVector getPosition() const
Getter for vector of position at closest approach of track in r/phi projection.
Container for likelihoods obtained by the VXD dE/dx PID (VXDDedxPIDModule).
DBObjPtr< SVDdEdxPDFs > m_SVDDedxPDFs
SVD DB object for dedx vs.
void calculateMeans(double &mean, double &truncatedMean, double &truncatedMeanErr, const std::vector< double > &dedx) const
Save arithmetic and truncated mean for the 'dedx' values.
int m_trackID
counter for tracks in this event
virtual void initialize() override
Initialize the module.
StoreArray< SVDCluster > m_svdClusters
Optional array of SVDClusters.
bool m_usePXD
use PXD data for likelihood
virtual void event() override
This method is called for each event.
StoreArray< MCParticle > m_mcparticles
Optional array of MCParticles.
StoreArray< VXDDedxLikelihood > m_dedxLikelihoods
Output array of VXDDedxLikelihoods.
void checkPDFs()
Check the pdfs for consistency every time they change in the database.
virtual void terminate() override
End of the event processing.
void saveSiHits(VXDDedxTrack *track, const HelixHelper &helix, const std::vector< HitClass * > &hits) const
save energy loss and hit information from SVD/PXDHits to track
DBObjPtr< PXDdEdxPDFs > m_PXDDedxPDFs
PXD DB object for dedx vs.
StoreArray< VXDDedxTrack > m_dedxTracks
Output array of VXDDedxTracks.
virtual ~VXDDedxPIDModule()
Destructor.
int m_eventID
counter for events
bool m_useSVD
use SVD data for likelihood
StoreArray< Track > m_tracks
Required array of Tracks.
bool m_onlyPrimaryParticles
For MC only: if true, only save data for primary particles (as determined by MC truth)
StoreArray< PXDCluster > m_pxdClusters
Optional array of PXDClusters.
static double getTraversedLength(const PXDCluster *hit, const HelixHelper *helix)
returns traversed length through active medium of given PXDCluster.
StoreArray< RecoTrack > m_recoTracks
Required array of RecoTracks.
bool m_useIndividualHits
use individual hits (true) or truncated mean (false) to determine likelihoods
VXDDedxPIDModule()
Default constructor.
double m_trackDistanceThreshhold
track distance threshold
Debug output for VXDDedxPID module.
Class to facilitate easy access to sensor information of the VXD like coordinate transformations or p...
const SensorInfoBase & getSensorInfo(Belle2::VxdID id) const
Return a reference to the SensorInfo of a given SensorID.
static GeoCache & getInstance()
Return a reference to the singleton instance.
Base class to provide Sensor Information for PXD and SVD.
SensorType getType() const
Return the Type of the Sensor.
Class to uniquely identify a any structure of the PXD and SVD.
baseType getLayerNumber() const
Get the layer id.
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
double sqrt(double a)
sqrt for double
MCParticle * getMother() const
Returns a pointer to the mother particle.
Abstract base class for different kinds of events.