Commit in lcsim/src/org/lcsim/recon/tracking/seedtracker/strategybuilder on MAIN
AllPassFilter.java+24added 1.1
DefaultLayerWeight.java+48added 1.1
DetectorMismatchException.java+16added 1.1
DumbLayer.java+49added 1.1
ExampleDriver.java+40added 1.1
IParticleFilter.java+38added 1.1
IStrategyBuilder.java+101added 1.1
LayerWeight.java+339added 1.1
NonPromptFilter.java+35added 1.1
RunStrategyBuilder.java+195added 1.1
StrategyBasedFilter.java+48added 1.1
StrategyBuilder.java+506added 1.1
StrategyBuilderUtils.java+169added 1.1
StrategyCombiner.java+50added 1.1
SubsetScorer.java+94added 1.1
+1752
15 added files
Refactor seedtracker to recon.tracking

lcsim/src/org/lcsim/recon/tracking/seedtracker/strategybuilder
AllPassFilter.java added at 1.1
diff -N AllPassFilter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ AllPassFilter.java	27 Aug 2008 17:55:49 -0000	1.1
@@ -0,0 +1,24 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.lcsim.recon.tracking.seedtracker.strategybuilder;
+
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.MCParticle;
+
+/**
+ *
+ * @author cozzy
+ */
+public class AllPassFilter implements IParticleFilter {
+
+    public boolean passes(MCParticle p) {
+        return true; 
+    }
+
+    public void setEvent(EventHeader event){
+        return; 
+    }
+}

lcsim/src/org/lcsim/recon/tracking/seedtracker/strategybuilder
DefaultLayerWeight.java added at 1.1
diff -N DefaultLayerWeight.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ DefaultLayerWeight.java	27 Aug 2008 17:55:49 -0000	1.1
@@ -0,0 +1,48 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.lcsim.recon.tracking.seedtracker.strategybuilder;
+
+/**
+ *The layer weighting scheme used by default by StrategyBuilder if no other is
+ * provided. It's loaded from a resource based on the name of the detector. 
+ * 
+ * After construction, the LayerWeight object may be accessed using getWeight(); 
+ * 
+ * @author cozzy
+ */
+public class DefaultLayerWeight {
+
+    private static final String prefix = "default_weights_";
+    private static final String suffix = ".xml"; 
+
+    private LayerWeight weight;
+    public DefaultLayerWeight(String detectorName){
+        try { 
+
+            // This is kind of screwy: if the detector name has a period in it,
+            // then loading the resource would normally throw an exception. 
+            // We can fix this by replacing "." with "%2E" (URL encoding).  
+            // It's probably best to avoid having periods in detector names
+            // though. 
+            
+            detectorName = detectorName.replace(".","%2E"); 
+            weight = LayerWeight.getLayerWeightFromResource(LayerWeight.getDefaultResourcePrefix()+prefix+detectorName+suffix);
+        } catch(Exception e) {
+            System.out.println("WARNING: could not find default layer weights for detector "+detectorName+". Falling back to empty layer weights with possibly insane default parameters.");
+            weight = new LayerWeight(); 
+        }
+    }   
+    /**
+     * Return the constructed weight for the detector. 
+     * @return The default weight for the detector name specified in the 
+     * constructor, or, if nothing is found, then an unmodified LayerWeight 
+     * object. 
+     */
+    public LayerWeight getWeight(){
+        return weight; 
+    }
+
+}

lcsim/src/org/lcsim/recon/tracking/seedtracker/strategybuilder
DetectorMismatchException.java added at 1.1
diff -N DetectorMismatchException.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ DetectorMismatchException.java	27 Aug 2008 17:55:49 -0000	1.1
@@ -0,0 +1,16 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.lcsim.recon.tracking.seedtracker.strategybuilder;
+
+/**
+ *
+ * @author cozzy
+ */
+public class DetectorMismatchException extends RuntimeException {
+    public DetectorMismatchException(String expectedName, String actualName) {
+        super("Expected detector: "+expectedName+". Actual detector: "+actualName); 
+    }
+}

lcsim/src/org/lcsim/recon/tracking/seedtracker/strategybuilder
DumbLayer.java added at 1.1
diff -N DumbLayer.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ DumbLayer.java	27 Aug 2008 17:55:49 -0000	1.1
@@ -0,0 +1,49 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.lcsim.recon.tracking.seedtracker.strategybuilder;
+
+import org.lcsim.geometry.subdetector.BarrelEndcapFlag;
+
+/**Simple layer to uniquely define layers. Like SeedLayer but without
+ * information about layer type. 
+ * 
+ * @author cozzy
+ */
+public class DumbLayer{
+
+        String detectorName; 
+        int layer; 
+        BarrelEndcapFlag be; 
+        
+        public DumbLayer(String det, int lyr, BarrelEndcapFlag be){
+            detectorName = det; 
+            layer = lyr;  
+            this.be = be;
+        }
+        
+        
+        @Override
+        public boolean equals(Object other) {
+            if (this == other) return true; 
+            if (! (other instanceof DumbLayer)) return false; 
+            DumbLayer dl = (DumbLayer) other; 
+            return ( this.be.equals(dl.be) &&
+                     this.layer == dl.layer &&
+                     this.detectorName.equals(dl.detectorName)); 
+        }
+        
+        //dumb hash function... 
+        @Override
+        public int hashCode() {
+            return 20*( be.ordinal() + 1) + layer + 500*(detectorName.hashCode() % 1000);
+        }
+
+        @Override
+        public String toString() {
+            return ("DumbLayer: det="+detectorName+" lyr="+layer+" be="+ be.toString()); 
+        }
+        
+    }

lcsim/src/org/lcsim/recon/tracking/seedtracker/strategybuilder
ExampleDriver.java added at 1.1
diff -N ExampleDriver.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ExampleDriver.java	27 Aug 2008 17:55:49 -0000	1.1
@@ -0,0 +1,40 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.lcsim.recon.tracking.seedtracker.strategybuilder;
+
+import org.lcsim.util.Driver;
+
+/**
+ * Driver used to illustrate usage of StrategyBuilder w/out using the 
+ * command line. (Look at RunStrategyBuilder to learn how to use Strategy
+ * Builder with the command line). 
+ * 
+ * @author cozzy
+ */
+public class ExampleDriver extends Driver {
+    
+   //this will be the output file... this example outputs it in the 
+   //system's temporary directory. 
+   private String outputfile = System.getProperties().getProperty("java.io.tmpdir")+
+            System.getProperties().getProperty("file.separator")+
+            "ExampleStrategyList.xml"; 
+   
+   public ExampleDriver(){
+       
+       StrategyBuilder builder = new StrategyBuilder(); 
+       
+       //set the output file 
+       builder.setOutput(outputfile);
+       builder.setVerbose(true); //verbose output
+      
+       //see the IStrategyBuilder interface for other settable options
+       
+       add(builder); 
+       
+   }
+   
+
+}

lcsim/src/org/lcsim/recon/tracking/seedtracker/strategybuilder
IParticleFilter.java added at 1.1
diff -N IParticleFilter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ IParticleFilter.java	27 Aug 2008 17:55:49 -0000	1.1
@@ -0,0 +1,38 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.lcsim.recon.tracking.seedtracker.strategybuilder;
+
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.MCParticle;
+
+/**
+ * A particle filter is applied to MCParticles in the training step. LayerSets 
+ * are not generated by MCParticles which do not pass the filters. Note that 
+ * a minimum number of layers hit is necessary in addition to passing the filter. 
+ * 
+ * The default behavior for StrategyBuilder is to use a StrategyBasedFilter, which
+ * gets cutoffs for DCA, z0 and pt based on prototype strategy. 
+ * 
+ * 
+ * @author cozzy
+ */
+public interface IParticleFilter {
+    
+    /**
+     * Returns true if the MCParticle passes the filter, false otherwise. Called
+     * for every MCParticle by StrategyBuilder. 
+     * 
+     * @param p The test MCParticle
+     * @return
+     */
+    public boolean passes(MCParticle p); 
+    
+    /**
+     * This method is called for each event by StrategyBuilder.  
+     * @param event
+     */
+    public void setEvent(EventHeader event);  
+}

