Skip to content

Conversation

@S81D
Copy link
Collaborator

@S81D S81D commented Sep 29, 2025

Describe your changes

VertexLeastSquares is a PMT-based vertex reconstruction tool that can be used for low energy events (NC-like, neutrons, etc...) without an MRD track to assist in the reconstruction. More info can be found on the included README, and in Andrew's slides.

It can be used on MC hits, MC waveform-reconstructed hits, and data hits. It is designed to run over clusters to yield a reconstructed vertex (x,y,z) and stdev to the timing residuals.

Checklist before submitting your PR

  • This PR implements a single change (one new/modified Tool, or a set of changes to implement one new/modified feature)
  • This PR alters the minimum number of files to affect this change
  • If this PR includes a new Tool, a README and minimal demonstration ToolChain is provided
  • If a new Tool/ToolChain requires model or configuration files, their paths are not hard-coded, and means of generating those files is described in the readme, with examples provided on /pnfs/annie/persistent
  • For every new usage, there is a reason the data must be on the heap
  • For every new there is a delete, unless I explicitly know why (e.g. ROOT or a BoostStore takes ownership)
    ^ store should take care of the new used in the tool (line 134, 135) but it would be nice to double check.

Copy link
Collaborator

@jminock jminock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did not spot any memory leaks or logical issues. Everything is well-documented (thank you!) and should not impede any other Tools or ToolChains

removed event skipping - PMTWaveformSim will be adjusted
Copy link
Collaborator

@marc1uk marc1uk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code in general looks good, just a few places where we can reduce a lot of duplication with some templating or lambdas.

}

//-----------------------------------------------------------------------------
std::vector<Position> VertexLeastSquares::GenerateVetices() // this is Andrew's fault there's a typo (and no I'm not going to fix it :) )
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's like reading code by @brichards64 😆

std::vector<Position> VertexLeastSquares::GenerateVetices() // this is Andrew's fault there's a typo (and no I'm not going to fix it :) )
{

if (fExternalSeeding) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's an if/else branch here of ~50 odd lines on each branch, but as far as I can see the only difference between them is whether to add the buffers to yMin, yMax, and max_radius. It seems you could just do

if (fExternalSeeding) {
   yMin -= fYBuffer;
   yMax x= fYBuffer;
   max_radius += fRadialBuffer;
}

and totally eliminate any code duplication.



//------------------------------------------------------------------------------
void VertexLeastSquares::EvalAtGuessVertexMC(util::Matrix &A, util::Vector &b,
Copy link
Collaborator

@marc1uk marc1uk Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you guess what I'm gonna say...? 🙃

This is wholly identical to EvalAtGuessVertex, other than our constant headache of taking vector<Hit> instead of vector<MCHit>. There are two simple ways to deal with this here:

  1. make EvalAtGaussVertex a templated method. Only downside of this is the implementation needs to move to the header file.
  2. use a lambda. Downside is that lambdas can't be members so wrapping is a bit awkward. One way could be as follows:
void VertexLeastSquares::EvalAtGuessVertex(const std::vector<Hit>& hits, const std::vector<MCHit>& mchits, ... ){
    auto process = [](auto& hits){
        // all current code in EvalAtGaussVertexMC can go here unchanged
    }
   
    if(hits) process(hits);
    else     process(mchits);
}

This keeps the EvalAtGuessVertex code within a member function without moving the implementation to the header, while taking advantage of lambdas' ability to accept auto to work with both types.
I'm happy to accept either (or something else), but please do one or the other.

// We need at least 4 hits
if (filt_hits.size() < 4) {
std::cout << "Not enough hits. We only have: " << filt_hits.size() << std::endl;
fVertexMap->emplace(clusterpair.first, Position(-99, -99, -99));
Copy link
Collaborator

@marc1uk marc1uk Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is a vertex necessary? can the map simply not have an entry?
with c++17 we could use std::optional.... but for now, perhaps as a minimum using an outside the tank position would be helpful.... 😕

}
}

// Don't let the loop last forever
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while(true){
   ++loop_num;
   if(loop_num > max_loop_num) break;
}

.... so a for loop then? 😅

double max_vertical = fGeom->GetTankHalfheight() + fExternalVertexMaxHeight;

if (radial_dist > max_radial || std::abs(dy) > max_vertical) {
continue; // reject this seed
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this comment be 'reject this guess'

}

//------------------------------------------------------------------------------
void VertexLeastSquares::RunLoopMC()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another duplicate function



//------------------------------------------------------------------------------
std::vector<MCHit> VertexLeastSquares::FilterHitsMC(std::vector<MCHit> hits)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm assuming this can also be merged with FilterHits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants