//
// MicromanagerReader.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.*;
import java.util.*;
import loci.formats.*;
/**
* MicromanagerReader is the file format reader for Micro-Manager files.
*
* <dl><dt><b>Source code:</b></dt>
* <dd><a href="https://skyking.microscopy.wisc.edu/trac/java/browser/trunk/loci/formats/in/MicromanagerReader.java">Trac</a>,
* <a href="https://skyking.microscopy.wisc.edu/svn/java/trunk/loci/formats/in/MicromanagerReader.java">SVN</a></dd></dl>
*/
public class MicromanagerReader extends FormatReader {
// -- Constants --
/** File containing extra metadata. */
private static final String METADATA = "metadata.txt";
// -- Fields --
/** Helper reader for TIFF files. */
private TiffReader tiffReader;
/** List of TIFF files to open. */
private Vector tiffs;
// -- Constructor --
/** Constructs a new Micromanager reader. */
public MicromanagerReader() {
super("Micro-Manager", new String[] {"tif", "tiff", "txt"});
}
// -- IFormatReader API methods --
/* @see loci.formats.IFormatReader#isThisType(byte[]) */
public boolean isThisType(byte[] b) {
return tiffReader.isThisType(b);
}
/* @see loci.formats.IFormatReader#getUsedFiles() */
public String[] getUsedFiles() {
FormatTools.assertId(currentId, true, 1);
String[] s = new String[tiffs.size() + 1];
tiffs.copyInto(s);
s[tiffs.size()] = currentId;
return s;
}
/* @see loci.formats.IFormatReader#openBytes(int, byte[]) */
public byte[] openBytes(int no, byte[] buf)
throws FormatException, IOException
{
FormatTools.assertId(currentId, true, 1);
FormatTools.checkPlaneNumber(this, no);
tiffReader.setId((String) tiffs.get(no));
return tiffReader.openBytes(0, buf);
}
/* @see loci.formats.IFormatReader#close(boolean) */
public void close(boolean fileOnly) throws IOException {
if (fileOnly) {
if (tiffReader != null) tiffReader.close(fileOnly);
}
else close();
}
// -- IFormatHandler API methods --
/* @see loci.formats.IFormatHandler#isThisType(String, boolean) */
public boolean isThisType(String name, boolean open) {
File f = new File(name).getAbsoluteFile();
String[] list = null;
if (f.exists()) list = f.getParentFile().list();
else list = (String[]) Location.getIdMap().keySet().toArray(new String[0]);
if (list == null) return false;
for (int i=0; i<list.length; i++) {
if (list[i].endsWith("metadata.txt")) return super.isThisType(name, open);
}
return false;
}
/* @see loci.formats.IFormatHandler#close() */
public void close() throws IOException {
super.close();
if (tiffReader != null) tiffReader.close();
tiffReader = null;
tiffs = null;
}
// -- Internal FormatReader API methods --
/* @see loci.formats.FormatReader#initFile(String) */
public void initFile(String id) throws FormatException, IOException {
super.initFile(id);
tiffReader = new TiffReader();
status("Reading metadata file");
// find metadata.txt
File file = new File(currentId).getAbsoluteFile();
in = new RandomAccessStream(file.exists() ? new File(file.getParentFile(),
METADATA).getAbsolutePath() : METADATA);
String parent = file.exists() ? file.getParentFile().getAbsolutePath() : "";
// usually a small file, so we can afford to read it into memory
byte[] meta = new byte[(int) in.length()];
in.read(meta);
String s = new String(meta);
meta = null;
status("Finding image file names");
// first find the name of each TIFF file
tiffs = new Vector();
int pos = 0;
while (true) {
pos = s.indexOf("FileName", pos);
if (pos == -1 || pos >= in.length()) break;
String name = s.substring(s.indexOf(":", pos), s.indexOf(",", pos));
tiffs.add(0,
parent + File.separator + name.substring(3, name.length() - 1));
pos++;
}
// now parse the rest of the metadata
status("Populating metadata");
int start = s.indexOf("Summary");
int end = s.indexOf("}", start);
if (start != -1 && end > start) {
s = s.substring(s.indexOf("\n", start), end).trim();
}
StringTokenizer st = new StringTokenizer(s, "\n");
while (st.hasMoreTokens()) {
String token = st.nextToken();
boolean open = token.indexOf("[") != -1;
boolean closed = token.indexOf("]") != -1;
if (open || (!open && !closed)) {
int quote = token.indexOf("\"") + 1;
String key = token.substring(quote, token.indexOf("\"", quote));
if (!open && !closed) {
String value = token.substring(token.indexOf(":") + 1).trim();
value = value.substring(0, value.length() - 1);
addMeta(key, value);
if (key.equals("Channels")) core.sizeC[0] = Integer.parseInt(value);
}
else if (!closed){
StringBuffer valueBuffer = new StringBuffer();
while (!closed) {
token = st.nextToken();
closed = token.indexOf("]") != -1;
valueBuffer.append(token);
}
String value = valueBuffer.toString();
value.replaceAll("\n", "").trim();
value = value.substring(0, value.length() - 1);
addMeta(key, value);
if (key.equals("Channels")) core.sizeC[0] = Integer.parseInt(value);
}
else {
String value =
token.substring(token.indexOf("[") + 1, token.indexOf("]")).trim();
value = value.substring(0, value.length() - 1);
addMeta(key, value);
if (key.equals("Channels")) core.sizeC[0] = Integer.parseInt(value);
}
}
}
tiffReader.setId((String) tiffs.get(0));
String z = (String) metadata.get("Slices");
if (z != null) {
core.sizeZ[0] = Integer.parseInt(z);
}
else core.sizeZ[0] = 1;
String t = (String) metadata.get("Frames");
if (t != null) {
core.sizeT[0 ] = Integer.parseInt(t);
}
else core.sizeT[0] = tiffs.size() / core.sizeC[0];
core.sizeX[0] = tiffReader.getSizeX();
core.sizeY[0] = tiffReader.getSizeY();
core.currentOrder[0] = "XYZCT";
core.pixelType[0] = tiffReader.getPixelType();
core.rgb[0] = tiffReader.isRGB();
core.interleaved[0] = false;
core.littleEndian[0] = tiffReader.isLittleEndian();
core.imageCount[0] = tiffs.size();
core.indexed[0] = false;
core.falseColor[0] = false;
core.metadataComplete[0] = true;
MetadataStore store = getMetadataStore();
store.setImage(currentId, null, null, null);
FormatTools.populatePixels(store, this);
for (int i=0; i<core.sizeC[0]; i++) {
store.setLogicalChannel(i, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null);
// TODO : retrieve min/max from the metadata
//store.setChannelGlobalMinMax(i, getChannelGlobalMinimum(id, i),
// getChannelGlobalMaximum(id, i), null);
}
}
}