Commit in CDMS/src/CDMS/Partridge on MAIN
CompareImages.java+94added 1.1
Image.java+61added 1.1
ImageAnalysis.java+96added 1.1
ImageIOTest.java+53added 1.1
ImageNavigator.java+578added 1.1
InterpolatePixelIntensity.java+184added 1.1
PixelArray.java+146added 1.1
ProcessImage.java+48added 1.1
ReadBMP.java+82added 1.1
ReadTGA.java+87added 1.1
WriteBMP.java+91added 1.1
+1520
11 added files
Rearrange CDMS code

CDMS/src/CDMS/Partridge
CompareImages.java added at 1.1
diff -N CompareImages.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ CompareImages.java	28 Jul 2010 17:32:08 -0000	1.1
@@ -0,0 +1,94 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package CDMS.Partridge;
+
+import Partridge.*;
+import org.freehep.math.minuit.FCNBase;
+
+/**
+ *
+ * @author richp
+ */
+public class CompareImages implements FCNBase {
+
+    private Image _test;
+    private Image _ref;
+    private Image _dif;
+    private int _height;
+    private int _width;
+    private double _eps = 1.e-6;
+    private int _calls = 0;
+    private WriteBMP _writer = new WriteBMP();
+
+    public CompareImages(Image test, Image ref) {
+        _test = test;
+        _ref = ref;
+        _height = ref.getHeight();
+        _width = ref.getWidth();
+
+        //  Check that the images are the same size
+        if (test.getHeight() != _height ||
+                test.getWidth() != _width) {
+            throw new RuntimeException("Images are different size");
+        }
+    }
+
+    public double valueOf(double[] args) {
+
+        //  Get the variables we are minimizing
+        double hoffset = args[0];
+        double voffset = args[1];
+        double rotang = args[2];
+        int border = (int) Math.round(args[3]);
+
+        _calls++;
+
+        //  Setup pixel arrays for the reference image and the test image
+        PixelArray refpix = new PixelArray(0., 0., 0., 1., _width, _height);
+        PixelArray testpix = new PixelArray(hoffset, voffset, rotang, 1., _width, _height);
+
+        //  Setup the pixel interpolation
+        InterpolatePixelIntensity interpolate = new InterpolatePixelIntensity(_ref, refpix, testpix);
+
+        double chisq = 0.;
+//        _dif = new Image(_height - 2 * _border, _width - 2 * _border);
+
+        //  Loop over pixels in the test image, leaving off the border pixels that might not
+        //  have corresponding reference pixels
+        for (int row = border; row < _height - border; row++) {
+            for (int col = border; col < _width - border; col++) {
+
+                //  Find the interpolated reference intensity for this test pixel
+                int pixel = testpix.getPixel(row, col);
+                double ipred = interpolate.Interpolate(pixel);
+
+                //  Compare with the intensity of the test pixel
+                double itest = _test.getIntensity(row, col);
+                chisq += (itest - ipred) * (itest - ipred);
+//                int red = 0;
+//                int blue = 0;
+//                int green = 0;
+//                if (itest > ipred) {
+//                    red = (int) (itest - ipred);
+//                }
+//                if (itest < ipred) {
+//                    green = (int) (ipred - itest);
+//                }
+//                _dif.setPixel(row - _border, col - _border, red, green, blue);
+            }
+        }
+
+//        String filename = "c:/CDMS/difimage"+_calls+".bmp";
+//        _writer.WriteImage(_dif, filename);
+
+        System.out.println("hoff: " + hoffset + " voff: " + voffset + " rotang: " + rotang + " chisq: " + chisq/1000.);
+        return chisq / 1000.;
+    }
+
+    public Image getImage() {
+        return _dif;
+    }
+
+}

CDMS/src/CDMS/Partridge
Image.java added at 1.1
diff -N Image.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Image.java	28 Jul 2010 17:32:08 -0000	1.1
@@ -0,0 +1,61 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package CDMS.Partridge;
+
+/**
+ *
+ * @author richp
+ */
+public class Image {
+
+    private int _width;
+    private int _height;
+    private int[][] _red;
+    private int[][] _green;
+    private int[][] _blue;
+
+    public Image(int width, int height) {
+
+        _width = width;
+        _height = height;
+        _red = new int[_height][_width];
+        _green = new int[_height][_width];
+        _blue = new int[_height][_width];
+    }
+
+    public void setPixel (int row, int col, int red, int green, int blue) {
+        _red[row][col] = red;
+        _green[row][col] = green;
+        _blue[row][col] = blue;
+    }
+
+    public int getWidth() {
+        return _width;
+    }
+
+    public int getHeight() {
+        return _height;
+    }
+
+    public int getRed(int row, int col) {
+        return _red[row][col];
+    }
+
+    public int getGreen(int row, int col) {
+        return _green[row][col];
+    }
+
+    public int getBlue(int row, int col) {
+        return _blue[row][col];
+    }
+
+    public double getIntensity(int row, int col) {
+        int red = _red[row][col];
+        int grn = _green[row][col];
+        int blu = _blue[row][col];
+        return Math.sqrt((red*red + grn*grn + blu*blu) / 3.);
+    }
+}

CDMS/src/CDMS/Partridge
ImageAnalysis.java added at 1.1
diff -N ImageAnalysis.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ImageAnalysis.java	28 Jul 2010 17:32:08 -0000	1.1
@@ -0,0 +1,96 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package CDMS.Partridge;
+
+import java.io.IOException;
+import org.freehep.math.minuit.FunctionMinimum;
+import org.freehep.math.minuit.MnMigrad;
+import org.freehep.math.minuit.MnSimplex;
+import org.freehep.math.minuit.MnUserParameters;
+
+/**
+ *
+ * @author richp
+ */
+public class ImageAnalysis {
+
+    public static void main(String[] args) throws IOException {
+
+        //  Set the file names of the test and reference images
+        String test_file = "c:/CDMS/ChargeDivisionUR_24-2_1.bmp";
+//        String test_file = "c:/CDMS/MedLightSide.bmp";
+//        String test_file = "c:/CDMS/Comparison.bmp";
+        String ref_file = "c:/CDMS/ChargeDivisionUR_23-2_1.bmp";
+
+        //  Read in the image files
+        ReadBMP reader = new ReadBMP();
+        WriteBMP writer = new WriteBMP();
+        Image test = reader.ReadImage(test_file);
+        Image ref = reader.ReadImage(ref_file);
+        writer.WriteImage(ref, "c:/CDMS/testimage.bmp");
+
+        //  Instantiate the image comparison class with these images
+        CompareImages comp = new CompareImages(test, ref);
+
+        MnUserParameters pars = new MnUserParameters();
+        pars.add("xoff", 0.234, 0.0, -10., 10.);
+        pars.add("yoff", 0.090, 0.0, -10., 10.);
+        pars.add("angle", 0.006, .0002, -0.05, 0.05);
+        pars.add("border", 20., 0.);
+        pars.fix(0);
+        pars.fix(1);
+        pars.fix(2);
+        pars.fix(3);
+
+        MnSimplex minimize = new MnSimplex(comp, pars);
+
+//        MnMigrad minimize = new MnMigrad(comp, pars);
+
+        FunctionMinimum fcnmin = minimize.minimize();
+        MnUserParameters finalpars = fcnmin.userParameters();
+        double hoff = finalpars.value(0);
+        double voff = finalpars.value(1);
+        double rotang = finalpars.value(2);
+        int border = (int) Math.round(finalpars.value(3));
+
+        int width = test.getWidth();
+        int height = test.getHeight();
+        PixelArray testpix = new PixelArray(hoff, voff, rotang, 1., width, height);
+        PixelArray refpix = new PixelArray(0., 0., 0., 1., width, height);
+        InterpolatePixelIntensity interpolate = new InterpolatePixelIntensity(ref, refpix, testpix);
+        Image output = new Image(width - 2 * border, height - 2 * border);
+
+        for (int i=border; i<height-border; i++) {
+            for (int j=border; j<width-border; j++) {
+                double itest = test.getIntensity(i, j);
+                double iref = interpolate.Interpolate(testpix.getPixel(i, j));
+                int red = test.getRed(i, j);
+                int green = test.getGreen(i, j);
+                int blue = test.getBlue(i, j);
+                if (itest - iref > 50) {
+                    red = 255;
+                    green = 0;
+                    blue = 0;
+                }
+                if (iref - itest > 50) {
+                    red = 0;
+                    green = 255;
+                    blue = 0;
+                }
+                output.setPixel(i-border, j-border, red, green, blue);
+            }
+        }
+        String filename = "c:/CDMS/outputimage.bmp";
+        writer.WriteImage(output, filename);
+
+        ProcessImage process = new ProcessImage();
+        process.HistIntensity("Test Intensity", test);
+        process.HistIntensity("Reference Intensity", ref);
+        process.HistDeviations(border, testpix, test, refpix, ref);
+        process.CloseFile();
+
+        System.out.println("horiz offset: "+hoff+" vert offset: "+voff+" rot angle: "+rotang);
+    }
+}

