Print

Print


Author: [log in to unmask]
Date: Mon Jan  9 13:15:27 2017
New Revision: 4659

Log:
[HPSJAVA-708] Fix display of tracks and particles in Wired by installing custom heprep converters in the HPS plugin.

Added:
    java/trunk/plugin/src/main/java/org/hps/plugin/HPSParticleConverter.java
    java/trunk/plugin/src/main/java/org/hps/plugin/HPSTrackConverter.java
Modified:
    java/trunk/plugin/src/main/java/org/hps/plugin/HPSPlugin.java

Added: java/trunk/plugin/src/main/java/org/hps/plugin/HPSParticleConverter.java
 =============================================================================
--- java/trunk/plugin/src/main/java/org/hps/plugin/HPSParticleConverter.java	(added)
+++ java/trunk/plugin/src/main/java/org/hps/plugin/HPSParticleConverter.java	Mon Jan  9 13:15:27 2017
@@ -0,0 +1,199 @@
+package org.hps.plugin;
+
+import hep.graphics.heprep.HepRepFactory;
+import hep.graphics.heprep.HepRepInstance;
+import hep.graphics.heprep.HepRepInstanceTree;
+import hep.graphics.heprep.HepRepType;
+import hep.graphics.heprep.HepRepTypeTree;
+import hep.physics.vec.Hep3Vector;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.ReconstructedParticle;
+import org.lcsim.event.Track;
+import org.lcsim.geometry.Detector;
+import org.lcsim.util.heprep.HepRepCollectionConverter;
+import org.lcsim.util.heprep.LCSimHepRepConverter;
+import org.lcsim.util.heprep.RandomColorMap;
+import org.lcsim.util.swim.HelixSwimmer;
+import org.lcsim.util.swim.HelixSwimmerYField;
+
+/**
+ * This class converts an LCIO ReconstructedParticle to the HepRep format for
+ * display by Wired4.  Clusters and tracks from a RP are given the same randomly
+ * generated color.  Charged Tracks, Neutral Tracks, and Calorimeter Clusters are
+ * given their own sub-types, so that they can be easily switched on and off.
+ * 
+ * @author jeremym
+ */
+class HPSParticleConverter implements HepRepCollectionConverter
+{
+    
+    private static final double[] ORIGIN = {0, 0, 0.00001};
+    RandomColorMap rcolorMap;
+
+    private static final double[] zero = {0, 0, 0};
+    
+    public HPSParticleConverter()
+    {
+        rcolorMap = new RandomColorMap(50);
+    }
+
+    public boolean canHandle(Class k)
+    {
+        return ReconstructedParticle.class.isAssignableFrom(k);
+    }
+    
+    public void convert(EventHeader event, List collection, HepRepFactory factory, HepRepTypeTree typeTree, HepRepInstanceTree instanceTree)
+    {               
+        rcolorMap.reset(collection.size());
+        
+        String pfoName = event.getMetaData(collection).getName();        
+        
+        // RP top-level type.
+        HepRepType rpType = factory.createHepRepType(typeTree, pfoName);
+        rpType.addAttValue("layer", LCSimHepRepConverter.PARTICLES_LAYER);
+        
+        // Neutral Tracks type.
+        HepRepType neutralTracksType = factory.createHepRepType(rpType, "NeutralTracks");
+        neutralTracksType.addAttValue("layer", LCSimHepRepConverter.PARTICLES_LAYER);
+        neutralTracksType.addAttValue("drawAs","Line");
+        /*neutralTracksType.addAttValue("LineStyle", "Dashed"); // Doesn't work.
+        neutralTracksType.addAttValue("color",Color.GREEN);*/
+        
+        // Charged Tracks type.
+        HepRepType chargedTracksType = factory.createHepRepType(rpType, "ChargedTracks");
+        chargedTracksType.addAttValue("layer", LCSimHepRepConverter.PARTICLES_LAYER);
+        chargedTracksType.addAttValue("drawAs","Line");
+        
+        // Clusters type.
+        HepRepType clustersType = factory.createHepRepType(rpType, "CalClusters");
+        clustersType.addAttValue("color",Color.RED);
+        clustersType.addAttValue("fill",true);
+        clustersType.addAttValue("fillColor",Color.RED);
+        clustersType.addAttValue("layer", LCSimHepRepConverter.HITS_LAYER);
+        
+        /*
+        clustersType.addAttValue("layer", LCSimHepRepConverter.HITS_LAYER);
+        clustersType.addAttValue("drawAs", "Point");
+        clustersType.addAttValue("MarkName", "Box");
+        clustersType.addAttDef("energy", "Hit Energy", "physics", "");
+        clustersType.addAttDef("cluster", "Cluster Energy", "physics", "");
+        */
+        
+        int rpCnt = 0;
+        for (ReconstructedParticle rp : (List<ReconstructedParticle>) collection)
+        {                      
+            // Get the color for this RP.
+            Color rpColor = rcolorMap.getColor(rpCnt % rcolorMap.size());
+            
+            List<Cluster> clusters = rp.getClusters();
+            List<Track> tracks = rp.getTracks();
+            
+            convertClusters(event, clusters, factory, typeTree, instanceTree, rpColor, clustersType);                                                                    
+            convertTracks(event, tracks, factory, typeTree, instanceTree, rpColor, chargedTracksType);
+            
+            if (rp.getCharge() == 0)
+            {
+                convertNeutralParticle(event.getDetector(), rp, instanceTree, factory, neutralTracksType, rpColor);
+            }                      
+            
+            ++rpCnt;
+        }
+    }
+    
+    private void convertClusters(EventHeader event, List<Cluster> collection, HepRepFactory factory, HepRepTypeTree typeTree, HepRepInstanceTree instanceTree, Color clusterColor, HepRepType type)
+    {       
+        List<CalorimeterHit> hits = new ArrayList<CalorimeterHit>();
+        
+        HepRepInstance instanceC = factory.createHepRepInstance(instanceTree, type);
+        
+        for (Cluster cluster : collection)
+        {
+            if (cluster.getCalorimeterHits().size() != 0) {
+                hits.addAll(cluster.getCalorimeterHits());
+            }
+        }
+           
+        if (hits != null)
+        {
+            for (CalorimeterHit hit : hits)
+            {
+                if (hit != null) {
+                    double[] pos = hit.getPosition();
+                    HepRepInstance instanceX = factory.createHepRepInstance(instanceC, type);
+                    instanceX.addAttValue("MarkSize", 5);
+                    instanceX.addAttValue("color", clusterColor);
+                    instanceX.addAttValue("showparentattributes", true);
+                    instanceX.addAttValue("pickparent", true);
+                    //HepRepPoint pp = 
+                    factory.createHepRepPoint(instanceX, pos[0], pos[1], pos[2]);
+                }
+            }
+        }
+    }   
+
+    private void convertTracks(EventHeader event, List<Track> collection, HepRepFactory factory, HepRepTypeTree typeTree, HepRepInstanceTree instanceTree, Color trackColor, HepRepType type)
+    {   
+        if (collection.size() == 0)
+            return;
+        
+        Detector detector = event.getDetector();
+
+        double trackingRMax = detector.getConstants().get("tracking_region_radius").getValue();
+        double trackingZMax = detector.getConstants().get("tracking_region_zmax").getValue();
+
+        double[] field = detector.getFieldMap().getField(ORIGIN);
+        HelixSwimmer helix = new HelixSwimmerYField(field[1]);
+             
+        for (Track t : (List<Track>) collection)
+        {                        
+            helix.setTrack(t);
+            double distanceToCylinder = helix.getDistanceToCylinder(trackingRMax, trackingZMax);
+
+            HepRepInstance instanceX = factory.createHepRepInstance(instanceTree, type);
+            instanceX.addAttValue("color", trackColor);
+
+            double dAlpha = 10; // 1cm
+            for (int k = 0; k < 200; k++)
+            {
+                double d = k * dAlpha;
+                if (d > distanceToCylinder)
+                    break;
+                Hep3Vector point = helix.getPointAtDistance(d);
+                factory.createHepRepPoint(instanceX, point.x(), point.y(), point.z());
+            }
+        }
+    }
+    
+    // TODO: Connect to cluster center instead of swimming.
+    public void convertNeutralParticle(Detector detector, ReconstructedParticle p, HepRepInstanceTree tree, HepRepFactory factory, HepRepType type, Color rpColor)
+    {  
+        HepRepInstance instanceX = factory.createHepRepInstance(tree, type);
+        
+        double trackingRMax = detector.getConstants().get("tracking_region_radius").getValue();
+        double trackingZMax = detector.getConstants().get("tracking_region_zmax").getValue();
+
+        double[] field = detector.getFieldMap().getField(zero);
+        HelixSwimmer helix = new HelixSwimmer(field[2]);
+        
+        double charge = p.getCharge();
+        Hep3Vector start =  p.getReferencePoint();
+        Hep3Vector momentum = p.getMomentum();
+        helix.setTrack(momentum, start, (int) charge);
+        double distanceToCylinder = helix.getDistanceToCylinder(trackingRMax,trackingZMax);
+        
+        Hep3Vector stop = helix.getPointAtDistance(distanceToCylinder);
+           
+        factory.createHepRepPoint(instanceX,start.x(),start.y(),start.z());
+        factory.createHepRepPoint(instanceX,stop.x(),stop.y(),stop.z());
+        instanceX.addAttValue("color", rpColor);
+        instanceX.addAttValue("momentum",p.getEnergy());
+        instanceX.addAttValue("type",p.getType());                   
+    }
+}

