-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initialize_Canonical() and getDistanceToHelix() updates for reference points other than (0,0,0) #29
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @jfklama,
Thanks for this. One request I would have from my side is the following: Could you either remove the commented std::cout
debug prints, or make them "proper" debug outputs with streamlog_out(DEBUG)
(potentially choosing an appropriate debug level here to make sure it only appears with rather detailed output).
@dudarboh could you also have a look at the implementation to see if this indeed solves some of the issues you raised?
Hi @jfklama, I can't really comment on your changes for Also I see you re-calculate Also, do these fixes work for tracks which are created with other broken constructors? @tmadlener, we also should not forget that this ... We should either keep them both consistent with each other, or remove one of them. Otherwise it is even a bigger mess.. Also, I think Debugging all the trigonometry 100 times is not fun. Better to do it once and put in some tests. |
Very good point. I can have a look at merging those into one templated class (in a separate PR).
I fully agree with this. Covering everything from the Helix class now is probably a lot of work, but at least adding tests for newly added functionality or bug fixes should be rather straight forward. In principle there is a very simple test program already present here, but we can also try and set up "proper unit testing" rather quickly here. |
Dear @tmadlener, @dudarboh I've made the additional changes - removed / changed outputs, added general description in the header and "getters" for
I have never used other initializers and didn't touch them. Regarding "proper" unit testing, unfortunately I have no experience with that - I can try to help somehow, but probably I would need to see some examples first... |
62f012f
to
bfdf6de
Compare
@jfklama I have rebased this onto the latest version. Is this pull request still relevant? Could you also briefly check that I didn't introduce any obvious mistakes during rebasing? |
…nts other than (0,0,0)
bfdf6de
to
ce93d98
Compare
@jfklama I rebased this again to pick up the unit test setup, so it should now be a lot easier to add a few tests that make sure that things work as expected. |
@tmadlener I have found some small inconsistencies, it should fine now. |
Thanks for checking (and fixing my mistakes). Would it be possible to add some (or at least one) test for this? There is a basic example of how to do this in source/tests/unittests/TestHelixClass.cpp Essentially what you need to do is:
|
I've added some tests of calculating distance between helices. It seems that my changes worked at least in my case (highly displaced, non-pointing tracks) but in general the behavior can still be unexpected. However, the backward compatibility looks fine. I assume that if someone used HelixClass so far, they tested the performance (like e.g. in the case of V0Finder) so we should keep it. It's quite surprising that some tests are passed by one HelixClass version and failed by the other... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @jfklama, thanks for adding some tests. It seems that at least in the CI that we are running here quite a few of them are failing at the moment: https://github.com/iLCSoft/MarlinUtil/actions/runs/3432147649/jobs/5734311976#step:4:628 Are these working locally for you?
I have an additional style comment below.
No, these tests correspond to the '(0,0,0) reference point' case with large Honestly, with the form of this algorithm, I am not sure whether it even fundamentally makes sense to use (0,0,0) as a reference point if tracks are highly displaced. Would it make sense to put some warnings in the code for those case scenarios? |
OK. So if I understand correctly, you added tests for your newly added changes, and these are working as expected (at least for the use cases you intend to use them)? But then you also added some more tests, trying to cover existing functionality, and these are currently broken. If that is the case, I would leave the unittests for your expected behavior and remove the ones from that try to use the new developments together with existing functionality. We will deal with the non-trivial things from the existing functionality in separate PRs. Those should be kept rather small, so that they are not too much work to create and review. |
@jfklama Two critical bugsThere are two critical bugs:
// this is currently implemented and it is simply wrong
// _xCentre = _referencePoint[0] + _radius*cos(_phi0-_const_pi2*_charge);
// _yCentre = _referencePoint[1] + _radius*sin(_phi0-_const_pi2*_charge);
// this is how it should be
_xCentre = _xAtPCA + _radius*cos(_phi0-_const_pi2*_charge);
_yCentre = _yAtPCA + _radius*sin(_phi0-_const_pi2*_charge);
// this is currently implemented and it is simply wrong
// _referencePoint[0] = _xAtPCA;
// _referencePoint[1] = _yAtPCA;
// _referencePoint[2] = _z0;
// this is how it should be
_referencePoint[0] = 0.;
_referencePoint[1] = 0.;
_referencePoint[2] = 0.; but changing latter might have an impact on currently running code, so one has to thoroughly check if this part is used anywhere @tmadlener... `getDistanceToHelix() requires both the center of the helix and reference point: FloatT x01 = getXC();
FloatT y01 = getYC();
FloatT x02 = helix->getXC();
FloatT y02 = helix->getYC();
...
FloatT ref1[3];
FloatT ref2[3];
for (int i=0;i<3;++i) {
ref1[i]=_referencePoint[i];
ref2[i]=helix->getReferencePoint()[i];
} So, without fixing two bugs above, even if the algorithm inside |
Hi @dudarboh
Thanks, I missed it - most likely, because I used reference points close to the helix, so the difference was not noticeable. This is also a consequence of the "old" implementation (which you point out later), where x_yPCA were assigned to the reference point. I can quickly correct this.
This I have left on purpose, exactly because these variables are used in the So I didn't want to break it, even though I would guess your suggestion should improve it (but this would require tests). I don't know what effect this fix would have on other packages. |
Ah, ok, I see. I should admit, I completely lost the understanding how does it work. |
Hopefully not only for my case... I think that the old implementation was "approximately" good, as long as one used ref. point = (0,0,0) and rather small On the other hand, maybe we should consider fixing also the current |
@jfklama I think we should consider fixing As we all agree, this whole business needs a complete ovehaul. Which we will not do for the next patch. So, we either:
@tmadlener, your take on this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies for not coming back to this earlier. This seems to be becoming a larger and larger project the more we (well you) look into it. Maybe we should try to get something into the next release that is useful for you and then try to see how to actually tackle this in a more systematic way.
I think currently not breaking existing code is the most important concern. So anything that could change that should be avoided (at least for the upcoming tag and patch release). As far as I can tell, the current version does that, right? I.e. it only adds a new constructor, but essentially leaves the rest of the functionality as it is. Or could it potentially also change outcomes for other constructors?
I have left a few comments inline. One thing that is not yet entirely clear to me (and here you are probably the experts), is how tight the floating point comparisons can be made. Ideally they would be very tight, and really essentially testing numerical equality, rather than "equality in a physics sense" (i.e. probably doesn't change the outcome of an analysis).
Another option to at least make it possible for you to continue with your work would be the following: As the long term plan is to go to the aidaTT
helix utilities in any case, you could also directly start using that instead of trying to tack on the necessary functionality on to here, where we know, that we will have to change it in any case in the future. I am not entirely sure how much work that entails, but maybe you could have a quick look to see if that will take days or if it is more likely going to be weeks.
FloatT phi0 = atan2( momentum[1],momentum[0] ); | ||
if (phi0 < 0) phi0 += 2 * M_PI; | ||
|
||
helix.Initialize_Canonical(-1.767, -9.163e-03, -2.103e-01, -8.808e-05, 8.251, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for slighly better readability of the tests, could some of these magic numbers be put into variables with a meaningful way? That would make the comparisons below a bit easier to interpret as well.
FloatT vtx_momentum1[3]; | ||
FloatT vtx_momentum2[3]; | ||
FloatT vertex1[3]; | ||
FloatT vertex2[3]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FloatT vtx_momentum1[3]; | |
FloatT vtx_momentum2[3]; | |
FloatT vertex1[3]; | |
FloatT vertex2[3]; | |
std::array<FloatT, 3> vtx_momentum1; | |
std::array<FloatT, 3> vtx_momentum2; | |
std::array<FloatT, 3> vertex1; | |
std::array<FloatT, 3> vertex2; |
Just for consistency throughout the tests. You probably have to use a .data()
below then to pass things.
FloatT vtx_momentum1[3]; | ||
FloatT vtx_momentum2[3]; | ||
FloatT vertex1[3]; | ||
FloatT vertex2[3]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above.
// distance should be small but nonzero | ||
CHECK_THAT(0.0, Catch::Matchers::WithinAbs(dist1, 2)); | ||
CHECK_THAT(0.0, Catch::Matchers::WithinAbs(dist2, 2)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is 2 mm(?) a reasonable difference for it still to be considered non-zero? Or is this mainly to make these tests pass? Is it possible to calculate the actual expected distance in this case, and check that with a much smaller epsilon?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's partly to make the tests pass, but also, honestly, I don't see any way to calculate this, other than as currently implemented in getDistanceToHelix()
. If the helices do not cross (which of course is the case in real life), the calculation becomes highly non-trivial, as one can see from complexity of the algorithm. So either we accept the current algorithm prediction as the "correct" and use it in the test, or assume the distance should be small and accept everything close to zero within some margin.
I chose the latter option because: 1) I think 2 mm is a good precision for such a high track displacement 2) from my experience, when there is a bug in the algorithm, the calculated distance explodes, 3) even though I went through this code and I believe I understand how it works, it is still not mine and it might happen that I am missing something (as with the x_yCentre bug pointed out by @dudarboh)
Hi @tmadlener, sorry for a late response.
In principle yes, for the
Thanks for the comments. Unfortunately, regarding the floating point numbers, that is not clear for me as well. I have seen some strange behaviour depending on precision of the input variables...
For me the main problem with the aidaTT helix utilities is that it doesn't have any tool to calculate distance/PCA between helices ;) I can see some functions for finding intersections which could be potentially used for that, but at first glance I have no idea how they work. So it could take some time... To be very honest, for my work I can use my implementation of the |
BEGINRELEASENOTES
Fixes of some of the issues mentioned in #24
ENDRELEASENOTES