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()); + } + } + } +}