Modified: java/trunk/plugin/src/main/java/org/hps/plugin/HPSPlugin.java
 =============================================================================
--- java/trunk/plugin/src/main/java/org/hps/plugin/HPSPlugin.java	(original)
+++ java/trunk/plugin/src/main/java/org/hps/plugin/HPSPlugin.java	Mon Jan  9 13:15:27 2017
@@ -1,12 +1,65 @@
 package org.hps.plugin;
 
 import org.freehep.application.studio.Plugin;
+import org.freehep.application.studio.Studio;
+import org.freehep.util.FreeHEPLookup;
+import org.lcsim.event.ReconstructedParticle;
+import org.lcsim.event.Track;
+import org.lcsim.util.heprep.HepRepCollectionConverter;
+import org.lcsim.util.heprep.LCSimHepRepConverter;
 
 /**
- * This is just a dummy plugin class to make JAS3 happy.
+ * JAS3 plugin for HPS.
+ * This install custom converter for the Track and ReconstructedParticle classes. 
+ * 
  * @author Jeremy McCormick
  * @version $Id: HPSPlugin.java,v 1.1 2013/06/03 16:23:47 jeremy Exp $
  */
 
-public class HPSPlugin extends Plugin 
-{}
+public class HPSPlugin extends Plugin {
+    
+    /**
+     * Install a custom converter for HPS Track and ReconstructedParticle objects
+     * so that they are swum correctly in the B-field. 
+     */
+    protected void postInit() {
+        
+        Studio app = getApplication();
+        FreeHEPLookup lookup = app.getLookup();
+         
+        // Get the HepRep converter registered by lcsim.
+        Class<?> converterClass = null;
+        try {
+            converterClass = Class.forName("org.lcsim.util.heprep.LCSimHepRepConverter");
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException(e);
+        }                       
+        LCSimHepRepConverter converter = (LCSimHepRepConverter) lookup.lookup(converterClass);
+        if (converter == null) {
+            throw new RuntimeException("LCSimHepRepConverter was not found.");
+        }
+        
+        // Remove the existing track converter from the lcsim plugin.
+        HepRepCollectionConverter trackConverter = converter.findConverter(Track.class);
+        if (trackConverter != null) {
+            converter.deregister(trackConverter);            
+        } else {
+            throw new RuntimeException("The TrackConverter was not found.");
+        }
+        
+        // Register the HPS track converter in the heprep converter.
+        converter.register(new HPSTrackConverter());
+        
+        // Remove the existing particle converter.
+        HepRepCollectionConverter particleConverter = converter.findConverter(ReconstructedParticle.class);
+        if (particleConverter != null) {
+            converter.deregister(particleConverter);
+        } else {
+            throw new RuntimeException("The ReconstructedParticleConverter was not found.");
+        }
+        
+        // Register the HPS particle converter.
+        converter.register(new HPSParticleConverter());
+    }
+    
+}

