Commit in GeomConverter/src/org/lcsim/geometry/compact/converter/GODL on MAIN
Main.java+723added 1.1
Added Main routine implementing converter from compact to GODL.  (Commit for WL.)

GeomConverter/src/org/lcsim/geometry/compact/converter/GODL
Main.java added at 1.1
diff -N Main.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Main.java	23 Jul 2005 00:43:46 -0000	1.1
@@ -0,0 +1,723 @@
+package org.lcsim.geometry.compact.converter.GODL;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.List;
+import java.util.Set;
+import javax.swing.filechooser.FileFilter;
+import org.lcsim.geometry.compact.Header;
+import org.lcsim.geometry.compact.Constant;
+import org.lcsim.geometry.compact.Detector;
+import org.lcsim.geometry.GeometryReader;
+import org.lcsim.geometry.compact.Field;
+import org.lcsim.geometry.compact.Readout;
+import org.lcsim.geometry.compact.Segmentation;
+import org.lcsim.geometry.compact.Subdetector;
+import org.lcsim.geometry.compact.converter.Converter;
+import org.lcsim.geometry.field.Solenoid;
+import org.lcsim.geometry.layer.Layer;
+import org.lcsim.geometry.layer.LayerSlice;
+import org.lcsim.geometry.layer.LayerStack;
+import org.lcsim.geometry.segmentation.GridXYZ;
+import org.lcsim.geometry.segmentation.NonprojectiveCylinder;
+import org.lcsim.geometry.segmentation.ProjectiveCylinder;
+import org.lcsim.geometry.segmentation.ProjectiveZPlane;
+import org.lcsim.geometry.subdetector.CylindricalBarrelCalorimeter;
+import org.lcsim.geometry.subdetector.CylindricalEndcapCalorimeter;
+import org.lcsim.geometry.subdetector.DiskTracker;
+import org.lcsim.geometry.subdetector.MultiLayerTracker;
+import org.lcsim.geometry.util.IDDescriptor;
+import org.lcsim.material.Material;
+import org.lcsim.material.MaterialElement;
+import org.lcsim.material.MaterialManager;
+/**
+ *
+ * @author Willy Langeveld
+ */
+public class Main implements Converter
+{
+    private HashSet materials;
+    private boolean existsMaterial(String mat)
+    {
+        return(materials.contains(mat));
+    }
+    private void addMaterial(String mat)
+    {
+        materials.add(mat);
+        return;
+    }
+    private static boolean validateDefault = true;
+    private boolean validate;
+    /**
+     * @param args the command line arguments
+     */
+    public static void main(String[] args) throws Exception
+    {
+        if (args.length < 1 || args.length >2) usage();
+        String fn = args[0];
+        InputStream in = new BufferedInputStream(new FileInputStream(args[0]));
+        OutputStream out = (args.length == 1 ? System.out : new BufferedOutputStream(new FileOutputStream(args[1])));
+        //String fn = "C:/cygwin/home/wglp09/GeomConverter/test/org/lcsim/geometry/compact/sdjan03_compact.xml";
+        //InputStream in = new BufferedInputStream(new FileInputStream(fn));
+        //OutputStream out = new BufferedOutputStream(new FileOutputStream("C:/cygwin/home/wglp09/lelaps/lelaps/foo.godl"));
+        new Main(validateDefault).convert(fn,in,out);
+    }
+    Main(boolean validate) throws Exception
+    {
+        materials = new HashSet();
+        this.validate = validate;
+    }
+    public Main() throws Exception
+    {
+        this(validateDefault);
+    }
+    public void val(PrintStream p, String s, String t)
+    {
+        if (t != null) p.println(s + " = \"" + t + "\";");
+        else           p.println(s + " = \"\";");
+        return;
+    }
+    public void vald(PrintStream p, String s, String t)
+    {
+        if (t != null) p.println(s + " = " + t + ";");
+        else           p.println(s + " = 0;");
+        return;
+    }
+    public void valdc(PrintStream p, String s, String t)
+    {
+        if (t != null) p.println(s + " = " + t);
+        else           p.println(s + " = 0;");
+        return;
+    }
+    public void val(PrintStream p, String s, double t)
+    {
+        p.println(s + " = " + t + ";");
+        return;
+    }
+    public void pval(PrintStream p, String s, String t)
+    {
+        if (t != null) p.println(s + " += \"" + t + "\";");
+        return;
+    }
+    public void pvald(PrintStream p, String s, String t)
+    {
+        if (t != null) p.println(s + " += " + t + ";");
+        return;
+    }
+    public void pval(PrintStream p, String s, double t)
+    {
+        p.println(s + " += " + t + ";");
+        return;
+    }
+    public void line(PrintStream p, String s)
+    {
+        if (s != null) p.println(s);
+        else           p.println("");
+        return;
+    }
+    public void line(PrintStream p)
+    {
+        p.println("");
+        return;
+    }
+    public void preamble(PrintStream p, String inputFileName, Detector det)
+    {
+        line(p, "###");
+        line(p);
+        line(p, "# GeomConverter-generated GODL output");
+        line(p, "# -- GODL converter version 1.0 --");
+        line(p, "# From: " + inputFileName);
+        line(p);
+        line(p, "###");
+        line(p, "cm  = 0.01 _meter;");
+        line(p, "m   = _meter;");
+        line(p, "g   = _gram;");
+        line(p, "atm = _atmosphere;");
+        line(p, "K   = _kelvin;");
+        line(p, "T   = _tesla;");
+        line(p, "deg = _degree;");
+        line(p, "unit(\"cm\", \"m\", \"g\", \"atm\", \"K\", \"T\", \"deg\");");
+        return;
+    }
+    public void header(PrintStream p, Detector det)
+    {
+        line(p, "#");
+        line(p, "# Header");
+        line(p, "#");
+        
+        Header h = det.getHeader();
+        val(p, "detectorName   ", h.getDetectorName());
+        val(p, "author         ", h.getAuthor());
+        val(p, "detectorURL    ", h.getURL());
+        val(p, "comment        ", h.getComment());
+        val(p, "detectorVersion", h.getVersion());
+        return;
+    }
+    public void constants(PrintStream p, Detector det)
+    {
+        line(p, "#");
+        line(p, "# Constants");
+        line(p, "#");
+        
+        Map<String,Constant> cl = det.getConstants();
+        Set<Map.Entry<String, Constant>> set = cl.entrySet();
+        for (Map.Entry<String, Constant> i: set)
+        {
+            val(p, "data_" + i.getKey(), i.getValue().getValue());
+        }
+        return;
+    }
+    public void materials(PrintStream p, Detector det)
+    {
+        line(p, "#");
+        line(p, "# Materials");
+        line(p, "#");
+        line(p, "vacuum = element(\"vacuum\");");
+        addMaterial("vacuum");
+        MaterialManager mm = MaterialManager.instance();
+        Map<String, Material> mmap = mm.materials();
+        for (Material i: mmap.values())
+        {
+            List<MaterialElement> el = i.getElements();
+            List<Double> elf = i.getMassFractions();
+            String formula = "";
+            if (el.size() == 1)
+            {
+                formula += el.get(0).getName();
+                vald(p, "mat_" + i.getName(), "element(\"" + formula + "\")");
+            }
+            else
+            {
+                for (int j = 0; j < el.size(); j++)
+                {
+                    formula += el.get(j).getName();
+                    formula += "" + elf.get(j);
+                }
+                vald(p, "mat_" + i.getName(), "compound(formula(\"" + formula + "\"), density("
+                        + i.getRadiationLength()/i.getRadiationLengthWithDensity() + " g/cm3))");
+            }
+            addMaterial("mat_" + i.getName());
+        }
+        return;
+    }
+    public void fields(PrintStream p, Detector det)
+    {
+        line(p, "#");
+        line(p, "# Magnetic field");
+        line(p, "#");
+        
+        Map<String, Field> fl = det.getFields();
+        for (Field f: fl.values())
+        {
+            double[] fi = {0., 0., 5.0};
+            double[] fo = {0., 0., -0.6};
+            double or = 5000.0;
+            double zm = 2810.0;
+            if (f instanceof Solenoid)
+            {
+                fi = ((Solenoid) f).getInnerField();
+                fo = ((Solenoid) f).getOuterField();
+                or = Math.sqrt(((Solenoid) f).getOuterRadius2());
+                zm = ((Solenoid) f).getZMax();
+            }
+            else
+            {
+                System.err.println(" -- Ignoring field " + f.getName() + ", GeomConverter doesn't support fields properly.");
+                System.err.println(" -- Using standard 5 tesla field");
+            }
+            line(p, "Field = cylinder(name(\"Secondary BField\"),");
+            line(p, "                 innerRadius(0.0 cm), outerRadius(" + or * 1.5 + " mm), length(" + 2 * zm + " mm),");
+            line(p, "                 bfield(" + fo[0] + " T, "+ fo[1] + " T, " + fo[2] + " T));");
+            line(p, "Field2 = cylinder(name(\"Main BField\"),");
+            line(p, "                  innerRadius(0.0), outerRadius(" + or + " mm), length(" + 2 * zm + " mm),");
+            line(p, "                  bfield(" + fi[0] + " T, "+ fi[1] + " T, " + fi[2] + " T));");
+            line(p, "Field += placement(@Field2);");
+        }
+        return;
+    }
+    public void readouts(PrintStream p, Detector det)
+    {
+        line(p, "#");
+        line(p, "# ID Codes (Readouts)");
+        line(p, "#");
+        
+        Map<String, Readout> rl = det.getReadouts();
+        for (Readout r: rl.values())
+        {
+            IDDescriptor id = r.getIDDescriptor();
+            Segmentation seg = r.getSegmentation();
+            int theta_seg = 0;
+            int phi_seg = 0;
+            double x_seg = 0;
+            double y_seg = 0;
+            double z_seg = 0;
+            if (seg instanceof ProjectiveCylinder)
+            {
+                theta_seg = ((ProjectiveCylinder) seg).getThetaBins();
+                phi_seg = ((ProjectiveCylinder) seg).getPhiBins();
+            }
+            else if (seg instanceof NonprojectiveCylinder)
+            {
+                z_seg = ((NonprojectiveCylinder) seg).getGridSizeZ();
+                phi_seg = (int) (2 * Math.PI / ((NonprojectiveCylinder) seg).getGridSizePhi());
+            }
+            else if (seg instanceof ProjectiveZPlane)
+            {
+                theta_seg = ((ProjectiveZPlane) seg).getThetaBins();
+                phi_seg = ((ProjectiveZPlane) seg).getPhiBins();
+            }
+            else if (seg instanceof GridXYZ)
+            {
+                x_seg = ((GridXYZ) seg).getGridSizeX();
+                y_seg = ((GridXYZ) seg).getGridSizeY();
+                z_seg = ((GridXYZ) seg).getGridSizeZ();
+            }
+            
+            String rname = r.getName();
+            val(p, rname, "x: fp0 y: fp1 z: fp2 layer: d3 0 0");
+            boolean usingfirst = true;
+            int rotations = 0;
+            for (int i = 0; i < id.fieldCount(); i++)
+            {
+                String name = id.fieldName(i);
+                int    start = id.fieldStart(i);
+                int    length = id.fieldLength(i);
+                if (length < 0)
+                {
+                    length = - length;
+                }
+                String code = "";
+                if (name.equals("layer"))
+                {
+                    code =  " layer 1 " + length + " bitshift 1 sub and";
+                }
+                else if (name.equals("system"))
+                {
+                    code =  " system 1 " + length + " bitshift 1 sub and";
+                }
+                else if (name.equals("barrel"))
+                {
+                    //
+                    // Note that barrel may be one or zero. If 1, then we make it 2 if z < 0.
+                    //
+                    code =  " barrel barrel z neg H truncate mul add 1 " + length + " bitshift 1 sub and";
+                }
+                else if(name.equals("theta"))
+                {
+                    code =  " x x mul y y mul add sqrt z atan2 " + theta_seg +
+                            " mul _pi div truncate 1 " + length + " bitshift 1 sub and";
+                }
+                else if(name.equals("phi"))
+                {
+                    code =  " y x atan2m " + phi_seg +
+                            " mul 0.5 mul _pi div truncate 1 " + length +
+                            " bitshift 1 sub and";
+                }
+                else if(name.equals("x"))
+                {
+                    code =  " x " + x_seg + " div truncate 1 " + length + " bitshift 1 sub and";
+                }
+                else if(name.equals("y"))
+                {
+                    code =  " y " + y_seg + " div truncate 1 " + length + " bitshift 1 sub and";
+                }
+                else if(name.equals("z"))
+                {
+                    code =  " z " + z_seg + " div truncate 1 " + length + " bitshift 1 sub and";
+                }
+                if (start > 31)
+                {
+                    code = " exch" + code;
+                    usingfirst = false;
+                    start -= 32;
+                }
+                if (start > 0) code += " " + start + " bitshift";
+                code += " or";
+                if (!usingfirst)
+                {
+                    usingfirst = true;
+                    code += " exch";
+                }
+                pval(p, rname, code);
+            }
+        }
+        return;
+    }
+    String findMaterial(PrintStream p, Layer layer)
+    {
+        List<LayerSlice> lslist = layer.getSlices();
+        String material = "mat_";
+        int nslices = 0;
+        for (LayerSlice lsl: lslist)
+        {
+            String partname = lsl.getMaterial().getName();
+            material += partname;
+            nslices++;
+        }
+        //
+        // Make a new material if this one doesn't exist yet
+        //
+        if (nslices > 1 && !existsMaterial(material))
+        {
+            valdc(p, material, "mixture(name(\"" + material + "\"),");
+            for (LayerSlice lsl: lslist)
+            {
+                double t = lsl.getThickness();
+                String partname = lsl.getMaterial().getName();
+                line(p, "   part(@mat_" + partname + ", fraction(" + t + ")),");
+            }
+            line(p, "   by(\"volume\")");
+            line(p, ");");
+            addMaterial(material);
+        }
+        return(material);
+    }
+    public void beampipe(PrintStream p, Detector det)
+    {
+        line(p, "#");
+        line(p, "# Since the GODL converter does not yet support polycone beampipes,");
+        line(p, "# we supply here a generic beampipe plus various masks");
+        line(p, "# These were taken from the SiDMay05.xml compact description,");
+        line(p, "#");
+        vald(p, "Be", "element(\"Be\");");
+        vald(p, "Ti", "element(\"Ti\");");
+        vald(p, "W", "element(\"W\");");
+        // Beam pipe:
+        //<constant name="tracking_region_zmax" value="167.9*cm" />
+        vald(p, "tracking_region_zmax", "167.9 cm");
+        //<zplane rmin="tracking_region_zmax*17./351" rmax="(tracking_region_zmax*17./351+.1)" z="-tracking_region_zmax" />
+        //<zplane rmin="1.2*cm" rmax="1.3*cm" z="-6.251*cm" />
+        line(p, "zmin   = -tracking_region_zmax;");
+        line(p, "zmax   = -6.251 cm;");
+        line(p, "length = zmax - zmin;");
+        line(p, "offset = zmin + 0.5 * length;");
+        line(p, "Pipe1  = cone(name(\"Pipe1\"),");
+        line(p, "    innerBottomRadius(tracking_region_zmax * 17.0/351.0),");
+        line(p, "    outerBottomRadius(tracking_region_zmax * 17.0/351.0 + 0.1 cm),");
+        line(p, "    innerTopRadius(1.2 cm),");
+        line(p, "    outerTopRadius(1.3 cm),");
+        line(p, "    length(length), @Be);");
+        line(p, "World += placement(@Pipe1);");
+        //<zplane rmin="1.2*cm" rmax="1.225*cm" z="-6.25*cm" />
+        line(p, "zmin   = zmax;");
+        line(p, "zmax   = -6.25 cm;");
+        line(p, "length = zmax - zmin;");
+        line(p, "offset = zmin + 0.5 * length;");
+        line(p, "Pipe2  = cone(name(\"Pipe2\"),");
+        line(p, "    innerBottomRadius(1.2 cm),");
+        line(p, "    outerBottomRadius(1.3 cm),");
+        line(p, "    innerTopRadius(1.2 cm),");
+        line(p, "    outerTopRadius(1.225 cm),");
+        line(p, "    length(length), @Be);");
+        line(p, "World += placement(@Pipe2);");
+        //<zplane rmin="1.2*cm" rmax="1.225*cm" z="6.25*cm" />
+        line(p, "zmin   = zmax;");
+        line(p, "zmax   = 6.25 cm;");
+        line(p, "length = zmax - zmin;");
+        line(p, "offset = zmin + 0.5 * length;");
+        line(p, "Pipe3  = cylinder(name(\"Pipe3\"),");
+        line(p, "    innerRadius(1.2 cm),");
+        line(p, "    outerRadius(1.225 cm),");
+        line(p, "    length(length), @Be);");
+        line(p, "World += placement(@Pipe3);");
+        //<zplane rmin="1.2*cm" rmax="1.3*cm" z="6.251*cm" />
+        line(p, "zmin   = zmax;");
+        line(p, "zmax   = 6.251 cm;");
+        line(p, "length = zmax - zmin;");
+        line(p, "offset = zmin + 0.5 * length;");
+        line(p, "Pipe4  = cone(name(\"Pipe4\"),");
+        line(p, "    innerBottomRadius(1.2 cm),");
+        line(p, "    outerBottomRadius(1.225 cm),");
+        line(p, "    innerTopRadius(1.2 cm),");
+        line(p, "    outerTopRadius(1.3 cm),");
+        line(p, "    length(length), @Be);");
+        line(p, "World += placement(@Pipe4);");
+        //<zplane rmin="tracking_region_zmax*17./351" rmax="(tracking_region_zmax*17./351+.1)" z="tracking_region_zmax" />
+        line(p, "zmin   = zmax;");
+        line(p, "zmax   = tracking_region_zmax;");
+        line(p, "length = zmax - zmin;");
+        line(p, "offset = zmin + 0.5 * length;");
+        line(p, "Pipe5  = cone(name(\"Pipe5\"),");
+        line(p, "    innerBottomRadius(1.2 cm),");
+        line(p, "    outerBottomRadius(1.3 cm),");
+        line(p, "    innerTopRadius(tracking_region_zmax * 17.0/351.0),");
+        line(p, "    outerTopRadius(tracking_region_zmax * 17.0/351.0 + 0.1 cm),");
+        line(p, "    length(length), @Be);");
+        line(p, "World += placement(@Pipe5);");
+        // Liner:
+        //<zplane z="-6.25*cm" rmin="1.195*cm" rmax="1.20*cm" />
+        //<zplane z="6.25*cm" rmin="1.195*cm" rmax="1.20*cm" />
+        line(p, "zmin   = -6.25 cm;");
+        line(p, "zmax   = 6.25 cm;");
+        line(p, "length = zmax - zmin;");
+        line(p, "offset = zmin + 0.5 * length;");
+        line(p, "Pipe_Inner_Shield = cylinder(name(\"Pipe inner shield\"),");
+        line(p, "    innerRadius(1.195 cm), outerRadius(1.2 cm),");
+        line(p, "    length(length), @Ti);");
+        line(p, "World += placement(@Pipe_Inner_Shield, translate(0, 0, offset));");
+        line(p, "#");
+        line(p, "# Masks");
+        line(p, "#");
+        //<zplane rmin="8.0*cm" rmax="19.0*cm" z="200.0*cm" />
+        //<zplane rmin="15.0*cm" rmax="19.0*cm" z="315.0*cm" />
+        line(p, "zmin   = 200.0 cm;");
+        line(p, "zmax   = 315.0 cm;");
+        line(p, "length = zmax - zmin;");
+        line(p, "offset = zmin + 0.5 * length;");
+        line(p, "Mask_Cone = cone(name(\"Mask cone\"),");
+        line(p, "               innerBottomRadius(8.0 cm), outerBottomRadius(19.0 cm),");
+        line(p, "               innerTopRadius(15 cm),     outerTopRadius(19.0 cm),");
+        line(p, "               length(length), @W, type(\"mask\"));");
+        line(p, "World += placement(@Mask_Cone, translate(0, 0, offset));");
+        line(p, "World += placement(@Mask_Cone, rotate(axis(\"x\"), angle(180 deg)), translate(0, 0, -offset));");
+        return;
+    }
+    public void detectors(PrintStream p, Detector det)
+    {
+        line(p, "#");
+        line(p, "# Detector and subdetectors");
+        line(p, "# First create a world cylinder from the box coordinates already specified");
+        line(p, "#");
+        line(p, "data_world_r = sqrt(data_world_x * data_world_x + data_world_y * data_world_y) / 4.0;");
+        line(p, "World = cylinder(name(detectorName), radius(data_world_r mm), length(data_world_z mm), @vacuum);");
+        line(p, "#");
+        line(p, "# Now create other detectors and add them to the world");
+        line(p, "#");
+        Map<String, Subdetector> dl = det.getSubdetectors();
+        for (Subdetector s: dl.values())
+        {
+            if (s instanceof CylindricalBarrelCalorimeter)
+            {
+                CylindricalBarrelCalorimeter m = (CylindricalBarrelCalorimeter) s;
+                String name     = m.getName();
+                int sysid       = m.getSystemID();
+                String rname    = m.getReadout().getName();
+                double innerR   = m.getInnerRadius();
+                double outerR   = m.getOuterRadius();
+                double zmin     = m.getZMin();
+                double zmax     = m.getZMax();
+                LayerStack ls   = m.getLayering().getLayerStack();
+                int nlayers     = ls.getNumberOfLayers();
+                
+                Layer layer       = ls.getLayer(0);
+                boolean sensitive = layer.findIndexOfFirstSensitiveSlice() != -1;
+                String material   = findMaterial(p, layer);
+                
+                valdc(p, name, "cylinder(name(\"" + name + "\"), ");
+                line(p, "   length(" + (zmax - zmin) + " mm), ");
+                line(p, "   innerRadius(" + innerR + " mm),");
+                line(p, "   outerRadius(" + outerR + " mm),");
+                line(p, "   nLayers(" + nlayers + "),");
+                String comma = "";
+                if (sensitive) comma = ",";
+                String type = "hadcal";
+                if (name.startsWith("EM") || name.startsWith("LUM")) type = "emcal";
+                line(p, "   @" + material + ", type(\"" + type + "\")" + comma);
+                if (sensitive)
+                {
+                    line(p, "   idCode(code(" + rname + "),");
+                    line(p, "          data(\"system\", " + sysid + "),");
+                    line(p, "          data(\"barrel\", 0)");
+                    line(p, "   )");
+                }
+                line(p, ");");
+                line(p, "World += placement(@" + name + ", translate(0, 0, " + (0.5 * (zmax + zmin)) + " mm));");
+            }
+            else if (s instanceof CylindricalEndcapCalorimeter)
+            {
+                CylindricalEndcapCalorimeter m = (CylindricalEndcapCalorimeter) s;
+                String name     = m.getName();
+                int sysid       = m.getSystemID();
+                boolean reflect = m.getReflect();
+                String rname    = m.getReadout().getName();
+                double innerR   = m.getInnerRadius();
+                double outerR   = m.getOuterRadius();
+                double zmin     = m.getZMin();
+                double zmax     = m.getZMax();
+                LayerStack ls   = m.getLayering().getLayerStack();
+                int nlayers     = ls.getNumberOfLayers();
+                
+                Layer layer       = ls.getLayer(0);
+                boolean sensitive = layer.findIndexOfFirstSensitiveSlice() != -1;
+                String material   = findMaterial(p, layer);
+                
+                valdc(p, name, "cylinder(name(\"" + name + "\"), ");
+                line(p, "   length(" + (zmax - zmin) + " mm), ");
+                line(p, "   innerRadius(" + innerR + " mm),");
+                line(p, "   outerRadius(" + outerR + " mm),");
+                line(p, "   nSlices(" + nlayers + "),");
+                String comma = "";
+                if (sensitive) comma = ",";
+                String type = "hadcal";
+                if (name.startsWith("EM") || name.startsWith("LUM")) type = "emcal";
+                line(p, "   @" + material + ", type(\"" + type + "\")" + comma);
+                if (sensitive)
+                {
+                    line(p, "   idCode(code(" + rname + "),");
+                    line(p, "          data(\"system\", " + sysid + "),");
+                    line(p, "          data(\"barrel\", 1)");
+                    line(p, "   )");
+                }
+                line(p, ");");
+                line(p, "World += placement(@" + name + ", translate(0, 0, " + (0.5 * (zmax + zmin)) + " mm));");
+                if (reflect)
+                {
+                    line(p, "World += placement(@" + name
+                            + ", rotate(axis(\"x\"), angle(180 deg)), translate(0, 0, "
+                            + (- 0.5 * (zmax + zmin)) + " mm));");
+                }
+            }
+            else if (s instanceof DiskTracker)
+            {
+                DiskTracker m = (DiskTracker) s;
+                String name     = m.getName();
+                int sysid       = m.getSystemID();
+                boolean reflect = m.getReflect();
+                String rname    = m.getReadout().getName();
+                double[] innerR = m.getInnerR();
+                double[] outerR = m.getOuterR();
+                double[] innerZ = m.getInnerZ();
+                LayerStack ls   = m.getLayering().getLayerStack();
+                int nlayers     = ls.getNumberOfLayers();
+                
+                for (int i = 0; i < nlayers; i++)
+                {
+                    Layer layer       = ls.getLayer(i);
+                    double thickness  = layer.getThickness();
+                    boolean sensitive = layer.findIndexOfFirstSensitiveSlice() != -1;
+                    String material   = findMaterial(p, layer);
+                    
+                    String detname = name;
+                    if (nlayers > 1) detname += "." + i;
+                    
+                    valdc(p, detname, "cylinder(name(\"" + name + "\"), ");
+                    line(p, "   length(" + thickness + " mm), ");
+                    line(p, "   innerRadius(" + innerR[i] + " mm),");
+                    line(p, "   outerRadius(" + outerR[i] + " mm),");
+                    String comma = "";
+                    if (sensitive) comma = ", ";
+                    line(p, "   @" + material + ", type(\"tracker\")" + comma);
+                    if (sensitive)
+                    {
+                        line(p, "   idCode(code(" + rname + "),");
+                        line(p, "          data(\"layer\", " + i + "),");
+                        line(p, "          data(\"system\", " + sysid + "),");
+                        line(p, "          data(\"barrel\", 1)");
+                        line(p, "   )");
+                    }
+                    line(p, ");");
+                    line(p, "World += placement(@" + detname + ", translate(0, 0, " + (innerZ[i] + 0.5 * thickness) + " mm));");
+                    if (reflect)
+                    {
+                        line(p, "World += placement(@" + detname
+                                + ", rotate(axis(\"x\"), angle(180 deg)), translate(0, 0, "
+                                + (- innerZ[i] - 0.5 * thickness) + " mm));");
+                    }
+                }
+            }
+            else if (s instanceof MultiLayerTracker)
+            {
+                MultiLayerTracker m = (MultiLayerTracker) s;
+                String name     = m.getName();
+                int sysid       = m.getSystemID();
+                String rname    = m.getReadout().getName();
+                double[] innerR = m.getInnerR();
+                double[] outerZ = m.getOuterZ();
+                LayerStack ls   = m.getLayering().getLayerStack();
+                int nlayers     = ls.getNumberOfLayers();
+                
+                for (int i = 0; i < nlayers; i++)
+                {
+                    Layer layer       = ls.getLayer(i);
+                    double thickness  = layer.getThickness();
+                    boolean sensitive = layer.findIndexOfFirstSensitiveSlice() != -1;
+                    String material   = findMaterial(p, layer);
+                    
+                    String detname = name;
+                    if (nlayers > 1) detname += "." + i;
+                    
+                    valdc(p, detname, "cylinder(name(\"" + name + "\"), ");
+                    line(p, "   length(" + outerZ[i] * 2 + " mm), ");
+                    line(p, "   innerRadius(" + innerR[i] + " mm),");
+                    line(p, "   outerRadius(" + (innerR[i] + thickness) + " mm),");
+                    String comma = "";
+                    if (sensitive) comma = ", ";
+                    line(p, "   @" + material + ", type(\"tracker\")" + comma);
+                    if (sensitive)
+                    {
+                        line(p, "   idCode(code(" + rname + "),");
+                        line(p, "          data(\"layer\", " + i + "),");
+                        line(p, "          data(\"system\", " + sysid + "),");
+                        line(p, "          data(\"barrel\", 0)");
+                        line(p, "   )");
+                    }
+                    line(p, ");");
+                    line(p, "World += placement(@" + detname + ");");
+                }
+            }
+        }
+        return;
+    }
+    
+    public void convert(String inputFileName, InputStream in, OutputStream out) throws Exception
+    {
+        if ( out != null )
+        {
+            GeometryReader reader = new GeometryReader();
+            Detector det = reader.read(in);
+            PrintStream p = new PrintStream(out);
+            
+            preamble(p, inputFileName, det);
+            header(p,  det);
+            constants(p, det);
+            materials(p, det);
+            fields(p, det);
+            readouts(p, det);
+            detectors(p, det);
+            beampipe(p, det);
+            
+            line(p, "#");
+            line(p, "# End of file");
+            line(p, "#");
+            
+            out.close();
+        }
+        return;
+    }
+    
+    private static void usage()
+    {
+        System.out.println("java "+Main.class.getName()+" <compact> [<GODL>]");
+        System.exit(0);
+    }
+    
+    public String getOutputFormat()
+    {
+        return "GODL";
+    }
+    
+    public FileFilter getFileFilter()
+    {
+        return new GODLFileFilter();
+    }
+    
+    private static class GODLFileFilter extends FileFilter
+    {
+        public boolean accept(java.io.File file)
+        {
+            return file.isDirectory() || file.getName().endsWith(".godl");
+        }
+        
+        public String getDescription()
+        {
+            return "GODL file (*.godl)";
+        }
+    }
+}
\ No newline at end of file
CVSspam 0.2.8