lcsim/src/org/lcsim/recon/tracking/seedtracker/strategybuilder
IStrategyBuilder.java added at 1.1
diff -N IStrategyBuilder.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ IStrategyBuilder.java	27 Aug 2008 17:55:49 -0000	1.1
@@ -0,0 +1,101 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.lcsim.recon.tracking.seedtracker.strategybuilder;
+
+import java.util.List;
+import org.lcsim.recon.tracking.seedtracker.SeedStrategy;
+
+/**
+ *This interface is mainly written for documentation purposes (since StrategyBuilder
+ * is somewhat full of code). 
+ * 
+ * @author cozzy
+ */
+public interface IStrategyBuilder {
+    
+    /**
+     *  Sets the location of the output XML file of strategy lists
+     * @param filename
+     */
+    public void setOutput(String filename);
+    
+    /**
+     * If symmetrize is true, then the Strategy will be force symmetrized between the two endcaps. 
+     * @param symmetrize
+     */
+    public void setSymmetrize(boolean symmetrize); 
+    
+    /**
+     * Sets the minimum number of layers that an MCParticle must go through to be considered
+     * for strategy finidng
+     * @param min
+     */
+    public void setMinLayers(int min);
+    
+    /**
+     * Sets the number of confirmation layers desired
+     * @param confirmed
+     */
+    public void setNumConfirmLayers(int confirmed); 
+    
+    /**
+     * Sets the number of seed layers desired
+     * @param seed
+     */
+    public void setNumSeedLayers(int seed);
+    
+    /**
+     * Sets the LayerWeight object of the strategy builder. A layer weight is 
+     * used to treat certain layers preferentially. If no layer weight specified, 
+     * the default layer weight will be used. 
+     * @param lw
+     */
+    public void setLayerWeight(LayerWeight lw); 
+    
+    /**
+     * Set the prototype for the generated strategies. The values for cutoffs
+     * and such will be copied from the prototype. If not prototype is specified,
+     * the default values for SeedStrategy will be used. 
+     * @param strategy
+     */
+    public void setStrategyPrototype(SeedStrategy strategy); 
+    
+    /**
+     * Set a starting strategy list. New strategies will only be generated for 
+     * particles not already found by the starting strategy list. 
+     * @param startList
+     */
+    public void setStartingStrategyList(List<SeedStrategy> startList); 
+    
+    /**
+     * Enables extra output if verbose is true. 
+     * @param verbose
+     */
+    public void setVerbose(boolean verbose); 
+    
+    /**
+     * Set the minimum unweighted score to create a strategy. This represents
+     * the minimum number of additional tracks in the test event that could
+     * theoretically be found if the strategy is included. 
+     * @param score
+     */
+    public void setMinimumUnweightedScore(int score);
+    
+    /**
+     * Sets the particle filter applied to MCParticles during the processing step. 
+     * MCParticles which do not pass this filter will not be considered for
+     * strategy finding. Note that MCParticles must also pass the MinLayers 
+     * requirement regardless of the filter.  
+     * 
+     * If no filter is specified, a filter will be generated from dca, z0 and
+     * pt cutoffs present in the prototype SeedStrategy. 
+     * 
+     * If no filter is desired, AllPassFilter may be used. 
+     * 
+     * @param filter
+     */
+    public void setParticleFilter(IParticleFilter filter);
+}