CDMS/src/CDMS/Partridge
ImageIOTest.java added at 1.1
diff -N ImageIOTest.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ImageIOTest.java	28 Jul 2010 17:32:08 -0000	1.1
@@ -0,0 +1,53 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package CDMS.Partridge;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+
+import java.io.IOException;
+import javax.imageio.ImageIO;
+
+/**
+ *
+ * @author richp
+ */
+public class ImageIOTest {
+
+    public static void main(String[] args) throws IOException {
+
+        String dir = "c:/CDMS/IZipG47_Side1_Al/";
+        String fname = "IZipG47_Side1_Al-";
+        String oname = "IZipG47_Side1_Al-";
+        String itype = "BMP";
+        String otype = "png";
+
+        int first = 1;
+        int last = 8585;
+
+        for (int inum = first; inum <= last; inum++) {
+            BufferedImage image = ImageIO.read(new File(dir+fname+inum+"."+itype));
+
+            int onum = inum - first + 1;
+            File outfile = new File(dir+fname+inum+"."+otype);
+
+            ImageIO.write(image, otype, outfile);
+        }
+    }
+
+    private BufferedImage rotate(BufferedImage image) {
+
+        int width = image.getWidth();
+        int height = image.getHeight();
+        BufferedImage rotated = new BufferedImage(width, height, image.getType());
+        for (int row = 0; row < height; row++) {
+            for (int col = 0; col < width; col++) {
+                int pixel = image.getRGB(col, row);
+                rotated.setRGB(width - col - 1, height - row - 1, pixel);
+            }
+        }
+        return rotated;
+    }
+}