Added: java/trunk/plugin/src/main/java/org/hps/plugin/HPSTrackConverter.java
 =============================================================================
--- java/trunk/plugin/src/main/java/org/hps/plugin/HPSTrackConverter.java	(added)
+++ java/trunk/plugin/src/main/java/org/hps/plugin/HPSTrackConverter.java	Mon Jan  9 13:15:27 2017
@@ -0,0 +1,121 @@
+package org.hps.plugin;
+
+import hep.graphics.heprep.HepRepFactory;
+import hep.graphics.heprep.HepRepInstance;
+import hep.graphics.heprep.HepRepInstanceTree;
+import hep.graphics.heprep.HepRepType;
+import hep.graphics.heprep.HepRepTypeTree;
+import hep.physics.vec.Hep3Vector;
+
+import java.util.List;
+
+import org.lcsim.constants.Constants;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.EventHeader.LCMetaData;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackState;
+import org.lcsim.geometry.Detector;
+import org.lcsim.util.heprep.HepRepCollectionConverter;
+import org.lcsim.util.heprep.LCSimHepRepConverter;
+import org.lcsim.util.swim.HelixSwimmer;
+import org.lcsim.util.swim.HelixSwimmerYField;
+
+/**
+ * Convert an HPS track to heprep for Wired display.
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+public class HPSTrackConverter implements HepRepCollectionConverter {
+
+    private static final double[] ORIGIN = {0, 0, 0.00001};
+    
+    public boolean canHandle(Class k) {
+        return Track.class.isAssignableFrom(k);
+    }
+
+    public void convert(EventHeader event, List collection, HepRepFactory factory, HepRepTypeTree typeTree, HepRepInstanceTree instanceTree) {
+        try {
+            event.getDetector();
+        } catch (Exception x) {
+            return;
+        }
+        
+        if (collection.size() == 0)
+            return;
+        
+        List<Track> trackList = (List<Track>) collection;
+        Track firstTrack = trackList.get(0);
+        
+        LCMetaData meta = event.getMetaData(collection);
+        String name = meta.getName();
+        Detector detector = event.getDetector();
+
+        double trackingRMax = detector.getConstants().get("tracking_region_radius").getValue();
+        double trackingZMax = detector.getConstants().get("tracking_region_zmax").getValue();
+
+        double[] field = detector.getFieldMap().getField(ORIGIN);
+        HelixSwimmer helix = new HelixSwimmerYField(field[1]);
+        
+        HepRepType typeX = factory.createHepRepType(typeTree, name);
+        typeX.addAttValue("layer", LCSimHepRepConverter.PARTICLES_LAYER);
+        typeX.addAttValue("drawAs", "Line");
+
+        typeX.addAttDef("pT", "Transverse momentum", "physics", "");
+        typeX.addAttDef("dedX", "de/Dx", "physics", "GeV");
+        typeX.addAttDef("dedX error", "", "physics", "GeV");
+        typeX.addAttDef("Charge", "", "physics", "");
+        typeX.addAttDef("Chi2", "", "physics", "");
+        typeX.addAttDef("pX", "Momentum X", "physics", "GeV");
+        typeX.addAttDef("pY", "Momentum Y", "physics", "GeV");
+        typeX.addAttDef("pZ", "Momentum Z", "physics", "GeV");
+        typeX.addAttDef("NDF", "Number Degrees Freedom", "physics", "");
+        typeX.addAttDef("Reference Point X", "Reference Point X", "physics", "mm");
+        typeX.addAttDef("Reference Point Y", "Reference Point Y", "physics", "mm");
+        typeX.addAttDef("Reference Point Z", "Reference Point Z", "physics", "mm");
+        typeX.addAttDef("d0", "d0", "physics", "");
+        typeX.addAttDef("phi0", "phi0", "physics", "");
+        typeX.addAttDef("omega", "omega", "physics", "");
+        typeX.addAttDef("z0", "z0", "physics", "");
+        typeX.addAttDef("s", "s", "physics", "");
+
+        for (Track track : trackList) {
+            
+            helix.setTrack(track);
+            double distanceToCylinder = helix.getDistanceToCylinder(trackingRMax, trackingZMax);
+
+            TrackState ts = track.getTrackStates().get(0);
+            double[] referencePoint = ts.getReferencePoint();
+            double[] momentum = ts.getMomentum();
+
+            HepRepInstance instanceX = factory.createHepRepInstance(instanceTree, typeX);
+            double pt = field[2] * Constants.fieldConversion / Math.abs(ts.getParameter(2));
+
+            instanceX.addAttValue("pT", pt);
+            instanceX.addAttValue("dedX", track.getdEdx());
+            instanceX.addAttValue("dedX error", track.getdEdxError());
+            instanceX.addAttValue("Charge", track.getCharge());
+            instanceX.addAttValue("Chi2", track.getChi2());
+            instanceX.addAttValue("pX", momentum[0]);
+            instanceX.addAttValue("pY", momentum[1]);
+            instanceX.addAttValue("pZ", momentum[2]);
+            instanceX.addAttValue("NDF", track.getNDF());
+            instanceX.addAttValue("Reference Point X", referencePoint[0]);
+            instanceX.addAttValue("Reference Point Y", referencePoint[1]);
+            instanceX.addAttValue("Reference Point Z", referencePoint[2]);
+            instanceX.addAttValue("d0", ts.getParameter(0));
+            instanceX.addAttValue("phi0", ts.getParameter(1));
+            instanceX.addAttValue("omega", ts.getParameter(2));
+            instanceX.addAttValue("z0", ts.getParameter(3));
+            instanceX.addAttValue("s", ts.getParameter(4));
+
+            double dAlpha = 10; // 1cm
+
+            for (int k = 0; k < 200; k++) {
+                double d = k * dAlpha;
+                if (d > distanceToCylinder)
+                    break;
+                Hep3Vector point = helix.getPointAtDistance(d);
+                factory.createHepRepPoint(instanceX, point.x(), point.y(), point.z());
+            }
+        }
+    }       
+}