lcsim/src/org/lcsim/recon/tracking/seedtracker/strategybuilder
LayerWeight.java added at 1.1
diff -N LayerWeight.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ LayerWeight.java	27 Aug 2008 17:55:49 -0000	1.1
@@ -0,0 +1,339 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.lcsim.recon.tracking.seedtracker.strategybuilder;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import org.jdom.Attribute;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.Namespace;
+import org.jdom.input.SAXBuilder;
+import org.jdom.output.Format;
+import org.jdom.output.XMLOutputter;
+import org.lcsim.geometry.subdetector.BarrelEndcapFlag;
+import org.lcsim.util.xml.ClasspathEntityResolver;
+
+/**
+ *LayerWeights are used by SubsetScorer and to disambiguate between Seed and 
+ * Confirm layers. 
+ * 
+ * @author cozzy
+ */
+public class LayerWeight {
+    
+        private double default_weight = 1.0;
+        private double adjacence_constant = 2.0;
+        private double adjacence_exponent = 0.1;
+        private double adjacence_multiplier = 1.0;
+        private Map<DumbLayer, Double> weights; 
+        private Map<String, Double> readout_efficiencies; 
+        private double defaultEfficiency = 1.0; 
+        private String targetDetector = "None Specified"; 
+        private boolean divideByTwo = false; 
+        
+        public LayerWeight(){
+            weights = new HashMap<DumbLayer,Double>(); 
+            readout_efficiencies = new HashMap<String,Double>(); 
+        } 
+        
+        public LayerWeight(LayerWeight lw){
+            this.default_weight = lw.default_weight; 
+            this.weights = lw.weights; 
+            this.readout_efficiencies = lw.readout_efficiencies; 
+        }
+    
+        public LayerWeight(DumbLayer[] layers, double[] wghts, String[] readoutNames, double[] readoutEfficiencies){
+            if (layers.length!=wghts.length || readoutNames.length!=readoutEfficiencies.length)
+                throw new RuntimeException("Array lengths don't match"); 
+            
+            
+            weights = new HashMap<DumbLayer,Double>();
+            
+            for (int i = 0; i < layers.length; i++)
+                setWeight(layers[i], wghts[i]); 
+            
+            readout_efficiencies = new HashMap<String,Double>(); 
+            for (int i = 0 ; i < layers.length; i++)
+                setReadoutEfficiency(readoutNames[i],readoutEfficiencies[i]); 
+        }
+        
+        public void setDefaultWeight(double d){
+            default_weight = d; 
+        }
+        
+        public void setDefaultReadoutEfficiency(double d){
+            checkReadoutEfficiencyValid(d);
+            defaultEfficiency = d; 
+        }
+        
+        public void setWeight(DumbLayer lyr, double weight){
+            weights.put(lyr, weight); 
+        }
+        
+        public void setReadoutEfficiency(String readoutName, double eff){
+            checkReadoutEfficiencyValid(eff);
+            readout_efficiencies.put(readoutName, eff); 
+            
+        }
+        public void setTargetDetector(String name){
+            targetDetector = name; 
+        }
+        
+        public String getTargetDetector() {
+            return targetDetector; 
+        }
+        
+        public double getWeight(DumbLayer layer) {
+            if (weights.containsKey(layer)){
+                return weights.get(layer).doubleValue(); 
+            } else return default_weight; 
+        }
+        
+        public double getReadoutEfficiency(String readoutName) {
+            if (readout_efficiencies.containsKey(readoutName)) {
+                return readout_efficiencies.get(readoutName); 
+            } else return defaultEfficiency; 
+        }
+        
+        public double getWeight(Set<DumbLayer> set) {
+            double ret = 0.0;
+            
+            for (DumbLayer lyr : set) {
+                ret+=getWeight(lyr); 
+            }
+            
+            ret /= (double) set.size(); 
+            return ret; 
+        }
+        
+        public double getAdjacenceConstant() {
+            return adjacence_constant;
+        }       
+
+        public double getAdjacenceMultiplier() {
+            return adjacence_multiplier;
+        }
+
+        public void setAdjacenceMultiplier(double adjacence_multiplier) {
+            this.adjacence_multiplier = adjacence_multiplier;
+        }
+        
+        public void setAdjacenceConstant(double adjacence_constant) {
+            this.adjacence_constant = adjacence_constant;
+        }
+        
+        public double getAdjacenceExponent() {
+            return adjacence_exponent;
+        }
+
+        public void setAdjacenceExponent(double adjacence_exponent) {
+            this.adjacence_exponent = adjacence_exponent;
+        }
+
+        public boolean isDivideByTwo() {
+            return divideByTwo;
+        }
+
+        public void setDivideByTwo(boolean divideByTwo) {
+            this.divideByTwo = divideByTwo;
+        }
+
+        
+                
+        /**
+         * Returns the prefix of the default resource path to where the 
+         * layer weight XML files are stored.
+         * @return default resource path to XML weights
+         */
+        public static String getDefaultResourcePrefix(){
+            return "org/lcsim/contrib/seedtracker/strategybuilder/weights/";
+        }
+        
+        /**
+         * Loads LayerWeight definitions from the resource with the specified name.
+         * The name should be something like /org/lcsim/contrib/seedtracker/strategybuilder/weights/weights.xml
+         * 
+         * getDefaultResourcePrefix() may be helpful. 
+         * 
+         * @param resourceName the full name of the resource file to read
+         * @return the read LayerWeight definitions
+         */
+        public static LayerWeight getLayerWeightFromResource(String resourceName) {    
+            return getLayerWeightFromInputStream(LayerWeight.class.getClassLoader().getResourceAsStream(resourceName)); 
+            
+        }
+        
+        
+        public Comparator getComparator(){
+            return new Comparator(){
+                public int compare(Object o1, Object o2) {
+                    DumbLayer dl1 = (DumbLayer) o1;
+                    DumbLayer dl2 = (DumbLayer) o2; 
+                    double s1 = LayerWeight.this.getWeight(dl1);
+                    double s2 = LayerWeight.this.getWeight(dl2);
+                    return Double.compare(s1, s2); 
+                }
+            };
+        }
+        
+        
+        /**
+         * Loads LayerWeight definitions from the specified input stream
+         * @param in an input stream corresponding to a valid XML file 
+         * @return the read LayerWeight definitions
+         */
+        public static LayerWeight getLayerWeightFromInputStream(InputStream in){
+            
+            Document doc; 
+            SAXBuilder builder = new SAXBuilder();
+            builder.setValidation(true); 
+            builder.setFeature("http://apache.org/xml/features/validation/schema", true);
+            builder.setEntityResolver(new ClasspathEntityResolver());
+            try {
+                doc = builder.build(in);
+            } catch (JDOMException jdom) {
+                jdom.printStackTrace();
+                throw new RuntimeException("JDOM exception occurred"); 
+            } catch (IOException io ) {
+                io.printStackTrace();
+                throw new RuntimeException("IO Exception occurred"); 
+            }
+            
+            return getLayerWeightFromDocument(doc);
+ 
+        }
+        /**
+         * Loads LayerWeight definitions from the specified file. 
+         * @param file a valid XML file specifying layer weights
+         * @return the read LayerWeight definitions
+         */
+        public static LayerWeight getLayerWeightFromFile(File file){
+            
+            if (! file.exists() )
+                throw new RuntimeException("File "+file.toString()+" not found"); 
+            
+            Document doc; 
+            SAXBuilder builder = new SAXBuilder();
+            builder.setValidation(true); 
+            builder.setFeature("http://apache.org/xml/features/validation/schema", true);
+            builder.setEntityResolver(new ClasspathEntityResolver());
+            try {
+                doc = builder.build(file);
+            } catch (JDOMException jdom) {
+                jdom.printStackTrace();
+                throw new RuntimeException("JDOM exception occurred"); 
+            } catch (IOException io ) {
+                io.printStackTrace();
+                throw new RuntimeException("IO Exception occurred"); 
+            }
+            
+            return getLayerWeightFromDocument(doc); 
+        }
+        
+        private void checkReadoutEfficiencyValid(double d){
+            if (d < 0. || d > 1.00000001)
+                throw new RuntimeException("Readout Efficiency must be between 0 and 1"); 
+        }
+        
+        private static LayerWeight getLayerWeightFromDocument(Document doc) {
+            Element root = doc.getRootElement(); 
+            LayerWeight lw = new LayerWeight(); 
+            
+            try {
+                lw.setDefaultWeight(Double.valueOf(root.getChildText("DefaultWeight")).doubleValue());
+                lw.setDefaultReadoutEfficiency(Double.valueOf(root.getChildText("DefaultReadoutEfficiency")));
+                try {lw.setAdjacenceMultiplier(Double.valueOf(root.getChildText("AdjacenceMultiplier")).doubleValue());} catch(NullPointerException npe){}
+                try {lw.setAdjacenceConstant(Double.valueOf(root.getChildText("AdjacenceConstant")).doubleValue());} catch(NullPointerException npe){}
+                try {lw.setAdjacenceExponent(Double.valueOf(root.getChildText("AdjacenceExponent")).doubleValue());} catch(NullPointerException npe){}
+                try {lw.setTargetDetector(root.getChildText("TargetDetector"));} catch(NullPointerException npe){}
+                try {lw.setDivideByTwo(Boolean.valueOf(root.getChild("TargetDetector").getAttributeValue("divide_by_two_in_tracker_endcap")));} catch(NullPointerException npe){}
+                Element layers = root.getChild("Layers"); 
+                for (Object o : layers.getChildren("Layer")){
+                    
+                    Element e = (Element) o; 
+                    String detName = e.getAttributeValue("detector_name"); 
+                    int layer_number = Integer.valueOf(e.getAttributeValue("layer_number")).intValue(); 
+                    BarrelEndcapFlag beflag = BarrelEndcapFlag.valueOf(e.getAttributeValue("be_flag")); 
+                    DumbLayer dl = new DumbLayer(detName, layer_number, beflag); 
+                    lw.setWeight(dl, Double.valueOf(e.getText()));
+                } 
+                
+                Element ro = root.getChild("ReadoutEfficiencies"); 
+                
+                if (ro!=null) {
+                    for (Object o : ro.getChildren("ReadoutEfficiency")){
+                        Element e = (Element) o; 
+                        String readoutName = e.getAttributeValue("readout"); 
+                        lw.setReadoutEfficiency(readoutName, Double.valueOf(e.getText()));
+                    }
+                }
+                
+            } catch (Exception e) {
+                e.printStackTrace();
+                throw new RuntimeException("Something bad happened when parsing"); 
+            }
+                
+            return lw; 
+        }
+        /**
+         * Writes this LayerWeight to an XML file with a location specified
+         * by the given file object. 
+         * @param file output File object 
+         * @return true if succesful, false otherwise. 
+         */
+        public boolean writeToFile(File file){
+            Element root = new Element("LayerWeight"); 
+            Document doc = new Document(root); 
+            Namespace xs = Namespace.getNamespace("xs", "http://www.w3.org/2001/XMLSchema-instance");
+            root.addNamespaceDeclaration(xs);
+            root.setAttribute(new Attribute("noNamespaceSchemaLocation","http://lcsim.org/contrib/seedtracker/strategybuilder/strategies.xsd",xs));
+            root.addContent(new Element("DefaultWeight").addContent(String.valueOf(default_weight))); 
+            root.addContent(new Element("DefaultReadoutEfficiency").addContent(String.valueOf(defaultEfficiency)));          
+            root.addContent(new Element("TargetDetector").addContent(String.valueOf(targetDetector)).setAttribute("divide_by_two_in_tracker_endcap", String.valueOf(divideByTwo))); 
+            root.addContent(new Element("AdjacenceConstant").addContent(String.valueOf(adjacence_constant))); 
+            root.addContent(new Element("AdjacenceMultiplier").addContent(String.valueOf(adjacence_multiplier))); 
+            root.addContent(new Element("AdjacenceExponent").addContent(String.valueOf(adjacence_exponent))); 
+            
+            Element ro = new Element("ReadoutEfficiencies"); 
+            
+            for (String readout : readout_efficiencies.keySet()) {
+                Element re = new Element("ReadoutEfficiency"); 
+                re.setAttribute("readout",readout); 
+                re.addContent(String.valueOf(readout_efficiencies.get(readout))); 
+                ro.addContent(re);
+            }   
+            root.addContent(ro); 
+            
+            Element layers = new Element("Layers"); 
+            for (DumbLayer lyr : weights.keySet()) {
+                Element layer = new Element("Layer"); 
+                layer.setAttribute("layer_number", String.valueOf(lyr.layer)); 
+                layer.setAttribute("detector_name", String.valueOf(lyr.detectorName)); 
+                layer.setAttribute("be_flag", lyr.be.toString()); 
+                layer.addContent(String.valueOf(weights.get(lyr))); 
+                layers.addContent(layer); 
+            }
+            root.addContent(layers); 
+            
+            try {
+                XMLOutputter out = new XMLOutputter(Format.getPrettyFormat()); 
+                FileWriter fw = new FileWriter(file); 
+                out.output(doc, fw);
+            } catch (Exception e){
+                e.printStackTrace();
+                return false; 
+            }
+            return true; 
+        }
+    }

lcsim/src/org/lcsim/recon/tracking/seedtracker/strategybuilder
NonPromptFilter.java added at 1.1
diff -N NonPromptFilter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ NonPromptFilter.java	27 Aug 2008 17:55:49 -0000	1.1
@@ -0,0 +1,35 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.lcsim.recon.tracking.seedtracker.strategybuilder;
+
+import org.lcsim.recon.tracking.seedtracker.analysis.HelixParamCalculator;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.MCParticle;
+
+/**
+ *
+ * @author cozzy
+ */
+public class NonPromptFilter implements IParticleFilter {
+    
+    private EventHeader event; 
+    private double minDist = 10.0; 
+    private double minPT = 1.0; 
+    public boolean passes(MCParticle p) {
+        
+        HelixParamCalculator calc = new HelixParamCalculator(p, event); 
+        
+        if (calc.getDCA() < minDist && calc.getZ0() < minDist) return false; 
+        if (calc.getMCTransverseMomentum() < minPT) return false; 
+        return true; 
+        
+    }
+    
+    public void setEvent(EventHeader event){
+        this.event = event; 
+    }
+
+}