CDMS/src/CDMS/Partridge
ImageNavigator.java added at 1.1
diff -N ImageNavigator.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ImageNavigator.java	28 Jul 2010 17:32:08 -0000	1.1
@@ -0,0 +1,578 @@
+package CDMS.Partridge;
+
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StreamTokenizer;
+import java.util.ArrayList;
+import java.util.Formatter;
+import java.util.List;
+
+/**
+ * Create html files that allow easy navigation among detector images
+ *
+ * @author Richard Partridge
+ */
+public class ImageNavigator {
+
+    private static String imagefilesuffix = ".png";
+    private static String htmlfilesuffix = ".htm";
+    private static int[][] colorgrid = {{5, 5, 5, 4, 4, 4, 5, 5, 5},
+                                        {5, 5, 4, 3, 3, 3, 4, 5, 5},
+                                        {5, 4, 3, 2, 2, 2, 3, 4, 5},
+                                        {4, 3, 2, 1, 1, 1, 2, 3, 4},
+                                        {4, 3, 2, 1, 0, 1, 2, 3, 4},
+                                        {4, 3, 2, 1, 1, 1, 2, 3, 4},
+                                        {5, 4, 3, 2, 2, 2, 3, 4, 5},
+                                        {5, 5, 4, 3, 3, 3, 4, 5, 5},
+                                        {5, 5, 5, 4, 4, 4, 5, 5, 5}};
+    private static String[] colortable = {"red", "lightsalmon", "khaki", "lightgreen", "turquoise", "lightsteelblue"};
+
+    /**
+     * Main method for the ImageNavigator
+     *
+     * @param args the command line arguments (none currently)
+     * @throws IOException
+     */
+    public static void main(String[] args) throws IOException {
+
+        //  Process the image file(s)
+//        process("c:/CDMS/IZIPTestWaferBatch21_I11_TB/Autorun_IZipTestWaferBatch21_I11_TB_28Apr10.txt",
+//                "c:/CDMS/IZipTestWaferBatch21_I11_TB/", "IZipTestWaferBatch21_I11_TB-", 1,
+//                "IZip Test Wafer Batch 21 I11 TB", "28 April 2010");
+//        process("c:/CDMS/IZIPTestWaferBatch21_I14_TB/Autorun_IZipTestWaferBatch21_I14_TB_30Apr10.txt",
+//                "c:/CDMS/IZipTestWaferBatch21_I14_TB/", "IZipTestWaferBatch21_I14_TB-", 1,
+//                "IZip Test Wafer Batch 21 I14 TB", "30 April 2010");
+//        process("c:/CDMS/IZIPTestWaferBatch21_I11_TB_75x3/Autorun_IZipTestWaferBatch21_I11_TB_75x3_10May10.txt",
+//                "c:/CDMS/IZipTestWaferBatch21_I11_TB_75x3/",
+//                "IZipTestWaferBatch21_I11_TB_75x3-", 1, "IZip Test Wafer Batch 21 I11 TB", "10 May 2010");
+//        process("c:/CDMS/IZIPG18M_TB/Autorun_IZipG18M_TB_27Apr10.txt", "c:/CDMS/IZIPG18M_TB/",
+//                "IZipG18M_TB-", 8901, "IZip G18M TB", "27 April 2010");
+//        process("c:/CDMS/IZipG18M_LR/Autorun_IZipG18M_LR_26Apr10.txt", "c:/CDMS/IZipG18M_LR/",
+//                "IZipG18M_LR-",  316, "IZip G18M LR", "26 April 2010");
+//        process("c:/CDMS/IZIPG18M_TB_75x3/Autorun_IZipG18M_TB_75x3_11May10.txt",
+//                "c:/CDMS/IZIPG18M_TB_75x3/", "IZipG18M_TB_75x3-", 1, "IZip G18M TB x75.3",
+//                "11 May 2010");
+//        process("c:/CDMS/IZIPG18M_LR_75x3/Autorun_IZipG18M_LR_75x3_11May10.txt",
+//                "c:/CDMS/IZIPG18M_LR_75x3/", "IZipG18M_LR_75x3-", 1, "IZip G18M LR x75.3",
+//                "11 May 2010");
+        process("c:/CDMS/IZipG47_Side1_Al/Autorun_IZipG47_Side1_Al_23July10.txt",
+                "c:/CDMS/IZipG47_Side1_Al/", "IZipG47_Side1_Al-", 1, "IZip G47 Side 1 Al",
+                "23 July 2010");    }
+
+    /**
+     *
+     * @param autorunfile name of autorun file used to acquire images
+     * @param fileprefix prefix applicable to all image and html files
+     * @param firstimagenumber image number of first image
+     * @throws IOException
+     */
+    private static void process(String autorunfile, String htmlfiledir, String fileprefix,
+            int firstimagenumber, String detectorID, String date) throws IOException {
+
+        //  Open the autorun file and setup a StreamTokenizer for a comma delimited list
+        FileReader fr = new FileReader(autorunfile);
+        StreamTokenizer tok = new StreamTokenizer(fr);
+        tok.resetSyntax();
+        tok.wordChars(32, 126);
+        tok.parseNumbers();
+        tok.whitespaceChars(44, 44);
+        tok.whitespaceChars(0, 31);
+        tok.eolIsSignificant(true);
+
+        //  Initialize the autorun file information for each row
+        int nrows = 0;
+        List<Integer> nimages = new ArrayList<Integer>();
+        double dx = 0.;
+        double dy = 0.;
+        List<Double> xc = new ArrayList<Double>();
+        List<Double> yc = new ArrayList<Double>();
+
+        //  Loop over the autorun file entries
+        while (tok.nextToken() != tok.TT_EOF) {
+
+            //  Search for the next SET_PART_REPEAT command
+            if (tok.ttype != tok.TT_WORD) continue;
+            if (!tok.sval.equals("SET_PART_REPEAT")) continue;
+
+            //  Get the parameters for the SET_PART_REPEAT command and check that
+            //  we have the expected number of parameters (10)
+            List<Double> args = getNumbersInLine(tok);
+            if (args.size() != 10) throw new RuntimeException("Part Repeat command has "
+                    +args.size()+" fields, 10 expected");
+
+            //  Save the number of images in this row
+            nimages.add((int) Math.round(args.get(0))+1);
+
+            //  Make sure that we don't have multiple rows
+            if (args.get(1) != 0) throw new RuntimeException("Invalid Part Repeat command");
+
+            //  If this is the first row, save the spacing between columns
+            if (nrows == 0) {
+                dx = args.get(2) * 25.4;
+            } else {
+
+                //  Make sure that we maintain a constant column spacing
+                if (Math.abs(args.get(2) * 25.4 - dx) > 1.e-8) throw new RuntimeException("Variable column spacing");
+            }
+
+            //  Make sure that we move horizontally (dy = dz = 0) within a row
+            if (args.get(3) != 0) throw new RuntimeException("Invalid Part Repeat command");
+            if (args.get(4) != 0) throw new RuntimeException("Invalid Part Repeat command");
+
+            //  Check other parameters for correct settings
+            if (args.get(5) != 1) throw new RuntimeException("Invalid Part Repeat command");
+            if (args.get(6) != 0) throw new RuntimeException("Invalid Part Repeat command");
+            if (args.get(7) != 1) throw new RuntimeException("Invalid Part Repeat command");
+            if (args.get(8) != 1) throw new RuntimeException("Invalid Part Repeat command");
+            if (args.get(9) != 1) throw new RuntimeException("Invalid Part Repeat command");
+
+            //  The first token on the following line should be the part routine file name
+            //  This part routine takes a picture that is approximately centered on the
+            //  coordinates specified in the part routine command line
+            if (tok.nextToken() != tok.TT_WORD)
+                throw new RuntimeException("Expected a part routine");
+
+            //  Get the coordinates where the part routine is executed
+            args = getNumbersInLine(tok);
+
+            //  The first two coordinates specify the x and y locations
+            xc.add(args.get(0));
+            yc.add(args.get(1));
+
+            //  If this is the second row, calculate the row spacing between the first two rows
+            if (nrows == 1) dy = yc.get(1) - yc.get(0);
+
+            //  Check to make sure that additional rows maintain a constant row spacing
+            if (nrows > 1) {
+                if (Math.abs(yc.get(nrows) - yc.get(nrows-1) - dy) > 1.e-7)
+                    throw new RuntimeException("Variable row spacing");
+            }
+
+            //  Check that we take images at z = 0 with no coordinate system rotation
+            if (args.get(2) != 0) throw new RuntimeException("Invalid Part Routine coordinate");
+            if (args.get(3) != 0) throw new RuntimeException("Invalid Part Routine coordinate");
+            if (args.get(4) != 0) throw new RuntimeException("Invalid Part Routine coordinate");
+            if (args.get(5) != 0) throw new RuntimeException("Invalid Part Routine coordinate");
+
+            //  Increment the row counter
+            nrows++;
+        }
+
+        //  Find the minimum and maximum x coordinates
+        double xmin = 1.e10;
+        double xmax = -1.e10;
+        for (int i=0; i<nrows; i++) {
+
+            //  xfirst is the x coordinate of the first image in the row
+            double xfirst = xc.get(i);
+
+            //  xlast is the x coordinate of the last image in the row
+            double xlast = xfirst + (nimages.get(i)-1) * dx;
+
+            if (xfirst < xmin) xmin = xfirst;
+            if (xlast > xmax) xmax = xlast;
+        }
+
+        //  Find the number of columns required to hold the entire image
+        int ncols = (int) Math.round((xmax - xmin) / dx) + 1;
+
+        //  Create arrays with the image numbers and the image file names
+        Integer[][] inum = new Integer[nrows][ncols];
+        String[][] image = new String[nrows][ncols];
+
+        //  Loop over the images, which are numbered sequentially starting
+        // at the first column of the first row, incrementing for each
+        // successive column in the row before the row number is incremented
+        int imagenum = firstimagenumber;
+        for (int irow=0; irow<nrows; irow++) {
+
+            //  Get the column number in the image array for the first image of this row
+            int firstcol = (int) Math.round((xc.get(irow) - xmin) / dx);
+
+            //  Loop over the images in this row
+            for (int icol=firstcol; icol<firstcol + nimages.get(irow); icol++) {
+
+                //  Save the image number and the image file name
+                inum[irow][icol] = imagenum;
+                image[irow][icol] = fileprefix+inum[irow][icol].toString()+imagefilesuffix;
+
+                //  Increment the image number
+                imagenum++;
+            }
+        }
+
+        //  Create arrays of html page numbers and file names
+        //  Since each page has a 2x2 array of images, we will have one more
+        //  row and column of pages than there are images
+        String[][] page = new String[nrows+1][ncols+1];
+
+        //  Loop over the rows and columns of the pages
+        int pagenum = 0;
+        for (int irow = 0; irow<nrows+1; irow++) {
+            for (int icol=0; icol<ncols+1; icol++) {
+
+                //  The row and column indexices reference the lower right (LR)
+                //  image on the page.  Check to see if we have at least one
+                //  image on the page
+                if (getString(irow-1, icol-1, image) != null ||     // UL image
+                        getString(irow, icol-1, image) != null ||   // LL image
+                        getString(irow-1, icol, image) != null ||   // UR image
+                        getString(irow, icol, image) != null) {     // LR image
+
+                    //  If we have >0 images, we will create an html page.  Assign
+                    //  a number to the page and then increment the page number
+                    page[irow][icol] = fileprefix+pagenum+htmlfilesuffix;
+                    pagenum++;
+                } else {
+
+                    //  If there aren't any images, set the page number negative
+                    page[irow][icol] = null;
+                }
+            }
+        }
+
+        //  Create the html pages
+        for (int irow = 0; irow<nrows+1; irow++) {
+            for (int icol=0; icol<ncols+1; icol++) {
+
+                //  Get the file name for this page - skip those with no images
+                String pfile = page[irow][icol];
+                if (pfile == null) continue;
+
+                //  Create a PrintWriter to handle writing the file
+                FileWriter fw = new FileWriter(htmlfiledir+pfile, false);
+                PrintWriter pw = new PrintWriter(fw);
+
+                //  Create the preamble material (doctype and header)
+                pw.println("<!doctype html public \"-//w3c//dtd html 4.01 transitional//en\">");
+                pw.println("<html>");
+                pw.println("<head> <title> CDMS Detector Image Navigator</title> </head>");
+
+                //  Start the body and table containing all info on this page
+                pw.println("<body bgcolor=\"silver\">");
+                pw.println("<table cellspacing=\"0\" border=\"0\" cellpadding=\"0\" >");
+
+                //  First table row has navigation links
+                pw.println("<tr>");
+
+                //  Link to NW page if it exists
+                String fn = getString(irow-1, icol-1, page);
+                 if (fn != null) {
+                    pw.println("<td align=\"center\"> <a href=\""+fn+"\"> NW </a> </td>");
+                } else {
+                    pw.println("<td> </td>");
+                }
+
+                //  Link to N page if it exists
+                fn = getString(irow-1, icol, page);
+                 if (fn != null) {
+                    pw.println("<td align=\"center\"> <a href=\""+fn+"\"> N </a> </td>");
+                } else {
+                    pw.println("<td> </td>");
+                }
+
+                //  Link to NE page if it exists
+                fn = getString(irow-1, icol+1, page);
+                 if (fn != null) {
+                    pw.println("<td align=\"center\"> <a href=\""+fn+"\"> NE </a> </td>");
+                } else {
+                    pw.println("<td> </td>");
+                }
+
+                //  Put empty cell in 4th column finish row
+                pw.println("<td> </td>");
+                pw.println("</tr>");
+
+                //  Second table row has navigation links, images, and info
+                pw.println("<tr>");
+
+                //  Link to W page if it exists
+                fn = getString(irow, icol-1, page);
+                 if (fn != null) {
+                    pw.println("<td align=\"center\"> <a href=\""+fn+"\"> W </a> </td>");
+                } else {
+                    pw.println("<td> </td>");
+                }
+
+                //  Put in a "sub-table" of images into this cell
+                pw.println("<td align=\"center\">");
+                pw.println("<table cellspacing=\"0\" border=\"0\" cellpadding=\"2\">");
+
+                //  First row of subtable has UL and UR images
+                pw.println("<tr>");
+
+                //  Link to UL image if it exists
+                fn = getString(irow-1, icol-1, image);
+                if (fn != null) {
+                    pw.println("<td align=\"center\"> <img src=\""+fn+"\"> </td>");
+                } else {
+                    pw.println("<td> </td>");
+                }
+
+                //  Link to UR image if it exists
+                fn = getString(irow-1, icol, image);
+                if (fn != null) {
+                    pw.println("<td align=\"center\"> <img src=\""+fn+"\"> </td>");
+                } else {
+                    pw.println("<td> </td>");
+                }
+
+                //  Finish row 1 of subtable
+                pw.println("</tr>");
+
+                //  Second row has LL and LR images
+                pw.println("<tr>");
+
+                //  Link to LL image if it exists
+                fn = getString(irow, icol-1, image);
+                if (fn != null) {
+                    pw.println("<td align=\"center\"> <img src=\""+fn+"\"> </td>");
+                } else {
+                    pw.println("<td> </td>");
+                }
+
+                //  Link to LR image if it exists
+                fn = getString(irow, icol, image);
+                if (fn != null) {
+                    pw.println("<td align=\"center\"> <img src=\""+fn+"\"> </td>");
+                } else {
+                    pw.println("<td> </td>");
+                }
+
+                //  Finish subtable and cell
+                pw.println("</tr>");
+                pw.println("</table>");
+                pw.println("</td>");
+
+                //  Link to E page if it exists
+                fn = getString(irow, icol+1, page);
+                 if (fn != null) {
+                    pw.println("<td align=\"center\"> <a href=\""+fn+"\"> E </a> </td>");
+                } else {
+                    pw.println("<td> </td>");
+                }
+
+                //  Put in a "sub-table" of page information and navigation map into this cell
+                pw.println("<td align=\"center\">");
+                pw.println("<table cellspacing=\"0\" border=\"0\" cellpadding=\"5\">");
+
+                //  First row of subtable has page information
+                pw.println("<tr>");
+                pw.println("<td align=\"center\">");
+                pw.println("<p><h2> CDMS Image Navigator </h2>");
+                pw.println("<p> Detector "+detectorID);
+                pw.println("<p> Imaging Date: "+date);
+                pw.println("<p><h3> Current View </h3>");
+
+                //  Find the range of rows and columns on the page
+                int irowmin = 9999;
+                int irowmax = -9999;
+                int icolmin = 9999;
+                int icolmax = -9999;
+                for (int ir=irow-1; ir<irow+1; ir++) {
+                    for (int ic=icol-1; ic<icol+1; ic++) {
+                        if (getString(ir, ic, image) != null) {
+                            if (ir < irowmin) irowmin = ir;
+                            if (ir > irowmax) irowmax = ir;
+                            if (ic < icolmin) icolmin = ic;
+                            if (ic > icolmax) icolmax = ic;
+                        }
+                    }
+                }
+
+                //  Write out the row and column indices
+                pw.println("<p> Rows:  "+irowmin+" - "+irowmax);
+                pw.println("<p> Columns:  "+icolmin+" - "+icolmax);
+
+                //  Write out the image numbers
+                if (getString(irow-1, icol-1, image) != null)
+                    pw.println("<p> UL Image "+inum[irow-1][icol-1]);
+                if (getString(irow-1, icol, image) != null)
+                    pw.println("<p> UR Image "+inum[irow-1][icol]);
+                if (getString(irow, icol-1, image) != null)
+                    pw.println("<p> LL Image "+inum[irow][icol-1]);
+                if (getString(irow, icol, image) != null)
+                    pw.println("<p> LR Image "+inum[irow][icol]);
+
+                //  Write out the coordinates of the image center
+                Formatter fmt = new Formatter();
+                double x = xmin + 0.5 * (icolmin + icolmax) * dx;
+                double y = yc.get(0) + 0.5 * (irowmin +irowmax) * dy;
+                double r = Math.sqrt(x*x + y*y);
+                double phi = 180. * Math.atan2(y, x) / Math.PI;
+                pw.println("<p><h3>Center Coordinates</h3>");
+                fmt.format("<p> x: %.3f mm", x);
+                fmt.format("<p> y: %.3f mm", y);
+                fmt.format("<p> r: %.3f mm", r);
+                fmt.format("<p> phi: %.3f&deg;",phi);
+                pw.println(fmt);
+
+                //  Finish row 1 of information subtable
+                pw.println("</td>");
+                pw.println("</tr>");
+
+                //  Second row of information has a navigation table
+                pw.println("<tr>");
+                pw.println("<td align=\"center\">");
+                pw.println("<p><h3> Sector Navigator </h3><p>");
+                pw.println("<table cellspacing=\"0\" border=\"0\" cellpadding=\"0\">");
+
+                //  Find which sector this page belongs
+                int ix0 = (int) Math.round(9. * irow / (nrows + 1) - 0.5);
+                int iy0 = (int) Math.round(9. * icol / (ncols + 1) - 0.5);
+
+                //  Make sure sector number is valid - first/last row/col are on the edge
+                if (ix0 < 0) ix0 = 0;
+                if (ix0 > 8) ix0 = 8;
+                if (iy0 < 0) iy0 = 0;
+                if (iy0 > 8) iy0 = 8;
+
+                //  Loop over a 9x9 sector grid and link sectors to the nearest page
+                int sector = 0;
+                for (int ix=0; ix<9; ix++) {
+
+                    //  Find the image row closest to this sector row and start a table row
+                    int sectorrow = (int) Math.round((nrows + 1) * (ix + 0.5) / 9.);
+                     pw.println("<tr>");
+
+                    //  Loop over the sector columns and find the nearest image column
+                    for (int iy=0; iy<9; iy++) {
+                        int sectorcol = (int) Math.round((ncols + 1) * (iy + 0.5) / 9.);
+
+                        //  If there is a corresponding html page, link to it and update the sector count
+                        fn = getString(sectorrow, sectorcol, page);
+                        if (fn != null) {
+                            String color = colortable[colorgrid[ix][iy]];
+                            if (ix == ix0 && iy == iy0) color = "black";
+                            pw.println("<td align=\"center\" bgcolor=\""+color+"\"> <a href=\""+fn+"\"> "+sector+"</a> </td>");
+                            sector++;
+                        } else {
+                            pw.println("<td> </td>");
+                        }
+                    }
+
+                    //  End the table row
+                    pw.println("</tr>");
+                }
+
+                //  Finish up the navigation table
+                pw.println("<tr> </tr>");
+                pw.println("</td>");
+                pw.println("</table>");
+
+                //  Finish up the information/navigation table
+                pw.println("</td>");
+                pw.println("<tr> <td align=\"center\"> Current Sector is Black </td> </tr>");
+                pw.println("</table>");
+
+                //  Finish the 2nd row
+                pw.println("</td>");
+                pw.println("</tr>");
+
+                //  Last table row has navigation links
+                pw.println("<tr>");
+
+                //  Link to SW page if it exists
+                fn = getString(irow+1, icol-1, page);
+                 if (fn != null) {
+                    pw.println("<td align=\"center\"> <a href=\""+fn+"\"> SW </a> </td>");
+                } else {
+                    pw.println("<td> </td>");
+                }
+
+                //  Link to S page if it exists
+                fn = getString(irow+1, icol, page);
+                 if (fn != null) {
+                    pw.println("<td align=\"center\"> <a href=\""+fn+"\"> S </a> </td>");
+                } else {
+                    pw.println("<td> </td>");
+                }
+
+                //  Link to SE page if it exists
+                fn = getString(irow+1, icol+1, page);
+                 if (fn != null) {
+                    pw.println("<td align=\"center\"> <a href=\""+fn+"\"> SE </a> </td>");
+                } else {
+                    pw.println("<td> </td>");
+                }
+
+                //  Put empty cell in 4th column finish row, table
+                pw.println("<td> </td>");
+                pw.println("</tr>");
+                pw.println("</table>");
+
+                //  Finish up
+                pw.println("</body>");
+                pw.println("</html>");
+                pw.close();
+            }
+        }
+    }
+
+    /**
+     * Get a list of numbers in a line on the input stream
+     *
+     * @param tok StreamTokenizer with the next token being the first number
+     * @return List of numbers in the current line
+     * @throws IOException
+     */
+    @SuppressWarnings("static-access")
+    private static List<Double> getNumbersInLine(StreamTokenizer tok) throws IOException {
+
+        //  Create a list of numbers that the tokenizer finds
+        List<Double> nums = new ArrayList<Double>();
+
+        //  Loop looking for either end of line or end of file
+        while (tok.nextToken() != tok.TT_EOF) {
+            if (tok.ttype == tok.TT_EOL) {
+                break;
+            }
+
+            //  Check to make sure that we only get numeric tokens
+            if (tok.ttype != tok.TT_NUMBER) {
+                continue;
+//                throw new RuntimeException("Non numeric data encountered");
+            }
+
+            //  Found a number token - add it to the list
+//          System.out.println("value: "+tok.nval);
+            nums.add(tok.nval);
+        }
+        return nums;
+    }
+
+    /**
+     * Check to see if we have a valid row/col index for a given String array
+     *
+     * @param row row number
+     * @param col column number
+     * @param array double indexed String array A[row][col]
+     * @return true if we have a valid index
+     */
+    private static boolean CheckIndex(int row, int col, String[][] array) {
+
+        //  Check row and column to see if we have valid indices
+        if (row < 0) return false;
+        if (row >= array.length) return false;
+        if (col < 0) return false;
+        if (col >= array[row].length) return false;
+        return true;
+    }
+
+    /**
+     * Retrieve the specified string after checking for a valid index
+     *
+     * @param row row number
+     * @param col column number
+     * @param array double indexed String array A[row][col]
+     * @return specified string
+     */
+    private static String getString(int row, int col, String[][] array) {
+
+        //  Return null if we don't have a valid index, otherwise return the string
+        if (!CheckIndex(row, col, array)) return null;
+        return array[row][col];
+    }
+}

