- #include <algorithm>
-
- // Gaudi
- #include "GaudiKernel/PhysicalConstants.h"
-
- // Tb/TbKernel
- #include "TbKernel/TbFunctors.h"
-
- // Local
- #include "TbAlignmentMinuit2.h"
-
- DECLARE_TOOL_FACTORY(TbAlignmentMinuit2)
-
- //=============================================================================
- // Standard constructor, initializes variables
- //=============================================================================
- TbAlignmentMinuit2::TbAlignmentMinuit2(const std::string& type,
- const std::string& name,
- const IInterface* parent)
- : TbAlignmentMinuitBase(type, name, parent) {
-
- declareProperty("ClusterLocation",
- m_clusterLocation = LHCb::TbClusterLocation::Default);
- declareProperty("DeviceToAlign", m_deviceToAlign = 999);
- declareProperty("IsDUT", m_isDUT = true);
- declareProperty("RefitTracks", m_refitTracks = false);
- declareProperty("TimeWindow", m_twindow = 200. * Gaudi::Units::ns);
- declareProperty("XWindow", m_xwindow = 1. * Gaudi::Units::mm);
- declareProperty("IgnoreEdge",m_ignoreEdge=1);
- m_dofsDefault = {true, true, true, true, true, true};
- }
-
- //=============================================================================
- // Destructor
- //=============================================================================
- TbAlignmentMinuit2::~TbAlignmentMinuit2() {}
-
- //=============================================================================
- // Collect the tracks and clusters to be used for the alignment.
- //=============================================================================
- StatusCode TbAlignmentMinuit2::execute(
- std::vector<TbAlignmentTrack*>& alignmentTracks) {
-
- // Grab the tracks.
- LHCb::TbTracks* tracks = getIfExists<LHCb::TbTracks>(m_trackLocation);
- if (!tracks) {
- return Error("No tracks in " + m_trackLocation);
- }
- if (!m_isDUT) {
- // We want to align a plane which is included in the pattern recognition.
- for (LHCb::TbTrack* track : *tracks) {
- // Skip low-quality tracks.
- if (track->chi2() > m_maxChi2) continue;
- // Add a new alignment track (cloning track and clusters) to the store.
- alignmentTracks.emplace_back(new TbAlignmentTrack(track));
- }
- return StatusCode::SUCCESS;
- }
- // We want to align a plane which is not included in the pattern recognition.
- if (m_twindow < 0. && m_xwindow < 0.) {
- // Use the clusters which have been associated to the track.
- for (LHCb::TbTrack* track : *tracks) {
- // Skip low-quality tracks.
- if (track->chi2() > m_maxChi2) continue;
- auto clusters = track->associatedClusters();
- for (auto it = clusters.begin(), end = clusters.end(); it != end; ++it) {
- if ((*it)->plane() != m_deviceToAlign) continue;
- // Create a new alignment track (cloning the track).
- TbAlignmentTrack* alignmentTrack = new TbAlignmentTrack(track);
- // Clone the cluster and add it to the alignment track.
- LHCb::TbCluster* alignmentCluster = (*it)->clone();
- alignmentTrack->track()->addToAssociatedClusters(alignmentCluster);
- alignmentTrack->addToClusters(alignmentCluster);
- // Add the alignment track to the store.
- alignmentTracks.push_back(alignmentTrack);
- // Stop after the first valid cluster.
- break;
- }
- }
- return StatusCode::SUCCESS;
- }
- // We need to associate DUT clusters to the track.
- // Grab the clusters on the device to align.
- const std::string clusterLocation = m_clusterLocation + std::to_string(m_deviceToAlign);
- LHCb::TbClusters* clusters = getIfExists<LHCb::TbClusters>(clusterLocation);
- if (!clusters) {
- return Error("No clusters in " + clusterLocation);
- }
- unsigned int edgeRejected(0), spaceRejected(0);
-
- for (LHCb::TbTrack* track : *tracks) {
- // Skip low-quality tracks.
- if (track->chi2PerNdof() > m_maxChi2) continue;
- // Calculate the track intercept on the device to align.
- const auto pGlobal = geomSvc()->intercept(track, m_deviceToAlign);
- const auto pLocal = geomSvc()->globalToLocal(pGlobal, m_deviceToAlign);
- // Calculate the time window.
- const double tMin = track->htime() - m_twindow;
- const double tMax = track->htime() + m_twindow;
- // Get the first cluster within the time window.
- LHCb::TbClusters::iterator end = clusters->end();
- LHCb::TbClusters::iterator begin = std::lower_bound(
- clusters->begin(), end, tMin, lowerBound<const LHCb::TbCluster*>());
- if (begin == clusters->end()) continue;
- // Loop over the clusters.
- for (LHCb::TbClusters::iterator it = begin; it != end; ++it) {
- // Stop when outside the time window.
- if ((*it)->htime() > tMax) break;
- // Skip clusters too far away from the track intercept.
- const double dx = (*it)->xloc() - pLocal.x();
- const double dy = (*it)->yloc() - pLocal.y();
- if (fabs(dx) > m_xwindow || fabs(dy) > m_xwindow){ spaceRejected++; continue; }
- // Skip clusters close to the edge of the sensor.
- if (isEdge(*it) && m_ignoreEdge ){edgeRejected++; continue;}
- // Create a new alignment track (cloning the track).
- TbAlignmentTrack* alignmentTrack = new TbAlignmentTrack(track);
- // Clone the cluster and add it to the alignment track.
- LHCb::TbCluster* alignmentCluster = (*it)->clone();
- alignmentTrack->track()->addToAssociatedClusters(alignmentCluster);
- alignmentTrack->addToClusters(alignmentCluster);
- // Add the alignment track to the store.
- alignmentTracks.push_back(alignmentTrack);
- // Stop after the first valid cluster.
- break;
- }
- }
- //info() << edgeRejected << " " << spaceRejected << " " << tracks->size() << endmsg;
-
- return StatusCode::SUCCESS;
- }
-
- //=============================================================================
- // Calculate the chi2.
- //=============================================================================
- void TbAlignmentMinuit2::chi2(double& f, double* par, double* /*g*/) {
-
- const unsigned int offset = m_deviceToAlign * 6;
- // Check the z-position.
- const double z = m_modules[m_deviceToAlign]->z() + par[offset + 2];
- if (m_deviceToAlign > 0) {
- if (z <= m_modules[m_deviceToAlign - 1]->z()) {
- info() << "Z is below limit!" << endmsg;
- f = std::numeric_limits<double>::max();
- return;
- }
- }
- if (m_deviceToAlign < m_nPlanes - 1) {
- if (z >= m_modules[m_deviceToAlign + 1]->z()) {
- info() << "Z is above limit!" << endmsg;
- f = std::numeric_limits<double>::max();
- return;
- }
- }
-
- m_modules[m_deviceToAlign]->setAlignment(par[offset + 0], par[offset + 1],
- par[offset + 2], par[offset + 3],
- par[offset + 4], par[offset + 5]);
- // Loop over the alignment tracks.
- f = 0.;
- for (auto it = m_tracks.begin(), end = m_tracks.end(); it != end; ++it) {
- // Form residuals with all clusters selected for alignment
- auto clusters = (*it)->clusters();
- for (auto ic = clusters.cbegin(), end = clusters.cend(); ic != end; ++ic) {
- if ((*ic)->plane() != m_deviceToAlign) continue;
- Gaudi::XYZPoint point = geomSvc()->localToGlobal(
- Gaudi::XYZPoint((*ic)->xloc(), (*ic)->yloc(), 0), m_deviceToAlign);
- Gaudi::XYZPoint intercept =
- geomSvc()->intercept((*it)->track(), m_deviceToAlign);
- // TODO: why not the local residual?
- const double xresidual = point.x() - intercept.x();
- // const double xresidual = (*ic)->xloc() - intercept.x();
- const double yresidual = point.y() - intercept.y();
- // const double yresidual = (*ic)->yloc() - intercept.y();
- f += xresidual * xresidual + yresidual * yresidual;
- }
- }
- }
-
- //=============================================================================
- // Main alignment function.
- //=============================================================================
- void TbAlignmentMinuit2::align(
- std::vector<TbAlignmentTrack*>& alignmentTracks) {
-
- TbAlignmentMinuitBase::align(alignmentTracks);
- info() << "Minuit technique 2. Aligning plane " << m_deviceToAlign << endmsg;
- for (unsigned int i = 0; i < m_nPlanes; ++i) {
- if (masked(i) || i == m_deviceToAlign)
- m_trackFit->maskPlane(i);
- else
- m_trackFit->unmaskPlane(i);
- }
-
- for (auto alignmentTrack : m_tracks) m_trackFit->fit(alignmentTrack->track());
-
- for (unsigned int iteration = 0; iteration < m_nIterations; ++iteration) {
- info() << "Iteration " << iteration + 1 << "/" << m_nIterations << endmsg;
- // Loop over detector modules
- for (unsigned int i = 0; i < m_nPlanes; ++i) {
- const unsigned int offset = 6 * i;
- if (i == m_deviceToAlign) {
- info() << "*** Wobbling detector " << i << endmsg;
- for (unsigned int j = 0; j < 6; ++j) {
- if (m_dofs[j]) {
- m_fitter->ReleaseParameter(offset + j);
- } else {
- m_fitter->FixParameter(offset + j);
- }
- }
- } else {
- m_fitter->FixParameter(offset + 0); // x
- m_fitter->FixParameter(offset + 1); // y
- m_fitter->FixParameter(offset + 2); // z
- m_fitter->FixParameter(offset + 3); // Rx
- m_fitter->FixParameter(offset + 4); // Ry
- m_fitter->FixParameter(offset + 5); // Rz
- }
- }
- // Execute minimization and calculate proper error matrix
- double arglist[2];
- arglist[0] = 10000;
- arglist[1] = 1.e-2;
- m_fitter->ExecuteCommand("MIGRAD", arglist, 2);
- m_fitter->ExecuteCommand("HESSE", arglist, 1);
- if (msgLevel(MSG::INFO)) m_fitter->ExecuteCommand("SHOW PARAMETERS", 0, 0);
-
- updateGeometry();
- }
-
- if (m_refitTracks) {
- for (unsigned int i = 0; i < m_nPlanes; ++i) {
- if (masked(i))
- m_trackFit->maskPlane(i);
- else
- m_trackFit->unmaskPlane(i);
- }
- for (auto it : m_tracks) m_trackFit->fit(it->track());
- }
- }