lcsim/src/org/lcsim/recon/tracking/seedtracker/strategybuilder
RunStrategyBuilder.java added at 1.1
diff -N RunStrategyBuilder.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ RunStrategyBuilder.java	27 Aug 2008 17:55:49 -0000	1.1
@@ -0,0 +1,195 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.lcsim.recon.tracking.seedtracker.strategybuilder;
+
+import java.io.File;
+import org.lcsim.recon.tracking.seedtracker.StrategyXMLUtils;
+import org.lcsim.util.Driver;
+import org.lcsim.util.loop.LCSimLoop;
+
+/**
+ * Class used to run StrategyBuilder from outside of Jas3. 
+ * 
+ * With Maven 2, it is possible to use the command (from inside the base lcsim directory):
+ * 
+ * mvn exec:java -Dexec.mainClass="org.lcsim.contrib.seedtracker.strategybuilder.RunStrategyBuilder" -Dexec.args="arg1 arg2 etc..."
+ * 
+ * A shell script to do this is provided in resources/org/lcsim/contrib/seedtracker/strategybuilder/, 
+ * note that the script should be run from the base lcsim directory. 
+ * 
+ * If anybody wants to write a windows shell script, that would be great. 
+ * 
+ * @author cozzy
+ */
+public class RunStrategyBuilder {
+    public static void main(String[] args) {
+        String filename=""; 
+        String outFile = StrategyBuilder.defaultOutputFile; 
+        int numEvents=-1; 
+        String startingStrategies = ""; 
+        String prototypeFile = "";
+        int prototypeN = -1; 
+        boolean verbose = StrategyBuilder.defaultVerbose; 
+        boolean symmetrize = StrategyBuilder.defaultSymmetrize; 
+        String lwfn = ""; 
+        int mintrks = StrategyBuilder.defaultMinUnweightedScore;
+        String filterClassName = ""; 
+        String altDriver = ""; 
+        
+        //parse arguments.. if error print usage
+        try{
+            int no_flag_counter = 0; 
+            for (int i = 0; i < args.length; i++){
+                
+                String arg = args[i]; 
+                
+                if (arg.equals("-h")) {
+                    printUsage();
+                    System.exit(0);
+                } else if (arg.equals("-o")) {
+                    outFile = args[++i]; 
+                } else if (arg.equals("-e")) {
+                    numEvents = Integer.valueOf(args[++i]); 
+                } else if (arg.equals("-s")) {
+                    startingStrategies = args[++i]; 
+                } else if (arg.equals("-p")) {
+                    prototypeFile = args[++i];
+                    prototypeN = Integer.valueOf(args[++i]); 
+                } else if (arg.equals("-v")) {
+                    verbose = !verbose; 
+                } else if (arg.equals("-l")) {
+                    lwfn = args[++i]; 
+                } else if (arg.equals("-m")) {
+                    mintrks = Integer.valueOf(args[++i]);
+                } else if (arg.equals("-f")) {
+                    filterClassName = args[++i]; 
+                } else if (arg.equals("-a")) {
+                    altDriver = args[++i]; 
+                } else if (arg.equals("-y")) {
+                    symmetrize = !symmetrize; 
+                } else if (arg.startsWith("-")){
+                    throw new Exception(); 
+                } else {
+                    if (no_flag_counter > 0) throw new Exception(); 
+                    no_flag_counter++; 
+                    filename = arg; 
+                }
+            }
+            if (no_flag_counter == 0) throw new Exception(); 
+            
+        } catch (Exception e){
+            printUsage();
+            System.exit(1); 
+        }
+        IStrategyBuilder builder = new StrategyBuilder(); 
+        
+        if (altDriver.length() > 0) {
+            try {
+                builder = (IStrategyBuilder) Class.forName(altDriver).newInstance();
+            }  catch (ClassNotFoundException cfne) {
+                System.out.println("Class "+altDriver+ " not found :'( Exiting."); 
+                System.exit(3); 
+            } catch (InstantiationException ie) {
+                System.out.println("Class "+altDriver+ " could not be instantiated. Does the constructor take arguments? Exiting.");
+                System.exit(4); 
+            } catch (IllegalAccessException iae) {
+                System.out.println("IllegalAccessException? WTF does that mean? Exiting."); 
+                System.exit(5); 
+            } catch (ClassCastException cce) {
+                System.out.println("Unable to cast "+altDriver+ " as a IStrategyBuilder. Exiting"); 
+                System.exit(6); 
+            }
+            
+            if (!(builder instanceof Driver)) {
+                System.out.println("Alternative driver must extend Driver. Exiting"); 
+                System.exit(14123); 
+            }
+        } 
+        
+        builder.setVerbose(verbose);
+        builder.setMinimumUnweightedScore(mintrks);
+        builder.setOutput(outFile);
+        builder.setSymmetrize(symmetrize);
+        
+        if (startingStrategies.length() > 0)
+            builder.setStartingStrategyList(StrategyXMLUtils.getStrategyListFromFile(new File(startingStrategies)));
+        
+        if (prototypeFile.length() > 0)
+            builder.setStrategyPrototype(StrategyXMLUtils.getStrategyListFromFile(new File(prototypeFile)).get(prototypeN));
+        
+        if (lwfn.length() > 0)
+            builder.setLayerWeight(LayerWeight.getLayerWeightFromFile(new File(lwfn)));
+        
+        
+        // if a non-default MCParticle Filter is set, then try to load it and assign it. 
+        if (filterClassName.length() > 0){
+            try {
+                builder.setParticleFilter((IParticleFilter) Class.forName(filterClassName).newInstance());
+            } catch (ClassNotFoundException cfne) {
+                System.out.println("Class "+filterClassName+ " not found :'( Exiting."); 
+                System.exit(123); 
+            } catch (InstantiationException ie){
+                System.out.println("Class "+filterClassName+ " could not be instantiated. Does the constructor take arguments? Exiting.");
+                System.exit(234); 
+            } catch (IllegalAccessException iae){
+                System.out.println("IllegalAccessException? WTF does that mean? Exiting."); 
+                System.exit(345); 
+            } catch (ClassCastException cce){
+                System.out.println("Unable to cast "+filterClassName+ " as a IParticleFilter. Exiting"); 
+                System.exit(456); 
+            }
+        }
+        
+        // check data file existence
+        File file = new File(filename);
+        if (!file.exists()) {
+            System.out.println("Cannot find data file "+file.toString()+". Exiting. "); 
+            System.exit(7);
+        }
+        
+        
+        if(verbose){
+            System.out.println("Starting... Reading Geometry"); 
+        }
+        
+        
+        //load the driver and run it. 
+        try {
+
+            LCSimLoop loop = new LCSimLoop(); 
+            loop.setLCIORecordSource(file); 
+            loop.add( (Driver) builder ); 
+            loop.loop(numEvents, null); 
+            loop.dispose(); 
+        } catch (Exception e){
+            e.printStackTrace(); 
+            throw new RuntimeException("oopsie"); 
+        }    
+    }
+    
+    
+    private static void printUsage(){
+        
+        System.out.println("Usage: RunStrategyBuilder INPUTRECORD [flags]");
+        System.out.println(" -h \t\t\t\tPrint this message");
+        System.out.println(" -v \t\t\t\tBe verbose");
+        System.out.println(" -y \t\t\t\tDon't auto-symmetrize north/south. \n\t\t\t\t You may want to do this is starting strategies\n\t\t\t\t aren't symmetric.");
+        System.out.println(" -o OUTPUTFILE \t\t\tset output XML file to OUTPUTFILE\n\t\t\t\t (default is in TEMP dir)");
+        System.out.println(" -e NUM_EVENTS \t\t\tRun only NUM_EVENTS events instead of all"); 
+        System.out.println(" -s STARTING_STRATEGY_FILE \tUse starting strategies in the specified file"); 
+        System.out.println(" -p PROTOTYPE_STRATEGY_FILE N\tUse the Nth strategy in the specified file\n\t\t\t\t as a prototype. N is 0-indexed.");       
+        System.out.println(" -l LAYER_WEIGHTS_FILE\t\tUse the weights in the specified file");       
+        System.out.println(" -m MIN_TRKS_FOR_STRATEGY \tMinimum number of tracks to \n\t\t\t\t that could theoretically be found" +
+                "\n\t\t\t\tnecessary to make a strategy\n\t\t\t\t (default: 3)");    
+        System.out.println(" -f FILTER_CLASS\t\tSpecify an MCParticle filter by naming a " +
+                "\n\t\t\t\t fully qualified (i.e. org.lcsim.etc) class. \n\t\t\t\t By default, " +
+                "a filter based on the prototype \n\t\t\t\t strategy cutoffs is used.");
+        System.out.println(" -a ALTERNATIVE_DRIVER\t\tUse an alternative driver instead of \n\t\t\t\t the default StrategyBuilder. " +
+                "Must implement\n\t\t\t\t IStrategyBuilder and extend Driver. UNTESTED.\n\t\t\t\t " +
+                "Fully qualified class name must be used \n\t\t\t\t (i.e. org.lcsim.etc)"); 
+    }
+    
+}