CDMS/src/CDMS/Partridge
InterpolatePixelIntensity.java added at 1.1
diff -N InterpolatePixelIntensity.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ InterpolatePixelIntensity.java	28 Jul 2010 17:32:08 -0000	1.1
@@ -0,0 +1,184 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package CDMS.Partridge;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author richp
+ */
+public class InterpolatePixelIntensity {
+
+    private Image _ref;
+    private PixelArray _refpix;
+    private PixelArray _testpix;
+    private double _eps = 1.e-12;
+
+    public InterpolatePixelIntensity(Image ref, PixelArray refpix, PixelArray testpix) {
+        _ref = ref;
+        _refpix = refpix;
+        _testpix = testpix;
+    }
+
+    public double Interpolate(int pixel) {
+
+        //  Find the center of the current test pixel
+        double[] testcenter = _testpix.getCenter(pixel);
+
+        //  Find the reference pixel containing the center of the test pixel
+        int refcenter = _refpix.getPixel(testcenter[0], testcenter[1]);
+
+        //  Get the list of reference pixels to check for overlaps
+        List<Integer> refnbrs = _refpix.getNeighbors(refcenter);
+
+        //  Initialize the pixel area and weighted intensity sums
+        double totarea = 0.;
+        double intensity = 0.;
+
+        //  Loop over the list of reference pixels
+        for (Integer nbr : refnbrs) {
+
+            //  Create a list for vertices of the overlap region between this ref pixel and the test pixel
+            List<double[]> vertices = new ArrayList<double[]>();
+
+            //  Loop over the reference pixel vertices and see if the reference vertex
+            //  is inside the test pixel.  If so add it to the list of vertices (don't
+            //  worry about duplicate vertices - they contribute no additional polygon area
+            for (int i = 0; i < 4; i++) {
+                double[] vtx = _refpix.getVertex(i, nbr);
+                if (_testpix.Inside(pixel, vtx)) vertices.add(vtx);
+            }
+
+            //  Now loop over the test pixel vertices
+            for (int i = 0; i < 4; i++) {
+                double[] vtx = _testpix.getVertex(i, pixel);
+                if (_refpix.Inside(nbr, vtx)) vertices.add(vtx);
+            }
+
+            //  Finally, find any vertices produced by intersections of pixel edges
+            for (int i1=0; i1<4; i1++) {
+                int i2 = (i1 + 1) % 4;
+                double[] vt1 = _testpix.getVertex(i1, pixel);
+                double[] vt2 = _testpix.getVertex(i2, pixel);
+                for (int j1=0; j1<4; j1++) {
+                    int j2 = (j1 + 1) % 4;
+                    double[] vr1 = _refpix.getVertex(j1, nbr);
+                    double[] vr2 = _refpix.getVertex(j2, nbr);
+                    double[] vtx = findIntersection(vt1, vt2, vr1, vr2);
+                    if (vtx != null) vertices.add(vtx);
+                }
+            }
+
+            //  If there are no vertices, the test pixel and this reference pixel don't overlap
+            if (vertices.size() == 0) continue;
+
+            //  Find the area of overlap between the test pixel and this reference neighbor pixel
+            double area = getArea(vertices);
+            totarea += area;
+
+            //  Take the interpolated intensity to be the sum of the reference neighbor intensities
+            //  weighted by the overlap area
+            int refrow = _refpix.getRow(nbr);
+            int refcol = _refpix.getCol(nbr);
+            intensity += area * _ref.getIntensity(refrow, refcol);
+        }
+
+        //  Check to make sure the total pixel area is unity
+        if (Math.abs(totarea - 1.) > Math.sqrt(_eps)) {
+            System.out.println(" ***** Grand total area: "+totarea+" *****");
+            throw new RuntimeException("area sum error");
+        }
+
+        return intensity;
+    }
+
+    private double[] findIntersection(double[] vt1, double[] vt2, double[] vr1, double[] vr2) {
+
+        //  Find the variables defining the line between vt1 and vt2
+        double a1 = vt2[1] - vt1[1];
+        double b1 = vt1[0] - vt2[0];
+        double c1 = a1 * vt1[0] + b1 * vt1[1];
+
+        //  Find the variables defining the line between vr1 and vr2
+        double a2 = vr2[1] - vr1[1];
+        double b2 = vr1[0] - vr2[0];
+        double c2 = a2 * vr1[0] + b2 * vr1[1];
+
+        //  Calculate the determinant, check for parallel lines
+        double det = a1 * b2 - a2 * b1;
+        if (Math.abs(det) < _eps) return null;
+
+        //  Find the intersection using the determinant method
+        double x = (b2 * c1 - b1 * c2) / det;
+        double y = (a1 * c2 - a2 * c1) / det;
+
+        //  Check that the x coordinate of the intersection is on the line segment
+        if (x < Math.min(vt1[0], vt2[0]) - _eps || x > Math.max(vt1[0], vt2[0]) + _eps) return null;
+        if (x < Math.min(vr1[0], vr2[0]) - _eps || x > Math.max(vr1[0], vr2[0]) + _eps) return null;
+
+        //  Also check y in case the line is vertical
+        if (y < Math.min(vt1[1], vt2[1]) - _eps || y > Math.max(vt1[1], vt2[1]) + _eps) return null;
+        if (y < Math.min(vr1[1], vr2[1]) - _eps || y > Math.max(vr1[1], vr2[1]) + _eps) return null;
+
+        double[] cross = {x, y};
+        return cross;
+    }
+
+    private double getArea(List<double[]> polygon) {
+
+        //  Check that we have at least 3 polygon vertices
+        int nv = polygon.size();
+        if (nv < 3) return 0.;
+
+        //  Order the vertices so that adjacent vertices describe a line segment in the
+        //  polygon
+        OrderVertices(polygon);
+
+        //  Find the area of the polygon (see, for example, http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/)
+        double area = 0.;
+        for (int i = 0; i < nv; i++) {
+            int j = (i + 1) % nv;
+            double[] p0 = polygon.get(i);
+            double[] p1 = polygon.get(j);
+            double darea = 0.5 * (p0[0] * p1[1] - p1[0] * p0[1]);
+            area += darea;
+        }
+        return Math.abs(area);
+    }
+
+    private double[] PseudoCentroid(List<double[]> polygon) {
+
+        // Find a point within the convex polygon by averaging the coordinates of all vertices
+        double[] pcent = {0., 0.};
+        int nv = polygon.size();
+        for (double[] point : polygon) {
+            pcent[0] += point[0] / nv;
+            pcent[1] += point[1] / nv;
+        }
+        return pcent;
+    }
+
+    private void OrderVertices(List<double[]> polygon) {
+
+        //  Take as an origin a point within the polygon and order the polygon vertices according to their azimuthal angle
+        double[] pcent = PseudoCentroid(polygon);
+        int nv = polygon.size();
+        for (int i = 0; i < nv - 1; i++) {
+            for (int j = i + 1; j < nv; j++) {
+                //  phi1 calcuation must stay inside loop because of possible re-ordering
+                double phi1 = Math.atan2(polygon.get(i)[1] - pcent[1], polygon.get(i)[0] - pcent[0]);
+                double phi2 = Math.atan2(polygon.get(j)[1] - pcent[1], polygon.get(j)[0] - pcent[0]);
+                if (phi1 > phi2) {
+                    double[] temp = polygon.get(j);
+                    polygon.set(j, polygon.get(i));
+                    polygon.set(i, temp);
+                }
+            }
+        }
+    }
+}

