//
// GelReader.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
*/
package loci.formats.in;
import java.io.IOException;
import loci.common.DataTools;
import loci.common.DateTools;
import loci.common.RandomAccessInputStream;
import loci.formats.FormatException;
import loci.formats.FormatTools;
import loci.formats.MetadataTools;
import loci.formats.meta.MetadataStore;
import ome.xml.model.primitives.PositiveFloat;
import loci.formats.tiff.IFD;
import loci.formats.tiff.IFDList;
import loci.formats.tiff.TiffParser;
import loci.formats.tiff.TiffRational;
/**
* GelReader is the file format reader for
* Molecular Dynamics GEL TIFF files.
*
* <dl><dt><b>Source code:</b></dt>
* <dd><a href="http://trac.openmicroscopy.org.uk/ome/browser/bioformats.git/components/bio-formats/src/loci/formats/in/GelReader.java">Trac</a>,
* <a href="http://git.openmicroscopy.org/?p=bioformats.git;a=blob;f=components/bio-formats/src/loci/formats/in/GelReader.java;hb=HEAD">Gitweb</a></dd></dl>
*
* @author Melissa Linkert melissa at glencoesoftware.com
*/
public class GelReader extends BaseTiffReader {
// -- Constants --
public static final String DATE_FORMAT = "yyyy:MM:dd";
public static final String TIME_FORMAT = "HH:mm:ss";
public static final String DATE_TIME_FORMAT = DATE_FORMAT + " " + TIME_FORMAT;
public static final String[] FORMATS =
new String[] {DATE_TIME_FORMAT, DATE_FORMAT, TIME_FORMAT};
// GEL TIFF private IFD tags.
private static final int MD_FILETAG = 33445;
private static final int MD_SCALE_PIXEL = 33446;
private static final int MD_LAB_NAME = 33448;
private static final int MD_SAMPLE_INFO = 33449;
private static final int MD_PREP_DATE = 33450;
private static final int MD_PREP_TIME = 33451;
private static final int MD_FILE_UNITS = 33452;
// Scaling options
private static final int SQUARE_ROOT = 2;
private static final int LINEAR = 128;
// -- Fields --
private long fmt;
// -- Constructor --
/** Constructs a new GEL reader. */
public GelReader() {
super("Amersham Biosciences GEL", new String[] {"gel"});
domains = new String[] {FormatTools.GEL_DOMAIN};
}
// -- IFormatReader API methods --
/* @see loci.formats.IFormatReader#isThisType(RandomAccessInputStream) */
public boolean isThisType(RandomAccessInputStream stream) throws IOException {
TiffParser parser = new TiffParser(stream);
parser.setDoCaching(false);
IFD ifd = parser.getFirstIFD();
if (ifd == null) return false;
return ifd.containsKey(MD_FILETAG);
}
/**
* @see loci.formats.IFormatReader#openBytes(int, byte[], int, int, int, int)
*/
public byte[] openBytes(int no, byte[] buf, int x, int y, int w, int h)
throws FormatException, IOException
{
IFD ifd = ifds.get(no);
if (fmt == SQUARE_ROOT) {
float scale =
((TiffRational) ifd.getIFDValue(MD_SCALE_PIXEL)).floatValue();
byte[] tmp = new byte[buf.length];
// DO NOT call super.openBytes here. MinimalTiffReader will interpret
// the pixels as half-floats, when really they are unsigned shorts.
tiffParser.getSamples(ifds.get(no), tmp, x, y, w, h);
int originalBytes = ifd.getBitsPerSample()[0] / 8;
for (int i=0; i<tmp.length/4; i++) {
long value = DataTools.bytesToShort(tmp, i*originalBytes,
originalBytes, isLittleEndian());
long square = value * value;
float pixel = square * scale;
DataTools.unpackBytes(Float.floatToIntBits(pixel), buf, i*4, 4,
isLittleEndian());
}
}
else super.openBytes(no, buf, x, y, w, h);
return buf;
}
// -- Internal BaseTiffReader API methods --
/* @see BaseTiffReader#initMetadata() */
protected void initMetadata() throws FormatException, IOException {
ifds = tiffParser.getIFDs();
if (ifds.size() > 1) {
IFDList tmpIFDs = ifds;
ifds = new IFDList();
for (int i=0; i<tmpIFDs.size()/2; i++) {
IFD ifd = new IFD();
ifds.add(ifd);
ifd.putAll(tmpIFDs.get(i*2 + 1));
ifd.putAll(tmpIFDs.get(i*2));
tiffParser.fillInIFD(ifd);
}
}
super.initStandardMetadata();
IFD firstIFD = ifds.get(0);
tiffParser.fillInIFD(firstIFD);
fmt = firstIFD.getIFDLongValue(MD_FILETAG, LINEAR);
if (fmt == SQUARE_ROOT) core[0].pixelType = FormatTools.FLOAT;
TiffRational scale = (TiffRational) firstIFD.getIFDValue(MD_SCALE_PIXEL);
if (scale == null) scale = new TiffRational(1, 1);
core[0].imageCount = ifds.size();
core[0].sizeT = getImageCount();
// ignore MD_COLOR_TABLE
String info = firstIFD.getIFDStringValue(MD_SAMPLE_INFO);
String prepDate = firstIFD.getIFDStringValue(MD_PREP_DATE);
String prepTime = firstIFD.getIFDStringValue(MD_PREP_TIME);
if (getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) {
String units = firstIFD.getIFDStringValue(MD_FILE_UNITS);
String lab = firstIFD.getIFDStringValue(MD_LAB_NAME);
addGlobalMeta("Scale factor", scale);
addGlobalMeta("Lab name", lab);
addGlobalMeta("Sample info", info);
addGlobalMeta("Date prepared", prepDate);
addGlobalMeta("Time prepared", prepTime);
addGlobalMeta("File units", units);
addGlobalMeta("Data format",
fmt == SQUARE_ROOT ? "square root" : "linear");
}
MetadataStore store = makeFilterMetadata();
MetadataTools.populatePixels(store, this);
String parsedDate = DateTools.formatDate(prepDate, FORMATS);
String parsedTime = DateTools.formatDate(prepTime, FORMATS);
if (parsedDate != null) {
store.setImageAcquiredDate(parsedDate, 0);
}
else if (parsedTime != null) {
store.setImageAcquiredDate(parsedTime, 0);
}
else {
MetadataTools.setDefaultCreationDate(store, getCurrentFile(), 0);
}
if (getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) {
Double pixelSize = new Double(scale.doubleValue());
store.setPixelsPhysicalSizeX(new PositiveFloat(pixelSize), 0);
store.setPixelsPhysicalSizeY(new PositiveFloat(pixelSize), 0);
}
}
}