lcsim/src/org/lcsim/recon/tracking/seedtracker/strategybuilder
StrategyBasedFilter.java added at 1.1
diff -N StrategyBasedFilter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ StrategyBasedFilter.java	27 Aug 2008 17:55:49 -0000	1.1
@@ -0,0 +1,48 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.lcsim.recon.tracking.seedtracker.strategybuilder;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import org.lcsim.recon.tracking.seedtracker.SeedStrategy;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.MCParticle;
+import org.lcsim.recon.tracking.seedtracker.analysis.HelixParamCalculator;
+
+/**
+ *A filter based on the cutoff values in a SeedStrategy. 
+ * @author cozzy
+ */
+public class StrategyBasedFilter implements IParticleFilter {
+
+    double pt; 
+    double dca; 
+    double z0; 
+    double b;        
+    Hep3Vector ip = new BasicHep3Vector(0., 0., 0.); 
+    
+    public StrategyBasedFilter(SeedStrategy strategy){
+        pt = strategy.getMinPT();
+        dca = strategy.getMaxDCA(); 
+        z0 = strategy.getMaxZ0(); 
+        
+    }
+    
+   
+    public boolean passes(MCParticle p) {
+        HelixParamCalculator calc = new HelixParamCalculator(p, b); 
+        return (
+                Math.abs(calc.getDCA()) < dca  && 
+                Math.abs(calc.getZ0()) < z0    &&
+                calc.getMCTransverseMomentum() > pt
+                );
+    }
+    
+    public void setEvent(EventHeader event){
+        b = event.getDetector().getFieldMap().getField(ip).z();
+    }
+
+}