CDMS/src/CDMS/Partridge
PixelArray.java added at 1.1
diff -N PixelArray.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ PixelArray.java	28 Jul 2010 17:32:08 -0000	1.1
@@ -0,0 +1,146 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package CDMS.Partridge;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author richp
+ */
+public class PixelArray {
+
+    private double _x0;
+    private double _y0;
+    private double _rotang;
+    private double _size;
+    private int _nx;
+    private int _ny;
+    private double _xc;
+    private double _yc;
+    private double _u[] = new double[2];
+    private double _v[] = new double[2];
+    private double[] _xv = new double[4];
+    private double[] _yv = new double[4];
+
+    public PixelArray(double x0, double y0, double rotang, double size, int nx, int ny) {
+
+        //  Save the parameters that define the pixel array
+        _x0 = x0;
+        _y0 = y0;
+        _rotang = rotang;
+        _size = size;
+        _nx = nx;
+        _ny = ny;
+
+        //  Get unit vectors along the col (u) and row (v) directions
+        double cphi = Math.cos(rotang);
+        double sphi = Math.sin(rotang);
+        _u[0] = cphi;
+        _u[1] = sphi;
+        _v[0] = -sphi;
+        _v[1] = cphi;
+
+        //  Find the coordinates of the LL pixel given offsets x0, y0 specified for
+        //  the center pixel
+        double xll = _x0 + 0.5 * _size * (_nx * (1 - _u[0]) - _ny * _v[0]);
+        double yll = _y0 + 0.5 * _size * (_ny * (1 - _v[1]) - _nx * _u[1]);
+
+        //  Find the vertices of pixel 0 whose LL corner is at the origin
+        //  Vertices are stored in a clockwise direction
+        _xv[0] = xll;
+        _yv[0] = yll;
+        _xv[1] = xll + _size * _v[0];
+        _yv[1] = yll + _size * _v[1];
+        _xv[2] = xll + _size * (_u[0] + _v[0]);
+        _yv[2] = yll + _size * (_u[1] + _v[1]);
+        _xv[3] = xll + _size * _u[0];
+        _yv[3] = yll + _size * _u[1];
+
+        //  Find the center
+        _xc = (_xv[0] + _xv[2]) / 2.;
+        _yc = (_yv[0] + _yv[2]) / 2.;
+    }
+
+    public double[] getCenter(int pixel) {
+        int row = getRow(pixel);
+        int col = getCol(pixel);
+        double[] center = new double[2];
+        center[0] = _xc + _size * (col * _u[0] + row * _v[0]);
+        center[1] = _yc + _size * (col * _u[1] + row * _v[1]);
+        return center;
+    }
+
+    public boolean Inside(int pixel, double[] vtx0) {
+        for (int i=0; i<4; i++) {
+            int j = (i+1) % 4;
+            double[] vtx1 = getVertex(i, pixel);
+            double[] vtx2 = getVertex(j, pixel);
+            if (twicearea(vtx1[0], vtx1[1], vtx2[0], vtx2[1], vtx0[0], vtx0[1]) < 0.) return false;
+        }
+        return true;
+    }
+
+    public double[] getVertex(int ivtx, int pixel) {
+        int row = getRow(pixel);
+        int col = getCol(pixel);
+        double[] vtx = new double[2];
+        vtx[0] = _xv[ivtx] + _size * (col * _u[0] + row * _v[0]);
+        vtx[1] = _yv[ivtx] + _size * (col * _u[1] + row * _v[1]);
+        return vtx;
+    }
+
+    public int getRow(int pixel) {
+        int row = pixel / _nx;
+        if (row < 0 || row >= _ny) throw new RuntimeException("Invalid pixel number");
+        return row;
+    }
+
+    public int getCol(int pixel) {
+        int col = pixel % _nx;
+        if (col < 0 || col >= _nx) throw new RuntimeException("Invalid pixel number");
+        return col;
+    }
+
+    public int getPixel(int row, int col) {
+        if (row < 0 || row >= _ny) throw new RuntimeException("Invalid row number");
+        if (col < 0 || col >= _nx) throw new RuntimeException("Invalid col number");
+        return row * _nx + col;
+    }
+
+    public int getPixel(double x, double y) {
+        int col = (int) Math.round(((x-_xc)*_u[0] + (y-_yc)*_u[1]) / _size);
+        int row = (int) Math.round(((x-_xc)*_v[0] + (y-_yc)*_v[1]) / _size);
+        return getPixel(row, col);
+    }
+
+    public int getNRow() {
+        return _ny;
+    }
+
+    public int getNCol() {
+        return _nx;
+    }
+
+    public List<Integer> getNeighbors(int pixel) {
+        List<Integer> nbrs = new ArrayList<Integer>();
+        int row = getRow(pixel);
+        int col = getCol(pixel);
+        for (int irow=row-1; irow<row+2; irow++) {
+            if (irow < 0 || irow >= _ny) continue;
+            for (int icol=col-1; icol<col+2; icol++) {
+                if (icol < 0 || icol > _nx) continue;
+                nbrs.add(getPixel(irow, icol));
+            }
+        }
+        return nbrs;
+    }
+
+    private double twicearea(double x1, double y1, double x2, double y2, double x3, double y3) {
+        return (x3*y2 - x2*y3) - (x3*y1 - x1*y3) + (x2*y1 - x1*y2);
+    }
+}

