Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Add some more examples

...

Caveat: That is not real, compilable code! The real thing will not look exactly like it, since several problems were quietly swept under the carpet. But it illustrates the general structure.

Pieces of a PFA

One of the main advantages of a modular approach is that algorithms can be shared and re-used with minimal coding. In this section, we'll list some classes that are in CVS and that slot into this framework. (Note: This list is definitely not complete – it's just some of the ones I'm familiar with.)

When writing classes, please strive for flexibility and reuseability.

  • org.lcsim.recon.cluster.nn.NearestNeighborClusterDriver: This is a general-purpose clusterer. It uses a nearest-neighbor approach, starting from seed points and recursively adding nearby hits, where "nearby" is defined in terms of numbers of cells in each direction. The driver looks up every List<CalorimeterHit> in the event and applies the clusterer to each, writing out the clustered hits as a List<Cluster>. The name of each output list is the name of the input list plus a common extension (default is "NearestNeighborClusterDriver").
  • org.lcsim.recon.cluster.mst.MSTClusterDriver: This is another general-purpose clusterer. It also works with a nearest-neighbor approach, but with a user-definable metric. The default metric is 3D distance between the centers of the two hit cells. This is in general more computationally expensive than the NN clusterer, but is less sensitive to changes in the detector geometry. The driver also has hooks to let the user veto certain kinds of hits or clusters.
  • org.lcsim.recon.cluster.mipfinder.MIPClusterDriver: This clusterer is intended to find MIPs and track segments. It looks for sequences of isolated or near-isolated hits in adjacent layers.
  • org.lcsim.recon.cluster.clumpfinder.ClumpFinder: This driver reads in a HitMap and tries to find dense clumps of hits. These are written out as a list of Clusters, and left-over hits are written out as a HitMap.

Here is some example code showing how these pieces can be combined. Notice how quite a bit of the code is just manipulation of HitMaps and cluster lists.

No Format

public class ExamplePFA extends Driver
{
  public ExamplePFA()
  {
    // [Set up the hit maps and run DigiSim as usual]

    // Find MIP and track segments in the ECAL and HCAL
    TrackClusterDriver ecalMIP = new TrackClusterDriver("input hit map ecal",
        "mips ecal", "hit map ecal without mips");
    TrackClusterDriver hcalMIP = new TrackClusterDriver("input hit map hcal",
        "mips hcal", "hit map hcal without mips");
    add(ecalMIP);
    add(hcalMIP);
    // Merge the two lists:
    ListAddDriver<Cluster> mergeMIPs = new ListAddDriver<Cluster>();
    mergeMIPs.addInputList("mips ecal");
    mergeMIPs.addInputList("mips hcal");
    mergeMIPs.setOutputList("mips");
    add(mergeMIPs);

    // Find photons in the ECAL (cheating here)
    add(new ListFilterDriver(new ParticlePDGDecision(22), mcListName, "MCParticles photons only"));
    PerfectClusterer myCheatPhotonFinder = new PerfectClusterer();
    myCheatPhotonFinder.setInputHitMap("hit map ecal without mips");
    myCheatPhotonFinder.setOutputHitMap("hit map ecal without mips or photons");
    myCheatPhotonFinder.setOutputClusterList("photon clusters");
    myCheatPhotonFinder.setMCParticleList("MCParticles photons only");
    myCheatPhotonFinder.allowHitSharing(false);
    add(myCheatPhotonFinder);

    // Find clumps in ECAL and HCAL
    ClumpFinder findClumpsECAL = new ClumpFinder("hit map ecal without mips or photons",
        "clumps ecal", "hit map ecal without mips or photons or clumps");
    ClumpFinder findClumpsHCAL = new ClumpFinder("hit map hcal without mips",
        "clumps hcal", "hit map hcal without mips or clumps");
    add(findClumpsECAL);
    add(findClumpsHCAL);
    ListAddDriver<Cluster> mergeClumps = new ListAddDriver<Cluster>();
    mergeClumps.addInputList("clumps ecal");
    mergeClumps.addInputList("clumps hcal");
    mergeClumps.setOutputList("clumps");
    add(mergeClumps);

    // Merge clumps, MIPs and any other hits into larger clusters.
    // We still retain the old lists, so we can go back later and
    // study the structure.
 
    // First, the ECAL:   
    MSTClusterDriver mstEcal = new MSTClusterDriver("ecal hit map after mst", "mst clusters ecal");
    mstEcal.addInputHitMap("hit map ecal without mips or photons or clumps");
    mstEcal.addUserInputList("mips ecal");
    mstEcal.addUserInputList("clumps ecal");
    mstEcal.setThreshold(30.0); // 30mm point-to-point
    mstEcal.registerMetrics(new MinimumHitToHitDistance());
    add (mstEcal);

    // Then the HCAL:
    MSTClusterDriver mstHcal = new MSTClusterDriver("hcal hit map after mst", "mst clusters hcal");
    mstHcal.addInputHitMap("hit map hcal without mips or clumps");
    mstHcal.addUserInputList("mips hcal");
    mstHcal.addUserInputList("clumps hcal");
    mstHcal.setThreshold(100.0); // 100mm point-to-point
    mstHcal.registerMetrics(new MinimumHitToHitDistance());
    add (mstHcal);

    // Link clusters across the ECAL-HCAL boundary
    MSTClusterDriver mstDriverLink = new MSTClusterDriver("User");
    mstDriverLink.registerMetrics(new MinimumHitToHitDistance());
    mstDriverLink.setThreshold(50.0); // 50mm
    mstDriverLink.addUserInputList("mst clusters ecal");
    mstDriverLink.addUserInputList("mst clusters hcal");
    mstDriverLink.setClusterName("mst clusters linked");
    mstDriverLink.setPairDecision(new BothCalorimetersDecision());
    add(mstDriverLink);    
  }
}

Things that need doing

Updates needed in the code:

  • A real, live PFA in this format
  • Standard routines for telling you how well your PFA did (Ron's ClusterAnalysis?)
  • Example(s) in the main org.lcsim tree, probably under org.lcsim.plugin.web.examples

...