lcsim/src/org/lcsim/recon/tracking/seedtracker/strategybuilder
StrategyBuilder.java added at 1.1
diff -N StrategyBuilder.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ StrategyBuilder.java	27 Aug 2008 17:55:49 -0000	1.1
@@ -0,0 +1,506 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.lcsim.recon.tracking.seedtracker.strategybuilder;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import org.lcsim.recon.tracking.seedtracker.SeedLayer;
+import org.lcsim.recon.tracking.seedtracker.SeedLayer.SeedType;
+import org.lcsim.recon.tracking.seedtracker.SeedStrategy;
+import org.lcsim.recon.tracking.seedtracker.StrategyXMLMetadata;
+import org.lcsim.recon.tracking.seedtracker.StrategyXMLUtils;
+import org.lcsim.detector.DetectorElementStore;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.IDetectorElementContainer;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.fit.helicaltrack.HitIdentifier;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.subdetector.BarrelEndcapFlag;
+import org.lcsim.util.Driver;
+
+/**
+ * StrategyBuilder automatically generates strategies for a detector by
+ * seeing what layers MCParticles tend to go through. 
+ * 
+ * See interface for public method doc. 
+ * 
+ * @author cozzy
+ */
+public class StrategyBuilder extends Driver implements IStrategyBuilder {
+    
+    public static final String defaultOutputFile = System.getProperties().getProperty("java.io.tmpdir")+
+            System.getProperties().getProperty("file.separator")+
+            "BuiltStrategies.xml"; 
+    
+    //these are defined separately because RunStrategyBuilder uses some of these too... 
+    public static final boolean defaultVerbose = false; 
+    public static final int defaultMinLayers = 7; 
+    public static final int defaultConfirmLayers =1; 
+    public static final int defaultSeedLayers =3; 
+    public static final int defaultMinUnweightedScore = 1; 
+    public static final boolean defaultSymmetrize = true;  
+   
+    private boolean verbose = defaultVerbose; 
+    private boolean symmetrize = defaultSymmetrize; 
+    private int min_layers = defaultMinLayers;  
+    private int confirm_layers = defaultConfirmLayers;  
+    private int seed_layers = defaultSeedLayers; 
+    private String outputFile = defaultOutputFile; 
+    private int minUnweightedScore = defaultMinUnweightedScore;  
+    private boolean oldConfirm = false; 
+    private List<SeedStrategy> startingStrategies = new ArrayList<SeedStrategy>(); 
+    private Set<Set<DumbLayer>> startingSet = new HashSet<Set<DumbLayer>>(); //this will be generated from startingStrategies
+    private SeedStrategy prototype = new SeedStrategy("null", new ArrayList<SeedLayer>()); 
+    private LayerWeight weighter = null;
+    private HitIdentifier ID = new HitIdentifier();
+    //this stores the list of all sets of layers
+    private List<Set<DumbLayer>> setlist = new ArrayList<Set<DumbLayer>>();
+    private String detectorName; 
+    private IParticleFilter filter; 
+    private List<List<DumbLayer>> adjacentlist = new ArrayList<List<DumbLayer>>(); 
+    //4:26
+    private Random random = new Random(); 
+    
+
+    @Override 
+    protected void startOfData(){
+      //Use default filter if none is specified
+        if (filter==null) {
+            filter = new StrategyBasedFilter(prototype); 
+        }
+    }
+    
+    //In the process step, we build two lists of collections:
+    //      The set list is a list of the sets of layers hit by MCParticles hitting over min layers layers
+    //      The adjacence list is a list of a list of hits that are determined to be adjacent based on MCParticle trajectory
+    @Override
+    protected void process(EventHeader event){
+
+        super.process(event);
+        
+        if (verbose) {
+            if (event.getEventNumber() % 100 == 0)
+            System.out.println("Processed "+event.getEventNumber()+" events.");
+        }
+        
+        filter.setEvent(event);
+        
+        //Build MCMap from SimTrackerHits, including inefficiency modeling
+        Map<MCParticle, List<SimTrackerHit>> mcmap = buildMCMap(event);
+        
+        //filter MCs 
+        Iterator<MCParticle> mciter = mcmap.keySet().iterator(); 
+        while (mciter.hasNext()){
+            MCParticle next = mciter.next(); 
+            if (!filter.passes(next)){
+                mciter.remove(); 
+            }
+        }
+        
+        //Build and add layer sets, as well as adjacent lists
+        for(List<SimTrackerHit> l : mcmap.values()) {
+            Set<DumbLayer> set = new HashSet<DumbLayer>(); 
+            
+            //sort by time, which allows creation of adjacence lists. 
+            Collections.sort(l, new Comparator() {
+
+                public int compare(Object o1, Object o2) {
+                    SimTrackerHit h1 = (SimTrackerHit) o1; 
+                    SimTrackerHit h2 = (SimTrackerHit) o2; 
+                    return Double.compare(h1.getTime(), h2.getTime()); 
+                }
+            });
+            
+            //this will store all the working adjacent lists
+            LinkedList<List<DumbLayer>> tempAdjacentLayersList = new LinkedList<List<DumbLayer>>(); 
+            
+            for (SimTrackerHit h : l) {
+                IDetectorElementContainer cont = DetectorElementStore.getInstance().find(h.getIdentifier());
+                if(cont.isEmpty()) continue; 
+                IDetectorElement de = cont.get(0); 
+                String detname = ID.getName(de);
+                int lyr = ID.getLayer(de);
+                BarrelEndcapFlag be = ID.getBarrelEndcapFlag(de); 
+                
+                //kludgy divide by two thing
+                if (weighter.isDivideByTwo() && be.isEndcap() && 
+                        (detname.indexOf("Tracker") > -1 || detname.indexOf("Tkr") > -1) ) {
+                    lyr/=2;  // sid01 doubles up on layer numbering in the endcap. 
+                }
+                
+                //if symmetrizing, we want to treat North and South layers equivalently. 
+                if (symmetrize && be.isEndcap()) be = BarrelEndcapFlag.ENDCAP; 
+                DumbLayer dl = new DumbLayer(detname, lyr, be); 
+                set.add(dl);
+                
+                //create a new adjacent list that starts with this layer if none already exists
+                //(This is necessary because of the doubling of SimTrackerHits in the tracker endcap)
+                if (tempAdjacentLayersList.isEmpty() || !tempAdjacentLayersList.getLast().contains(dl)) {
+                    List<DumbLayer> adjacentLayers = new ArrayList<DumbLayer>(); 
+                    tempAdjacentLayersList.addLast(adjacentLayers);
+                }
+                
+                //see which adjacent lists already have enough layers, and add those to the list
+                Iterator<List<DumbLayer>> it = tempAdjacentLayersList.iterator(); 
+                while (it.hasNext()) {
+                    List<DumbLayer> s = it.next(); 
+                    if(!s.contains(dl)) s.add(dl); //otherwise we get doubled layers in the forward region of the tracker 
+                    if (s.size() == confirm_layers + seed_layers) {
+                        adjacentlist.add(s); 
+                        it.remove(); 
+                    }
+                }
+            }
+                        
+            //Ensure layer set has minimum number of layers
+            if (set.size() >= min_layers)
+                setlist.add(set); 
+        }
+    }
+    
+    @Override
+    protected void suspend(){
+        
+        if (verbose) System.out.println("Finished processing. Beginning analysis."); 
+        Set<DumbLayer> allLayers = new HashSet<DumbLayer>(); 
+        
+        //Get all layers that are used at some point
+        for (Set<DumbLayer> set : setlist) 
+            allLayers.addAll(set); 
+        if (verbose) System.out.println(allLayers.size()+" total layers.");
+        
+       //create startingSet... this will be used so that new strategies aren't extraneously generated
+       for (SeedStrategy strategy : startingStrategies){
+            Set<DumbLayer> subset = new HashSet<DumbLayer>(); 
+            for (SeedLayer lyr : strategy.getLayers(SeedLayer.SeedType.Seed))
+                subset.add(new DumbLayer(lyr.getDetName(), lyr.getLayer(), lyr.getBarrelEndcapFlag())); 
+            
+            for (SeedLayer lyr: strategy.getLayers(SeedLayer.SeedType.Confirm))
+                subset.add(new DumbLayer(lyr.getDetName(), lyr.getLayer(), lyr.getBarrelEndcapFlag())); 
+            startingSet.add(subset); 
+        }
+        if (verbose) System.out.println(startingStrategies.size()+" starting strategies defined.");
+       
+       //If any of the starting strategies can find a set, discard it.
+        Iterator<Set<DumbLayer>> iter = setlist.iterator(); 
+        while (iter.hasNext()){
+            Set<DumbLayer> this_set = iter.next();     
+            if (startingCanFind(this_set)){
+                iter.remove(); 
+            }
+         }
+        
+        //Generate the scorer and assign its weighter
+        SubsetScorer scorer = new SubsetScorer(setlist,adjacentlist); 
+        scorer.setLayerWeight(weighter); 
+        
+        //Generate all possible subsets of the right size of allLayers
+        List<Set<DumbLayer>> all_subsets = StrategyBuilderUtils.generateAllPossibleDumbLayerSubsetsList(allLayers, confirm_layers+seed_layers); 
+        if (verbose) System.out.println(all_subsets.size() + " possible subsets of size "+(confirm_layers+seed_layers)); 
+        
+        //convert setlist to set to eliminate duplicates... 
+        Set<Set<DumbLayer>> setset = new HashSet<Set<DumbLayer>>(setlist.size()); 
+        setset.addAll(setlist); 
+        
+        //usedSets keeps track of what has been used already
+        Set<Set<DumbLayer>> usedSets = new HashSet<Set<DumbLayer>>(setset.size()); 
+        
+        //final_sets will store the generated seed + confirm layers
+        Set<Set<DumbLayer>> final_sets = new HashSet<Set<DumbLayer>>(); 
+        if (verbose) System.out.println("Layer set has "+setset.size()+" entries.");
+        //map from a final_set to all other associated layers to generate extension layers
+        Map<Set<DumbLayer>, Set<DumbLayer>> extendmap = new HashMap<Set<DumbLayer>,Set<DumbLayer>>();
+        
+        //Figure out a "good" set of four-layer combinations by brute force...
+        //We have a scoring algorithm and we find the maximal scoring one. 
+        while (true){
+            if (usedSets.size() == setset.size()) break; //if we've used all sets, then we're done! 
+            
+            Set<DumbLayer> max = all_subsets.get(0); 
+            double maxScore = 0; 
+            
+            //get the highest scoring strategy...
+            for (Set<DumbLayer> trial : all_subsets){
+                double score = scorer.getScore(trial); 
+                if (score > maxScore) {
+                    maxScore = score; 
+                    max = trial; 
+                }
+            }
+            
+            //ignore anything that has too few occurrences... 
+            if (scorer.getUnweightedScore(max) <= minUnweightedScore) break; 
+            
+            scorer.markUsed(max);
+            final_sets.add(max); 
+            extendmap.put(max, new HashSet<DumbLayer>()); 
+            
+            for (Set<DumbLayer> this_set : setset) {
+                if (this_set.containsAll(max)) { //If this set contains all the layers in max, it should be findable! 
+                    
+                    //add extension layers to extendmap
+                    Set<DumbLayer> nw = new HashSet<DumbLayer>(); 
+                    for (DumbLayer dumb : this_set){
+                        if(!max.contains(dumb)) nw.add(dumb);
+                    }
+                    Set<DumbLayer> old = extendmap.get(max); 
+                    old.addAll(nw); 
+                    extendmap.put(max, old); 
+                    
+                    //remove this set from consideration
+                    usedSets.add(this_set); 
+                }
+            }
+            
+            if (verbose) System.out.println(setset.size() - usedSets.size() + " entries left to be covered."); 
+        }
+        if(verbose) System.out.println("Done finding strategies"); 
+        if(verbose) System.out.println(final_sets.toString());  
+       
+        //Generate the StrategyList 
+        int counter = 0; 
+        List<SeedStrategy> strat_list = new ArrayList<SeedStrategy>(); 
+        strat_list.addAll(startingStrategies); 
+        
+        
+        //create Strategies from final_sets... this part is klunky right now. 
+        for (Set<DumbLayer> s : final_sets) {
+
+            List<DumbLayer> dlyrlst = new ArrayList<DumbLayer>(); 
+            dlyrlst.addAll(s); 
+            
+            /**
+             * Here we figure out which layers to use for seeding and which to use
+             * for confirming. Since it is highly advantageous for the seed layers 
+             * to be adjacent, we will try to enforce that if possible. 
+             */
+            
+            //get adjacence info if set is adjacent. 
+            List<DumbLayer> adjacenceInfo = null; 
+            for (List<DumbLayer> l : adjacentlist) {
+                if (s.containsAll(l) && l.containsAll(s)) {
+                    adjacenceInfo = l; 
+                    break; 
+                }
+            }
+            
+            //if not all layers are adjacent, then perhaps a subset of size seed_layers is... 
+            if (adjacenceInfo == null) {
+                for (Set<DumbLayer> ss : StrategyBuilderUtils.generateAllPossibleDumbLayerSubsetsList(s, seed_layers)){
+                    for (List<DumbLayer> l : adjacentlist) {
+                        if (ss.containsAll(l) && l.containsAll(ss)) {
+                            adjacenceInfo = l; 
+                            break; 
+                        }
+                    }
+                }
+            }
+                        
+            /**
+             * The following operations manipulate dlyrlst such that the first num_confirm items will be
+             * used for confirmation and the rest will be used for seeding.  
+             * 
+             * This is kind of kludgy and it might be less confusing if it were changed. 
+             */
+            
+            //if these layers aren't adjacent, just use the weights to figure out which layers to confirm with
+            if (adjacenceInfo == null || oldConfirm) {
+                //sort the list from smallest to largest weight. Use smallest weight(s) for confirmation layer(s). 
+                Collections.sort(dlyrlst, weighter.getComparator()); 
+            } 
+            
+            //If all layers are adjacent, we use either the first or last layers to confirm, depending on the layer weights
+            else if (adjacenceInfo.size() == dlyrlst.size()) { 
+                dlyrlst = adjacenceInfo; 
+                if (weighter.getWeight(dlyrlst.get(0)) > weighter.getWeight(dlyrlst.get(dlyrlst.size()-1)))
+                    Collections.reverse(dlyrlst);
+                    
+            //Otherwise, use the adjacent layers as seeds and not the others... 
+            } else {
+                dlyrlst.removeAll(adjacenceInfo);
+                dlyrlst.addAll(adjacenceInfo); 
+            }
+                     
+            int confirmed = 0; //add the first num_confirm as confirmed... the rest as seed. 
+
+            List<SeedLayer> lyrlst = new ArrayList<SeedLayer>(); 
+
+            //get extension layers...sort from smallest weight to largest weight
+            //                      because the list will be reversed. 
+            List<SeedLayer> extendlyr = new ArrayList<SeedLayer>(); 
+            List<DumbLayer> dumbextendlyr = new ArrayList<DumbLayer>(); 
+            dumbextendlyr.addAll(extendmap.get(s)); 
+            Collections.sort(dumbextendlyr, weighter.getComparator()); 
+            
+            for (DumbLayer lyr : dumbextendlyr) {
+                extendlyr.add(new SeedLayer(lyr.detectorName, lyr.layer, lyr.be, SeedType.Extend)); 
+            }
+            
+            lyrlst.addAll(extendlyr);             
+            //get seed/confirmation layers
+            for (DumbLayer lyr : dlyrlst){
+                SeedType type;
+                
+                if (confirmed < confirm_layers) {
+                    type = SeedType.Confirm;
+                    confirmed++; 
+                }
+                else type = SeedType.Seed; 
+                lyrlst.add(new SeedLayer(lyr.detectorName, lyr.layer, lyr.be, type)); 
+            }
+            Collections.reverse(lyrlst); // reverse so seed layers on top 
+            
+            String name = "AUTOGEN" + counter++ +"_"+lyrlst.hashCode(); 
+            
+            //copy over cutoff info from prototype
+            SeedStrategy stgy = new SeedStrategy(name,lyrlst);
+            stgy.copyCutoffsFromStrategy(prototype); 
+            strat_list.add(stgy); 
+        }
+        
+        StrategyXMLMetadata meta = new StrategyXMLMetadata(); 
+        String comment = "Strategy list Autogenerated by Strategy Builder on "+new Date()+".";
+        meta.targetDetector =  detectorName; 
+        meta.comment = comment;
+        
+        //If symmetrizing, make Endcap Layers for both north and south
+        if (symmetrize) {
+            if (verbose) System.out.println("Symmetrizing..."); 
+            StrategyBuilderUtils.symmetrizeStrategies(strat_list);
+        }
+        
+        StrategyXMLUtils.writeStrategyListToFile(strat_list, new File(outputFile), meta);
+        if (verbose) System.out.println(strat_list.size()+" strategies generated."); 
+        if (verbose) System.out.println("Strategies XML file written at "+outputFile); 
+    }
+    
+    @Override
+    protected void detectorChanged(Detector detector){
+        detectorName = detector.getDetectorName(); 
+        
+        //use default weighter if not specified... default depends on detector name
+        if (weighter==null) {
+           setLayerWeight(new DefaultLayerWeight(detectorName).getWeight());
+        }
+        
+        //check that detectors match layer weights (unless the TargetDetector is unspecified)
+        if(!weighter.getTargetDetector().equals("None Specified") && !weighter.getTargetDetector().equals(detectorName)) {
+            throw new DetectorMismatchException(detectorName, weighter.getTargetDetector()); 
+        }
+    }
+    
+    
+    // ===============setters===============// documented in interface
+    public void setOutput(String filename){
+        outputFile = filename;
+    }
+    
+    public void setLayerWeight(LayerWeight lw){
+        weighter = lw; 
+    }
+    
+    public void setMinLayers(int min){
+        min_layers = min; 
+    }
+    
+    public void setNumConfirmLayers(int clayers){
+        confirm_layers = clayers; 
+    }
+
+    public void setNumSeedLayers(int slayers){
+        seed_layers = slayers; 
+    }
+    
+    public void setStrategyPrototype(SeedStrategy proto){
+        prototype = proto; 
+    }
+    
+    public void setStartingStrategyList(List<SeedStrategy> slist){
+        startingStrategies = slist; 
+    }
+    
+    public void setVerbose(boolean v){
+        verbose = true; 
+    }
+    
+    public void setMinimumUnweightedScore(int sc){
+        minUnweightedScore = sc; 
+    }
+            
+    public void setParticleFilter(IParticleFilter pfilter){
+        filter = pfilter; 
+    }
+    
+    public void setSymmetrize(boolean set){
+        symmetrize = set; 
+    }
+
+    //========privates ============//
+    private Map<MCParticle, List<SimTrackerHit>> buildMCMap(EventHeader event) {
+
+        //Build MC Map from SimTrackerHits
+        Map<MCParticle, List<SimTrackerHit>> mcmap = new HashMap<MCParticle, List<SimTrackerHit>>();
+        List<SimTrackerHit> allhits = new ArrayList<SimTrackerHit>();
+
+
+        for (List<SimTrackerHit> l : event.get(SimTrackerHit.class)) {
+
+            /**
+             * We simulate inefficiency in SimTrackerHit => TrackerHit conversion,
+             * otherwise the strategies will miss certain classes of hits
+             */
+
+            EventHeader.LCMetaData meta = event.getMetaData(l);
+            String readout = meta.getName();
+            double efficiency = weighter.getReadoutEfficiency(readout);
+            for (SimTrackerHit h : l) {
+                if (random.nextDouble() < efficiency) {
+                    allhits.add(h);
+                }
+            }
+        }
+
+        for (SimTrackerHit h : allhits) {
+            MCParticle p = h.getMCParticle();
+            List<SimTrackerHit> these_hits;
+            if (mcmap.containsKey(p)) {
+                these_hits = mcmap.get(p);
+            } else {
+                these_hits = new ArrayList<SimTrackerHit>();
+            }
+
+            these_hits.add(h);
+            mcmap.put(p, these_hits);
+        }
+
+        return mcmap;
+    }
+    
+    private boolean startingCanFind(Set<DumbLayer> set){
+        
+        for (Set<DumbLayer> s : startingSet){
+            if (set.containsAll(s))
+                return true; 
+        }
+        
+        return false; 
+    }
+    
+
+}