CDMS/src/CDMS/Partridge
ProcessImage.java added at 1.1
diff -N ProcessImage.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ProcessImage.java	28 Jul 2010 17:32:08 -0000	1.1
@@ -0,0 +1,48 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package CDMS.Partridge;
+
+import java.io.IOException;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author richp
+ */
+public class ProcessImage {
+
+    private AIDA aida = AIDA.defaultInstance();
+
+    public ProcessImage() {
+    }
+
+    public void HistDeviations(int border, PixelArray testpix, Image test, PixelArray refpix, Image ref) {
+        InterpolatePixelIntensity interpolate = new InterpolatePixelIntensity(ref, refpix, testpix);
+        int height = test.getHeight();
+        int width = test.getWidth();
+        for (int i=border; i<height-border; i++) {
+            for (int j=border; j<width-border; j++) {
+                double itest = test.getIntensity(i, j);
+                double iref = interpolate.Interpolate(testpix.getPixel(i, j));
+                aida.histogram1D("Intensity Difference", 340, -170., 170.).fill(itest-iref);
+                aida.histogram2D("itest vs iref", 170, 0., 170., 170, 0., 170.).fill((itest), iref);
+            }
+        }
+    }
+
+    public void HistIntensity(String title, Image image) throws IOException {
+        for (int i=0; i<image.getHeight(); i++) {
+            for (int j=1; j<image.getWidth(); j++) {
+                double intensity = image.getIntensity(i, j);
+                aida.histogram1D(title, 170, 0., 170.).fill(intensity);
+            }
+        }
+    }
+
+    public void CloseFile() throws IOException {
+        aida.saveAs("c:/CDMS/intensity.aida");
+    }
+}
\ No newline at end of file

