// // ImporterTest.java // package loci.plugins.in; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import ij.CompositeImage; import ij.ImagePlus; import ij.ImageStack; import ij.process.ImageProcessor; import ij.process.LUT; import java.awt.Color; import java.awt.image.IndexColorModel; import java.io.IOException; import java.lang.reflect.Field; import loci.common.Location; import loci.common.Region; import loci.formats.FormatException; import loci.formats.FormatTools; import loci.plugins.BF; import org.junit.Test; // TODO // left off // should be able to make colorTests() handle both ImagePluses and CompositeImages. Change lutTest() too. Then can get // rid of ImagePlusLutTest(). // the color test methods seem to fail for indexed data (my issue - need to fix indexValuesTest for special cases) // the special case is 1/1/indexed w/lutLen=3. 2/3's of values are all 0. This is correct behavior. // special note: the colorDefault code has a COLOR case (indexed and wantLutDefined both true) that is not correct. // In fact in the whole method need better case logic to create the three possible modes and then test for them. // I cannot get BF to set hasChannelLut true so far and this kills the COLOR mode. Also with indexed I've gotten // back COMPOSITE when expecting GRAYSCALE (or vice versa, I don't remember at the moment) because I have no test // that matches the channelFiller.isFilled() case in BF. // the color test methods seem to fail for virtual=true (no longer seems to be case - something Curtis fixed?) // datasetSwapDims has ugly workaround to handle bad signed data / virtual flag interaction. Need BF fix. // (Curtis may have fixed. Existing code hacked to work until I know more.) // many test methods are only UINT8 // expand compositeTestSubcases() to handle more pixTypes and indexed data // implement more combo tests // maybe phase out *Index(ImageProcessor) to support indexed data // add pixelsTest() where necessary // perhaps refactor the various imageSeriesIn... and ImagesIn... order tests into a general tester and an orderBy param // broken // comboCropAndAutoscale for INT32. I think its a limitation of Fake. The values of the cropped image are less // than the minimum representable value of an int as a float. So when we make a FloatProcessor on the int[] data // the huge negative values get clamped to the lowest representable point and thus max and min are not set correctly // by IJ. I have verified that the pixel data that is sent to FloatProcessor() is correct. Limitation we'll live // with I guess. // (OLD) seem broken but don't know status from Curtis // colorized: 1/1/indexed (all indices 0 for all images), 3/1/indexed (iIndex,cIndex) (although w/ falseColor its okay), // 6/3/nonindexed (iIndex,cIndex), 12/3/nonindexed (iIndex,cIndex), 3/3/indexed (iIndex,cIndex) // record does not work // note // I changed MemoryRecord from "Flip Horizontally" (which could not be found at runtime) to "Invert". Verified // "Invert" is recordable and record("invert") getting called but doRecording is false for some reason. Also Curtis // thought flip would be easier to use for predicting actual values rather than special case code with invert. As // I'm only doing UINT8 for now this is not a problem. // (OLD) waiting on BF implementations for // - indexed color support // must address before release // - macros should still work like before // - add some tests for combination of options // comboConcatSplit() - done and passing // comboManyOptions - done and passing // other combo tests - rely on color code working. Waiting for BF. (OLD) // would be nice to address before release // - BF/imageJ returning wrong values of max num pixels (UINT32 off by one - IJ bug, float weird too, etc.) // - memoryRecord failure (needs BF code fix) // - open individual files: try to come up with a way to test without a disk file as source // - output stack order - testing of iIndex? should match imagestack number? i.e. 5th plane == 4 - doesn't look so // - improve, comment, and generalize code for increased coverage /** * A class for testing the Bio-Formats Importer behavior. * * <dl><dt><b>Source code:</b></dt> * <dd><a href="http://trac.openmicroscopy.org.uk/ome/browser/bioformats.git/components/loci-plugins/test/loci/plugins/in/ImporterTest.java">Trac</a>, * <a href="http://git.openmicroscopy.org/?p=bioformats.git;a=blob;f=components/loci-plugins/test/loci/plugins/in/ImporterTest.java;hb=HEAD">Gitweb</a></dd></dl> * * @author Barry DeZonia bdezonia at wisc.edu */ public class ImporterTest { /** Whether to log debugging messages to stdout. */ static final boolean DEBUG = false; /** * Whether to run tests with special requirements. * This flag is mainly to disable the testDatasetOpenFilesIndividually test * on systems without the required Bio-Rad PIC sample data available. */ static final boolean RUN_SPECIAL_TESTS = false; private enum Axis {Z,C,T}; private enum ChannelOrder {ZCT, ZTC, CZT, CTZ, TZC, TCZ}; private static final boolean[] BOOLEAN_STATES = new boolean[] {false, true}; private static Color[] DEFAULT_COLOR_ORDER = new Color[] {Color.RED, Color.GREEN, Color.BLUE, Color.WHITE, Color.CYAN, Color.MAGENTA, Color.YELLOW}; private static Color[] CUSTOM_COLOR_ORDER = new Color[] {Color.BLUE, Color.RED, Color.GREEN, Color.MAGENTA, Color.YELLOW, Color.CYAN, Color.WHITE}; private static final boolean NOT_INDEXED = false; private static final boolean INDEXED = true; private static final boolean FALSE_COLOR = true; private static final boolean REAL_COLOR = false; private static final int ONE_SERIES = 1; private static final String[] FAKE_FILES; private static final String FAKE_PATTERN; private static final int FAKE_PLANE_COUNT = 7; private static final int FAKE_CHANNEL_COUNT = 3; private static final int FAKE_TIMEPOINT_COUNT = 5; private static final int FAKE_SIZE_X = 50; private static final int FAKE_SIZE_Y = 50; static { //String template = "test_C%s_TP%s&sizeX=50&sizeY=20&sizeZ=7.fake"; String template = constructFakeFilename("test_C%s_TP%s", FormatTools.UINT8, FAKE_SIZE_X, FAKE_SIZE_Y, FAKE_PLANE_COUNT, 1, 1, -1, false, -1, false, -1); FAKE_FILES = new String[] { String.format(template, "1", "1"), String.format(template, "2", "1"), String.format(template, "3", "1"), String.format(template, "1", "2"), String.format(template, "2", "2"), String.format(template, "3", "2"), String.format(template, "1", "3"), String.format(template, "2", "3"), String.format(template, "3", "3"), String.format(template, "1", "4"), String.format(template, "2", "4"), String.format(template, "3", "4"), String.format(template, "1", "5"), String.format(template, "2", "5"), String.format(template, "3", "5") }; FAKE_PATTERN = String.format(template, "<1-3>", "<1-5>"); for (String file : FAKE_FILES) { Location.mapId(file, "iThinkI'mImportantButI'mNot"); } } // ** Helper methods ******************************************************************* private static String constructFakeFilename(String title, int pixelType, int sizeX, int sizeY, int sizeZ, int sizeC, int sizeT, int numSeries, boolean indexed, int rgb, boolean falseColor, int lutLength) { // some tests rely on each image being large enough to get the s,i,z,t,c index pixels of a // FakeFile. This requires the x value of tested images to be somewhat large. Assert // the input image fits the bill if (sizeX < 41) { throw new IllegalArgumentException("constructFakeFilename() - width < 41 : can break some of our tests"); } String fileName = ""; fileName += title; fileName += "&pixelType=" + FormatTools.getPixelTypeString(pixelType); fileName += "&sizeX=" + sizeX; fileName += "&sizeY=" + sizeY; fileName += "&sizeZ=" + sizeZ; fileName += "&sizeC=" + sizeC; fileName += "&sizeT=" + sizeT; if (numSeries > 0) fileName += "&series=" + numSeries; if (indexed) fileName += "&indexed=true"; if (rgb != -1) fileName += "&rgb=" + rgb; if (falseColor) fileName += "&falseColor=true"; if (lutLength > 0) fileName += "&lutLength=" + lutLength; fileName += ".fake"; return fileName; } /** Series number of the given image processor. */ private int sIndex(ImageProcessor proc) { return (int) proc.getPixelValue(0, 0); } /** Image number of the given image processor. */ private int iIndex(ImageProcessor proc) { return (int) proc.getPixelValue(10, 0); } /** Slice number of the given image processor. */ private int zIndex(ImageProcessor proc) { return (int) proc.getPixelValue(20, 0); } /** Channel number of the given image processor. */ private int cIndex(ImageProcessor proc) { return (int) proc.getPixelValue(30, 0); } /** Frame number of the given image processor. */ private int tIndex(ImageProcessor proc) { return (int) proc.getPixelValue(40, 0); } /** Series number of the given ImagePlus at z,c,t index */ private int sIndex(ImagePlus imp, int z, int c, int t, boolean indexed, boolean falseColor) { return getPixelValue(0,0,imp,z,c,t,indexed,falseColor); } /** Image number of the given ImagePlus at z,c,t index */ @SuppressWarnings("unused") private int iIndex(ImagePlus imp, int z, int c, int t, boolean indexed, boolean falseColor) { return getPixelValue(10,0,imp,z,c,t,indexed,falseColor); } /** Slice number of the given ImagePlus at z,c,t index */ private int zIndex(ImagePlus imp, int z, int c, int t, boolean indexed, boolean falseColor) { return getPixelValue(20,0,imp,z,c,t,indexed,falseColor); } /** Channel number of the given ImagePlus at z,c,t index */ private int cIndex(ImagePlus imp, int z, int c, int t, boolean indexed, boolean falseColor) { return getPixelValue(30,0,imp,z,c,t,indexed,falseColor); } /** Frame number of the given ImagePlus at z,c,t index */ private int tIndex(ImagePlus imp, int z, int c, int t, boolean indexed, boolean falseColor) { return getPixelValue(40,0,imp,z,c,t,indexed,falseColor); } /** Logs the given messages to stdout. */ private void log(String s) { System.out.println(s); } /** a debug routine for printing the SIZCT indices of a slice in a FakeFile stack */ private void printVals(ImageProcessor proc) { if (DEBUG) log( " S=" + sIndex(proc) + " I=" + iIndex(proc) + " Z=" + zIndex(proc) + " C=" + cIndex(proc) + " T=" + tIndex(proc)); } /** returns the character at the given index within a string that is a permutation of ZCT */ private char axisChar(String order, int d) { if ((d < 0) || (d > 2)) throw new IllegalArgumentException("axisChar() - index out of bounds [0..2]: "+d); return order.charAt(d); } /** returns Axis given an order string and an index */ private Axis axis(String order, int d) { char dimChar = axisChar(order,d); if (dimChar == 'Z') return Axis.Z; if (dimChar == 'C') return Axis.C; if (dimChar == 'T') return Axis.T; throw new IllegalArgumentException("axis() - unknown dimension specified: ("+dimChar+")"); } /** returns z, c, or t value given an Axis selector */ private int value(Axis axis, int z, int c, int t) { if (axis == Axis.Z) return z; if (axis == Axis.C) return c; if (axis == Axis.T) return t; throw new IllegalArgumentException("value() - unknown axis: "+axis); } /** returns z, c, or t index value given an ImageProcessor and an Axis selector */ private int index(Axis axis, ImageProcessor proc) { if (axis == Axis.Z) return zIndex(proc); if (axis == Axis.C) return cIndex(proc); if (axis == Axis.T) return tIndex(proc); throw new IllegalArgumentException("index() - unknown axis: "+axis); } /** get full order (XYTCZ) from ChannelOrder (TCZ) as string */ private String bfChanOrd(ChannelOrder order) { return "XY" + order.toString(); } /** returns the number of of elements in a series given from, to, and by values */ private int numInSeries(int from, int to, int by) { if (by < 1) throw new IllegalArgumentException("numInSeries passed a stepBy value < 1"); // could calc this but simple loop suffices for our purposes int count = 0; for (int i = from; i <= to; i += by) count++; return count; } // this next method useful to avoid changes to instance vars of ImagePlus by query functions /** Gets values of private instance variable ints from an ImagePlus */ private int getField(ImagePlus imp, String fieldName) { Exception exc = null; try { Field field = ImagePlus.class.getDeclaredField(fieldName); field.setAccessible(true); Object value = field.get(imp); return (Integer) value; } catch (SecurityException e) { exc = e; } catch (NoSuchFieldException e) { exc = e; } catch (IllegalArgumentException e) { exc = e; } catch (IllegalAccessException e) { exc = e; } exc.printStackTrace(); return -1; } /** The number of Z slices in an ImagePlus */ private int getSizeZ(ImagePlus imp) { return getField(imp, "nSlices"); } /** The number of T slices in an ImagePlus */ private int getSizeT(ImagePlus imp) { return getField(imp, "nFrames"); } /** The number of effective C slices in an ImagePlus */ private int getEffectiveSizeC(ImagePlus imp) { return getField(imp, "nChannels"); } /** set an ImagePlus' position relative to CZT ordering (matches imp.setPosition()) */ private void setCztPosition(ImagePlus imp, int z, int c, int t) { // czt order : should match the .setPosition(c,z,t) code int sliceNumber = c + (z*imp.getNChannels()) + (t*imp.getNSlices()*imp.getNChannels()); imp.setSlice(sliceNumber+1); } /** set an ImagePlus' position relative to ZCT ordering (rather than default CZT) */ private void setZctPosition(ImagePlus imp, int z, int c, int t) { // zct order int sliceNumber = z + (c*imp.getNSlices()) + (t*imp.getNSlices()*imp.getNChannels()); imp.setSlice(sliceNumber+1); } // note - the following code relies on setZctPosition() being called previously. Otherwise regular ImagePlus case // won't work. In general this method not designed for general use but actually just for use by getPixelValue(). /** gets the color table from any kind of ImagePlus (composite or not) - not for general use */ private LUT getColorTable(ImagePlus imp, int channel) { if (imp instanceof CompositeImage) return ((CompositeImage)imp).getChannelLut(channel+1); // else a regular ImagePlus //if (DEBUG) log(" getting color table from a regular ImagePlus."); IndexColorModel icm = (IndexColorModel)imp.getProcessor().getColorModel(); // TODO - maybe I can cast from IndexColorModel to LUT here - depends what IJ did. // otherwise make a LUT byte[] reds = new byte[256], greens = new byte[256], blues = new byte[256]; icm.getReds(reds); icm.getGreens(greens); icm.getBlues(blues); return new LUT(reds,greens,blues); } /** get the actual pixel value (lookup when data is indexed) of the index of a fake image at a given z,c,t */ private int getPixelValue(int x,int y, ImagePlus imp, int z, int c, int t, boolean indexed, boolean falseColor) { //TODO - restore - changed for compositeTest debugging setZctPosition(imp,z,c,t); setCztPosition(imp,z,c,t); int rawValue = (int) (imp.getProcessor().getPixelValue(x, y)); if ((!indexed) || (falseColor)) // TODO - disabling falseColor test here improves 3/1/indexed/falseColor return rawValue; // otherwise indexed - lookup pixel value in LUT LUT lut = getColorTable(imp,c); int value = lut.getRed(rawValue); // since r g and b vals should be the same choose one arbitrarily. // OR Use red in case lut len < 3 and zero fills other channels //if (DEBUG) log(" did a lut lookup in getPixelValue("+z+","+c+","+t+") = "+value+" (rawValue = "+rawValue+")"); return value; } /** calculate the effective size C of an image given various params */ private int effectiveC(int sizeC, int rgb, int lutLen, boolean indexed, boolean falseColor) { int effC = sizeC; if (indexed) // this is from Melissa { if (falseColor) effC /= rgb; else // not falseColor effC *= lutLen; } return effC; } // ****** helper tests **************************************************************************************** /** tests that the correct number of ImagePluses exist */ private void impsCountTest(ImagePlus[] imps, int numExpected) { assertNotNull(imps); assertEquals(numExpected,imps.length); } /** tests that the stack of an ImagePlus is of a given size */ private void stackTest(ImagePlus imp, int expectedSize) { assertNotNull(imp); assertEquals(expectedSize,imp.getStack().getSize()); } /** tests that the dimensions of an ImagePlus match passed in x,y,z,c,t values */ private void xyzctTest(ImagePlus imp, int x, int y, int z, int c, int t) { assertNotNull(imp); assertEquals(x,imp.getWidth()); assertEquals(y,imp.getHeight()); assertEquals(z,getSizeZ(imp)); assertEquals(c,getEffectiveSizeC(imp)); assertEquals(t,getSizeT(imp)); } /** tests that the first and last entries of a lut match expected values */ private void lutTest(CompositeImage ci, int channel, int minR, int minG, int minB, int maxR, int maxG, int maxB) { // channel is 0-based LUT lut = ci.getChannelLut(channel+1); // IJ is 1-based byte[] reds = new byte[256]; byte[] blues = new byte[256]; byte[] greens = new byte[256]; lut.getReds(reds); lut.getGreens(greens); lut.getBlues(blues); /* TODO - helper for testing falseColor problems if (DEBUG) log(" expected min rgb : "+minR+" "+minG+" "+minB); if (DEBUG) log(" expected max rgb : "+maxR+" "+maxG+" "+maxB); if (DEBUG) log(" actual min rgb : "+reds[0]+" "+greens[0]+" "+blues[0]); if (DEBUG) log(" actual max rgb : "+(reds[255]&0xff)+" "+(greens[255]&0xff)+" "+(blues[255]&0xff)); */ assertEquals((byte)minR,reds[0]); assertEquals((byte)maxR,reds[255]); assertEquals((byte)minG,greens[0]); assertEquals((byte)maxG,greens[255]); assertEquals((byte)minB,blues[0]); assertEquals((byte)maxB,blues[255]); } /** tests that each channel lut in a CompositeImage matches the passed in expected colors */ private void colorTests(CompositeImage ci, int numChannels, Color[] expectedColors) { for (int i = 0; i < numChannels; i++) { Color color = expectedColors[i]; lutTest(ci,i,0,0,0,color.getRed(),color.getGreen(),color.getBlue()); } } /** tests that input to the crop tests is valid */ private void verifyCropInput(int sizeX, int sizeY, int originCropX, int originCropY, int sizeCrop) { assertTrue((sizeX > 50) || (sizeY > 10)); assertTrue(sizeX < 256); assertTrue(sizeY < 256); assertTrue(sizeCrop > 0); assertTrue(originCropX >= 0); assertTrue(originCropY >= 0); assertTrue((originCropX > 50) || (originCropY > 10)); assertTrue(originCropX + sizeCrop <= sizeX); assertTrue(originCropY + sizeCrop <= sizeY); } /** tests that the indices of a FakeFile[z,c,t] match passed in values*/ private boolean indexValuesTest(ImagePlus imp, int z, int c, int t, boolean indexed, boolean falseColor, int expS, /*int expI,*/ int expZ, int expC, int expT) { // TODO - returns a boolean so we can print out all values before asserting failure. Could be changed if desired. int tempS = sIndex(imp, z, c, t, indexed, falseColor); //int tempI = iIndex(imp, z, c, t, indexed, falseColor); int tempZ = zIndex(imp, z, c, t, indexed, falseColor); int tempC = cIndex(imp, z, c, t, indexed, falseColor); int tempT = tIndex(imp, z, c, t, indexed, falseColor); //if (DEBUG) log("actual CZT "+tempC+" "+tempZ+" "+tempT); //if (DEBUG) log(" indices test (I forced to 0)"); //if (DEBUG) log(" expected (sizct): "+expS+" "+0+" "+expZ+" "+expC+" "+expT); //if (DEBUG) log(" actual (sizct): "+tempS+" "+0+" "+tempZ+" "+tempC+" "+tempT); //TODO - remove this debugging code if ((expS != tempS) || /*(expI != tempI) ||*/ (expZ != tempZ) || (expC != tempC) || (expT != tempT)) { //if (DEBUG) log(" indices test"); //if (DEBUG) log(" expected (sizct): "+expS+" "+expI+" "+expZ+" "+expC+" "+expT); //if (DEBUG) log(" actual (sizct): "+tempS+" "+tempI+" "+tempZ+" "+tempC+" "+tempT); return false; } assertEquals(expS,tempS); //assertEquals(expI,tempI); // not so important we test this assertEquals(expZ,tempZ); assertEquals(expC,tempC); assertEquals(expT,tempT); return true; } /** tests that a FakeFile dataset has index values in ZCT order */ private void stackInZctOrderTest(ImagePlus imp, int maxZ, int maxC, int maxT, boolean indexed, boolean falseColor) { if (DEBUG) log("stackInZctOrderTest()"); boolean success = true; stackTest(imp,(maxZ * maxC * maxT)); int iIndex = 0; for (int t = 0; t < maxT; t++) { for (int c = 0; c < maxC; c++) { for (int z = 0; z < maxZ; z++) { int expectedS = 0; //int expectedI = iIndex; int expectedZ = z; int expectedC = c; int expectedT = t; iIndex++; success &= indexValuesTest(imp,z,c,t,indexed,falseColor,expectedS,expectedZ,expectedC,expectedT); } } } if (!success) fail("indexValuesTest() failed for some values"); } /** tests that a FakeFile dataset has index values in CZT order */ private void stackInCztOrderTest(ImagePlus imp, int maxZ, int maxC, int maxT, boolean indexed, boolean falseColor) { if (DEBUG) log("stackInCztOrderTest()"); boolean success = true; stackTest(imp,(maxZ * maxC * maxT)); int iIndex = 0; for (int t = 0; t < maxT; t++) { for (int z = 0; z < maxZ; z++) { for (int c = 0; c < maxC; c++) { int expectedS = 0; //int expectedI = 0; // won't test anymore : some tricky cases arise int expectedZ = z; int expectedC = c; int expectedT = t; iIndex++; success &= indexValuesTest(imp,z,c,t,indexed,falseColor,expectedS,expectedZ,expectedC,expectedT); } } } if (!success) fail("indexValuesTest() failed for some values"); } /** tests that a FakeFile dataset has index values in CZT order repeated once per series */ private void multipleSeriesInCztOrderTest(ImagePlus imp, int numSeries, int maxZ, int maxC, int maxT) { // make sure the number of slices in stack is a sum of all series stackTest(imp,(numSeries*maxZ*maxC*maxT)); ImageStack st = imp.getStack(); int slice = 0; for (int sIndex = 0; sIndex < numSeries; sIndex++) { for (int tIndex = 0; tIndex < maxT; tIndex++) { for (int zIndex = 0; zIndex < maxZ; zIndex++) { for (int cIndex = 0; cIndex < maxC; cIndex++) { ImageProcessor proc = st.getProcessor(++slice); assertEquals(sIndex, sIndex(proc)); assertEquals(zIndex, zIndex(proc)); assertEquals(cIndex, cIndex(proc)); assertEquals(tIndex, tIndex(proc)); } } } } } /** tests that an ImagePlus stack is in a specified order */ private void stackInSpecificOrderTest(ImagePlus imp, String chOrder) { ImageStack st = imp.getStack(); int x = imp.getWidth(); int y = imp.getHeight(); int z = imp.getNSlices(); int c = imp.getNChannels(); int t = imp.getNFrames(); Axis fastest = axis(chOrder,0); Axis middle = axis(chOrder,1); Axis slowest = axis(chOrder,2); int maxI = value(slowest,z,c,t); int maxJ = value(middle,z,c,t); int maxK = value(fastest,z,c,t); int slice = 0; for (int i = 0; i < maxI; i++) { for (int j = 0; j < maxJ; j++) { for (int k = 0; k < maxK; k++) { ImageProcessor proc = st.getProcessor(++slice); //printVals(proc); assertNotNull(proc); assertEquals(x,proc.getWidth()); assertEquals(y,proc.getHeight()); assertEquals(0,sIndex(proc)); assertEquals(i,index(slowest,proc)); assertEquals(j,index(middle,proc)); assertEquals(k,index(fastest,proc)); } } } } /** tests that the pixel values of a FakeFile are as expected */ private void pixelsTest(ImagePlus imp, int pixType, boolean indexed, boolean falseColor) { assertTrue(pixType == FormatTools.UINT8); // TODO - for now assertTrue(imp.getHeight() > 10); int max = imp.getWidth(); if (max > 255) max = 255; for (int t = 0; t < imp.getNFrames(); t++) for (int c = 0; c < imp.getNChannels(); c++) for (int z = 0; z < imp.getNSlices(); z++) for (int i = 0; i < max; i++) assertEquals(i,getPixelValue(i,10,imp,z,c,t,indexed,falseColor)); } /** tests that the pixels values of a cropped FakeFile are correct */ private void croppedPixelsTest(ImagePlus imp, int ox, int cropSize) { ImageProcessor proc = imp.getProcessor(); for (int ix = 0; ix < cropSize; ix++) for (int iy = 0; iy < cropSize; iy++) assertEquals(ox+ix,proc.getPixelValue(ix, iy),0); } /** tests that multiple file groups are pulled into one dataset */ private void groupedFilesTest(ImagePlus imp, int expNumZ, int expNumC, int expNumT) { stackTest(imp,expNumZ*expNumC*expNumT); ImageStack st = imp.getStack(); //if (DEBUG) log("groupedFilesTest"); int slice = 0; for (int t = 0; t < expNumT; t++) { for (int z = 0; z < expNumZ; z++) { for (int c = 0; c < expNumC; c++) { ImageProcessor proc = st.getProcessor(++slice); //printVals(proc); assertEquals(0,sIndex(proc)); assertEquals(z,iIndex(proc)); assertEquals(z,zIndex(proc)); assertEquals(0,cIndex(proc)); assertEquals(0,tIndex(proc)); } } } } /** tests that a dataset has had its Z & T dimensions swapped */ private void swappedZtTest(ImagePlus imp, int pixType, boolean virtual, int originalZ, int originalC, int originalT) { if (DEBUG) log("swappedZtTest() : virtual "+virtual+" pixType "+FormatTools.getPixelTypeString(pixType)); stackTest(imp,(originalZ*originalC*originalT)); ImageStack st = imp.getStack(); // verify that the dimensional extents were swapped final int actualSizeZ = imp.getNSlices(); final int actualSizeC = imp.getNChannels(); final int actualSizeT = imp.getNFrames(); assertEquals(originalT, actualSizeZ); // Z<->T swapped assertEquals(originalC, actualSizeC); assertEquals(originalZ, actualSizeT); // Z<->T swapped // verify that every plane appears in the swapped order int slice = 0; for (int tIndex = 0; tIndex < actualSizeT; tIndex++) { for (int zIndex = 0; zIndex < actualSizeZ; zIndex++) { for (int cIndex = 0; cIndex < actualSizeC; cIndex++) { int actualZ, actualC, actualT; ImageProcessor proc = st.getProcessor(++slice); actualZ = tIndex(proc); // Z<->T swapped actualC = cIndex(proc); actualT = zIndex(proc); // Z<->T swapped assertEquals(zIndex, actualZ); assertEquals(cIndex, actualC); assertEquals(tIndex, actualT); } } } } /** Tests that an ImageStack is ordered ZCT according to specified from/to/by points of z/c/t */ private void seriesInZctOrderTest(ImagePlus imp, boolean indexed, boolean falseColor, int zFrom, int zTo, int zBy, int cFrom, int cTo, int cBy, int tFrom, int tTo, int tBy) { int zs = numInSeries(zFrom,zTo,zBy); int cs = numInSeries(cFrom,cTo,cBy); int ts = numInSeries(tFrom,tTo,tBy); stackTest(imp,(zs * cs * ts)); for (int t = 0; t < ts; t++) { for (int c = 0; c < cs; c++) { for (int z = 0; z < zs; z++) { int zIndex = zIndex(imp,z,c,t,indexed,falseColor); int cIndex = cIndex(imp,z,c,t,indexed,falseColor); int tIndex = tIndex(imp,z,c,t,indexed,falseColor); int zVal = zFrom + z*zBy; int cVal = cFrom + c*cBy; int tVal = tFrom + t*tBy; assertEquals(zVal,zIndex); assertEquals(cVal,cIndex); assertEquals(tVal,tIndex); } } } } /** tests that the Calibration of an ImagePlus of signed integer data is correct */ /** tests if images split on Z are ordered correctly */ private void imagesZInCtOrderTest(ImagePlus[] imps, int sizeX, int sizeY, int sizeZ, int sizeC, int sizeT) { // unwind CZT loop : Z pulled outside, CT in order for (int z = 0; z < sizeZ; z++) { ImagePlus imp = imps[z]; xyzctTest(imp,sizeX,sizeY,1,sizeC,sizeT); stackTest(imp,sizeC * sizeT); ImageStack st = imp.getStack(); int slice = 0; for (int t = 0; t < sizeT; t++) { for (int c = 0; c < sizeC; c++) { ImageProcessor proc = st.getProcessor(++slice); // test the values assertEquals(z,zIndex(proc)); assertEquals(c,cIndex(proc)); assertEquals(t,tIndex(proc)); } } } } /** tests if images split on C are ordered correctly */ private void imagesCInZtOrderTest(ImagePlus[] imps, int sizeX, int sizeY, int sizeZ, int sizeC, int sizeT) { // unwind CZT loop : C pulled outside, ZT in order for (int c = 0; c < sizeC; c++) { ImagePlus imp = imps[c]; xyzctTest(imp,sizeX,sizeY,sizeZ,1,sizeT); stackTest(imp,sizeZ * sizeT); ImageStack st = imp.getStack(); int slice = 0; for (int t = 0; t < sizeT; t++) { for (int z = 0; z < sizeZ; z++) { ImageProcessor proc = st.getProcessor(++slice); // test the values assertEquals(z,zIndex(proc)); assertEquals(c,cIndex(proc)); assertEquals(t,tIndex(proc)); } } } } /** tests if images split on T are ordered correctly */ private void imagesTInCzOrderTest(ImagePlus[] imps, int sizeX, int sizeY, int sizeZ, int sizeC, int sizeT) { // unwind CZT loop : T pulled outside, CZ in order for (int t = 0; t < sizeT; t++) { ImagePlus imp = imps[t]; xyzctTest(imp,sizeX,sizeY,sizeZ,sizeC,1); stackTest(imp,sizeZ * sizeC); ImageStack st = imp.getStack(); int slice = 0; for (int z = 0; z < sizeZ; z++) { for (int c = 0; c < sizeC; c++) { ImageProcessor proc = st.getProcessor(++slice); // test the values assertEquals(z,zIndex(proc)); assertEquals(c,cIndex(proc)); assertEquals(t,tIndex(proc)); } } } } /** tests that a set of images is ordered via Z first - used by concatSplit tests */ private void imageSeriesZInCtOrderTest(ImagePlus[] imps, int numSeries, int sizeX, int sizeY, int sizeZ, int sizeC, int sizeT) { // from CZT order: Z pulled out, CT in order for (int z = 0; z < sizeZ; z++) { ImagePlus imp = imps[z]; xyzctTest(imp,sizeX,sizeY,1,sizeC,sizeT*numSeries); stackTest(imp,numSeries*sizeC*sizeT); ImageStack st = imp.getStack(); for (int s = 0; s < numSeries; s++) { int slice = s*sizeC*sizeT; for (int t = 0; t < sizeT; t++) { for (int c = 0; c < sizeC; c++) { //if (DEBUG) log("index "+index); ImageProcessor proc = st.getProcessor(++slice); //printVals(proc); //if (DEBUG) log("s z c t "+s+" "+z+" "+c+" "+t); //if (DEBUG) log("z c t "+z+" "+c+" "+t); //if (DEBUG) log("is iz ic it "+sIndex(proc)+" "+zIndex(proc)+" "+cIndex(proc)+" "+tIndex(proc)); // test the values assertEquals(z,zIndex(proc)); assertEquals(c,cIndex(proc)); assertEquals(t,tIndex(proc)); assertEquals(s,sIndex(proc)); } } } } } /** tests that a set of images is ordered via C first - used by concatSplit tests */ private void imageSeriesCInZtOrderTest(ImagePlus[] imps, int numSeries, int sizeX, int sizeY, int sizeZ, int sizeC, int sizeT) { // from CZT order: C pulled out, ZT in order for (int c = 0; c < sizeC; c++) { ImagePlus imp = imps[c]; xyzctTest(imp,sizeX,sizeY,sizeZ,1,sizeT*numSeries); stackTest(imp,numSeries*sizeZ*sizeT); ImageStack st = imp.getStack(); for (int s = 0; s < numSeries; s++) { int slice = s*sizeZ*sizeT; for (int t = 0; t < sizeT; t++) { for (int z = 0; z < sizeZ; z++) { ImageProcessor proc = st.getProcessor(++slice); //if (DEBUG) log("index "+index); //if (DEBUG) log("s z c t "+s+" "+z+" "+c+" "+t); //if (DEBUG) log("iz ic it "+zIndex(proc)+" "+cIndex(proc)+" "+tIndex(proc)); // test the values assertEquals(z,zIndex(proc)); assertEquals(c,cIndex(proc)); assertEquals(t,tIndex(proc)); assertEquals(s,sIndex(proc)); } } } } } // this one will be different from the previous two as we concat along T by default for FakeFiles as all dims compatible. // Then we're splitting on T. Logic will need to be different from others. /** tests that a set of images is ordered via T first - used by concatSplit tests */ private void imageSeriesTInCzOrderTest(ImagePlus[] imps, int numSeries, int sizeX, int sizeY, int sizeZ, int sizeC, int sizeT) { int imageNum = 0; for (int s = 0; s < numSeries; s++) { // from CZT order: T pulled out, CZ in order for (int t = 0; t < sizeT; t++) { ImagePlus imp = imps[imageNum++]; xyzctTest(imp,sizeX,sizeY,sizeZ,sizeC,1); stackTest(imp,sizeZ*sizeC); ImageStack st = imp.getStack(); int slice = 0; for (int z = 0; z < sizeZ; z++) { for (int c = 0; c < sizeC; c++) { ImageProcessor proc = st.getProcessor(++slice); //printVals(proc); //if (DEBUG) log("index "+index); //if (DEBUG) log("s z c t "+s+" "+z+" "+c+" "+t); //if (DEBUG) log("iz ic it "+zIndex(proc)+" "+cIndex(proc)+" "+tIndex(proc)); // test the values assertEquals(z,zIndex(proc)); assertEquals(c,cIndex(proc)); assertEquals(t,tIndex(proc)); assertEquals(s,sIndex(proc)); } } } } } /** tests that an image stack is correctly ordered after swapping and cropping */ private void stackCtzSwappedAndCroppedTest(ImagePlus[] imps, int cropSizeX, int cropSizeY, int origSizeZ, int origSizeC, int origSizeT, int start, int stepBy) { // note orig data is ZCT. swapping order is CTZ (all dims swapped). int newMaxT = origSizeC; int numC = numInSeries(start,origSizeC-1,stepBy); int newZ = origSizeT; int newC = origSizeZ; int newT = numC; for (int zIndex = 0; zIndex < newZ; zIndex++) { ImagePlus imp = imps[zIndex]; xyzctTest(imp,cropSizeX,cropSizeY,1,newC,newT); // all dims changed stackTest(imp,newC*newT); ImageStack st = imp.getStack(); int slice = 0; for (int tIndex = start; tIndex < newMaxT; tIndex += stepBy) { for (int cIndex = 0; cIndex < newC; cIndex++) { ImageProcessor proc = st.getProcessor(++slice); assertEquals(cropSizeX,proc.getWidth()); assertEquals(cropSizeY,proc.getHeight()); final int actualZ = tIndex(proc); final int actualC = zIndex(proc); final int actualT = cIndex(proc); assertEquals(zIndex, actualZ); assertEquals(cIndex, actualC); assertEquals(tIndex, actualT); } } } } // ******** specific testers ********************************** /** tests BioFormats when directly calling BF.openImagePlus(path) (no options set) */ private void defaultBehaviorTester(int pixType, int x, int y, int z, int c, int t) { String path = constructFakeFilename("default", pixType, x, y, z, c, t, -1, false, -1, false, -1); ImagePlus[] imps = null; try { imps = BF.openImagePlus(path); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } impsCountTest(imps,1); ImagePlus imp = imps[0]; xyzctTest(imp,x,y,z,c,t); } /** tests BF's options.setStackOrder() */ private void outputStackOrderTester(boolean virtual, int pixType, ChannelOrder order, int x, int y, int z, int c, int t) { String bfChOrder = bfChanOrd(order); String chOrder = order.toString(); String path = constructFakeFilename("stack", pixType, x, y, z, c, t, -1, false, -1, false, -1); ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setVirtual(virtual); options.setId(path); options.setStackOrder(bfChOrder); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } impsCountTest(imps,1); ImagePlus imp = imps[0]; xyzctTest(imp,x,y,z,c,t); stackTest(imp,z*c*t); stackInSpecificOrderTest(imp, chOrder); } /** tests BF's options.setGroupFiles() */ private void datasetGroupFilesTester(boolean virtual) { String path = FAKE_FILES[0]; ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setVirtual(virtual); options.setGroupFiles(true); options.setId(path); imps = BF.openImagePlus(options); assertEquals(FAKE_PATTERN, options.getId()); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } impsCountTest(imps,1); xyzctTest(imps[0], FAKE_SIZE_X, FAKE_SIZE_Y, FAKE_PLANE_COUNT, FAKE_CHANNEL_COUNT, FAKE_TIMEPOINT_COUNT); groupedFilesTest(imps[0], FAKE_PLANE_COUNT, FAKE_CHANNEL_COUNT, FAKE_TIMEPOINT_COUNT); } /** tests BF's options.setUngroupFiles() */ private void datasetOpenFilesIndividuallyTester(boolean virtual) { // TODO - try to remove file dependency String path = "2channel_stack_raw01.pic"; // there is a second file called "2channel_stack_raw02.pic" present in the same directory // if open indiv true should only load one of them, otherwise both // try ungrouped ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setVirtual(virtual); options.setUngroupFiles(true); options.setId(path); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } // test results impsCountTest(imps,1); stackTest(imps[0],16); // one loaded as one set with 16 slices // try grouped try { ImporterOptions options = new ImporterOptions(); options.setVirtual(virtual); options.setUngroupFiles(false); options.setId(path); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } // test results impsCountTest(imps,1); stackTest(imps[0],32); // both loaded as one set of 32 slices } /** tests BF's options.setSwapDimensions() */ private void datasetSwapDimsTester(boolean virtual, int pixType, int x, int y, int z, int t) { if (DEBUG) log("datsetSwapDimsTester() virtual = "+virtual+" pixType = "+FormatTools.getPixelTypeString(pixType)); int c = 3; ChannelOrder swappedOrder = ChannelOrder.TCZ; // original order is ZCT String path = constructFakeFilename("swapDims", pixType, x, y, z, c, t, -1, false, -1, false, -1); ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setVirtual(virtual); options.setId(path); options.setSwapDimensions(true); options.setInputOrder(0, bfChanOrd(swappedOrder)); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } impsCountTest(imps,1); ImagePlus imp = imps[0]; xyzctTest(imp,x,y,t,c,z); // Z<->T swapped swappedZtTest(imp,pixType,virtual,z,c,t); } /** open a fakefile series either as separate ImagePluses or as one ImagePlus depending on input flag allOfThem */ private ImagePlus[] openSeriesTest(String fakeFileName, boolean virtual, boolean openAllValue) { ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setVirtual(virtual); options.setId(fakeFileName); options.setOpenAllSeries(openAllValue); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } return imps; } /** tests BF's options.setOpenAllSeries() */ private void datasetOpenAllSeriesTester(boolean virtual, boolean openAll) { int x = 55, y = 20, z = 2, c = 3, t = 4, numSeries = 5; String path = constructFakeFilename("openAllSeries", FormatTools.UINT32, x, y, z, c, t, numSeries, false, -1, false, -1); int expectedNumImps = 1; if (openAll) expectedNumImps = numSeries; ImagePlus[] imps = openSeriesTest(path,virtual,openAll); impsCountTest(imps,expectedNumImps); for (int i = 0; i < expectedNumImps; i++) xyzctTest(imps[i],x,y,z,c,t); } /** tests BF's options.setOpenAllSeries() and options.setConcatenate() */ private void datasetConcatenateTester(int pixType, int x, int y, int z, int c, int t, int s) { assertTrue(s >= 1); // necessary for this test // open all series as one String path = constructFakeFilename("concat", pixType, x, y, z, c, t, s, false, -1, false, -1); ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setId(path); options.setOpenAllSeries(true); options.setConcatenate(true); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } // test results impsCountTest(imps,1); ImagePlus imp = imps[0]; // with FakeFiles all dims compatible for concat, BF will concat along T. Thus t*s in next test. xyzctTest(imp,x,y,z,c,t*s); multipleSeriesInCztOrderTest(imp,s,z,c,t); } private void ascendingValuesTest(byte[] data, int expectedLength) { assertEquals(expectedLength,data.length); for (int i = 0; i < expectedLength; i++) assertEquals(i,data[i]&0xff); } // TODO : can I replace all calls to this to colorTests() passing numChannels == 1. Another way: modify lutTest() to // use a standard ImagePlus rather than a CompImg and have it call getColorTable(). Then pass in just RED ramped // test values. private void imagePlusLutTest(ImagePlus imp, boolean indexed, boolean falseColor, Color color) { // When numCh < 2 or numCh > 7 the setColorMode() code for Composite and Colorize cannot create a CompositeImage. // Therefore it creates a one channel ImagePlus with a LUT that only ramps the red channel. Test this to be // the case. assertFalse(imp instanceof CompositeImage); if (indexed) { fail("imagePlusLutTest() - not yet supporting indexed"); if (falseColor) ; } LUT lut = getColorTable(imp,0); byte[] data = new byte[256]; if (color.getRed() > 0) { lut.getReds(data); ascendingValuesTest(data,256); } if (color.getGreen() > 0) { lut.getGreens(data); ascendingValuesTest(data,256); } if (color.getBlue() > 0) { lut.getBlues(data); ascendingValuesTest(data,256); } } /** tests BF's options.setColorMode(composite) */ private void colorDefaultTester(boolean virtual, int pixType, boolean indexed, int channels, int chanPerPlane, boolean falseColor, int numSeries, boolean wantLutDefined) { if (DEBUG) log("colorDefaultTester(): pixType "+FormatTools.getPixelTypeString(pixType)+" indexed "+indexed+" channels "+ channels+" chanPerPlane "+chanPerPlane+" falseColor "+falseColor+" numSeries "+numSeries+" defineLut "+wantLutDefined); int sizeX = 55, sizeY = 71, sizeZ = 3, sizeT = 4; // reportedly works in BF as long as numSeries*sizeC*3 <= 25 String path = constructFakeFilename("colorDefault", pixType, sizeX, sizeY, sizeZ, channels, sizeT, numSeries, indexed, chanPerPlane, falseColor, -1); ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setVirtual(virtual); options.setColorMode(ImporterOptions.COLOR_MODE_DEFAULT); if (indexed && wantLutDefined) { for (int s = 0; s < numSeries; s++) options.setCustomColor(s, 0, Color.PINK); // set the first channel lut to pink to force COLOR mode as return } options.setId(path); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } impsCountTest(imps,1); ImagePlus imp = imps[0]; int lutLen = 3; int expectedSizeC = effectiveC(channels, chanPerPlane, lutLen, indexed, falseColor); xyzctTest(imp,sizeX,sizeY,sizeZ,expectedSizeC,sizeT); if ((expectedSizeC >= 2) && (expectedSizeC <= 7)) { assertTrue(imp.isComposite()); CompositeImage ci = (CompositeImage)imp; assertEquals(chanPerPlane > 1, ci.hasCustomLuts()); Color[] colorOrder; int expectedType; if (chanPerPlane > 1) // TODO : apparently need another test here for channelFiller.isFilled() case so 1/1/indexed works { expectedType = CompositeImage.COMPOSITE; colorOrder = DEFAULT_COLOR_ORDER; } else if (indexed && wantLutDefined) { // TODO - left working here. this case doesn't work yet. // have to figure how BF calcs hasChannelLut so I can exercise it here expectedType = CompositeImage.COLOR; colorOrder = new Color[]{Color.PINK,Color.WHITE,Color.WHITE,Color.WHITE,Color.WHITE,Color.WHITE,Color.WHITE,Color.WHITE}; } else { expectedType = CompositeImage.GRAYSCALE; colorOrder = DEFAULT_COLOR_ORDER; } assertEquals(expectedType, ci.getMode()); colorTests(ci,expectedSizeC,colorOrder); } else // expectedSizeC < 2 or > 7 - we should have gotten back a regular ImagePlus { assertFalse(imp.isComposite()); imagePlusLutTest(imp,indexed,falseColor,DEFAULT_COLOR_ORDER[0]); } stackInCztOrderTest(imp,sizeZ,expectedSizeC,sizeT,indexed,falseColor); // TODO : i've done no pixel testing } /** tests BF's options.setColorMode(composite) */ private void colorCompositeTester(boolean virtual, int pixType, boolean indexed, int channels, int chanPerPlane, boolean falseColor, int numSeries) { if (DEBUG) log("colorCompositeTester(): pixType "+FormatTools.getPixelTypeString(pixType)+" indexed "+indexed+" channels "+channels+" chanPerPlane "+chanPerPlane+" falseColor "+falseColor+" numSeries "+numSeries); int sizeX = 55, sizeY = 71, sizeZ = 3, sizeT = 4; // reportedly works in BF as long as numSeries*sizeC*3 <= 25 String path = constructFakeFilename("colorComposite", pixType, sizeX, sizeY, sizeZ, channels, sizeT, numSeries, indexed, chanPerPlane, falseColor, -1); ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setVirtual(virtual); options.setColorMode(ImporterOptions.COLOR_MODE_COMPOSITE); options.setId(path); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } impsCountTest(imps,1); ImagePlus imp = imps[0]; int lutLen = 3; int expectedSizeC = effectiveC(channels, chanPerPlane, lutLen, indexed, falseColor); xyzctTest(imp,sizeX,sizeY,sizeZ,expectedSizeC,sizeT); if ((expectedSizeC >= 2) && (expectedSizeC <= 7)) { assertTrue(imp.isComposite()); CompositeImage ci = (CompositeImage)imp; assertTrue(ci.hasCustomLuts()); assertEquals(CompositeImage.COMPOSITE, ci.getMode()); colorTests(ci,expectedSizeC,DEFAULT_COLOR_ORDER); } else // expectedSizeC < 2 or > 7 - we should have gotten back a regular ImagePlus { assertFalse(imp.isComposite()); imagePlusLutTest(imp,indexed,falseColor,DEFAULT_COLOR_ORDER[0]); } stackInCztOrderTest(imp,sizeZ,expectedSizeC,sizeT,indexed,falseColor); // TODO : i've done no pixel testing } /** tests BF's options.setColorMode(colorized) */ private void colorColorizedTester(boolean virtual, int pixType, boolean indexed, int channels, int chanPerPlane, boolean falseColor, int numSeries) { if (DEBUG) log("colorColorizedTester(): pixType "+FormatTools.getPixelTypeString(pixType)+" indexed "+indexed+" channels "+channels+" chanPerPlane "+chanPerPlane+" falseColor "+falseColor+" numSeries "+numSeries); int sizeX = 55, sizeY = 71, sizeZ = 3, sizeT = 4; String path = constructFakeFilename("colorColorized", pixType, sizeX, sizeY, sizeZ, channels, sizeT, numSeries, indexed, chanPerPlane, falseColor, -1); ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setVirtual(virtual); options.setColorMode(ImporterOptions.COLOR_MODE_COLORIZED); // TODO : do I need to set Color info for series here like Custom? options.setId(path); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } impsCountTest(imps,1); ImagePlus imp = imps[0]; int lutLen = 3; int expectedSizeC = effectiveC(channels, chanPerPlane, lutLen, indexed, falseColor); xyzctTest(imp,sizeX,sizeY,sizeZ,expectedSizeC,sizeT); if ((expectedSizeC >= 2) && (expectedSizeC <= 7)) { assertTrue(imp.isComposite()); CompositeImage ci = (CompositeImage)imp; assertTrue(ci.hasCustomLuts()); assertEquals(CompositeImage.COLOR, ci.getMode()); colorTests(ci,expectedSizeC,DEFAULT_COLOR_ORDER); } else // expectedSizeC < 2 or > 7 - we should have gotten back a regular ImagePlus { assertFalse(imp.isComposite()); imagePlusLutTest(imp,indexed,falseColor,DEFAULT_COLOR_ORDER[0]); } stackInCztOrderTest(imp,sizeZ,expectedSizeC,sizeT,indexed,falseColor); // TODO : i've done no pixel testing } /** tests BF's options.setColorMode(gray) */ private void colorGrayscaleTester(boolean virtual, int pixType, boolean indexed, int channels, int chanPerPlane, boolean falseColor, int numSeries) { if (DEBUG) log("colorGrayscaleTester(): pixType "+FormatTools.getPixelTypeString(pixType)+" indexed "+indexed+" channels "+channels+" chanPerPlane "+chanPerPlane+" falseColor "+falseColor+" numSeries "+numSeries); int sizeX = 55, sizeY = 71, sizeZ = 3, sizeT = 4; String path = constructFakeFilename("colorGrayscale", pixType, sizeX, sizeY, sizeZ, channels, sizeT, numSeries, indexed, chanPerPlane, falseColor, -1); ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setVirtual(virtual); options.setColorMode(ImporterOptions.COLOR_MODE_GRAYSCALE); options.setId(path); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } impsCountTest(imps,1); ImagePlus imp = imps[0]; int lutLen = 3; int expectedSizeC = effectiveC(channels, chanPerPlane, lutLen, indexed, falseColor); xyzctTest(imp,sizeX,sizeY,sizeZ,expectedSizeC,sizeT); if ((expectedSizeC >= 2) && (expectedSizeC <= 7)) { assertTrue(imp.isComposite()); CompositeImage ci = (CompositeImage)imp; assertFalse(ci.hasCustomLuts()); assertEquals(CompositeImage.GRAYSCALE, ci.getMode()); colorTests(ci,expectedSizeC,DEFAULT_COLOR_ORDER); } else // expectedSizeC < 2 or > 7 - we should have gotten back a regular ImagePlus { assertFalse(imp.isComposite()); imagePlusLutTest(imp,indexed,falseColor,DEFAULT_COLOR_ORDER[0]); } stackInCztOrderTest(imp,sizeZ,expectedSizeC,sizeT,indexed,falseColor); // TODO : i've done no pixel testing } /** tests BF's options.setColorMode(custom) */ private void colorCustomTester(boolean virtual, int pixType, boolean indexed, int channels, int chanPerPlane, boolean falseColor, int numSeries) { if (DEBUG) log("colorCustomTester(): pixType "+FormatTools.getPixelTypeString(pixType)+" indexed "+indexed+" channels "+channels+" chanPerPlane "+chanPerPlane+" falseColor "+falseColor+" numSeries "+numSeries); int sizeX = 55, sizeY = 71, sizeZ = 3, sizeT = 4; String path = constructFakeFilename("colorCustom", pixType, sizeX, sizeY, sizeZ, channels, sizeT, numSeries, indexed, chanPerPlane, falseColor, -1); ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setVirtual(virtual); options.setColorMode(ImporterOptions.COLOR_MODE_CUSTOM); int maxChannels = (channels <= 7) ? channels : 7; for (int s = 0; s < numSeries; s++) for (int c = 0; c < maxChannels; c++) options.setCustomColor(s, c, CUSTOM_COLOR_ORDER[c]); options.setId(path); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } impsCountTest(imps,1); ImagePlus imp = imps[0]; int lutLen = 3; int expectedSizeC = effectiveC(channels, chanPerPlane, lutLen, indexed, falseColor); xyzctTest(imp,sizeX,sizeY,sizeZ,expectedSizeC,sizeT); if ((expectedSizeC >= 2) && (expectedSizeC <= 7)) { assertTrue(imp.isComposite()); CompositeImage ci = (CompositeImage)imp; assertTrue(ci.hasCustomLuts()); assertEquals(CompositeImage.COLOR, ci.getMode()); colorTests(ci,expectedSizeC,CUSTOM_COLOR_ORDER); } else // expectedSizeC < 2 or > 7 - we should have gotten back a regular ImagePlus { assertFalse(imp.isComposite()); imagePlusLutTest(imp,indexed,falseColor,CUSTOM_COLOR_ORDER[0]); } stackInCztOrderTest(imp,sizeZ,expectedSizeC,sizeT,indexed,falseColor); // TODO : i've done no pixel testing } /** tests BF's options.setVirtual() */ private void memoryVirtualStackTester(boolean desireVirtual) { int x = 604, y = 531, z = 7, c = 1, t = 1; String path = constructFakeFilename("vstack", FormatTools.UINT16, x, y, z, c, t, -1, false, -1, false, -1); // open stack ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setId(path); options.setVirtual(desireVirtual); // user specified value here imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } // test results impsCountTest(imps,1); ImagePlus imp = imps[0]; xyzctTest(imp,x,y,z,c,t); assertEquals(desireVirtual,imp.getStack().isVirtual()); } /** tests BF's options.setVirtual() with options.setRecord() */ /* TODO - underlying BF code is not working. Comment out for now private void memoryRecordModificationsTester(boolean wantToRemember) { int x = 50, y = 15, z = 3, c = 1, t = 1; String path = constructFakeFilename("memRec", FormatTools.UINT8, x, y, z, c, t, -1, false, -1, false, -1); ImagePlus[] imps = null; assertTrue(y > 10); // needed for this test assertTrue(z > 1); // open file try { ImporterOptions options = new ImporterOptions(); options.setId(path); options.setVirtual(true); options.setRecord(wantToRemember); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } // basic tests impsCountTest(imps,1); ImagePlus imp = imps[0]; xyzctTest(imp,x,y,z,c,t); // change data in slice 1, swap to slice 2, swap back, see whether data reverts imp.setSlice(1); assertEquals(1,(int)imp.getProcessor().getPixelValue(1,10)); // run a plugin whose changes are recorded WindowManager.setTempCurrentImage(imp); IJ.run("Invert","slice"); assertEquals(254,(int)imp.getProcessor().getPixelValue(1,10)); imp.setSlice(2); assertEquals(1,(int)imp.getProcessor().getPixelValue(1,10)); imp.setSlice(1); int expectedVal = wantToRemember ? 254 : 1; assertEquals(expectedVal,(int)imp.getProcessor().getPixelValue(1,10)); } */ /** tests BF's options.set?Begin(), options.set?End(), and options.set?Step() */ private void memorySpecifyRangeTester(int z, int c, int t, int zFrom, int zTo, int zBy, int cFrom, int cTo, int cBy, int tFrom, int tTo, int tBy) { int pixType = FormatTools.UINT8, x=50, y=5; String path = constructFakeFilename("range", pixType, x, y, z, c, t, -1, false, -1, false, -1); ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setId(path); // only set values when nondefault behavior specified // z's if (zFrom != 0) options.setZBegin(0, zFrom); if (zTo != z-1) options.setZEnd(0, zTo); if (zBy != 1) options.setZStep(0, zBy); // c's if (cFrom != 0) options.setCBegin(0, cFrom); if (cTo != c-1) options.setCEnd(0, cTo); if (cBy != 1) options.setCStep(0, cBy); // t's if (tFrom != 0) options.setTBegin(0, tFrom); if (tTo != t-1) options.setTEnd(0, tTo); if (tBy != 1) options.setTStep(0, tBy); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } // should have the data in one series impsCountTest(imps,1); ImagePlus imp = imps[0]; xyzctTest(imp,x,y,numInSeries(zFrom,zTo,zBy),numInSeries(cFrom,cTo,cBy),numInSeries(tFrom,tTo,tBy)); // should be in correct order seriesInZctOrderTest(imp,false,false,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); } /** tests BF's options.setCrop() and options.setCropRegion() */ private void memoryCropTester(int x, int y, int ox, int oy, int cropSize) { verifyCropInput(x, y, ox, oy, cropSize); // needed for this test String path = constructFakeFilename("crop", FormatTools.UINT8, x, y, 1, 1, 1, -1, false, -1, false, -1); // open image ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setId(path); options.setCrop(true); options.setCropRegion(0, new Region(ox, oy, cropSize, cropSize)); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } // test results impsCountTest(imps,1); ImagePlus imp = imps[0]; xyzctTest(imp,cropSize,cropSize,1,1,1); // test we got the right pixels croppedPixelsTest(imp,ox,cropSize); } /** tests BF's options.setSplitChannels() */ private void splitChannelsTester() { final int sizeX = 50, sizeY = 20, sizeZ = 5, sizeC = 3, sizeT = 7; final String path = constructFakeFilename("splitC", FormatTools.UINT8, sizeX, sizeY, sizeZ, sizeC, sizeT, -1, false, -1, false, -1); // open image ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setSplitChannels(true); options.setId(path); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } // one image per channel impsCountTest(imps,sizeC); imagesCInZtOrderTest(imps,sizeX,sizeY,sizeZ,sizeC,sizeT); } /** tests BF's options.setFocalPlanes() */ private void splitFocalPlanesTester() { final int sizeX = 50, sizeY = 20, sizeZ = 5, sizeC = 3, sizeT = 7; final String path = constructFakeFilename("splitZ", FormatTools.UINT8, sizeX, sizeY, sizeZ, sizeC, sizeT, -1, false, -1, false, -1); // open image ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setSplitFocalPlanes(true); options.setId(path); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } // one image per focal plane impsCountTest(imps,sizeZ); imagesZInCtOrderTest(imps,sizeX,sizeY,sizeZ,sizeC,sizeT); } /** tests BF's options.setSplitTimepoints() */ private void splitTimepointsTester() { final int sizeX = 50, sizeY = 20, sizeZ = 5, sizeC = 3, sizeT = 7; final String path = constructFakeFilename("splitT", FormatTools.UINT8, 50, 20, sizeZ, sizeC, sizeT, -1, false, -1, false, -1); // open image ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setSplitTimepoints(true); options.setId(path); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } // one image per time point impsCountTest(imps,sizeT); imagesTInCzOrderTest(imps,sizeX,sizeY,sizeZ,sizeC,sizeT); } // note - this test needs to rely on crop() to get predictable nonzero minimums /** tests BF's options.setConcatenate() with options.setSplitFocalPlanes() */ private void comboConcatSplitFocalPlanesTester() { // take a nontrivial zct set of series // run split and concat at same time final int sizeX = 50, sizeY = 20, sizeZ = 3, sizeC = 5, sizeT = 7, series = 4; final String path = constructFakeFilename("concatSplitZ", FormatTools.UINT8, sizeX, sizeY, sizeZ, sizeC, sizeT, series, false, -1, false, -1); // open image ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setOpenAllSeries(true); options.setConcatenate(true); options.setSplitFocalPlanes(true); options.setId(path); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } // one image per focal plane impsCountTest(imps,sizeZ); imageSeriesZInCtOrderTest(imps,series,sizeX,sizeY,sizeZ,sizeC,sizeT); } /** tests BF's options.setConcatenate() with options.setSplitChannels() */ private void comboConcatSplitChannelsTester() { // take a nontrivial zct set of series // run split and concat at same time final int sizeX = 50, sizeY = 20, sizeZ = 3, sizeC = 5, sizeT = 7, series = 4; final String path = constructFakeFilename("concatSplitC", FormatTools.UINT8, sizeX, sizeY, sizeZ, sizeC, sizeT, series, false, -1, false, -1); // open image ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setOpenAllSeries(true); options.setConcatenate(true); options.setSplitChannels(true); options.setId(path); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } // one image per channel impsCountTest(imps,sizeC); imageSeriesCInZtOrderTest(imps,series,sizeX,sizeY,sizeZ,sizeC,sizeT); } /** tests BF's options.setConcatenate() with options.setSplitTimepoints() */ private void comboConcatSplitTimepointsTester() { // take a nontrivial zct set of series // run split and concat at same time final int sizeX = 50, sizeY = 20, sizeZ = 3, sizeC = 5, sizeT = 7, numSeries = 4; final String path = constructFakeFilename("concatSplitT", FormatTools.UINT8, sizeX, sizeY, sizeZ, sizeC, sizeT, numSeries, false, -1, false, -1); // open image ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setOpenAllSeries(true); options.setConcatenate(true); options.setSplitTimepoints(true); options.setId(path); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } // numSeries images per timepoint impsCountTest(imps,sizeT*numSeries); imageSeriesTInCzOrderTest(imps,numSeries,sizeX,sizeY,sizeZ,sizeC,sizeT); } /** tests BF's options.setColormode(composite) - alternate, later definition */ private void compositeSubcaseTester(int sizeC, boolean indexed) { int pixType = FormatTools.UINT8, sizeX = 60, sizeY = 30, sizeZ = 2, sizeT = 3, numSeries = 1, rgb = -1, lutLen = -1; boolean falseColor = false; String path = constructFakeFilename("colorComposite", pixType, sizeX, sizeY, sizeZ, sizeC, sizeT, numSeries, indexed, rgb, falseColor, lutLen); ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setColorMode(ImporterOptions.COLOR_MODE_COMPOSITE); options.setId(path); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } impsCountTest(imps,1); ImagePlus imp = imps[0]; xyzctTest(imp,sizeX,sizeY,sizeZ,sizeC,sizeT); assertTrue(imp.isComposite()); CompositeImage ci = (CompositeImage)imp; assertTrue(ci.hasCustomLuts()); assertEquals(CompositeImage.COMPOSITE, ci.getMode()); colorTests(ci,sizeC,DEFAULT_COLOR_ORDER); stackInZctOrderTest(imp,sizeZ,sizeC,sizeT,indexed,falseColor); pixelsTest(imp,pixType,indexed,falseColor); } // ** ImporterTest methods ************************************************************** @Test public void testDefaultBehavior() { defaultBehaviorTester(FormatTools.UINT8, 57, 78, 5, 4, 3); defaultBehaviorTester(FormatTools.UINT32, 323, 206, 3, 2, 1); defaultBehaviorTester(FormatTools.UINT16, 400, 300, 1, 1, 1); defaultBehaviorTester(FormatTools.INT8, 232, 153, 3, 7, 5); defaultBehaviorTester(FormatTools.INT16, 107, 414, 1, 1, 1); defaultBehaviorTester(FormatTools.INT32, 158, 99, 2, 3, 4); defaultBehaviorTester(FormatTools.FLOAT, 73, 99, 3, 4, 5); defaultBehaviorTester(FormatTools.DOUBLE, 106, 44, 5, 5, 4); } @Test public void testOutputStackOrder() { for (ChannelOrder order : ChannelOrder.values()) for (boolean virtual : BOOLEAN_STATES) outputStackOrderTester(virtual,FormatTools.UINT8, order, 82, 47, 2, 3, 4); } @Test public void testDatasetGroupFiles() { for (boolean virtual : BOOLEAN_STATES) datasetGroupFilesTester(virtual); } @Test public void testDatasetOpenFilesIndividually() { if (RUN_SPECIAL_TESTS) { for (boolean virtual : BOOLEAN_STATES) datasetOpenFilesIndividuallyTester(virtual); } } @Test public void testDatasetSwapDims() { // TODO: testing only swapping Z&T of XYZTC. Add more option testing. // Note that testComboManyOptions() tests another swap order for (boolean virtual : BOOLEAN_STATES) { datasetSwapDimsTester(virtual,FormatTools.UINT8, 82, 47, 1, 3); datasetSwapDimsTester(virtual,FormatTools.UINT16, 82, 47, 3, 1); datasetSwapDimsTester(virtual,FormatTools.UINT16, 82, 47, 5, 2); datasetSwapDimsTester(virtual,FormatTools.UINT32, 82, 47, 5, 2); datasetSwapDimsTester(virtual,FormatTools.FLOAT, 67, 109, 4, 3); datasetSwapDimsTester(virtual,FormatTools.DOUBLE, 67, 100, 3, 2); datasetSwapDimsTester(virtual,FormatTools.INT8, 44, 108, 1, 4); datasetSwapDimsTester(virtual,FormatTools.INT16, 44, 108, 2, 1); datasetSwapDimsTester(virtual,FormatTools.INT32, 44, 108, 4, 3); } } @Test public void testDatasetOpenAllSeries() { for (boolean virtual : BOOLEAN_STATES) { for (boolean openAll : BOOLEAN_STATES) { datasetOpenAllSeriesTester(virtual,openAll); datasetOpenAllSeriesTester(virtual,openAll); } } } @Test public void testDatasetConcatenate() { // NOTE: for now we will not use a virtual boolean with datasetConcatenateTester() as that combo not a legal one in BF // open a dataset that has multiple series and should get back a single series datasetConcatenateTester(FormatTools.UINT8, 82, 47, 1, 1, 1, 1); datasetConcatenateTester(FormatTools.UINT8, 82, 47, 1, 1, 1, 17); datasetConcatenateTester(FormatTools.UINT8, 82, 47, 4, 5, 2, 9); } @Test public void testColorDefault() { for (int pixType : new int[]{FormatTools.UINT8, FormatTools.UINT16}) { for (boolean virtual : new boolean[]{false,true}) { for (boolean defineLutEntry : BOOLEAN_STATES) { // these here to simplify debugging // edge cases in number of channels nonindexed in one series colorDefaultTester(virtual,pixType,NOT_INDEXED,1,1,REAL_COLOR,ONE_SERIES,defineLutEntry); colorDefaultTester(virtual,pixType,NOT_INDEXED,2,2,REAL_COLOR,ONE_SERIES,defineLutEntry); colorDefaultTester(virtual,pixType,NOT_INDEXED,7,7,REAL_COLOR,ONE_SERIES,defineLutEntry); colorDefaultTester(virtual,pixType,NOT_INDEXED,8,8,REAL_COLOR,ONE_SERIES,defineLutEntry); // edge cases in number of channels nonindexed in one series colorDefaultTester(virtual,pixType,NOT_INDEXED,4,4,REAL_COLOR,ONE_SERIES,defineLutEntry); colorDefaultTester(virtual,pixType,NOT_INDEXED,6,3,REAL_COLOR,ONE_SERIES,defineLutEntry); colorDefaultTester(virtual,pixType,NOT_INDEXED,12,3,REAL_COLOR,ONE_SERIES,defineLutEntry); // edge case : standard 3 chan planar layout colorDefaultTester(virtual,pixType,NOT_INDEXED,3,1,REAL_COLOR,ONE_SERIES,defineLutEntry); // edge case 1 channel indexed // TODO - this one fails UINT8 before I used general pixTypes. With gen pix types indexed does not make sense. //colorDefaultTester(virtual,FormatTools.UINT8,INDEXED,1,1,REAL_COLOR,ONE_SERIES,defineLutEntry); } } } } @Test public void testColorComposite() { for (boolean virtual : new boolean[]{false,true}) { // these here to simplify debugging // edge cases in number of channels nonindexed in one series // TODO : next one fails when virtual true colorCompositeTester(virtual,FormatTools.UINT8,NOT_INDEXED,1,1,REAL_COLOR,ONE_SERIES); colorCompositeTester(virtual,FormatTools.UINT8,NOT_INDEXED,2,2,REAL_COLOR,ONE_SERIES); colorCompositeTester(virtual,FormatTools.UINT8,NOT_INDEXED,7,7,REAL_COLOR,ONE_SERIES); // TODO : next one fails when virtual true colorCompositeTester(virtual,FormatTools.UINT8,NOT_INDEXED,8,8,REAL_COLOR,ONE_SERIES); // edge cases in number of channels nonindexed in one series colorCompositeTester(virtual,FormatTools.UINT8,NOT_INDEXED,4,4,REAL_COLOR,ONE_SERIES); colorCompositeTester(virtual,FormatTools.UINT8,NOT_INDEXED,6,3,REAL_COLOR,ONE_SERIES); // TODO : next one fails when virtual true colorCompositeTester(virtual,FormatTools.UINT8,NOT_INDEXED,12,3,REAL_COLOR,ONE_SERIES); // edge case : standard 3 chan planar layout colorCompositeTester(virtual,FormatTools.UINT8,NOT_INDEXED,3,1,REAL_COLOR,ONE_SERIES); // edge case 1 channel indexed // TODO - this one fails. Actual czt vals back from code are all zeroes 2/3 of the time (1 chan goes to 3) //colorCompositeTester(FormatTools.UINT8,INDEXED,1,1,REAL_COLOR,ONE_SERIES); // general test loop int[] pixTypes = new int[] {FormatTools.UINT8,FormatTools.UINT16}; int[] channels = new int[] {1,2,3,4,5,6,7,8,9}; int[] series = new int[] {1,2,3,4}; int[] channelsPerPlaneVals = new int[]{1,2,3}; for (int pixFormat : pixTypes) { for (int chanCount : channels) { for (int numSeries : series) { for (int channelsPerPlane : channelsPerPlaneVals) { for (boolean indexed : new boolean[]{false}) { // TODO - indexed not test right now : replace with BOOLEAN_STATES for (boolean falseColor : BOOLEAN_STATES) { //if (DEBUG) log(" format "+pixFormat+"indexed "+indexed+" rgb "+rgb+" fasleColor "+falseColor+" c "+c+" s "+s); // TODO see what happens when we remove this //if ((chanCount*numSeries*3) > 25) // IJ slider limitation //{ // if (DEBUG) log("************************* chanCount "+chanCount+" numSeries "+numSeries+" 25 sliders exceeded "+(chanCount*numSeries*3)); // continue; //} if (!indexed && falseColor) // invalid combo - skip continue; if ((chanCount % channelsPerPlane) != 0) // invalid combo - skip continue; colorCompositeTester(virtual,pixFormat,indexed,chanCount,channelsPerPlane,falseColor,numSeries); } } } } } } } } @Test public void testColorColorized() { for (int pixType : new int[]{FormatTools.UINT8, FormatTools.UINT16}) { for (boolean virtual : new boolean[]{false,true}) { // these here to simplify debugging // edge cases in number of channels nonindexed in one series colorColorizedTester(virtual,pixType,NOT_INDEXED,1,1,REAL_COLOR,ONE_SERIES); colorColorizedTester(virtual,pixType,NOT_INDEXED,2,2,REAL_COLOR,ONE_SERIES); colorColorizedTester(virtual,pixType,NOT_INDEXED,7,7,REAL_COLOR,ONE_SERIES); colorColorizedTester(virtual,pixType,NOT_INDEXED,8,8,REAL_COLOR,ONE_SERIES); // edge cases in number of channels nonindexed in one series colorColorizedTester(virtual,pixType,NOT_INDEXED,4,4,REAL_COLOR,ONE_SERIES); colorColorizedTester(virtual,pixType,NOT_INDEXED,6,3,REAL_COLOR,ONE_SERIES); colorColorizedTester(virtual,pixType,NOT_INDEXED,12,3,REAL_COLOR,ONE_SERIES); // edge case : standard 3 chan planar layout colorColorizedTester(virtual,pixType,NOT_INDEXED,3,1,REAL_COLOR,ONE_SERIES); // edge case 1 channel indexed // TODO - this one fails UINT8 before I used general pixTypes. With gen pix types indexed does not make sense. //colorColorizedTester(virtual,FormatTools.UINT8,INDEXED,1,1,REAL_COLOR,ONE_SERIES); } } } @Test public void testColorGrayscale() { for (int pixType : new int[]{FormatTools.UINT8, FormatTools.UINT16}) { for (boolean virtual : new boolean[]{false,true}) { // these here to simplify debugging // edge cases in number of channels nonindexed in one series colorGrayscaleTester(virtual,pixType,NOT_INDEXED,1,1,REAL_COLOR,ONE_SERIES); colorGrayscaleTester(virtual,pixType,NOT_INDEXED,2,2,REAL_COLOR,ONE_SERIES); colorGrayscaleTester(virtual,pixType,NOT_INDEXED,7,7,REAL_COLOR,ONE_SERIES); colorGrayscaleTester(virtual,pixType,NOT_INDEXED,8,8,REAL_COLOR,ONE_SERIES); // edge cases in number of channels nonindexed in one series colorGrayscaleTester(virtual,pixType,NOT_INDEXED,4,4,REAL_COLOR,ONE_SERIES); colorGrayscaleTester(virtual,pixType,NOT_INDEXED,6,3,REAL_COLOR,ONE_SERIES); colorGrayscaleTester(virtual,pixType,NOT_INDEXED,12,3,REAL_COLOR,ONE_SERIES); // edge case : standard 3 chan planar layout colorGrayscaleTester(virtual,pixType,NOT_INDEXED,3,1,REAL_COLOR,ONE_SERIES); // edge case 1 channel indexed // TODO - this one fails UINT8 before I used general pixTypes. With gen pix types indexed does not make sense. //colorGrayscaleTester(FormatTools.UINT8,INDEXED,1,1,REAL_COLOR,ONE_SERIES); } } } @Test public void testColorCustom() { for (int pixType : new int[]{FormatTools.UINT8, FormatTools.UINT16}) { for (boolean virtual : new boolean[]{false,true}) { // these here to simplify debugging // edge cases in number of channels nonindexed in one series colorCustomTester(virtual,pixType,NOT_INDEXED,1,1,REAL_COLOR,ONE_SERIES); colorCustomTester(virtual,pixType,NOT_INDEXED,2,2,REAL_COLOR,ONE_SERIES); colorCustomTester(virtual,pixType,NOT_INDEXED,7,7,REAL_COLOR,ONE_SERIES); colorCustomTester(virtual,pixType,NOT_INDEXED,8,8,REAL_COLOR,ONE_SERIES); // edge cases in number of channels nonindexed in one series colorCustomTester(virtual,pixType,NOT_INDEXED,4,4,REAL_COLOR,ONE_SERIES); colorCustomTester(virtual,pixType,NOT_INDEXED,6,3,REAL_COLOR,ONE_SERIES); colorCustomTester(virtual,pixType,NOT_INDEXED,12,3,REAL_COLOR,ONE_SERIES); // edge case : standard 3 chan planar layout colorCustomTester(virtual,pixType,NOT_INDEXED,3,1,REAL_COLOR,ONE_SERIES); // edge case 1 channel indexed // TODO - this one fails UINT8 before I used general pixTypes. With gen pix types indexed does not make sense. //colorCustomTester(FormatTools.UINT8,INDEXED,1,1,REAL_COLOR,ONE_SERIES); } } /* old way int[] pixTypes = new int[]{FormatTools.UINT8, FormatTools.UINT16, FormatTools.FLOAT}; int[] xs = new int[] {45}; int[] ys = new int[] {14}; int[] zs = new int[] {1,2}; int[] cs = new int[] {2,3,4,5,6,7}; // all that BF/IJ supports right now int[] ts = new int[] {1,2}; int[] series = new int[] {1,2,3,4}; for (int pixFormat : pixTypes) for (int x : xs) for (int y : ys) for (int z : zs) for (int c : cs) for (int t : ts) for (int s : series) //if ((c*s*3) <= 25) // IJ slider limitation { //if (DEBUG) log("format "+pixFormat+" x "+x+" y "+y+" z "+z+" c "+c+" t "+t+" s "+s); colorCustomTester(pixFormat,x,y,z,c,t,s); } */ } @Test public void testColorAutoscale() { new AutoscaleTest().testAutoscale(); } @Test public void testMemoryVirtualStack() { for (boolean virtual : BOOLEAN_STATES) memoryVirtualStackTester(virtual); } /* TODO - underlying BF code is not working. Comment out for now @Test public void testMemoryRecordModifications() { // recordMemory has virtual always set to true. no need to do any other virtual testing for (boolean rememberChanges : BOOLEAN_STATES) memoryRecordModificationsTester(rememberChanges); } */ @Test public void testMemorySpecifyRange() { // note - can't specify range in a virtualStack - no need to test int z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy; // test partial z: from z=8; c=3; t=2; zFrom=2; zTo=z-1; zBy=1; cFrom=0; cTo=c-1; cBy=1; tFrom=0; tTo=t-1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); // test partial z: to z=8; c=3; t=2; zFrom=0; zTo=4; zBy=1; cFrom=0; cTo=c-1; cBy=1; tFrom=0; tTo=t-1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); // test partial z: by z=8; c=3; t=2; zFrom=0; zTo=z-1; zBy=3; cFrom=0; cTo=c-1; cBy=1; tFrom=0; tTo=t-1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); // test full z z=8; c=3; t=2; zFrom=2; zTo=7; zBy=3; cFrom=0; cTo=c-1; cBy=1; tFrom=0; tTo=t-1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); // test partial c: from z=6; c=14; t=4; zFrom=0; zTo=z-1; zBy=1; cFrom=3; cTo=c-1; cBy=1; tFrom=0; tTo=t-1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); // test partial c: to z=6; c=14; t=4; zFrom=0; zTo=z-1; zBy=1; cFrom=0; cTo=6; cBy=1; tFrom=0; tTo=t-1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); // test partial c: by z=6; c=14; t=4; zFrom=0; zTo=z-1; zBy=1; cFrom=0; cTo=c-1; cBy=4; tFrom=0; tTo=t-1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); // test full c z=6; c=14; t=4; zFrom=0; zTo=z-1; zBy=1; cFrom=0; cTo=12; cBy=4; tFrom=0; tTo=t-1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); // test partial t: from z=3; c=5; t=13; zFrom=0; zTo=z-1; zBy=1; cFrom=0; cTo=c-1; cBy=1; tFrom=4; tTo=t-1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); // test partial t: to z=3; c=5; t=13; zFrom=0; zTo=z-1; zBy=1; cFrom=0; cTo=c-1; cBy=1; tFrom=0; tTo=8; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); // test partial t: by z=3; c=5; t=13; zFrom=0; zTo=z-1; zBy=1; cFrom=0; cTo=c-1; cBy=1; tFrom=0; tTo=t-1; tBy=2; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); // test full t z=3; c=5; t=13; zFrom=0; zTo=z-1; zBy=1; cFrom=0; cTo=c-1; cBy=1; tFrom=4; tTo=13; tBy=2; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); // test edge case combo with an invalid by z=2; c=2; t=2; zFrom=0; zTo=0; zBy=2; cFrom=1; cTo=1; cBy=1; tFrom=0; tTo=1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); // test a combination of zct's z=5; c=4; t=6; zFrom=1; zTo=4; zBy=2; cFrom=1; cTo=3; cBy=1; tFrom=2; tTo=5; tBy=2; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); // test another combination of zct's z=7; c=7; t=7; zFrom=3; zTo=6; zBy=4; cFrom=1; cTo=6; cBy=3; tFrom=0; tTo=2; tBy=2; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); // test bad combination of zct's - choosing beyond ends of ranges // z index before 0 begin try { z=7; c=7; t=7; zFrom=-1; zTo=z-1; zBy=1; cFrom=0; cTo=c-1; cBy=1; tFrom=0; tTo=t-1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); fail(); } catch (IllegalArgumentException e) { assertTrue(true); } // z index after z-1 end try { z=7; c=7; t=7; zFrom=0; zTo=z; zBy=1; cFrom=0; cTo=c-1; cBy=1; tFrom=0; tTo=t-1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); fail(); } catch (IllegalArgumentException e) { assertTrue(true); } // z by < 1 try { z=7; c=7; t=7; zFrom=0; zTo=z-1; zBy=0; cFrom=0; cTo=c-1; cBy=1; tFrom=0; tTo=t-1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); fail(); } catch (IllegalArgumentException e) { assertTrue(true); } // c index before 0 begin try { z=7; c=7; t=7; zFrom=0; zTo=z-1; zBy=1; cFrom=-1; cTo=c-1; cBy=1; tFrom=0; tTo=t-1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); fail(); } catch (IllegalArgumentException e) { assertTrue(true); } // c index after c-1 end try { z=7; c=7; t=7; zFrom=0; zTo=z-1; zBy=1; cFrom=0; cTo=c; cBy=1; tFrom=0; tTo=t-1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); fail(); } catch (IllegalArgumentException e) { assertTrue(true); } // c by < 1 try { z=7; c=7; t=7; zFrom=0; zTo=z-1; zBy=1; cFrom=0; cTo=c-1; cBy=0; tFrom=0; tTo=t-1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); fail(); } catch (IllegalArgumentException e) { assertTrue(true); } // t index before 0 begin try { z=7; c=7; t=7; zFrom=0; zTo=z-1; zBy=1; cFrom=0; cTo=c-1; cBy=1; tFrom=-1; tTo=t-1; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); fail(); } catch (IllegalArgumentException e) { assertTrue(true); } // t index after t-1 end try { z=7; c=7; t=7; zFrom=0; zTo=z-1; zBy=1; cFrom=0; cTo=c-1; cBy=1; tFrom=0; tTo=t; tBy=1; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); fail(); } catch (IllegalArgumentException e) { assertTrue(true); } // t by < 1 try { z=7; c=7; t=7; zFrom=0; zTo=z-1; zBy=1; cFrom=0; cTo=c-1; cBy=1; tFrom=0; tTo=t-1; tBy=0; memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); fail(); } catch (IllegalArgumentException e) { assertTrue(true); } /* TODO - could replace above code with this uber combo test // comprehensive but probably WAY too much computation to finish in reasonable time z = 6; c = 5; t = 4; for (int zStart = -1; zStart < z+2; zStart++) for (int zEnd = -1; zEnd < z+2; zEnd++) for (int zInc = -1; zInc < z+2; zInc++) for (int cStart = -1; cStart < c+2; cStart++) for (int cEnd = -1; cEnd < c+2; cEnd++) for (int cInc = -1; cInc < c+2; cInc++) for (int tStart = -1; tStart < t+2; tStart++) for (int tEnd = -1; tEnd < t+2; tEnd++) for (int tInc = -1; tInc < t+2; tInc++) // if an invalid index of some kind if ((zStart < 0) || (zStart >= z) || (zEnd < 0) || (zEnd >= z) || // ignored by BF (zEnd < zStart) || (zInc < 1) || (cStart < 0) || (cStart >= c) || (cEnd < 0) || (cEnd >= c) || // ignored by BF (cEnd < cStart) || (cInc < 1) || (tStart < 0) || (tStart >= t) || (tEnd < 0) || (tEnd >= t) || // ignored by BF (tEnd < tStart) || (tInc < 1)) { // expect failure try { memorySpecifyRangeTester(z,c,t,zFrom,zTo,zBy,cFrom,cTo,cBy,tFrom,tTo,tBy); if (DEBUG) log("memorySpecifyRange() test failed: combo = zct "+z+" "+c+" "+t+ " z vals "+zFrom+" "+zTo+" "+zBy+ " c vals "+cFrom+" "+cTo+" "+cBy+ " t vals "+tFrom+" "+tTo+" "+tBy); fail("BF did not catch bad indexing code"); } catch (IllegalArgumentException e) { assertTrue(true); } } else // expect success memorySpecifyRangeTester(z,c,t,zStart,zEnd,zInc,cStart,cEnd,cInc,tStart,tEnd,tInc); */ } @Test public void testMemoryCrop() { // note - can't crop a virtualStack. therefore no need to test it. memoryCropTester(203, 255, 55, 20, 3); memoryCropTester(203, 184, 55, 40, 2); memoryCropTester(101, 76, 0, 25, 4); memoryCropTester(100, 122, 0, 15, 3); } @Test public void testSplitChannels() { // note - can't split channels on a virtual stack. no need to test it. splitChannelsTester(); } @Test public void testSplitFocalPlanes() { splitFocalPlanesTester(); } @Test public void testSplitTimepoints() { splitTimepointsTester(); } /* @Test public void testComboConcatColorize() { // note - concat doesn't work with virtualStacks. No need to test virtual here. fail("unimplemented"); } */ @Test public void testComboConcatSplitFocalPlanes() { // note - concat and split both don't work with virtualStacks. No need to test virtual here. comboConcatSplitFocalPlanesTester(); } @Test public void testComboConcatSplitChannels() { // note - concat and split both don't work with virtualStacks. No need to test virtual here. comboConcatSplitChannelsTester(); } @Test public void testComboConcatSplitTimepoints() { // note - concat and split both don't work with virtualStacks. No need to test virtual here. comboConcatSplitTimepointsTester(); } /* @Test public void testComboColorizeSplit() { // note - split both doesn't work with virtualStacks. No need to test virtual here. fail("unimplemented"); } */ /* @Test public void testComboConcatColorizeSplit() { // note - concat and split both don't work with virtualStacks. No need to test virtual here. fail("unimplemented"); } */ @Test public void testComboManyOptions() { // note - crop and setTStep both don't work with virtualStacks. No need to test virtual here. int pixType = FormatTools.UINT16, sizeX = 106, sizeY = 33, sizeZ = 3, sizeC = 5, sizeT = 7; int cropOriginX = 0, cropOriginY = 0, cropSizeX = 55, cropSizeY = 16, start = 1, stepBy = 2; ChannelOrder swappedOrder = ChannelOrder.CTZ; // orig is ZCT : this is a deadly swap of all dims // note - to reuse existing code it is necessary that the crop origin is (0,0) String path = constructFakeFilename("superCombo", pixType, sizeX, sizeY, sizeZ, sizeC, sizeT, 1, false, -1, false, -1); ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setId(path); options.setSwapDimensions(true); options.setInputOrder(0, bfChanOrd(swappedOrder)); options.setCrop(true); options.setCropRegion(0, new Region(cropOriginX,cropOriginY,cropSizeX,cropSizeY)); options.setTStep(0, stepBy); options.setTBegin(0, start); options.setSplitFocalPlanes(true); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } impsCountTest(imps,sizeT); // we split on Z but that dim was swapped with T stackCtzSwappedAndCroppedTest(imps,cropSizeX,cropSizeY,sizeZ,sizeC,sizeT,start,stepBy); } private void colorizeSubcaseTester(int pixType, int sizeC, int rgb, boolean indexed, boolean falseColor, int lutLen) { if ((pixType != FormatTools.UINT8) && (pixType != FormatTools.UINT16)) throw new IllegalArgumentException("colorizeSubcaseTester(): passed an invalid pixelType: not UINT8 or UINT16 ("+pixType+")"); if (sizeC % rgb != 0) throw new IllegalArgumentException("colorizeSubcaseTester() passed a bad combo of sizeC and rgb: "+sizeC+" "+rgb); //int totalChannels = sizeC; int channelsPerPlane = rgb; //int totalPlanes = totalChannels / channelsPerPlane; if (channelsPerPlane > 7) throw new IllegalArgumentException("colorizeSubcaseTester() passed bad sizeC - channelsPerPlane > 7 : "+channelsPerPlane); int sizeX = 60, sizeY = 30, sizeZ = 1, sizeT = 1, numSeries = 1; String path = constructFakeFilename("colorColorized", pixType, sizeX, sizeY, sizeZ, sizeC, sizeT, numSeries, indexed, rgb, falseColor, lutLen); ImagePlus[] imps = null; try { ImporterOptions options = new ImporterOptions(); options.setColorMode(ImporterOptions.COLOR_MODE_COLORIZED); options.setId(path); imps = BF.openImagePlus(options); } catch (IOException e) { fail(e.getMessage()); } catch (FormatException e) { fail(e.getMessage()); } impsCountTest(imps,1); ImagePlus imp = imps[0]; if (DEBUG) log(" Returned imp: Z = " +imp.getNSlices()+ " C = " +imp.getNChannels()+" T = "+imp.getNFrames()); for (int tIndex = 0; tIndex < imp.getNFrames(); tIndex++) { for (int cIndex = 0; cIndex < imp.getNChannels(); cIndex++) { for (int zIndex = 0; zIndex < imp.getNSlices(); zIndex++) { setZctPosition(imp,zIndex,cIndex,tIndex); // TODO - should change this loop to czt order and use setCztPosition() ImageProcessor proc = imp.getProcessor(); printVals(proc); } } } if (lutLen == -1) lutLen = 3; int expectedSizeC = effectiveC(sizeC, rgb, lutLen, indexed, falseColor); //if (DEBUG) log(" chans channsPerPlane planes expectedSizeC "+totalChannels+" "+channelsPerPlane+" "+totalPlanes+" "+expectedSizeC); xyzctTest(imp,sizeX,sizeY,sizeZ,expectedSizeC,sizeT); // TODO: the following code conditional as BF sometimes does not return a CompositeImage. Handle better after BF // changed and after I've handled all special cases. if (imp.isComposite()) { CompositeImage ci = (CompositeImage)imp; assertTrue(ci.hasCustomLuts()); assertEquals(CompositeImage.COLOR, ci.getMode()); // TODO - falseColor stuff needs to be impl if (!falseColor) colorTests(ci,expectedSizeC,DEFAULT_COLOR_ORDER); } else if (DEBUG) log(" Not a composite image"); //int iIndex = 0; for (int cIndex = 0; cIndex < expectedSizeC; cIndex++) for (int tIndex = 0; tIndex < sizeT; tIndex++) for (int zIndex = 0; zIndex < sizeZ; zIndex++) if (DEBUG) log(" iIndex pix val ("+zIndex+","+cIndex+","+tIndex+") = "+getPixelValue(10,0,imp,zIndex,cIndex,tIndex,indexed,falseColor)); //assertEquals(iIndex++,getPixelValue(10,0,imp,zIndex,cIndex,tIndex,indexed)); // TODO - replace above nested loop with this when this test debugged : //stackInZctOrderTest(imp,sizeZ,expectedSizeC,sizeT,indexed); } // TODO - see if this can go away. How much does testColorColorize() handle this? // TODO - make a virtual case when working // TODO - enable tests rather thans prints. Its been a while since I worked on this and it may be working better now. @Test public void testColorizeSubcases() { if (DEBUG) log("testColorizeSubcases() - begin special cases"); // INDEXED and sizeC == 1,2,3,anything bigger than 3 // sizeC == 1, rgb == 1, indexed, 8 bit, implicit lut length of 3 - KEY test to do, also note can vary lut len if (DEBUG) log("1/1 indexed"); colorizeSubcaseTester(FormatTools.UINT8,1,1,INDEXED,REAL_COLOR,-1); if (DEBUG) log("1/1 indexed falseColor"); colorizeSubcaseTester(FormatTools.UINT8,1,1,INDEXED,FALSE_COLOR,-1); if (DEBUG) log("1/1/indexed lutLen==2"); colorizeSubcaseTester(FormatTools.UINT8,1,1,INDEXED,REAL_COLOR,2); // sizeC == 1, rgb == 1, indexed, 16 bit, implicit lut length of 3 - 2nd important test to do, also note can vary lut len if (DEBUG) log("1/1 indexed (16-bit)"); colorizeSubcaseTester(FormatTools.UINT16,1,1,INDEXED,REAL_COLOR,-1); if (DEBUG) log("1/1 indexed (16-bit) falseColor"); colorizeSubcaseTester(FormatTools.UINT16,1,1,INDEXED,FALSE_COLOR,-1); if (DEBUG) log("1/1/indexed (16-bit) lutLen==2"); colorizeSubcaseTester(FormatTools.UINT16,1,1,INDEXED,REAL_COLOR,2); // sizeC = 3 and rgb = 1 if (DEBUG) log("3/1 indexed"); colorizeSubcaseTester(FormatTools.UINT8,3,1,INDEXED,REAL_COLOR,-1); if (DEBUG) log("3/1 indexed falseColor"); colorizeSubcaseTester(FormatTools.UINT8,3,1,INDEXED,FALSE_COLOR,-1); // TODO - might be working // sizeC = 3 and rgb = 3 : interleaved if (DEBUG) log("3/3 indexed"); colorizeSubcaseTester(FormatTools.UINT8,3,3,INDEXED,REAL_COLOR,-1); // TODO - enable this failing test //if (DEBUG) log("3/3 indexed falseColor"); //colorizeSubcaseTester(FormatTools.UINT8,3,3,INDEXED,FALSE_COLOR,-1); // NOT INDEXED // sizeC == 1 : don't test yet // TODO - is this limitation now fixed in BF? Do we need to test here? // sizeC = 4 and rgb = 4 : interleaved including alpha // if indexed == true this combo throws exception in CompositeImage constructor if (DEBUG) log("4/4 nonindexed"); // TODO - might be working colorizeSubcaseTester(FormatTools.UINT8,4,4,NOT_INDEXED,REAL_COLOR,-1); // sizeC = 6, rgb = 3, indexed = false // if indexed == true this combo throws exception in CompositeImage constructor if (DEBUG) log("6/3 nonindexed"); colorizeSubcaseTester(FormatTools.UINT8,6,3,NOT_INDEXED,REAL_COLOR,-1); // sizeC = 12, rgb = 3, indexed = false if (DEBUG) log("12/3 nonindexed"); colorizeSubcaseTester(FormatTools.UINT8,12,3,NOT_INDEXED,REAL_COLOR,-1); if (DEBUG) log("testColorizeSubcases() - past special cases"); /* for (int sizeC : new int[] {1,2,3,4,6,12}) for (int rgb : new int[] {1,2,3,4}) if (sizeC % rgb == 0) for (int pixType : new int[] {FormatTools.UINT8}) // TODO - add later FormatTools.UINT16 for (boolean indexed : BOOLEAN_STATES) for (boolean falseColor : BOOLEAN_STATES) { if (!indexed && falseColor) // if !indexed make sure falseColor is false to avoid illegal combo continue; if (DEBUG) log("Colorized: pixType("+FormatTools.getPixelTypeString(pixType)+") sizeC("+sizeC+") rgb("+rgb+") indexed("+indexed+") falseColor("+falseColor+")"); colorizeSubcaseTester(pixType,sizeC,rgb,indexed,falseColor,-1); } if (DEBUG) log("testColorizeSubcases() - past all cases"); */ if (DEBUG) log("testColorizeSubcases() : numerous failures : actual tests commented out to see all print statements."); } // TODO - see if this can go away. How much does testColorComposite() handle this? // TODO - make a virtual case when working @Test public void testCompositeSubcases() { // TODO - handle more cases with falseColor, rgb, etc. for (boolean indexed : BOOLEAN_STATES) for (int channels = 2; channels <= 7; channels++) if (!indexed) // TODO - remove this limitation when BF updated compositeSubcaseTester(channels,indexed); if (DEBUG) log("compositeSubcases() unfinished but 2<=sizeC<=7 nonindexed working"); } }