/* * #%L * BSD implementations of Bio-Formats readers and writers * %% * Copyright (C) 2005 - 2015 Open Microscopy Environment: * - Board of Regents of the University of Wisconsin-Madison * - Glencoe Software, Inc. * - University of Dundee * %% * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * #L% */ package loci.formats; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.Hashtable; import java.util.List; import java.util.Set; import java.util.Vector; import loci.common.DataTools; import loci.common.Location; import loci.common.RandomAccessInputStream; import loci.common.services.DependencyException; import loci.common.services.ServiceFactory; import loci.formats.in.DefaultMetadataOptions; import loci.formats.in.MetadataLevel; import loci.formats.in.MetadataOptions; import loci.formats.meta.DummyMetadata; import loci.formats.meta.FilterMetadata; import loci.formats.meta.IMetadata; import loci.formats.meta.MetadataStore; import loci.formats.ome.OMEXMLMetadata; import loci.formats.services.OMEXMLService; import ome.xml.model.AffineTransform; import ome.xml.model.enums.AcquisitionMode; import ome.xml.model.enums.ArcType; import ome.xml.model.enums.Binning; import ome.xml.model.enums.Compression; import ome.xml.model.enums.ContrastMethod; import ome.xml.model.enums.Correction; import ome.xml.model.enums.DetectorType; import ome.xml.model.enums.DimensionOrder; import ome.xml.model.enums.EnumerationException; import ome.xml.model.enums.ExperimentType; import ome.xml.model.enums.FilamentType; import ome.xml.model.enums.FillRule; import ome.xml.model.enums.FilterType; import ome.xml.model.enums.FontFamily; import ome.xml.model.enums.FontStyle; import ome.xml.model.enums.IlluminationType; import ome.xml.model.enums.Immersion; import ome.xml.model.enums.LaserMedium; import ome.xml.model.enums.LaserType; import ome.xml.model.enums.LineCap; import ome.xml.model.enums.Marker; import ome.xml.model.enums.Medium; import ome.xml.model.enums.MicrobeamManipulationType; import ome.xml.model.enums.MicroscopeType; import ome.xml.model.enums.NamingConvention; import ome.xml.model.enums.PixelType; import ome.xml.model.enums.Pulse; import ome.xml.model.enums.handlers.AcquisitionModeEnumHandler; import ome.xml.model.enums.handlers.ArcTypeEnumHandler; import ome.xml.model.enums.handlers.BinningEnumHandler; import ome.xml.model.enums.handlers.CompressionEnumHandler; import ome.xml.model.enums.handlers.ContrastMethodEnumHandler; import ome.xml.model.enums.handlers.CorrectionEnumHandler; import ome.xml.model.enums.handlers.DetectorTypeEnumHandler; import ome.xml.model.enums.handlers.DimensionOrderEnumHandler; import ome.xml.model.enums.handlers.ExperimentTypeEnumHandler; import ome.xml.model.enums.handlers.FilamentTypeEnumHandler; import ome.xml.model.enums.handlers.FillRuleEnumHandler; import ome.xml.model.enums.handlers.FilterTypeEnumHandler; import ome.xml.model.enums.handlers.FontFamilyEnumHandler; import ome.xml.model.enums.handlers.FontStyleEnumHandler; import ome.xml.model.enums.handlers.IlluminationTypeEnumHandler; import ome.xml.model.enums.handlers.ImmersionEnumHandler; import ome.xml.model.enums.handlers.LaserMediumEnumHandler; import ome.xml.model.enums.handlers.LaserTypeEnumHandler; import ome.xml.model.enums.handlers.LineCapEnumHandler; import ome.xml.model.enums.handlers.MarkerEnumHandler; import ome.xml.model.enums.handlers.MediumEnumHandler; import ome.xml.model.enums.handlers.MicrobeamManipulationTypeEnumHandler; import ome.xml.model.enums.handlers.MicroscopeTypeEnumHandler; import ome.xml.model.enums.handlers.NamingConventionEnumHandler; import ome.xml.model.enums.handlers.PixelTypeEnumHandler; import ome.xml.model.enums.handlers.PulseEnumHandler; /** * Abstract superclass of all biological file format readers. */ public abstract class FormatReader extends FormatHandler implements IFormatReader { // -- Constants -- /** Default thumbnail width and height. */ protected static final int THUMBNAIL_DIMENSION = 128; // -- Fields -- /** Current file. */ protected transient RandomAccessInputStream in; /** Hashtable containing metadata key/value pairs. */ protected Hashtable<String, Object> metadata; /** The number of the current series. */ protected int coreIndex = 0; /** The number of the current series (non flat). */ protected int series = 0; /** Core metadata values. */ protected List<CoreMetadata> core; /** The number of the current resolution. */ protected int resolution = 0; /** Whether or not resolutions are flattened. */ protected boolean flattenedResolutions = true; /** * Whether the file extension matching one of the reader's suffixes * is necessary to identify the file as an instance of this format. */ protected boolean suffixNecessary = true; /** * Whether the file extension matching one of the reader's suffixes * is sufficient to identify the file as an instance of this format. */ protected boolean suffixSufficient = true; /** Whether this format supports multi-file datasets. */ protected boolean hasCompanionFiles = false; /** Short description of the structure of the dataset. */ protected String datasetDescription = "Single file"; /** Whether or not to normalize float data. */ protected boolean normalizeData; /** Whether or not to filter out invalid metadata. */ protected boolean filterMetadata; /** Whether or not to save proprietary metadata in the MetadataStore. */ protected boolean saveOriginalMetadata = false; /** Whether or not MetadataStore sets C = 3 for indexed color images. */ protected boolean indexedAsRGB = false; /** Whether or not to group multi-file formats. */ protected boolean group = true; /** List of domains in which this format is used. */ protected String[] domains = new String[0]; /** * Current metadata store. Should never be accessed directly as the * semantics of {@link #getMetadataStore()} prevent "null" access. */ protected MetadataStore metadataStore = new DummyMetadata(); /** Metadata parsing options. */ protected MetadataOptions metadataOptions = new DefaultMetadataOptions(); private ServiceFactory factory; private OMEXMLService service; // -- Constructors -- /** Constructs a format reader with the given name and default suffix. */ public FormatReader(String format, String suffix) { super(format, suffix); } /** Constructs a format reader with the given name and default suffixes. */ public FormatReader(String format, String[] suffixes) { super(format, suffixes); } // -- Internal FormatReader API methods -- /* @see IFormatReader#reopenFile() */ @Override public void reopenFile() throws IOException { if (in != null) { in.close(); } in = new RandomAccessInputStream(currentId); in.order(isLittleEndian()); } /** * Initializes the given file (parsing header information, etc.). * Most subclasses should override this method to perform * initialization operations such as parsing metadata. * * @throws FormatException if a parsing error occurs processing the file. * @throws IOException if an I/O error occurs processing the file */ protected void initFile(String id) throws FormatException, IOException { LOGGER.debug("{}.initFile({})", this.getClass().getName(), id); if (currentId != null) { String[] s = getUsedFiles(); for (int i=0; i<s.length; i++) { if (id.equals(s[i])) return; } } coreIndex = 0; series = 0; close(); currentId = id; metadata = new Hashtable<String, Object>(); core = new ArrayList<CoreMetadata>(); CoreMetadata core0 = new CoreMetadata(); core.add(core0); core0.orderCertain = true; // reinitialize the MetadataStore // NB: critical for metadata conversion to work properly! getMetadataStore().createRoot(); } /** Returns true if the given file name is in the used files list. */ protected boolean isUsedFile(String file) { String[] usedFiles = getUsedFiles(); for (String used : usedFiles) { if (used.equals(file)) return true; String path = new Location(file).getAbsolutePath(); if (used.equals(path)) return true; } return false; } /** Adds an entry to the specified Hashtable. */ protected void addMeta(String key, Object value, Hashtable<String, Object> meta) { if (key == null || value == null || getMetadataOptions().getMetadataLevel() == MetadataLevel.MINIMUM) { return; } key = key.trim(); boolean string = value instanceof String || value instanceof Character; // string value, if passed in value is a string String val = string ? String.valueOf(value) : null; if (filterMetadata || (saveOriginalMetadata && (getMetadataStore() instanceof OMEXMLMetadata))) { // filter out complex data types boolean simple = string || value instanceof Number || value instanceof Boolean; if (!simple) return; // verify key & value are reasonable length int maxLen = 8192; if (key.length() > maxLen) return; if (string && val.length() > maxLen) return; // remove all non-printable characters key = DataTools.sanitize(key); if (string) val = DataTools.sanitize(val); // verify key contains at least one alphabetic character if (!key.matches(".*[a-zA-Z].*")) return; // remove <, > and & to prevent XML parsing errors String[] invalidSequences = new String[] { "<", ">", "&", "<", ">", "&" }; for (int i=0; i<invalidSequences.length; i++) { if (key.indexOf(invalidSequences[i]) >= 0) { key = key.replaceAll(invalidSequences[i], ""); } if (string && val.indexOf(invalidSequences[i]) >= 0) { val = val.replaceAll(invalidSequences[i], ""); } } // verify key & value are not empty if (key.length() == 0) return; if (string && val.trim().length() == 0) return; if (string) value = val; } meta.put(key, val == null ? value : val); } /** Adds an entry to the global metadata table. */ protected void addGlobalMeta(String key, Object value) { addMeta(key, value, metadata); } /** Adds an entry to the global metadata table. */ protected void addGlobalMeta(String key, boolean value) { addGlobalMeta(key, new Boolean(value)); } /** Adds an entry to the global metadata table. */ protected void addGlobalMeta(String key, byte value) { addGlobalMeta(key, new Byte(value)); } /** Adds an entry to the global metadata table. */ protected void addGlobalMeta(String key, short value) { addGlobalMeta(key, new Short(value)); } /** Adds an entry to the global metadata table. */ protected void addGlobalMeta(String key, int value) { addGlobalMeta(key, new Integer(value)); } /** Adds an entry to the global metadata table. */ protected void addGlobalMeta(String key, long value) { addGlobalMeta(key, new Long(value)); } /** Adds an entry to the global metadata table. */ protected void addGlobalMeta(String key, float value) { addGlobalMeta(key, new Float(value)); } /** Adds an entry to the global metadata table. */ protected void addGlobalMeta(String key, double value) { addGlobalMeta(key, new Double(value)); } /** Adds an entry to the global metadata table. */ protected void addGlobalMeta(String key, char value) { addGlobalMeta(key, new Character(value)); } /** Gets a value from the global metadata table. */ protected Object getGlobalMeta(String key) { return metadata.get(key); } /** * Add the given key/value pair to the given hashtable. * If the key already exists, a list will be stored in the hashtable * and the value will be appended to the list. * @param key the key to store in the hashtable * @param value the value to store in the hashtable or list * @param meta the hashtable in which to store the key/value */ protected void addMetaList(String key, Object value, Hashtable<String, Object> meta) { Vector list = (Vector) meta.get(key); meta.remove(key); addMeta(key, value, meta); Object newValue = meta.get(key); meta.remove(key); if (newValue != null) { if (list == null) { list = new Vector(); } list.add(newValue); meta.put(key, list); } else if (list != null) { meta.put(key, list); } } /** * Add the given key/value pair to the global metadata hashtable. * If the key already exists, a list will be stored in the hashtable * and the value will be appended to the list. * @param key the key to store in the hashtable * @param value the value to store in the hashtable or list */ protected void addGlobalMetaList(String key, Object value) { addMetaList(key, value, metadata); } /** * Add the given key/value pair to the current series metadata hashtable. * If the key already exists, a list will be stored in the hashtable * and the value will be appended to the list. */ protected void addSeriesMetaList(String key, Object value) { addMetaList(key, value, core.get(getCoreIndex()).seriesMetadata); } /** * Call {@link #updateMetadataLists(Hashtable)} on * all metadata hashtables. */ protected void flattenHashtables() { updateMetadataLists(metadata); for (int s=0; s<core.size(); s++) { if (core.get(s).seriesMetadata.size() > 0) { updateMetadataLists(core.get(s).seriesMetadata); } } } /** * For the given metadata hashtable, replace any value that is * a list with one key/value pair per list entry. The new keys * will be the original key with the list index appended. * @param meta the hashtable from which to remove lists */ private void updateMetadataLists(Hashtable<String, Object> meta) { String[] keys = meta.keySet().toArray(new String[meta.size()]); for (String key : keys) { Object v = meta.get(key); if (v instanceof Vector) { Vector list = (Vector) v; int digits = String.valueOf(list.size()).length(); for (int i=0; i<list.size(); i++) { String index = String.valueOf(i + 1); while (index.length() < digits) { index = "0" + index; } meta.put(key + " #" + index, list.get(i)); } meta.remove(key); } } } /** Adds an entry to the metadata table for the current series. */ protected void addSeriesMeta(String key, Object value) { addMeta(key, value, core.get(getCoreIndex()).seriesMetadata); } /** Adds an entry to the metadata table for the current series. */ protected void addSeriesMeta(String key, boolean value) { addSeriesMeta(key, new Boolean(value)); } /** Adds an entry to the metadata table for the current series. */ protected void addSeriesMeta(String key, byte value) { addSeriesMeta(key, new Byte(value)); } /** Adds an entry to the metadata table for the current series. */ protected void addSeriesMeta(String key, short value) { addSeriesMeta(key, new Short(value)); } /** Adds an entry to the metadata table for the current series. */ protected void addSeriesMeta(String key, int value) { addSeriesMeta(key, new Integer(value)); } /** Adds an entry to the metadata table for the current series. */ protected void addSeriesMeta(String key, long value) { addSeriesMeta(key, new Long(value)); } /** Adds an entry to the metadata table for the current series. */ protected void addSeriesMeta(String key, float value) { addSeriesMeta(key, new Float(value)); } /** Adds an entry to the metadata table for the current series. */ protected void addSeriesMeta(String key, double value) { addSeriesMeta(key, new Double(value)); } /** Adds an entry to the metadata table for the current series. */ protected void addSeriesMeta(String key, char value) { addSeriesMeta(key, new Character(value)); } /** Gets an entry from the metadata table for the current series. */ protected Object getSeriesMeta(String key) { return core.get(getCoreIndex()).seriesMetadata.get(key); } /** Reads a raw plane from disk. */ protected byte[] readPlane(RandomAccessInputStream s, int x, int y, int w, int h, byte[] buf) throws IOException { return readPlane(s, x, y, w, h, 0, buf); } /** Reads a raw plane from disk. */ protected byte[] readPlane(RandomAccessInputStream s, int x, int y, int w, int h, int scanlinePad, byte[] buf) throws IOException { int c = getRGBChannelCount(); int bpp = FormatTools.getBytesPerPixel(getPixelType()); if (x == 0 && y == 0 && w == getSizeX() && h == getSizeY() && scanlinePad == 0) { s.read(buf); } else if (x == 0 && w == getSizeX() && scanlinePad == 0) { if (isInterleaved()) { s.skipBytes(y * w * bpp * c); s.read(buf, 0, h * w * bpp * c); } else { int rowLen = w * bpp; for (int channel=0; channel<c; channel++) { s.skipBytes(y * rowLen); s.read(buf, channel * h * rowLen, h * rowLen); if (channel < c - 1) { // no need to skip bytes after reading final channel s.skipBytes((getSizeY() - y - h) * rowLen); } } } } else { int scanlineWidth = getSizeX() + scanlinePad; if (isInterleaved()) { s.skipBytes(y * scanlineWidth * bpp * c); for (int row=0; row<h; row++) { s.skipBytes(x * bpp * c); s.read(buf, row * w * bpp * c, w * bpp * c); if (row < h - 1) { // no need to skip bytes after reading final row s.skipBytes(bpp * c * (scanlineWidth - w - x)); } } } else { for (int channel=0; channel<c; channel++) { s.skipBytes(y * scanlineWidth * bpp); for (int row=0; row<h; row++) { s.skipBytes(x * bpp); s.read(buf, channel * w * h * bpp + row * w * bpp, w * bpp); if (row < h - 1 || channel < c - 1) { // no need to skip bytes after reading final row of final channel s.skipBytes(bpp * (scanlineWidth - w - x)); } } if (channel < c - 1) { // no need to skip bytes after reading final channel s.skipBytes(scanlineWidth * bpp * (getSizeY() - y - h)); } } } } return buf; } /** Return a properly configured loci.formats.meta.FilterMetadata. */ protected MetadataStore makeFilterMetadata() { return new FilterMetadata(getMetadataStore(), isMetadataFiltered()); } // -- IMetadataConfigurable API methods -- /* (non-Javadoc) * @see loci.formats.IMetadataConfigurable#getSupportedMetadataLevels() */ @Override public Set<MetadataLevel> getSupportedMetadataLevels() { Set<MetadataLevel> supportedLevels = new HashSet<MetadataLevel>(); supportedLevels.add(MetadataLevel.ALL); supportedLevels.add(MetadataLevel.NO_OVERLAYS); supportedLevels.add(MetadataLevel.MINIMUM); return supportedLevels; } /* (non-Javadoc) * @see loci.formats.IMetadataConfigurable#getMetadataOptions() */ @Override public MetadataOptions getMetadataOptions() { return metadataOptions; } /* (non-Javadoc) * @see loci.formats.IMetadataConfigurable#setMetadataOptions(loci.formats.in.MetadataOptions) */ @Override public void setMetadataOptions(MetadataOptions options) { this.metadataOptions = options; } // -- IFormatReader API methods -- /** * Checks if a file matches the type of this format reader. * Checks filename suffixes against those known for this format. * If the suffix check is inconclusive and the open parameter is true, * the file is opened and tested with * {@link #isThisType(RandomAccessInputStream)}. * * @param open If true, and the file extension is insufficient to determine * the file type, the (existing) file is opened for further analysis. */ @Override public boolean isThisType(String name, boolean open) { // if file extension ID is insufficient and we can't open the file, give up if (!suffixSufficient && !open) return false; if (suffixNecessary || suffixSufficient) { // it's worth checking the file extension boolean suffixMatch = super.isThisType(name); // if suffix match is required but it doesn't match, failure if (suffixNecessary && !suffixMatch) return false; // if suffix matches and that's all we need, green light it if (suffixMatch && suffixSufficient) return true; } // suffix matching was inconclusive; we need to analyze the file contents if (!open) return false; // not allowed to open any files try { RandomAccessInputStream stream = new RandomAccessInputStream(name); boolean isThisType = isThisType(stream); stream.close(); return isThisType; } catch (IOException exc) { LOGGER.debug("", exc); return false; } } /* @see IFormatReader#isThisType(byte[]) */ @Override public boolean isThisType(byte[] block) { try { RandomAccessInputStream stream = new RandomAccessInputStream(block); boolean isThisType = isThisType(stream); stream.close(); return isThisType; } catch (IOException e) { LOGGER.debug("", e); } return false; } /* @see IFormatReader#isThisType(RandomAccessInputStream) */ @Override public boolean isThisType(RandomAccessInputStream stream) throws IOException { return false; } /* @see IFormatReader#getImageCount() */ @Override public int getImageCount() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).imageCount; } /* @see IFormatReader#isRGB() */ @Override public boolean isRGB() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).rgb; } /* @see IFormatReader#getSizeX() */ @Override public int getSizeX() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).sizeX; } /* @see IFormatReader#getSizeY() */ @Override public int getSizeY() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).sizeY; } /* @see IFormatReader#getSizeZ() */ @Override public int getSizeZ() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).sizeZ; } /* @see IFormatReader#getSizeC() */ @Override public int getSizeC() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).sizeC; } /* @see IFormatReader#getSizeT() */ @Override public int getSizeT() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).sizeT; } /* @see IFormatReader#getPixelType() */ @Override public int getPixelType() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).pixelType; } /* @see IFormatReader#getBitsPerPixel() */ @Override public int getBitsPerPixel() { FormatTools.assertId(currentId, true, 1); if (core.get(getCoreIndex()).bitsPerPixel == 0) { core.get(getCoreIndex()).bitsPerPixel = FormatTools.getBytesPerPixel(getPixelType()) * 8; } return core.get(getCoreIndex()).bitsPerPixel; } /* @see IFormatReader#getEffectiveSizeC() */ @Override public int getEffectiveSizeC() { // NB: by definition, imageCount == effectiveSizeC * sizeZ * sizeT int sizeZT = getSizeZ() * getSizeT(); if (sizeZT == 0) return 0; return getImageCount() / sizeZT; } /* @see IFormatReader#getRGBChannelCount() */ @Override public int getRGBChannelCount() { int effSizeC = getEffectiveSizeC(); if (effSizeC == 0) return 0; return getSizeC() / effSizeC; } /* @see IFormatReader#isIndexed() */ @Override public boolean isIndexed() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).indexed; } /* @see IFormatReader#isFalseColor() */ @Override public boolean isFalseColor() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).falseColor; } /* @see IFormatReader#get8BitLookupTable() */ @Override public byte[][] get8BitLookupTable() throws FormatException, IOException { return null; } /* @see IFormatReader#get16BitLookupTable() */ @Override public short[][] get16BitLookupTable() throws FormatException, IOException { return null; } /* @see IFormatReader#getModuloZ() */ @Override public Modulo getModuloZ() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).moduloZ; } /* @see IFormatReader#getModuloC() */ @Override public Modulo getModuloC() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).moduloC; } /* @see IFormatReader#getModuloT() */ @Override public Modulo getModuloT() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).moduloT; } /* @see IFormatReader#getThumbSizeX() */ @Override public int getThumbSizeX() { FormatTools.assertId(currentId, true, 1); if (core.get(getCoreIndex()).thumbSizeX == 0) { int sx = getSizeX(); int sy = getSizeY(); int thumbSizeX = 0; if (sx < THUMBNAIL_DIMENSION && sy < THUMBNAIL_DIMENSION) thumbSizeX = sx; else if (sx > sy) thumbSizeX = THUMBNAIL_DIMENSION; else if (sy > 0) thumbSizeX = sx * THUMBNAIL_DIMENSION / sy; if (thumbSizeX == 0) thumbSizeX = 1; return thumbSizeX; } return core.get(getCoreIndex()).thumbSizeX; } /* @see IFormatReader#getThumbSizeY() */ @Override public int getThumbSizeY() { FormatTools.assertId(currentId, true, 1); if (core.get(getCoreIndex()).thumbSizeY == 0) { int sx = getSizeX(); int sy = getSizeY(); int thumbSizeY = 1; if (sx < THUMBNAIL_DIMENSION && sy < THUMBNAIL_DIMENSION) thumbSizeY = sy; else if (sy > sx) thumbSizeY = THUMBNAIL_DIMENSION; else if (sx > 0) thumbSizeY = sy * THUMBNAIL_DIMENSION / sx; if (thumbSizeY == 0) thumbSizeY = 1; return thumbSizeY; } return core.get(getCoreIndex()).thumbSizeY; } /* @see IFormatReader.isLittleEndian() */ @Override public boolean isLittleEndian() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).littleEndian; } /* @see IFormatReader#getDimensionOrder() */ @Override public String getDimensionOrder() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).dimensionOrder; } /* @see IFormatReader#isOrderCertain() */ @Override public boolean isOrderCertain() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).orderCertain; } /* @see IFormatReader#isThumbnailSeries() */ @Override public boolean isThumbnailSeries() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).thumbnail; } /* @see IFormatReader#isInterleaved() */ @Override public boolean isInterleaved() { return isInterleaved(0); } /* @see IFormatReader#isInterleaved(int) */ @Override public boolean isInterleaved(int subC) { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).interleaved; } /* @see IFormatReader#openBytes(int) */ @Override public byte[] openBytes(int no) throws FormatException, IOException { return openBytes(no, 0, 0, getSizeX(), getSizeY()); } /* @see IFormatReader#openBytes(int, byte[]) */ @Override public byte[] openBytes(int no, byte[] buf) throws FormatException, IOException { return openBytes(no, buf, 0, 0, getSizeX(), getSizeY()); } /* @see IFormatReader#openBytes(int, int, int, int, int) */ @Override public byte[] openBytes(int no, int x, int y, int w, int h) throws FormatException, IOException { int ch = getRGBChannelCount(); int bpp = FormatTools.getBytesPerPixel(getPixelType()); byte[] newBuffer; try { newBuffer = DataTools.allocate(w, h, ch, bpp); } catch (IllegalArgumentException e) { throw new FormatException("Image plane too large. Only 2GB of data can " + "be extracted at one time. You can workaround the problem by opening " + "the plane in tiles; for further details, see: " + "http://www.openmicroscopy.org/site/support/bio-formats/about/" + "bug-reporting.html#common-issues-to-check", e); } return openBytes(no, newBuffer, x, y, w, h); } /* @see IFormatReader#openBytes(int, byte[], int, int, int, int) */ @Override public abstract byte[] openBytes(int no, byte[] buf, int x, int y, int w, int h) throws FormatException, IOException; /* @see IFormatReader#openPlane(int, int, int, int, int int) */ @Override public Object openPlane(int no, int x, int y, int w, int h) throws FormatException, IOException { // NB: Readers use byte arrays by default as the native type. return openBytes(no, x, y, w, h); } /* @see IFormatReader#openThumbBytes(int) */ @Override public byte[] openThumbBytes(int no) throws FormatException, IOException { FormatTools.assertId(currentId, true, 1); return FormatTools.openThumbBytes(this, no); } /* @see IFormatReader#close(boolean) */ @Override public void close(boolean fileOnly) throws IOException { if (in != null) in.close(); if (!fileOnly) { in = null; currentId = null; resolution = 0; core = null; } } /* @see IFormatReader#getSeriesCount() */ @Override public int getSeriesCount() { FormatTools.assertId(currentId, true, 1); if (hasFlattenedResolutions()) { return core.size(); } return coreIndexToSeries(core.size() - 1) + 1; } /* @see IFormatReader#setSeries(int) */ @Override public void setSeries(int no) { coreIndex = seriesToCoreIndex(no); series = no; resolution = 0; } /* @see IFormatReader#getSeries() */ @Override public int getSeries() { return series; } /* @see IFormatReader#setGroupFiles(boolean) */ @Override public void setGroupFiles(boolean groupFiles) { FormatTools.assertId(currentId, false, 1); group = groupFiles; } /* @see IFormatReader#isGroupFiles() */ @Override public boolean isGroupFiles() { return group; } /* @see IFormatReader#fileGroupOption(String) */ @Override public int fileGroupOption(String id) throws FormatException, IOException { return FormatTools.CANNOT_GROUP; } /* @see IFormatReader#isMetadataComplete() */ @Override public boolean isMetadataComplete() { FormatTools.assertId(currentId, true, 1); return core.get(getCoreIndex()).metadataComplete; } /* @see IFormatReader#setNormalized(boolean) */ @Override public void setNormalized(boolean normalize) { FormatTools.assertId(currentId, false, 1); normalizeData = normalize; } /* @see IFormatReader#isNormalized() */ @Override public boolean isNormalized() { return normalizeData; } /* @see IFormatReader#setOriginalMetadataPopulated(boolean) */ @Override public void setOriginalMetadataPopulated(boolean populate) { FormatTools.assertId(currentId, false, 1); saveOriginalMetadata = populate; } /* @see IFormatReader#isOriginalMetadataPopulated() */ @Override public boolean isOriginalMetadataPopulated() { return saveOriginalMetadata; } /* @see IFormatReader#getUsedFiles() */ @Override public String[] getUsedFiles() { return getUsedFiles(false); } /* @see IFormatReader#getUsedFiles() */ @Override public String[] getUsedFiles(boolean noPixels) { int oldSeries = getSeries(); Vector<String> files = new Vector<String>(); for (int i=0; i<getSeriesCount(); i++) { setSeries(i); String[] s = getSeriesUsedFiles(noPixels); if (s != null) { for (String file : s) { if (getSeriesCount() == 1 || !files.contains(file)) { files.add(file); } } } } setSeries(oldSeries); return files.toArray(new String[files.size()]); } /* @see IFormatReader#getSeriesUsedFiles() */ @Override public String[] getSeriesUsedFiles() { return getSeriesUsedFiles(false); } /* @see IFormatReader#getSeriesUsedFiles(boolean) */ @Override public String[] getSeriesUsedFiles(boolean noPixels) { return noPixels ? null : new String[] {currentId}; } /* @see IFormatReader#getAdvancedUsedFiles(boolean) */ @Override public FileInfo[] getAdvancedUsedFiles(boolean noPixels) { String[] files = getUsedFiles(noPixels); if (files == null) return null; FileInfo[] infos = new FileInfo[files.length]; for (int i=0; i<infos.length; i++) { infos[i] = new FileInfo(); infos[i].filename = files[i]; infos[i].reader = this.getClass(); infos[i].usedToInitialize = files[i].endsWith(getCurrentFile()); } return infos; } /* @see IFormatReader#getAdvancedSeriesUsedFiles(boolean) */ @Override public FileInfo[] getAdvancedSeriesUsedFiles(boolean noPixels) { String[] files = getSeriesUsedFiles(noPixels); if (files == null) return null; FileInfo[] infos = new FileInfo[files.length]; for (int i=0; i<infos.length; i++) { infos[i] = new FileInfo(); infos[i].filename = files[i]; infos[i].reader = this.getClass(); infos[i].usedToInitialize = files[i].endsWith(getCurrentFile()); } return infos; } /* @see IFormatReader#getCurrentFile() */ @Override public String getCurrentFile() { return currentId; } /* @see IFormatReader#getIndex(int, int, int) */ @Override public int getIndex(int z, int c, int t) { FormatTools.assertId(currentId, true, 1); return FormatTools.getIndex(this, z, c, t); } /* @see IFormatReader#getIndex(int, int, int, int, int, int) */ public int getIndex(int z, int c, int t, int moduloZ, int moduloC, int moduloT) { FormatTools.assertId(currentId, true, 1); return FormatTools.getIndex(this, z, c, t, moduloZ, moduloC, moduloT); } /* @see IFormatReader#getZCTCoords(int) */ @Override public int[] getZCTCoords(int index) { FormatTools.assertId(currentId, true, 1); return FormatTools.getZCTCoords(this, index); } /* @see IFormatReader#getZCTModuloCoords(int) */ public int[] getZCTModuloCoords(int index) { FormatTools.assertId(currentId, true, 1); return FormatTools.getZCTModuloCoords(this, index); } /* @see IFormatReader#getMetadataValue(String) */ @Override public Object getMetadataValue(String field) { FormatTools.assertId(currentId, true, 1); flattenHashtables(); return getGlobalMeta(field); } /* @see IFormatReader#getSeriesMetadataValue(String) */ @Override public Object getSeriesMetadataValue(String field) { FormatTools.assertId(currentId, true, 1); flattenHashtables(); return getSeriesMeta(field); } /* @see IFormatReader#getGlobalMetadata() */ @Override public Hashtable<String, Object> getGlobalMetadata() { FormatTools.assertId(currentId, true, 1); flattenHashtables(); return metadata; } /* @see IFormatReader#getSeriesMetadata() */ @Override public Hashtable<String, Object> getSeriesMetadata() { FormatTools.assertId(currentId, true, 1); if (core.get(getCoreIndex()).seriesMetadata.size() > 0) { flattenHashtables(); } return core.get(getCoreIndex()).seriesMetadata; } /* @see IFormatReader#getCoreMetadataList() */ @Override public List<CoreMetadata> getCoreMetadataList() { FormatTools.assertId(currentId, true, 1); return core; } /* @see IFormatReader#setMetadataFiltered(boolean) */ @Override public void setMetadataFiltered(boolean filter) { FormatTools.assertId(currentId, false, 1); filterMetadata = filter; } /* @see IFormatReader#isMetadataFiltered() */ @Override public boolean isMetadataFiltered() { return filterMetadata; } /* @see IFormatReader#setMetadataStore(MetadataStore) */ @Override public void setMetadataStore(MetadataStore store) { FormatTools.assertId(currentId, false, 1); if (store == null) { throw new IllegalArgumentException("Metadata object cannot be null; " + "use loci.formats.meta.DummyMetadata instead"); } metadataStore = store; } /* @see IFormatReader#getMetadataStore() */ @Override public MetadataStore getMetadataStore() { return metadataStore; } /* @see IFormatReader#getMetadataStoreRoot() */ @Override public Object getMetadataStoreRoot() { FormatTools.assertId(currentId, true, 1); return getMetadataStore().getRoot(); } /* @see IFormatReader#getUnderlyingReaders() */ @Override public IFormatReader[] getUnderlyingReaders() { return null; } /* @see IFormatReader#isSingleFile(String) */ @Override public boolean isSingleFile(String id) throws FormatException, IOException { return true; } /* @see IFormatReader#getRequiredDirectories(String[]) */ @Override public int getRequiredDirectories(String[] files) throws FormatException, IOException { return 0; } /* @see IFormatReader#getDatasetStructureDescription() */ @Override public String getDatasetStructureDescription() { return datasetDescription; } /* @see IFormatReader#hasCompanionFiles() */ @Override public boolean hasCompanionFiles() { return hasCompanionFiles; } /* @see IFormatReader#getPossibleDomains(String) */ @Override public String[] getPossibleDomains(String id) throws FormatException, IOException { return domains; } /* @see IFormatReader#getDomains() */ @Override public String[] getDomains() { FormatTools.assertId(currentId, true, 1); return domains; } /* @see IFormatReader#getOptimalTileWidth() */ @Override public int getOptimalTileWidth() { FormatTools.assertId(currentId, true, 1); return getSizeX(); } /* @see IFormatReader#getOptimalTileHeight() */ @Override public int getOptimalTileHeight() { FormatTools.assertId(currentId, true, 1); int bpp = FormatTools.getBytesPerPixel(getPixelType()); int maxHeight = (1024 * 1024) / (getSizeX() * getRGBChannelCount() * bpp); return (int) Math.min(maxHeight, getSizeY()); } // -- Sub-resolution API methods -- @Override public int seriesToCoreIndex(int series) { if (hasFlattenedResolutions()) { // coreIndex and series are identical if (series < 0 || series >= core.size()) { throw new IllegalArgumentException("Invalid series: " + series); } return series; } // Use corresponding coreIndex if (this.series == series) { return coreIndex - resolution; } int index = 0; for (int i = 0; i < series && index < core.size(); i++) { if (core.get(i) != null) index += core.get(index).resolutionCount; else throw new IllegalArgumentException("Invalid series (null core["+i+"]: " + series); } if (index < 0 || index >= core.size()) { throw new IllegalArgumentException("Invalid series: " + series + " index="+index); } return index; } @Override public int coreIndexToSeries(int index) { if (index < 0 || index >= core.size()) { throw new IllegalArgumentException("Invalid index: " + index); } if (hasFlattenedResolutions()) { // coreIndex and series are identical return index; } // Use corresponding series if (coreIndex == index) { return series; } // Convert from non-flattened coreIndex to flattened series int series = 0; for (int i=0; i<index;) { if (core.get(i) != null) { int nextSeries = i + core.get(i).resolutionCount; if (index < nextSeries) break; i = nextSeries; } else { throw new IllegalArgumentException("Invalid coreIndex (null core["+i+"]: " + index); } series++; } return series; } /* @see IFormatReader#getResolutionCount() */ @Override public int getResolutionCount() { FormatTools.assertId(currentId, true, 1); if (hasFlattenedResolutions()) { return 1; } return core.get(seriesToCoreIndex(getSeries())).resolutionCount; } /* @see IFormatReader#setResolution(int) */ @Override public void setResolution(int no) { if (no < 0 || no >= getResolutionCount()) { throw new IllegalArgumentException("Invalid resolution: " + no); } coreIndex = seriesToCoreIndex(getSeries()) + no; resolution = no; } /* @see IFormatReader#getResolution() */ @Override public int getResolution() { return resolution; } /* @see IFormatReader#hasFlattenedResolutions */ @Override public boolean hasFlattenedResolutions() { return flattenedResolutions; } /* @see IFormatReader#setFlattenedResolutions(boolean) */ @Override public void setFlattenedResolutions(boolean flattened) { FormatTools.assertId(currentId, false, 1); flattenedResolutions = flattened; } @Override public int getCoreIndex() { return coreIndex; } /* @see IFormatHandler#setCoreIndex(int) */ @Override public void setCoreIndex(int no) { if (no < 0 || no >= core.size()) { throw new IllegalArgumentException("Invalid series: " + no); } series = coreIndexToSeries(no); coreIndex = no; resolution = no - seriesToCoreIndex(series); } // -- IFormatHandler API methods -- /* @see IFormatHandler#isThisType(String) */ @Override public boolean isThisType(String name) { // if necessary, open the file for further analysis return isThisType(name, true); } /** * Initializes a reader from the input file name. * * Calls {@link #initFile(String id)} to initializes the input file, reads * all of the metadata and sets the reader up for reading planes. * The performance of this method depends on the format and can be up to * several minutes for large file sets. * * @param id a {@link String} specifying the path to the file */ @Override public void setId(String id) throws FormatException, IOException { LOGGER.debug("{} initializing {}", this.getClass().getSimpleName(), id); if (currentId == null || !new Location(id).getAbsolutePath().equals( new Location(currentId).getAbsolutePath())) { initFile(id); MetadataStore store = getMetadataStore(); if (saveOriginalMetadata) { if (store instanceof OMEXMLMetadata) { setupService(); Hashtable<String, Object> allMetadata = new Hashtable<String, Object>(); allMetadata.putAll(metadata); for (int series=0; series<getSeriesCount(); series++) { String name = "Series " + series; try { String realName = ((IMetadata) store).getImageName(series); if (realName != null && realName.trim().length() != 0) { name = realName; } } catch (Exception e) { } setSeries(series); MetadataTools.merge(getSeriesMetadata(), allMetadata, name + " "); } setSeries(0); service.populateOriginalMetadata((OMEXMLMetadata) store, allMetadata); } } if (store instanceof OMEXMLMetadata) { ((OMEXMLMetadata) store).resolveReferences(); setupService(); for (int series=0; series<getSeriesCount(); series++) { setSeries(series); if (getModuloZ().length() > 1 || getModuloC().length() > 1 || getModuloT().length() > 1) { service.addModuloAlong( (OMEXMLMetadata) store, core.get(series), series); } } setSeries(0); } } } /** Initialize the OMEXMLService needed by {@link #setId(String)} */ private void setupService() { try { if (factory == null) factory = new ServiceFactory(); if (service == null) { service = factory.getInstance(OMEXMLService.class); } } catch (DependencyException e) { LOGGER.warn("OMEXMLService not available.", e); } } /* @see IFormatHandler#close() */ @Override public void close() throws IOException { close(false); } // -- Metadata enumeration convenience methods -- /** * Retrieves an {@link ome.xml.model.enums.AcquisitionMode} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected AcquisitionMode getAcquisitionMode(String value) throws FormatException { AcquisitionModeEnumHandler handler = new AcquisitionModeEnumHandler(); try { return (AcquisitionMode) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("AcquisitionMode creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.ArcType} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected ArcType getArcType(String value) throws FormatException { ArcTypeEnumHandler handler = new ArcTypeEnumHandler(); try { return (ArcType) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("ArcType creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.Binning} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected Binning getBinning(String value) throws FormatException { BinningEnumHandler handler = new BinningEnumHandler(); try { return (Binning) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("Binning creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.Compression} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected Compression getCompression(String value) throws FormatException { CompressionEnumHandler handler = new CompressionEnumHandler(); try { return (Compression) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("Compression creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.ContrastMethod} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected ContrastMethod getContrastMethod(String value) throws FormatException { ContrastMethodEnumHandler handler = new ContrastMethodEnumHandler(); try { return (ContrastMethod) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("ContrastMethod creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.Correction} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected Correction getCorrection(String value) throws FormatException { CorrectionEnumHandler handler = new CorrectionEnumHandler(); try { return (Correction) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("Correction creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.DetectorType} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected DetectorType getDetectorType(String value) throws FormatException { DetectorTypeEnumHandler handler = new DetectorTypeEnumHandler(); try { return (DetectorType) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("DetectorType creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.DimensionOrder} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected DimensionOrder getDimensionOrder(String value) throws FormatException { DimensionOrderEnumHandler handler = new DimensionOrderEnumHandler(); try { return (DimensionOrder) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("DimensionOrder creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.ExperimentType} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected ExperimentType getExperimentType(String value) throws FormatException { ExperimentTypeEnumHandler handler = new ExperimentTypeEnumHandler(); try { return (ExperimentType) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("ExperimentType creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.FilamentType} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected FilamentType getFilamentType(String value) throws FormatException { FilamentTypeEnumHandler handler = new FilamentTypeEnumHandler(); try { return (FilamentType) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("FilamentType creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.FillRule} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected FillRule getFillRule(String value) throws FormatException { FillRuleEnumHandler handler = new FillRuleEnumHandler(); try { return (FillRule) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("FillRule creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.FilterType} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected FilterType getFilterType(String value) throws FormatException { FilterTypeEnumHandler handler = new FilterTypeEnumHandler(); try { return (FilterType) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("FilterType creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.FontFamily} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected FontFamily getFontFamily(String value) throws FormatException { FontFamilyEnumHandler handler = new FontFamilyEnumHandler(); try { return (FontFamily) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("FontFamily creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.FontStyle} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected FontStyle getFontStyle(String value) throws FormatException { FontStyleEnumHandler handler = new FontStyleEnumHandler(); try { return (FontStyle) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("FontStyle creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.IlluminationType} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected IlluminationType getIlluminationType(String value) throws FormatException { IlluminationTypeEnumHandler handler = new IlluminationTypeEnumHandler(); try { return (IlluminationType) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("IlluminationType creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.Immersion} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected Immersion getImmersion(String value) throws FormatException { ImmersionEnumHandler handler = new ImmersionEnumHandler(); try { return (Immersion) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("Immersion creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.LaserMedium} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected LaserMedium getLaserMedium(String value) throws FormatException { LaserMediumEnumHandler handler = new LaserMediumEnumHandler(); try { return (LaserMedium) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("LaserMedium creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.LaserType} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected LaserType getLaserType(String value) throws FormatException { LaserTypeEnumHandler handler = new LaserTypeEnumHandler(); try { return (LaserType) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("LaserType creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.LineCap} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected LineCap getLineCap(String value) throws FormatException { LineCapEnumHandler handler = new LineCapEnumHandler(); try { return (LineCap) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("LineCap creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.Marker} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected Marker getMarker(String value) throws FormatException { MarkerEnumHandler handler = new MarkerEnumHandler(); try { return (Marker) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("Marker creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.Medium} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected Medium getMedium(String value) throws FormatException { MediumEnumHandler handler = new MediumEnumHandler(); try { return (Medium) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("Medium creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.MicrobeamManipulationType} * enumeration value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected MicrobeamManipulationType getMicrobeamManipulationType(String value) throws FormatException { MicrobeamManipulationTypeEnumHandler handler = new MicrobeamManipulationTypeEnumHandler(); try { return (MicrobeamManipulationType) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("MicrobeamManipulationType creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.MicroscopeType} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected MicroscopeType getMicroscopeType(String value) throws FormatException { MicroscopeTypeEnumHandler handler = new MicroscopeTypeEnumHandler(); try { return (MicroscopeType) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("MicroscopeType creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.NamingConvention} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected NamingConvention getNamingConvention(String value) throws FormatException { NamingConventionEnumHandler handler = new NamingConventionEnumHandler(); try { return (NamingConvention) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("NamingConvention creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.PixelType} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected PixelType getPixelType(String value) throws FormatException { PixelTypeEnumHandler handler = new PixelTypeEnumHandler(); try { return (PixelType) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("PixelType creation failed", e); } } /** * Retrieves an {@link ome.xml.model.enums.Pulse} enumeration * value for the given String. * * @throws ome.xml.model.enums.EnumerationException if an appropriate * enumeration value is not found. */ protected Pulse getPulse(String value) throws FormatException { PulseEnumHandler handler = new PulseEnumHandler(); try { return (Pulse) handler.getEnumeration(value); } catch (EnumerationException e) { throw new FormatException("Pulse creation failed", e); } } /** * Construct an {@link ome.xml.model.AffineTransform} corresponding to * the given angle. * @param theta the angle of rotation in radians */ protected AffineTransform getRotationTransform(double theta) { AffineTransform transform = new AffineTransform(); transform.setA02(0.0); transform.setA12(0.0); transform.setA00(Math.cos(theta)); transform.setA11(Math.cos(theta)); transform.setA01(Math.sin(theta)); transform.setA10(-1 * Math.sin(theta)); return transform; } }