-
Notifications
You must be signed in to change notification settings - Fork 82
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
Add TrkStrawHitMC provenance and guard against empty StrawDigiMCs #1291
Add TrkStrawHitMC provenance and guard against empty StrawDigiMCs #1291
Conversation
Hi @edcallaghan,
which require these tests: build. @Mu2e/fnalbuild-users, @Mu2e/write have access to CI actions on main. ⌛ The following tests have been triggered for 5ceb93b: build (Build queue has 4 jobs) |
☔ The build tests failed for 5ceb93b.
N.B. These results were obtained from a build of this Pull Request at 5ceb93b after being merged into the base branch at 684bac4. For more information, please check the job page here. |
@edcallaghan Does this need to be tested with your PR in Production? or are the failures a different issue? |
📝 The HEAD of |
The failure is unrelated to the PR in Production. This has something to do with the root dictionaries (I think) for a struct which has been extended in this PR. I didn't see any equivalent related in my local testing, so I'll have to look into it. |
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.
The intent here is clear, I suggest a few minor cleanups.
MCDataProducts/inc/KalSeedMC.hh
Outdated
@@ -95,6 +104,7 @@ namespace mu2e { | |||
float _wireTau; // threshold cluster distance to the wire along the perpedicular particle path | |||
float _strawDOCA; // signed doca to straw | |||
float _strawPhi; // cylindrical phi from -pi to pi with 0 in Z direction | |||
TrkStrawHitProvenance _provenance; // TODO default read value == Sim? |
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.
I support a default value, perhaps 'unknown' to flag errors downstream
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.
The EnumToStringSparse class template requires that the detail class contain an enumerator named "unknown" and it default constructs it's objects to have a value of "unknown".
You will also add the implementation for the two functions declared in the detail class.
I suggest you moved the TrkStrawHitProvenance to be it's own .hh and .cc . Then use them in KalSeedMC .
If you prefer to keep them in KalSeedMC, then create KalSeedMC.cc to hold the missing implementation.
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.
Of course, making the initialization manifest does make the code more readable.
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.
... or add a comment that it defaults to unknown.
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.
A default constructor is now explicitly defined for the TrkStrawHitMC
struct, which initializes the provenance to unknown
.
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.
The default provenance has been updated to Simulation
, so that existing simulation will be deserialized correctly.
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.
@kutschke The common DigiProvenance
now inhabits a standalone src/inc pair.
Re default values: maybe I misunderstand your commentary, but the discussion here is about how to correctly initialize the provenance data member of TrkStrawHitMC
when deserializing preexisting simulation in which the provenance field did not exist. Since the default value for the actual provenance enum will be unknown
, as you asy, this needs to be explicitly overridden in the TrkStrawHitMC
constructor to mark the preexisting simulation as having been produced as such.
TrkDiag/src/TrkMCTools.cc
Outdated
// if mc info is not meaningful, then skip this digi. | ||
// this looks sketchy, but nowhere is an implicit association | ||
// between the sct and mcdigis collection actually assumed | ||
if (mcdigi.provenance() == StrawDigiProvenance::External){ |
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.
Please restructure logic to avoid 'continue'
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.
Done.
…, and default-initialize the latter
- change default provenance to Simulation, to accomodate presimulated data - finish implementation of associated provenance class - squash SimParticle index bound calculation in SelectRecoMC
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.
A few followups
MCDataProducts/inc/KalSeedMC.hh
Outdated
@@ -95,6 +104,7 @@ namespace mu2e { | |||
float _wireTau; // threshold cluster distance to the wire along the perpedicular particle path | |||
float _strawDOCA; // signed doca to straw | |||
float _strawPhi; // cylindrical phi from -pi to pi with 0 in Z direction | |||
TrkStrawHitProvenance _provenance; // TODO default read value == Sim? |
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.
The EnumToStringSparse class template requires that the detail class contain an enumerator named "unknown" and it default constructs it's objects to have a value of "unknown".
You will also add the implementation for the two functions declared in the detail class.
I suggest you moved the TrkStrawHitProvenance to be it's own .hh and .cc . Then use them in KalSeedMC .
If you prefer to keep them in KalSeedMC, then create KalSeedMC.cc to hold the missing implementation.
MCDataProducts/inc/KalSeedMC.hh
Outdated
@@ -95,6 +104,7 @@ namespace mu2e { | |||
float _wireTau; // threshold cluster distance to the wire along the perpedicular particle path | |||
float _strawDOCA; // signed doca to straw | |||
float _strawPhi; // cylindrical phi from -pi to pi with 0 in Z direction | |||
TrkStrawHitProvenance _provenance; // TODO default read value == Sim? |
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.
Of course, making the initialization manifest does make the code more readable.
MCDataProducts/inc/KalSeedMC.hh
Outdated
@@ -95,6 +104,7 @@ namespace mu2e { | |||
float _wireTau; // threshold cluster distance to the wire along the perpedicular particle path | |||
float _strawDOCA; // signed doca to straw | |||
float _strawPhi; // cylindrical phi from -pi to pi with 0 in Z direction | |||
TrkStrawHitProvenance _provenance; // TODO default read value == Sim? |
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.
... or add a comment that it defaults to unknown.
MCDataProducts/inc/KalSeedMC.hh
Outdated
@@ -95,6 +105,7 @@ namespace mu2e { | |||
float _wireTau; // threshold cluster distance to the wire along the perpedicular particle path | |||
float _strawDOCA; // signed doca to straw | |||
float _strawPhi; // cylindrical phi from -pi to pi with 0 in Z direction | |||
TrkStrawHitProvenance _provenance; // origin/validity of MC info object |
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.
If it's possible to do the default initialization here rather than in the c'tor initializer list, that would be better. I don't know if that's possible.
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.
AFAIK the default values have to be designated in the constructor (maybe in the definition for argument-supplied fields, but definitely in the initializer list otherwise).
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.
What I was getting at is that for sufficiently simple types, you can initialize it in the same line as the declaration
_provenance = (static_cast(DigiProvenanceDetail::Simulation);
Then it is implicitly present in the initializer list of all c'tors. What I am not sure about is whether this type is simple enough. I bet it will be if you use the typedef I suggested in my recent review.
…giProvenance class
@kutschke Sorry, I may have been using a stale page yesterday, which is why I seemed to have ignored your comments! I agree with you that the multiple provenance classes is starting to look like the wrong pattern (and we haven't even gotten beyond tracker yet), so I've consolidated into a single |
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.
Thanks a lot for the cleanups the structure now looks really good. I have one last suggestion, then I think this is good for merging.
…ion to offer helper methods
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.
Thanks for making the changes. It's great that you and Dave are thinking ahead to the other subsystems - I had not got that far yet.
I just noticed on more thing - see the inline comment. Then i think we are done.
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.
Thanks for making the requested changes, this looks good.
FYI, I snuck in one extra provenance check to make the standard |
...and also a higher-level but similar-purpose interface |
MCDataProducts/inc/DigiProvenance.hh
Outdated
}; | ||
using StringedDigiProvenance = EnumToStringSparse<DigiProvenanceDetail>; | ||
|
||
class DigiProvenance: public StringedDigiProvenance{ |
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.
Three things. First, EnumToStringSparse does not have a virtual d'tor so we should not inherit from it. That's easy to fix, we can give it a virtual d'tor and also add the other 4 rule of 5 functions as =default. ( My style is if the compiler will do the right thing for all rule of 5 functions I just leave them out and add a one line comment to that effect - I see that EnumToStringSparse is so old that the rule of 5 was then the rule of 3.) Go ahead and edit EnumToStringSparse.
The second issue is the CSAID C++ experts strongly advise against using inheritance when containment will do. We do violate this in some places. I think we are OK here.
Third, I think that if you add
typedef StringedDigiProvenance::enum_type enum_type;
(or try the equivalent using would be better ).
Then downstream code can avoid needing the DigiProvenanceDetail:: and you may also be able to avoid the static casts. I am not 100% sure that I have all details right here but I am pretty sure I am close.
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.
After sleeping on it, there is an different solution that avoids introducing the third type and avoids issue with inheritance, just use a free function:
using DigiProvenance = EnumToStringSparse<DigiProvenanceDetail>;
bool containsSimulation( DigiProvenance::enum_type id ){
return ( id == DigiProvenance::Simulation || id == DigiProvenance::Mixed );
}
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.
The free-function approach appears to be the path of least resistance --- it is preferable, IMO, to the extra baggage needed to make another distinct class pass muster. (FWIW, I went with inheritance over containment here because otherwise there are extra implementations to add to the list (i.e. forwarding all of the member functions of EnumToStringSparse<>
)).
That being said, I'm seeing issues with serialization of that simpler implementation (using DigiProvenance = EnumToStringSparse<DigiProvenanceDetail>
) manifesting as data corruption after deserializing, in which the actual enum_type
not being set correctly. Since this should be simpler the scenario, I'm not really sure what's going wrong. I'll have another try at figuring it out, but if I can't then I may need to just push updates to EnumToStringSparse<>
to make it "inheritable."
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.
Sorry for the slow response.
Can you point me to your working code that is failing and tell me what the error message is?
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.
No worries. I have the changes in a branch at https://github.com/edcallaghan/mu2e-Offline/tree/update_TrkStrawHitMC_provenance_free_functions. If you compile that (should work at head) and run the contents of ~ejc3/public/DigiProvenance
, you can reproduce for yourself. (This is a pair of jobs exemplified in .../run.sh
, in which we first physics-mix'' [pm] a few NoPrimary [np] events, and then
digi-mix'' [dm] a few CEs into them [ce]). You can see the error in .../dm-ce.log
, the relevant bit pasted here:
---- EventProcessorFailure BEGIN
EventProcessor: an exception occurred during current event processing
---- ScheduleExecutionFailure BEGIN
Path: ProcessingStopped.
---- ProductNotFound BEGIN
A request to resolve an Ptr to a product containing items of type: mu2e::StrawGasStep with ProductID 2189702261
cannot be satisfied because the product cannot be found.
The productGetter was not set -- are you trying to dereference a Ptr during mixing?
The above exception was thrown while processing module StrawDigiMCFilter/Triggerable run: 1202 subRun: 0 event: 1
---- ProductNotFound END
Exception going through path TriggerablePath
---- ScheduleExecutionFailure END
---- EventProcessorFailure END
But: my statement that the problem is in the serialization of the provenance was confused and, I think, incorrect. After another round of less-sloppy testing, the problem presents with the current version in this PR as well.
I suspect that the actual problem is with the construction of a new StrawDigiMC
at https://github.com/Mu2e/Offline/blob/main/TrackerMC/src/StrawDigiBundleCollection.cc#L223, ultimately stemming from the same "scope constraint" on use of art data products as I mention in #1290. That has nothing to do with the implementation of DigiProvenance
, so I can push the simpler implementation for that here. If I'm right, then another PR will need to be opened which addresses the invalid Ptr
s.
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.
I am looking at it now.
Just a wild guess and it's from memory. If your are making two data products, ACollection and BCollection, both in the same module, and if one contains Ptrs into the other, you cannot dereference the Ptrs until the module has returned. So they only work in downstream modules. The reason is that the pointee data product does not exist until after the return ( the move and the return are like a database two phase commit ).
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.
Please make dm-ce.fcl readable by me.
ls -l ~ejc3/public/DigiProvenance/dm-ce.fcl
-rw-------+ 1 ejc3 nobody 4177 Jun 30 15:46 /nashome/e/ejc3/public/DigiProvenance/dm-ce.fcl
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 looks like my wild guess is irrelevant The changes to Filters/src/StrawDigiMCFilter_module.cc look simple enough. So I agree it's likely that the bug is earlier in the workflow.
That's for making the change to the free function and fixing the typo. My reason for suggesting the free function was the same as in your reply.
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.
Sorry, ~ejc3/public/DigiProvenance/dm-ce.fcl
is now public-readable.
But, that being said, I think the issue here is actually much dumber than what I was getting at. When "digi mixing," I am mixing in the StrawDigiMC
s, each of which contains an art::Ptr<SimParticle>
into a SimParticleCollection
. But I don't actually mix the SimParticleCollection
in, so of course the pointer can't be dereferenced.
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.
Are all of the fixes in now?
MCDataProducts/src/DigiProvenance.cc
Outdated
|
||
bool DigiProvenance::ContainsSimulation() const{ | ||
DigiProvenanceDetail::enum_type id = this->id(); | ||
bool rv = ((id == DigiProvenanceDetail::Simulation) || (id == DigiProvenanceDetail::Simulation)); |
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 this a typo? Should one of them be Mixed?
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.
Yes and yes --- thank you for catching this!
... and I like that you added ContainsSimulation() - it should reduce pilot error. |
… and revert subclassing of EnumToStringSparse<>
@FNALbuild run build test |
⌛ The following tests have been triggered for 4ead963: build (Build queue has 4 jobs) |
@kutschke To checkpoint the status of this, But something we've learned here is that, because |
I think you are saying that you plan to deal with the outstanding issues in a new PR. Is that correct? Will old workflows work correctly in the mean time? |
Yes, and yes. No existing workflows are effected, but the projected workflow for mixing simulation onto simulation needs to be adjusted, which can be a separate PR. |
That works for me. Presuming the CI comes in cleanly I will approve and merge |
☀️ The build tests passed at 4ead963.
N.B. These results were obtained from a build of this Pull Request at 4ead963 after being merged into the base branch at 465477c. For more information, please check the job page here. |
This PR addresses fallout from PR #1245. In particular, that PR implemented functionality which can produce dummy
StrawDigiMC
objects which do not actually contain any useful information. Issue #1272 is a discussion place for structural replacements for that situation, but as it stands these dummy objects can be produced and must be accounted for in downstream analysis, which is partially addressed and partially enabled here. This PR enables the use of theSelectRecoMC
module on events which containStrawDigi
s from purely external origin.Changes to existing data structures:
-
TrkStrawHitMC
: a provenance data member is added, in sync with and acting to the same effect as the newly-introduced provenance data member ofStrawDigiMC
. This allows to guard against inspecting the underlying information of aTrkStrawHitMC
associated with aStrawDigiMC
for which no meaningful truth information exists. This is not only desireable for correct analysis, but structurally necessary to short-circuit references of invalid pointers.Changes to existing functionality:
-
SelectRecoMC
: Loops overStrawDigiMC
s which may attempt to inspect the truth information contain therein now check the provenance of theStrawDigiMC
and do not proceed with such inspection if the provenance isExternal
.TrkStrawHitMC
objects which are instantiated inherit their provenance from the preexistingStrawDigiMC
.-
TrkMCTools::findMCTrk
: A loop overStrawDigiMC
s now checks the provenance field before inspecting truth information, as above. This is a situation where it appears that there one stl-vector is being constructed in sync with another, but such synchronization is not actually assumed or required anywhere.