CDMS/src/CDMS/Partridge
ReadBMP.java added at 1.1
diff -N ReadBMP.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ReadBMP.java	28 Jul 2010 17:32:08 -0000	1.1
@@ -0,0 +1,82 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package CDMS.Partridge;
+
+import java.io.BufferedInputStream;
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ *
+ * @author richp
+ */
+public class ReadBMP {
+
+    public ReadBMP() {
+    }
+
+    public Image ReadImage(String file) {
+
+        Image image;
+
+        try {
+            DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
+
+            int magicnumber = getShort(in);
+            if (magicnumber != 19778)
+                throw new RuntimeException("This is not a BMP file - magic number = "+magicnumber);
+            int filesize = getInt(in);
+            int reserved1 = getShort(in);
+            int reserved2 = getShort(in);
+            int imageOffset = getInt(in);
+            int headerLength = getInt(in);
+            if (headerLength != 40) throw new RuntimeException("Unsupported header length: "+headerLength);
+            int imageWidth = getInt(in);
+            int imageHeight = getInt(in);
+            int nplane = getShort(in);
+            int pixelDepth = getShort(in);
+            int compressionType = getInt(in);
+            int imageSize = getInt(in);
+            int horres = getInt(in);
+            int vertres = getInt(in);
+            int npalate = getInt(in);
+            int nused = getInt(in);
+
+            System.out.println("Image width: " + imageWidth + " image height: " + imageHeight);
+            image = new Image(imageWidth, imageHeight);
+
+            for (int row = 0; row < imageHeight; row++) {
+                for (int col = 0; col < imageWidth; col++) {
+                    int blue = in.readUnsignedByte();
+                    int green = in.readUnsignedByte();
+                    int red = in.readUnsignedByte();
+                    int fill = in.readUnsignedByte();
+                    image.setPixel(row, col, red, green, blue);
+                }
+            }
+
+        } catch(IOException e)  {
+            System.out.println(e.toString());
+            return null;
+        }
+
+        return image;
+    }
+
+    private short getShort(DataInputStream in) throws IOException {
+        int low = in.readUnsignedByte();
+        int high = in.readUnsignedByte();
+        int value = low + 256 * high;
+        return (short) value;
+    }
+
+    private int getInt(DataInputStream in) throws IOException {
+        int low = getShort(in);
+        int high = getShort(in);
+        long value = low + 256*256 * high;
+        return (int) value;
+    }
+}
\ No newline at end of file

