Skip to content

A revision of the HelixClass #24

Description

@dudarboh

Brief description

After the discussion with @yradkhorrami we discovered some issues in the HelixClass which I will describe here below. All problems are connected to the fact that HelixClass initializers all rely on the assumption that reference point = (0, 0, 0) even in the situations when it is really not supposed to.
This might lead to ambiguity and misunderstanding all over the place.

HelixClass::Initialize_Canonical()

Issue

A helix in the canonical representation is defined by the reference point and 5 parameters: phi0, omega, tanL, d0, z0.

This initializer is useful to define the helix from the trackState which has all parameters defined.
However this initializer doesn't take reference point as an input argument and assumes reference point always to be (0,0,0)
which can lead to a confusion:

auto ts = track->getTrackState(AtLastHit);
HelixClass helix;
helix.Initialize_Canonical( ts->getPhi0(), ts->getD0(), ts->getZ0(), ts->getOmega(), ts->geTanLambda(), 3.5);

Here the helixClass treats passed d0, z0 arguments as with respect to the (0, 0, 0). However in the trackState they are written with respect to the arbitrary reference_point=ts->getReferencePoint() which is not necessarily (0, 0, 0).
This will result with a helix of the same curvature and dip, but completely different positioning as one would expect from the trackState.

By simply copying d0 and z0 parameters we completely transform their geometrical meaning:

helix.getD0() == ts.getD0() // true
helix.getZ0() == ts.getZ0() // true

As the ts.getZ0() is the distance along z between helix PCA and the ts->getReferencePoint()[2]
While the helix.getZ0() is the distance along z between helix PCA and the z=0.
So they shouldn't be identical if we talk about "the same" helix.

In the current state to get the desired helix one would have to be aware to recalculate d0 and z0 from the track state assuming reference point is (0, 0, 0), e.g.:

auto ts = track->getTrackState(AtLastHit);
HelixClass helix;
double newD0 = getD0AtIP(ts->getReferencePoint(), ts->Phi0(), ts->getD0(), ts->getZ0), ...);
double newZ0 = getZ0AtIP(ts->getReferencePoint(), ts->Phi0(), ts->getD0(), ts->getZ0), ...);

helix.Initialize_Canonical( ts->getPhi0(), newD0, newZ0, ts->getOmega(), ts->geTanLambda(), bField);

which is not necessarily trivial...

Potential way to improve

Provide reference point as an input argument to avoid ambiguity.

HelixClass::Initialize_VP()

Issue

This initializer is useful if one has:

  • (x, y, z) coordinates of the point on the helix
  • momentum of the helix at the given point

It uses the given point as a reference point to construct the helix:

void HelixClass::Initialize_VP(float * pos, float * mom, float q, float B) {
_referencePoint[0] = pos[0];
_referencePoint[1] = pos[1];
_referencePoint[2] = pos[2];

One would expect that output d0 and z0 paremeters must be 0 as the reference point is on the helix by definition.
However, while calculating d0 and z0 initializer comes backs to assuming reference point as (0,0,0) without mentioning it anywhere:

_d0 = double(q)*radius - q_sign * double(sqrt(xCentre*xCentre+yCentre*yCentre)); // not 0
_z0 = pos[2] + _radius*_tanLambda*q*(deltaPhi + _const_2pi*nCircles); // not 0

This would fail the user, if he plans to use d0, z0 helix parameters further in the program, e.g. to draw the helix,
which @yradkhorrami has experienced in the following example:

float pos[3] = getVertexPosition();
float mom[3] = getMomentum();

HelixClass helix;
helix.Initialize_VP(pos, mom, charge, bField);

double Px = pt * std::cos(  helix->getPhi() );
double Py = pt * std::sin(  helix->getPhi() );
double Pz = pt * helix->getTanLambda() ;
double Xs = helix->getReferencePoint()[0] -  helix->getD0() * std::sin( helix->getPhi() ) ; // d0 should be 0
double Ys = helix->getReferencePoint()[1] +  helix->getD0() * std::cos( helix->getPhi() ) ; // d0 should be 0
double Zs = helix->getReferencePoint()[2] +  helix->getZ0() ; // z0 should be 0

DDMarlinCED::drawHelix(bField, charge, Xs, Ys, Zs, Px, Py, Pz, ...);
// results in the different helix from:
// DDMarlinCED::drawHelix(bField, charge, pos[0], pos[1], pos[2], mom[0], mom[1], mom[2], ...);

Potential way to improve

Cross check all the equations and remove any assumptions of reference point as 0,0,0 where it is definitely shouldn't be and set d0 and z0 as 0.

HelixClass::Initialize_BZ()

Issue

This initializer is good when we know exact geometrical properties of the helix:

  • Coordinates of the center: xCentre, yCentre
  • Radius radius
  • Dip bZ
  • starting phase of the helix phi0

One should immediately note very inconvenient naming of the phi0 parameter.
Inside the Initialize_BZ() the phi0 parameter is a phase shift of the initial helix along z and is NOT a track parameter as in previous two initializers, which is a great point to become confused in this context.

We also see inconsistency between helix.getReferencePoint() which seems to be ON the helix:

  _referencePoint[2] = zBegin;
  _referencePoint[0] = xCentre + radius*cos(bZ*zBegin+phi0);
  _referencePoint[1] = yCentre + radius*sin(bZ*zBegin+phi0);

and output d0 and z0 parameters that have nothing to do with the helix reference point. It is hard to understand for me from the equations with respect to what point d0 and z0 are actually calculated in this case...

_d0 = -_xAtPCA*sin(_phi0) + _yAtPCA*cos(_phi0);
_z0 = _referencePoint[2] - (deltaPhi + _const_2pi*nCircles)/bZ;  

I am very confused about the most of the equations in the Initialize_BZ(). So some discussion with experts would be nice. E.g.:
_phiAtPCA = atan2(-_yCentre,-_xCentre); does it make sense?

Potential way to improve

Cross check all of the equations, rename phi0 to something different, e.g. phase0

HelixClass_double ?

This is just a comment to bring a discussion on why we have separate class for the HelixClass with double. Is it bad to transit HelixClass from float to double? Overload/template? Isn't there any better way to implement this?

List of packages using HelixClass

  1. Garlic/GarlicExtendedTrack
    providing a comment:
    (231) // get helix-plane intersection by hand (the one from HelixClass seems strange/buggy...)
  2. LCFIVertex/ConversionTagger
  3. FPCCDSiliconTracking_MarlinTrk
  4. V0Finder
  5. (Its quite a lot, I will finish it later at some point...)

Any thoughts, comments @tmadlener, @gaede?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions