lcsim/src/org/lcsim/recon/tracking/seedtracker
diff -u -r1.2 -r1.3
--- HelixFitter.java 9 Oct 2008 17:47:30 -0000 1.2
+++ HelixFitter.java 13 Oct 2008 01:05:27 -0000 1.3
@@ -23,6 +23,7 @@
import org.lcsim.fit.line.SlopeInterceptLineFit;
import org.lcsim.recon.tracking.seedtracker.diagnostic.ISeedTrackerDiagnostics;
import org.lcsim.fit.zsegment.ZSegmentFit;
+import org.omg.PortableServer._ServantActivatorStub;
/**
*
@@ -35,7 +36,6 @@
private HelicalTrackFit _helix;
private MaterialManager _materialmanager;
private ConstrainHelix _constrain;
- private HelixUtils _helixutils;
private double _bfield = 0.;
private CircleFit _circlefit;
private SlopeInterceptLineFit _linefit;
@@ -47,7 +47,6 @@
*/
public HelixFitter(MaterialManager materialmanager) {
_materialmanager = materialmanager;
- _helixutils = new HelixUtils();
_scattering = new MultipleScattering(_materialmanager);
_constrain = new ConstrainHelix();
}
@@ -56,7 +55,7 @@
// Initialize fit results to null objects
_helix = null;
-
+
// Check that we have set the magnetic field
if (_bfield == 0.) throw new RuntimeException("B Field must be set before calling the Helix fitter");
@@ -66,11 +65,8 @@
// Retrieve list of hits to be fit
List<HelicalTrackHit> hitlist = seed.getHits();
- // Retrieve the last helix fit (if any) for the MS error calculation
- HelicalTrackFit oldhelix = seed.getHelix();
-
// If this is the candidate's first helix fit, first do a fit without MS errors
- if (oldhelix == null) {
+ if (seed.getHelix() == null) {
// Reset the stereo hit positions to their nominal value
for (HelicalTrackHit hit : hitlist) {
@@ -78,31 +74,29 @@
}
// Do the fit
_status = _fitter.fit(hitlist);
- checkfit();
+ SaveFit();
+
+ // Check for unrecoverable fit errors and call appropriate diagnostic
if (_status != FitStatus.Success) {
if(_diag!=null) _diag.fireFitterFitMade(seed, null,_circlefit,_linefit,_zsegmentfit, _status, false);
return false;
}
// Retrieve the helix parameters from this fit
- oldhelix = _fitter.getFit();
+ seed.setHelix(_fitter.getFit());
+
+ // Calculate the multiple scattering angles for this helix
+ seed.setScatterAngles(_scattering.FindScatters(seed.getHelix()));
}
- // Calculate the MS errors
- Map<HelicalTrackHit, MultipleScatter> msmap = _scattering.HelixScatters(oldhelix, hitlist);
-
- // Adjust stereo hit positions and covariance matrices for cross hits
- Map<HelicalTrackHit, Double> pathmap = oldhelix.PathMap();
- for (HelicalTrackHit hit : hitlist) {
- if (hit instanceof HelicalTrackCross) {
- TrackDirection trkdir = _helixutils.CalculateTrackDirection(oldhelix, pathmap.get(hit));
- ((HelicalTrackCross) hit).setTrackDirection(trkdir, oldhelix.covariance());
- }
- }
+ // Update the stereo hit positions and covariance matrices
+ CorrectStereoHits(hitlist, seed.getHelix());
// Do a helix fit including MS errors
- _status = _fitter.fit(hitlist, msmap, oldhelix);
- checkfit();
+ _status = _fitter.fit(hitlist, seed.getMSMap(), seed.getHelix());
+ SaveFit();
+
+ // Check for unrecoverable fit errors and call appropriate diagnostic
if (_status != FitStatus.Success) {
if(_diag!=null) _diag.fireFitterFitMade(seed, null,_circlefit,_linefit,_zsegmentfit, _status, false);
return false;
@@ -113,8 +107,14 @@
// Set the non-holonomic constraint chi square
_constrain.setConstraintChisq(strategy, _helix, hitlist);
+
+ // If the total chi square is below the cut, we have a successful fit
boolean success = _helix.chisqtot() <= strategy.getMaxChisq();
if(_diag!=null) _diag.fireFitterFitMade(seed, _helix, _circlefit, _linefit, _zsegmentfit, _status, success);
+
+ // If fit was successful, set the new multiple scattering angles
+ if (success) seed.setScatterAngles(_scattering.FindScatters(_helix));
+
return success;
}
@@ -123,15 +123,6 @@
return;
}
- public void setBField(double bfield) {
-
- // Save b field and pass it to the multiple scattering and chisq constraint classes
- _bfield = bfield;
- _scattering.setBField(_bfield);
- _constrain.setBField(_bfield);
- return;
- }
-
public HelicalTrackFit getHelix() {
return _helix;
}
@@ -152,14 +143,25 @@
return _zsegmentfit;
}
- private void checkfit() {
+ public void setBField(double bfield) {
+ _bfield = bfield;
+ _scattering.setBField(_bfield);
+ _constrain.setBField(_bfield);
+ return;
+ }
+
+ private void SaveFit() {
+
+ // Default to no fit results when circle fit fails
_circlefit = null;
_linefit = null;
_zsegmentfit = null;
+
+ // Save the circle fit results if they exist
if (_status == FitStatus.CircleFitFailed) return;
- else {
- _circlefit = _fitter.getCircleFit();
- }
+ _circlefit = _fitter.getCircleFit();
+
+ // If we have a circle fit, try to save the line fit / zsegment fit results
if (_status == FitStatus.LineFitFailed) return;
if (_status == FitStatus.ZSegmentFitFailed) return;
_linefit = _fitter.getLineFit();
@@ -167,4 +169,21 @@
return;
}
+
+ private void CorrectStereoHits(List<HelicalTrackHit> hitlist, HelicalTrackFit helix) {
+
+ // Get the PathMap - used to find the track direction at the hit location
+ Map<HelicalTrackHit, Double> pathmap = helix.PathMap();
+
+ // Loop over the hits and look for stereo hits
+ for (HelicalTrackHit hit : hitlist) {
+ if (hit instanceof HelicalTrackCross) {
+
+ // Found a stereo hit - calculate the track direction and pass it to the hit
+ TrackDirection trkdir = HelixUtils.CalculateTrackDirection(helix, pathmap.get(hit));
+ ((HelicalTrackCross) hit).setTrackDirection(trkdir, helix.covariance());
+ }
+ }
+ return;
+ }
}
\ No newline at end of file
lcsim/src/org/lcsim/recon/tracking/seedtracker
diff -u -r1.1 -r1.2
--- MaterialManager.java 27 Aug 2008 17:59:02 -0000 1.1
+++ MaterialManager.java 13 Oct 2008 01:05:27 -0000 1.2
@@ -41,14 +41,15 @@
public class MaterialManager {
private static final boolean DEBUG = false; //enable debug output
- private static final boolean TUBE_ONLY = true; //only use Tube elements for calculating volume.
+ private static final boolean TUBE_ONLY = true; //only use Tube elements for calculating volume.
- private List<MaterialPolyconeSegment> _matpc = new ArrayList<MaterialPolyconeSegment>();
+ private List<MaterialPolyconeSegment> _matpc = new ArrayList<MaterialPolyconeSegment>();
private List<MaterialCylinder> _matcyl = new ArrayList<MaterialCylinder>();
private List<MaterialDisk> _matdsk = new ArrayList<MaterialDisk>();
- private HashMap<ISolid,Double> solid_vol_map = new HashMap<ISolid,Double>(400);
+ private HashMap<ISolid,Double> solid_vol_map = new HashMap<ISolid,Double>(400);
private double _rmax;
-
+ private double _zmax = 1800.;
+
/** Creates a new instance of MaterialManager */
public MaterialManager() {
}
@@ -62,32 +63,32 @@
//
// First find the logical volume associated with the tracker
- IPhysicalVolumeNavigator nav = det.getNavigator();
+ IPhysicalVolumeNavigator nav = det.getNavigator();
ILogicalVolume ltrkr = det.getTrackingVolume().getLogicalVolume();
// Loop over the volumes defined at the compact.xml level
for (IPhysicalVolume pvtree : ltrkr.getDaughters()) {
// Flatten the geometry tree to get all daughters with material
//List<IPhysicalVolume> pvflat = Flatten(pvtree);
- List<UniquePV> pvflat = Flatten(pvtree,nav);
+ List<UniquePV> pvflat = Flatten(pvtree,nav);
+
+// System.out.println(pvflat.size());
+ // Calculate the total volume of material, skip this object if 0
+ VolumeGroupInfo vgi = performVolumeGroupCalculations(pvflat);
+
+ double vtot;
+ if (TUBE_ONLY) vtot = vgi.vtot_tube_only;
+ else vtot = vgi.vtot;
-// System.out.println(pvflat.size());
- // Calculate the total volume of material, skip this object if 0
- VolumeGroupInfo vgi = performVolumeGroupCalculations(pvflat);
-
- double vtot;
- if (TUBE_ONLY) vtot = vgi.vtot_tube_only;
- else vtot = vgi.vtot;
-
-
- if (pvtree.getLogicalVolume().getSolid() instanceof Polycone){
- handlePolycone(pvtree);
- continue;
- }
+
+ if (pvtree.getLogicalVolume().getSolid() instanceof Polycone){
+ handlePolycone(pvtree);
+ continue;
+ }
if (vtot > 0.) {
// Calculate the average radiation length for this volume
-
+
// Determine if this volume should be modeled as barrel or disk
if (isCylinder(vgi.rmin,vgi.rmax,vgi.zmin,vgi.zmax)) {
@@ -96,22 +97,22 @@
double thickness = vtot / (2. * Math.PI * vgi.weighted_r * zlen * vgi.X0);
if (DEBUG){
- System.out.println(pvtree.getName());
- System.out.println("x0: "+vgi.X0 + "| zmin: "+vgi.zmin + "| zmax: "+vgi.zmax + "| vtot: "+vtot + "| thickness: "+thickness +
- "| rmin: "+vgi.rmin + "| rmax: "+vgi.rmax);
- System.out.println();
+ System.out.println(pvtree.getName());
+ System.out.println("x0: "+vgi.X0 + "| zmin: "+vgi.zmin + "| zmax: "+vgi.zmax + "| vtot: "+vtot + "| thickness: "+thickness +
+ "| rmin: "+vgi.rmin + "| rmax: "+vgi.rmax);
+ System.out.println();
}
_matcyl.add(new MaterialCylinder(pvtree, vgi.weighted_r, vgi.zmin, vgi.zmax, thickness));
} else {
-
+
double thickness = vtot / (Math.PI * (vgi.rmax*vgi.rmax - vgi.rmin*vgi.rmin) * vgi.X0);
if (DEBUG){
- System.out.println(pvtree.getName());
- System.out.println("x0: "+vgi.X0 + "| zmin: "+vgi.zmin + "| zmax: "+vgi.zmax + "| vtot: "+vtot + "| thickness: "+thickness +
- "| rmin: "+vgi.rmin + "| rmax: "+vgi.rmax);
- System.out.println();
+ System.out.println(pvtree.getName());
+ System.out.println("x0: "+vgi.X0 + "| zmin: "+vgi.zmin + "| zmax: "+vgi.zmax + "| vtot: "+vtot + "| thickness: "+thickness +
+ "| rmin: "+vgi.rmin + "| rmax: "+vgi.rmax);
+ System.out.println();
}
_matdsk.add(new MaterialDisk(pvtree, vgi.rmin, vgi.rmax, vgi.weighted_z, thickness));
@@ -119,9 +120,9 @@
}
}
- solid_vol_map.clear();
+ solid_vol_map.clear();
- // Find the outer radius of the tracking volume
+ // Find the envelope of the tracking volume
// First loop over all the subdetector elements
IDetectorElement de = det.getDetectorElement();
for (IDetectorElement child : de.getChildren()) {
@@ -133,7 +134,7 @@
IIdentifier id = child.getIdentifier();
// Check if this is the ECalBarrel
- if (dehelper.isEcalBarrel(id)) {
+ if (dehelper.isEcal(id)) {
// Check for geometry info to make sure we don't have an ECal endcap
if (child.hasGeometryInfo()) {
@@ -145,11 +146,27 @@
// Take the inner ECal radius was the outer tracker radius
_rmax = tube.getInnerRadius();
+ System.out.println("Ecal radius = "+_rmax);
}
+ } else {
+ // Have the ECal Endcap volume - loop over the endcaps
+ for (IDetectorElement grandchild : child.getChildren()) {
+ if (dehelper.isEcalEndcapPositive(grandchild.getIdentifier())) {
+ if (grandchild.hasGeometryInfo()) {
+ ISolid solid = grandchild.getGeometry().getLogicalVolume().getSolid();
+ if (solid instanceof Tube) {
+ Tube tube = (Tube) solid;
+ _zmax = grandchild.getGeometry().getPosition().z() - tube.getZHalfLength();
+ System.out.println("ECal inner Z = "+_zmax);
+ }
+ }
+ }
+ }
}
}
}
}
+ return;
}
public List<MaterialCylinder> getMaterialCylinders() {
@@ -161,37 +178,40 @@
}
public List<MaterialPolyconeSegment> getMaterialPolyconeSegments() {
- return _matpc;
+ return _matpc;
}
public double getRMax() {
return _rmax;
}
+ public double getZMax() {
+ return _zmax;
+ }
private List<UniquePV> Flatten(IPhysicalVolume vol, IPhysicalVolumeNavigator nav){
- LinkedList<UniquePV> pvtree = new LinkedList<UniquePV>();
- List<UniquePV> pvflat = new ArrayList<UniquePV>();
- pvtree.add(new UniquePV(vol,nav));
+ LinkedList<UniquePV> pvtree = new LinkedList<UniquePV>();
+ List<UniquePV> pvflat = new ArrayList<UniquePV>();
+ pvtree.add(new UniquePV(vol,nav));
while(pvtree.size()>0) {
- UniquePV upv = pvtree.poll();
- IPhysicalVolume pv = upv.getPV();
+ UniquePV upv = pvtree.poll();
+ IPhysicalVolume pv = upv.getPV();
if (pv.getLogicalVolume().getNumberOfDaughters()==0) {
- pvflat.add(upv);
+ pvflat.add(upv);
}
-
+
else {
for(IPhysicalVolume p : pv.getLogicalVolume().getDaughters()) {
- pvtree.add(upv.createDaughterUniquePV(p));
+ pvtree.add(upv.createDaughterUniquePV(p));
}
}
}
- return pvflat;
+ return pvflat;
}
@@ -201,39 +221,39 @@
// special handling for Polycone...
private void handlePolycone(IPhysicalVolume pv){
- Polycone pc = (Polycone) pv.getLogicalVolume().getSolid();
- IMaterial mat = pv.getLogicalVolume().getMaterial();
+ Polycone pc = (Polycone) pv.getLogicalVolume().getSolid();
+ IMaterial mat = pv.getLogicalVolume().getMaterial();
//Loop through each segment
for (int i = 0; i < pc.getNumberOfZPlanes()-1; i++){
ZPlane zp1 = pc.getZPlane(i);
- ZPlane zp2 = pc.getZPlane(i+1);
+ ZPlane zp2 = pc.getZPlane(i+1);
- double z1 = zp1.getZ();
- double z2 = zp2.getZ();
- double vol = Polycone.getSegmentVolume(zp1, zp2);
- double zlen = Math.abs(z2-z1);
- double ravg = 0.25*(zp1.getRMax() + zp1.getRMin() + zp2.getRMax() + zp2.getRMin());
- double ang = Math.atan2( 0.5 * (zp1.getRMax() + zp1.getRMin() - zp2.getRMax() - zp2.getRMin())
- , zlen );
- double X0 = 10*mat.getRadiationLength()/mat.getDensity();
- double thickness = Math.cos(ang) * vol / (2 * Math.PI * ravg * zlen * X0);
+ double z1 = zp1.getZ();
+ double z2 = zp2.getZ();
+ double vol = Polycone.getSegmentVolume(zp1, zp2);
+ double zlen = Math.abs(z2-z1);
+ double ravg = 0.25*(zp1.getRMax() + zp1.getRMin() + zp2.getRMax() + zp2.getRMin());
+ double ang = Math.atan2( 0.5 * (zp1.getRMax() + zp1.getRMin() - zp2.getRMax() - zp2.getRMin())
+ , zlen );
+ double X0 = 10*mat.getRadiationLength()/mat.getDensity();
+ double thickness = Math.cos(ang) * vol / (2 * Math.PI * ravg * zlen * X0);
//This is a cylinder
if(zp1.getRMax()==zp2.getRMax() && zp1.getRMin()==zp2.getRMin()) {
_matcyl.add(new MaterialCylinder(pv, ravg, Math.min(z1,z2), Math.max(z1,z2), thickness));
- if(DEBUG){
- System.out.println("Cylindrical segment of "+pv.getName());
- System.out.println("zmin = "+ z1 + "| zmax = "+z2 + "| ravg = "+ravg + "| thickness = "+thickness);
+ if(DEBUG){
+ System.out.println("Cylindrical segment of "+pv.getName());
+ System.out.println("zmin = "+ z1 + "| zmax = "+z2 + "| ravg = "+ravg + "| thickness = "+thickness);
}
}
- //Otherwise this is a non-cylindrical polycone segment
+ //Otherwise this is a non-cylindrical polycone segment
else {
- _matpc.add(new MaterialPolyconeSegment(pv, zp1, zp2, thickness, ang));
- if(DEBUG){
- System.out.println("Non-Cylindrical segment of "+pv.getName());
- System.out.println("ZPlane 1: "+zp1.toString() + "| ZPlane 2: "+zp2.toString() + "| thickness = "+thickness);
+ _matpc.add(new MaterialPolyconeSegment(pv, zp1, zp2, thickness, ang));
+ if(DEBUG){
+ System.out.println("Non-Cylindrical segment of "+pv.getName());
+ System.out.println("ZPlane 1: "+zp1.toString() + "| ZPlane 2: "+zp2.toString() + "| thickness = "+thickness);
}
}
}
@@ -243,185 +263,184 @@
* A "struct" holding geometry information about a single physical volume
*/
class VolumeInfo {
- double rmax = 0.0;
- double rmin = 1.e10;
+ double rmax = 0.0;
+ double rmin = 1.e10;
double zmin = 1.e10;
- double zmax = -1.e10;
+ double zmax = -1.e10;
}
/**
- * A "struct" holding geometry information about lists of physical volumes
- */
+ * A "struct" holding geometry information about lists of physical volumes
+ */
class VolumeGroupInfo{
- double rmax = 0.0;
- double rmin = 1.e10;
- double zmin = 1.e10;
- double zmax = -1.e10;
- double X0 = 0.0;
- double weighted_r = 0.0;
- double weighted_z = 0.0;
- double vtot_tube_only = 0.;
- double vtot = 0.0;
+ double rmax = 0.0;
+ double rmin = 1.e10;
+ double zmin = 1.e10;
+ double zmax = -1.e10;
+ double X0 = 0.0;
+ double weighted_r = 0.0;
+ double weighted_z = 0.0;
+ double vtot_tube_only = 0.;
+ double vtot = 0.0;
}
-
+
//This function performs all the calculations on lists of physical volumes
private VolumeGroupInfo performVolumeGroupCalculations(List<UniquePV> volgroup) {
-
- VolumeGroupInfo vgi = new VolumeGroupInfo();
-
+
+ VolumeGroupInfo vgi = new VolumeGroupInfo();
+
//If we have a top-level polycone, don't bother doing anything, because it'll be handled specially
if (volgroup.size()==1 && volgroup.get(0).getSolid() instanceof Polycone){
- return vgi;
+ return vgi;
}
-
+
//The normal case
- double totwgt = 0.0;
- if (DEBUG && volgroup.isEmpty()) System.out.println("Empty volume group...");
+ double totwgt = 0.0;
+ if (DEBUG && volgroup.isEmpty()) System.out.println("Empty volume group...");
for(UniquePV pv : volgroup) {
-
+
//increment total volume
- double vol = this.getVolumeOfSolid(pv.getSolid());
- if (pv.getSolid() instanceof Tube) vgi.vtot_tube_only += vol;
+ double vol = this.getVolumeOfSolid(pv.getSolid());
+ if (pv.getSolid() instanceof Tube) vgi.vtot_tube_only += vol;
vgi.vtot+=vol;
//calculate weighted R / Z / Radiation Length
- VolumeInfo vi = performVolumeCalculations(pv);
- IMaterial mat = pv.getPV().getLogicalVolume().getMaterial();
- double matX0 = 10.0 * mat.getRadiationLength() / mat.getDensity();
- double wgt = vol / matX0;
- double z0 = pv.getLtoGTransform().getTranslation().z();
- vgi.weighted_r+= 0.5 * (vi.rmin + vi.rmax) * wgt;
- vgi.weighted_z+= z0 * wgt;
- totwgt += wgt;
-
- //grab (z/r)(mins/maxes)
+ VolumeInfo vi = performVolumeCalculations(pv);
+ IMaterial mat = pv.getPV().getLogicalVolume().getMaterial();
+ double matX0 = 10.0 * mat.getRadiationLength() / mat.getDensity();
+ double wgt = vol / matX0;
+ double z0 = pv.getLtoGTransform().getTranslation().z();
+ vgi.weighted_r+= 0.5 * (vi.rmin + vi.rmax) * wgt;
+ vgi.weighted_z+= z0 * wgt;
+ totwgt += wgt;
+
+ //grab (z/r)(mins/maxes)
vgi.zmin = Math.min(vi.zmin,vgi.zmin);
vgi.zmax = Math.max(vi.zmax,vgi.zmax);
vgi.rmin = Math.min(vi.rmin,vgi.rmin);
- vgi.rmax = Math.max(vi.rmax,vgi.rmax);
-
+ vgi.rmax = Math.max(vi.rmax,vgi.rmax);
+
}
-
+
//finish weighted R/Z calculations + perform X0 calculation
if (totwgt > 0.) {
vgi.weighted_r /= totwgt;
- vgi.weighted_z /= totwgt;
- vgi.X0 = vgi.vtot / totwgt;
- }
-
- return vgi;
+ vgi.weighted_z /= totwgt;
+ vgi.X0 = vgi.vtot / totwgt;
+ }
+
+ return vgi;
}
-
+
private double getVolumeOfSolid(ISolid solid){
if (solid_vol_map.containsKey(solid)){
- return solid_vol_map.get(solid).doubleValue();
+ return solid_vol_map.get(solid).doubleValue();
}
-
+
else {
- double vol;
- try{ vol = solid.getCubicVolume(); }
- catch(Exception e) { vol = 0.0; }
- solid_vol_map.put(solid,vol);
- return vol;
+ double vol;
+ try{ vol = solid.getCubicVolume(); } catch(Exception e) { vol = 0.0; }
+ solid_vol_map.put(solid,vol);
+ return vol;
}
}
-
+
private VolumeInfo performVolumeCalculations(UniquePV pv){
-
- VolumeInfo vi = new VolumeInfo();
+
+ VolumeInfo vi = new VolumeInfo();
ISolid solid = pv.getSolid();
-
+
//ASSUMPTION: tube is along z-axis and has center at r = 0
if (solid instanceof Tube) {
Tube tube = (Tube) solid;
double z0 = pv.getLtoGTransform().getTranslation().z();
- vi.zmax = z0 + tube.getZHalfLength();
- vi.zmin = z0 - tube.getZHalfLength();
- vi.rmin = tube.getInnerRadius();
- vi.rmax = tube.getOuterRadius();
+ vi.zmax = z0 + tube.getZHalfLength();
+ vi.zmin = z0 - tube.getZHalfLength();
+ vi.rmin = tube.getInnerRadius();
+ vi.rmax = tube.getOuterRadius();
}
-
+
else if (solid instanceof Box) {
- Box box = (Box) solid;
+ Box box = (Box) solid;
for (Point3D p : box.getVertices()){
Hep3Vector transformed = pv.localToGlobal(p.getHep3Vector());
vi.zmin = Math.min(transformed.z(), vi.zmin);
vi.zmax = Math.max(transformed.z(), vi.zmax);
- double r = Math.sqrt(transformed.x() * transformed.x() + transformed.y() * transformed.y());
+ double r = Math.sqrt(transformed.x() * transformed.x() + transformed.y() * transformed.y());
vi.rmin = Math.min(vi.rmin, r);
- vi.rmax = Math.max(vi.rmax, r);
+ vi.rmax = Math.max(vi.rmax, r);
}
}
-
- //Note: this information will NOT be used most of the time...
- // Polycones that are top-level elements (e.g. the beampipe) are
- // handled specially (since the radiation length is a function of z).
+
+ //Note: this information will NOT be used most of the time...
+ // Polycones that are top-level elements (e.g. the beampipe) are
+ // handled specially (since the radiation length is a function of z).
// The information here will only be used in case a top-level element
- // has a subelement that is a Polycone, in which case it'll be
- // approximated as the smallest possible cylinder.
+ // has a subelement that is a Polycone, in which case it'll be
+ // approximated as the smallest possible cylinder.
else if (solid instanceof Polycone) {
- Polycone pc = (Polycone) solid;
- List<Polycone.ZPlane> zplanes = pc.getZPlanes();
-
+ Polycone pc = (Polycone) solid;
+ List<Polycone.ZPlane> zplanes = pc.getZPlanes();
+
//For now, just take the minimum rmin and rmax of the polycone
for (Polycone.ZPlane z : zplanes){
if (z.getRMax()>0 && z.getRMin()>0) {
vi.rmin = Math.min(vi.rmin,z.getRMin());
- vi.rmax = vi.rmax > 0. ? Math.min(vi.rmax,z.getRMax()) : z.getRMax();
+ vi.rmax = vi.rmax > 0. ? Math.min(vi.rmax,z.getRMax()) : z.getRMax();
}
}
-
- vi.zmin = pc.getZPlanes().get(0).getZ();
- vi.zmax = pc.getZPlanes().get(pc.getZPlanes().size()-1).getZ();
-
- //check for wrong order
+
+ vi.zmin = pc.getZPlanes().get(0).getZ();
+ vi.zmax = pc.getZPlanes().get(pc.getZPlanes().size()-1).getZ();
+
+ //check for wrong order
if (vi.zmin > vi.zmax) {
- double temp = vi.zmin;
+ double temp = vi.zmin;
vi.zmin = vi.zmax;
- vi.zmax = temp;
+ vi.zmax = temp;
}
}
-
- return vi;
+
+ return vi;
}
-
+
/**
- * A UniquePV is a wrapper around IPhysicalVolumePath which provides
- * some convenience methods and caches transformations.
+ * A UniquePV is a wrapper around IPhysicalVolumePath which provides
+ * some convenience methods and caches transformations.
*/
class UniquePV{
- IPhysicalVolumePath path;
- IPhysicalVolumeNavigator nav;
- ITransform3D transform = null;
+ IPhysicalVolumePath path;
+ IPhysicalVolumeNavigator nav;
+ ITransform3D transform = null;
/**
- * Generates a top-level UniquePV.
+ * Generates a top-level UniquePV.
* @param root The top-level IPhysicalVolume
* @param navigator The IPhysicalVolumeNavigator associated with the detector
*/
public UniquePV(IPhysicalVolume root, IPhysicalVolumeNavigator navigator){
- path = new PhysicalVolumePath();
- nav = navigator;
- path.add(root);
+ path = new PhysicalVolumePath();
+ nav = navigator;
+ path.add(root);
}
/**
* Generates a UniquePV from a path. (Shallow copy of path)
- * @param path
+ * @param path
* @param navigator
*/
public UniquePV(IPhysicalVolumePath path, IPhysicalVolumeNavigator navigator){
- this.path = path;
- nav = navigator;
+ this.path = path;
+ nav = navigator;
}
/**
- * Returns the IPhysicalVolume (the last element of the path)
+ * Returns the IPhysicalVolume (the last element of the path)
*/
public IPhysicalVolume getPV(){
return path.getLeafVolume();
@@ -433,10 +452,10 @@
* @return
*/
public UniquePV createDaughterUniquePV(IPhysicalVolume daughter){
- IPhysicalVolumePath np = new PhysicalVolumePath();
- np.addAll(path);
- np.add(daughter);
- return new UniquePV(np,nav);
+ IPhysicalVolumePath np = new PhysicalVolumePath();
+ np.addAll(path);
+ np.add(daughter);
+ return new UniquePV(np,nav);
}
@@ -447,34 +466,34 @@
*/
public Hep3Vector localToGlobal(Hep3Vector v) {
- return getLtoGTransform().transformed(v);
+ return getLtoGTransform().transformed(v);
}
/**
- * Returns the solid associated with the physical volume.
+ * Returns the solid associated with the physical volume.
* @return
*/
public ISolid getSolid(){
- return this.getPV().getLogicalVolume().getSolid();
+ return this.getPV().getLogicalVolume().getSolid();
}
/**
* Returns the local-to-global transform
- * @return an ITransform3D from local coordinates to global coordinates.
+ * @return an ITransform3D from local coordinates to global coordinates.
*/
public ITransform3D getLtoGTransform() {
if (transform == null) {
- transform = nav.getTransform(path);
+ transform = nav.getTransform(path);
}
- return transform;
+ return transform;
}
- @Override
+ @Override
public String toString(){
- return path.toString();
+ return path.toString();
}
}
-
-
-
+
+
+
}
lcsim/src/org/lcsim/recon/tracking/seedtracker
diff -u -r1.2 -r1.3
--- MultipleScattering.java 9 Oct 2008 17:47:30 -0000 1.2
+++ MultipleScattering.java 13 Oct 2008 01:05:28 -0000 1.3
@@ -12,6 +12,7 @@
import hep.physics.vec.VecOp;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -28,7 +29,6 @@
* @version 1.0
*/
public class MultipleScattering {
- private HelixUtils _hutil = new HelixUtils();
private MaterialManager _materialmanager;
private double _bfield = 0.;
private int _mxint = 10;
@@ -41,77 +41,7 @@
public MultipleScattering(MaterialManager materialmanager) {
_materialmanager = materialmanager;
}
-
- /**
- * Calculate the multiple scattering errors for a given helix.
- * The Helix PathMap is used to determine the x-y path length
- * from the DCA to the hits on the helix.
- *
- *
- * @param helix HelicalTrackFit that we want the ms errors for
- * @return map containing the MultipleScatter objects for each hit
- */
- public Map<HelicalTrackHit, MultipleScatter> HelixScatters(HelicalTrackFit helix, List<HelicalTrackHit> hitlist) {
-
- // Create an empty map to hold the multiple scattering errors
- Map<HelicalTrackHit, MultipleScatter> msmap = new HashMap<HelicalTrackHit, MultipleScatter>();
-
- // Retreive the x-y path lengths and calculate sin^2(theta) for this helix
- Map<HelicalTrackHit, Double> pathmap = helix.PathMap();
- double sth2 = Math.pow(helix.sth(), 2);
-
- // Make sure all hits have x-y path lengths. Hits added since the last fit
- // won't have path lengths, so estimate the path length measured from the DCA
- for (HelicalTrackHit hit : hitlist) {
- if (!pathmap.containsKey(hit)) {
- pathmap.put(hit, (Double) _hutil.PathLength(helix, hit));
- }
- }
-
- // Construct a list of material scatterings for this helix
- List<ScatterAngle> scatters = FindScatters(helix);
-
- // Loop over the hits on the helix and calculate the multiple scattering errors
- for (HelicalTrackHit hit : hitlist) {
- double hitpath = pathmap.get(hit);
-
- // Loop over scattering points and sum in quadrature ms errors for this hit.
- // It is assumed that we can ignore ms correlations during the track-finding stage.
- double rphi_ms2 = 0.;
- double z_ms2 = 0.;
- for (ScatterAngle scat : scatters) {
-
- // Find the x-y path length to this scatter
- double scatpath = scat.PathLen();
-
- // If the scatter is before the hit, calculate the ms errors for this scatter
- if (scatpath < hitpath) {
-
- // Get the multiple scattering plane angle for this scatter
- double angle = scat.Angle();
-
- // Sum in quadrature the r-phi ms errors. It is assumed that we
- // can ignore track curvature in calculating these errors during
- // the track-finding stage.
- rphi_ms2 += Math.pow((hitpath - scatpath) * angle, 2);
-
- // Sum in quadrature the z ms errors assuming a barrel geometry where
- // the path length is fixed. While z is fixed for disk detectors, we
- // still do a z vs s fit by assuming the track direction is reasonably
- // well known and converting the radial measurement error into an effective
- // z coordinate error.
- z_ms2 += Math.pow((hitpath - scatpath) * angle / sth2, 2);
- }
- }
-
- // Create a new MultipleScatter object and store it in the map of ms errors
- MultipleScatter ms = new MultipleScatter(Math.sqrt(rphi_ms2), Math.sqrt(z_ms2));
- msmap.put(hit, ms);
- }
-
- return msmap;
- }
-
+
/**
* Find the path lengths and multiple scattering angles for each
* intersection of the helix with tracker material
@@ -131,22 +61,19 @@
List<MaterialDisk> matdsk = _materialmanager.getMaterialDisks();
// Find the largest path length to a hit
- double smax = 0.;
- for (Map.Entry<HelicalTrackHit, Double> mapentry : helix.PathMap().entrySet()) {
- smax = Math.max(smax, mapentry.getValue());
- }
+ double smax = 9999.;
// We can't go further than the ECal, however
double rmax = _materialmanager.getRMax();
- List<Double> slist = _hutil.PathToCylinder(helix, rmax, smax, 1);
- for (Double s : slist) {
- smax = Math.min(smax, s);
- }
+ List<Double> slist = HelixUtils.PathToCylinder(helix, rmax, smax, 1);
+ if (slist.size() > 0) smax = Math.min(smax, slist.get(0));
+ double zmax = _materialmanager.getZMax();
+ smax = Math.min(smax, HelixUtils.PathToZPlane(helix, zmax));
for (MaterialDisk disk : matdsk) {
- double s = _hutil.PathToZPlane(helix, disk.z());
+ double s = HelixUtils.PathToZPlane(helix, disk.z());
if (s > 0. && s < smax) {
- Hep3Vector pos = _hutil.PointOnHelix(helix, s);
+ Hep3Vector pos = HelixUtils.PointOnHelix(helix, s);
double r = Math.sqrt(Math.pow(pos.x(), 2) + Math.pow(pos.y(),2));
if (r >= disk.rmin() && r <= disk.rmax()) {
double cth = Math.abs(helix.cth());
@@ -159,18 +86,18 @@
for (MaterialCylinder cyl : matcyl) {
double r = cyl.radius();
- double scmin = _hutil.PathToZPlane(helix, cyl.zmin());
- double scmax = _hutil.PathToZPlane(helix, cyl.zmax());
+ double scmin = HelixUtils.PathToZPlane(helix, cyl.zmin());
+ double scmax = HelixUtils.PathToZPlane(helix, cyl.zmax());
if (scmin > scmax) {
double temp = scmin;
scmin = scmax;
scmax = temp;
}
- List<Double> pathlist = _hutil.PathToCylinder(helix, r, smax, _mxint);
+ List<Double> pathlist = HelixUtils.PathToCylinder(helix, r, smax, _mxint);
for (Double s : pathlist) {
if (s > scmin && s < scmax) {
- Hep3Vector dir = _hutil.Direction(helix, s);
- Hep3Vector pos = _hutil.PointOnHelix(helix, s);
+ Hep3Vector dir = HelixUtils.Direction(helix, s);
+ Hep3Vector pos = HelixUtils.PointOnHelix(helix, s);
Hep3Vector rhat = VecOp.unit(new BasicHep3Vector(pos.x(), pos.y(), 0.));
double cth = Math.abs(VecOp.dot(dir, rhat));
double radlen = cyl.ThicknessInRL() / Math.max(cth, 0.001);
@@ -179,9 +106,58 @@
}
}
}
+
+ // Sort the multiple scatters by their path length
+ Collections.sort(scatters);
return scatters;
}
+ public static MultipleScatter CalculateScatter(HelicalTrackHit hit, HelicalTrackFit helix, List<ScatterAngle> scatters) {
+
+ // Retreive the x-y path length and calculate sin^2(theta) for this helix
+ double sth2 = Math.pow(helix.sth(), 2);
+
+ // Make sure the hit has an x-y path lengths. Hits added since the last fit
+ // won't have path lengths, so estimate the path length measured from the DCA
+ Map<HelicalTrackHit, Double> pathmap = helix.PathMap();
+ if (!pathmap.containsKey(hit)) {
+ pathmap.put(hit, (Double) HelixUtils.PathLength(helix, hit));
+ }
+
+ double hitpath = pathmap.get(hit);
+
+ // Loop over scattering points and sum in quadrature ms errors for this hit.
+ // It is assumed that we can ignore ms correlations during the track-finding stage.
+ double rphi_ms2 = 0.;
+ double z_ms2 = 0.;
+ for (ScatterAngle scat : scatters) {
+
+ // Find the x-y path length to this scatter
+ double scatpath = scat.PathLen();
+
+ // If the scatter is before the hit, calculate the ms errors for this scatter
+ if (scatpath > hitpath) break;
+
+ // Get the multiple scattering plane angle for this scatter
+ double angle = scat.Angle();
+
+ // Sum in quadrature the r-phi ms errors. It is assumed that we
+ // can ignore track curvature in calculating these errors during
+ // the track-finding stage.
+ rphi_ms2 += Math.pow((hitpath - scatpath) * angle, 2);
+
+ // Sum in quadrature the z ms errors assuming a barrel geometry where
+ // the path length is fixed. While z is fixed for disk detectors, we
+ // still do a z vs s fit by assuming the track direction is reasonably
+ // well known and converting the radial measurement error into an effective
+ // z coordinate error.
+ z_ms2 += Math.pow((hitpath - scatpath) * angle / sth2, 2);
+ }
+
+ // Return the requested MultipleScatter
+ return new MultipleScatter(Math.sqrt(rphi_ms2), Math.sqrt(z_ms2));
+ }
+
public void setBField(double bfield) {
_bfield = bfield;
return;
@@ -192,4 +168,4 @@
double angle = (0.0136 / p) * Math.sqrt(radlength) * (1.0 + 0.038 * Math.log(radlength));
return angle;
}
-}
+}
\ No newline at end of file