//
// ImprovisionTiffReader.java
//
/*
LOCI Bio-Formats package for reading and converting biological file formats.
Copyright (C) 2005-@year@ Melissa Linkert, Curtis Rueden, Chris Allan,
Eric Kjellman and Brian Loranger.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Library 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 Library General Public License for more details.
You should have received a copy of the GNU Library 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 java.util.*;
import loci.formats.*;
/**
* ImprovisionTiffReader is the file format reader for
* Improvision TIFF files.
*
* <dl><dt><b>Source code:</b></dt>
* <dd><a href="https://skyking.microscopy.wisc.edu/trac/java/browser/trunk/loci/formats/in/ImprovisionTiffReader.java">Trac</a>,
* <a href="https://skyking.microscopy.wisc.edu/svn/java/trunk/loci/formats/in/ImprovisionTiffReader.java">SVN</a></dd></dl>
*/
public class ImprovisionTiffReader extends BaseTiffReader {
// -- Fields --
private String[] cNames;
private int pixelSizeT;
// -- Constructor --
public ImprovisionTiffReader() {
super("Improvision TIFF", new String[] {"tif", "tiff"});
}
// -- IFormatHandler API methods --
/* @see loci.formats.IFormatHandler#isThisType(String, boolean) */
public boolean isThisType(String name, boolean open) {
if (!super.isThisType(name, open)) return false; // check extension
if (!open) return true; // not allowed to check the file contents
// just checking the filename isn't enough to differentiate between
// Improvision and regular TIFF; open the file and check more thoroughly
try {
RandomAccessStream ras = new RandomAccessStream(name);
Hashtable ifd = TiffTools.getFirstIFD(ras);
ras.close();
if (ifd == null) return false;
String comment =
(String) ifd.get(new Integer(TiffTools.IMAGE_DESCRIPTION));
return comment == null ? false : comment.indexOf("Improvision") != -1;
}
catch (IOException exc) {
if (debug) trace(exc);
return false;
}
}
// -- Internal BaseTiffReader API methods --
/* @see BaseTiffReader#initStandardMetadata() */
protected void initStandardMetadata() throws FormatException, IOException {
super.initStandardMetadata();
put("Improvision", "yes");
// parse key/value pairs in the comment
String comment = (String) getMeta("Comment");
if (comment != null) {
StringTokenizer st = new StringTokenizer(comment, "\n");
while (st.hasMoreTokens()) {
String line = st.nextToken();
int equals = line.indexOf("=");
if (equals < 0) continue;
String key = line.substring(0, equals);
String value = line.substring(equals + 1);
addMeta(key, value);
}
metadata.remove("Comment");
}
String tz = (String) getMeta("TotalZPlanes");
String tc = (String) getMeta("TotalChannels");
String tt = (String) getMeta("TotalTimepoints");
if (tz == null) tz = "1";
if (tc == null) tc = "1";
if (tt == null) tt = "1";
core.sizeZ[0] = Integer.parseInt(tz);
core.sizeC[0] = Integer.parseInt(tc);
core.sizeT[0] = Integer.parseInt(tt);
if (core.sizeZ[0] * core.sizeC[0] * core.sizeT[0] < core.imageCount[0]) {
core.sizeC[0] = core.imageCount[0];
}
// parse each of the comments to determine axis ordering
long[] stamps = new long[ifds.length];
int[][] coords = new int[ifds.length][3];
cNames = new String[core.sizeC[0]];
for (int i=0; i<ifds.length; i++) {
comment = (String) TiffTools.getIFDValue(ifds[i],
TiffTools.IMAGE_DESCRIPTION);
comment = comment.replaceAll("\r\n", "\n");
comment = comment.replaceAll("\r", "\n");
StringTokenizer st = new StringTokenizer(comment, "\n");
String channelName = null;
while (st.hasMoreTokens()) {
String line = st.nextToken();
int equals = line.indexOf("=");
if (equals < 0) continue;
String key = line.substring(0, equals);
String value = line.substring(equals + 1);
if (key.equals("TimeStampMicroSeconds")) {
stamps[i] = Long.parseLong(value);
}
else if (key.equals("ZPlane")) coords[i][0] = Integer.parseInt(value);
else if (key.equals("ChannelNo")) {
coords[i][1] = Integer.parseInt(value);
}
else if (key.equals("TimepointName")) {
coords[i][2] = Integer.parseInt(value);
}
else if (key.equals("ChannelName")) {
channelName = value;
}
else if (key.equals("ChannelNo")) {
int ndx = Integer.parseInt(value);
if (cNames[ndx] == null) cNames[ndx] = channelName;
}
}
}
// determine average time per plane
long sum = 0;
for (int i=1; i<stamps.length; i++) {
long diff = stamps[i] - stamps[i - 1];
if (diff > 0) sum += diff;
}
pixelSizeT = (int) (sum / core.sizeT[0]);
// determine dimension order
core.currentOrder[0] = "XY";
for (int i=1; i<coords.length; i++) {
int zDiff = coords[i][0] - coords[i - 1][0];
int cDiff = coords[i][1] - coords[i - 1][1];
int tDiff = coords[i][2] - coords[i - 1][2];
if (zDiff > 0 && core.currentOrder[0].indexOf("Z") < 0) {
core.currentOrder[0] += "Z";
}
if (cDiff > 0 && core.currentOrder[0].indexOf("C") < 0) {
core.currentOrder[0] += "C";
}
if (tDiff > 0 && core.currentOrder[0].indexOf("T") < 0) {
core.currentOrder[0] += "T";
}
if (core.currentOrder[0].length() == 5) break;
}
if (core.currentOrder[0].indexOf("Z") < 0) core.currentOrder[0] += "Z";
if (core.currentOrder[0].indexOf("C") < 0) core.currentOrder[0] += "C";
if (core.currentOrder[0].indexOf("T") < 0) core.currentOrder[0] += "T";
}
/* @see BaseTiffReader#initMetadataStore() */
protected void initMetadataStore() {
super.initMetadataStore();
MetadataStore store = getMetadataStore();
FormatTools.populatePixels(store, this);
float fx = Float.parseFloat((String) getMeta("XCalibrationMicrons"));
float fy = Float.parseFloat((String) getMeta("YCalibrationMicrons"));
float fz = Float.parseFloat((String) getMeta("ZCalibrationMicrons"));
store.setDimensions(new Float(fx), new Float(fy), new Float(fz),
null, new Float(pixelSizeT / 1000000.0), null);
}
}