214 legacy.
PVres = 8.88f;
216 const auto barrel = makeKernelParameters(legacy, SurfaceKind::Cylinder);
217 BOOST_CHECK_CLOSE(barrel.trackletMinPt, 1.11f, 1e-6);
218 BOOST_CHECK_CLOSE(barrel.nSigmaCut, 3.33f, 1e-6);
219 BOOST_CHECK_CLOSE(barrel.maxChi2ClusterAttachment, 4.44f, 1e-6);
220 BOOST_CHECK_CLOSE(barrel.maxChi2NDF, 5.55f, 1e-6);
221 BOOST_CHECK_CLOSE(barrel.pvResolution, 8.88f, 1e-6);
224 const auto disk = makeKernelParameters(legacy, SurfaceKind::Disk);
225 BOOST_CHECK_CLOSE(disk.trackletMinPt, 1.11f, 1e-6);
226 BOOST_CHECK_CLOSE(disk.nSigmaCut, 3.33f, 1e-6);
227 BOOST_CHECK_CLOSE(disk.maxChi2ClusterAttachment, 4.44f, 1e-6);
228 BOOST_CHECK_CLOSE(disk.maxChi2NDF, 5.55f, 1e-6);
236 const auto params = makeKernelParameters(legacy, SurfaceKind::Cylinder);
237 BOOST_REQUIRE(
params.isValid());
240 configureCylinderIndex(indexUtils, legacy);
242 const auto source = makeGlobalCluster(2.f, 0.f, 0.5f);
243 const auto sourceMeasurement = makeMeasurement(
source);
244 const auto vertex = makeVertex(0.f, 0.f, 0.f, 1.e-4f, 1.e-4f, 4.e-4f, 4);
245 const auto state = makeCylinderProjectionCache(0, 3, 2.f, 4.f, 3.8f, 4.2f, 5.e-4f, 2.e-3f, 0.08f);
248 BOOST_REQUIRE((projectCylinderSearchWindow(
252 const float targetMeanRadius = 0.5f * (
state.targetMinR +
state.targetMaxR);
253 const float deltaRadius = targetMeanRadius -
source.radius;
254 const float zAtTargetMeanR = tanLambda * deltaRadius +
source.z;
255 const float projectionScale = 1.f + deltaRadius /
source.radius;
256 const float originScale = projectionScale - 1.f;
257 const float sourceCoordinateVariance = o2::its::math_utils::Sq(
state.sourcePositionResolution);
258 const float varianceZ =
259 o2::its::math_utils::Sq(projectionScale) * sourceCoordinateVariance +
260 o2::its::math_utils::Sq(tanLambda * projectionScale) * sourceCoordinateVariance +
261 o2::its::math_utils::Sq(originScale) *
vertex.getSigmaZ2() +
262 o2::its::math_utils::Sq(deltaRadius *
state.edgeMSAngle);
263 const auto predictionAndVarianceAt = [&](
float radius) {
264 const float deltaR = radius -
source.radius;
265 const float scale = 1.f + deltaR /
source.radius;
266 const float origin = scale - 1.f;
267 const float candidateVariance =
268 o2::its::math_utils::Sq(scale) * sourceCoordinateVariance +
269 o2::its::math_utils::Sq(tanLambda * scale) * sourceCoordinateVariance +
271 o2::its::math_utils::Sq(deltaR *
state.edgeMSAngle);
272 return std::pair{
source.z + tanLambda * deltaR, candidateVariance};
274 const auto [minPrediction, minVariance] = predictionAndVarianceAt(
state.targetMinR);
275 const auto [maxPrediction, maxVariance] = predictionAndVarianceAt(
state.targetMaxR);
276 const float lowerBound = std::min(minPrediction -
params.nSigmaCut * std::sqrt(minVariance),
277 maxPrediction -
params.nSigmaCut * std::sqrt(maxVariance));
278 const float upperBound = std::max(minPrediction +
params.nSigmaCut * std::sqrt(minVariance),
279 maxPrediction +
params.nSigmaCut * std::sqrt(maxVariance));
280 const auto directBins = getBinsPhiColumn(
source.phi,
state.toLayer, 0.5f * (lowerBound + upperBound),
281 0.5f * (upperBound - lowerBound),
state.edgePhiCut, indexUtils);
287 const auto [midpointPrediction, midpointVariance] = evaluateSearchWindowAt(window, targetMeanRadius);
289 BOOST_CHECK_CLOSE_FRACTION(midpointVariance, varianceZ, 1.e-6f);
290 const auto [evaluatedMinPrediction, evaluatedMinVariance] = evaluateSearchWindowAt(window,
state.targetMinR);
292 BOOST_CHECK_CLOSE_FRACTION(evaluatedMinVariance, minVariance, 1.e-6f);
293 const auto [evaluatedMaxPrediction, evaluatedMaxVariance] = evaluateSearchWindowAt(window,
state.targetMaxR);
295 BOOST_CHECK_CLOSE_FRACTION(evaluatedMaxVariance, maxVariance, 1.e-6f);
299 SurfaceKind::Cylinder,
state, indexUtils,
params.nSigmaCut,
300 beamUncertaintyWindow));
301 const auto [beamPrediction, beamVariance] = evaluateSearchWindowAt(beamUncertaintyWindow, targetMeanRadius);
303 BOOST_CHECK_CLOSE_FRACTION(beamVariance,
304 varianceZ + o2::its::math_utils::Sq(tanLambda * originScale) * 1.e-3f, 1.e-6f);
306 legacy.
PVres = 0.025f;
307 const auto differentConfiguredPVParams = makeKernelParameters(legacy, SurfaceKind::Cylinder);
308 BOOST_REQUIRE(differentConfiguredPVParams.isValid());
310 BOOST_REQUIRE((projectCylinderSearchWindow(
311 sourceMeasurement,
source,
vertex,
state, indexUtils, differentConfiguredPVParams, differentConfiguredPVWindow)));
312 checkSearchWindowEqual(differentConfiguredPVWindow, window);
318 const auto params = makeKernelParameters(legacy, SurfaceKind::Disk);
319 BOOST_REQUIRE(
params.isValid());
322 setDiskLookup(indexUtils, legacy);
324 constexpr int fromLayer = 1;
325 constexpr int toLayer = 4;
326 const float fromZ =
kMFTSurfaces[fromLayer].referenceCoordinate;
327 const float toZ =
kMFTSurfaces[toLayer].referenceCoordinate;
328 const auto source = makeGlobalCluster(1.2f, 0.7f, fromZ);
329 const auto sourceMeasurement = makeMeasurement(
source, 2.e-4f, 3.e-4f);
330 const auto vertex = makeVertex(0.01f, -0.02f, 0.1f, 4.e-4f, 5.e-4f, 0.04f, 3);
331 const auto state = makeDiskProjectionCache(fromLayer, toLayer, 2.f, fromZ, toZ, toZ, 3.e-3f, 0.04f);
334 BOOST_REQUIRE((projectDiskSearchWindow(
338 const float deltaZ = toZ -
source.z;
339 const float expectedRadius =
source.radius +
slope * deltaZ;
340 const float radialScale = expectedRadius /
source.radius;
341 const float expectedX = radialScale *
source.x;
342 const float expectedY = radialScale *
source.y;
343 const float projectionScale = 1.f + deltaZ / (
source.z -
vertex.getZ());
344 const float originScale = projectionScale - 1.f;
345 const float sourceCoordinateVariance = o2::its::math_utils::Sq(
state.sourcePositionResolution);
346 const float varianceR =
347 o2::its::math_utils::Sq(projectionScale) * sourceCoordinateVariance +
348 o2::its::math_utils::Sq(
slope * projectionScale) * sourceCoordinateVariance +
349 o2::its::math_utils::Sq(
slope * originScale) *
vertex.getSigmaZ2() +
350 o2::its::math_utils::Sq(deltaZ *
state.edgeMSAngle);
352 const auto [evaluatedRadius, evaluatedVariance] = evaluateSearchWindowAt(window, toZ);
354 BOOST_CHECK_CLOSE_FRACTION(evaluatedVariance, varianceR, 1.e-6f);
360 SurfaceKind::Disk,
state, indexUtils,
params.nSigmaCut,
361 beamUncertaintyWindow));
362 const auto [beamRadius, beamVariance] = evaluateSearchWindowAt(beamUncertaintyWindow, toZ);
364 BOOST_CHECK_CLOSE_FRACTION(beamVariance,
365 varianceR + o2::its::math_utils::Sq(originScale) * 1.e-3f, 1.e-6f);
372 const auto params = makeKernelParameters(legacy, SurfaceKind::Disk);
373 BOOST_REQUIRE(
params.isValid());
376 setDiskLookup(indexUtils, legacy);
378 constexpr int fromLayer = 0;
379 constexpr int toLayer = 1;
380 const float fromZ =
kMFTSurfaces[fromLayer].referenceCoordinate;
381 const float toZ =
kMFTSurfaces[toLayer].referenceCoordinate;
382 const auto source = makeGlobalCluster(1.2f, 0.7f, fromZ);
383 const auto measurement = makeMeasurement(
source, 2.e-4f, 3.e-4f);
384 const auto vertex = makeVertex(0.01f, -0.02f, 0.1f, 4.e-4f, 5.e-4f, 0.04f, 3);
386 const auto pointTarget = makeDiskProjectionCache(fromLayer, toLayer, 2.f, fromZ, toZ, toZ, 3.e-3f, 0.04f);
387 const auto intervalTarget = makeDiskProjectionCache(fromLayer, toLayer, 2.f, fromZ, toZ - 0.5f, toZ + 0.5f, 3.e-3f, 0.04f);
390 BOOST_REQUIRE((projectDiskSearchWindow(measurement,
source,
vertex, pointTarget, indexUtils,
params, pointWindow)));
391 BOOST_REQUIRE((projectDiskSearchWindow(measurement,
source,
vertex, intervalTarget, indexUtils,
params, intervalWindow)));
394 const float sourceCoordinateVariance = o2::its::math_utils::Sq(intervalTarget.sourcePositionResolution);
395 const float sourceVarianceScale = (1.f + o2::its::math_utils::Sq(
slope)) * sourceCoordinateVariance;
396 const float originVarianceScale = o2::its::math_utils::Sq(
slope) *
vertex.getSigmaZ2();
397 const float edgeMSVarianceScale = o2::its::math_utils::Sq(intervalTarget.edgeMSAngle);
398 const auto predictionAndVarianceAt = [&](
float z) {
399 const float deltaZ =
z -
source.z;
400 const float originScale = deltaZ / (
source.z -
vertex.getZ());
401 const float projectionScale = 1.f + originScale;
402 const float candidateVariance =
403 o2::its::math_utils::Sq(projectionScale) * sourceVarianceScale +
404 o2::its::math_utils::Sq(originScale) * originVarianceScale +
405 o2::its::math_utils::Sq(deltaZ) * edgeMSVarianceScale;
406 return std::pair{
source.radius +
slope * deltaZ, candidateVariance};
408 const auto [minPrediction, minVariance] = predictionAndVarianceAt(intervalTarget.targetMinZ);
409 const auto [maxPrediction, maxVariance] = predictionAndVarianceAt(intervalTarget.targetMaxZ);
410 const float lowerBound = std::min(minPrediction -
params.nSigmaCut * std::sqrt(minVariance),
411 maxPrediction -
params.nSigmaCut * std::sqrt(maxVariance));
412 const float upperBound = std::max(minPrediction +
params.nSigmaCut * std::sqrt(minVariance),
413 maxPrediction +
params.nSigmaCut * std::sqrt(maxVariance));
414 const auto directBins = getBinsPhiColumn(
source.phi, intervalTarget.toLayer, 0.5f * (lowerBound + upperBound),
415 0.5f * (upperBound - lowerBound), intervalTarget.edgePhiCut, indexUtils);
421 const auto [pointPrediction, pointVariance] = evaluateSearchWindowAt(pointWindow, toZ);
422 const auto [intervalPrediction, intervalVariance] = evaluateSearchWindowAt(intervalWindow, toZ);
423 BOOST_CHECK_CLOSE_FRACTION(intervalPrediction, pointPrediction, 1.e-6f);
424 BOOST_CHECK_CLOSE_FRACTION(intervalVariance, pointVariance, 1.e-6f);
425 BOOST_CHECK_CLOSE_FRACTION(intervalWindow.phiPrediction, pointWindow.phiPrediction, 1.e-6f);
426 BOOST_CHECK_SMALL(intervalWindow.phiVariance - pointWindow.phiVariance, 1.e-9f);
428 const auto [evaluatedMinPrediction, evaluatedMinVariance] = evaluateSearchWindowAt(intervalWindow, intervalTarget.targetMinZ);
430 BOOST_CHECK_CLOSE_FRACTION(evaluatedMinVariance, minVariance, 1.e-6f);
431 const auto [evaluatedMaxPrediction, evaluatedMaxVariance] = evaluateSearchWindowAt(intervalWindow, intervalTarget.targetMaxZ);
433 BOOST_CHECK_CLOSE_FRACTION(evaluatedMaxVariance, maxVariance, 1.e-6f);
441 configureCylinderIndex(cylinderIndexUtils, legacy);
442 const auto cylinderParams = makeKernelParameters(legacy, SurfaceKind::Cylinder);
443 const auto cylinderSource = makeGlobalCluster(2.f, 0.f, 100.f);
444 const auto cylinderMeasurement = makeMeasurement(cylinderSource);
445 const auto cylinderVertex = makeVertex(0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
446 const auto cylinderState = makeCylinderProjectionCache(0, 3, 2.f, 4.f, 3.8f, 4.2f, 5.e-4f, 2.e-3f, 0.08f);
448 {101, 102, 103, 104}, 105.f, 106.f, 107.f, 108.f, 109.f, 110.f, 111.f, 112.f};
449 auto cylinderOut = cylinderSentinel;
451 cylinderMeasurement, cylinderSource, cylinderVertex, cylinderState, cylinderIndexUtils, cylinderParams, cylinderOut)));
452 checkSearchWindowEqual(cylinderOut, cylinderSentinel);
455 setDiskLookup(diskIndexUtils, legacy, 0.1f, 0.01f);
456 const auto diskParams = makeKernelParameters(legacy, SurfaceKind::Disk);
457 constexpr int fromLayer = 0;
458 constexpr int toLayer = 1;
459 const float fromZ =
kMFTSurfaces[fromLayer].referenceCoordinate;
460 const float toZ =
kMFTSurfaces[toLayer].referenceCoordinate;
461 const auto diskSource = makeGlobalCluster(1.f, 0.5f, fromZ);
462 const auto diskMeasurement = makeMeasurement(diskSource);
463 const auto diskVertex = makeVertex(0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
464 const auto diskState = makeDiskProjectionCache(fromLayer, toLayer, 2.f, fromZ, toZ, toZ, 3.e-3f, 0.04f);
466 {201, 202, 203, 204}, 205.f, 206.f, 207.f, 208.f, 209.f, 210.f, 211.f, 212.f};
467 auto diskOut = diskSentinel;
469 diskMeasurement, diskSource, diskVertex, diskState, diskIndexUtils, diskParams, diskOut)));
470 checkSearchWindowEqual(diskOut, diskSentinel);
476 const auto params = makeKernelParameters(legacy, SurfaceKind::Disk);
477 constexpr int fromLayer = 0;
478 constexpr int toLayer = 1;
479 const float fromZ =
kMFTSurfaces[fromLayer].referenceCoordinate;
480 const float toZ =
kMFTSurfaces[toLayer].referenceCoordinate;
481 const auto source = makeGlobalCluster(1.f, 0.5f, fromZ);
482 const auto sourceMeasurement = makeMeasurement(
source);
483 const auto state = makeDiskProjectionCache(fromLayer, toLayer, 2.f, fromZ, toZ, toZ, 3.e-3f, 0.04f);
486 setDiskLookup(indexUtils, legacy);
488 const auto straightVertex = makeVertex(0.1f, -0.2f, 0.3f, 4.e-4f, 5.e-4f, 0.04f);
490 BOOST_REQUIRE((projectDiskSearchWindow(
491 sourceMeasurement,
source, straightVertex,
state, indexUtils,
params, straightWindow)));
494 const auto [straightPrediction, straightVariance] = evaluateSearchWindowAt(straightWindow, toZ);
499 const auto displacedVertex = makeVertex(-3.f, 4.f, straightVertex.getZ(), 8.f, 9.f, straightVertex.getSigmaZ2());
501 BOOST_REQUIRE((projectDiskSearchWindow(
502 sourceMeasurement,
source, displacedVertex,
state, indexUtils,
params, displacedWindow)));
503 checkSearchWindowEqual(displacedWindow, straightWindow);
505 const auto fallbackVertex = makeVertex(0.1f, -0.2f, fromZ, 4.e-4f, 5.e-4f, 0.f);
507 const TrackletSearchWindow sentinel{{1, 2, 3, 4}, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f, 11.f, 12.f};
508 fallbackWindow = sentinel;
510 sourceMeasurement,
source, fallbackVertex,
state, indexUtils,
params, fallbackWindow)));
511 checkSearchWindowEqual(fallbackWindow, sentinel);
517 cylinderParameters.
PVres = 0.f;
518 const auto cylinderKernelParameters = makeKernelParameters(cylinderParameters, SurfaceKind::Cylinder);
520 configureCylinderIndex(cylinderIndex, cylinderParameters);
521 const auto vertex = makeVertex(0.f, 0.f, 0.f, 1.e-4f, 1.e-4f, 4.e-4f, 4);
522 const auto cylinderState = makeCylinderProjectionCache(0, 1, 2.f, 4.f, 3.8f, 4.2f, 5.e-4f, 2.e-3f, 0.08f);
523 const auto sourceMeasurement = makeMeasurement(2.f, 0.f, 0.5f);
524 const auto source = makeGlobalCluster(2.f, 0.f, 0.5f);
527 BOOST_REQUIRE((projectCylinderSearchWindow(
528 sourceMeasurement,
source,
vertex, cylinderState, cylinderIndex, cylinderKernelParameters, baseline)));
530 auto poisonedSource =
source;
531 poisonedSource.x = -999.f;
532 poisonedSource.y = 888.f;
533 poisonedSource.z = -777.f;
535 BOOST_REQUIRE((projectCylinderSearchWindow(
536 sourceMeasurement, poisonedSource,
vertex, cylinderState, cylinderIndex, cylinderKernelParameters, poisonedWindow)));
537 checkSearchWindowEqual(poisonedWindow, baseline);
539 auto poisonedNavigationCache =
source;
540 poisonedNavigationCache.radius = 4.f;
542 BOOST_REQUIRE((projectCylinderSearchWindow(
543 sourceMeasurement, poisonedNavigationCache,
vertex, cylinderState, cylinderIndex, cylinderKernelParameters, cachePoisonedWindow)));
544 checkSearchWindowEqual(cachePoisonedWindow, baseline);
547 const auto diskKernelParameters = makeKernelParameters(diskParameters, SurfaceKind::Disk);
549 setDiskLookup(diskIndex, diskParameters);
550 const float fromZ =
kMFTSurfaces[0].referenceCoordinate;
552 const auto diskMeasurement = makeMeasurement(1.f, 0.5f, fromZ, 2.e-4f, 3.e-4f, 7.f);
553 auto diskLocator = makeGlobalCluster(1.f, 0.5f, fromZ);
554 const auto diskState = makeDiskProjectionCache(0, 1, 2.f, fromZ, toZ, toZ, 3.e-3f, 0.04f);
556 BOOST_REQUIRE((projectDiskSearchWindow(
557 diskMeasurement, diskLocator,
vertex, diskState, diskIndex, diskKernelParameters, diskBaseline)));
558 diskLocator.x = 123.f;
559 diskLocator.y = -321.f;
560 diskLocator.z = 456.f;
561 auto uvPoisoned = diskMeasurement;
562 uvPoisoned.covariance.xy = -12345.f;
564 BOOST_REQUIRE((projectDiskSearchWindow(
565 uvPoisoned, diskLocator,
vertex, diskState, diskIndex, diskKernelParameters, diskPoisoned)));
566 checkSearchWindowEqual(diskPoisoned, diskBaseline);