lcsim/src/org/lcsim/recon/tracking/seedtracker/strategybuilder
StrategyBuilderUtils.java added at 1.1
diff -N StrategyBuilderUtils.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ StrategyBuilderUtils.java	27 Aug 2008 17:55:49 -0000	1.1
@@ -0,0 +1,169 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.lcsim.recon.tracking.seedtracker.strategybuilder;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import org.lcsim.recon.tracking.seedtracker.SeedLayer;
+import org.lcsim.recon.tracking.seedtracker.SeedLayer.SeedType;
+import org.lcsim.recon.tracking.seedtracker.SeedStrategy;
+import org.lcsim.geometry.subdetector.BarrelEndcapFlag;
+
+/**
+ * StrategyBuilder was getting too bloated, so some of the code has been moved here
+ * @author cozzy
+ */
+public class StrategyBuilderUtils {
+    
+    private static final BarrelEndcapFlag[] beArray = 
+            new BarrelEndcapFlag[]{BarrelEndcapFlag.ENDCAP_NORTH, BarrelEndcapFlag.ENDCAP_SOUTH}; 
+    
+    /**
+     * Symmetrizes the given StrategyList... Modifies 
+     * the original list rather than returning a new one. 
+     * 
+     * It is assumed that the  input list uses the beflag ENDCAP rather 
+     * than ENDCAP_NORTH or ENDCAP_SOUTH. Anything with ENDCAP_NORTH or 
+     * ENDCAP_SOUTH won't be touched... 
+     * 
+     * @param strat_list
+     */
+    static void symmetrizeStrategies (List<SeedStrategy> strat_list) {
+        
+        /**
+         * There are 3 interesting cases here:
+         * 
+         *   1) None of the layers are in the endcap. Symmetrization unnecessary.
+         *   2) Only extension layers are in the endcap. In this case we should 
+         *      modify the extension layers so that both endcaps appear. We remove
+         *      the old extension layer and replace it with two new ones. 
+         *   3) Extension layers appear in the seeds or confirm layers. 
+         *      In this case, we remove the old strategy and replace it with 
+         *      two new ones. 
+         * 
+         * 
+         *   We can't tell the difference between (2) and (3) until after we have
+         *   gone through the entire set, so the code keeps track of the changes
+         *   that would be necessary for (2) and apply them only if (3) doesn't
+         *   happen. 
+         * 
+         */
+
+        List<SeedStrategy> symmetrized = new ArrayList<SeedStrategy>(); 
+        Iterator<SeedStrategy> it = strat_list.iterator(); 
+        //this will store additional extension layers in the case that there are no endcap Seed/Confirm layers
+        List<SeedLayer> additionalExtendLayers = new ArrayList<SeedLayer>(); 
+        List<SeedLayer> removeLayers = new ArrayList<SeedLayer>(); 
+        while (it.hasNext()) {
+            SeedStrategy next = it.next(); 
+            boolean extendOnlyFlag = true; //If all the Seed/Confirm layers are BarrelOnly, then we can 
+                                           //just have both endcaps in the extend layers without creating a new strategy. 
+            additionalExtendLayers.clear(); 
+            removeLayers.clear(); 
+            for (SeedLayer l : next.getLayerList()) {
+                //Anything with BarrelEndcapFlag ENDCAP in seed or confirm should be mirrored for both sides
+                if (l.getBarrelEndcapFlag()==BarrelEndcapFlag.ENDCAP && l.getType()!=SeedType.Extend) {
+                    it.remove(); //remove this strategy... we will replace it with the other two symmetrized ones
+                    //loop through both north and south configurations
+                    for (BarrelEndcapFlag be : beArray) {
+                        SeedStrategy newstrat = makeMirroredLayer(next, be);
+                        symmetrized.add(newstrat); 
+                    }
+                    extendOnlyFlag = false; 
+                    break; 
+
+                } else if (l.getBarrelEndcapFlag()==BarrelEndcapFlag.ENDCAP) {
+                    removeLayers.add(l); 
+                    additionalExtendLayers.add(new SeedLayer(l.getDetName(), l.getLayer(), beArray[0], l.getType()));
+                    additionalExtendLayers.add(new SeedLayer(l.getDetName(), l.getLayer(), beArray[1], l.getType()));
+                }
+            }
+
+            if (extendOnlyFlag) {
+                next.getLayerList().addAll(additionalExtendLayers);
+                next.getLayerList().removeAll(removeLayers);
+            }
+
+        }
+        strat_list.addAll(symmetrized); 
+    }
+    
+    
+    private static SeedStrategy makeMirroredLayer(SeedStrategy next, BarrelEndcapFlag be) {
+        List<SeedLayer> symmlyrs = new ArrayList<SeedLayer>(); //store the new layers here
+        for (SeedLayer ll : next.getLayerList()) {
+            if (ll.getBarrelEndcapFlag().isBarrel()) {
+                // if it's a barrel layer, we can just add it
+                symmlyrs.add(ll);
+            } else {
+                //otherwise change from ENDCAP to either ENDCAP_NORTH or ENDCAP_SOUTH
+                SeedLayer newlyr = new SeedLayer(ll.getDetName(), ll.getLayer(), be, ll.getType());
+                symmlyrs.add(newlyr);
+            }
+        }
+        SeedStrategy newstrat = new SeedStrategy(next.getName() + be.toString(), symmlyrs); //create new strategy
+        newstrat.copyCutoffsFromStrategy(next); //copy parameters
+        return newstrat;
+    }
+    
+    
+   /**
+    * Returns a list of possible subsets of DumbLayers.... wrapper around generateAllPossibleSubsets
+    * @param allLayers
+    * @param subset_size
+    * @return
+    */
+    public static List<Set<DumbLayer>> generateAllPossibleDumbLayerSubsetsList(Set<DumbLayer> allLayers, int subset_size) {
+        Set<Object> set = new HashSet<Object>();
+        set.addAll(allLayers); 
+        Set<Set> subsets = generateAllPossibleSubsets(set, subset_size);         
+        List<Set<DumbLayer>> ret = new ArrayList<Set<DumbLayer>>(); 
+        for (Set<DumbLayer> subset : subsets) {
+            ret.add(subset); 
+        }   
+        return ret; 
+    }
+  
+       
+    /**
+     * Returns all possible subsets of a given size of the set allObjects
+     * @param allObjects The set to find subsets of
+     * @param subset_size The size desired of subsets. 
+     * @return A set of subsets, all of size sub_set size
+     */
+    public static Set<Set> generateAllPossibleSubsets(Set allObjects, int subset_size) {
+
+        assert(subset_size > 0 && subset_size <= allObjects.size()); 
+        
+        if (subset_size == 1){
+            Set<Set> ret = new HashSet<Set>(); 
+            for (Object o : allObjects){
+                Set set = new HashSet(); 
+                set.add(o); 
+                ret.add(set); 
+            }
+            return ret; 
+        }
+
+        else {
+            Set<Set> ret = new HashSet<Set>();  
+            for(Object o : allObjects) {
+                Set newSet = new HashSet(); 
+                newSet.addAll(allObjects); 
+                newSet.remove(o); 
+                Set<Set> partial = generateAllPossibleSubsets(newSet, subset_size-1); 
+                for (Set s : partial) s.add(o); 
+                ret.addAll(partial); 
+            }
+            return ret; 
+        }
+    }
+    
+}

lcsim/src/org/lcsim/recon/tracking/seedtracker/strategybuilder
StrategyCombiner.java added at 1.1
diff -N StrategyCombiner.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ StrategyCombiner.java	27 Aug 2008 17:55:49 -0000	1.1
@@ -0,0 +1,50 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.lcsim.recon.tracking.seedtracker.strategybuilder;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import org.lcsim.recon.tracking.seedtracker.SeedStrategy;
+import org.lcsim.recon.tracking.seedtracker.StrategyXMLUtils;
+
+/**
+ *
+ * @author cozzy
+ */
+public class StrategyCombiner {
+
+    public static void main(String[] args){
+        
+        if (args.length < 3){
+            printUsage(); 
+            System.exit(1); 
+        }
+        
+        String filename = args[0]; 
+        
+        List<SeedStrategy> lst = new ArrayList<SeedStrategy>(); 
+        
+        for (int i = 1; i < args.length; i++) {
+            List<SeedStrategy> portion = StrategyXMLUtils.getStrategyListFromFile(new File(args[i])); 
+            for (SeedStrategy s : portion){
+                if (!lst.contains(s)) lst.add(s); 
+            }
+        }
+        
+        StrategyXMLUtils.writeStrategyListToFile(lst, new File(filename));
+    }
+    
+    
+    
+    
+    private static void printUsage(){
+        System.out.println("Usage:"); 
+        System.out.println("StrategyCombiner OUTPUT_FILE STRATEGY1 STRATEGY2 [STRATEGY3... ]");
+        System.out.println("\t\tWhere the different strategies are XML files");   
+    }
+    
+}

lcsim/src/org/lcsim/recon/tracking/seedtracker/strategybuilder
SubsetScorer.java added at 1.1
diff -N SubsetScorer.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SubsetScorer.java	27 Aug 2008 17:55:49 -0000	1.1
@@ -0,0 +1,94 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.lcsim.recon.tracking.seedtracker.strategybuilder;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ *
+ * @author cozzy
+ */
+public class SubsetScorer {
+        
+        Map<Set<DumbLayer>,Integer> setmap = new HashMap<Set<DumbLayer>,Integer>(); 
+        LayerWeight weighter = new LayerWeight(); 
+        Map<Set<DumbLayer>,Integer> adjacencemap = new HashMap<Set<DumbLayer>,Integer>(); 
+        
+        public SubsetScorer(List<Set<DumbLayer>> setlist, List<List<DumbLayer>> adjacentSets) {
+            
+            for (Set<DumbLayer> set : setlist) {
+                if(setmap.containsKey(set)){
+                    setmap.put(set,setmap.get(set).intValue()+1);  
+                } else {
+                    setmap.put(set,1); 
+                }
+            }
+            
+           for (List<DumbLayer> list : adjacentSets) {
+               //convert to a set because of faster lookup? (actually it might not be since the collection sizes are so small?)
+               Set<DumbLayer> set = new HashSet<DumbLayer>(list.size());
+               set.addAll(list); 
+                if(adjacencemap.containsKey(set)){
+                    adjacencemap.put(set,adjacencemap.get(set).intValue()+1);  
+                } else {
+                    adjacencemap.put(set,1); 
+                }
+            }
+           
+//           System.out.println(adjacencemap.toString());
+        }
+        
+        public void setLayerWeight(LayerWeight lw) {
+            weighter = lw; 
+        }
+        
+       
+        //s * w * (a + b * adjacence ^ c)
+        //
+        public double getScore(Set<DumbLayer> testSet) {
+          return getUnweightedScore(testSet) * weighter.getWeight(testSet)
+                  * (  weighter.getAdjacenceConstant() + 
+                        Math.pow(getAdjacence(testSet), weighter.getAdjacenceExponent())
+                         * weighter.getAdjacenceMultiplier() 
+                    ); 
+            
+            
+         
+        }
+        
+        public double getUnweightedScore(Set<DumbLayer> testSet){
+            
+            int ret = 0; 
+            for (Set<DumbLayer> s : setmap.keySet()){
+                if (s.containsAll(testSet)) {
+                    ret+= setmap.get(s).intValue();
+                }
+            }
+            return ret;
+        }
+        
+        public int getAdjacence(Set<DumbLayer> testSet){
+            if (adjacencemap.containsKey(testSet)){
+                return adjacencemap.get(testSet); 
+            } 
+            
+            return 0; 
+        }
+        
+        public void markUsed(Set<DumbLayer> testSet) {
+            for (Set<DumbLayer> s : setmap.keySet()){
+                if (s.containsAll(testSet)) {
+                    setmap.put(s,0); 
+                }
+            }
+        }
+        
+        
+    }
\ No newline at end of file
CVSspam 0.2.8