CDMS/src/CDMS/Partridge
ReadTGA.java added at 1.1
diff -N ReadTGA.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ReadTGA.java	28 Jul 2010 17:32:08 -0000	1.1
@@ -0,0 +1,87 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package CDMS.Partridge;
+
+import java.io.BufferedInputStream;
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ *
+ * @author richp
+ */
+public class ReadTGA {
+
+    public ReadTGA() {
+    }
+
+    public Image ReadImage(String file) {
+
+        Image image;
+
+        try {
+            DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
+
+            int imageIDLen = in.readUnsignedByte();
+            int colormapType = in.readUnsignedByte();
+            int imageType = in.readUnsignedByte();
+            if (imageType != 2) {
+                throw new RuntimeException("Unsupported image type: " + imageType);
+            }
+            int colormapStartingIndex = getShort(in);
+            int colormapLength = getShort(in);
+            int colormapEntrySize = in.readUnsignedByte();
+            int imageOrigin_x = getShort(in);
+            int imageOrigin_y = getShort(in);
+            int imageWidth = getShort(in);
+            int imageHeight = getShort(in);
+            int pixelDepth = in.readUnsignedByte();
+            int imageDescriptor = in.readUnsignedByte();
+
+            int[] imageID;
+            if (imageIDLen > 0) {
+                imageID = new int[imageIDLen];
+                for (int i = 0; i < imageIDLen; i++) {
+                    imageID[i] = in.readUnsignedByte();
+                }
+            }
+
+            int colormapSize = colormapLength * colormapEntrySize / 8;
+            int[] colormap;
+            if (colormapSize > 0) {
+                colormap = new int[colormapSize];
+                for (int i = 0; i < colormapSize; i++) {
+                    colormap[i] = in.readUnsignedByte();
+                }
+            }
+
+            System.out.println("Image width: " + imageWidth + " image height: " + imageHeight);
+            image = new Image(imageWidth, imageHeight);
+
+            for (int row = 0; row < imageHeight; row++) {
+                for (int col = 0; col < imageWidth; col++) {
+                    int red = in.readUnsignedByte();
+                    int green = in.readUnsignedByte();
+                    int blue = in.readUnsignedByte();
+                    image.setPixel(row, col, red, green, blue);
+                }
+            }
+
+        } catch(IOException e)  {
+            System.out.println(e.toString());
+            return null;
+        }
+
+        return image;
+    }
+
+    private static short getShort(DataInputStream in) throws IOException {
+        int low = in.readUnsignedByte();
+        int high = in.readUnsignedByte();
+        int value = low + 256 * high;
+        return (short) value;
+    }
+}
\ No newline at end of file

CDMS/src/CDMS/Partridge
WriteBMP.java added at 1.1
diff -N WriteBMP.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ WriteBMP.java	28 Jul 2010 17:32:08 -0000	1.1
@@ -0,0 +1,91 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package CDMS.Partridge;
+
+import java.io.BufferedOutputStream;
+import java.io.DataOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ *
+ * @author richp
+ */
+public class WriteBMP {
+
+    public WriteBMP() {
+    }
+
+    public void WriteImage(Image image, String file) {
+
+        try {
+            DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
+
+            int imageWidth = image.getWidth();
+            int imageHeight = image.getHeight();
+            int headerLength = 40;
+            int imageOffset = headerLength + 14;
+            int imageSize = 4 * imageWidth * imageHeight;
+            int filesize = imageOffset + imageSize;
+            int magicnumber = 19778;
+            int reserved = 0;
+            int nplane = 1;
+            int pixelDepth = 32;
+            int compressionType = 0;
+            int horres = 3780;
+            int vertres = 3780;
+            int npalate = 0;
+            int nused = 0;
+
+            putShort(out, magicnumber);
+            putInt(out, filesize);
+            putShort(out, reserved);
+            putShort(out, reserved);
+            putInt(out, imageOffset);
+            putInt(out, headerLength);
+            putInt(out, imageWidth);
+            putInt(out, imageHeight);
+            putShort(out, nplane);
+            putShort(out, pixelDepth);
+            putInt(out, compressionType);
+            putInt(out, imageSize);
+            putInt(out, horres);
+            putInt(out, vertres);
+            putInt(out, npalate);
+            putInt(out, nused);
+
+            byte[] pixel = new byte[4];
+            for (int row = 0; row < imageHeight; row++) {
+                for (int col = 0; col < imageWidth; col++) {
+                    pixel[0] = (byte) image.getBlue(row, col);
+                    pixel[1] = (byte) image.getGreen(row, col);
+                    pixel[2] = (byte) image.getRed(row, col);
+                    pixel[3] = -1;
+                    out.write(pixel);
+                }
+            }
+
+            out.close();
+
+        } catch (IOException e) {
+            System.out.println(e.toString());
+            return;
+        }
+    }
+
+    private void putShort(DataOutputStream out, int value) throws IOException {
+        byte[] data = new byte[2];
+        data[0] = (byte)((value % 256) & 255);
+        data[1] = (byte) ((value / 256) & 255);
+        out.write(data);
+    }
+
+    private void putInt(DataOutputStream out, int value) throws IOException {
+        int low = (value % 65536) & 65535 ;
+        int hi = (value / 65536) & 65535;
+        putShort(out, low);
+        putShort(out, hi);
+    }
+}
CVSspam 0.2.8