/** Compiles an N-dimensional list of axis lengths from the given reader. */ private int[] getDimLengths(IFormatReader r) { final int sizeX = r.getSizeX(); final int sizeY = r.getSizeY(); final int sizeZ = r.getSizeZ(); final int sizeT = r.getSizeT(); // final String[] cDimTypes = r.getChannelDimTypes(); final int[] cDimLengths = r.getChannelDimLengths(); final String dimOrder = r.getDimensionOrder(); final List<Integer> dimLengthsList = new ArrayList<Integer>(); // add core dimensions for (int i = 0; i < dimOrder.length(); i++) { final char dim = dimOrder.charAt(i); switch (dim) { case 'X': if (sizeX > 1) dimLengthsList.add(sizeX); break; case 'Y': if (sizeY > 1) dimLengthsList.add(sizeY); break; case 'Z': if (sizeZ > 1) dimLengthsList.add(sizeZ); break; case 'T': if (sizeT > 1) dimLengthsList.add(sizeT); break; case 'C': for (int c = 0; c < cDimLengths.length; c++) { int len = cDimLengths[c]; if (len > 1) dimLengthsList.add(len); } break; } } // convert result to primitive array final int[] dimLengths = new int[dimLengthsList.size()]; for (int i = 0; i < dimLengths.length; i++) { dimLengths[i] = dimLengthsList.get(i); } return dimLengths; }
@Test(dataProvider = "wrappers") public void testCoreMetadata(IFormatReader reader) { assertNotNull(reader.getCurrentFile()); CoreMetadata[] core = reader.getCoreMetadata(); assertEquals(core.length, reader.getSeriesCount()); for (int i = 0; i < reader.getSeriesCount(); i++) { reader.setSeries(i); assertEquals(core[i].sizeX, reader.getSizeX()); assertEquals(core[i].sizeY, reader.getSizeY()); assertEquals(core[i].sizeZ, reader.getSizeZ()); assertEquals(core[i].sizeC, reader.getSizeC()); assertEquals(core[i].sizeT, reader.getSizeT()); assertEquals(core[i].pixelType, reader.getPixelType()); assertEquals(core[i].imageCount, reader.getImageCount()); assertEquals(core[i].dimensionOrder, reader.getDimensionOrder()); assertEquals(core[i].littleEndian, reader.isLittleEndian()); assertEquals(core[i].rgb, reader.isRGB()); assertEquals(core[i].interleaved, reader.isInterleaved()); assertEquals(core[i].indexed, reader.isIndexed()); } }
private <T extends RealType<T>> void populatePlane( IFormatReader r, int no, byte[] plane, LocalizablePlaneCursor<T> cursor) { final int sizeX = r.getSizeX(); final int pixelType = r.getPixelType(); final boolean little = r.isLittleEndian(); final int[] dimLengths = getDimLengths(r); final int[] pos = new int[dimLengths.length]; final int planeX = 0; final int planeY = 1; getPosition(r, no, pos); cursor.reset(planeX, planeY, pos); while (cursor.hasNext()) { cursor.fwd(); final int index = cursor.getPosition(planeX) + cursor.getPosition(planeY) * sizeX; final double value = decodeWord(plane, index, pixelType, little); cursor.getType().setReal(value); } }
/** Copies the current dimensional position into the given array. */ private void getPosition(IFormatReader r, int no, int[] pos) { final int sizeX = r.getSizeX(); final int sizeY = r.getSizeY(); final int sizeZ = r.getSizeZ(); final int sizeT = r.getSizeT(); // final String[] cDimTypes = r.getChannelDimTypes(); final int[] cDimLengths = r.getChannelDimLengths(); final String dimOrder = r.getDimensionOrder(); final int[] zct = r.getZCTCoords(no); int index = 0; for (int i = 0; i < dimOrder.length(); i++) { final char dim = dimOrder.charAt(i); switch (dim) { case 'X': if (sizeX > 1) index++; // NB: Leave X axis position alone. break; case 'Y': if (sizeY > 1) index++; // NB: Leave Y axis position alone. break; case 'Z': if (sizeZ > 1) pos[index++] = zct[0]; break; case 'T': if (sizeT > 1) pos[index++] = zct[2]; break; case 'C': final int[] cPos = FormatTools.rasterToPosition(cDimLengths, zct[1]); for (int c = 0; c < cDimLengths.length; c++) { if (cDimLengths[c] > 1) pos[index++] = cPos[c]; } break; } } }
/** Compiles an N-dimensional list of axis types from the given reader. */ private String[] getDimTypes(IFormatReader r) { final int sizeX = r.getSizeX(); final int sizeY = r.getSizeY(); final int sizeZ = r.getSizeZ(); final int sizeT = r.getSizeT(); final String[] cDimTypes = r.getChannelDimTypes(); final int[] cDimLengths = r.getChannelDimLengths(); final String dimOrder = r.getDimensionOrder(); final List<String> dimTypes = new ArrayList<String>(); // add core dimensions for (char dim : dimOrder.toCharArray()) { switch (dim) { case 'X': if (sizeX > 1) dimTypes.add(X); break; case 'Y': if (sizeY > 1) dimTypes.add(Y); break; case 'Z': if (sizeZ > 1) dimTypes.add(Z); break; case 'T': if (sizeT > 1) dimTypes.add(TIME); break; case 'C': for (int c = 0; c < cDimTypes.length; c++) { int len = cDimLengths[c]; if (len > 1) dimTypes.add(cDimTypes[c]); } break; } } return dimTypes.toArray(new String[0]); }
/** * Attempts to import the given file IDs using Bio-Formats, as a single group. Pixels are saved to * the pixels file designated by OMEIS, and an OME-XML metadata block describing the successfully * imported data is dumped to standard output. */ public void importIds(int[] fileIds) throws OmeisException, FormatException, IOException { boolean doLittle = isLittleEndian(); Arrays.sort(fileIds); // set up file path mappings String[] ids = new String[fileIds.length]; for (int i = 0; i < fileIds.length; i++) { Hashtable fileInfo = getFileInfo(fileIds[i]); ids[i] = (String) fileInfo.get("Name"); String path = getLocalFilePath(fileIds[i]); Location.mapId(ids[i], path); } // read file group String id = ids[0]; String path = Location.getMappedId(id); if (DEBUG) log("Reading file '" + id + "' --> " + path); // verify that all given file IDs were grouped by the reader reader.setId(id); String[] used = reader.getUsedFiles(); if (used == null) { throw new FormatException("Invalid file list for " + path); } if (used.length != ids.length) { throw new FormatException( "File list length mismatch for " + path + ": used=" + a2s(used) + "; ids=" + a2s(ids)); } boolean[] done = new boolean[ids.length]; int numLeft = ids.length; for (int i = 0; i < used.length; i++) { for (int j = 0; j < ids.length; j++) { if (done[j]) continue; if (used[i].equals(ids[j])) { done[j] = true; numLeft--; break; } } } if (numLeft > 0) { throw new FormatException("File list does not correspond to ID list for " + path); } int seriesCount = reader.getSeriesCount(); // get DOM and Pixels elements for the file's OME-XML metadata OMENode ome = (OMENode) omexmlMeta.getRoot(); Document omeDoc = ome.getDOMElement().getOwnerDocument(); Vector pix = DOMUtil.findElementList("Pixels", omeDoc); if (pix.size() != seriesCount) { throw new FormatException( "Pixels element count (" + pix.size() + ") does not match series count (" + seriesCount + ") for '" + id + "'"); } if (DEBUG) log(seriesCount + " series detected."); for (int s = 0; s < seriesCount; s++) { reader.setSeries(s); // gather pixels information for this series int sizeX = reader.getSizeX(); int sizeY = reader.getSizeY(); int sizeZ = reader.getSizeZ(); int sizeC = reader.getSizeC(); int sizeT = reader.getSizeT(); int pixelType = reader.getPixelType(); int bytesPerPixel; boolean isSigned, isFloat; switch (pixelType) { case FormatTools.INT8: bytesPerPixel = 1; isSigned = true; isFloat = false; break; case FormatTools.UINT8: bytesPerPixel = 1; isSigned = false; isFloat = false; break; case FormatTools.INT16: bytesPerPixel = 2; isSigned = true; isFloat = false; break; case FormatTools.UINT16: bytesPerPixel = 2; isSigned = false; isFloat = false; break; case FormatTools.INT32: bytesPerPixel = 4; isSigned = true; isFloat = false; break; case FormatTools.UINT32: bytesPerPixel = 4; isSigned = false; isFloat = false; break; case FormatTools.FLOAT: bytesPerPixel = 4; isSigned = true; isFloat = true; break; case FormatTools.DOUBLE: bytesPerPixel = 8; isSigned = true; isFloat = true; break; default: throw new FormatException( "Unknown pixel type for '" + id + "' series #" + s + ": " + pixelType); } boolean little = reader.isLittleEndian(); boolean swap = doLittle != little && bytesPerPixel > 1 && !isFloat; // ask OMEIS to allocate new pixels file int pixelsId = newPixels(sizeX, sizeY, sizeZ, sizeC, sizeT, bytesPerPixel, isSigned, isFloat); String pixelsPath = getLocalPixelsPath(pixelsId); if (DEBUG) { log("Series #" + s + ": id=" + pixelsId + ", path=" + pixelsPath); } // write pixels to file FileOutputStream out = new FileOutputStream(pixelsPath); int imageCount = reader.getImageCount(); if (DEBUG) { log( "Processing " + imageCount + " planes (sizeZ=" + sizeZ + ", sizeC=" + sizeC + ", sizeT=" + sizeT + "): "); } // OMEIS expects XYZCT order -- // interleaved RGB files will be handled a bit more slowly due to this // ordering (ChannelSeparator must read each plane three times), but // caching performed by the OS helps some for (int t = 0; t < sizeT; t++) { for (int c = 0; c < sizeC; c++) { for (int z = 0; z < sizeZ; z++) { int ndx = reader.getIndex(z, c, t); if (DEBUG) { log("Reading plane #" + ndx + ": z=" + z + ", c=" + c + ", t=" + t); } byte[] plane = reader.openBytes(ndx); if (swap) { // swap endianness for (int b = 0; b < plane.length; b += bytesPerPixel) { for (int k = 0; k < bytesPerPixel / 2; k++) { int i1 = b + k; int i2 = b + bytesPerPixel - k - 1; byte b1 = plane[i1]; byte b2 = plane[i2]; plane[i1] = b2; plane[i2] = b1; } } } out.write(plane); } } } out.close(); if (DEBUG) log("[done]"); // tell OMEIS we're done pixelsId = finishPixels(pixelsId); if (DEBUG) log("finishPixels called (new id=" + pixelsId + ")"); // get SHA1 hash for finished pixels String sha1 = getPixelsSHA1(pixelsId); if (DEBUG) log("SHA1=" + sha1); // inject important extra attributes into proper Pixels element Element pixels = (Element) pix.elementAt(s); pixels.setAttribute("FileSHA1", sha1); pixels.setAttribute("ImageServerID", "" + pixelsId); pixels.setAttribute("DimensionOrder", "XYZCT"); // ignored anyway String pType = pixels.getAttribute("PixelType"); if (pType.startsWith("u")) { pixels.setAttribute("PixelType", pType.replace('u', 'U')); } if (DEBUG) log("Pixel attributes injected."); } reader.close(); // accumulate XML into buffer ByteArrayOutputStream xml = new ByteArrayOutputStream(); try { DOMUtil.writeXML(xml, omeDoc); } catch (javax.xml.transform.TransformerException exc) { throw new FormatException(exc); } // output OME-XML to standard output xml.close(); String xmlString = new String(xml.toByteArray()); if (DEBUG) log(xmlString); if (http) printHttpResponseHeader(); System.out.println(xmlString); }