// // PlugInBioFormatsImporter.java // /* OME Bio-Formats package for reading and converting biological file formats. Copyright (C) 2005-@year@ UW-Madison LOCI and Glencoe Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ import gov.nih.mipav.model.file.*; import gov.nih.mipav.model.structures.ModelImage; import gov.nih.mipav.model.structures.ModelStorageBase; import gov.nih.mipav.plugins.PlugInFile; import gov.nih.mipav.view.*; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Vector; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.SwingUtilities; import loci.common.DataTools; import loci.formats.*; import loci.formats.gui.GUITools; import loci.formats.meta.IMetadata; /** * A plugin for opening life sciences files in MIPAV using Bio-Formats. * * <dl><dt><b>Source code:</b></dt> * <dd><a href="http://trac.openmicroscopy.org.uk/ome/browser/bioformats.git/components/bio-formats/utils/mipav/PlugInBioFormatsImporter.java">Trac</a>, * <a href="http://git.openmicroscopy.org/?p=bioformats.git;a=blob;f=components/bio-formats/utils/mipav/PlugInBioFormatsImporter.java;hb=HEAD">Gitweb</a></dd></dl> * * @author Curtis Rueden ctrueden at wisc.edu */ public class PlugInBioFormatsImporter implements PlugInFile { // -- Constants -- /** Update progress bar no more often than this many milliseconds. */ protected static final int PROGRESS_THRESHOLD = 100; // -- Fields -- protected DimensionSwapper reader; protected JFileChooser chooser; // -- Constructor -- public PlugInBioFormatsImporter() { reader = new DimensionSwapper(new ChannelSeparator()); } // -- PlugInFile API methods -- public boolean canReadImages() { return true; } public boolean canWriteImages() { return false; } public boolean isExtensionSupported(String ext) { String[] suffixes = reader.getSuffixes(); ext = ext.toLowerCase(); // suffixes are alphabetized; use binary search int min = 0, max = suffixes.length - 1; while (min <= max) { int index = (min + max) / 2; int value = ext.compareTo(suffixes[index]); if (value < 0) min = index + 1; // suffix is later in the list else if (value > 0) max = index - 1; // suffix is earlier in the list else return true; // found suffix } return false; // suffix not found } public void readImage() { final ViewUserInterface mipav = ViewUserInterface.getReference(); // prompt user to choose a file if (chooser == null) { chooser = GUITools.buildFileChooser(reader); chooser.setCurrentDirectory(new File(Preferences.getImageDirectory())); } JFrame parent = mipav.getMainFrame(); int rval = chooser.showOpenDialog(parent); if (rval != JFileChooser.APPROVE_OPTION) return; // user canceled final File file = chooser.getSelectedFile(); // load the image in a separate thread Thread importerThread = new Thread("BioFormats-Importer") { public void run() { String name = file.getName(); String dir = file.getParent(); // open file using Bio-Formats setMessage(mipav, "Importing " + name + "...", true); String id = file.getPath(); try { long tic = System.currentTimeMillis(); IMetadata store = MetadataTools.createOMEXMLMetadata(); reader.setMetadataStore(store); reader.setId(id); // MIPAV assumes 4-D data in XYZT order reader.setOutputOrder("XYZTC"); // harvest some core metadata int imageCount = reader.getImageCount(); boolean little = reader.isLittleEndian(); int pixelType = reader.getPixelType(); int bpp = FormatTools.getBytesPerPixel(pixelType); boolean floating = FormatTools.isFloatingPoint(pixelType); int sizeX = reader.getSizeX(); int sizeY = reader.getSizeY(); int sizeZ = reader.getSizeZ(); int sizeT = reader.getSizeT(); int sizeC = reader.getSizeC(); String imageName = store.getImageName(0); if (sizeC > 1) { throw new FormatException( "Multichannel data is unsupported at the moment"); } // compute MIPAV buffer type int mipavType; switch (pixelType) { case FormatTools.INT8: mipavType = ModelStorageBase.BYTE; break; case FormatTools.UINT8: mipavType = ModelStorageBase.UBYTE; break; case FormatTools.INT16: mipavType = ModelStorageBase.SHORT; break; case FormatTools.UINT16: mipavType = ModelStorageBase.USHORT; break; case FormatTools.INT32: mipavType = ModelStorageBase.INTEGER; break; case FormatTools.UINT32: mipavType = ModelStorageBase.UINTEGER; break; case FormatTools.FLOAT: mipavType = ModelStorageBase.FLOAT; break; case FormatTools.DOUBLE: mipavType = ModelStorageBase.DOUBLE; break; default: throw new FormatException("Unsupported pixel type: " + pixelType); } // harvest physical resolution Float dimPhysSizeX = store.getDimensionsPhysicalSizeX(0, 0); Float dimPhysSizeY = store.getDimensionsPhysicalSizeY(0, 0); Float dimPhysSizeZ = store.getDimensionsPhysicalSizeZ(0, 0); Float dimTimeInc = store.getDimensionsTimeIncrement(0, 0); float physSizeX = dimPhysSizeX == null ? 1.0f : dimPhysSizeX.floatValue(); float physSizeY = dimPhysSizeY == null ? 1.0f : dimPhysSizeY.floatValue(); float physSizeZ = dimPhysSizeZ == null ? 1.0f : dimPhysSizeZ.floatValue(); float timeInc = dimTimeInc == null ? 1.0f : dimTimeInc.floatValue(); // compute dimensional extents int[] dimExtents = {sizeX, sizeY, sizeZ, sizeT}; float[] res = {physSizeX, physSizeY, physSizeZ, timeInc}; int[] units = { FileInfoBase.MICROMETERS, FileInfoBase.MICROMETERS, FileInfoBase.MICROMETERS, FileInfoBase.SECONDS }; // create MIPAV image object ModelImage modelImage = new ModelImage(mipavType, dimExtents, imageName); // import planes into MIPAV image byte[] buf = new byte[bpp * sizeX * sizeY]; for (int i=0; i<imageCount; i++) { setMessage(mipav, "Reading plane #" + (i + 1) + "/" + imageCount, false); reader.openBytes(i, buf); // convert byte array to appropriate primitive type int offset = i * buf.length; Object array = DataTools.makeDataArray(buf, bpp, floating, little); // assign data to MIPAV image object switch (mipavType) { case ModelStorageBase.BYTE: case ModelStorageBase.UBYTE: modelImage.importData(offset, (byte[]) array, false); break; case ModelStorageBase.SHORT: case ModelStorageBase.USHORT: modelImage.importData(offset, (short[]) array, false); break; case ModelStorageBase.INTEGER: case ModelStorageBase.UINTEGER: modelImage.importData(offset, (int[]) array, false); break; case ModelStorageBase.FLOAT: modelImage.importData(offset, (float[]) array, false); break; case ModelStorageBase.DOUBLE: modelImage.importData(offset, (double[]) array, false); break; default: throw new FormatException("Unknown buffer type: " + mipavType); } } setMessage(mipav, "Finishing import...", true); // create a FileInfo object for each image plane FileInfoBase[] fileInfo = new FileInfoBase[imageCount]; for (int i=0; i<imageCount; i++) { // HACK: Use FileInfoImageXML since FileInfoBase is abstract. fileInfo[i] = new FileInfoImageXML(name, dir, FileUtility.XML); fileInfo[i].setExtents(dimExtents); fileInfo[i].setResolutions(res); fileInfo[i].setUnitsOfMeasure(units); fileInfo[i].setDataType(mipavType); } modelImage.setFileInfo(fileInfo); // scale color range and display MIPAV image modelImage.calcMinMax(); new ViewJFrameImage(modelImage); long toc = System.currentTimeMillis(); long time = toc - tic; long avg = time / imageCount; setMessage(mipav, name + ": Read " + imageCount + " planes in " + (time / 1000f) + " seconds (" + avg + " ms/plane)", true); } catch (FormatException exc) { exc.printStackTrace(); MipavUtil.displayError( "An error occurred parsing the file: " + exc.getMessage()); } catch (IOException exc) { exc.printStackTrace(); MipavUtil.displayError( "An I/O error occurred reading the file: " + exc.getMessage()); } } }; importerThread.start(); } public void writeImage(ModelImage image) { throw new IllegalStateException("Unsupported"); } // -- Helper methods -- private long lastTime = 0; private synchronized void setMessage(final ViewUserInterface mipav, final String message, final boolean force) { long time = System.currentTimeMillis(); long elapsed = time - lastTime; if (elapsed >= PROGRESS_THRESHOLD || force) { lastTime = time; SwingUtilities.invokeLater(new Runnable() { public void run() { mipav.setMessageText(message); } }); } } }