Author: [log in to unmask] Date: Wed Jan 18 11:57:10 2017 New Revision: 4668 Log: Simple Analysis Driver to compare SimTrackerHit positions with strip cluster positions in the sensors. Added: java/trunk/analysis/src/main/java/org/hps/analysis/MC/ java/trunk/analysis/src/main/java/org/hps/analysis/MC/MCTrackerHitResidualAnalysisDriver.java Added: java/trunk/analysis/src/main/java/org/hps/analysis/MC/MCTrackerHitResidualAnalysisDriver.java ============================================================================= --- java/trunk/analysis/src/main/java/org/hps/analysis/MC/MCTrackerHitResidualAnalysisDriver.java (added) +++ java/trunk/analysis/src/main/java/org/hps/analysis/MC/MCTrackerHitResidualAnalysisDriver.java Wed Jan 18 11:57:10 2017 @@ -0,0 +1,213 @@ +package org.hps.analysis.MC; + +import hep.physics.matrix.SymmetricMatrix; +import hep.physics.vec.BasicHep3Vector; +import hep.physics.vec.Hep3Vector; +import java.io.IOException; +import static java.lang.Math.sqrt; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.hps.analysis.examples.DetailedAnalysisDriver; +import org.hps.recon.tracking.TrackUtils; +import org.lcsim.detector.DetectorElementStore; +import org.lcsim.detector.IDetectorElement; +import org.lcsim.detector.IRotation3D; +import org.lcsim.detector.ITransform3D; +import org.lcsim.detector.ITranslation3D; +import org.lcsim.detector.identifier.IExpandedIdentifier; +import org.lcsim.detector.identifier.IIdentifier; +import org.lcsim.detector.identifier.IIdentifierDictionary; +import org.lcsim.detector.tracker.silicon.HpsSiSensor; +import org.lcsim.detector.tracker.silicon.SiSensor; +import org.lcsim.event.EventHeader; +import org.lcsim.event.RawTrackerHit; +import org.lcsim.event.RelationalTable; +import org.lcsim.event.SimTrackerHit; +import org.lcsim.event.Track; +import org.lcsim.event.TrackerHit; +import org.lcsim.util.Driver; +import org.lcsim.util.aida.AIDA; + +/** + * Simple Driver to compare positions of the SimTrackerHits with the TrackerHits + * created by the full SVT simulation. This analyzes SimTrackerHits and + * TrackerHits separately, so should only be run on MC events with single + * tracks. TODO follow the link back from the TrackerHit to the SimTrackerHit to + * get a 1-to-1 correspondence between the hits. + * + * @author Norman A Graf + * + * @version $Id: + */ +public class MCTrackerHitResidualAnalysisDriver extends Driver +{ + + private boolean debug = false; + AIDA aida = AIDA.defaultInstance(); + String aidaFileName = "MCTrackerHitResidualAnalysisDriverPlots"; + String aidaFileType = "aida"; + + @Override + protected void process(EventHeader event) + { + // a map of MC hit positions keyed on sensor name + Map<String, List<Double>> mcSensorHitPositionMap = new HashMap<String, List<Double>>(); + // a map of Tracker hit positions keyed on sensor name + Map<String, List<Double>> trackSensorHitPositionMap = new HashMap<String, List<Double>>(); + + // First step is to get the SimTrackerHits and determine their location + // in local coordinates. + List<SimTrackerHit> simHits = event.get(SimTrackerHit.class, "TrackerHits"); + System.out.println("found " + simHits.size() + " SimTrackerHits"); + // loop over each hit + for (SimTrackerHit hit : simHits) { + // get the hit's position in global coordinates.. + Hep3Vector globalPos = hit.getPositionVec(); + // get the transformation from global to local + ITransform3D g2lXform = hit.getDetectorElement().getGeometry().getGlobalToLocal(); + //System.out.println("transform matrix: " + g2lXform); + IRotation3D rotMat = g2lXform.getRotation(); + //System.out.println("rotation matrix: " + rotMat); + ITranslation3D transMat = g2lXform.getTranslation(); + //System.out.println("translation vector: " + transMat); + // check that we can reproduce the local origin + ITransform3D l2gXform = hit.getDetectorElement().getGeometry().getLocalToGlobal(); + Hep3Vector o = new BasicHep3Vector(); + //System.out.println("origin: " + o); + // tranform the local origin into global position + Hep3Vector localOriginInglobal = l2gXform.transformed(o); + //System.out.println("transformed local to global: " + localOriginInglobal); + // and now back... + //System.out.println("and back: " + g2lXform.transformed(localOriginInglobal)); + // hmmm, so why is this not the same as the translation vector of the transform? + //Note: + // u is the measurement direction perpendicular to the strip + // v is along the strip + // w is normal to the wafer plane + + Hep3Vector localPos = g2lXform.transformed(globalPos); +// System.out.println("Layer: " + hit.getLayer() + " Layer Number: " + hit.getLayerNumber() + " ID: " + hit.getCellID() + " " + hit.getDetectorElement().getName()); +// System.out.println("global position " + globalPos); +// System.out.println("local position " + localPos); + String sensorName = hit.getDetectorElement().getName(); + double u = localPos.x(); + System.out.println("MC " + hit.getDetectorElement().getName() + " u= " + localPos.x()); + if (mcSensorHitPositionMap.containsKey(sensorName)) { + List<Double> vals = mcSensorHitPositionMap.get(sensorName); + vals.add(u); + } else { + List<Double> vals = new ArrayList<Double>(); + vals.add(u); + mcSensorHitPositionMap.put(sensorName, vals); + } + } // end of loop over SimTrackerHits + + // let's look at Tracker hits + setupSensors(event); + RelationalTable hitToStrips = TrackUtils.getHitToStripsTable(event); + RelationalTable hitToRotated = TrackUtils.getHitToRotatedTable(event); + List<Track> tracks = event.get(Track.class, "MatchedTracks"); + System.out.println("found " + tracks.size() + " tracks"); + for (Track t : tracks) { + List<TrackerHit> hits = t.getTrackerHits(); + System.out.println("track has " + hits.size() + " hits"); + if (hits.size() == 6) { + for (TrackerHit h : hits) { + Set<TrackerHit> stripList = hitToStrips.allFrom(hitToRotated.from(h)); + for (TrackerHit strip : stripList) { + List rawHits = strip.getRawHits(); + HpsSiSensor sensor = null; + for (Object o : rawHits) { + RawTrackerHit rth = (RawTrackerHit) o; + // TODO figure out why the following collection is always null + //List<SimTrackerHit> stipMCHits = rth.getSimTrackerHits(); + sensor = (HpsSiSensor) rth.getDetectorElement(); + } + int nHitsInCluster = rawHits.size(); + String sensorName = sensor.getName(); + Hep3Vector posG = new BasicHep3Vector(strip.getPosition()); + Hep3Vector posL = sensor.getGeometry().getGlobalToLocal().transformed(posG); + double u = posL.x(); + double mcU = mcSensorHitPositionMap.get(sensorName).get(0); + + aida.cloud1D(sensorName + "_" + nHitsInCluster + "_hitCluster meas - MC u position").fill(u - mcU); + // now for the uncertainty in u + SymmetricMatrix covG = new SymmetricMatrix(3, strip.getCovMatrix(), true); + SymmetricMatrix covL = sensor.getGeometry().getGlobalToLocal().transformed(covG); + double sigmaU = sqrt(covL.e(0, 0)); + aida.cloud1D(sensorName + "_" + nHitsInCluster + "_hitCluster meas - MC u position pull").fill((u - mcU) / sigmaU); + aida.cloud1D(sensorName + " number of hits in cluster").fill(nHitsInCluster); + System.out.println(" Track Hit: " + nHitsInCluster + " " + sensorName + " u " + u + " mcU " + mcU + " sigmaU " + sigmaU); + } + } + } // end of loop over six-hit tracks + } // end of loop over tracks + } + + protected void endOfData() + { + try { + aida.saveAs(aidaFileName + "." + aidaFileType); + } catch (IOException ex) { + Logger.getLogger(DetailedAnalysisDriver.class.getName()).log(Level.SEVERE, null, ex); + } + } + + public void setAidaFileName(String s) + { + aidaFileName = s; + } + + public void setAidaFileType(String s) + { + aidaFileType = s; + } + + private void setupSensors(EventHeader event) + { + List<RawTrackerHit> rawTrackerHits = null; + if (event.hasCollection(RawTrackerHit.class, "SVTRawTrackerHits")) { + rawTrackerHits = event.get(RawTrackerHit.class, "SVTRawTrackerHits"); + } + if (event.hasCollection(RawTrackerHit.class, "RawTrackerHitMaker_RawTrackerHits")) { + rawTrackerHits = event.get(RawTrackerHit.class, "RawTrackerHitMaker_RawTrackerHits"); + } + EventHeader.LCMetaData meta = event.getMetaData(rawTrackerHits); + // Get the ID dictionary and field information. + IIdentifierDictionary dict = meta.getIDDecoder().getSubdetector().getDetectorElement().getIdentifierHelper().getIdentifierDictionary(); + int fieldIdx = dict.getFieldIndex("side"); + int sideIdx = dict.getFieldIndex("strip"); + for (RawTrackerHit hit : rawTrackerHits) { + // The "side" and "strip" fields needs to be stripped from the ID for sensor lookup. + IExpandedIdentifier expId = dict.unpack(hit.getIdentifier()); + expId.setValue(fieldIdx, 0); + expId.setValue(sideIdx, 0); + IIdentifier strippedId = dict.pack(expId); + // Find the sensor DetectorElement. + List<IDetectorElement> des = DetectorElementStore.getInstance().find(strippedId); + if (des == null || des.size() == 0) { + throw new RuntimeException("Failed to find any DetectorElements with stripped ID <0x" + Long.toHexString(strippedId.getValue()) + ">."); + } else if (des.size() == 1) { + hit.setDetectorElement((SiSensor) des.get(0)); + } else { + // Use first sensor found, which should work unless there are sensors with duplicate IDs. + for (IDetectorElement de : des) { + if (de instanceof SiSensor) { + hit.setDetectorElement((SiSensor) de); + break; + } + } + } + // No sensor was found. + if (hit.getDetectorElement() == null) { + throw new RuntimeException("No sensor was found for hit with stripped ID <0x" + Long.toHexString(strippedId.getValue()) + ">."); + } + } + } + +}